diff options
Diffstat (limited to 'source')
571 files changed, 18305 insertions, 18148 deletions
diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt index e89ec2b255a..ddfc7c06fb6 100644 --- a/source/blender/CMakeLists.txt +++ b/source/blender/CMakeLists.txt @@ -66,6 +66,7 @@ set(SRC_DNA_INC ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_packedFile_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_particle_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_property_types.h + ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_rigidbody_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_scene_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_screen_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_sdna_types.h @@ -106,6 +107,10 @@ add_subdirectory(modifiers) add_subdirectory(makesdna) add_subdirectory(makesrna) +if(WITH_BULLET) + add_subdirectory(rigidbody) +endif() + if(WITH_COMPOSITOR) add_subdirectory(opencl) # later on this may be used more generally add_subdirectory(compositor) diff --git a/source/blender/SConscript b/source/blender/SConscript index 5675575e245..e103aaf8bef 100644 --- a/source/blender/SConscript +++ b/source/blender/SConscript @@ -61,6 +61,9 @@ if env['WITH_BF_OPENEXR']: if env['WITH_BF_QUICKTIME']: SConscript (['quicktime/SConscript']) +if env['WITH_BF_BULLET']: + SConscript (['rigidbody/SConscript']) + if env['WITH_BF_COLLADA']: SConscript (['collada/SConscript']) diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h index 25b55eacd77..0ca97975d87 100644 --- a/source/blender/blenfont/BLF_api.h +++ b/source/blender/blenfont/BLF_api.h @@ -183,6 +183,7 @@ void BLF_dir_free(char **dirs, int count); #define BLF_KERNING_DEFAULT (1 << 3) #define BLF_MATRIX (1 << 4) #define BLF_ASPECT (1 << 5) +#define BLF_HINTING (1 << 6) #define BLF_DRAW_STR_DUMMY_MAX 1024 diff --git a/source/blender/blenfont/BLF_translation.h b/source/blender/blenfont/BLF_translation.h index 9a2789d36cc..5b2c4e87165 100644 --- a/source/blender/blenfont/BLF_translation.h +++ b/source/blender/blenfont/BLF_translation.h @@ -33,6 +33,8 @@ #ifndef __BLF_TRANSLATION_H__ #define __BLF_TRANSLATION_H__ +#include "BLI_utildefines.h" /* for bool type */ + #define TEXT_DOMAIN_NAME "blender" /* blf_lang.c */ @@ -48,24 +50,30 @@ void BLF_lang_free(void); /* Set the current locale. */ void BLF_lang_set(const char *); -/* Get the current locale (short code, e.g. es_ES). */ +/* Get the current locale ([partial] ISO code, e.g. es_ES). */ const char *BLF_lang_get(void); +/* Get locale's elements (if relevant pointer is not NULL and element actually exists, e.g. if there is no variant, + * *variant and *language_variant will always be NULL). + * Non-null elements are always MEM_mallocN'ed, it's the caller's responsibility to free them. + * NOTE: Always available, even in non-WITH_INTERNATIONAL builds. + */ +void BLF_locale_explode(const char *locale, char **language, char **country, char **variant, + char **language_country, char **language_variant); + /* Get EnumPropertyItem's for translations menu. */ struct EnumPropertyItem *BLF_RNA_lang_enum_properties(void); /* blf_translation.c */ -#ifdef WITH_INTERNATIONAL unsigned char *BLF_get_unifont(int *unifont_size); void BLF_free_unifont(void); -#endif const char *BLF_pgettext(const char *msgctxt, const char *msgid); /* translation */ -int BLF_translate_iface(void); -int BLF_translate_tooltips(void); +bool BLF_translate_iface(void); +bool BLF_translate_tooltips(void); const char *BLF_translate_do_iface(const char *msgctxt, const char *msgid); const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid); @@ -76,17 +84,17 @@ const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid); /* Those macros should be used everywhere in UI code. */ #ifdef WITH_INTERNATIONAL -/* #define _(msgid) BLF_gettext(msgid) */ - #define IFACE_(msgid) BLF_translate_do_iface(NULL, msgid) - #define TIP_(msgid) BLF_translate_do_tooltip(NULL, msgid) - #define CTX_IFACE_(context, msgid) BLF_translate_do_iface(context, msgid) - #define CTX_TIP_(context, msgid) BLF_translate_do_tooltip(context, msgid) +/*# define _(msgid) BLF_gettext(msgid) */ +# define IFACE_(msgid) BLF_translate_do_iface(NULL, msgid) +# define TIP_(msgid) BLF_translate_do_tooltip(NULL, msgid) +# define CTX_IFACE_(context, msgid) BLF_translate_do_iface(context, msgid) +# define CTX_TIP_(context, msgid) BLF_translate_do_tooltip(context, msgid) #else -/* #define _(msgid) msgid */ - #define IFACE_(msgid) msgid - #define TIP_(msgid) msgid - #define CTX_IFACE_(context, msgid) msgid - #define CTX_TIP_(context, msgid) msgid +/*# define _(msgid) msgid */ +# define IFACE_(msgid) msgid +# define TIP_(msgid) msgid +# define CTX_IFACE_(context, msgid) msgid +# define CTX_TIP_(context, msgid) msgid #endif /* Helper macro, when we want to define a same msgid for multiple msgctxt... @@ -102,8 +110,11 @@ const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid); * things, and limit the number of existing contexts! */ -/* Default, void context. Just in case... */ -#define BLF_I18NCONTEXT_DEFAULT "" +/* Default, void context. + * WARNING! The "" context is not the same as no (NULL) context at mo/boost::locale level! + */ +#define BLF_I18NCONTEXT_DEFAULT NULL /* Translated as None in Python. */ +#define BLF_I18NCONTEXT_DEFAULT_BPY_INTERN "" /* Only used in code, never exposed to user! */ /* Default context for operator names/labels. */ #define BLF_I18NCONTEXT_OPERATOR_DEFAULT "Operator" @@ -146,4 +157,52 @@ const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid); #define BLF_I18NCONTEXT_ID_MOVIECLIP "MovieClip" #define BLF_I18NCONTEXT_ID_MASK "Mask" +/* Helper for bpy.app.i18n object... */ +typedef struct +{ + const char *c_id; + const char *py_id; + const char *value; +} BLF_i18n_contexts_descriptor; + +#define BLF_I18NCONTEXTS_ITEM(ctxt_id, py_id) {#ctxt_id, py_id, ctxt_id} + +#define BLF_I18NCONTEXTS_DESC { \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_DEFAULT, "default"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "operator_default"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_ACTION, "id_action"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_ARMATURE, "id_armature"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_BRUSH, "id_brush"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_CAMERA, "id_camera"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_CURVE, "id_curve"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_GPENCIL, "id_gpencil"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_GROUP, "id_group"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_ID, "id_id"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_IMAGE, "id_image"), \ + /*BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_IPO, "id_ipo"),*/ \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_SHAPEKEY, "id_shapekey"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_LAMP, "id_lamp"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_LIBRARY, "id_library"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_LATTICE, "id_lattice"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_MATERIAL, "id_material"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_METABALL, "id_metaball"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_MESH, "id_mesh"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_NODETREE, "id_nodetree"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_OBJECT, "id_object"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_PARTICLESETTINGS, "id_particlesettings"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_SCENE, "id_scene"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_SCREEN, "id_screen"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_SEQUENCE, "id_sequence"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_SPEAKER, "id_speaker"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_SOUND, "id_sound"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_TEXTURE, "id_texture"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_TEXT, "id_text"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_VFONT, "id_vfont"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_WORLD, "id_world"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_WINDOWMANAGER, "id_windowmanager"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_MOVIECLIP, "id_movieclip"), \ + BLF_I18NCONTEXTS_ITEM(BLF_I18NCONTEXT_ID_MASK, "id_mask"), \ + {NULL, NULL, NULL} \ +} + #endif /* __BLF_TRANSLATION_H__ */ diff --git a/source/blender/blenfont/CMakeLists.txt b/source/blender/blenfont/CMakeLists.txt index a3afd853cba..42298133d7d 100644 --- a/source/blender/blenfont/CMakeLists.txt +++ b/source/blender/blenfont/CMakeLists.txt @@ -29,6 +29,7 @@ set(INC ../editors/include ../makesdna ../makesrna + ../python ../imbuf ../../../intern/guardedalloc ../../../intern/locale diff --git a/source/blender/blenfont/SConscript b/source/blender/blenfont/SConscript index 354a030775e..8273ddf1e40 100644 --- a/source/blender/blenfont/SConscript +++ b/source/blender/blenfont/SConscript @@ -31,7 +31,7 @@ Import ('env') sources = env.Glob('intern/*.c') incs = '. intern #/intern/guardedalloc #/intern/locale ../blenkernel ../blenlib ../blenloader' -incs += ' ../makesdna ../makesrna ../imbuf ../editors/include' +incs += ' ../makesdna ../makesrna ../python ../imbuf ../editors/include' incs += ' #/extern/glew/include' incs += ' ' + env['BF_FREETYPE_INC'] @@ -46,4 +46,4 @@ if env['WITH_BF_INTERNATIONAL']: if env['WITH_BF_FREESTYLE']: defs.append('WITH_FREESTYLE') -env.BlenderLib ( 'bf_blenfont', sources, Split(incs), Split(defs), libtype=['core','player'], priority=[210,210] ) +env.BlenderLib ( 'bf_blenfont', sources, Split(incs), defines=defs, libtype=['core','player'], priority=[210,210] ) diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c index 12c0088e93e..a6b04b24399 100644 --- a/source/blender/blenfont/intern/blf_glyph.c +++ b/source/blender/blenfont/intern/blf_glyph.c @@ -213,6 +213,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c) FT_Error err; FT_Bitmap bitmap, tempbitmap; int sharp = (U.text_render & USER_TEXT_DISABLE_AA); + int flags = FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP; FT_BBox bbox; unsigned int key; @@ -220,10 +221,13 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c) if (g) return g; + if (font->flags & BLF_HINTING) + flags &= ~FT_LOAD_NO_HINTING; + if (sharp) err = FT_Load_Glyph(font->face, (FT_UInt)index, FT_LOAD_TARGET_MONO); else - err = FT_Load_Glyph(font->face, (FT_UInt)index, FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP); /* Sure about NO_* flags? */ + err = FT_Load_Glyph(font->face, (FT_UInt)index, flags); if (err) return NULL; diff --git a/source/blender/blenfont/intern/blf_lang.c b/source/blender/blenfont/intern/blf_lang.c index 9086799f984..73294f1aed6 100644 --- a/source/blender/blenfont/intern/blf_lang.c +++ b/source/blender/blenfont/intern/blf_lang.c @@ -27,41 +27,35 @@ * \ingroup blf */ - -#include "BLF_translation.h" /* own include */ - -#include "BLI_utildefines.h" - -#ifdef WITH_INTERNATIONAL - #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "boost_locale_wrapper.h" - -#include "BKE_global.h" - -#include "DNA_userdef_types.h" - #include "RNA_types.h" -#include "MEM_guardedalloc.h" +#include "BLF_translation.h" /* own include */ #include "BLI_fileops.h" #include "BLI_linklist.h" #include "BLI_path_util.h" #include "BLI_string.h" +#include "BKE_global.h" + +#include "DNA_userdef_types.h" + +#include "MEM_guardedalloc.h" + +#ifdef WITH_INTERNATIONAL + +#include "boost_locale_wrapper.h" + /* Locale options. */ static const char **locales = NULL; static int num_locales = 0; static EnumPropertyItem *locales_menu = NULL; static int num_locales_menu = 0; -#define ULANGUAGE ((U.language >= 0 && U.language < num_locales) ? U.language : 0) -#define LOCALE(_id) (locales ? locales[_id] : "") - static void free_locales(void) { if (locales) { @@ -113,7 +107,7 @@ static void fill_locales(void) } num_locales_menu++; /* The "closing" void item... */ - /* And now, buil locales and locale_menu! */ + /* And now, build locales and locale_menu! */ locales_menu = MEM_callocN(num_locales_menu * sizeof(EnumPropertyItem), __func__); line = lines; /* Do not allocate locales with zero-sized mem, as LOCALE macro uses NULL locales as invalid marker! */ @@ -177,14 +171,20 @@ static void fill_locales(void) BLI_file_free_lines(lines); } +#endif /* WITH_INTERNATIONAL */ EnumPropertyItem *BLF_RNA_lang_enum_properties(void) { +#ifdef WITH_INTERNATIONAL return locales_menu; +#else + return NULL; +#endif } void BLF_lang_init(void) { +#ifdef WITH_INTERNATIONAL char *messagepath = BLI_get_folder(BLENDER_DATAFILES, "locale"); if (messagepath) { @@ -194,15 +194,24 @@ void BLF_lang_init(void) else { printf("%s: 'locale' data path for translations not found, continuing\n", __func__); } +#else +#endif } void BLF_lang_free(void) { +#ifdef WITH_INTERNATIONAL free_locales(); +#else +#endif } +#define ULANGUAGE ((U.language >= 0 && U.language < num_locales) ? U.language : 0) +#define LOCALE(_id) (locales ? locales[(_id)] : "") + void BLF_lang_set(const char *str) { +#ifdef WITH_INTERNATIONAL int ulang = ULANGUAGE; const char *short_locale = str ? str : LOCALE(ulang); const char *short_locale_utf8 = NULL; @@ -232,37 +241,77 @@ void BLF_lang_set(const char *str) if (short_locale[0]) { MEM_freeN((void *)short_locale_utf8); } +#else + (void)str; +#endif } +/* Get the current locale (short code, e.g. es_ES). */ const char *BLF_lang_get(void) { - int uilang = ULANGUAGE; - return LOCALE(uilang); +#ifdef WITH_INTERNATIONAL + const char *locale = LOCALE(ULANGUAGE); + if (locale[0] == '\0') { + /* Default locale, we have to find which one we are actually using! */ + locale = bl_locale_get(); + } + return locale; +#else + return ""; +#endif } #undef LOCALE #undef ULANGUAGE -#else /* ! WITH_INTERNATIONAL */ - -void BLF_lang_init(void) -{ - return; -} - -void BLF_lang_free(void) +/* Get locale's elements (if relevant pointer is not NULL and element actually exists, e.g. if there is no variant, + * *variant and *language_variant will always be NULL). + * Non-null elements are always MEM_mallocN'ed, it's the caller's responsibility to free them. + * NOTE: Keep that one always available, you never know, may become useful even in no-WITH_INTERNATIONAL context... + */ +void BLF_locale_explode(const char *locale, char **language, char **country, char **variant, + char **language_country, char **language_variant) { - return; -} + char *m1, *m2, *_t = NULL; -void BLF_lang_set(const char *UNUSED(str)) -{ - return; -} + m1 = strchr(locale, '_'); + m2 = strchr(locale, '@'); -const char *BLF_lang_get(void) -{ - return ""; + if (language || language_variant) { + if (m1 || m2) { + _t = m1 ? BLI_strdupn(locale, m1 - locale) : BLI_strdupn(locale, m2 - locale); + if (language) + *language = _t; + } + else if (language) { + *language = BLI_strdup(locale); + } + } + if (country) { + if (m1) + *country = m2 ? BLI_strdupn(m1 + 1, m2 - (m1 + 1)) : BLI_strdup(m1 + 1); + else + *country = NULL; + } + if (variant) { + if (m2) + *variant = BLI_strdup(m2 + 1); + else + *variant = NULL; + } + if (language_country) { + if (m1) + *language_country = m2 ? BLI_strdupn(locale, m2 - locale) : BLI_strdup(locale); + else + *language_country = NULL; + } + if (language_variant) { + if (m2) + *language_variant = m1 ? BLI_strdupcat(_t, m2) : BLI_strdup(locale); + else + *language_variant = NULL; + } + if (_t && !language) { + MEM_freeN(_t); + } } - -#endif /* WITH_INTERNATIONAL */ diff --git a/source/blender/blenfont/intern/blf_translation.c b/source/blender/blenfont/intern/blf_translation.c index 5d4b631688a..a77b464822b 100644 --- a/source/blender/blenfont/intern/blf_translation.c +++ b/source/blender/blenfont/intern/blf_translation.c @@ -33,26 +33,28 @@ #include "BLF_translation.h" -#ifdef WITH_INTERNATIONAL - -#include "boost_locale_wrapper.h" - #include "MEM_guardedalloc.h" -#include "BLI_utildefines.h" +#include "BLI_fileops.h" #include "BLI_path_util.h" #include "BLI_string.h" -#include "BLI_path_util.h" -#include "BLI_fileops.h" #include "DNA_userdef_types.h" /* For user settings. */ +#include "BPY_extern.h" + +#ifdef WITH_INTERNATIONAL + +#include "boost_locale_wrapper.h" + static const char unifont_filename[] = "droidsans.ttf.gz"; static unsigned char *unifont_ttf = NULL; static int unifont_size = 0; +#endif /* WITH_INTERNATIONAL */ unsigned char *BLF_get_unifont(int *unifont_size_r) { +#ifdef WITH_INTERNATIONAL if (unifont_ttf == NULL) { char *fontpath = BLI_get_folder(BLENDER_DATAFILES, "fonts"); if (fontpath) { @@ -70,21 +72,41 @@ unsigned char *BLF_get_unifont(int *unifont_size_r) *unifont_size_r = unifont_size; return unifont_ttf; +#else + (void)unifont_size_r; + return NULL; +#endif } void BLF_free_unifont(void) { +#ifdef WITH_INTERNATIONAL if (unifont_ttf) MEM_freeN(unifont_ttf); -} - +#else #endif +} const char *BLF_pgettext(const char *msgctxt, const char *msgid) { #ifdef WITH_INTERNATIONAL if (msgid && msgid[0]) { - return bl_locale_pgettext(msgctxt, msgid); + const char *ret; + + /*if (msgctxt && !strcmp(msgctxt, BLF_I18NCONTEXT_DEFAULT_BPY_INTERN)) { */ + if (msgctxt && !msgctxt[0]) { + /* BLF_I18NCONTEXT_DEFAULT_BPY_INTERN context is reserved and considered the same as default NULL one. */ + msgctxt = NULL; + } + ret = bl_locale_pgettext(msgctxt, msgid); + /* We assume if the returned string is the same (memory level) as the msgid, no translation was found, + * and we can try py scripts' ones! + */ + if (ret == msgid) { + ret = BPY_app_translations_py_pgettext(msgctxt, msgid); + } + + return ret; } return ""; #else @@ -93,21 +115,21 @@ const char *BLF_pgettext(const char *msgctxt, const char *msgid) #endif } -int BLF_translate_iface(void) +bool BLF_translate_iface(void) { #ifdef WITH_INTERNATIONAL return (U.transopts & USER_DOTRANSLATE) && (U.transopts & USER_TR_IFACE); #else - return 0; + return false; #endif } -int BLF_translate_tooltips(void) +bool BLF_translate_tooltips(void) { #ifdef WITH_INTERNATIONAL return (U.transopts & USER_DOTRANSLATE) && (U.transopts & USER_TR_TOOLTIPS); #else - return 0; + return false; #endif } diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index f06547fe2e3..5f504df5628 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -95,6 +95,8 @@ struct BMEditMesh; struct ListBase; struct PBVH; +#define DM_OMP_LIMIT 0 /* setting zero so we can catch bugs in OpenMP/BMesh */ + /* number of sub-elements each mesh element has (for interpolation) */ #define SUB_ELEMS_VERT 0 #define SUB_ELEMS_EDGE 2 @@ -729,4 +731,4 @@ BLI_INLINE int DM_origindex_mface_mpoly(const int *index_mf_to_mpoly, const int return (j != ORIGINDEX_NONE) ? (index_mp_to_orig ? index_mp_to_orig[j] : j) : ORIGINDEX_NONE; } -#endif +#endif /* __BKE_DERIVEDMESH_H__ */ diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 2d7030b2d42..4f54f93a7fc 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -220,7 +220,7 @@ void BKE_pose_remove_group(struct Object *ob); void what_does_obaction(struct Object *ob, struct Object *workob, struct bPose *pose, struct bAction *act, char groupname[], float cframe); /* for proxy */ -void BKE_pose_copy_result(struct bPose *to, struct bPose *from); +bool BKE_pose_copy_result(struct bPose *to, struct bPose *from); /* clear all transforms */ void BKE_pose_rest(struct bPose *pose); diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 9c6d26c08bc..2548d95c383 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -42,7 +42,7 @@ extern "C" { * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 265 -#define BLENDER_SUBVERSION 8 +#define BLENDER_SUBVERSION 9 /* 262 was the last editmesh release but it has compatibility code for bmesh data */ #define BLENDER_MINVERSION 262 @@ -52,7 +52,7 @@ extern "C" { /* can be left blank, otherwise a,b,c... etc with no quotes */ #define BLENDER_VERSION_CHAR a /* alpha/beta/rc/release, docs use this */ -#define BLENDER_VERSION_CYCLE alpha +#define BLENDER_VERSION_CYCLE beta extern char versionstr[]; /* from blender.c */ diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index 248fe9c8968..91f0525d4f3 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -36,6 +36,7 @@ struct ID; struct Brush; struct ImBuf; +struct ImagePool; struct Scene; struct wmOperator; // enum CurveMappingPreset; @@ -67,7 +68,8 @@ float BKE_brush_curve_strength_clamp(struct Brush *br, float p, const float len) float BKE_brush_curve_strength(struct Brush *br, float p, const float len); /* used for sculpt */ /* sampling */ -void BKE_brush_sample_tex(const struct Scene *scene, struct Brush *brush, const float xy[2], float rgba[4], const int thread); +void BKE_brush_sample_tex(const struct Scene *scene, struct Brush *brush, const float sampleco[3], float rgba[4], const int thread, struct ImagePool *pool); +void BKE_brush_sample_tex_2D(const struct Scene *scene, struct Brush *brush, const float xy[2], float rgba[4], const int thread); void BKE_brush_imbuf_new(const struct Scene *scene, struct Brush *brush, short flt, short texfalloff, int size, struct ImBuf **imbuf, int use_color_correction); diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h index 96e05aa87b9..e0b7e68bafc 100644 --- a/source/blender/blenkernel/BKE_colortools.h +++ b/source/blender/blenkernel/BKE_colortools.h @@ -42,14 +42,6 @@ struct Histogram; struct ImBuf; struct rctf; -#if defined _MSC_VER -# define DO_INLINE __inline -#elif defined(__sun) || defined(__sun__) -# define DO_INLINE -#else -# define DO_INLINE static inline -#endif - void curvemapping_set_defaults(struct CurveMapping *cumap, int tot, float minx, float miny, float maxx, float maxy); struct CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, float maxy); void curvemapping_free_data(struct CurveMapping *cumap); diff --git a/source/blender/blenkernel/BKE_depsgraph.h b/source/blender/blenkernel/BKE_depsgraph.h index cf7e4b24288..49dc1bfd732 100644 --- a/source/blender/blenkernel/BKE_depsgraph.h +++ b/source/blender/blenkernel/BKE_depsgraph.h @@ -36,13 +36,14 @@ extern "C" { // #define DEPS_DEBUG -struct ID; -struct Main; -struct Scene; -struct DagNodeQueue; struct DagForest; struct DagNode; +struct DagNodeQueue; struct GHash; +struct ID; +struct Main; +struct Object; +struct Scene; /* **** DAG relation types *** */ diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 499609932d1..bfee5e820c3 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -44,6 +44,7 @@ struct anim; struct Scene; struct Object; struct ImageFormatData; +struct ImagePool; struct Main; #define IMA_MAX_SPACE 64 @@ -146,6 +147,11 @@ int BKE_image_has_ibuf(struct Image *ima, struct ImageUser *iuser); struct ImBuf *BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **lock_r); void BKE_image_release_ibuf(struct Image *ima, struct ImBuf *ibuf, void *lock); +struct ImagePool *BKE_image_pool_new(void); +void BKE_image_pool_free(struct ImagePool *pool); +struct ImBuf *BKE_image_pool_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, struct ImagePool *pool); +void BKE_image_pool_release_ibuf(struct Image *ima, struct ImBuf *ibuf, struct ImagePool *pool); + /* returns a new image or NULL if it can't load */ struct Image *BKE_image_load(const char *filepath); /* returns existing Image when filename/type is same (frame optional) */ @@ -219,6 +225,10 @@ void BKE_image_buf_fill_color(unsigned char *rect, float *rect_float, int width, void BKE_image_buf_fill_checker(unsigned char *rect, float *rect_float, int height, int width); void BKE_image_buf_fill_checker_color(unsigned char *rect, float *rect_float, int height, int width); +/* Cycles hookup */ +unsigned char *BKE_image_get_pixels_for_frame(struct Image *image, int frame); +float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index be42ee524de..7c36ff07da5 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -102,5 +102,4 @@ typedef struct Main { } #endif -#endif - +#endif /* __BKE_MAIN_H__ */ diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 3466a914bce..cfe562e231c 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -100,6 +100,16 @@ void BKE_mesh_calc_poly_center(struct MPoly *mpoly, struct MLoop *loopstart, float BKE_mesh_calc_poly_area(struct MPoly *mpoly, struct MLoop *loopstart, struct MVert *mvarray, const float polynormal[3]); +void BKE_mesh_calc_relative_deform( + const struct MPoly *mpoly, const int totpoly, + const struct MLoop *mloop, const int totvert, + + const float (*vert_cos_src)[3], + const float (*vert_cos_dst)[3], + + const float (*vert_cos_org)[3], + float (*vert_cos_new)[3]); + /* Find the index of the loop in 'poly' which references vertex, * returns -1 if not found */ int poly_find_loop_from_vert(const struct MPoly *poly, diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 0a2f757b38e..718fa2f9ecd 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -577,7 +577,7 @@ struct ShadeResult; struct bNodeTreeExec *ntreeShaderBeginExecTree(struct bNodeTree *ntree, int use_tree_data); void ntreeShaderEndExecTree(struct bNodeTreeExec *exec, int use_tree_data); -void ntreeShaderExecTree(struct bNodeTree *ntree, struct ShadeInput *shi, struct ShadeResult *shr); +bool ntreeShaderExecTree(struct bNodeTree *ntree, struct ShadeInput *shi, struct ShadeResult *shr); void ntreeShaderGetTexcoMode(struct bNodeTree *ntree, int osa, short *texco, int *mode); void nodeShaderSynchronizeID(struct bNode *node, int copyto); @@ -737,8 +737,6 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria /* API */ struct CompBuf; -struct bNodeTreeExec *ntreeCompositBeginExecTree(struct bNodeTree *ntree, int use_tree_data); -void ntreeCompositEndExecTree(struct bNodeTreeExec *exec, int use_tree_data); void ntreeCompositExecTree(struct bNodeTree *ntree, struct RenderData *rd, int rendering, int do_previews, const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings); void ntreeCompositTagRender(struct Scene *sce); diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 0a4a7f75e25..211b6189fa8 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -34,6 +34,7 @@ struct bContext; struct BMesh; +struct BMFace; struct Brush; struct MDisps; struct MeshElemMap; @@ -46,6 +47,7 @@ struct Paint; struct PBVH; struct Scene; struct StrokeCache; +struct ImagePool; extern const char PAINT_CURSOR_SCULPT[3]; extern const char PAINT_CURSOR_VERTEX_PAINT[3]; @@ -72,6 +74,7 @@ int paint_vertsel_test(struct Object *ob); int paint_is_face_hidden(const struct MFace *f, const struct MVert *mvert); int paint_is_grid_face_hidden(const unsigned int *grid_hidden, int gridsize, int x, int y); +int paint_is_bmesh_face_hidden(struct BMFace *f); /* paint masks */ float paint_grid_paint_mask(const struct GridPaintMask *gpm, unsigned level, @@ -114,6 +117,7 @@ typedef struct SculptSession { /* Used to cache the render of the active texture */ unsigned int texcache_side, *texcache, texcache_actual; + struct ImagePool *tex_pool; /* Layer brush persistence between strokes */ float (*layer_co)[3]; /* Copy of the mesh vertices' locations */ diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index f15ad296e4a..3394c4f4ce0 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -306,7 +306,7 @@ int psys_get_particle_state(struct ParticleSimulationData *sim, int p, struct Pa void psys_sph_init(struct ParticleSimulationData *sim, struct SPHData *sphdata); void psys_sph_finalise(struct SPHData *sphdata); -void psys_sph_density(struct BVHTree *tree, struct SPHData* data, float co[3], float vars[2]); +void psys_sph_density(struct BVHTree *tree, struct SPHData *data, float co[3], float vars[2]); /* for anim.c */ void psys_get_dupli_texture(struct ParticleSystem *psys, struct ParticleSettings *part, diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 709db7e4570..99ed978561e 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -113,6 +113,9 @@ typedef enum { PBVHType BKE_pbvh_type(const PBVH *bvh); +/* Get the PBVH root's bounding box */ +void BKE_pbvh_bounding_box(const PBVH *bvh, float min[3], float max[3]); + /* multires hidden data, only valid for type == PBVH_GRIDS */ unsigned int **BKE_pbvh_grid_hidden(const PBVH *bvh); diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index 77b35e1a25c..1cb50425c40 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -67,6 +67,7 @@ #define PTCACHE_TYPE_SMOKE_DOMAIN 3 #define PTCACHE_TYPE_SMOKE_HIGHRES 4 #define PTCACHE_TYPE_DYNAMICPAINT 5 +#define PTCACHE_TYPE_RIGIDBODY 6 /* high bits reserved for flags that need to be stored in file */ #define PTCACHE_TYPEFLAG_COMPRESS (1 << 16) @@ -91,6 +92,7 @@ struct PointCache; struct Scene; struct SmokeModifierData; struct SoftBody; +struct RigidBodyWorld; /* temp structure for read/write */ typedef struct PTCacheData { @@ -260,6 +262,7 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, struct Object *ob, struct Par void BKE_ptcache_id_from_cloth(PTCacheID *pid, struct Object *ob, struct ClothModifierData *clmd); void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd); void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, struct Object *ob, struct DynamicPaintSurface *surface); +void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, struct Object *ob, struct RigidBodyWorld *rbw); void BKE_ptcache_ids_from_object(struct ListBase *lb, struct Object *ob, struct Scene *scene, int duplis); @@ -294,10 +297,6 @@ int BKE_ptcache_read(PTCacheID *pid, float cfra); /* Main cache writing call. */ int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra); -/****************** Continue physics ***************/ -void BKE_ptcache_set_continue_physics(struct Main *bmain, struct Scene *scene, int enable); -int BKE_ptcache_get_continue_physics(void); - /******************* Allocate & free ***************/ struct PointCache *BKE_ptcache_add(struct ListBase *ptcaches); void BKE_ptcache_free_mem(struct ListBase *mem_cache); diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h new file mode 100644 index 00000000000..607c3026388 --- /dev/null +++ b/source/blender/blenkernel/BKE_rigidbody.h @@ -0,0 +1,95 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joshua Leung, Sergej Reich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file BKE_rigidbody.h + * \ingroup blenkernel + * \brief API for Blender-side Rigid Body stuff + */ + + +#ifndef __BKE_RIGIDBODY_H__ +#define __BKE_RIGIDBODY_H__ + +struct RigidBodyWorld; +struct RigidBodyOb; + +struct Scene; +struct Object; +struct Group; + +/* -------------- */ +/* Memory Management */ + +void BKE_rigidbody_free_world(struct RigidBodyWorld *rbw); +void BKE_rigidbody_free_object(struct Object *ob); +void BKE_rigidbody_free_constraint(struct Object *ob); + +/* ...... */ + +struct RigidBodyOb *BKE_rigidbody_copy_object(struct Object *ob); +struct RigidBodyCon *BKE_rigidbody_copy_constraint(struct Object *ob); + +/* -------------- */ +/* Setup */ + +/* create Blender-side settings data - physics objects not initialised yet */ +struct RigidBodyWorld *BKE_rigidbody_create_world(struct Scene *scene); +struct RigidBodyOb *BKE_rigidbody_create_object(struct Scene *scene, struct Object *ob, short type); +struct RigidBodyCon *BKE_rigidbody_create_constraint(struct Scene *scene, struct Object *ob, short type); + +/* 'validate' (i.e. make new or replace old) Physics-Engine objects */ +void BKE_rigidbody_validate_sim_world(struct Scene *scene, struct RigidBodyWorld *rbw, short rebuild); +void BKE_rigidbody_validate_sim_object(struct RigidBodyWorld *rbw, struct Object *ob, short rebuild); +void BKE_rigidbody_validate_sim_shape(struct Object *ob, short rebuild); +void BKE_rigidbody_validate_sim_constraint(struct RigidBodyWorld *rbw, struct Object *ob, short rebuild); + +/* -------------- */ +/* Utilities */ + +struct RigidBodyWorld *BKE_rigidbody_get_world(struct Scene *scene); +void BKE_rigidbody_remove_object(struct Scene *scene, struct Object *ob); +void BKE_rigidbody_remove_constraint(struct Scene *scene, struct Object *ob); + +/* -------------- */ +/* Utility Macros */ + +/* get mass of Rigid Body Object to supply to RigidBody simulators */ +#define RBO_GET_MASS(rbo) \ + ((rbo && ((rbo->type == RBO_TYPE_PASSIVE) || (rbo->flag & RBO_FLAG_KINEMATIC) || (rbo->flag & RBO_FLAG_DISABLED))) ? (0.0f) : (rbo->mass)) +/* get collision margin for Rigid Body Object, triangle mesh and cone shapes cannot embed margin, convex hull always uses custom margin */ +#define RBO_GET_MARGIN(rbo) \ + ((rbo->flag & RBO_FLAG_USE_MARGIN || rbo->shape == RB_SHAPE_CONVEXH || rbo->shape == RB_SHAPE_TRIMESH || rbo->shape == RB_SHAPE_CONE) ? (rbo->margin) : (0.04f)) + +/* -------------- */ +/* Simulation */ + +void BKE_rigidbody_aftertrans_update(struct Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle); +void BKE_rigidbody_sync_transforms(struct Scene *scene, struct Object *ob, float ctime); +void BKE_rigidbody_cache_reset(struct RigidBodyWorld *rbw); +void BKE_rigidbody_do_simulation(struct Scene *scene, float ctime); + +#endif /* __BKE_RIGIDBODY_H__ */ diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 6447b2a8dee..9bf0991272a 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -72,6 +72,7 @@ struct Scene *BKE_scene_add(struct Main *bmain, const char *name); /* base functions */ struct Base *BKE_scene_base_find(struct Scene *scene, struct Object *ob); struct Base *BKE_scene_base_add(struct Scene *sce, struct Object *ob); +void BKE_scene_base_unlink(struct Scene *sce, struct Base *base); void BKE_scene_base_deselect_all(struct Scene *sce); void BKE_scene_base_select(struct Scene *sce, struct Base *selbase); int BKE_scene_base_iter_next(struct Scene **scene, int val, struct Base **base, struct Object **ob); @@ -115,6 +116,7 @@ int BKE_scene_use_new_shading_nodes(struct Scene *scene); void BKE_scene_disable_color_management(struct Scene *scene); int BKE_scene_check_color_management_enabled(const struct Scene *scene); +int BKE_scene_check_rigidbody_active(const struct Scene *scene); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_tessmesh.h b/source/blender/blenkernel/BKE_tessmesh.h index 9462822e25f..b3e6ab37273 100644 --- a/source/blender/blenkernel/BKE_tessmesh.h +++ b/source/blender/blenkernel/BKE_tessmesh.h @@ -83,7 +83,7 @@ typedef struct BMEditMesh { } BMEditMesh; void BMEdit_RecalcTessellation(BMEditMesh *em); -BMEditMesh *BMEdit_Create(BMesh *bm, int do_tessellate); +BMEditMesh *BMEdit_Create(BMesh *bm, const bool do_tessellate); BMEditMesh *BMEdit_Copy(BMEditMesh *em); BMEditMesh *BMEdit_FromObject(struct Object *ob); void BMEdit_Free(BMEditMesh *em); diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h index 1e3dd426efa..be30eba0559 100644 --- a/source/blender/blenkernel/BKE_text.h +++ b/source/blender/blenkernel/BKE_text.h @@ -105,6 +105,7 @@ int text_check_bracket(const char ch); int text_check_delim(const char ch); int text_check_digit(const char ch); int text_check_identifier(const char ch); +int text_check_identifier_nodigit(const char ch); int text_check_whitespace(const char ch); int text_find_identifier_start(const char *str, int i); diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 23f23acad6b..2eeecefe231 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -128,6 +128,7 @@ set(SRC intern/pointcache.c intern/property.c intern/report.c + intern/rigidbody.c intern/sca.c intern/scene.c intern/screen.c @@ -219,6 +220,7 @@ set(SRC BKE_pointcache.h BKE_property.h BKE_report.h + BKE_rigidbody.h BKE_sca.h BKE_scene.h BKE_screen.h @@ -261,7 +263,10 @@ if(WITH_BULLET) list(APPEND INC_SYS ${BULLET_INCLUDE_DIRS} ) - add_definitions(-DUSE_BULLET) + list(APPEND INC + ../rigidbody + ) + add_definitions(-DWITH_BULLET) endif() #if(WITH_MOD_CLOTH_ELTOPO) diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index 2998da824ef..bcdf37da104 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -41,6 +41,7 @@ incs += ' ../render/extern/include ../makesrna' incs += ' ../imbuf ../ikplugin ../avi #/intern/elbeem/extern ../nodes ../modifiers' incs += ' #/intern/iksolver/extern ../blenloader' incs += ' #/extern/bullet2/src' +incs += ' ../rigidbody' incs += ' #/intern/opennl/extern #/intern/bsp/extern' incs += ' ../gpu #/extern/glew/include' incs += ' ../bmesh' @@ -110,7 +111,7 @@ if env['WITH_BF_QUICKTIME']: incs += ' ' + env['BF_QUICKTIME_INC'] if env['WITH_BF_BULLET']: - defs.append('USE_BULLET') + defs.append('WITH_BULLET') if env['OURPLATFORM'] == 'darwin': if env['WITH_BF_OPENMP']: diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c index cc20470b4d5..2079c783898 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.c +++ b/source/blender/blenkernel/intern/CCGSubSurf.c @@ -16,12 +16,6 @@ #include "BLI_utildefines.h" /* for BLI_assert */ -#ifdef _MSC_VER -# define CCG_INLINE __inline -#else -# define CCG_INLINE inline -#endif - /* used for normalize_v3 in BLI_math_vector * float.h's FLT_EPSILON causes trouble with subsurf normals - campbell */ #define EPSILON (1.0e-35f) @@ -305,7 +299,7 @@ struct CCGVert { // byte *userData; }; -static CCG_INLINE byte *VERT_getLevelData(CCGVert *v) +BLI_INLINE byte *VERT_getLevelData(CCGVert *v) { return (byte *)(&(v)[1]); } @@ -324,7 +318,7 @@ struct CCGEdge { // byte *userData; }; -static CCG_INLINE byte *EDGE_getLevelData(CCGEdge *e) +BLI_INLINE byte *EDGE_getLevelData(CCGEdge *e) { return (byte *)(&(e)[1]); } @@ -342,17 +336,17 @@ struct CCGFace { // byte *userData; }; -static CCG_INLINE CCGVert **FACE_getVerts(CCGFace *f) +BLI_INLINE CCGVert **FACE_getVerts(CCGFace *f) { return (CCGVert **)(&f[1]); } -static CCG_INLINE CCGEdge **FACE_getEdges(CCGFace *f) +BLI_INLINE CCGEdge **FACE_getEdges(CCGFace *f) { return (CCGEdge **)(&(FACE_getVerts(f)[f->numVerts])); } -static CCG_INLINE byte *FACE_getCenterData(CCGFace *f) +BLI_INLINE byte *FACE_getCenterData(CCGFace *f) { return (byte *)(&(FACE_getEdges(f)[(f)->numVerts])); } @@ -698,28 +692,28 @@ static CCGFace *_face_new(CCGFaceHDL fHDL, CCGVert **verts, CCGEdge **edges, int return f; } -static CCG_INLINE void *_face_getIECo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize) +BLI_INLINE void *_face_getIECo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize) { int maxGridSize = ccg_gridsize(levels); int spacing = ccg_spacing(levels, lvl); byte *gridBase = FACE_getCenterData(f) + dataSize * (1 + S * (maxGridSize + maxGridSize * maxGridSize)); return &gridBase[dataSize * x * spacing]; } -static CCG_INLINE void *_face_getIENo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize, int normalDataOffset) +BLI_INLINE void *_face_getIENo(CCGFace *f, int lvl, int S, int x, int levels, int dataSize, int normalDataOffset) { int maxGridSize = ccg_gridsize(levels); int spacing = ccg_spacing(levels, lvl); byte *gridBase = FACE_getCenterData(f) + dataSize * (1 + S * (maxGridSize + maxGridSize * maxGridSize)); return &gridBase[dataSize * x * spacing + normalDataOffset]; } -static CCG_INLINE void *_face_getIFCo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize) +BLI_INLINE void *_face_getIFCo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize) { int maxGridSize = ccg_gridsize(levels); int spacing = ccg_spacing(levels, lvl); byte *gridBase = FACE_getCenterData(f) + dataSize * (1 + S * (maxGridSize + maxGridSize * maxGridSize)); return &gridBase[dataSize * (maxGridSize + (y * maxGridSize + x) * spacing)]; } -static CCG_INLINE float *_face_getIFNo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize, int normalDataOffset) +BLI_INLINE float *_face_getIFNo(CCGFace *f, int lvl, int S, int x, int y, int levels, int dataSize, int normalDataOffset) { int maxGridSize = ccg_gridsize(levels); int spacing = ccg_spacing(levels, lvl); @@ -742,7 +736,7 @@ static int _face_getEdgeIndex(CCGFace *f, CCGEdge *e) return i; return -1; } -static CCG_INLINE void *_face_getIFCoEdge(CCGFace *f, CCGEdge *e, int f_ed_idx, int lvl, int eX, int eY, int levels, int dataSize) +BLI_INLINE void *_face_getIFCoEdge(CCGFace *f, CCGEdge *e, int f_ed_idx, int lvl, int eX, int eY, int levels, int dataSize) { int maxGridSize = ccg_gridsize(levels); int spacing = ccg_spacing(levels, lvl); @@ -1422,18 +1416,25 @@ static void ccgSubSurf__calcVertNormals(CCGSubSurf *ss, float no[3]; for (S = 0; S < f->numVerts; S++) { - for (y = 0; y < gridSize - 1; y++) - for (x = 0; x < gridSize - 1; x++) + for (y = 0; y < gridSize - 1; y++) { + for (x = 0; x < gridSize - 1; x++) { NormZero(FACE_getIFNo(f, lvl, S, x, y)); + } + } - if (FACE_getEdges(f)[(S - 1 + f->numVerts) % f->numVerts]->flags & Edge_eEffected) - for (x = 0; x < gridSize - 1; x++) + if (FACE_getEdges(f)[(S - 1 + f->numVerts) % f->numVerts]->flags & Edge_eEffected) { + for (x = 0; x < gridSize - 1; x++) { NormZero(FACE_getIFNo(f, lvl, S, x, gridSize - 1)); - if (FACE_getEdges(f)[S]->flags & Edge_eEffected) - for (y = 0; y < gridSize - 1; y++) + } + } + if (FACE_getEdges(f)[S]->flags & Edge_eEffected) { + for (y = 0; y < gridSize - 1; y++) { NormZero(FACE_getIFNo(f, lvl, S, gridSize - 1, y)); - if (FACE_getVerts(f)[S]->flags & Vert_eEffected) + } + } + if (FACE_getVerts(f)[S]->flags & Vert_eEffected) { NormZero(FACE_getIFNo(f, lvl, S, gridSize - 1, gridSize - 1)); + } } for (S = 0; S < f->numVerts; S++) { diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index dde1d5870ca..8ca6d045712 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -169,7 +169,7 @@ static MPoly *dm_getPolyArray(DerivedMesh *dm) static MVert *dm_dupVertArray(DerivedMesh *dm) { - MVert *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumVerts(dm), + MVert *tmp = MEM_mallocN(sizeof(*tmp) * dm->getNumVerts(dm), "dm_dupVertArray tmp"); if (tmp) dm->copyVertArray(dm, tmp); @@ -179,7 +179,7 @@ static MVert *dm_dupVertArray(DerivedMesh *dm) static MEdge *dm_dupEdgeArray(DerivedMesh *dm) { - MEdge *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumEdges(dm), + MEdge *tmp = MEM_mallocN(sizeof(*tmp) * dm->getNumEdges(dm), "dm_dupEdgeArray tmp"); if (tmp) dm->copyEdgeArray(dm, tmp); @@ -189,7 +189,7 @@ static MEdge *dm_dupEdgeArray(DerivedMesh *dm) static MFace *dm_dupFaceArray(DerivedMesh *dm) { - MFace *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumTessFaces(dm), + MFace *tmp = MEM_mallocN(sizeof(*tmp) * dm->getNumTessFaces(dm), "dm_dupFaceArray tmp"); if (tmp) dm->copyTessFaceArray(dm, tmp); @@ -199,7 +199,7 @@ static MFace *dm_dupFaceArray(DerivedMesh *dm) static MLoop *dm_dupLoopArray(DerivedMesh *dm) { - MLoop *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumLoops(dm), + MLoop *tmp = MEM_mallocN(sizeof(*tmp) * dm->getNumLoops(dm), "dm_dupLoopArray tmp"); if (tmp) dm->copyLoopArray(dm, tmp); @@ -209,7 +209,7 @@ static MLoop *dm_dupLoopArray(DerivedMesh *dm) static MPoly *dm_dupPolyArray(DerivedMesh *dm) { - MPoly *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumPolys(dm), + MPoly *tmp = MEM_mallocN(sizeof(*tmp) * dm->getNumPolys(dm), "dm_dupPolyArray tmp"); if (tmp) dm->copyPolyArray(dm, tmp); @@ -574,7 +574,7 @@ void DM_to_meshkey(DerivedMesh *dm, Mesh *me, KeyBlock *kb) if (totvert == 0 || me->totvert == 0 || me->totvert != totvert) return; if (kb->data) MEM_freeN(kb->data); - kb->data = MEM_callocN(me->key->elemsize * me->totvert, "kb->data"); + kb->data = MEM_mallocN(me->key->elemsize * me->totvert, "kb->data"); kb->totelem = totvert; fp = kb->data; @@ -1584,9 +1584,15 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos DM_add_edge_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); DM_add_poly_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL); - range_vn_i(DM_get_vert_data_layer(dm, CD_ORIGINDEX), dm->numVertData, 0); - range_vn_i(DM_get_edge_data_layer(dm, CD_ORIGINDEX), dm->numEdgeData, 0); - range_vn_i(DM_get_poly_data_layer(dm, CD_ORIGINDEX), dm->numPolyData, 0); +#pragma omp parallel sections if (dm->numVertData + dm->numEdgeData + dm->numPolyData >= DM_OMP_LIMIT) + { +#pragma omp section + { range_vn_i(DM_get_vert_data_layer(dm, CD_ORIGINDEX), dm->numVertData, 0); } +#pragma omp section + { range_vn_i(DM_get_edge_data_layer(dm, CD_ORIGINDEX), dm->numEdgeData, 0); } +#pragma omp section + { range_vn_i(DM_get_poly_data_layer(dm, CD_ORIGINDEX), dm->numPolyData, 0); } + } } } @@ -2353,15 +2359,14 @@ DMCoNo *mesh_get_mapped_verts_nors(Scene *scene, Object *ob) return NULL; dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX); - vertexcosnos = MEM_callocN(sizeof(DMCoNo) * me->totvert, "vertexcosnos map"); if (dm->foreachMappedVert) { + vertexcosnos = MEM_callocN(sizeof(DMCoNo) * me->totvert, "vertexcosnos map"); dm->foreachMappedVert(dm, make_vertexcosnos__mapFunc, vertexcosnos); } else { - DMCoNo *v_co_no = vertexcosnos; + DMCoNo *v_co_no = vertexcosnos = MEM_mallocN(sizeof(DMCoNo) * me->totvert, "vertexcosnos map"); int a; - for (a = 0; a < me->totvert; a++, v_co_no++) { dm->getVertCo(dm, a, v_co_no->co); dm->getVertNo(dm, a, v_co_no->no); diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 63e12dfb99d..5ccf9146440 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -1118,18 +1118,18 @@ void BKE_pose_rest(bPose *pose) } /* both poses should be in sync */ -void BKE_pose_copy_result(bPose *to, bPose *from) +bool BKE_pose_copy_result(bPose *to, bPose *from) { bPoseChannel *pchanto, *pchanfrom; if (to == NULL || from == NULL) { - printf("pose result copy error to:%p from:%p\n", (void *)to, (void *)from); /* debug temp */ - return; + printf("Pose copy error, pose to:%p from:%p\n", (void *)to, (void *)from); /* debug temp */ + return false; } if (to == from) { printf("BKE_pose_copy_result source and target are the same\n"); - return; + return false; } @@ -1153,6 +1153,7 @@ void BKE_pose_copy_result(bPose *to, bPose *from) pchanto->protectflag = pchanfrom->protectflag; } } + return true; } /* For the calculation of the effects of an Action at the given frame on an object diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 4058809c275..dab54756c82 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -69,6 +69,7 @@ #include "BKE_depsgraph.h" #include "BKE_anim.h" #include "BKE_report.h" +#include "BKE_rigidbody.h" // XXX bad level call... @@ -327,6 +328,7 @@ static void motionpaths_calc_update_scene(Scene *scene) { #if 1 // 'production' optimizations always on Base *base, *last = NULL; + float ctime = BKE_scene_frame_get(scene); /* only stuff that moves or needs display still */ DAG_scene_update_flags(G.main, scene, scene->lay, TRUE); @@ -340,6 +342,14 @@ static void motionpaths_calc_update_scene(Scene *scene) last = base; } + /* run rigidbody sim + * NOTE: keep in sync with BKE_scene_update_for_newframe() in scene.c + */ + // XXX: this position may still change, objects not being updated correctly before simulation is run + // NOTE: current position is so that rigidbody sim affects other objects + if (BKE_scene_check_rigidbody_active(scene)) + BKE_rigidbody_do_simulation(scene, ctime); + /* perform updates for tagged objects */ /* XXX: this will break if rigs depend on scene or other data that * is animated but not attached to/updatable from objects */ diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 11ae242023c..fb2d1a3aaf7 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -426,6 +426,9 @@ void BKE_userdef_free(void) /* handle changes in settings that need recalc */ void BKE_userdef_state(void) { + /* prevent accidents */ + if (U.pixelsize == 0) U.pixelsize = 1; + BLF_default_dpi(U.pixelsize * U.dpi); U.widget_unit = (U.pixelsize * U.dpi * 20 + 36) / 72; diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index 6db1052d6bd..624e86d5787 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -462,6 +462,10 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int OceanModifierData *omd = (OceanModifierData *) md; rewrite_path_fixed(omd->cachepath, visit_cb, absbase, bpath_user_data); } + else if (md->type == eModifierType_MeshCache) { + MeshCacheModifierData *mcmd = (MeshCacheModifierData *) md; + rewrite_path_fixed(mcmd->filepath, visit_cb, absbase, bpath_user_data); + } } if (ob->soft) { diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index aeb0407b37f..70eaa00b82e 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -259,7 +259,6 @@ void BKE_brush_debug_print_state(Brush *br) BR_TEST_FLAG(BRUSH_SIZE_PRESSURE); BR_TEST_FLAG(BRUSH_JITTER_PRESSURE); BR_TEST_FLAG(BRUSH_SPACING_PRESSURE); - BR_TEST_FLAG(BRUSH_FIXED_TEX); BR_TEST_FLAG(BRUSH_RAKE); BR_TEST_FLAG(BRUSH_ANCHORED); BR_TEST_FLAG(BRUSH_DIR_IN); @@ -472,8 +471,49 @@ int BKE_brush_clone_image_delete(Brush *brush) return 0; } -/* Brush Sampling */ -void BKE_brush_sample_tex(const Scene *scene, Brush *brush, const float xy[2], float rgba[4], const int thread) +/* Brush Sampling for 3d brushes. Currently used for texture painting only, but should be generalized */ +void BKE_brush_sample_tex(const Scene *scene, Brush *brush, const float sampleco[3], float rgba[4], const int thread, struct ImagePool *pool) +{ + MTex *mtex = &brush->mtex; + + if (mtex && mtex->tex) { + float tin, tr, tg, tb, ta; + int hasrgb; + const int radius = BKE_brush_size_get(scene, brush); + + if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) { + hasrgb = externtex(mtex, sampleco, &tin, &tr, &tg, &tb, &ta, thread, pool); + } + else { + float co[3]; + + co[0] = sampleco[0] / radius; + co[1] = sampleco[1] / radius; + co[2] = 0.0f; + + hasrgb = externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, thread, pool); + } + + if (hasrgb) { + rgba[0] = tr; + rgba[1] = tg; + rgba[2] = tb; + rgba[3] = ta; + } + else { + rgba[0] = tin; + rgba[1] = tin; + rgba[2] = tin; + rgba[3] = 1.0f; + } + } + else { + rgba[0] = rgba[1] = rgba[2] = rgba[3] = 1.0f; + } +} + +/* Brush Sampling for 2D brushes. when we unify the brush systems this will be necessarily a separate function */ +void BKE_brush_sample_tex_2D(const Scene *scene, Brush *brush, const float xy[2], float rgba[4], const int thread) { MTex *mtex = &brush->mtex; @@ -486,7 +526,7 @@ void BKE_brush_sample_tex(const Scene *scene, Brush *brush, const float xy[2], f co[1] = xy[1] / radius; co[2] = 0.0f; - hasrgb = externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, thread); + hasrgb = externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, thread, NULL); if (hasrgb) { rgba[0] = tr; @@ -506,7 +546,8 @@ void BKE_brush_sample_tex(const Scene *scene, Brush *brush, const float xy[2], f } } -/* TODO, use define for 'texfall' arg */ +/* TODO, use define for 'texfall' arg + * NOTE: only used for 2d brushes currently! */ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texfall, int bufsize, ImBuf **outbuf, int use_color_correction) { ImBuf *ibuf; @@ -545,10 +586,10 @@ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texf dstf[3] = alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); } else if (texfall == 1) { - BKE_brush_sample_tex(scene, brush, xy, dstf, 0); + BKE_brush_sample_tex_2D(scene, brush, xy, dstf, 0); } else { - BKE_brush_sample_tex(scene, brush, xy, rgba, 0); + BKE_brush_sample_tex_2D(scene, brush, xy, rgba, 0); mul_v3_v3v3(dstf, rgba, brush_rgb); dstf[3] = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); } @@ -575,11 +616,11 @@ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texf dst[3] = FTOCHAR(alpha_f); } else if (texfall == 1) { - BKE_brush_sample_tex(scene, brush, xy, rgba, 0); + BKE_brush_sample_tex_2D(scene, brush, xy, rgba, 0); rgba_float_to_uchar(dst, rgba); } else if (texfall == 2) { - BKE_brush_sample_tex(scene, brush, xy, rgba, 0); + BKE_brush_sample_tex_2D(scene, brush, xy, rgba, 0); mul_v3_v3(rgba, brush->rgb); alpha_f = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); @@ -588,7 +629,7 @@ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texf dst[3] = FTOCHAR(alpha_f); } else { - BKE_brush_sample_tex(scene, brush, xy, rgba, 0); + BKE_brush_sample_tex_2D(scene, brush, xy, rgba, 0); alpha_f = rgba[3] * alpha * BKE_brush_curve_strength_clamp(brush, len_v2(xy), radius); dst[0] = crgb[0]; @@ -621,7 +662,9 @@ void BKE_brush_imbuf_new(const Scene *scene, Brush *brush, short flt, short texf void BKE_brush_size_set(Scene *scene, Brush *brush, int size) { UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; - + + size = (int)((float)size / U.pixelsize); + if (ups->flag & UNIFIED_PAINT_SIZE) ups->size = size; else diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c index ad828a70dd8..5028d978351 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.c @@ -38,11 +38,11 @@ #include "BLI_utildefines.h" #include "BLI_linklist.h" +#include "BLI_math.h" #include "BKE_DerivedMesh.h" #include "BKE_tessmesh.h" -#include "BLI_math.h" #include "MEM_guardedalloc.h" /* Math stuff for ray casting on mesh faces and for nearest surface */ diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index 57c88919021..d1842b99831 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -237,6 +237,9 @@ void BKE_camera_params_from_object(CameraParams *params, Object *ob) params->clipsta = la->clipsta; params->clipend = la->clipend; } + else { + params->lens = 35.0f; + } } void BKE_camera_params_from_view3d(CameraParams *params, View3D *v3d, RegionView3D *rv3d) diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 85dd4c67fdf..66b457ec502 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1111,6 +1111,19 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, index_mp_to_orig = NULL; } + /* TODO: same as for solid draw, not entirely correct, but works fine for now, + * will skip using textures (dyntopo currently destroys UV anyway) and + * works fine for matcap + */ + if (cddm->pbvh && cddm->pbvh_draw && BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH) { + if (dm->numTessFaceData) { + setMaterial(1, &gattribs); + BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, FALSE); + } + + return; + } + cdDM_update_normals_from_pbvh(dm); matnr = -1; @@ -1412,6 +1425,19 @@ static void cdDM_drawMappedFacesMat(DerivedMesh *dm, index_mp_to_orig = NULL; } + /* TODO: same as for solid draw, not entirely correct, but works fine for now, + * will skip using textures (dyntopo currently destroys UV anyway) and + * works fine for matcap + */ + if (cddm->pbvh && cddm->pbvh_draw && BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH) { + if (dm->numTessFaceData) { + setMaterial(userData, 1, NULL); + BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, FALSE); + } + + return; + } + cdDM_update_normals_from_pbvh(dm); matnr = -1; @@ -2285,6 +2311,7 @@ void CDDM_calc_normals_tessface(DerivedMesh *dm) */ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) { +// #define USE_LOOPS CDDerivedMesh *cddm = (CDDerivedMesh *)dm; CDDerivedMesh *cddm2 = NULL; MVert *mv, *mvert = NULL; @@ -2296,18 +2323,27 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) MLoop *ml, *mloop = NULL; BLI_array_declare(mloop); EdgeHash *ehash = BLI_edgehash_new(); - int *newv = NULL, *newe = NULL, *newl = NULL; + int *newv = NULL, *newe = NULL; +#ifdef USE_LOOPS + int *newl = NULL; +#endif int *oldv = NULL, *olde = NULL, *oldl = NULL, *oldp = NULL; BLI_array_declare(oldv); BLI_array_declare(olde); BLI_array_declare(oldl); BLI_array_declare(oldp); - int i, j, c, totloop, totpoly; - + int i, j, c, totpoly; +#ifdef USE_LOOPS + int totloop; +#endif + +#ifdef USE_LOOPS totloop = dm->numLoopData; +#endif totpoly = dm->numPolyData; - newv = MEM_callocN(sizeof(int) * dm->numVertData, "newv vtable CDDM_merge_verts"); - newe = MEM_callocN(sizeof(int) * dm->numEdgeData, "newv etable CDDM_merge_verts"); - newl = MEM_callocN(sizeof(int) * totloop, "newv ltable CDDM_merge_verts"); - + newv = MEM_mallocN(sizeof(int) * dm->numVertData, "newv vtable CDDM_merge_verts"); + newe = MEM_mallocN(sizeof(int) * dm->numEdgeData, "newv etable CDDM_merge_verts"); +#ifdef USE_LOOPS + newl = MEM_mallocN(sizeof(int) * totloop, "newv ltable CDDM_merge_verts"); +#endif /* fill newl with destination vertex indices */ mv = cddm->mvert; c = 0; @@ -2317,6 +2353,10 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) newv[i] = c++; BLI_array_append(mvert, *mv); } + else { + /* dummy value */ + newv[i] = 0; + } } /* now link target vertices to destination indices */ @@ -2385,7 +2425,9 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) for (j = 0; j < mp->totloop; j++, ml++) { med = cddm->medge + ml->e; if (LIKELY(med->v1 != med->v2)) { +#ifdef USE_LOOPS newl[j + mp->loopstart] = BLI_array_count(mloop); +#endif BLI_array_append(oldl, j + mp->loopstart); BLI_array_append(mloop, *ml); c++; @@ -2451,8 +2493,10 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) MEM_freeN(newv); if (newe) MEM_freeN(newe); +#ifdef USE_LOOPS if (newl) MEM_freeN(newl); +#endif if (oldv) MEM_freeN(oldv); if (olde) diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index fdd7dc94979..c1293542963 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -483,7 +483,7 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived clmd->sim_parms->dt = clmd->sim_parms->timescale / clmd->sim_parms->stepsPerFrame; /* handle continuous simulation with the play button */ - if (BKE_ptcache_get_continue_physics() || ((clmd->sim_parms->preroll > 0) && (framenr > startframe - clmd->sim_parms->preroll) && (framenr < startframe))) { + if ((clmd->sim_parms->preroll > 0) && (framenr > startframe - clmd->sim_parms->preroll) && (framenr < startframe)) { BKE_ptcache_invalidate(cache); /* do simulation */ diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 60bf67e19e3..061657c8f2d 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -59,7 +59,7 @@ #include "BKE_modifier.h" #include "BKE_DerivedMesh.h" -#ifdef USE_BULLET +#ifdef WITH_BULLET #include "Bullet-C-Api.h" #endif #include "BLI_kdopbvh.h" @@ -385,7 +385,7 @@ static CollPair* cloth_collision(ModifierData *md1, ModifierData *md2, CollisionModifierData *collmd = (CollisionModifierData *) md2; /* Cloth *cloth = clmd->clothObject; */ /* UNUSED */ MFace *face1=NULL, *face2 = NULL; -#ifdef USE_BULLET +#ifdef WITH_BULLET ClothVertex *verts1 = clmd->clothObject->verts; #endif double distance = 0; @@ -458,7 +458,7 @@ static CollPair* cloth_collision(ModifierData *md1, ModifierData *md2, } } -#ifdef USE_BULLET +#ifdef WITH_BULLET // calc distance + normal distance = plNearestPoints ( verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, collmd->current_x[collpair->bp3].co, collpair->pa, collpair->pb, collpair->vector ); diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 529fe07cab3..d08c16eac9e 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -895,7 +895,7 @@ void curvemapping_table_RGBA(const CurveMapping *cumap, float **array, int *size #define INV_255 (1.f / 255.f) -DO_INLINE int get_bin_float(float f) +BLI_INLINE int get_bin_float(float f) { int bin = (int)((f * 255.0f) + 0.5f); /* 0.5 to prevent quantisation differences */ diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index fe8bd0cc5a4..a6e68b9b2d5 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -1746,7 +1746,7 @@ static void calc_bevel_sin_cos(float x1, float y1, float x2, float y2, float *si else t02 = (saacos(t02)) / 2.0f; - t02 = (float)sin(t02); + t02 = sinf(t02); if (t02 == 0.0f) t02 = 1.0f; @@ -2220,6 +2220,7 @@ void BKE_curve_bevelList_make(Object *ob) struct bevelsort *sortdata, *sd, *sd1; int a, b, nr, poly, resolu = 0, len = 0; int do_tilt, do_radius, do_weight; + int is_editmode = 0; /* this function needs an object, because of tflag and upflag */ cu = ob->data; @@ -2233,12 +2234,17 @@ void BKE_curve_bevelList_make(Object *ob) if (cu->editnurb && ob->type != OB_FONT) { ListBase *nurbs = BKE_curve_editNurbs_get(cu); nu = nurbs->first; + is_editmode = 1; } else { nu = cu->nurb.first; } - while (nu) { + for (; nu; nu = nu->next) { + + if (nu->hide && is_editmode) + continue; + /* check if we will calculate tilt data */ do_tilt = CU_DO_TILT(cu, nu); do_radius = CU_DO_RADIUS(cu, nu); /* normal display uses the radius, better just to calculate them */ @@ -2384,7 +2390,6 @@ void BKE_curve_bevelList_make(Object *ob) } } } - nu = nu->next; } /* STEP 2: DOUBLE POINTS AND AUTOMATIC RESOLUTION, REDUCE DATABLOCKS */ diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 42389564ec0..78d7bfa5bc5 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -2290,7 +2290,7 @@ static short animdata_use_time(AnimData *adt) return 0; } -static void dag_object_time_update_flags(Object *ob) +static void dag_object_time_update_flags(Scene *scene, Object *ob) { if (ob->constraints.first) { bConstraint *con; @@ -2350,6 +2350,9 @@ static void dag_object_time_update_flags(Object *ob) if (object_modifiers_use_time(ob)) ob->recalc |= OB_RECALC_DATA; if ((ob->pose) && (ob->pose->flag & POSE_CONSTRAINTS_TIMEDEPEND)) ob->recalc |= OB_RECALC_DATA; + if (ob->rigidbody_object && BKE_scene_check_rigidbody_active(scene)) + ob->recalc |= OB_RECALC_OB; + { AnimData *adt = BKE_animdata_from_id((ID *)ob->data); Mesh *me; @@ -2434,7 +2437,7 @@ void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const s if (do_time) { /* now if DagNode were part of base, the node->lay could be checked... */ /* we do all now, since the scene_flush checks layers and clears recalc flags even */ - dag_object_time_update_flags(ob); + dag_object_time_update_flags(scene, ob); } /* handled in next loop */ @@ -2447,7 +2450,7 @@ void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const s for (group = bmain->group.first; group; group = group->id.next) { if (group->id.flag & LIB_DOIT) { for (go = group->gobject.first; go; go = go->next) { - dag_object_time_update_flags(go->ob); + dag_object_time_update_flags(scene, go->ob); } } } @@ -2466,7 +2469,7 @@ void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const s /* hrmf... an exception to look at once, for invisible camera object we do it over */ if (scene->camera) - dag_object_time_update_flags(scene->camera); + dag_object_time_update_flags(scene, scene->camera); } /* and store the info in groupobject */ diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 643c7b1d972..23b0d3e6e22 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -309,10 +309,11 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase, i BPoint *bp; float *data; int a, len, resolu; + const int editmode = (!forRender && (cu->editnurb || cu->editfont)); nu = nubase->first; while (nu) { - if (nu->hide == 0) { + if (nu->hide == 0 || editmode == 0) { if (forRender && cu->resolu_ren != 0) resolu = cu->resolu_ren; else diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index fff51ab2a59..c92c52a7651 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -1483,7 +1483,9 @@ static void dynamicPaint_setInitialColor(DynamicPaintSurface *surface) /* for vertex surface loop through tfaces and find uv color * that provides highest alpha */ if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) { - #pragma omp parallel for schedule(static) + struct ImagePool *pool = BKE_image_pool_new(); + + #pragma omp parallel for schedule(static) shared(pool) for (i = 0; i < numOfFaces; i++) { int numOfVert = (mface[i].v4) ? 4 : 3; float uv[3] = {0.0f}; @@ -1496,7 +1498,7 @@ static void dynamicPaint_setInitialColor(DynamicPaintSurface *surface) uv[0] = tface[i].uv[j][0] * 2.0f - 1.0f; uv[1] = tface[i].uv[j][1] * 2.0f - 1.0f; - multitex_ext_safe(tex, uv, &texres); + multitex_ext_safe(tex, uv, &texres, pool); if (texres.tin > pPoint[*vert].alpha) { copy_v3_v3(pPoint[*vert].color, &texres.tr); @@ -1504,6 +1506,7 @@ static void dynamicPaint_setInitialColor(DynamicPaintSurface *surface) } } } + BKE_image_pool_free(pool); } else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) { ImgSeqFormatData *f_data = (ImgSeqFormatData *)sData->format_data; @@ -1529,7 +1532,7 @@ static void dynamicPaint_setInitialColor(DynamicPaintSurface *surface) uv_final[0] = uv_final[0] * 2.0f - 1.0f; uv_final[1] = uv_final[1] * 2.0f - 1.0f; - multitex_ext_safe(tex, uv_final, &texres); + multitex_ext_safe(tex, uv_final, &texres, NULL); /* apply color */ copy_v3_v3(pPoint[i].color, &texres.tr); diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index 91577320a9c..d41893b4335 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -69,7 +69,7 @@ extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */ -BMEditMesh *BMEdit_Create(BMesh *bm, int do_tessellate) +BMEditMesh *BMEdit_Create(BMesh *bm, const bool do_tessellate) { BMEditMesh *em = MEM_callocN(sizeof(BMEditMesh), __func__); @@ -1410,7 +1410,7 @@ static void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r) normal_float_to_short_v3(vert_r->no, eve->no); vert_r->flag = BM_vert_flag_to_mflag(eve); - if (cd_vert_bweight_offset != -1) vert_r->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset); + vert_r->bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset) : 0; vert_r++; } @@ -1421,7 +1421,7 @@ static void emDM_copyVertArray(DerivedMesh *dm, MVert *vert_r) normal_float_to_short_v3(vert_r->no, eve->no); vert_r->flag = BM_vert_flag_to_mflag(eve); - if (cd_vert_bweight_offset != -1) vert_r->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset); + vert_r->bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset) : 0; vert_r++; } @@ -1445,8 +1445,8 @@ static void emDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r) edge_r->flag = BM_edge_flag_to_mflag(eed); - if (cd_edge_crease_offset != -1) edge_r->crease = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_crease_offset); - if (cd_edge_bweight_offset != -1) edge_r->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_bweight_offset); + edge_r->crease = (cd_edge_crease_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_crease_offset) : 0; + edge_r->bweight = (cd_edge_bweight_offset != -1) ? BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_bweight_offset) : 0; edge_r++; } @@ -1469,6 +1469,7 @@ static void emDM_copyTessFaceArray(DerivedMesh *dm, MFace *face_r) face_r->mat_nr = (unsigned char) ef->mat_nr; face_r->flag = BM_face_flag_to_mflag(ef); + face_r->edcode = 0; face_r->v1 = BM_elem_index_get(l[0]->v); face_r->v2 = BM_elem_index_get(l[1]->v); diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 1f6db19ac27..1880cb42f4d 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -769,7 +769,7 @@ static void do_texture_effector(EffectorCache *eff, EffectorData *efd, EffectedP mul_m4_v3(eff->ob->imat, tex_co); } - hasrgb = multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result); + hasrgb = multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result, NULL); if (hasrgb && mode==PFIELD_TEX_RGB) { force[0] = (0.5f - result->tr) * strength; @@ -780,15 +780,15 @@ static void do_texture_effector(EffectorCache *eff, EffectorData *efd, EffectedP strength/=nabla; tex_co[0] += nabla; - multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+1); + multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+1, NULL); tex_co[0] -= nabla; tex_co[1] += nabla; - multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+2); + multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+2, NULL); tex_co[1] -= nabla; tex_co[2] += nabla; - multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+3); + multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+3, NULL); if (mode == PFIELD_TEX_GRAD || !hasrgb) { /* if we don't have rgb fall back to grad */ /* generate intensity if texture only has rgb value */ diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index d4634748c71..3e1e55132d8 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -962,9 +962,9 @@ makebreak: float si, co; ct = chartransdata + cu->pos; - si = (float)sin(ct->rot); - co = (float)cos(ct->rot); - + si = sinf(ct->rot); + co = cosf(ct->rot); + f = cu->editfont->textcurs[0]; f[0] = cu->fsize * (-0.1f * co + ct->xof); diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c index d8c3e260399..9c265814b8f 100644 --- a/source/blender/blenkernel/intern/icons.c +++ b/source/blender/blenkernel/intern/icons.c @@ -51,6 +51,8 @@ #include "BLO_sys_types.h" // for intptr_t support +#include "GPU_extensions.h" + /* GLOBALS */ static GHash *gIcons = NULL; @@ -138,7 +140,10 @@ void BKE_previewimg_freefunc(void *link) MEM_freeN(prv->rect[i]); prv->rect[i] = NULL; } + if (prv->gputexture[i]) + GPU_texture_free(prv->gputexture[i]); } + MEM_freeN(prv); } } @@ -165,6 +170,7 @@ PreviewImage *BKE_previewimg_copy(PreviewImage *prv) else { prv_img->rect[i] = NULL; } + prv_img->gputexture[i] = NULL; } } return prv_img; diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index 3be47668fb5..9086ef49e4d 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -663,7 +663,7 @@ int IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const int is_s { IDProperty *link1, *link2; - if (is_strict && BLI_countlist(&prop1->data.group) != BLI_countlist(&prop2->data.group)) + if (is_strict && prop1->len != prop2->len) return 0; for (link1 = prop1->data.group.first; link1; link1 = link1->next) { diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 21417386d65..82b0d231869 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -2205,9 +2205,20 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) } } +#if 0 /* force reload on first use, but not for multilayer, that makes nodes and buttons in ui drawing fail */ if (ima->type != IMA_TYPE_MULTILAYER) image_free_buffers(ima); +#else + /* image buffers for non-sequence multilayer will share buffers with RenderResult, + * however sequence multilayer will own buffers. Such logic makes switching from + * single multilayer file to sequence completely instable + * since changes in nodes seems this workaround isn't needed anymore, all sockets + * are nicely detecting anyway, but freeing buffers always here makes multilayer + * sequences behave stable + */ + image_free_buffers(ima); +#endif ima->ok = 1; if (iuser) @@ -2811,6 +2822,28 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ return ibuf; } +static void image_get_fame_and_index(Image *ima, ImageUser *iuser, int *frame_r, int *index_r) +{ + int frame = 0, index = 0; + + /* see if we already have an appropriate ibuf, with image source and type */ + if (ima->source == IMA_SRC_MOVIE) { + frame = iuser ? iuser->framenr : ima->lastframe; + } + else if (ima->source == IMA_SRC_SEQUENCE) { + if (ima->type == IMA_TYPE_IMAGE) { + frame = iuser ? iuser->framenr : ima->lastframe; + } + else if (ima->type == IMA_TYPE_MULTILAYER) { + frame = iuser ? iuser->framenr : ima->lastframe; + index = iuser ? iuser->multi_index : IMA_NO_INDEX; + } + } + + *frame_r = frame; + *index_r = index; +} + static ImBuf *image_get_ibuf_threadsafe(Image *ima, ImageUser *iuser, int *frame_r, int *index_r) { ImBuf *ibuf = NULL; @@ -2866,6 +2899,21 @@ static ImBuf *image_get_ibuf_threadsafe(Image *ima, ImageUser *iuser, int *frame return ibuf; } +BLI_INLINE int image_quick_test(Image *ima, ImageUser *iuser) +{ + if (ima == NULL) + return FALSE; + + if (iuser) { + if (iuser->ok == 0) + return FALSE; + } + else if (ima->ok == 0) + return FALSE; + + return TRUE; +} + /* Checks optional ImageUser and verifies/creates ImBuf. * * not thread-safe, so callee should worry about thread locks @@ -2880,14 +2928,7 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) *lock_r = NULL; /* quick reject tests */ - if (ima == NULL) - return NULL; - - if (iuser) { - if (iuser->ok == 0) - return NULL; - } - else if (ima->ok == 0) + if (!image_quick_test(ima, iuser)) return NULL; ibuf = image_get_ibuf_threadsafe(ima, iuser, &frame, &index); @@ -3011,14 +3052,7 @@ int BKE_image_has_ibuf(Image *ima, ImageUser *iuser) ImBuf *ibuf; /* quick reject tests */ - if (ima == NULL) - return FALSE; - - if (iuser) { - if (iuser->ok == 0) - return FALSE; - } - else if (ima->ok == 0) + if (!image_quick_test(ima, iuser)) return FALSE; ibuf = image_get_ibuf_threadsafe(ima, iuser, NULL, NULL); @@ -3037,6 +3071,122 @@ int BKE_image_has_ibuf(Image *ima, ImageUser *iuser) return ibuf != NULL; } +/* ******** Pool for image buffers ******** */ + +typedef struct ImagePoolEntry { + struct ImagePoolEntry *next, *prev; + Image *image; + ImBuf *ibuf; + int index; + int frame; +} ImagePoolEntry; + +typedef struct ImagePool { + ListBase image_buffers; +} ImagePool; + +ImagePool *BKE_image_pool_new(void) +{ + ImagePool *pool = MEM_callocN(sizeof(ImagePool), "Image Pool"); + + return pool; +} + +void BKE_image_pool_free(ImagePool *pool) +{ + ImagePoolEntry *entry, *next_entry; + + /* use single lock to dereference all the image buffers */ + BLI_spin_lock(&image_spin); + + for (entry = pool->image_buffers.first; entry; entry = next_entry) { + next_entry = entry->next; + + if (entry->ibuf) + IMB_freeImBuf(entry->ibuf); + + MEM_freeN(entry); + } + + BLI_spin_unlock(&image_spin); + + MEM_freeN(pool); +} + +BLI_INLINE ImBuf *image_pool_find_entry(ImagePool *pool, Image *image, int frame, int index, int *found) +{ + ImagePoolEntry *entry; + + *found = FALSE; + + for (entry = pool->image_buffers.first; entry; entry = entry->next) { + if (entry->image == image && entry->frame == frame && entry->index == index) { + *found = TRUE; + return entry->ibuf; + } + } + + return NULL; +} + +ImBuf *BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool) +{ + ImBuf *ibuf; + int index, frame, found; + + if (!image_quick_test(ima, iuser)) + return NULL; + + if (pool == NULL) { + /* pool could be NULL, in this case use general acquire function */ + return BKE_image_acquire_ibuf(ima, iuser, NULL); + } + + image_get_fame_and_index(ima, iuser, &frame, &index); + + ibuf = image_pool_find_entry(pool, ima, frame, index, &found); + if (found) + return ibuf; + + BLI_spin_lock(&image_spin); + + ibuf = image_pool_find_entry(pool, ima, frame, index, &found); + + /* will also create entry even in cases image buffer failed to load, + * prevents trying to load the same buggy file multiple times + */ + if (!found) { + ImagePoolEntry *entry; + + ibuf = image_acquire_ibuf(ima, iuser, NULL); + + if (ibuf) + IMB_refImBuf(ibuf); + + entry = MEM_callocN(sizeof(ImagePoolEntry), "Image Pool Entry"); + entry->image = ima; + entry->frame = frame; + entry->index = index; + entry->ibuf = ibuf; + + BLI_addtail(&pool->image_buffers, entry); + } + + BLI_spin_unlock(&image_spin); + + return ibuf; +} + +void BKE_image_pool_release_ibuf(Image *ima, ImBuf *ibuf, ImagePool *pool) +{ + /* if pool wasn't actually used, use general release stuff, + * for pools image buffers will be dereferenced on pool free + */ + if (pool == NULL) { + BKE_image_release_ibuf(ima, ibuf, NULL); + } +} + int BKE_image_user_frame_get(const ImageUser *iuser, int cfra, int fieldnr, short *r_is_in_range) { const int len = (iuser->fie_ima * iuser->frames) / 2; @@ -3199,3 +3349,57 @@ void BKE_image_get_aspect(Image *image, float *aspx, float *aspy) else *aspy = 1.0f; } + +unsigned char *BKE_image_get_pixels_for_frame(struct Image *image, int frame) +{ + ImageUser iuser = {0}; + void *lock; + ImBuf *ibuf; + unsigned char *pixels = NULL; + + iuser.framenr = frame; + iuser.ok = TRUE; + + ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock); + + if (ibuf) { + pixels = (unsigned char *) ibuf->rect; + + if (pixels) + pixels = MEM_dupallocN(pixels); + + BKE_image_release_ibuf(image, ibuf, lock); + } + + if (!pixels) + return NULL; + + return pixels; +} + +float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame) +{ + ImageUser iuser = {0}; + void *lock; + ImBuf *ibuf; + float *pixels = NULL; + + iuser.framenr = frame; + iuser.ok = TRUE; + + ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock); + + if (ibuf) { + pixels = ibuf->rect_float; + + if (pixels) + pixels = MEM_dupallocN(pixels); + + BKE_image_release_ibuf(image, ibuf, lock); + } + + if (!pixels) + return NULL; + + return pixels; +} diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index ccc57a24540..803b1e68915 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -108,19 +108,6 @@ void BKE_key_free_nolib(Key *key) } -/* GS reads the memory pointed at in a specific ordering. There are, - * however two definitions for it. I have jotted them down here, both, - * but I think the first one is actually used. The thing is that - * big-endian systems might read this the wrong way round. OTOH, we - * constructed the IDs that are read out with this macro explicitly as - * well. I expect we'll sort it out soon... */ - -/* from blendef: */ -#define GS(a) (*((short *)(a))) - -/* from misc_util: flip the bytes from x */ -/* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */ - Key *BKE_key_add(ID *id) /* common function */ { Key *key; diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 98625807ddc..610237abcdd 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -47,6 +47,7 @@ #include "DNA_brush_types.h" #include "DNA_camera_types.h" #include "DNA_group_types.h" +#include "DNA_gpencil_types.h" #include "DNA_ipo_types.h" #include "DNA_key_types.h" #include "DNA_lamp_types.h" @@ -54,6 +55,8 @@ #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meta_types.h" +#include "DNA_movieclip_types.h" +#include "DNA_mask_types.h" #include "DNA_nla_types.h" #include "DNA_node_types.h" #include "DNA_scene_types.h" @@ -64,51 +67,49 @@ #include "DNA_vfont_types.h" #include "DNA_windowmanager_types.h" #include "DNA_world_types.h" -#include "DNA_gpencil_types.h" -#include "DNA_movieclip_types.h" -#include "DNA_mask_types.h" #include "BLI_blenlib.h" #include "BLI_dynstr.h" #include "BLI_utildefines.h" #include "BKE_bpath.h" +#include "BKE_action.h" #include "BKE_animsys.h" +#include "BKE_armature.h" +#include "BKE_brush.h" #include "BKE_camera.h" #include "BKE_context.h" -#include "BKE_lamp.h" -#include "BKE_library.h" -#include "BKE_main.h" -#include "BKE_global.h" -#include "BKE_sound.h" -#include "BKE_object.h" -#include "BKE_screen.h" -#include "BKE_mesh.h" -#include "BKE_material.h" #include "BKE_curve.h" -#include "BKE_mball.h" -#include "BKE_text.h" -#include "BKE_texture.h" -#include "BKE_scene.h" +#include "BKE_fcurve.h" +#include "BKE_font.h" +#include "BKE_global.h" +#include "BKE_group.h" +#include "BKE_gpencil.h" +#include "BKE_idprop.h" #include "BKE_icons.h" #include "BKE_image.h" #include "BKE_ipo.h" #include "BKE_key.h" -#include "BKE_world.h" -#include "BKE_font.h" -#include "BKE_group.h" +#include "BKE_lamp.h" #include "BKE_lattice.h" -#include "BKE_armature.h" -#include "BKE_action.h" +#include "BKE_library.h" +#include "BKE_mesh.h" +#include "BKE_material.h" +#include "BKE_main.h" +#include "BKE_mball.h" +#include "BKE_movieclip.h" +#include "BKE_mask.h" #include "BKE_node.h" -#include "BKE_brush.h" -#include "BKE_idprop.h" +#include "BKE_object.h" #include "BKE_particle.h" -#include "BKE_gpencil.h" -#include "BKE_fcurve.h" +#include "BKE_packedFile.h" #include "BKE_speaker.h" -#include "BKE_movieclip.h" -#include "BKE_mask.h" +#include "BKE_sound.h" +#include "BKE_screen.h" +#include "BKE_scene.h" +#include "BKE_text.h" +#include "BKE_texture.h" +#include "BKE_world.h" #ifdef WITH_FREESTYLE # include "BKE_linestyle.h" #endif @@ -125,9 +126,6 @@ * only use this definition, makes little and big endian systems * work fine, in conjunction with MAKE_ID */ -/* from blendef: */ -#define GS(a) (*((short *)(a))) - /* ************* general ************************ */ @@ -795,9 +793,10 @@ void *BKE_libblock_copy(ID *id) return idn; } -static void BKE_library_free(Library *UNUSED(lib)) +static void BKE_library_free(Library *lib) { - /* no freeing needed for libraries yet */ + if (lib->packedfile) + freePackedFile(lib->packedfile); } static void (*free_windowmanager_cb)(bContext *, wmWindowManager *) = NULL; diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 4655dd04261..ad0a149a42c 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -684,19 +684,6 @@ Material *give_node_material(Material *ma) return NULL; } -/* GS reads the memory pointed at in a specific ordering. There are, - * however two definitions for it. I have jotted them down here, both, - * but I think the first one is actually used. The thing is that - * big-endian systems might read this the wrong way round. OTOH, we - * constructed the IDs that are read out with this macro explicitly as - * well. I expect we'll sort it out soon... */ - -/* from blendef: */ -#define GS(a) (*((short *)(a))) - -/* from misc_util: flip the bytes from x */ -/* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */ - void resize_object_material(Object *ob, const short totcol) { Material **newmatar; diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index dec7556392f..03df0c28944 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -533,7 +533,7 @@ BMesh *BKE_mesh_to_bmesh(Mesh *me, Object *ob) bm = BM_mesh_create(&bm_mesh_allocsize_default); - BM_mesh_bm_from_me(bm, me, TRUE, ob->shapenr); + BM_mesh_bm_from_me(bm, me, true, ob->shapenr); return bm; } @@ -1360,7 +1360,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase, int i; for (i = 0; i < 3; i++, mloopuv++) { - mloopuv->uv[0] = (mloop[i].v - startvert)/(float)(dl->nr - 1); + mloopuv->uv[0] = (mloop[i].v - startvert) / (float)(dl->nr - 1); mloopuv->uv[1] = 0.0f; } } @@ -1430,8 +1430,8 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase, /* find uv based on vertex index into grid array */ int v = mloop[i].v - startvert; - mloopuv->uv[0] = (v / dl->nr)/(float)orco_sizev; - mloopuv->uv[1] = (v % dl->nr)/(float)orco_sizeu; + mloopuv->uv[0] = (v / dl->nr) / (float)orco_sizev; + mloopuv->uv[1] = (v % dl->nr) / (float)orco_sizeu; /* cyclic correction */ if ((i == 0 || i == 1) && mloopuv->uv[1] == 0.0f) @@ -2993,6 +2993,68 @@ float BKE_mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart, } } +/** + * This function takes the difference between 2 vertex-coord-arrays + * (\a vert_cos_src, \a vert_cos_dst), + * and applies the difference to \a vert_cos_new relative to \a vert_cos_org. + * + * \param vert_cos_src reference deform source. + * \param vert_cos_dst reference deform destination. + * + * \param vert_cos_org reference for the output location. + * \param vert_cos_new resulting coords. + */ +void BKE_mesh_calc_relative_deform( + const MPoly *mpoly, const int totpoly, + const MLoop *mloop, const int totvert, + + const float (*vert_cos_src)[3], + const float (*vert_cos_dst)[3], + + const float (*vert_cos_org)[3], + float (*vert_cos_new)[3]) +{ + const MPoly *mp; + int i; + + int *vert_accum = MEM_callocN(sizeof(*vert_accum) * totvert, __func__); + + memset(vert_cos_new, '\0', sizeof(*vert_cos_new) * totvert); + + for (i = 0, mp = mpoly; i < totpoly; i++, mp++) { + const MLoop *loopstart = mloop + mp->loopstart; + int j; + + for (j = 0; j < mp->totloop; j++) { + int v_prev = (loopstart + ((mp->totloop + (j - 1)) % mp->totloop))->v; + int v_curr = (loopstart + j)->v; + int v_next = (loopstart + ((j + 1) % mp->totloop))->v; + + float tvec[3]; + + barycentric_transform( + tvec, vert_cos_dst[v_curr], + vert_cos_org[v_prev], vert_cos_org[v_curr], vert_cos_org[v_next], + vert_cos_src[v_prev], vert_cos_src[v_curr], vert_cos_src[v_next] + ); + + add_v3_v3(vert_cos_new[v_curr], tvec); + vert_accum[v_curr] += 1; + } + } + + for (i = 0; i < totvert; i++) { + if (vert_accum[i]) { + mul_v3_fl(vert_cos_new[i], 1.0f / (float)vert_accum[i]); + } + else { + copy_v3_v3(vert_cos_new[i], vert_cos_org[i]); + } + } + + MEM_freeN(vert_accum); +} + /* Find the index of the loop in 'poly' which references vertex, * returns -1 if not found */ int poly_find_loop_from_vert(const MPoly *poly, const MLoop *loopstart, diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index b12463daf72..722e1f2b918 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -1559,7 +1559,7 @@ static void old_mdisps_convert(MFace *mface, MDisps *mdisp) if (S == 1) { (*out)[1] = -(*out)[1]; } else if (S == 2) { SWAP(float, (*out)[0], (*out)[1]); } else if (S == 3) { (*out)[0] = -(*out)[0]; } - else if (S == 0) { SWAP(float, (*out)[0], (*out)[1]); (*out)[0] = -(*out)[0]; (*out)[1] = -(*out)[1]; }; + else if (S == 0) { SWAP(float, (*out)[0], (*out)[1]); (*out)[0] = -(*out)[0]; (*out)[1] = -(*out)[1]; } } } } diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 84e280034ed..c73bd5ef8fd 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1035,9 +1035,6 @@ void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user) */ if (ntree->execdata) { switch (ntree->type) { - case NTREE_COMPOSIT: - ntreeCompositEndExecTree(ntree->execdata, 1); - break; case NTREE_SHADER: ntreeShaderEndExecTree(ntree->execdata, 1); break; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 5a22973164e..8a6309593f1 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -83,6 +83,7 @@ #include "BKE_fcurve.h" #include "BKE_group.h" #include "BKE_icons.h" +#include "BKE_image.h" #include "BKE_key.h" #include "BKE_lamp.h" #include "BKE_lattice.h" @@ -97,6 +98,7 @@ #include "BKE_particle.h" #include "BKE_pointcache.h" #include "BKE_property.h" +#include "BKE_rigidbody.h" #include "BKE_sca.h" #include "BKE_scene.h" #include "BKE_sequencer.h" @@ -312,6 +314,9 @@ void free_sculptsession(Object *ob) if (ss->texcache) MEM_freeN(ss->texcache); + if (ss->tex_pool) + BKE_image_pool_free(ss->tex_pool); + if (ss->layer_co) MEM_freeN(ss->layer_co); @@ -386,6 +391,8 @@ void BKE_object_free(Object *ob) BKE_free_constraints(&ob->constraints); free_partdeflect(ob->pd); + BKE_rigidbody_free_object(ob); + BKE_rigidbody_free_constraint(ob); if (ob->soft) sbFree(ob->soft); if (ob->bsoft) bsbFree(ob->bsoft); @@ -1296,6 +1303,8 @@ static Object *object_copy_do(Object *ob, int copy_caches) } obn->soft = copy_softbody(ob->soft, copy_caches); obn->bsoft = copy_bulletsoftbody(ob->bsoft); + obn->rigidbody_object = BKE_rigidbody_copy_object(ob); + obn->rigidbody_constraint = BKE_rigidbody_copy_constraint(ob); BKE_object_copy_particlesystems(obn, ob); @@ -2153,6 +2162,8 @@ void BKE_object_where_is_calc_time(Scene *scene, Object *ob, float ctime) BKE_object_to_mat4(ob, ob->obmat); } + BKE_rigidbody_sync_transforms(scene, ob, ctime); + /* solve constraints */ if (ob->constraints.first && !(ob->transflag & OB_NO_CONSTRAINTS)) { bConstraintOb *cob; @@ -2714,8 +2725,10 @@ void BKE_object_handle_update(Scene *scene, Object *ob) case OB_ARMATURE: if (ob->id.lib && ob->proxy_from) { - // printf("pose proxy copy, lib ob %s proxy %s\n", ob->id.name, ob->proxy_from->id.name); - BKE_pose_copy_result(ob->pose, ob->proxy_from->pose); + if (BKE_pose_copy_result(ob->pose, ob->proxy_from->pose) == false) { + printf("Proxy copy error, lib Object: %s proxy Object: %s\n", + ob->id.name + 2, ob->proxy_from->id.name + 2); + } } else { BKE_pose_where_is(scene, ob); diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index c4274aa1f93..695ac7da792 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -35,10 +35,6 @@ #include "DNA_scene_types.h" -#include "BKE_global.h" /* XXX TESTING */ -#include "BKE_image.h" -#include "BKE_ocean.h" - #include "BLI_math.h" #include "BLI_path_util.h" #include "BLI_rand.h" @@ -46,6 +42,9 @@ #include "BLI_threads.h" #include "BLI_utildefines.h" +#include "BKE_image.h" +#include "BKE_ocean.h" + #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -1425,4 +1424,4 @@ void BKE_bake_ocean(struct Ocean *UNUSED(o), struct OceanCache *UNUSED(och), /* unused */ (void)update_cb; } -#endif /* WITH_OCEANSIM */
\ No newline at end of file +#endif /* WITH_OCEANSIM */ diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 9f77094994d..9fab052f80c 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -553,7 +553,7 @@ int unpackLibraries(Main *bmain, ReportList *reports) if (newname != NULL) { ret_value = RET_OK; - printf("Saved .blend library: %s\n", newname); + printf("Unpacked .blend library: %s\n", newname); freePackedFile(lib->packedfile); lib->packedfile = NULL; @@ -570,6 +570,16 @@ void packLibraries(Main *bmain, ReportList *reports) { Library *lib; + /* test for relativenss */ + for (lib = bmain->library.first; lib; lib = lib->id.next) + if (0 == BLI_path_is_rel(lib->name)) + break; + + if (lib) { + BKE_reportf(reports, RPT_ERROR, "Cannot pack absolute file: '%s'", lib->name); + return; + } + for (lib = bmain->library.first; lib; lib = lib->id.next) if (lib->packedfile == NULL) lib->packedfile = newPackedFile(reports, lib->name, bmain->name); diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 5847e7508f0..dc8aed91c00 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -47,6 +47,8 @@ #include "BKE_paint.h" #include "BKE_subsurf.h" +#include "bmesh.h" + #include <stdlib.h> #include <string.h> @@ -224,6 +226,22 @@ int paint_is_grid_face_hidden(const unsigned int *grid_hidden, BLI_BITMAP_GET(grid_hidden, (y + 1) * gridsize + x)); } +/* Return TRUE if all vertices in the face are visible, FALSE otherwise */ +int paint_is_bmesh_face_hidden(BMFace *f) +{ + BMLoop *l_iter; + BMLoop *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (BM_elem_flag_test(l_iter->v, BM_ELEM_HIDDEN)) { + return true; + } + } while ((l_iter = l_iter->next) != l_first); + + return false; +} + float paint_grid_paint_mask(const GridPaintMask *gpm, unsigned level, unsigned x, unsigned y) { diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index b2851962b49..71854a93f4d 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -3849,7 +3849,7 @@ static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSetti break; } - externtex(mtex, texvec, &value, rgba, rgba + 1, rgba + 2, rgba + 3, 0); + externtex(mtex, texvec, &value, rgba, rgba + 1, rgba + 2, rgba + 3, 0, NULL); if ((event & mtex->mapto) & PAMAP_ROUGH) ptex->rough1 = ptex->rough2 = ptex->roughe = texture_value_blend(def, ptex->rough1, value, mtex->roughfac, blend); @@ -3920,7 +3920,7 @@ void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTex break; } - externtex(mtex, texvec, &value, rgba, rgba + 1, rgba + 2, rgba + 3, 0); + externtex(mtex, texvec, &value, rgba, rgba + 1, rgba + 2, rgba + 3, 0, NULL); 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_system.c b/source/blender/blenkernel/intern/particle_system.c index 5eac86a7e77..fda5f6f2ecb 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -4500,7 +4500,7 @@ static void system_step(ParticleSimulationData *sim, float cfra) int startframe = 0, endframe = 100, oldtotpart = 0; /* cache shouldn't be used for hair or "continue physics" */ - if (part->type != PART_HAIR && BKE_ptcache_get_continue_physics() == 0) { + if (part->type != PART_HAIR) { psys_clear_temp_pointcache(psys); /* set suitable cache range automatically */ diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 2df2dd631d5..483dd2570e2 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -1238,6 +1238,19 @@ PBVHType BKE_pbvh_type(const PBVH *bvh) return bvh->type; } +void BKE_pbvh_bounding_box(const PBVH *bvh, float min[3], float max[3]) +{ + if (bvh->totnode) { + const BB *bb = &bvh->nodes[0].vb; + copy_v3_v3(min, bb->bmin); + copy_v3_v3(max, bb->bmax); + } + else { + zero_v3(min); + zero_v3(max); + } +} + BLI_bitmap *BKE_pbvh_grid_hidden(const PBVH *bvh) { BLI_assert(bvh->type == PBVH_GRIDS); @@ -1386,10 +1399,10 @@ void BKE_pbvh_raycast(PBVH *bvh, BKE_pbvh_HitOccludedCallback cb, void *data, } int ray_face_intersection(const float ray_start[3], - const float ray_normal[3], - const float *t0, const float *t1, - const float *t2, const float *t3, - float *fdist) + const float ray_normal[3], + const float *t0, const float *t1, + const float *t2, const float *t3, + float *fdist) { float dist; diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index 791288a4dda..9a0b1a76988 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -28,6 +28,7 @@ #include "BKE_ccg.h" #include "BKE_DerivedMesh.h" #include "BKE_global.h" +#include "BKE_paint.h" #include "BKE_pbvh.h" #include "GPU_buffers.h" @@ -53,7 +54,8 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index) GHASH_ITER (gh_iter, n->bm_faces) { BMFace *f = BLI_ghashIterator_getKey(&gh_iter); - BMIter bm_iter; + BMLoop *l_iter; + BMLoop *l_first; BMVert *v; void *node_val = SET_INT_IN_POINTER(node_index); @@ -61,7 +63,9 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index) BLI_ghash_insert(bvh->bm_face_to_node, f, node_val); /* Update vertices */ - BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) { + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + v = l_iter->v; if (!BLI_ghash_haskey(n->bm_unique_verts, v)) { if (BLI_ghash_haskey(bvh->bm_vert_to_node, v)) { if (!BLI_ghash_haskey(n->bm_other_verts, v)) @@ -74,7 +78,7 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index) } /* Update node bounding box */ BB_expand(&n->vb, v->co); - } + } while ((l_iter = l_iter->next) != l_first); } BLI_assert(n->vb.bmin[0] <= n->vb.bmax[0] && @@ -233,15 +237,16 @@ static int pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index) prim_bbc = BLI_ghash_ptr_new("prim_bbc"); GHASH_ITER (gh_iter, bvh->nodes[node_index].bm_faces) { - BMIter bm_iter; - BMVert *v; BMFace *f = BLI_ghashIterator_getKey(&gh_iter); BBC *bbc = MEM_callocN(sizeof(BBC), "BBC"); + BMLoop *l_iter; + BMLoop *l_first; BB_reset((BB *)bbc); - BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) { - BB_expand((BB *)bbc, v->co); - } + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + BB_expand((BB *)bbc, l_iter->v->co); + } while ((l_iter = l_iter->next) != l_first); BBC_update_centroid(bbc); BLI_ghash_insert(prim_bbc, f, bbc); @@ -286,16 +291,16 @@ static BMVert *pbvh_bmesh_vert_create(PBVH *bvh, int node_index, return v; } -static BMFace *pbvh_bmesh_face_create(PBVH *bvh, int node_index, BMVert *v1, - BMVert *v2, BMVert *v3, - const BMFace *UNUSED(example)) +static BMFace *pbvh_bmesh_face_create(PBVH *bvh, int node_index, + BMVert *v1, BMVert *v2, BMVert *v3, + const BMFace *UNUSED(example)) { BMFace *f; void *val = SET_INT_IN_POINTER(node_index); /* Note: passing NULL for the 'example' parameter, profiling shows * a small performance bump */ - f = BM_face_create_quad_tri(bvh->bm, v1, v2, v3, NULL, NULL, TRUE); + f = BM_face_create_quad_tri(bvh->bm, v1, v2, v3, NULL, NULL, true); if (!BLI_ghash_haskey(bvh->bm_face_to_node, f)) { BLI_ghash_insert(bvh->nodes[node_index].bm_faces, f, NULL); @@ -394,14 +399,18 @@ static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v) static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f) { PBVHNode *f_node; - BMIter bm_iter; BMVert *v; + BMLoop *l_iter; + BMLoop *l_first; + f_node = pbvh_bmesh_node_lookup(bvh, bvh->bm_face_to_node, f); /* Check if any of this face's vertices need to be removed * from the node */ - BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) { + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + v = l_iter->v; if (pbvh_bmesh_node_vert_use_count(bvh, f_node, v) == 1) { if (BLI_ghash_lookup(f_node->bm_unique_verts, v)) { /* Find a different node that uses 'v' */ @@ -419,7 +428,7 @@ static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f) BLI_ghash_remove(f_node->bm_other_verts, v, NULL, NULL); } } - } + } while ((l_iter = l_iter->next) != l_first); /* Remove face from node and top level */ BLI_ghash_remove(f_node->bm_faces, f, NULL, NULL); @@ -429,57 +438,20 @@ static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f) BM_log_face_removed(bvh->bm_log, f); } -static BMVert *bm_triangle_other_vert_find(BMFace *triangle, const BMVert *v1, - const BMVert *v2) +static void pbvh_bmesh_edge_loops(BLI_Buffer *buf, BMEdge *e) { - BLI_assert(triangle->len == 3); - BLI_assert(v1 != v2); - - if (triangle->len == 3) { - BMIter iter; - BMVert *v, *other = NULL; - int found_v1 = FALSE, found_v2 = FALSE; - - BM_ITER_ELEM (v, &iter, triangle, BM_VERTS_OF_FACE) { - if (v == v1) - found_v1 = TRUE; - else if (v == v2) - found_v2 = TRUE; - else - other = v; - } - - if (found_v1 && found_v2) - return other; + /* fast-path for most common case where an edge has 2 faces, + * no need to iterate twice. + * This assumes that the buffer */ + BMLoop **data = buf->data; + BLI_assert(buf->alloc_count >= 2); + if (LIKELY(BM_edge_loop_pair(e, &data[0], &data[1]))) { + buf->count = 2; } - - BLI_assert(0); - return NULL; -} - -static void pbvh_bmesh_edge_faces(BLI_Buffer *buf, BMEdge *e) -{ - BLI_buffer_resize(buf, BM_edge_face_count(e)); - BM_iter_as_array(NULL, BM_FACES_OF_EDGE, e, buf->data, buf->count); -} - -/* TODO: maybe a better way to do this, if not then this should go to - * bmesh_queries */ -static int bm_face_edge_backwards(BMFace *f, BMEdge *e) -{ - BMIter bm_iter; - BMLoop *l, *l1 = NULL, *l2 = NULL; - - BM_ITER_ELEM (l, &bm_iter, f, BM_LOOPS_OF_FACE) { - if (l->v == e->v1) - l1 = l; - else if (l->v == e->v2) - l2 = l; + else { + BLI_buffer_resize(buf, BM_edge_face_count(e)); + BM_iter_as_array(NULL, BM_LOOPS_OF_EDGE, e, buf->data, buf->count); } - - BLI_assert(l1 && l2); - BLI_assert(l1->next == l2 || l2->next == l1); - return l2->next == l1; } static void pbvh_bmesh_node_drop_orig(PBVHNode *node) @@ -504,12 +476,14 @@ typedef struct { static int edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f) { - BMVert *v[3]; + BMVert *v_tri[3]; float c[3]; /* Get closest point in triangle to sphere center */ - BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3); - closest_on_tri_to_point_v3(c, q->center, v[0]->co, v[1]->co, v[2]->co); + // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v_tri, 3); + BM_face_as_array_vert_tri(f, v_tri); + + closest_on_tri_to_point_v3(c, q->center, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co); /* Check if triangle intersects the sphere */ return ((len_squared_v3v3(q->center, c) <= q->radius_squared)); @@ -542,36 +516,34 @@ static void short_edge_queue_edge_add(EdgeQueue *q, BLI_mempool *pool, edge_queue_insert(q, pool, e, len_sq); } -static int long_edge_queue_face_add(EdgeQueue *q, BLI_mempool *pool, - BMFace *f) +static void long_edge_queue_face_add(EdgeQueue *q, BLI_mempool *pool, + BMFace *f) { - BMIter bm_iter; - BMEdge *e; - if (edge_queue_tri_in_sphere(q, f)) { + BMLoop *l_iter; + BMLoop *l_first; + /* Check each edge of the face */ - BM_ITER_ELEM (e, &bm_iter, f, BM_EDGES_OF_FACE) { - long_edge_queue_edge_add(q, pool, e); - } + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + long_edge_queue_edge_add(q, pool, l_iter->e); + } while ((l_iter = l_iter->next) != l_first); } - - return TRUE; } -static int short_edge_queue_face_add(EdgeQueue *q, BLI_mempool *pool, - BMFace *f) +static void short_edge_queue_face_add(EdgeQueue *q, BLI_mempool *pool, + BMFace *f) { - BMIter bm_iter; - BMEdge *e; - if (edge_queue_tri_in_sphere(q, f)) { + BMLoop *l_iter; + BMLoop *l_first; + /* Check each edge of the face */ - BM_ITER_ELEM (e, &bm_iter, f, BM_EDGES_OF_FACE) { - short_edge_queue_edge_add(q, pool, e); - } + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + short_edge_queue_edge_add(q, pool, l_iter->e); + } while ((l_iter = l_iter->next) != l_first); } - - return TRUE; } /* Create a priority queue containing vertex pairs connected by a long @@ -655,25 +627,26 @@ static void short_edge_queue_create(EdgeQueue *q, BLI_mempool *pool, /*************************** Topology update **************************/ static void pbvh_bmesh_split_edge(PBVH *bvh, EdgeQueue *q, BLI_mempool *pool, - BMEdge *e, BLI_Buffer *edge_faces) + BMEdge *e, BLI_Buffer *edge_loops) { BMVert *v_new; float mid[3]; int i, node_index; /* Get all faces adjacent to the edge */ - pbvh_bmesh_edge_faces(edge_faces, e); + pbvh_bmesh_edge_loops(edge_loops, e); /* Create a new vertex in current node at the edge's midpoint */ mid_v3_v3v3(mid, e->v1->co, e->v2->co); node_index = GET_INT_FROM_POINTER(BLI_ghash_lookup(bvh->bm_vert_to_node, - e->v1)); + e->v1)); v_new = pbvh_bmesh_vert_create(bvh, node_index, mid, e->v1); /* For each face, add two new triangles and delete the original */ - for (i = 0; i < edge_faces->count; i++) { - BMFace *f_adj = BLI_buffer_at(edge_faces, BMFace *, i); + for (i = 0; i < edge_loops->count; i++) { + BMLoop *l_adj = BLI_buffer_at(edge_loops, BMLoop *, i); + BMFace *f_adj = l_adj->f; BMFace *f_new; BMVert *opp, *v1, *v2; void *nip; @@ -687,15 +660,13 @@ static void pbvh_bmesh_split_edge(PBVH *bvh, EdgeQueue *q, BLI_mempool *pool, bvh->nodes[ni].flag |= PBVH_UpdateDrawBuffers; /* Find the vertex not in the edge */ - opp = bm_triangle_other_vert_find(f_adj, e->v1, e->v2); + opp = l_adj->prev->v; /* Get e->v1 and e->v2 in the order they appear in the * existing face so that the new faces' winding orders * match */ - v1 = e->v1; - v2 = e->v2; - if (bm_face_edge_backwards(f_adj, e)) - SWAP(BMVert *, v1, v2); + v1 = l_adj->v; + v2 = l_adj->next->v; if (ni != node_index && i == 0) pbvh_bmesh_vert_ownership_transfer(bvh, &bvh->nodes[ni], v_new); @@ -731,8 +702,8 @@ static void pbvh_bmesh_split_edge(PBVH *bvh, EdgeQueue *q, BLI_mempool *pool, } static int pbvh_bmesh_subdivide_long_edges(PBVH *bvh, EdgeQueue *q, - BLI_mempool *pool, - BLI_Buffer *edge_faces) + BLI_mempool *pool, + BLI_Buffer *edge_loops) { int any_subdivided = FALSE; @@ -764,30 +735,31 @@ static int pbvh_bmesh_subdivide_long_edges(PBVH *bvh, EdgeQueue *q, any_subdivided = TRUE; - pbvh_bmesh_split_edge(bvh, q, pool, e, edge_faces); + pbvh_bmesh_split_edge(bvh, q, pool, e, edge_loops); } return any_subdivided; } static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1, - BMVert *v2, GHash *deleted_verts, - BLI_Buffer *edge_faces, - BLI_Buffer *deleted_faces) + BMVert *v2, GHash *deleted_verts, + BLI_Buffer *edge_loops, + BLI_Buffer *deleted_faces) { BMIter bm_iter; BMFace *f; int i; /* Get all faces adjacent to the edge */ - pbvh_bmesh_edge_faces(edge_faces, e); + pbvh_bmesh_edge_loops(edge_loops, e); /* Remove the merge vertex from the PBVH */ pbvh_bmesh_vert_remove(bvh, v2); /* Remove all faces adjacent to the edge */ - for (i = 0; i < edge_faces->count; i++) { - BMFace *f_adj = BLI_buffer_at(edge_faces, BMFace *, i); + for (i = 0; i < edge_loops->count; i++) { + BMLoop *l_adj = BLI_buffer_at(edge_loops, BMLoop *, i); + BMFace *f_adj = l_adj->f; pbvh_bmesh_face_remove(bvh, f_adj); BM_face_kill(bvh->bm, f_adj); @@ -804,30 +776,32 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1, * really buy anything. */ deleted_faces->count = 0; BM_ITER_ELEM (f, &bm_iter, v2, BM_FACES_OF_VERT) { - BMVert *v[3]; + BMVert *v_tri[3]; BMFace *existing_face; PBVHNode *n; int ni; /* Get vertices, replace use of v2 with v1 */ - BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3); + // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v_tri, 3); + BM_face_as_array_vert_tri(f, v_tri); for (i = 0; i < 3; i++) { - if (v[i] == v2) - v[i] = v1; + if (v_tri[i] == v2) { + v_tri[i] = v1; + } } /* Check if a face using these vertices already exists. If so, * skip adding this face and mark the existing one for * deletion as well. Prevents extraneous "flaps" from being * created. */ - if (BM_face_exists(v, 3, &existing_face)) { + if (BM_face_exists(v_tri, 3, &existing_face)) { BLI_assert(existing_face); BLI_buffer_append(deleted_faces, BMFace *, existing_face); } else { n = pbvh_bmesh_node_lookup(bvh, bvh->bm_face_to_node, f); ni = n - bvh->nodes; - pbvh_bmesh_face_create(bvh, ni, v[0], v[1], v[2], f); + pbvh_bmesh_face_create(bvh, ni, v_tri[0], v_tri[1], v_tri[2], f); /* Ensure that v1 is in the new face's node */ if (!BLI_ghash_haskey(n->bm_unique_verts, v1) && @@ -842,20 +816,24 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1, /* Delete the tagged faces */ for (i = 0; i < deleted_faces->count; i++) { BMFace *f_del = BLI_buffer_at(deleted_faces, BMFace *, i); - BMVert *v[3]; + BMVert *v_tri[3]; + BMEdge *e_tri[3]; int j; - BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f_del, (void **)v, 3); + /* Get vertices and edges of face */ + BM_face_as_array_vert_tri(f_del, v_tri); + for (j = 0; j < 3; j++) + e_tri[j] = BM_edge_exists(v_tri[j], v_tri[j == 2 ? 0 : j + 1]); /* Check if any of the face's vertices are now unused, if so - remove them from the PBVH */ + * remove them from the PBVH */ for (j = 0; j < 3; j++) { - if (v[j] != v2 && BM_vert_face_count(v[j]) == 0) { - BLI_ghash_insert(deleted_verts, v[j], NULL); - pbvh_bmesh_vert_remove(bvh, v[j]); + if (v_tri[j] != v2 && BM_vert_face_count(v_tri[j]) == 1) { + BLI_ghash_insert(deleted_verts, v_tri[j], NULL); + pbvh_bmesh_vert_remove(bvh, v_tri[j]); } else { - v[j] = NULL; + v_tri[j] = NULL; } } @@ -863,18 +841,28 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1, pbvh_bmesh_face_remove(bvh, f_del); BM_face_kill(bvh->bm, f_del); + /* Check if any of the face's edges are now unused by any + * face, if so delete them */ + for (j = 0; j < 3; j++) { + if (BM_edge_face_count(e_tri[j]) == 0) + BM_edge_kill(bvh->bm, e_tri[j]); + } + /* Delete unused vertices */ for (j = 0; j < 3; j++) { - if (v[j]) { - BM_log_vert_removed(bvh->bm, bvh->bm_log, v[j]); - BM_vert_kill(bvh->bm, v[j]); + if (v_tri[j]) { + BM_log_vert_removed(bvh->bm, bvh->bm_log, v_tri[j]); + BM_vert_kill(bvh->bm, v_tri[j]); } } } - /* Move v1 to the midpoint of v1 and v2 */ - BM_log_vert_before_modified(bvh->bm, bvh->bm_log, v1); - mid_v3_v3v3(v1->co, v1->co, v2->co); + /* Move v1 to the midpoint of v1 and v2 (if v1 still exists, it + * may have been deleted above) */ + if (!BLI_ghash_haskey(deleted_verts, v1)) { + BM_log_vert_before_modified(bvh->bm, bvh->bm_log, v1); + mid_v3_v3v3(v1->co, v1->co, v2->co); + } /* Delete v2 */ BLI_assert(BM_vert_face_count(v2) == 0); @@ -884,9 +872,9 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1, } static int pbvh_bmesh_collapse_short_edges(PBVH *bvh, EdgeQueue *q, - BLI_mempool *pool, - BLI_Buffer *edge_faces, - BLI_Buffer *deleted_faces) + BLI_mempool *pool, + BLI_Buffer *edge_loops, + BLI_Buffer *deleted_faces) { float min_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len; GHash *deleted_verts; @@ -928,8 +916,8 @@ static int pbvh_bmesh_collapse_short_edges(PBVH *bvh, EdgeQueue *q, any_collapsed = TRUE; pbvh_bmesh_collapse_edge(bvh, e, v1, v2, - deleted_verts, edge_faces, - deleted_faces); + deleted_verts, edge_loops, + deleted_faces); } BLI_ghash_free(deleted_verts, NULL, NULL); @@ -962,15 +950,15 @@ int pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3], BMFace *f = BLI_ghashIterator_getKey(&gh_iter); BLI_assert(f->len == 3); - if (f->len == 3) { - BMVert *v[3]; + if (f->len == 3 && !paint_is_bmesh_face_hidden(f)) { + BMVert *v_tri[3]; - BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3); + BM_face_as_array_vert_tri(f, v_tri); hit |= ray_face_intersection(ray_start, ray_normal, - v[0]->co, - v[1]->co, - v[2]->co, - NULL, dist); + v_tri[0]->co, + v_tri[1]->co, + v_tri[2]->co, + NULL, dist); } } } @@ -1038,9 +1026,10 @@ void BKE_pbvh_build_bmesh(PBVH *bvh, BMesh *bm, int smooth_shading, /* Collapse short edges, subdivide long edges */ int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode, - const float center[3], float radius) + const float center[3], float radius) { - BLI_buffer_declare_static(BMFace *, edge_faces, BLI_BUFFER_NOP, 8); + /* 2 is enough for edge faces - manifold edge */ + BLI_buffer_declare_static(BMFace *, edge_loops, BLI_BUFFER_NOP, 2); BLI_buffer_declare_static(BMFace *, deleted_faces, BLI_BUFFER_NOP, 32); int modified = FALSE; @@ -1049,10 +1038,10 @@ int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode, if (mode & PBVH_Collapse) { EdgeQueue q; BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert) * 2, - 128, 128, 0); + 128, 128, 0); short_edge_queue_create(&q, queue_pool, bvh, center, radius); - pbvh_bmesh_collapse_short_edges(bvh, &q, queue_pool, &edge_faces, - &deleted_faces); + pbvh_bmesh_collapse_short_edges(bvh, &q, queue_pool, &edge_loops, + &deleted_faces); BLI_heap_free(q.heap, NULL); BLI_mempool_destroy(queue_pool); } @@ -1060,9 +1049,9 @@ int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode, if (mode & PBVH_Subdivide) { EdgeQueue q; BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert) * 2, - 128, 128, 0); + 128, 128, 0); long_edge_queue_create(&q, queue_pool, bvh, center, radius); - pbvh_bmesh_subdivide_long_edges(bvh, &q, queue_pool, &edge_faces); + pbvh_bmesh_subdivide_long_edges(bvh, &q, queue_pool, &edge_loops); BLI_heap_free(q.heap, NULL); BLI_mempool_destroy(queue_pool); } @@ -1077,14 +1066,27 @@ int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode, node->flag &= ~PBVH_UpdateTopology; } } - BLI_buffer_free(&edge_faces); + BLI_buffer_free(&edge_loops); BLI_buffer_free(&deleted_faces); return modified; } +BLI_INLINE void bm_face_as_array_index_tri(BMFace *f, int r_index[3]) +{ + BMLoop *l = BM_FACE_FIRST_LOOP(f); + + BLI_assert(f->len == 3); + + r_index[0] = BM_elem_index_get(l->v); l = l->next; + r_index[1] = BM_elem_index_get(l->v); l = l->next; + r_index[2] = BM_elem_index_get(l->v); +} + /* In order to perform operations on the original node coordinates - * (such as raycast), store the node's triangles and vertices.*/ + * (currently just raycast), store the node's triangles and vertices. + * + * Skips triangles that are hidden. */ void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node) { GHashIterator gh_iter; @@ -1120,15 +1122,22 @@ void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node) /* Copy the triangles */ i = 0; GHASH_ITER (gh_iter, node->bm_faces) { - BMIter bm_iter; BMFace *f = BLI_ghashIterator_getKey(&gh_iter); + + if (paint_is_bmesh_face_hidden(f)) + continue; + +#if 0 + BMIter bm_iter; BMVert *v; int j = 0; - BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) { node->bm_ortri[i][j] = BM_elem_index_get(v); j++; } +#else + bm_face_as_array_index_tri(f, node->bm_ortri[i]); +#endif i++; } node->bm_tot_ortri = i; diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 97948683e22..ef096adc7a7 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -43,6 +43,7 @@ #include "DNA_object_types.h" #include "DNA_object_force.h" #include "DNA_particle_types.h" +#include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" #include "DNA_smoke_types.h" @@ -72,6 +73,10 @@ #include "BIK_api.h" +#ifdef WITH_BULLET +# include "RBI_api.h" +#endif + /* both in intern */ #ifdef WITH_SMOKE #include "smoke_API.h" @@ -308,8 +313,9 @@ static void ptcache_particle_read(int index, void *psys_v, void **data, float cf pa->lifetime = times[2]; } - if (boid) + if (boid) { PTCACHE_DATA_TO(data, BPHYS_DATA_BOIDS, 0, &boid->data); + } /* determine velocity from previous location */ if (data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) { @@ -866,6 +872,97 @@ static int ptcache_dynamicpaint_read(PTCacheFile *pf, void *dp_v) return 1; } +/* Rigid Body functions */ +static int ptcache_rigidbody_write(int index, void *rb_v, void **data, int UNUSED(cfra)) +{ + RigidBodyWorld *rbw = rb_v; + Object *ob = NULL; + + if (rbw->objects) + ob = rbw->objects[index]; + + if (ob && ob->rigidbody_object) { + RigidBodyOb *rbo = ob->rigidbody_object; + + if (rbo->type == RBO_TYPE_ACTIVE) { +#ifdef WITH_BULLET + RB_body_get_position(rbo->physics_object, rbo->pos); + RB_body_get_orientation(rbo->physics_object, rbo->orn); +#endif + PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, rbo->pos); + PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, rbo->orn); + } + } + + return 1; +} +static void ptcache_rigidbody_read(int index, void *rb_v, void **data, float UNUSED(cfra), float *old_data) +{ + RigidBodyWorld *rbw = rb_v; + Object *ob = NULL; + + if (rbw->objects) + ob = rbw->objects[index]; + + if (ob && ob->rigidbody_object) { + RigidBodyOb *rbo = ob->rigidbody_object; + + if (rbo->type == RBO_TYPE_ACTIVE) { + + if (old_data) { + memcpy(rbo->pos, data, 3 * sizeof(float)); + memcpy(rbo->orn, data + 3, 4 * sizeof(float)); + } + else { + PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, rbo->pos); + PTCACHE_DATA_TO(data, BPHYS_DATA_ROTATION, 0, rbo->orn); + } + } + } +} +static void ptcache_rigidbody_interpolate(int index, void *rb_v, void **data, float cfra, float cfra1, float cfra2, float *old_data) +{ + RigidBodyWorld *rbw = rb_v; + Object *ob = NULL; + ParticleKey keys[4]; + float dfra; + + if (rbw->objects) + ob = rbw->objects[index]; + + if (ob && ob->rigidbody_object) { + RigidBodyOb *rbo = ob->rigidbody_object; + + if (rbo->type == RBO_TYPE_ACTIVE) { + + copy_v3_v3(keys[1].co, rbo->pos); + copy_v3_v3(keys[1].rot, rbo->orn); + + if (old_data) { + memcpy(keys[2].co, data, 3 * sizeof(float)); + memcpy(keys[2].rot, data + 3, 4 * sizeof(float)); + } + else { + BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2); + } + + dfra = cfra2 - cfra1; + + psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1); + interp_qt_qtqt(keys->rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra); + + copy_v3_v3(rbo->pos, keys->co); + copy_v3_v3(rbo->orn, keys->rot); + } + } +} +static int ptcache_rigidbody_totpoint(void *rb_v, int UNUSED(cfra)) +{ + RigidBodyWorld *rbw = rb_v; + + return rbw->numbodies; +} + /* Creating ID's */ void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb) { @@ -1071,6 +1168,42 @@ void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, Object *ob, DynamicPaintSu pid->max_step = 1; } +void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *rbw) +{ + + memset(pid, 0, sizeof(PTCacheID)); + + pid->ob= ob; + pid->calldata= rbw; + pid->type= PTCACHE_TYPE_RIGIDBODY; + pid->cache= rbw->pointcache; + pid->cache_ptr= &rbw->pointcache; + pid->ptcaches= &rbw->ptcaches; + pid->totpoint= pid->totwrite= ptcache_rigidbody_totpoint; + + pid->write_point = ptcache_rigidbody_write; + pid->read_point = ptcache_rigidbody_read; + pid->interpolate_point = ptcache_rigidbody_interpolate; + + pid->write_stream = NULL; + pid->read_stream = NULL; + + pid->write_extra_data = NULL; + pid->read_extra_data = NULL; + pid->interpolate_extra_data = NULL; + + pid->write_header = ptcache_basic_header_write; + pid->read_header = ptcache_basic_header_read; + + pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_ROTATION); + pid->info_types= 0; + + pid->stack_index = pid->cache->index; + + pid->default_step = 1; + pid->max_step = 1; +} + void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int duplis) { PTCacheID *pid; @@ -1132,6 +1265,12 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup } } } + + if (scene && ob->rigidbody_object && scene->rigidbody_world) { + pid = MEM_callocN(sizeof(PTCacheID), "PTCacheID"); + BKE_ptcache_id_from_rigidbody(pid, ob, scene->rigidbody_world); + BLI_addtail(lb, pid); + } if (scene && (duplis-- > 0) && (ob->transflag & OB_DUPLI)) { ListBase *lb_dupli_ob; @@ -2535,7 +2674,7 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) after= 0; if (mode == PTCACHE_RESET_DEPSGRAPH) { - if (!(cache->flag & PTCACHE_BAKED) && !BKE_ptcache_get_continue_physics()) { + if (!(cache->flag & PTCACHE_BAKED)) { after= 1; } @@ -2543,12 +2682,7 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) cache->flag |= PTCACHE_OUTDATED; } else if (mode == PTCACHE_RESET_BAKED) { - if (!BKE_ptcache_get_continue_physics()) { - reset= 1; - clear= 1; - } - else - cache->flag |= PTCACHE_OUTDATED; + cache->flag |= PTCACHE_OUTDATED; } else if (mode == PTCACHE_RESET_OUTDATED) { reset = 1; @@ -2645,6 +2779,14 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) } } + if (scene->rigidbody_world && (ob->rigidbody_object || ob->rigidbody_constraint)) { + if (ob->rigidbody_object) + ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_RESHAPE; + BKE_ptcache_id_from_rigidbody(&pid, ob, scene->rigidbody_world); + /* only flag as outdated, resetting should happen on start frame */ + pid.cache->flag |= PTCACHE_OUTDATED; + } + if (ob->type == OB_ARMATURE) BIK_clear_cache(ob->pose); @@ -2694,30 +2836,6 @@ void BKE_ptcache_remove(void) } } -/* Continuous Interaction */ - -static int CONTINUE_PHYSICS = 0; - -void BKE_ptcache_set_continue_physics(Main *bmain, Scene *scene, int enable) -{ - Object *ob; - - if (CONTINUE_PHYSICS != enable) { - CONTINUE_PHYSICS = enable; - - if (CONTINUE_PHYSICS == 0) { - for (ob=bmain->object.first; ob; ob=ob->id.next) - if (BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_OUTDATED)) - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); - } - } -} - -int BKE_ptcache_get_continue_physics(void) -{ - return CONTINUE_PHYSICS; -} - /* Point Cache handling */ PointCache *BKE_ptcache_add(ListBase *ptcaches) diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c new file mode 100644 index 00000000000..7cab0d7471f --- /dev/null +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -0,0 +1,1302 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joshua Leung, Sergej Reich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file rigidbody.c + * \ingroup blenkernel + * \brief Blender-side interface and methods for dealing with Rigid Body simulations + */ + +#include <stdio.h> +#include <string.h> +#include <stddef.h> +#include <float.h> +#include <math.h> +#include <limits.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_math.h" + +#ifdef WITH_BULLET +# include "RBI_api.h" +#endif + +#include "DNA_anim_types.h" +#include "DNA_group_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" +#include "DNA_object_force.h" +#include "DNA_rigidbody_types.h" +#include "DNA_scene_types.h" + +#include "BKE_animsys.h" +#include "BKE_cdderivedmesh.h" +#include "BKE_effect.h" +#include "BKE_group.h" +#include "BKE_object.h" +#include "BKE_mesh.h" +#include "BKE_pointcache.h" +#include "BKE_rigidbody.h" +#include "BKE_global.h" +#include "BKE_utildefines.h" + +#include "RNA_access.h" + +#ifdef WITH_BULLET + +/* ************************************** */ +/* Memory Management */ + +/* Freeing Methods --------------------- */ + +/* Free rigidbody world */ +void BKE_rigidbody_free_world(RigidBodyWorld *rbw) +{ + /* sanity check */ + if (!rbw) + return; + + if (rbw->physics_world) { + /* free physics references, we assume that all physics objects in will have been added to the world */ + GroupObject *go; + if (rbw->constraints) { + for (go = rbw->constraints->gobject.first; go; go = go->next) { + if (go->ob && go->ob->rigidbody_constraint) { + RigidBodyCon *rbc = go->ob->rigidbody_constraint; + + if (rbc->physics_constraint) + RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint); + } + } + } + if (rbw->group) { + for (go = rbw->group->gobject.first; go; go = go->next) { + if (go->ob && go->ob->rigidbody_object) { + RigidBodyOb *rbo = go->ob->rigidbody_object; + + if (rbo->physics_object) + RB_dworld_remove_body(rbw->physics_world, rbo->physics_object); + } + } + } + /* free dynamics world */ + RB_dworld_delete(rbw->physics_world); + } + if (rbw->objects) + free(rbw->objects); + + /* free cache */ + BKE_ptcache_free_list(&(rbw->ptcaches)); + rbw->pointcache = NULL; + + /* free effector weights */ + if (rbw->effector_weights) + MEM_freeN(rbw->effector_weights); + + /* free rigidbody world itself */ + MEM_freeN(rbw); +} + +/* Free RigidBody settings and sim instances */ +void BKE_rigidbody_free_object(Object *ob) +{ + RigidBodyOb *rbo = (ob) ? ob->rigidbody_object : NULL; + + /* sanity check */ + if (rbo == NULL) + return; + + /* free physics references */ + if (rbo->physics_object) { + RB_body_delete(rbo->physics_object); + rbo->physics_object = NULL; + } + + if (rbo->physics_shape) { + RB_shape_delete(rbo->physics_shape); + rbo->physics_shape = NULL; + } + + /* free data itself */ + MEM_freeN(rbo); + ob->rigidbody_object = NULL; +} + +/* Free RigidBody constraint and sim instance */ +void BKE_rigidbody_free_constraint(Object *ob) +{ + RigidBodyCon *rbc = (ob) ? ob->rigidbody_constraint : NULL; + + /* sanity check */ + if (rbc == NULL) + return; + + /* free physics reference */ + if (rbc->physics_constraint) { + RB_constraint_delete(rbc->physics_constraint); + rbc->physics_constraint = NULL; + } + + /* free data itself */ + MEM_freeN(rbc); + ob->rigidbody_constraint = NULL; +} + +/* Copying Methods --------------------- */ + +/* These just copy the data, clearing out references to physics objects. + * Anything that uses them MUST verify that the copied object will + * be added to relevant groups later... + */ + +RigidBodyOb *BKE_rigidbody_copy_object(Object *ob) +{ + RigidBodyOb *rboN = NULL; + + if (ob->rigidbody_object) { + /* just duplicate the whole struct first (to catch all the settings) */ + rboN = MEM_dupallocN(ob->rigidbody_object); + + /* tag object as needing to be verified */ + rboN->flag |= RBO_FLAG_NEEDS_VALIDATE; + + /* clear out all the fields which need to be revalidated later */ + rboN->physics_object = NULL; + rboN->physics_shape = NULL; + } + + /* return new copy of settings */ + return rboN; +} + +RigidBodyCon *BKE_rigidbody_copy_constraint(Object *ob) +{ + RigidBodyCon *rbcN = NULL; + + if (ob->rigidbody_constraint) { + /* just duplicate the whole struct first (to catch all the settings) */ + rbcN = MEM_dupallocN(ob->rigidbody_constraint); + + // RB_TODO be more clever about copying constrained objects + + /* tag object as needing to be verified */ + rbcN->flag |= RBC_FLAG_NEEDS_VALIDATE; + + /* clear out all the fields which need to be revalidated later */ + rbcN->physics_constraint = NULL; + } + + /* return new copy of settings */ + return rbcN; +} + +/* ************************************** */ +/* Setup Utilities - Validate Sim Instances */ + +/* create collision shape of mesh - convex hull */ +static rbCollisionShape *rigidbody_get_shape_convexhull_from_mesh(Object *ob, float margin, bool *can_embed) +{ + rbCollisionShape *shape = NULL; + Mesh *me = NULL; + + if (ob->type == OB_MESH && ob->data) { + me = ob->data; + } + else { + printf("ERROR: cannot make Convex Hull collision shape for non-Mesh object\n"); + } + + if (me && me->totvert) { + shape = RB_shape_new_convex_hull((float *)me->mvert, sizeof(MVert), me->totvert, margin, can_embed); + } + else { + printf("ERROR: no vertices to define Convex Hull collision shape with\n"); + } + + return shape; +} + +/* create collision shape of mesh - triangulated mesh + * returns NULL if creation fails. + */ +static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob) +{ + rbCollisionShape *shape = NULL; + + if (ob->type == OB_MESH) { + DerivedMesh *dm = CDDM_from_mesh(ob->data, ob); + + MVert *mvert; + MFace *mface; + int totvert; + int totface; + + /* ensure mesh validity, then grab data */ + DM_ensure_tessface(dm); + + mvert = (dm) ? dm->getVertArray(dm) : NULL; + totvert = (dm) ? dm->getNumVerts(dm) : 0; + mface = (dm) ? dm->getTessFaceArray(dm) : NULL; + totface = (dm) ? dm->getNumTessFaces(dm) : 0; + + /* sanity checking - potential case when no data will be present */ + if ((totvert == 0) || (totface == 0)) { + printf("WARNING: no geometry data converted for Mesh Collision Shape (ob = %s)\n", ob->id.name + 2); + } + else { + rbMeshData *mdata; + int i; + + /* init mesh data for collision shape */ + mdata = RB_trimesh_data_new(); + + /* loop over all faces, adding them as triangles to the collision shape + * (so for some faces, more than triangle will get added) + */ + for (i = 0; (i < totface) && (mface) && (mvert); i++, mface++) { + /* add first triangle - verts 1,2,3 */ + { + MVert *va = (IN_RANGE(mface->v1, 0, totvert)) ? (mvert + mface->v1) : (mvert); + MVert *vb = (IN_RANGE(mface->v2, 0, totvert)) ? (mvert + mface->v2) : (mvert); + MVert *vc = (IN_RANGE(mface->v3, 0, totvert)) ? (mvert + mface->v3) : (mvert); + + RB_trimesh_add_triangle(mdata, va->co, vb->co, vc->co); + } + + /* add second triangle if needed - verts 1,3,4 */ + if (mface->v4) { + MVert *va = (IN_RANGE(mface->v1, 0, totvert)) ? (mvert + mface->v1) : (mvert); + MVert *vb = (IN_RANGE(mface->v3, 0, totvert)) ? (mvert + mface->v3) : (mvert); + MVert *vc = (IN_RANGE(mface->v4, 0, totvert)) ? (mvert + mface->v4) : (mvert); + + RB_trimesh_add_triangle(mdata, va->co, vb->co, vc->co); + } + } + + /* construct collision shape + * + * These have been chosen to get better speed/accuracy tradeoffs with regards + * to limitations of each: + * - BVH-Triangle Mesh: for passive objects only. Despite having greater + * speed/accuracy, they cannot be used for moving objects. + * - GImpact Mesh: for active objects. These are slower and less stable, + * but are more flexible for general usage. + */ + if (ob->rigidbody_object->type == RBO_TYPE_PASSIVE) { + shape = RB_shape_new_trimesh(mdata); + } + else { + shape = RB_shape_new_gimpact_mesh(mdata); + } + } + + /* cleanup temp data */ + if (dm) { + dm->release(dm); + } + } + else { + printf("ERROR: cannot make Triangular Mesh collision shape for non-Mesh object\n"); + } + + return shape; +} + +/* Create new physics sim collision shape for object and store it, + * or remove the existing one first and replace... + */ +void BKE_rigidbody_validate_sim_shape(Object *ob, short rebuild) +{ + RigidBodyOb *rbo = ob->rigidbody_object; + rbCollisionShape *new_shape = NULL; + BoundBox *bb = NULL; + float size[3] = {1.0f, 1.0f, 1.0f}; + float radius = 1.0f; + float height = 1.0f; + float capsule_height; + float hull_margin = 0.0f; + bool can_embed = true; + + /* sanity check */ + if (rbo == NULL) + return; + + /* don't create a new shape if we already have one and don't want to rebuild it */ + if (rbo->physics_shape && !rebuild) + return; + + /* if automatically determining dimensions, use the Object's boundbox + * - assume that all quadrics are standing upright on local z-axis + * - assume even distribution of mass around the Object's pivot + * (i.e. Object pivot is centralised in boundbox) + */ + // XXX: all dimensions are auto-determined now... later can add stored settings for this + /* get object dimensions without scaling */ + bb = BKE_object_boundbox_get(ob); + if (bb) { + size[0] = (bb->vec[4][0] - bb->vec[0][0]); + size[1] = (bb->vec[2][1] - bb->vec[0][1]); + size[2] = (bb->vec[1][2] - bb->vec[0][2]); + } + mul_v3_fl(size, 0.5f); + + if (ELEM3(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) { + /* take radius as largest x/y dimension, and height as z-dimension */ + radius = MAX2(size[0], size[1]); + height = size[2]; + } + else if (rbo->shape == RB_SHAPE_SPHERE) { + /* take radius to the the largest dimension to try and encompass everything */ + radius = MAX3(size[0], size[1], size[2]); + } + + /* create new shape */ + switch (rbo->shape) { + case RB_SHAPE_BOX: + new_shape = RB_shape_new_box(size[0], size[1], size[2]); + break; + + case RB_SHAPE_SPHERE: + new_shape = RB_shape_new_sphere(radius); + break; + + case RB_SHAPE_CAPSULE: + capsule_height = (height - radius) * 2.0f; + new_shape = RB_shape_new_capsule(radius, (capsule_height > 0.0f) ? capsule_height : 0.0f); + break; + case RB_SHAPE_CYLINDER: + new_shape = RB_shape_new_cylinder(radius, height); + break; + case RB_SHAPE_CONE: + new_shape = RB_shape_new_cone(radius, height * 2.0f); + break; + + case RB_SHAPE_CONVEXH: + /* try to emged collision margin */ + if (!(rbo->flag & RBO_FLAG_USE_MARGIN)) + hull_margin = 0.04f; + new_shape = rigidbody_get_shape_convexhull_from_mesh(ob, hull_margin, &can_embed); + if (!(rbo->flag & RBO_FLAG_USE_MARGIN)) + rbo->margin = (can_embed) ? 0.04f : 0.0f; /* RB_TODO ideally we shouldn't directly change the margin here */ + break; + case RB_SHAPE_TRIMESH: + new_shape = rigidbody_get_shape_trimesh_from_mesh(ob); + break; + } + /* assign new collision shape if creation was successful */ + if (new_shape) { + if (rbo->physics_shape) + RB_shape_delete(rbo->physics_shape); + rbo->physics_shape = new_shape; + RB_shape_set_margin(rbo->physics_shape, RBO_GET_MARGIN(rbo)); + } +} + +/* --------------------- */ + +/* Create physics sim representation of object given RigidBody settings + * < rebuild: even if an instance already exists, replace it + */ +void BKE_rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, short rebuild) +{ + RigidBodyOb *rbo = (ob) ? ob->rigidbody_object : NULL; + float loc[3]; + float rot[4]; + + /* sanity checks: + * - object doesn't have RigidBody info already: then why is it here? + */ + if (rbo == NULL) + return; + + /* make sure collision shape exists */ + /* FIXME we shouldn't always have to rebuild collision shapes when rebuilding objects, but it's needed for constraints to update correctly */ + if (rbo->physics_shape == NULL || rebuild) + BKE_rigidbody_validate_sim_shape(ob, true); + + if (rbo->physics_object) { + if (rebuild == false) + RB_dworld_remove_body(rbw->physics_world, rbo->physics_object); + } + if (!rbo->physics_object || rebuild) { + /* remove rigid body if it already exists before creating a new one */ + if (rbo->physics_object) { + RB_body_delete(rbo->physics_object); + } + + mat4_to_loc_quat(loc, rot, ob->obmat); + + rbo->physics_object = RB_body_new(rbo->physics_shape, loc, rot); + + RB_body_set_friction(rbo->physics_object, rbo->friction); + RB_body_set_restitution(rbo->physics_object, rbo->restitution); + + RB_body_set_damping(rbo->physics_object, rbo->lin_damping, rbo->ang_damping); + RB_body_set_sleep_thresh(rbo->physics_object, rbo->lin_sleep_thresh, rbo->ang_sleep_thresh); + RB_body_set_activation_state(rbo->physics_object, rbo->flag & RBO_FLAG_USE_DEACTIVATION); + + if (rbo->type == RBO_TYPE_PASSIVE || rbo->flag & RBO_FLAG_START_DEACTIVATED) + RB_body_deactivate(rbo->physics_object); + + + RB_body_set_linear_factor(rbo->physics_object, + (ob->protectflag & OB_LOCK_LOCX) == 0, + (ob->protectflag & OB_LOCK_LOCY) == 0, + (ob->protectflag & OB_LOCK_LOCZ) == 0); + RB_body_set_angular_factor(rbo->physics_object, + (ob->protectflag & OB_LOCK_ROTX) == 0, + (ob->protectflag & OB_LOCK_ROTY) == 0, + (ob->protectflag & OB_LOCK_ROTZ) == 0); + + RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo)); + RB_body_set_kinematic_state(rbo->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED); + } + + if (rbw && rbw->physics_world) + RB_dworld_add_body(rbw->physics_world, rbo->physics_object, rbo->col_groups); +} + +/* --------------------- */ + +/* Create physics sim representation of constraint given rigid body constraint settings + * < rebuild: even if an instance already exists, replace it + */ +void BKE_rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, short rebuild) +{ + RigidBodyCon *rbc = (ob) ? ob->rigidbody_constraint : NULL; + float loc[3]; + float rot[4]; + float lin_lower; + float lin_upper; + float ang_lower; + float ang_upper; + + /* sanity checks: + * - object should have a rigid body constraint + * - rigid body constraint should have at least one constrained object + */ + if (rbc == NULL) { + return; + } + + if (ELEM4(NULL, rbc->ob1, rbc->ob1->rigidbody_object, rbc->ob2, rbc->ob2->rigidbody_object)) { + if (rbc->physics_constraint) { + RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint); + RB_constraint_delete(rbc->physics_constraint); + rbc->physics_constraint = NULL; + } + return; + } + + if (rbc->physics_constraint) { + if (rebuild == false) + RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint); + } + if (rbc->physics_constraint == NULL || rebuild) { + rbRigidBody *rb1 = rbc->ob1->rigidbody_object->physics_object; + rbRigidBody *rb2 = rbc->ob2->rigidbody_object->physics_object; + + /* remove constraint if it already exists before creating a new one */ + if (rbc->physics_constraint) { + RB_constraint_delete(rbc->physics_constraint); + rbc->physics_constraint = NULL; + } + + mat4_to_loc_quat(loc, rot, ob->obmat); + + if (rb1 && rb2) { + switch (rbc->type) { + case RBC_TYPE_POINT: + rbc->physics_constraint = RB_constraint_new_point(loc, rb1, rb2); + break; + case RBC_TYPE_FIXED: + rbc->physics_constraint = RB_constraint_new_fixed(loc, rot, rb1, rb2); + break; + case RBC_TYPE_HINGE: + rbc->physics_constraint = RB_constraint_new_hinge(loc, rot, rb1, rb2); + if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Z) { + RB_constraint_set_limits_hinge(rbc->physics_constraint, rbc->limit_ang_z_lower, rbc->limit_ang_z_upper); + } + else + RB_constraint_set_limits_hinge(rbc->physics_constraint, 0.0f, -1.0f); + break; + case RBC_TYPE_SLIDER: + rbc->physics_constraint = RB_constraint_new_slider(loc, rot, rb1, rb2); + if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X) + RB_constraint_set_limits_slider(rbc->physics_constraint, rbc->limit_lin_x_lower, rbc->limit_lin_x_upper); + else + RB_constraint_set_limits_slider(rbc->physics_constraint, 0.0f, -1.0f); + break; + case RBC_TYPE_PISTON: + rbc->physics_constraint = RB_constraint_new_piston(loc, rot, rb1, rb2); + if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X) { + lin_lower = rbc->limit_lin_x_lower; + lin_upper = rbc->limit_lin_x_upper; + } + else { + lin_lower = 0.0f; + lin_upper = -1.0f; + } + if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_X) { + ang_lower = rbc->limit_ang_x_lower; + ang_upper = rbc->limit_ang_x_upper; + } + else { + ang_lower = 0.0f; + ang_upper = -1.0f; + } + RB_constraint_set_limits_piston(rbc->physics_constraint, lin_lower, lin_upper, ang_lower, ang_upper); + break; + case RBC_TYPE_6DOF_SPRING: + rbc->physics_constraint = RB_constraint_new_6dof_spring(loc, rot, rb1, rb2); + + RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->flag & RBC_FLAG_USE_SPRING_X); + RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->spring_stiffness_x); + RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->spring_damping_x); + + RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->flag & RBC_FLAG_USE_SPRING_Y); + RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->spring_stiffness_y); + RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->spring_damping_y); + + RB_constraint_set_spring_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->flag & RBC_FLAG_USE_SPRING_Z); + RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_stiffness_z); + RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->spring_damping_z); + + RB_constraint_set_equilibrium_6dof_spring(rbc->physics_constraint); + /* fall through */ + case RBC_TYPE_6DOF: + if (rbc->type == RBC_TYPE_6DOF) /* a litte awkward but avoids duplicate code for limits */ + rbc->physics_constraint = RB_constraint_new_6dof(loc, rot, rb1, rb2); + + if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X) + RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->limit_lin_x_lower, rbc->limit_lin_x_upper); + else + RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_X, 0.0f, -1.0f); + + if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_Y) + RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->limit_lin_y_lower, rbc->limit_lin_y_upper); + else + RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Y, 0.0f, -1.0f); + + if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_Z) + RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->limit_lin_z_lower, rbc->limit_lin_z_upper); + else + RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Z, 0.0f, -1.0f); + + if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_X) + RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->limit_ang_x_lower, rbc->limit_ang_x_upper); + else + RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_X, 0.0f, -1.0f); + + if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Y) + RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->limit_ang_y_lower, rbc->limit_ang_y_upper); + else + RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Y, 0.0f, -1.0f); + + if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Z) + RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->limit_ang_z_lower, rbc->limit_ang_z_upper); + else + RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Z, 0.0f, -1.0f); + break; + } + } + + RB_constraint_set_enabled(rbc->physics_constraint, rbc->flag & RBC_FLAG_ENABLED); + + if (rbc->flag & RBC_FLAG_USE_BREAKING) + RB_constraint_set_breaking_threshold(rbc->physics_constraint, rbc->breaking_threshold); + else + RB_constraint_set_breaking_threshold(rbc->physics_constraint, FLT_MAX); + + if (rbc->flag & RBC_FLAG_OVERRIDE_SOLVER_ITERATIONS) + RB_constraint_set_solver_iterations(rbc->physics_constraint, rbc->num_solver_iterations); + else + RB_constraint_set_solver_iterations(rbc->physics_constraint, -1); + } + + if (rbw && rbw->physics_world && rbc->physics_constraint) { + RB_dworld_add_constraint(rbw->physics_world, rbc->physics_constraint, rbc->flag & RBC_FLAG_DISABLE_COLLISIONS); + } +} + +/* --------------------- */ + +/* Create physics sim world given RigidBody world settings */ +// NOTE: this does NOT update object references that the scene uses, in case those aren't ready yet! +void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, short rebuild) +{ + /* sanity checks */ + if (rbw == NULL) + return; + + /* create new sim world */ + if (rebuild || rbw->physics_world == NULL) { + if (rbw->physics_world) + RB_dworld_delete(rbw->physics_world); + rbw->physics_world = RB_dworld_new(scene->physics_settings.gravity); + } + + RB_dworld_set_solver_iterations(rbw->physics_world, rbw->num_solver_iterations); + RB_dworld_set_split_impulse(rbw->physics_world, rbw->flag & RBW_FLAG_USE_SPLIT_IMPULSE); +} + +/* ************************************** */ +/* Setup Utilities - Create Settings Blocks */ + +/* Set up RigidBody world */ +RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene) +{ + /* try to get whatever RigidBody world that might be representing this already */ + RigidBodyWorld *rbw; + + /* sanity checks + * - there must be a valid scene to add world to + * - there mustn't be a sim world using this group already + */ + if (scene == NULL) + return NULL; + + /* create a new sim world */ + rbw = MEM_callocN(sizeof(RigidBodyWorld), "RigidBodyWorld"); + + /* set default settings */ + rbw->effector_weights = BKE_add_effector_weights(NULL); + + rbw->ltime = PSFRA; + + rbw->time_scale = 1.0f; + + rbw->steps_per_second = 60; /* Bullet default (60 Hz) */ + rbw->num_solver_iterations = 10; /* 10 is bullet default */ + + rbw->pointcache = BKE_ptcache_add(&(rbw->ptcaches)); + rbw->pointcache->step = 1; + + /* return this sim world */ + return rbw; +} + +/* Add rigid body settings to the specified object */ +RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type) +{ + RigidBodyOb *rbo; + RigidBodyWorld *rbw = scene->rigidbody_world; + + /* sanity checks + * - rigidbody world must exist + * - object must exist + * - cannot add rigid body if it already exists + */ + if (ob == NULL || (ob->rigidbody_object != NULL)) + return NULL; + + /* create new settings data, and link it up */ + rbo = MEM_callocN(sizeof(RigidBodyOb), "RigidBodyOb"); + + /* set default settings */ + rbo->type = type; + + rbo->mass = 1.0f; + + rbo->friction = 0.5f; /* best when non-zero. 0.5 is Bullet default */ + rbo->restitution = 0.0f; /* best when zero. 0.0 is Bullet default */ + + rbo->margin = 0.04f; /* 0.04 (in meters) is Bullet default */ + + rbo->lin_sleep_thresh = 0.4f; /* 0.4 is half of Bullet default */ + rbo->ang_sleep_thresh = 0.5f; /* 0.5 is half of Bullet default */ + + rbo->lin_damping = 0.04f; /* 0.04 is game engine default */ + rbo->ang_damping = 0.1f; /* 0.1 is game engine default */ + + rbo->col_groups = 1; + + /* use triangle meshes for passive objects + * use convex hulls for active objects since dynamic triangle meshes are very unstable + */ + if (type == RBO_TYPE_ACTIVE) + rbo->shape = RB_SHAPE_CONVEXH; + else + rbo->shape = RB_SHAPE_TRIMESH; + + /* set initial transform */ + mat4_to_loc_quat(rbo->pos, rbo->orn, ob->obmat); + + /* flag cache as outdated */ + BKE_rigidbody_cache_reset(rbw); + + /* return this object */ + return rbo; +} + +/* Add rigid body constraint to the specified object */ +RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short type) +{ + RigidBodyCon *rbc; + RigidBodyWorld *rbw = scene->rigidbody_world; + + /* sanity checks + * - rigidbody world must exist + * - object must exist + * - cannot add constraint if it already exists + */ + if (ob == NULL || (ob->rigidbody_constraint != NULL)) + return NULL; + + /* create new settings data, and link it up */ + rbc = MEM_callocN(sizeof(RigidBodyCon), "RigidBodyCon"); + + /* set default settings */ + rbc->type = type; + + rbc->ob1 = NULL; + rbc->ob2 = NULL; + + rbc->flag |= RBC_FLAG_ENABLED; + rbc->flag |= RBC_FLAG_DISABLE_COLLISIONS; + + rbc->breaking_threshold = 10.0f; /* no good default here, just use 10 for now */ + rbc->num_solver_iterations = 10; /* 10 is Bullet default */ + + rbc->limit_lin_x_lower = -1.0f; + rbc->limit_lin_x_upper = 1.0f; + rbc->limit_lin_y_lower = -1.0f; + rbc->limit_lin_y_upper = 1.0f; + rbc->limit_lin_z_lower = -1.0f; + rbc->limit_lin_z_upper = 1.0f; + rbc->limit_ang_x_lower = -M_PI_4; + rbc->limit_ang_x_upper = M_PI_4; + rbc->limit_ang_y_lower = -M_PI_4; + rbc->limit_ang_y_upper = M_PI_4; + rbc->limit_ang_z_lower = -M_PI_4; + rbc->limit_ang_z_upper = M_PI_4; + + rbc->spring_damping_x = 0.5f; + rbc->spring_damping_y = 0.5f; + rbc->spring_damping_z = 0.5f; + rbc->spring_stiffness_x = 10.0f; + rbc->spring_stiffness_y = 10.0f; + rbc->spring_stiffness_z = 10.0f; + + /* flag cache as outdated */ + BKE_rigidbody_cache_reset(rbw); + + /* return this object */ + return rbc; +} + +/* ************************************** */ +/* Utilities API */ + +/* Get RigidBody world for the given scene, creating one if needed + * < scene: Scene to find active Rigid Body world for + */ +RigidBodyWorld *BKE_rigidbody_get_world(Scene *scene) +{ + /* sanity check */ + if (scene == NULL) + return NULL; + + return scene->rigidbody_world; +} + +void BKE_rigidbody_remove_object(Scene *scene, Object *ob) +{ + RigidBodyWorld *rbw = scene->rigidbody_world; + RigidBodyOb *rbo = ob->rigidbody_object; + RigidBodyCon *rbc; + GroupObject *go; + int i; + + if (rbw) { + /* remove from rigidbody world, free object won't do this */ + if (rbw->physics_world && rbo->physics_object) + RB_dworld_remove_body(rbw->physics_world, rbo->physics_object); + + /* remove object from array */ + if (rbw && rbw->objects) { + for (i = 0; i < rbw->numbodies; i++) { + if (rbw->objects[i] == ob) { + rbw->objects[i] = NULL; + break; + } + } + } + + /* remove object from rigid body constraints */ + if (rbw->constraints) { + for (go = rbw->constraints->gobject.first; go; go = go->next) { + Object *obt = go->ob; + if (obt) { + rbc = obt->rigidbody_constraint; + if (rbc->ob1 == ob) { + rbc->ob1 = NULL; + rbc->flag |= RBC_FLAG_NEEDS_VALIDATE; + } + if (rbc->ob2 == ob) { + rbc->ob2 = NULL; + rbc->flag |= RBC_FLAG_NEEDS_VALIDATE; + } + } + } + } + } + + /* remove object's settings */ + BKE_rigidbody_free_object(ob); + + /* flag cache as outdated */ + BKE_rigidbody_cache_reset(rbw); +} + +void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob) +{ + RigidBodyWorld *rbw = scene->rigidbody_world; + RigidBodyCon *rbc = ob->rigidbody_constraint; + + if (rbw) { + /* remove from rigidbody world, free object won't do this */ + if (rbw && rbw->physics_world && rbc->physics_constraint) + RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint); + } + /* remove object's settings */ + BKE_rigidbody_free_constraint(ob); + + /* flag cache as outdated */ + BKE_rigidbody_cache_reset(rbw); +} + + +/* ************************************** */ +/* Simulation Interface - Bullet */ + +/* Update object array and rigid body count so they're in sync with the rigid body group */ +static void rigidbody_update_ob_array(RigidBodyWorld *rbw) +{ + GroupObject *go; + int i, n; + + n = BLI_countlist(&rbw->group->gobject); + + if (rbw->numbodies != n) { + rbw->numbodies = n; + rbw->objects = realloc(rbw->objects, sizeof(Object *) * rbw->numbodies); + } + + for (go = rbw->group->gobject.first, i = 0; go; go = go->next, i++) { + Object *ob = go->ob; + rbw->objects[i] = ob; + } +} + +static void rigidbody_update_sim_world(Scene *scene, RigidBodyWorld *rbw) +{ + float adj_gravity[3]; + + /* adjust gravity to take effector weights into account */ + if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { + copy_v3_v3(adj_gravity, scene->physics_settings.gravity); + mul_v3_fl(adj_gravity, rbw->effector_weights->global_gravity * rbw->effector_weights->weight[0]); + } + else { + zero_v3(adj_gravity); + } + + /* update gravity, since this RNA setting is not part of RigidBody settings */ + RB_dworld_set_gravity(rbw->physics_world, adj_gravity); + + /* update object array in case there are changes */ + rigidbody_update_ob_array(rbw); +} + +static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *ob, RigidBodyOb *rbo) +{ + float loc[3]; + float rot[4]; + float scale[3]; + + /* only update if rigid body exists */ + if (rbo->physics_object == NULL) + return; + + mat4_decompose(loc, rot, scale, ob->obmat); + + /* update scale for all objects */ + RB_body_set_scale(rbo->physics_object, scale); + /* compensate for embedded convex hull collision margin */ + if (!(rbo->flag & RBO_FLAG_USE_MARGIN) && rbo->shape == RB_SHAPE_CONVEXH) + RB_shape_set_margin(rbo->physics_shape, RBO_GET_MARGIN(rbo) * MIN3(scale[0], scale[1], scale[2])); + + /* make transformed objects temporarily kinmatic so that they can be moved by the user during simulation */ + if ((ob->flag & SELECT && G.moving & G_TRANSFORM_OBJ) || rbo->type == RBO_TYPE_PASSIVE) { + RB_body_set_kinematic_state(rbo->physics_object, TRUE); + RB_body_set_mass(rbo->physics_object, 0.0f); + } + + /* update rigid body location and rotation for kinematic bodies */ + if (rbo->flag & RBO_FLAG_KINEMATIC || (ob->flag & SELECT && G.moving & G_TRANSFORM_OBJ)) { + RB_body_activate(rbo->physics_object); + RB_body_set_loc_rot(rbo->physics_object, loc, rot); + } + /* update influence of effectors - but don't do it on an effector */ + /* only dynamic bodies need effector update */ + else if (rbo->type == RBO_TYPE_ACTIVE && ((ob->pd == NULL) || (ob->pd->forcefield == PFIELD_NULL))) { + EffectorWeights *effector_weights = rbw->effector_weights; + EffectedPoint epoint; + ListBase *effectors; + + /* get effectors present in the group specified by effector_weights */ + effectors = pdInitEffectors(scene, ob, NULL, effector_weights); + if (effectors) { + float force[3] = {0.0f, 0.0f, 0.0f}; + float loc[3], vel[3]; + + /* create dummy 'point' which represents last known position of object as result of sim */ + // XXX: this can create some inaccuracies with sim position, but is probably better than using unsimulated vals? + RB_body_get_position(rbo->physics_object, loc); + RB_body_get_linear_velocity(rbo->physics_object, vel); + + pd_point_from_loc(scene, loc, vel, 0, &epoint); + + /* calculate net force of effectors, and apply to sim object + * - we use 'central force' since apply force requires a "relative position" which we don't have... + */ + pdDoEffectors(effectors, NULL, effector_weights, &epoint, force, NULL); + if (G.f & G_DEBUG) + printf("\tapplying force (%f,%f,%f) to '%s'\n", force[0], force[1], force[2], ob->id.name + 2); + /* activate object in case it is deactivated */ + if (!is_zero_v3(force)) + RB_body_activate(rbo->physics_object); + RB_body_apply_central_force(rbo->physics_object, force); + } + else if (G.f & G_DEBUG) + printf("\tno forces to apply to '%s'\n", ob->id.name + 2); + + /* cleanup */ + pdEndEffectors(&effectors); + } + /* NOTE: passive objects don't need to be updated since they don't move */ + + /* NOTE: no other settings need to be explicitly updated here, + * since RNA setters take care of the rest :) + */ +} + +/* Updates and validates world, bodies and shapes. + * < rebuild: rebuild entire simulation + */ +static void rigidbody_update_simulation(Scene *scene, RigidBodyWorld *rbw, int rebuild) +{ + GroupObject *go; + + /* update world */ + if (rebuild) + BKE_rigidbody_validate_sim_world(scene, rbw, true); + rigidbody_update_sim_world(scene, rbw); + + /* update objects */ + for (go = rbw->group->gobject.first; go; go = go->next) { + Object *ob = go->ob; + + if (ob && ob->type == OB_MESH) { + /* validate that we've got valid object set up here... */ + RigidBodyOb *rbo = ob->rigidbody_object; + /* update transformation matrix of the object so we don't get a frame of lag for simple animations */ + BKE_object_where_is_calc(scene, ob); + + if (rbo == NULL) { + /* Since this object is included in the sim group but doesn't have + * rigid body settings (perhaps it was added manually), add! + * - assume object to be active? That is the default for newly added settings... + */ + ob->rigidbody_object = BKE_rigidbody_create_object(scene, ob, RBO_TYPE_ACTIVE); + BKE_rigidbody_validate_sim_object(rbw, ob, true); + + rbo = ob->rigidbody_object; + } + else { + /* perform simulation data updates as tagged */ + /* refresh object... */ + if (rebuild) { + /* World has been rebuilt so rebuild object */ + BKE_rigidbody_validate_sim_object(rbw, ob, true); + } + else if (rbo->flag & RBO_FLAG_NEEDS_VALIDATE) { + BKE_rigidbody_validate_sim_object(rbw, ob, false); + } + /* refresh shape... */ + if (rbo->flag & RBO_FLAG_NEEDS_RESHAPE) { + /* mesh/shape data changed, so force shape refresh */ + BKE_rigidbody_validate_sim_shape(ob, true); + /* now tell RB sim about it */ + // XXX: we assume that this can only get applied for active/passive shapes that will be included as rigidbodies + RB_body_set_collision_shape(rbo->physics_object, rbo->physics_shape); + } + rbo->flag &= ~(RBO_FLAG_NEEDS_VALIDATE | RBO_FLAG_NEEDS_RESHAPE); + } + + /* update simulation object... */ + rigidbody_update_sim_ob(scene, rbw, ob, rbo); + } + } + /* update constraints */ + if (rbw->constraints == NULL) /* no constraints, move on */ + return; + for (go = rbw->constraints->gobject.first; go; go = go->next) { + Object *ob = go->ob; + + if (ob) { + /* validate that we've got valid object set up here... */ + RigidBodyCon *rbc = ob->rigidbody_constraint; + /* update transformation matrix of the object so we don't get a frame of lag for simple animations */ + BKE_object_where_is_calc(scene, ob); + + if (rbc == NULL) { + /* Since this object is included in the group but doesn't have + * constraint settings (perhaps it was added manually), add! + */ + ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, RBC_TYPE_FIXED); + BKE_rigidbody_validate_sim_constraint(rbw, ob, true); + + rbc = ob->rigidbody_constraint; + } + else { + /* perform simulation data updates as tagged */ + if (rebuild) { + /* World has been rebuilt so rebuild constraint */ + BKE_rigidbody_validate_sim_constraint(rbw, ob, true); + } + else if (rbc->flag & RBC_FLAG_NEEDS_VALIDATE) { + BKE_rigidbody_validate_sim_constraint(rbw, ob, false); + } + rbc->flag &= ~RBC_FLAG_NEEDS_VALIDATE; + } + } + } +} + +static void rigidbody_update_simulation_post_step(RigidBodyWorld *rbw) +{ + GroupObject *go; + + for (go = rbw->group->gobject.first; go; go = go->next) { + Object *ob = go->ob; + + if (ob) { + RigidBodyOb *rbo = ob->rigidbody_object; + /* reset kinematic state for transformed objects */ + if (ob->flag & SELECT && G.moving & G_TRANSFORM_OBJ) { + RB_body_set_kinematic_state(rbo->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED); + RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo)); + } + } + } +} + +/* Sync rigid body and object transformations */ +void BKE_rigidbody_sync_transforms(Scene *scene, Object *ob, float ctime) +{ + RigidBodyWorld *rbw = scene->rigidbody_world; + RigidBodyOb *rbo = ob->rigidbody_object; + + /* keep original transform for kinematic and passive objects */ + if (ELEM(NULL, rbw, rbo) || rbo->flag & RBO_FLAG_KINEMATIC || rbo->type == RBO_TYPE_PASSIVE) + return; + + /* use rigid body transform after cache start frame if objects is not being transformed */ + if (ctime > rbw->pointcache->startframe && !(ob->flag & SELECT && G.moving & G_TRANSFORM_OBJ)) { + float mat[4][4], size_mat[4][4], size[3]; + + /* keep original transform when the simulation is muted */ + if (rbw->flag & RBW_FLAG_MUTED) + return; + + normalize_qt(rbo->orn); // RB_TODO investigate why quaternion isn't normalized at this point + quat_to_mat4(mat, rbo->orn); + copy_v3_v3(mat[3], rbo->pos); + + mat4_to_size(size, ob->obmat); + size_to_mat4(size_mat, size); + mult_m4_m4m4(mat, mat, size_mat); + + copy_m4_m4(ob->obmat, mat); + } + /* otherwise set rigid body transform to current obmat */ + else { + mat4_to_loc_quat(rbo->pos, rbo->orn, ob->obmat); + } +} + +void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle) +{ + RigidBodyOb *rbo = ob->rigidbody_object; + + /* return rigid body and object to their initial states */ + copy_v3_v3(rbo->pos, ob->loc); + copy_v3_v3(ob->loc, loc); + + if (ob->rotmode > 0) { + eulO_to_quat(rbo->orn, ob->rot, ob->rotmode); + copy_v3_v3(ob->rot, rot); + } + else if (ob->rotmode == ROT_MODE_AXISANGLE) { + axis_angle_to_quat(rbo->orn, ob->rotAxis, ob->rotAngle); + copy_v3_v3(ob->rotAxis, rotAxis); + ob->rotAngle = rotAngle; + } + else { + copy_qt_qt(rbo->orn, ob->quat); + copy_qt_qt(ob->quat, quat); + } + if (rbo->physics_object) + RB_body_set_loc_rot(rbo->physics_object, rbo->pos, rbo->orn); + // RB_TODO update rigid body physics object's loc/rot for dynamic objects here as well (needs to be done outside bullet's update loop) +} + +void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) +{ + if (rbw) + rbw->pointcache->flag |= PTCACHE_OUTDATED; +} + +/* ------------------ */ + +/* Run RigidBody simulation for the specified physics world */ +void BKE_rigidbody_do_simulation(Scene *scene, float ctime) +{ + float timestep; + RigidBodyWorld *rbw = scene->rigidbody_world; + PointCache *cache; + PTCacheID pid; + int startframe, endframe; + + BKE_ptcache_id_from_rigidbody(&pid, NULL, rbw); + BKE_ptcache_id_time(&pid, scene, ctime, &startframe, &endframe, NULL); + cache = rbw->pointcache; + + /* flag cache as outdated if we don't have a world or number of objects in the simulation has changed */ + if (rbw->physics_world == NULL || rbw->numbodies != BLI_countlist(&rbw->group->gobject)) { + cache->flag |= PTCACHE_OUTDATED; + } + + if (ctime <= startframe) { + rbw->ltime = startframe; + /* reset and rebuild simulation if necessary */ + if (cache->flag & PTCACHE_OUTDATED) { + BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); + rigidbody_update_simulation(scene, rbw, true); + BKE_ptcache_validate(cache, (int)ctime); + cache->last_exact = 0; + cache->flag &= ~PTCACHE_REDO_NEEDED; + } + return; + } + /* rebuild world if it's outdated on second frame */ + else if (ctime == startframe + 1 && rbw->ltime == startframe && cache->flag & PTCACHE_OUTDATED) { + BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); + rigidbody_update_simulation(scene, rbw, true); + } + /* make sure we don't go out of cache frame range */ + else if (ctime > endframe) { + ctime = endframe; + } + + /* don't try to run the simulation if we don't have a world yet but allow reading baked cache */ + if (rbw->physics_world == NULL && !(cache->flag & PTCACHE_BAKED)) + return; + else if (rbw->objects == NULL) + rigidbody_update_ob_array(rbw); + + /* try to read from cache */ + // RB_TODO deal with interpolated, old and baked results + if (BKE_ptcache_read(&pid, ctime)) { + BKE_ptcache_validate(cache, (int)ctime); + rbw->ltime = ctime; + return; + } + + /* advance simulation, we can only step one frame forward */ + if (ctime == rbw->ltime + 1) { + /* write cache for first frame when on second frame */ + if (rbw->ltime == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0)) { + BKE_ptcache_write(&pid, startframe); + } + + /* update and validate simulation */ + rigidbody_update_simulation(scene, rbw, false); + + /* calculate how much time elapsed since last step in seconds */ + timestep = 1.0f / (float)FPS * (ctime - rbw->ltime) * rbw->time_scale; + /* step simulation by the requested timestep, steps per second are adjusted to take time scale into account */ + RB_dworld_step_simulation(rbw->physics_world, timestep, INT_MAX, 1.0f / (float)rbw->steps_per_second * min_ff(rbw->time_scale, 1.0f)); + + rigidbody_update_simulation_post_step(rbw); + + /* write cache for current frame */ + BKE_ptcache_validate(cache, (int)ctime); + BKE_ptcache_write(&pid, (unsigned int)ctime); + + rbw->ltime = ctime; + } +} +/* ************************************** */ + +#else /* WITH_BULLET */ + +/* stubs */ +#ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +void BKE_rigidbody_free_world(RigidBodyWorld *rbw) {} +void BKE_rigidbody_free_object(Object *ob) {} +void BKE_rigidbody_free_constraint(Object *ob) {} +struct RigidBodyOb *BKE_rigidbody_copy_object(Object *ob) { return NULL; } +struct RigidBodyCon *BKE_rigidbody_copy_constraint(Object *ob) { return NULL; } +void BKE_rigidbody_validate_sim_shape(Object *ob, short rebuild) {} +void BKE_rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, short rebuild) {} +void BKE_rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, short rebuild) {} +void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, short rebuild) {} +struct RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene) { return NULL; } +struct RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type) { return NULL; } +struct RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short type) { return NULL; } +struct RigidBodyWorld *BKE_rigidbody_get_world(Scene *scene) { return NULL; } +void BKE_rigidbody_remove_object(Scene *scene, Object *ob) {} +void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob) {} +void BKE_rigidbody_sync_transforms(Scene *scene, Object *ob, float ctime) {} +void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle) {} +void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) {} +void BKE_rigidbody_do_simulation(Scene *scene, float ctime) {} + +#ifdef __GNUC__ +# pragma GCC diagnostic pop +#endif + +#endif /* WITH_BULLET */ diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index eb56f34b99b..285646191f7 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -46,6 +46,7 @@ #include "DNA_group_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" +#include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_sequence_types.h" @@ -72,6 +73,7 @@ #include "BKE_object.h" #include "BKE_paint.h" #include "BKE_pointcache.h" +#include "BKE_rigidbody.h" #include "BKE_scene.h" #include "BKE_sequencer.h" #include "BKE_world.h" @@ -314,6 +316,9 @@ void BKE_scene_free(Scene *sce) BKE_free_animdata((ID *)sce); BKE_keyingsets_free(&sce->keyingsets); + if (sce->rigidbody_world) + BKE_rigidbody_free_world(sce->rigidbody_world); + if (sce->r.avicodecdata) { free_avicodecdata(sce->r.avicodecdata); MEM_freeN(sce->r.avicodecdata); @@ -950,6 +955,18 @@ Base *BKE_scene_base_add(Scene *sce, Object *ob) return b; } +void BKE_scene_base_unlink(Scene *sce, Base *base) +{ + /* remove rigid body constraint from world before removing object */ + if (base->object->rigidbody_constraint) + BKE_rigidbody_remove_constraint(sce, base->object); + /* remove rigid body object from world before removing object */ + if (base->object->rigidbody_object) + BKE_rigidbody_remove_object(sce, base->object); + + BLI_remlink(&sce->base, base); +} + void BKE_scene_base_deselect_all(Scene *sce) { Base *b; @@ -1205,6 +1222,12 @@ void BKE_scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay) BKE_animsys_evaluate_all_animation(bmain, sce, ctime); /*...done with recusrive funcs */ + /* run rigidbody sim */ + // XXX: this position may still change, objects not being updated correctly before simulation is run + // NOTE: current position is so that rigidbody sim affects other objects + if (BKE_scene_check_rigidbody_active(sce)) + BKE_rigidbody_do_simulation(sce, ctime); + /* clear "LIB_DOIT" flag from all materials, to prevent infinite recursion problems later * when trying to find materials with drivers that need evaluating [#32017] */ @@ -1393,3 +1416,8 @@ int BKE_scene_check_color_management_enabled(const Scene *scene) { return strcmp(scene->display_settings.display_device, "None") != 0; } + +int BKE_scene_check_rigidbody_active(const Scene *scene) +{ + return scene && scene->rigidbody_world && scene->rigidbody_world->group && !(scene->rigidbody_world->flag & RBW_FLAG_MUTED); +} diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index c64609c8e70..c0e85352217 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -1317,7 +1317,8 @@ static float check_zone(WipeZone *wipezone, int x, int y, Sequence *seq, float f switch (wipe->wipetype) { case DO_SINGLE_WIPE: - width = wipezone->width; + width = min_ii(wipezone->width, facf0 * yo); + width = min_ii(width, yo - facf0 * yo); if (angle == 0.0f) { b1 = posy; diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 2563fc268b1..be36e30808d 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -1060,7 +1060,7 @@ static void get_texture_value(Tex *texture, float tex_co[3], TexResult *texres) int result_type; /* no node textures for now */ - result_type = multitex_ext_safe(texture, tex_co, texres); + result_type = multitex_ext_safe(texture, tex_co, texres, NULL); /* if the texture gave an RGB value, we assume it didn't give a valid * intensity, since this is in the context of modifiers don't use perceptual color conversion. diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 79356d39235..e2c6df5e528 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -4108,18 +4108,6 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i softbody_reset(ob, sb, vertexCos, numVerts); } - /* continue physics special case */ - if (BKE_ptcache_get_continue_physics()) { - BKE_ptcache_invalidate(cache); - /* do simulation */ - dtime = timescale; - softbody_update_positions(ob, sb, vertexCos, numVerts); - softbody_step(scene, ob, sb, dtime); - softbody_to_object(ob, vertexCos, numVerts, 0); - sb->last_frame = framenr; - return; - } - /* still no points? go away */ if (sb->totpoint==0) { return; diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 01409a0f7e4..ce6e158b6d9 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -1017,7 +1017,11 @@ static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf) mf->flag = faceFlags[i].flag; mf->mat_nr = faceFlags[i].mat_nr; } - else mf->flag = ME_SMOOTH; + else { + mf->flag = ME_SMOOTH; +} + + mf->edcode = 0; } /* Translate GridHidden into the ME_HIDE flag for MVerts. Assumes @@ -1097,6 +1101,14 @@ void subsurf_copy_grid_paint_mask(DerivedMesh *dm, const MPoly *mpoly, } } +/* utility functon */ +BLI_INLINE void ccgDM_to_MVert(MVert *mv, const CCGKey *key, CCGElem *elem) +{ + copy_v3_v3(mv->co, CCG_elem_co(key, elem)); + normal_float_to_short_v3(mv->no, CCG_elem_no(key, elem)); + mv->flag = mv->bweight = 0; +} + static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; @@ -1107,7 +1119,7 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) int totvert, totedge, totface; int gridSize = ccgSubSurf_getGridSize(ss); int edgeSize = ccgSubSurf_getEdgeSize(ss); - int i = 0; + unsigned int i = 0; CCG_key_top_level(&key, ss); @@ -1117,24 +1129,20 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f); vd = ccgSubSurf_getFaceCenterData(f); - copy_v3_v3(mvert[i].co, CCG_elem_co(&key, vd)); - normal_float_to_short_v3(mvert[i].no, CCG_elem_no(&key, vd)); - i++; + ccgDM_to_MVert(&mvert[i++], &key, vd); for (S = 0; S < numVerts; S++) { - for (x = 1; x < gridSize - 1; x++, i++) { + for (x = 1; x < gridSize - 1; x++) { vd = ccgSubSurf_getFaceGridEdgeData(ss, f, S, x); - copy_v3_v3(mvert[i].co, CCG_elem_co(&key, vd)); - normal_float_to_short_v3(mvert[i].no, CCG_elem_no(&key, vd)); + ccgDM_to_MVert(&mvert[i++], &key, vd); } } for (S = 0; S < numVerts; S++) { for (y = 1; y < gridSize - 1; y++) { - for (x = 1; x < gridSize - 1; x++, i++) { + for (x = 1; x < gridSize - 1; x++) { vd = ccgSubSurf_getFaceGridData(ss, f, S, x, y); - copy_v3_v3(mvert[i].co, CCG_elem_co(&key, vd)); - normal_float_to_short_v3(mvert[i].no, CCG_elem_no(&key, vd)); + ccgDM_to_MVert(&mvert[i++], &key, vd); } } } @@ -1145,15 +1153,14 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) CCGEdge *e = ccgdm->edgeMap[index].edge; int x; - for (x = 1; x < edgeSize - 1; x++, i++) { - vd = ccgSubSurf_getEdgeData(ss, e, x); - copy_v3_v3(mvert[i].co, CCG_elem_co(&key, vd)); + for (x = 1; x < edgeSize - 1; x++) { /* This gives errors with -debug-fpe * the normals don't seem to be unit length. * this is most likely caused by edges with no * faces which are now zerod out, see comment in: * ccgSubSurf__calcVertNormals(), - campbell */ - normal_float_to_short_v3(mvert[i].no, CCG_elem_no(&key, vd)); + vd = ccgSubSurf_getEdgeData(ss, e, x); + ccgDM_to_MVert(&mvert[i++], &key, vd); } } @@ -1162,12 +1169,20 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) CCGVert *v = ccgdm->vertMap[index].vert; vd = ccgSubSurf_getVertData(ss, v); - copy_v3_v3(mvert[i].co, CCG_elem_co(&key, vd)); - normal_float_to_short_v3(mvert[i].no, CCG_elem_no(&key, vd)); - i++; + ccgDM_to_MVert(&mvert[i++], &key, vd); } } + +/* utility functon */ +BLI_INLINE void ccgDM_to_MEdge(MEdge *med, const int v1, const int v2, const short flag) +{ + med->v1 = v1; + med->v2 = v2; + med->crease = med->bweight = 0; + med->flag = flag; +} + static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; @@ -1176,8 +1191,9 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge) int totedge, totface; int gridSize = ccgSubSurf_getGridSize(ss); int edgeSize = ccgSubSurf_getEdgeSize(ss); - int i = 0; + unsigned int i = 0; short *edgeFlags = ccgdm->edgeFlags; + const short ed_interior_flag = ccgdm->drawInteriorEdges ? (ME_EDGEDRAW | ME_EDGERENDER) : 0; totface = ccgSubSurf_getNumFaces(ss); for (index = 0; index < totface; index++) { @@ -1186,36 +1202,22 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge) for (S = 0; S < numVerts; S++) { for (x = 0; x < gridSize - 1; x++) { - MEdge *med = &medge[i]; - - if (ccgdm->drawInteriorEdges) - med->flag = ME_EDGEDRAW | ME_EDGERENDER; - med->v1 = getFaceIndex(ss, f, S, x, 0, edgeSize, gridSize); - med->v2 = getFaceIndex(ss, f, S, x + 1, 0, edgeSize, gridSize); - i++; + ccgDM_to_MEdge(&medge[i++], + getFaceIndex(ss, f, S, x, 0, edgeSize, gridSize), + getFaceIndex(ss, f, S, x + 1, 0, edgeSize, gridSize), + ed_interior_flag); } for (x = 1; x < gridSize - 1; x++) { for (y = 0; y < gridSize - 1; y++) { - MEdge *med; - - med = &medge[i]; - if (ccgdm->drawInteriorEdges) - med->flag = ME_EDGEDRAW | ME_EDGERENDER; - med->v1 = getFaceIndex(ss, f, S, x, y, - edgeSize, gridSize); - med->v2 = getFaceIndex(ss, f, S, x, y + 1, - edgeSize, gridSize); - i++; - - med = &medge[i]; - if (ccgdm->drawInteriorEdges) - med->flag = ME_EDGEDRAW | ME_EDGERENDER; - med->v1 = getFaceIndex(ss, f, S, y, x, - edgeSize, gridSize); - med->v2 = getFaceIndex(ss, f, S, y + 1, x, - edgeSize, gridSize); - i++; + ccgDM_to_MEdge(&medge[i++], + getFaceIndex(ss, f, S, x, y, edgeSize, gridSize), + getFaceIndex(ss, f, S, x, y + 1, edgeSize, gridSize), + ed_interior_flag); + ccgDM_to_MEdge(&medge[i++], + getFaceIndex(ss, f, S, y, x, edgeSize, gridSize), + getFaceIndex(ss, f, S, y + 1, x, edgeSize, gridSize), + ed_interior_flag); } } } @@ -1224,31 +1226,32 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge) totedge = ccgSubSurf_getNumEdges(ss); for (index = 0; index < totedge; index++) { CCGEdge *e = ccgdm->edgeMap[index].edge; - unsigned int flags = 0; + short ed_flag = 0; int x; int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e)); - if (!ccgSubSurf_getEdgeNumFaces(e)) flags |= ME_LOOSEEDGE; + if (!ccgSubSurf_getEdgeNumFaces(e)) { + ed_flag |= ME_LOOSEEDGE; + } if (edgeFlags) { if (edgeIdx != -1) { #ifdef WITH_FREESTYLE - flags |= ((edgeFlags[index] & (ME_SEAM | ME_SHARP | ME_FREESTYLE_EDGE)) | ME_EDGEDRAW | ME_EDGERENDER); + ed_flag |= ((edgeFlags[index] & (ME_SEAM | ME_SHARP | ME_FREESTYLE_EDGE)) | ME_EDGEDRAW | ME_EDGERENDER); #else - flags |= ((edgeFlags[index] & (ME_SEAM | ME_SHARP)) | ME_EDGEDRAW | ME_EDGERENDER); + ed_flag |= ((edgeFlags[index] & (ME_SEAM | ME_SHARP)) | ME_EDGEDRAW | ME_EDGERENDER); #endif } } else { - flags |= ME_EDGEDRAW | ME_EDGERENDER; + ed_flag |= ME_EDGEDRAW | ME_EDGERENDER; } for (x = 0; x < edgeSize - 1; x++) { - MEdge *med = &medge[i]; - med->v1 = getEdgeIndex(ss, e, x, edgeSize); - med->v2 = getEdgeIndex(ss, e, x + 1, edgeSize); - med->flag = flags; - i++; + ccgDM_to_MEdge(&medge[i++], + getEdgeIndex(ss, e, x, edgeSize), + getEdgeIndex(ss, e, x + 1, edgeSize), + ed_flag); } } } @@ -1286,6 +1289,7 @@ static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface) edgeSize, gridSize); mf->mat_nr = mat_nr; mf->flag = flag; + mf->edcode = 0; i++; } diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index c337e339ebf..a0f611a5a7b 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -2930,6 +2930,16 @@ int text_check_identifier(const char ch) return 0; } +int text_check_identifier_nodigit(const char ch) +{ + if (ch <= '9') return 0; + if (ch < 'A') return 0; + if (ch <= 'Z' || ch == '_') return 1; + if (ch < 'a') return 0; + if (ch <= 'z') return 1; + return 0; +} + int text_check_whitespace(const char ch) { if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index fbaf6f70fbc..2e909f11eaa 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -615,6 +615,7 @@ void default_mtex(MTex *mtex) mtex->gravityfac = 1.0f; mtex->fieldfac = 1.0f; mtex->normapspace = MTEX_NSPACE_TANGENT; + mtex->brush_map_mode = MTEX_MAP_MODE_TILED; } diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 801fecc9f7c..3c5d94a21e4 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1660,7 +1660,7 @@ ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *sea /* real sampling requires libmv, but areas are supposing pattern would be * sampled if search area does exists, so we'll need to create empty * pattern area here to prevent adding NULL-checks all over just to deal - * with situation when lubmv is disabled + * with situation when libmv is disabled */ (void) frame_width; diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index cf2a165c2b2..7e51025883d 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -373,7 +373,7 @@ static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop) { char name[128]; char *param; - const AVOption *rv = NULL; + int fail = TRUE; PRINT("FFMPEG expert option: %s: ", prop->name); @@ -388,30 +388,30 @@ static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop) switch (prop->type) { case IDP_STRING: PRINT("%s.\n", IDP_String(prop)); - av_set_string3(c, prop->name, IDP_String(prop), 1, &rv); + fail = av_opt_set(c, prop->name, IDP_String(prop), 0); break; case IDP_FLOAT: PRINT("%g.\n", IDP_Float(prop)); - rv = av_set_double(c, prop->name, IDP_Float(prop)); + fail = av_opt_set_double(c, prop->name, IDP_Float(prop), 0); break; case IDP_INT: PRINT("%d.\n", IDP_Int(prop)); if (param) { if (IDP_Int(prop)) { - av_set_string3(c, name, param, 1, &rv); + fail = av_opt_set(c, name, param, 0); } else { return; } } else { - rv = av_set_int(c, prop->name, IDP_Int(prop)); + fail = av_opt_set_int(c, prop->name, IDP_Int(prop), 0); } break; } - if (!rv) { + if (fail) { PRINT("ffmpeg-option not supported: %s! Skipping.\n", prop->name); } } @@ -464,8 +464,9 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex error[0] = '\0'; - st = av_new_stream(of, 0); + st = avformat_new_stream(of, NULL); if (!st) return NULL; + st->id = 0; /* Set up the codec context */ @@ -541,16 +542,7 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex } if (codec_id == CODEC_ID_FFV1) { -#ifdef FFMPEG_FFV1_ALPHA_SUPPORTED - if (rd->im_format.planes == R_IMF_PLANES_RGBA) { - c->pix_fmt = PIX_FMT_RGB32; - } - else { - c->pix_fmt = PIX_FMT_BGR0; - } -#else c->pix_fmt = PIX_FMT_RGB32; -#endif } if (codec_id == CODEC_ID_QTRLE) { @@ -582,7 +574,7 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex set_ffmpeg_properties(rd, c, "video"); - if (avcodec_open(c, codec) < 0) { + if (avcodec_open2(c, codec, NULL) < 0) { BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size); return NULL; } @@ -619,8 +611,9 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex error[0] = '\0'; - st = av_new_stream(of, 1); + st = avformat_new_stream(of, NULL); if (!st) return NULL; + st->id = 1; c = st->codec; c->codec_id = codec_id; @@ -642,7 +635,7 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex set_ffmpeg_properties(rd, c, "audio"); - if (avcodec_open(c, codec) < 0) { + if (avcodec_open2(c, codec, NULL) < 0) { //XXX error("Couldn't initialize audio codec"); BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size); return NULL; @@ -1151,7 +1144,7 @@ IDProperty *BKE_ffmpeg_property_add(RenderData *rd, const char *type, int opt_in val.i = 0; - avcodec_get_context_defaults(&c); + avcodec_get_context_defaults3(&c, NULL); o = c.av_class->option + opt_index; parent = c.av_class->option + parent_index; @@ -1182,23 +1175,23 @@ IDProperty *BKE_ffmpeg_property_add(RenderData *rd, const char *type, int opt_in } switch (o->type) { - case FF_OPT_TYPE_INT: - case FF_OPT_TYPE_INT64: + case AV_OPT_TYPE_INT: + case AV_OPT_TYPE_INT64: val.i = FFMPEG_DEF_OPT_VAL_INT(o); idp_type = IDP_INT; break; - case FF_OPT_TYPE_DOUBLE: - case FF_OPT_TYPE_FLOAT: + case AV_OPT_TYPE_DOUBLE: + case AV_OPT_TYPE_FLOAT: val.f = FFMPEG_DEF_OPT_VAL_DOUBLE(o); idp_type = IDP_FLOAT; break; - case FF_OPT_TYPE_STRING: + case AV_OPT_TYPE_STRING: val.string.str = (char *)" "; val.string.len = 80; /* val.str = (char *)" ";*/ idp_type = IDP_STRING; break; - case FF_OPT_TYPE_CONST: + case AV_OPT_TYPE_CONST: val.i = 1; idp_type = IDP_INT; break; @@ -1238,7 +1231,7 @@ int BKE_ffmpeg_property_add_string(RenderData *rd, const char *type, const char char *param; IDProperty *prop = NULL; - avcodec_get_context_defaults(&c); + avcodec_get_context_defaults3(&c, NULL); strncpy(name_, str, sizeof(name_)); @@ -1259,10 +1252,10 @@ int BKE_ffmpeg_property_add_string(RenderData *rd, const char *type, const char if (!o) { return 0; } - if (param && o->type == FF_OPT_TYPE_CONST) { + if (param && o->type == AV_OPT_TYPE_CONST) { return 0; } - if (param && o->type != FF_OPT_TYPE_CONST && o->unit) { + if (param && o->type != AV_OPT_TYPE_CONST && o->unit) { p = my_av_find_opt(&c, param, o->unit, 0, 0); if (p) { prop = BKE_ffmpeg_property_add(rd, (char *) type, p - c.av_class->option, o - c.av_class->option); diff --git a/source/blender/blenlib/BLI_array.h b/source/blender/blenlib/BLI_array.h index 7c8816cb58a..0ba0f138c28 100644 --- a/source/blender/blenlib/BLI_array.h +++ b/source/blender/blenlib/BLI_array.h @@ -25,53 +25,19 @@ * ***** END GPL LICENSE BLOCK ***** */ +#ifndef __BLI_ARRAY_H__ +#define __BLI_ARRAY_H__ + /** \file BLI_array.h * \ingroup bli - * \brief A macro array library. - * - * this library needs to be changed to not use macros quite so heavily, - * and to be more of a complete array API. The way arrays are - * exposed to client code as normal C arrays is very useful though, imho. - * it does require some use of macros, however. - * - * anyway, it's used a bit too heavily to simply rewrite as a - * more "correct" solution without macros entirely. I originally wrote this - * to be very easy to use, without the normal pain of most array libraries. - * This was especially helpful when it came to the massive refactors necessary - * for bmesh, and really helped to speed the process up. - joeedh - * - * little array macro library. example of usage: - * - * int *arr = NULL; - * BLI_array_declare(arr); - * int i; - * - * for (i = 0; i < 10; i++) { - * BLI_array_grow_one(arr); - * arr[i] = something; - * } - * BLI_array_free(arr); - * - * arrays are buffered, using double-buffering (so on each reallocation, - * the array size is doubled). supposedly this should give good Big Oh - * behavior, though it may not be the best in practice. + * \brief A (mainly) macro array library. */ -#define BLI_array_declare(arr) \ - int _##arr##_count = 0; \ - void *_##arr##_tmp; \ - void *_##arr##_static = NULL - -/* this will use stack space, up to maxstatic array elements, before - * switching to dynamic heap allocation */ -#define BLI_array_staticdeclare(arr, maxstatic) \ - int _##arr##_count = 0; \ - void *_##arr##_tmp; \ - char _##arr##_static[maxstatic * sizeof(arr)] - +/* -------------------------------------------------------------------- */ +/* internal defines */ /* this returns the entire size of the array, including any buffering. */ -#define BLI_array_totalsize_dyn(arr) ( \ +#define _bli_array_totalsize_dynamic(arr) ( \ ((arr) == NULL) ? \ 0 : \ MEM_allocN_len(arr) / sizeof(*arr) \ @@ -80,55 +46,61 @@ #define _bli_array_totalsize_static(arr) \ (sizeof(_##arr##_static) / sizeof(*arr)) -#define BLI_array_totalsize(arr) ( \ +#define _bli_array_totalsize(arr) ( \ (size_t) \ (((void *)(arr) == (void *)_##arr##_static && (void *)(arr) != NULL) ? \ _bli_array_totalsize_static(arr) : \ - BLI_array_totalsize_dyn(arr)) \ + _bli_array_totalsize_dynamic(arr)) \ ) +/* BLI_array.c + * + * Doing the realloc in a macro isn't so simple, + * so use a function the macros can use. + */ +void _bli_array_grow_func(void **arr_p, const void *arr_static, + const int sizeof_arr_p, const int arr_count, const int num, + const char *alloc_str); + + +/* -------------------------------------------------------------------- */ +/* public defines */ + +#define BLI_array_declare(arr) \ + int _##arr##_count = 0; \ + void *_##arr##_static = NULL + +/* this will use stack space, up to maxstatic array elements, before + * switching to dynamic heap allocation */ +#define BLI_array_staticdeclare(arr, maxstatic) \ + int _##arr##_count = 0; \ + char _##arr##_static[maxstatic * sizeof(arr)] /* this returns the logical size of the array, not including buffering. */ #define BLI_array_count(arr) _##arr##_count -/* Grow the array by a fixed number of items. zeroes the new elements. +/* Grow the array by a fixed number of items. * * Allow for a large 'num' value when the new size is more then double * to allocate the exact sized array. */ - -/* grow an array by a specified number of items */ -#define BLI_array_grow_items(arr, num) ( \ +#define BLI_array_grow_items(arr, num) (( \ (((void *)(arr) == NULL) && \ ((void *)(_##arr##_static) != NULL) && \ - /* dont add _##arr##_count below because it must be zero */ \ + /* don't add _##arr##_count below because it must be zero */ \ (_bli_array_totalsize_static(arr) >= _##arr##_count + num)) ? \ /* we have an empty array and a static var big enough */ \ - ((arr = (void *)_##arr##_static), (_##arr##_count += (num))) \ + (arr = (void *)_##arr##_static) \ : \ /* use existing static array or allocate */ \ - (LIKELY(BLI_array_totalsize(arr) >= _##arr##_count + num) ? \ - (_##arr##_count += num) : /* UNLIKELY --> realloc */ \ - ( \ - (void) (_##arr##_tmp = MEM_callocN( \ - sizeof(*arr) * (num < _##arr##_count ? \ - (_##arr##_count * 2 + 2) : \ - (_##arr##_count + num)), \ - #arr " " __FILE__ ":" STRINGIFY(__LINE__) \ - ) \ - ), \ - (void) (arr && memcpy(_##arr##_tmp, \ - arr, \ - sizeof(*arr) * _##arr##_count) \ - ), \ - (void) (arr && ((void *)(arr) != (void *)_##arr##_static ? \ - (MEM_freeN(arr), arr) : \ - arr) \ - ), \ - (void) (arr = _##arr##_tmp \ - ), \ - (_##arr##_count += num) \ - )) \ -) + (LIKELY(_bli_array_totalsize(arr) >= _##arr##_count + num) ? \ + (void)0 /* do nothing */ : \ + _bli_array_grow_func((void **)&(arr), _##arr##_static, \ + sizeof(*arr), _##arr##_count, num, \ + "BLI_array." #arr), \ + (void)0) /* msvc2008 needs this */ \ + ), \ + /* increment the array count, all conditions above are accounted for. */ \ + (_##arr##_count += num)) /* returns length of array */ #define BLI_array_grow_one(arr) BLI_array_grow_items(arr, 1) @@ -167,20 +139,23 @@ /* resets the logical size of an array to zero, but doesn't * free the memory. */ #define BLI_array_empty(arr) \ - _##arr##_count = 0; (void)0 + { _##arr##_count = 0; } (void)0 /* set the count of the array, doesn't actually increase the allocated array * size. don't use this unless you know what you're doing. */ #define BLI_array_length_set(arr, count) \ - _##arr##_count = (count); (void)0 + { _##arr##_count = (count); }(void)0 /* only to prevent unused warnings */ #define BLI_array_fake_user(arr) \ (void)_##arr##_count, \ - (void)_##arr##_tmp, \ (void)_##arr##_static +/* -------------------------------------------------------------------- */ +/* other useful defines + * (unrelated to the main array macros) */ + /* not part of the 'API' but handy funcs, * same purpose as BLI_array_staticdeclare() * but use when the max size is known ahead of time */ @@ -224,3 +199,4 @@ const int _##arr##_count = (realsize) #endif +#endif /* __BLI_ARRAY_H__ */ diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h index 69d6478e0e2..94063c9a40a 100644 --- a/source/blender/blenlib/BLI_math_base.h +++ b/source/blender/blenlib/BLI_math_base.h @@ -80,6 +80,9 @@ #define MAXFLOAT ((float)3.40282347e+38) #endif +/* do not redefine functions from C99 or POSIX.1-2001 */ +#if !(defined(_ISOC99_SOURCE) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)) + #ifndef sqrtf #define sqrtf(a) ((float)sqrt(a)) #endif @@ -129,6 +132,8 @@ #define hypotf(a, b) ((float)hypot(a, b)) #endif +#endif /* C99 or POSIX.1-2001 */ + #ifdef WIN32 # ifndef FREE_WINDOWS # define isnan(n) _isnan(n) diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h index 3831ec3cbb4..145427ea529 100644 --- a/source/blender/blenlib/BLI_math_color.h +++ b/source/blender/blenlib/BLI_math_color.h @@ -102,8 +102,10 @@ void BLI_init_srgb_conversion(void); /**************** Alpha Transformations *****************/ -MINLINE void premul_to_straight_v4(float straight[4], const float premul[4]); -MINLINE void straight_to_premul_v4(float straight[4], const float premul[4]); +MINLINE void premul_to_straight_v4_v4(float straight[4], const float premul[4]); +MINLINE void premul_to_straight_v4(float color[4]); +MINLINE void straight_to_premul_v4_v4(float straight[4], const float premul[4]); +MINLINE void straight_to_premul_v4(float color[4]); MINLINE void straight_uchar_to_premul_float(float result[4], const unsigned char color[4]); MINLINE void premul_float_to_straight_uchar(unsigned char *result, const float color[4]); diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h index c12ec62ca1b..415c503146c 100644 --- a/source/blender/blenlib/BLI_math_matrix.h +++ b/source/blender/blenlib/BLI_math_matrix.h @@ -173,6 +173,8 @@ void rotate_m4(float mat[4][4], const char axis, const float angle); void mat3_to_rot_size(float rot[3][3], float size[3], float mat3[3][3]); void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], float wmat[4][4]); +void mat4_to_loc_quat(float loc[3], float quat[4], float wmat[4][4]); +void mat4_decompose(float loc[3], float quat[4], float size[3], float wmat[4][4]); void loc_eul_size_to_mat4(float R[4][4], const float loc[3], const float eul[3], const float size[3]); diff --git a/source/blender/blenlib/BLI_math_rotation.h b/source/blender/blenlib/BLI_math_rotation.h index 652925fbe49..e349a05ac23 100644 --- a/source/blender/blenlib/BLI_math_rotation.h +++ b/source/blender/blenlib/BLI_math_rotation.h @@ -186,6 +186,9 @@ float fov_to_focallength(float fov, float sensor); float angle_wrap_rad(float angle); float angle_wrap_deg(float angle); +int mat3_from_axis_conversion(int from_forward, int from_up, int to_forward, int to_up, + float r_mat[3][3]); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index f4572afec84..42a6b90f738 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -171,6 +171,10 @@ void mid_v3_v3v3(float r[3], const float a[3], const float b[3]); void mid_v2_v2v2(float r[2], const float a[2], const float b[2]); void mid_v3_v3v3v3(float v[3], const float v1[3], const float v2[3], const float v3[3]); +void flip_v4_v4v4(float v[4], const float v1[4], const float v2[4]); +void flip_v3_v3v3(float v[3], const float v1[3], const float v2[3]); +void flip_v2_v2v2(float v[2], const float v1[2], const float v2[2]); + /********************************* Comparison ********************************/ MINLINE int is_zero_v3(const float a[3]); @@ -251,6 +255,7 @@ void sub_vn_vn(float *array_tar, const float *array_src, const int size); void sub_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const int size); void msub_vn_vn(float *array_tar, const float *array_src, const float f, const int size); void msub_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, const float f, const int size); +void interp_vn_vn(float *array_tar, const float *array_src, const float t, const int size); void fill_vn_i(int *array_tar, const int size, const int val); void fill_vn_ushort(unsigned short *array_tar, const int size, const unsigned short val); void fill_vn_fl(float *array_tar, const int size, const float val); diff --git a/source/blender/blenlib/BLI_mempool.h b/source/blender/blenlib/BLI_mempool.h index 8fd2166e6f8..20ea89f3abf 100644 --- a/source/blender/blenlib/BLI_mempool.h +++ b/source/blender/blenlib/BLI_mempool.h @@ -86,6 +86,11 @@ __attribute__((warn_unused_result)) __attribute__((nonnull(1))) #endif ; +void BLI_mempool_as_array(BLI_mempool *pool, void **data) +#ifdef __GNUC__ +__attribute__((nonnull(1))) +#endif +; /** iteration stuff. note: this may easy to produce bugs with **/ /* private structure */ diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index f438e6bdec3..82ff09b5999 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -38,6 +38,7 @@ set(INC_SYS set(SRC intern/BLI_args.c + intern/BLI_array.c intern/BLI_dynstr.c intern/BLI_ghash.c intern/BLI_heap.c diff --git a/source/blender/blenlib/intern/BLI_array.c b/source/blender/blenlib/intern/BLI_array.c new file mode 100644 index 00000000000..5823b7db3f1 --- /dev/null +++ b/source/blender/blenlib/intern/BLI_array.c @@ -0,0 +1,97 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2008 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joseph Eagar, + * Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenlib/intern/BLI_array.c + * \ingroup bli + * \brief A (mainly) macro array library. + * + * This library needs to be changed to not use macros quite so heavily, + * and to be more of a complete array API. The way arrays are + * exposed to client code as normal C arrays is very useful though, imho. + * it does require some use of macros, however. + * + * anyway, it's used a bit too heavily to simply rewrite as a + * more "correct" solution without macros entirely. I originally wrote this + * to be very easy to use, without the normal pain of most array libraries. + * This was especially helpful when it came to the massive refactors necessary + * for bmesh, and really helped to speed the process up. - joeedh + * + * little array macro library. example of usage: + * + * int *arr = NULL; + * BLI_array_declare(arr); + * int i; + * + * for (i = 0; i < 10; i++) { + * BLI_array_grow_one(arr); + * arr[i] = something; + * } + * BLI_array_free(arr); + * + * arrays are buffered, using double-buffering (so on each reallocation, + * the array size is doubled). supposedly this should give good Big Oh + * behavior, though it may not be the best in practice. + */ + +#include <string.h> + +#include "BLI_array.h" + +#include "MEM_guardedalloc.h" + +/** + * This function is only to be called via macros. + * + * \note The caller must adjust \a arr_count + */ +void _bli_array_grow_func(void **arr_p, const void *arr_static, + const int sizeof_arr_p, const int arr_count, const int num, + const char *alloc_str) +{ + void *arr = *arr_p; + void *arr_tmp; + + arr_tmp = MEM_mallocN(sizeof_arr_p * + ((num < arr_count) ? + (arr_count * 2 + 2) : (arr_count + num)), alloc_str); + + if (arr) { + memcpy(arr_tmp, arr, sizeof_arr_p * arr_count); + + if (arr != arr_static) { + MEM_freeN(arr); + } + } + + *arr_p = arr_tmp; + + /* caller must do */ +#if 0 + arr_count += num; +#endif +} diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c index d98e63d88dd..0d6b8a44a1e 100644 --- a/source/blender/blenlib/intern/BLI_mempool.c +++ b/source/blender/blenlib/intern/BLI_mempool.c @@ -27,9 +27,7 @@ /** \file blender/blenlib/intern/BLI_mempool.c * \ingroup bli - */ - -/* + * * Simple, fast memory allocator for allocating many elements of the same size. */ @@ -295,33 +293,41 @@ int BLI_mempool_count(BLI_mempool *pool) void *BLI_mempool_findelem(BLI_mempool *pool, int index) { - if (!(pool->flag & BLI_MEMPOOL_ALLOW_ITER)) { - fprintf(stderr, "%s: Error! you can't iterate over this mempool!\n", __func__); - return NULL; - } - else if ((index >= 0) && (index < pool->totused)) { + BLI_assert(pool->flag & BLI_MEMPOOL_ALLOW_ITER); + + if ((index >= 0) && (index < pool->totused)) { /* we could have some faster mem chunk stepping code inline */ BLI_mempool_iter iter; void *elem; BLI_mempool_iternew(pool, &iter); for (elem = BLI_mempool_iterstep(&iter); index-- != 0; elem = BLI_mempool_iterstep(&iter)) { /* do nothing */ - }; + } return elem; } return NULL; } -void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter) +/** + * \param data array of pointers at least the size of 'pool->totused' + */ +void BLI_mempool_as_array(BLI_mempool *pool, void **data) { - if (!(pool->flag & BLI_MEMPOOL_ALLOW_ITER)) { - fprintf(stderr, "%s: Error! you can't iterate over this mempool!\n", __func__); - iter->curchunk = NULL; - iter->curindex = 0; - - return; + BLI_mempool_iter iter; + void *elem; + void **p = data; + BLI_assert(pool->flag & BLI_MEMPOOL_ALLOW_ITER); + BLI_mempool_iternew(pool, &iter); + for (elem = BLI_mempool_iterstep(&iter); elem; elem = BLI_mempool_iterstep(&iter)) { + *p++ = elem; } + BLI_assert((p - data) == pool->totused); +} + +void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter) +{ + BLI_assert(pool->flag & BLI_MEMPOOL_ALLOW_ITER); iter->pool = pool; iter->curchunk = pool->chunks.first; diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c index b8eeca50db6..c24da9fcf80 100644 --- a/source/blender/blenlib/intern/math_color_inline.c +++ b/source/blender/blenlib/intern/math_color_inline.c @@ -270,7 +270,7 @@ MINLINE int compare_rgb_uchar(const unsigned char col_a[3], const unsigned char /**************** Alpha Transformations *****************/ -MINLINE void premul_to_straight_v4(float straight[4], const float premul[4]) +MINLINE void premul_to_straight_v4_v4(float straight[4], const float premul[4]) { if (premul[3] == 0.0f || premul[3] == 1.0f) { straight[0] = premul[0]; @@ -287,7 +287,12 @@ MINLINE void premul_to_straight_v4(float straight[4], const float premul[4]) } } -MINLINE void straight_to_premul_v4(float premul[4], const float straight[4]) +MINLINE void premul_to_straight_v4(float color[4]) +{ + premul_to_straight_v4_v4(color, color); +} + +MINLINE void straight_to_premul_v4_v4(float premul[4], const float straight[4]) { float alpha = straight[3]; premul[0] = straight[0] * alpha; @@ -296,6 +301,11 @@ MINLINE void straight_to_premul_v4(float premul[4], const float straight[4]) premul[3] = straight[3]; } +MINLINE void straight_to_premul_v4(float color[4]) +{ + straight_to_premul_v4_v4(color, color); +} + MINLINE void straight_uchar_to_premul_float(float result[4], const unsigned char color[4]) { float alpha = color[3] / 255.0f; diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index 02fc5b07d6d..8f9ea917b8c 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -980,14 +980,8 @@ void normalize_m4(float mat[4][4]) void normalize_m4_m4(float rmat[4][4], float mat[4][4]) { - float len; - - len = normalize_v3_v3(rmat[0], mat[0]); - if (len != 0.0f) rmat[0][3] = mat[0][3] / len; - len = normalize_v3_v3(rmat[1], mat[1]); - if (len != 0.0f) rmat[1][3] = mat[1][3] / len; - len = normalize_v3_v3(rmat[2], mat[2]); - if (len != 0.0f) rmat[2][3] = mat[2][3] / len; + copy_m4_m4(rmat, mat); + normalize_m4(rmat); } void adjoint_m2_m2(float m1[2][2], float m[2][2]) @@ -1212,6 +1206,33 @@ void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], float wm copy_v3_v3(loc, wmat[3]); } +void mat4_to_loc_quat(float loc[3], float quat[4], float wmat[4][4]) +{ + float mat3[3][3]; + float mat3_n[3][3]; /* normalized mat3 */ + + copy_m3_m4(mat3, wmat); + normalize_m3_m3(mat3_n, mat3); + + /* so scale doesn't interfere with rotation [#24291] */ + /* note: this is a workaround for negative matrix not working for rotation conversion, FIXME */ + if (is_negative_m3(mat3)) { + negate_v3(mat3_n[0]); + negate_v3(mat3_n[1]); + negate_v3(mat3_n[2]); + } + + mat3_to_quat(quat, mat3_n); + copy_v3_v3(loc, wmat[3]); +} + +void mat4_decompose(float loc[3], float quat[4], float size[3], float wmat[4][4]) +{ + float rot[3][3]; + mat4_to_loc_rot_size(loc, rot, size, wmat); + mat3_to_quat(quat, rot); +} + void scale_m3_fl(float m[3][3], float scale) { m[0][0] = m[1][1] = m[2][2] = scale; @@ -1245,8 +1266,8 @@ void rotate_m4(float mat[4][4], const char axis, const float angle) assert(axis >= 'X' && axis <= 'Z'); - cosine = (float)cos(angle); - sine = (float)sin(angle); + cosine = cosf(angle); + sine = sinf(angle); switch (axis) { case 'X': for (col = 0; col < 4; col++) diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index 71f146e8131..b38b5a2de10 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -589,10 +589,10 @@ void interp_qt_qtqt(float result[4], const float quat1[4], const float quat2[4], } if ((1.0f - cosom) > 0.0001f) { - omega = (float)acos(cosom); - sinom = (float)sin(omega); - sc1 = (float)sin((1 - t) * omega) / sinom; - sc2 = (float)sin(t * omega) / sinom; + omega = acosf(cosom); + sinom = sinf(omega); + sc1 = sinf((1.0f - t) * omega) / sinom; + sc2 = sinf(t * omega) / sinom; } else { sc1 = 1.0f - t; @@ -1737,3 +1737,152 @@ float angle_wrap_deg(float angle) { return mod_inline(angle + 180.0f, 360.0f) - 180.0f; } + +/* axis conversion */ +static float _axis_convert_matrix[23][3][3] = { + {{-1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}}, + {{-1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, {0.0, -1.0, 0.0}}, + {{-1.0, 0.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 1.0, 0.0}}, + {{-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}}, + {{0.0, -1.0, 0.0}, {-1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}}, + {{0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}}, + {{0.0, 0.0, -1.0}, {-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}}, + {{0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, {0.0, 0.0, 1.0}}, + {{0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}}, + {{0.0, 0.0, -1.0}, {0.0, -1.0, 0.0}, {-1.0, 0.0, 0.0}}, + {{0.0, 0.0, 1.0}, {0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}}, + {{0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, {-1.0, 0.0, 0.0}}, + {{0.0, -1.0, 0.0}, {0.0, 0.0, -1.0}, {1.0, 0.0, 0.0}}, + {{0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, {1.0, 0.0, 0.0}}, + {{0.0, 0.0, -1.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0}}, + {{0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {1.0, 0.0, 0.0}}, + {{0.0, -1.0, 0.0}, {1.0, 0.0, 0.0}, {0.0, 0.0, 1.0}}, + {{0.0, 0.0, -1.0}, {1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}}, + {{0.0, 0.0, 1.0}, {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}}, + {{0.0, 1.0, 0.0}, {1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}}, + {{1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, -1.0}}, + {{1.0, 0.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}}, + {{1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, {0.0, 1.0, 0.0}}, +}; + +static int _axis_convert_lut[23][24] = { + {0x8C8, 0x4D0, 0x2E0, 0xAE8, 0x701, 0x511, 0x119, 0xB29, 0x682, 0x88A, + 0x09A, 0x2A2, 0x80B, 0x413, 0x223, 0xA2B, 0x644, 0x454, 0x05C, 0xA6C, + 0x745, 0x94D, 0x15D, 0x365}, + {0xAC8, 0x8D0, 0x4E0, 0x2E8, 0x741, 0x951, 0x159, 0x369, 0x702, 0xB0A, + 0x11A, 0x522, 0xA0B, 0x813, 0x423, 0x22B, 0x684, 0x894, 0x09C, 0x2AC, + 0x645, 0xA4D, 0x05D, 0x465}, + {0x4C8, 0x2D0, 0xAE0, 0x8E8, 0x681, 0x291, 0x099, 0x8A9, 0x642, 0x44A, + 0x05A, 0xA62, 0x40B, 0x213, 0xA23, 0x82B, 0x744, 0x354, 0x15C, 0x96C, + 0x705, 0x50D, 0x11D, 0xB25}, + {0x2C8, 0xAD0, 0x8E0, 0x4E8, 0x641, 0xA51, 0x059, 0x469, 0x742, 0x34A, + 0x15A, 0x962, 0x20B, 0xA13, 0x823, 0x42B, 0x704, 0xB14, 0x11C, 0x52C, + 0x685, 0x28D, 0x09D, 0x8A5}, + {0x708, 0xB10, 0x120, 0x528, 0x8C1, 0xAD1, 0x2D9, 0x4E9, 0x942, 0x74A, + 0x35A, 0x162, 0x64B, 0xA53, 0x063, 0x46B, 0x804, 0xA14, 0x21C, 0x42C, + 0x885, 0x68D, 0x29D, 0x0A5}, + {0xB08, 0x110, 0x520, 0x728, 0x941, 0x151, 0x359, 0x769, 0x802, 0xA0A, + 0x21A, 0x422, 0xA4B, 0x053, 0x463, 0x66B, 0x884, 0x094, 0x29C, 0x6AC, + 0x8C5, 0xACD, 0x2DD, 0x4E5}, + {0x508, 0x710, 0xB20, 0x128, 0x881, 0x691, 0x299, 0x0A9, 0x8C2, 0x4CA, + 0x2DA, 0xAE2, 0x44B, 0x653, 0xA63, 0x06B, 0x944, 0x754, 0x35C, 0x16C, + 0x805, 0x40D, 0x21D, 0xA25}, + {0x108, 0x510, 0x720, 0xB28, 0x801, 0x411, 0x219, 0xA29, 0x882, 0x08A, + 0x29A, 0x6A2, 0x04B, 0x453, 0x663, 0xA6B, 0x8C4, 0x4D4, 0x2DC, 0xAEC, + 0x945, 0x14D, 0x35D, 0x765}, + {0x748, 0x350, 0x160, 0x968, 0xAC1, 0x2D1, 0x4D9, 0x8E9, 0xA42, 0x64A, + 0x45A, 0x062, 0x68B, 0x293, 0x0A3, 0x8AB, 0xA04, 0x214, 0x41C, 0x82C, + 0xB05, 0x70D, 0x51D, 0x125}, + {0x948, 0x750, 0x360, 0x168, 0xB01, 0x711, 0x519, 0x129, 0xAC2, 0x8CA, + 0x4DA, 0x2E2, 0x88B, 0x693, 0x2A3, 0x0AB, 0xA44, 0x654, 0x45C, 0x06C, + 0xA05, 0x80D, 0x41D, 0x225}, + {0x348, 0x150, 0x960, 0x768, 0xA41, 0x051, 0x459, 0x669, 0xA02, 0x20A, + 0x41A, 0x822, 0x28B, 0x093, 0x8A3, 0x6AB, 0xB04, 0x114, 0x51C, 0x72C, + 0xAC5, 0x2CD, 0x4DD, 0x8E5}, + {0x148, 0x950, 0x760, 0x368, 0xA01, 0x811, 0x419, 0x229, 0xB02, 0x10A, + 0x51A, 0x722, 0x08B, 0x893, 0x6A3, 0x2AB, 0xAC4, 0x8D4, 0x4DC, 0x2EC, + 0xA45, 0x04D, 0x45D, 0x665}, + {0x688, 0x890, 0x0A0, 0x2A8, 0x4C1, 0x8D1, 0xAD9, 0x2E9, 0x502, 0x70A, + 0xB1A, 0x122, 0x74B, 0x953, 0x163, 0x36B, 0x404, 0x814, 0xA1C, 0x22C, + 0x445, 0x64D, 0xA5D, 0x065}, + {0x888, 0x090, 0x2A0, 0x6A8, 0x501, 0x111, 0xB19, 0x729, 0x402, 0x80A, + 0xA1A, 0x222, 0x94B, 0x153, 0x363, 0x76B, 0x444, 0x054, 0xA5C, 0x66C, + 0x4C5, 0x8CD, 0xADD, 0x2E5}, + {0x288, 0x690, 0x8A0, 0x0A8, 0x441, 0x651, 0xA59, 0x069, 0x4C2, 0x2CA, + 0xADA, 0x8E2, 0x34B, 0x753, 0x963, 0x16B, 0x504, 0x714, 0xB1C, 0x12C, + 0x405, 0x20D, 0xA1D, 0x825}, + {0x088, 0x290, 0x6A0, 0x8A8, 0x401, 0x211, 0xA19, 0x829, 0x442, 0x04A, + 0xA5A, 0x662, 0x14B, 0x353, 0x763, 0x96B, 0x4C4, 0x2D4, 0xADC, 0x8EC, + 0x505, 0x10D, 0xB1D, 0x725}, + {0x648, 0x450, 0x060, 0xA68, 0x2C1, 0x4D1, 0x8D9, 0xAE9, 0x282, 0x68A, + 0x89A, 0x0A2, 0x70B, 0x513, 0x123, 0xB2B, 0x204, 0x414, 0x81C, 0xA2C, + 0x345, 0x74D, 0x95D, 0x165}, + {0xA48, 0x650, 0x460, 0x068, 0x341, 0x751, 0x959, 0x169, 0x2C2, 0xACA, + 0x8DA, 0x4E2, 0xB0B, 0x713, 0x523, 0x12B, 0x284, 0x694, 0x89C, 0x0AC, + 0x205, 0xA0D, 0x81D, 0x425}, + {0x448, 0x050, 0xA60, 0x668, 0x281, 0x091, 0x899, 0x6A9, 0x202, 0x40A, + 0x81A, 0xA22, 0x50B, 0x113, 0xB23, 0x72B, 0x344, 0x154, 0x95C, 0x76C, + 0x2C5, 0x4CD, 0x8DD, 0xAE5}, + {0x048, 0xA50, 0x660, 0x468, 0x201, 0xA11, 0x819, 0x429, 0x342, 0x14A, + 0x95A, 0x762, 0x10B, 0xB13, 0x723, 0x52B, 0x2C4, 0xAD4, 0x8DC, 0x4EC, + 0x285, 0x08D, 0x89D, 0x6A5}, + {0x808, 0xA10, 0x220, 0x428, 0x101, 0xB11, 0x719, 0x529, 0x142, 0x94A, + 0x75A, 0x362, 0x8CB, 0xAD3, 0x2E3, 0x4EB, 0x044, 0xA54, 0x65C, 0x46C, + 0x085, 0x88D, 0x69D, 0x2A5}, + {0xA08, 0x210, 0x420, 0x828, 0x141, 0x351, 0x759, 0x969, 0x042, 0xA4A, + 0x65A, 0x462, 0xACB, 0x2D3, 0x4E3, 0x8EB, 0x084, 0x294, 0x69C, 0x8AC, + 0x105, 0xB0D, 0x71D, 0x525}, + {0x408, 0x810, 0xA20, 0x228, 0x081, 0x891, 0x699, 0x2A9, 0x102, 0x50A, + 0x71A, 0xB22, 0x4CB, 0x8D3, 0xAE3, 0x2EB, 0x144, 0x954, 0x75C, 0x36C, + 0x045, 0x44D, 0x65D, 0xA65}, + }; + +// _axis_convert_num = {'X': 0, 'Y': 1, 'Z': 2, '-X': 3, '-Y': 4, '-Z': 5} + +MINLINE int _axis_signed(const int axis) +{ + return (axis < 3) ? axis : axis - 3; +} + +/* + * Each argument us an axis in ['X', 'Y', 'Z', '-X', '-Y', '-Z'] + * where the first 2 are a source and the second 2 are the target. + */ +int mat3_from_axis_conversion(int from_forward, int from_up, int to_forward, int to_up, + float r_mat[3][3]) +{ + // from functools import reduce + int value; + int i; + + if (from_forward == to_forward && from_up == to_up) { + unit_m3(r_mat); + return false; + } + + if ((_axis_signed(from_forward) == _axis_signed(from_up)) || + (_axis_signed(to_forward) == _axis_signed(to_up))) + { + /* we could assert here! */ + unit_m3(r_mat); + return false; + } + + value = ((from_forward << (0 * 3)) | + (from_up << (1 * 3)) | + (to_forward << (2 * 3)) | + (to_up << (3 * 3))); + + for (i = 0; i < (sizeof(_axis_convert_matrix) / sizeof(*_axis_convert_matrix)); i++) { + int j; + for (j = 0; j < sizeof(*_axis_convert_lut) / sizeof(*_axis_convert_lut[0]); j++) { + if (_axis_convert_lut[i][j] == value) { + copy_m3_m3(r_mat, _axis_convert_matrix[i]); + return true; + } + } + + } +// BLI_assert(0); + return false; +} diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c index 812e2b3e63d..490ed2a99fb 100644 --- a/source/blender/blenlib/intern/math_vector.c +++ b/source/blender/blenlib/intern/math_vector.c @@ -122,6 +122,32 @@ void mid_v3_v3v3v3(float v[3], const float v1[3], const float v2[3], const float v[2] = (v1[2] + v2[2] + v3[2]) / 3.0f; } +/** + * Equivalent to: + * interp_v3_v3v3(v, v1, v2, -1.0f); + */ + +void flip_v4_v4v4(float v[4], const float v1[4], const float v2[4]) +{ + v[0] = v1[0] + (v1[0] - v2[0]); + v[1] = v1[1] + (v1[1] - v2[1]); + v[2] = v1[2] + (v1[2] - v2[2]); + v[3] = v1[3] + (v1[3] - v2[3]); +} + +void flip_v3_v3v3(float v[3], const float v1[3], const float v2[3]) +{ + v[0] = v1[0] + (v1[0] - v2[0]); + v[1] = v1[1] + (v1[1] - v2[1]); + v[2] = v1[2] + (v1[2] - v2[2]); +} + +void flip_v2_v2v2(float v[2], const float v1[2], const float v2[2]) +{ + v[0] = v1[0] + (v1[0] - v2[0]); + v[1] = v1[1] + (v1[1] - v2[1]); +} + /********************************** Angles ***********************************/ /* Return the angle in radians between vecs 1-2 and 2-3 in radians @@ -685,6 +711,19 @@ void msub_vn_vnvn(float *array_tar, const float *array_src_a, const float *array } } +void interp_vn_vn(float *array_tar, const float *array_src, const float t, const int size) +{ + const float s = 1.0f - t; + float *tar = array_tar + (size - 1); + const float *src = array_src + (size - 1); + int i = size; + while (i--) { + *(tar) = (s * *(tar)) + (t * *(src)); + tar--; + src--; + } +} + void fill_vn_i(int *array_tar, const int size, const int val) { int *tar = array_tar + (size - 1); diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c index f37e1e03f39..c159f707b98 100644 --- a/source/blender/blenlib/intern/noise.c +++ b/source/blender/blenlib/intern/noise.c @@ -1460,7 +1460,8 @@ float BLI_gNoise(float noisesize, float x, float y, float z, int hard, int noise noisefunc = cellNoiseU; break; case 0: - default: { + default: + { noisefunc = orgBlenderNoise; /* add one to make return value same as BLI_hnoise */ x += 1; @@ -1592,7 +1593,8 @@ float mg_fBm(float x, float y, float z, float H, float lacunarity, float octaves noisefunc = cellNoise; break; case 0: - default: { + default: + { noisefunc = orgBlenderNoiseS; } } @@ -1662,7 +1664,8 @@ float mg_MultiFractal(float x, float y, float z, float H, float lacunarity, floa noisefunc = cellNoise; break; case 0: - default: { + default: + { noisefunc = orgBlenderNoiseS; } } @@ -1728,7 +1731,8 @@ float mg_HeteroTerrain(float x, float y, float z, float H, float lacunarity, flo noisefunc = cellNoise; break; case 0: - default: { + default: + { noisefunc = orgBlenderNoiseS; } } @@ -1801,7 +1805,8 @@ float mg_HybridMultiFractal(float x, float y, float z, float H, float lacunarity noisefunc = cellNoise; break; case 0: - default: { + default: + { noisefunc = orgBlenderNoiseS; } } @@ -1876,7 +1881,8 @@ float mg_RidgedMultiFractal(float x, float y, float z, float H, float lacunarity noisefunc = cellNoise; break; case 0: - default: { + default: + { noisefunc = orgBlenderNoiseS; } } @@ -1941,7 +1947,8 @@ float mg_VLNoise(float x, float y, float z, float distortion, int nbas1, int nba noisefunc1 = cellNoise; break; case 0: - default: { + default: + { noisefunc1 = orgBlenderNoiseS; } } @@ -1975,7 +1982,8 @@ float mg_VLNoise(float x, float y, float z, float distortion, int nbas1, int nba noisefunc2 = cellNoise; break; case 0: - default: { + default: + { noisefunc2 = orgBlenderNoiseS; } } diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index 146e1d531f1..686484ef1db 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -729,6 +729,9 @@ void BLI_thread_queue_wait_finish(ThreadQueue *queue) void BLI_begin_threaded_malloc(void) { + /* Used for debug only */ + /* BLI_assert(thread_levels >= 0); */ + if (thread_levels == 0) { MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread); } @@ -737,6 +740,9 @@ void BLI_begin_threaded_malloc(void) void BLI_end_threaded_malloc(void) { + /* Used for debug only */ + /* BLI_assert(thread_levels >= 0); */ + thread_levels--; if (thread_levels == 0) MEM_set_lock_callback(NULL, NULL); diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c index b2d37e36004..5111baa06c1 100644 --- a/source/blender/blenloader/intern/readblenentry.c +++ b/source/blender/blenloader/intern/readblenentry.c @@ -311,8 +311,7 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFil /* makes lookup of existing video clips in old main */ blo_make_movieclip_pointer_map(fd, oldmain); - /* makes lookup of existing video clips in old main */ - blo_make_packed_pointer_map(fd, oldmain); + /* removed packed data from this trick - it's internal data that needs saves */ bfd = blo_read_file_internal(fd, filename); @@ -321,10 +320,7 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFil /* ensures relinked movie clips are not freed */ blo_end_movieclip_pointer_map(fd, oldmain); - - /* ensures relinked packed data is not freed */ - blo_end_packed_pointer_map(fd, oldmain); - + /* move libraries from old main to new main */ if (bfd && mainlist.first != mainlist.last) { diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index df68f711843..fdf23458c76 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -84,6 +84,7 @@ #include "DNA_packedFile_types.h" #include "DNA_particle_types.h" #include "DNA_property_types.h" +#include "DNA_rigidbody_types.h" #include "DNA_text_types.h" #include "DNA_view3d_types.h" #include "DNA_screen_types.h" @@ -213,20 +214,6 @@ * - initialize FileGlobal and copy pointers to Global */ -/* also occurs in library.c */ -/* GS reads the memory pointed at in a specific ordering. There are, - * however two definitions for it. I have jotted them down here, both, - * but I think the first one is actually used. The thing is that - * big-endian systems might read this the wrong way round. OTOH, we - * constructed the IDs that are read out with this macro explicitly as - * well. I expect we'll sort it out soon... */ - -/* from blendef: */ -#define GS(a) (*((short *)(a))) - -/* from misc_util: flip the bytes from x */ -/* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */ - /***/ typedef struct OldNew { @@ -1442,6 +1429,8 @@ void blo_end_movieclip_pointer_map(FileData *fd, Main *oldmain) } } +/* XXX disabled this feature - packed files also belong in temp saves and quit.blend, to make restore work */ + static void insert_packedmap(FileData *fd, PackedFile *pf) { oldnewmap_insert(fd->packedmap, pf, pf, 0); @@ -1865,6 +1854,7 @@ static PreviewImage *direct_link_preview_image(FileData *fd, PreviewImage *old_p if (prv->rect[i]) { prv->rect[i] = newdataadr(fd, prv->rect[i]); } + prv->gputexture[i] = NULL; } } @@ -2726,14 +2716,15 @@ static void lib_link_pose(FileData *fd, Object *ob, bPose *pose) { bPoseChannel *pchan; bArmature *arm = ob->data; - int rebuild; + int rebuild = 0; if (!pose || !arm) return; - - /* always rebuild to match proxy or lib changes */ - rebuild = ob->proxy || (ob->id.lib==NULL && arm->id.lib); + /* always rebuild to match proxy or lib changes, but on Undo */ + if (fd->memfile == NULL) + if (ob->proxy || (ob->id.lib==NULL && arm->id.lib)) + rebuild = 1; if (ob->proxy) { /* sync proxy layer */ @@ -4178,8 +4169,6 @@ static void lib_link_object(FileData *fd, Main *main) else { /* this triggers object_update to always use a copy */ ob->proxy->proxy_from = ob; - /* force proxy updates after load/undo, a bit weak */ - ob->recalc = ob->proxy->recalc = (OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); } } ob->proxy_group = newlibadr(fd, ob->id.lib, ob->proxy_group); @@ -4377,6 +4366,11 @@ static void lib_link_object(FileData *fd, Main *main) lib_link_particlesystems(fd, ob, &ob->id, &ob->particlesystem); lib_link_modifiers(fd, ob); + + if (ob->rigidbody_constraint) { + ob->rigidbody_constraint->ob1 = newlibadr(fd, ob->id.lib, ob->rigidbody_constraint->ob1); + ob->rigidbody_constraint->ob2 = newlibadr(fd, ob->id.lib, ob->rigidbody_constraint->ob2); + } } } @@ -4800,6 +4794,20 @@ static void direct_link_object(FileData *fd, Object *ob) } ob->bsoft = newdataadr(fd, ob->bsoft); ob->fluidsimSettings= newdataadr(fd, ob->fluidsimSettings); /* NT */ + + ob->rigidbody_object = newdataadr(fd, ob->rigidbody_object); + if (ob->rigidbody_object) { + RigidBodyOb *rbo = ob->rigidbody_object; + + /* must nullify the references to physics sim objects, since they no-longer exist + * (and will need to be recalculated) + */ + rbo->physics_object = NULL; + rbo->physics_shape = NULL; + } + ob->rigidbody_constraint = newdataadr(fd, ob->rigidbody_constraint); + if (ob->rigidbody_constraint) + ob->rigidbody_constraint->physics_constraint = NULL; link_list(fd, &ob->particlesystem); direct_link_particlesystems(fd, &ob->particlesystem); @@ -5018,6 +5026,18 @@ static void lib_link_scene(FileData *fd, Main *main) BKE_sequencer_update_muting(sce->ed); BKE_sequencer_update_sound_bounds_all(sce); + + /* rigidbody world relies on it's linked groups */ + if (sce->rigidbody_world) { + RigidBodyWorld *rbw = sce->rigidbody_world; + if (rbw->group) + rbw->group = newlibadr(fd, sce->id.lib, rbw->group); + if (rbw->constraints) + rbw->constraints = newlibadr(fd, sce->id.lib, rbw->constraints); + if (rbw->effector_weights) + rbw->effector_weights->group = newlibadr(fd, sce->id.lib, rbw->effector_weights->group); + } + if (sce->nodetree) { lib_link_ntree(fd, &sce->id, sce->nodetree); composite_patch(sce->nodetree, sce); @@ -5104,6 +5124,7 @@ static void direct_link_scene(FileData *fd, Scene *sce) Editing *ed; Sequence *seq; MetaStack *ms; + RigidBodyWorld *rbw; sce->theDag = NULL; sce->dagisvalid = 0; @@ -5303,6 +5324,28 @@ static void direct_link_scene(FileData *fd, Scene *sce) } direct_link_view_settings(fd, &sce->view_settings); + + sce->rigidbody_world = newdataadr(fd, sce->rigidbody_world); + rbw = sce->rigidbody_world; + if (rbw) { + /* must nullify the reference to physics sim object, since it no-longer exist + * (and will need to be recalculated) + */ + rbw->physics_world = NULL; + rbw->objects = NULL; + rbw->numbodies = 0; + + /* set effector weights */ + rbw->effector_weights = newdataadr(fd, rbw->effector_weights); + if (!rbw->effector_weights) + rbw->effector_weights = BKE_add_effector_weights(NULL); + + /* link cache */ + direct_link_pointcache_list(fd, &rbw->ptcaches, &rbw->pointcache, FALSE); + /* make sure simulation starts from the beginning after loading file */ + if (rbw->pointcache) + rbw->ltime = rbw->pointcache->startframe; + } } /* ************ READ WM ***************** */ @@ -5570,7 +5613,14 @@ static void lib_link_screen(FileData *fd, Main *main) } } -/* Only for undo files, or to restore a screen after reading without UI... */ +/** + * Only for undo files, or to restore a screen after reading without UI... + * + * user + * - 0: no usercount change + * - 1: ensure a user + * - 2: ensure a real user (even if a fake one is set) + */ static void *restore_pointer_by_name(Main *mainp, ID *id, int user) { if (id) { @@ -6029,6 +6079,7 @@ static void direct_link_screen(FileData *fd, bScreen *sc) v3d->afterdraw_xray.first = v3d->afterdraw_xray.last = NULL; v3d->afterdraw_xraytransp.first = v3d->afterdraw_xraytransp.last = NULL; v3d->properties_storage = NULL; + v3d->defmaterial = NULL; /* render can be quite heavy, set to wire on load */ if (v3d->drawtype == OB_RENDER) @@ -8863,6 +8914,15 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } + if (!MAIN_VERSION_ATLEAST(main, 265, 9)) { + Brush *br; + for (br = main->brush.first; br; br = br->id.next) { + if (br->ob_mode & OB_MODE_TEXTURE_PAINT) { + br->mtex.brush_map_mode = MTEX_MAP_MODE_TILED; + } + } + } + // if (main->versionfile < 265 || (main->versionfile == 265 && main->subversionfile < 7)) { #ifdef WITH_FREESTYLE @@ -9882,7 +9942,12 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob) if (ob->pd && ob->pd->tex) expand_doit(fd, mainvar, ob->pd->tex); - + + if (ob->rigidbody_constraint) { + expand_doit(fd, mainvar, ob->rigidbody_constraint->ob1); + expand_doit(fd, mainvar, ob->rigidbody_constraint->ob2); + } + } static void expand_scene(FileData *fd, Main *mainvar, Scene *sce) @@ -9940,6 +10005,11 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce) } SEQ_END } + + if (sce->rigidbody_world) { + expand_doit(fd, mainvar, sce->rigidbody_world->group); + expand_doit(fd, mainvar, sce->rigidbody_world->constraints); + } #ifdef DURIAN_CAMERA_SWITCH { @@ -10053,7 +10123,7 @@ void BLO_expand_main(void *fdhandle, Main *mainvar) a = set_listbasepointers(mainvar, lbarray); while (a--) { - id= lbarray[a]->first; + id = lbarray[a]->first; while (id) { if (id->flag & LIB_NEED_EXPAND) { switch (GS(id->name)) { @@ -10201,7 +10271,7 @@ static void give_base_to_objects(Main *mainvar, Scene *sce, Library *lib, const if (do_it) { base = MEM_callocN(sizeof(Base), "add_ext_base"); - BLI_addtail(&(sce->base), base); + BLI_addtail(&sce->base, base); base->lay = ob->lay; base->object = ob; base->flag = ob->flag; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 63d8c9b0e0e..475d96fd709 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -121,6 +121,7 @@ #include "DNA_packedFile_types.h" #include "DNA_particle_types.h" #include "DNA_property_types.h" +#include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" #include "DNA_sdna_types.h" #include "DNA_sequence_types.h" @@ -1490,6 +1491,14 @@ static void write_objects(WriteData *wd, ListBase *idbase) } writestruct(wd, DATA, "BulletSoftBody", 1, ob->bsoft); + if (ob->rigidbody_object) { + // TODO: if any extra data is added to handle duplis, will need separate function then + writestruct(wd, DATA, "RigidBodyOb", 1, ob->rigidbody_object); + } + if (ob->rigidbody_constraint) { + writestruct(wd, DATA, "RigidBodyCon", 1, ob->rigidbody_constraint); + } + write_particlesystems(wd, &ob->particlesystem); write_modifiers(wd, &ob->modifiers); } @@ -1515,7 +1524,7 @@ static void write_vfonts(WriteData *wd, ListBase *idbase) /* direct data */ - if (vf->packedfile && !wd->current) { + if (vf->packedfile) { pf = vf->packedfile; writestruct(wd, DATA, "PackedFile", 1, pf); writedata(wd, DATA, pf->size, pf->data); @@ -1965,7 +1974,7 @@ static void write_images(WriteData *wd, ListBase *idbase) writestruct(wd, ID_IM, "Image", 1, ima); if (ima->id.properties) IDP_WriteProperty(ima->id.properties, wd); - if (ima->packedfile && !wd->current) { + if (ima->packedfile) { pf = ima->packedfile; writestruct(wd, DATA, "PackedFile", 1, pf); writedata(wd, DATA, pf->size, pf->data); @@ -2316,7 +2325,14 @@ static void write_scenes(WriteData *wd, ListBase *scebase) } write_view_settings(wd, &sce->view_settings); - + + /* writing RigidBodyWorld data to the blend file */ + if (sce->rigidbody_world) { + writestruct(wd, DATA, "RigidBodyWorld", 1, sce->rigidbody_world); + writestruct(wd, DATA, "EffectorWeights", 1, sce->rigidbody_world->effector_weights); + write_pointcaches(wd, &(sce->rigidbody_world->ptcaches)); + } + sce= sce->id.next; } /* flush helps the compression for undo-save */ @@ -2574,14 +2590,18 @@ static void write_libraries(WriteData *wd, Main *main) } } + /* to be able to restore quit.blend and temp saves, the packed blend has to be in undo buffers... */ + /* XXX needs rethink, just like save UI in undo files now - would be nice to append things only for the] + quit.blend and temp saves */ if (foundone) { writestruct(wd, ID_LI, "Library", 1, main->curlib); - if (main->curlib->packedfile && !wd->current) { + if (main->curlib->packedfile) { PackedFile *pf = main->curlib->packedfile; writestruct(wd, DATA, "PackedFile", 1, pf); writedata(wd, DATA, pf->size, pf->data); - printf("write packed .blend: %s\n", main->curlib->name); + if (wd->current == NULL) + printf("write packed .blend: %s\n", main->curlib->name); } while (a--) { @@ -2712,7 +2732,7 @@ static void write_sounds(WriteData *wd, ListBase *idbase) writestruct(wd, ID_SO, "bSound", 1, sound); if (sound->id.properties) IDP_WriteProperty(sound->id.properties, wd); - if (sound->packedfile && !wd->current) { + if (sound->packedfile) { pf = sound->packedfile; writestruct(wd, DATA, "PackedFile", 1, pf); writedata(wd, DATA, pf->size, pf->data); diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt index 0606222bb17..d49686f204a 100644 --- a/source/blender/bmesh/CMakeLists.txt +++ b/source/blender/bmesh/CMakeLists.txt @@ -41,7 +41,6 @@ set(INC_SYS set(SRC operators/bmo_bevel.c operators/bmo_connect.c - operators/bmo_slide.c operators/bmo_create.c operators/bmo_dissolve.c operators/bmo_dupe.c diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h index 60d38719ddb..f593f78bab7 100644 --- a/source/blender/bmesh/bmesh.h +++ b/source/blender/bmesh/bmesh.h @@ -243,6 +243,7 @@ extern "C" { #include <stdlib.h> #include <stdio.h> +#include <assert.h> #include "bmesh_class.h" diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h index e838b130cef..4461a7afdd7 100644 --- a/source/blender/bmesh/bmesh_class.h +++ b/source/blender/bmesh/bmesh_class.h @@ -256,18 +256,17 @@ enum { }; /* defines */ - #define BM_ELEM_CD_GET_VOID_P(ele, offset) \ - ((void)0, (void *)((char *)(ele)->head.data + (offset))) + (assert(offset != -1), (void *)((char *)(ele)->head.data + (offset))) #define BM_ELEM_CD_SET_FLOAT(ele, offset, f) \ - { *((float *)((char *)(ele)->head.data + (offset))) = (f); } (void)0 + { assert(offset != -1); *((float *)((char *)(ele)->head.data + (offset))) = (f); } (void)0 #define BM_ELEM_CD_GET_FLOAT(ele, offset) \ - ((void)0, *((float *)((char *)(ele)->head.data + (offset)))) + (assert(offset != -1), *((float *)((char *)(ele)->head.data + (offset)))) #define BM_ELEM_CD_GET_FLOAT_AS_UCHAR(ele, offset) \ - (unsigned char)(BM_ELEM_CD_GET_FLOAT(ele, offset) * 255.0f) + (assert(offset != -1), (unsigned char)(BM_ELEM_CD_GET_FLOAT(ele, offset) * 255.0f)) /*forward declarations*/ diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index 5eeee45e7a9..fa58ccd98bc 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -53,7 +53,7 @@ static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, * \brief Make Quad/Triangle * * Creates a new quad or triangle from a list of 3 or 4 vertices. - * If \a nodouble is TRUE, then a check is done to see if a face + * If \a no_double is true, then a check is done to see if a face * with these vertices already exists and returns it instead. * * If a pointer to an example face is provided, it's custom data @@ -65,16 +65,16 @@ static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, BMFace *BM_face_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, - const BMFace *example, const int nodouble) + const BMFace *example, const bool no_double) { BMVert *vtar[4] = {v1, v2, v3, v4}; - return BM_face_create_quad_tri_v(bm, vtar, v4 ? 4 : 3, example, nodouble); + return BM_face_create_quad_tri_v(bm, vtar, v4 ? 4 : 3, example, no_double); } -BMFace *BM_face_create_quad_tri_v(BMesh *bm, BMVert **verts, int len, const BMFace *example, const int nodouble) +BMFace *BM_face_create_quad_tri_v(BMesh *bm, BMVert **verts, int len, const BMFace *example, const bool no_double) { BMFace *f = NULL; - int is_overlap = FALSE; + bool is_overlap = false; /* sanity check - debug mode only */ if (len == 3) { @@ -97,7 +97,7 @@ BMFace *BM_face_create_quad_tri_v(BMesh *bm, BMVert **verts, int len, const BMFa } - if (nodouble) { + if (no_double) { /* check if face exists or overlaps */ is_overlap = BM_face_exists(verts, len, &f); } @@ -793,7 +793,7 @@ void BM_elem_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, const void *sour /* First we copy select */ if (BM_elem_flag_test((BMElem *)sheader, BM_ELEM_SELECT)) { - BM_elem_select_set(target_mesh, (BMElem *)target, TRUE); + BM_elem_select_set(target_mesh, (BMElem *)target, true); } /* Now we copy flags */ diff --git a/source/blender/bmesh/intern/bmesh_construct.h b/source/blender/bmesh/intern/bmesh_construct.h index 60c465e5f5a..0f597dbb1d8 100644 --- a/source/blender/bmesh/intern/bmesh_construct.h +++ b/source/blender/bmesh/intern/bmesh_construct.h @@ -29,10 +29,10 @@ BMFace *BM_face_create_quad_tri_v(BMesh *bm, BMVert **verts, int len, - const BMFace *example, const int nodouble); + const BMFace *example, const bool no_double); BMFace *BM_face_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, - const BMFace *example, const int nodouble); + const BMFace *example, const bool no_double); void BM_face_copy_shared(BMesh *bm, BMFace *f); diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index ea9ab364b84..a2f2a9a0dba 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -109,7 +109,7 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example, cons * \brief Main function for creating a new edge. * * \note Duplicate edges are supported by the API however users should _never_ see them. - * so unless you need a unique edge or know the edge won't exist, you should call with \a nodouble = TRUE + * so unless you need a unique edge or know the edge won't exist, you should call with \a no_double = true */ BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, const eBMCreateFlag create_flag) { @@ -209,7 +209,8 @@ static BMLoop *bm_face_boundary_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge return l; } -BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short copyedges) +BMFace *BM_face_copy(BMesh *bm, BMFace *f, + const bool copy_verts, const bool copy_edges) { BMVert **verts = BLI_array_alloca(verts, f->len); BMEdge **edges = BLI_array_alloca(edges, f->len); @@ -222,7 +223,7 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short co l_iter = l_first = BM_FACE_FIRST_LOOP(f); i = 0; do { - if (copyverts) { + if (copy_verts) { verts[i] = BM_vert_create(bm, l_iter->v->co, l_iter->v, 0); } else { @@ -234,7 +235,7 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short co l_iter = l_first = BM_FACE_FIRST_LOOP(f); i = 0; do { - if (copyedges) { + if (copy_edges) { BMVert *v1, *v2; if (l_iter->e->v1 == verts[i]) { @@ -734,7 +735,7 @@ static int UNUSED_FUNCTION(bm_loop_length)(BMLoop *l) * * \return Success */ -static int bm_loop_reverse_loop(BMesh *bm, BMFace *f +static bool bm_loop_reverse_loop(BMesh *bm, BMFace *f #ifdef USE_BMESH_HOLES , BMLoopList *lst #endif @@ -748,7 +749,7 @@ static int bm_loop_reverse_loop(BMesh *bm, BMFace *f #endif const int len = f->len; - const int do_disps = CustomData_has_layer(&bm->ldata, CD_MDISPS); + const bool do_disps = CustomData_has_layer(&bm->ldata, CD_MDISPS); BMLoop *l_iter, *oldprev, *oldnext; BMEdge **edar = BLI_array_alloca(edar, len); int i, j, edok; @@ -816,13 +817,13 @@ static int bm_loop_reverse_loop(BMesh *bm, BMFace *f BM_CHECK_ELEMENT(f); - return 1; + return true; } /** * \brief Flip the faces direction */ -int bmesh_loop_reverse(BMesh *bm, BMFace *f) +bool bmesh_loop_reverse(BMesh *bm, BMFace *f) { #ifdef USE_BMESH_HOLES return bm_loop_reverse_loop(bm, f, f->loops.first); @@ -893,26 +894,26 @@ static int UNUSED_FUNCTION(count_flagged_disk)(BMVert *v, int flag) return i; } -static int disk_is_flagged(BMVert *v, int flag) +static bool disk_is_flagged(BMVert *v, int flag) { BMEdge *e = v->e; if (!e) - return FALSE; + return false; do { BMLoop *l = e->l; if (!l) { - return FALSE; + return false; } if (bmesh_radial_length(l) == 1) - return FALSE; + return false; do { if (!BM_ELEM_API_FLAG_TEST(l->f, flag)) - return FALSE; + return false; l = l->radial_next; } while (l != e->l); @@ -920,7 +921,7 @@ static int disk_is_flagged(BMVert *v, int flag) e = bmesh_disk_edge_next(e, v); } while (e != v->e); - return TRUE; + return true; } /* Mid-level Topology Manipulation Functions */ @@ -939,7 +940,7 @@ static int disk_is_flagged(BMVert *v, int flag) * \note this is a generic, flexible join faces function, * almost everything uses this, including #BM_faces_join_pair */ -BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const short do_del) +BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del) { BMFace *f, *newf; #ifdef USE_BMESH_HOLES @@ -1198,7 +1199,7 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, ListBase *holes, #endif BMEdge *example, - const short nodouble + const bool no_double ) { #ifdef USE_BMESH_HOLES @@ -1225,7 +1226,7 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, } /* allocate new edge between v1 and v2 */ - e = BM_edge_create(bm, v1, v2, example, nodouble ? BM_CREATE_NO_DOUBLE : 0); + e = BM_edge_create(bm, v1, v2, example, no_double ? BM_CREATE_NO_DOUBLE : 0); f2 = bm_face_create__sfme(bm, f); f1loop = bm_loop_create(bm, v2, e, f, v2loop, 0); @@ -1351,9 +1352,10 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) BMLoop *nextl; BMEdge *ne; BMVert *nv, *ov; - int i, edok, valence1 = 0, valence2 = 0; + int i, valence1 = 0, valence2 = 0; + bool edok; - BLI_assert(bmesh_vert_in_edge(e, tv) != FALSE); + BLI_assert(bmesh_vert_in_edge(e, tv) != false); ov = bmesh_edge_other_vert_get(e, tv); @@ -1384,11 +1386,11 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) /* verify disk cycles */ edok = bmesh_disk_validate(valence1, ov->e, ov); - BMESH_ASSERT(edok != FALSE); + BMESH_ASSERT(edok != false); edok = bmesh_disk_validate(valence2, tv->e, tv); - BMESH_ASSERT(edok != FALSE); + BMESH_ASSERT(edok != false); edok = bmesh_disk_validate(2, nv->e, nv); - BMESH_ASSERT(edok != FALSE); + BMESH_ASSERT(edok != false); /* Split the radial cycle if present */ nextl = e->l; @@ -1454,9 +1456,9 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) /* verify length of radial cycle */ edok = bmesh_radial_validate(radlen, e->l); - BMESH_ASSERT(edok != FALSE); + BMESH_ASSERT(edok != false); edok = bmesh_radial_validate(radlen, ne->l); - BMESH_ASSERT(edok != FALSE); + BMESH_ASSERT(edok != false); /* verify loop->v and loop->next->v pointers for e */ for (i = 0, l = e->l; i < radlen; i++, l = l->radial_next) { @@ -1465,7 +1467,7 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) BMESH_ASSERT(!(l->prev->e != ne && l->next->e != ne)); edok = bmesh_verts_in_edge(l->v, l->next->v, e); - BMESH_ASSERT(edok != FALSE); + BMESH_ASSERT(edok != false); BMESH_ASSERT(l->v != l->next->v); BMESH_ASSERT(l->e != l->next->e); @@ -1481,7 +1483,7 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) // BMESH_ASSERT(l->radial_next == l); BMESH_ASSERT(!(l->prev->e != e && l->next->e != e)); edok = bmesh_verts_in_edge(l->v, l->next->v, ne); - BMESH_ASSERT(edok != FALSE); + BMESH_ASSERT(edok != false); BMESH_ASSERT(l->v != l->next->v); BMESH_ASSERT(l->e != l->next->e); @@ -1533,12 +1535,13 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) * faces with just 2 edges. It is up to the caller to decide what to do with * these faces. */ -BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const short check_edge_double) +BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const bool check_edge_double) { BMEdge *oe; BMVert *ov, *tv; BMLoop *killoop, *l; - int len, radlen = 0, halt = 0, i, valence1, valence2, edok; + int len, radlen = 0, i, valence1, valence2; + bool edok, halt = false; if (bmesh_vert_in_edge(ke, kv) == 0) { return NULL; @@ -1617,7 +1620,7 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const short check_edge_dou /* Validate radial cycle of oe */ edok = bmesh_radial_validate(radlen, oe->l); - BMESH_ASSERT(edok != FALSE); + BMESH_ASSERT(edok != false); } /* deallocate edge */ @@ -1628,17 +1631,17 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const short check_edge_dou /* Validate disk cycle lengths of ov, tv are unchanged */ edok = bmesh_disk_validate(valence1, ov->e, ov); - BMESH_ASSERT(edok != FALSE); + BMESH_ASSERT(edok != false); edok = bmesh_disk_validate(valence2, tv->e, tv); - BMESH_ASSERT(edok != FALSE); + BMESH_ASSERT(edok != false); /* Validate loop cycle of all faces attached to 'oe' */ for (i = 0, l = oe->l; i < radlen; i++, l = l->radial_next) { BMESH_ASSERT(l->e == oe); edok = bmesh_verts_in_edge(l->v, l->next->v, oe); - BMESH_ASSERT(edok != FALSE); + BMESH_ASSERT(edok != false); edok = bmesh_loop_validate(l->f); - BMESH_ASSERT(edok != FALSE); + BMESH_ASSERT(edok != false); BM_CHECK_ELEMENT(l); BM_CHECK_ELEMENT(l->v); @@ -1806,7 +1809,7 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) /* validate the new loop cycle */ edok = bmesh_loop_validate(f1); - BMESH_ASSERT(edok != FALSE); + BMESH_ASSERT(edok != false); return f1; } @@ -1822,7 +1825,7 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) * where \a v and \a vtarget are connected by an edge * (assert checks for this case). */ -int BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target) +bool BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target) { void *loops_stack[BM_DEFAULT_ITER_STACK_SIZE]; BMLoop **loops; @@ -1832,7 +1835,7 @@ int BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target) /* verts already spliced */ if (v == v_target) { - return FALSE; + return false; } /* we can't modify the vert while iterating so first allocate an array of loops */ @@ -1862,7 +1865,7 @@ int BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target) /* v is unused now, and can be killed */ BM_vert_kill(bm, v); - return TRUE; + return true; } /** @@ -1876,7 +1879,7 @@ int BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target) * * \return Success */ -int bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len) +bool bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len) { BMEdge **stack = NULL; BLI_array_staticdeclare(stack, BM_DEFAULT_ITER_STACK_SIZE); @@ -1993,13 +1996,13 @@ int bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len) MEM_freeN(verts); } - return TRUE; + return true; } /** * High level function which wraps both #bmesh_vert_separate and #bmesh_edge_separate */ -int BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, +bool BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, BMEdge **e_in, int e_in_len) { int i; @@ -2023,7 +2026,7 @@ int BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, * * \note Edges must already have the same vertices. */ -int BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target) +bool BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target) { BMLoop *l; @@ -2034,7 +2037,7 @@ int BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target) * so assert on release builds */ BLI_assert(0); - return FALSE; + return false; } while (e->l) { @@ -2053,7 +2056,7 @@ int BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target) /* removes from disks too */ BM_edge_kill(bm, e); - return TRUE; + return true; } /** @@ -2067,7 +2070,7 @@ int BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target) * \note Does nothing if \a l_sep is already the only loop in the * edge radial. */ -int bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep) +bool bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep) { BMEdge *ne; int radlen; @@ -2078,7 +2081,7 @@ int bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep) radlen = bmesh_radial_length(e->l); if (radlen < 2) { /* no cut required */ - return TRUE; + return true; } if (l_sep == e->l) { @@ -2096,7 +2099,7 @@ int bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep) BM_CHECK_ELEMENT(ne); BM_CHECK_ELEMENT(e); - return TRUE; + return true; } /** diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h index 5fd4a6ec7df..d8cfc973394 100644 --- a/source/blender/bmesh/intern/bmesh_core.h +++ b/source/blender/bmesh/intern/bmesh_core.h @@ -27,7 +27,8 @@ * \ingroup bmesh */ -BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short copyedges); +BMFace *BM_face_copy(BMesh *bm, BMFace *f, + const bool copy_verts, const bool copy_edges); typedef enum eBMCreateFlag { /* faces and edges only */ @@ -49,16 +50,16 @@ void BM_face_kill(BMesh *bm, BMFace *f); void BM_edge_kill(BMesh *bm, BMEdge *e); void BM_vert_kill(BMesh *bm, BMVert *v); -int bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep); -int BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target); -int BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target); +bool bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep); +bool BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target); +bool BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target); -int bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len); +bool bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len); -int bmesh_loop_reverse(BMesh *bm, BMFace *f); +bool bmesh_loop_reverse(BMesh *bm, BMFace *f); -BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const short do_del); -int BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, +BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del); +bool BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, BMEdge **e_in, int e_in_len); /* EULER API - For modifying structure */ @@ -68,11 +69,11 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, ListBase *holes, #endif BMEdge *example, - const short nodouble + const bool no_double ); BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e); -BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const short check_edge_splice); +BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const bool check_edge_splice); BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e); BMVert *bmesh_urmv(BMesh *bm, BMFace *sf, BMVert *sv); BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *sl); diff --git a/source/blender/bmesh/intern/bmesh_error.h b/source/blender/bmesh/intern/bmesh_error.h index 2ef146c7b38..0f23f87c143 100644 --- a/source/blender/bmesh/intern/bmesh_error.h +++ b/source/blender/bmesh/intern/bmesh_error.h @@ -35,11 +35,11 @@ void BMO_error_raise(BMesh *bm, BMOperator *owner, int errcode, const char *msg) /* gets the topmost error from the stack. * returns error code or 0 if no error.*/ -int BMO_error_get(BMesh *bm, const char **msg, BMOperator **op); -int BMO_error_occurred(BMesh *bm); +int BMO_error_get(BMesh *bm, const char **msg, BMOperator **op); +bool BMO_error_occurred(BMesh *bm); /* same as geterror, only pops the error off the stack as well */ -int BMO_error_pop(BMesh *bm, const char **msg, BMOperator **op); +int BMO_error_pop(BMesh *bm, const char **msg, BMOperator **op); void BMO_error_clear(BMesh *bm); /* this is meant for handling errors, like self-intersection test failures. diff --git a/source/blender/bmesh/intern/bmesh_inline.h b/source/blender/bmesh/intern/bmesh_inline.h index 04b214f725a..102e9d47ffd 100644 --- a/source/blender/bmesh/intern/bmesh_inline.h +++ b/source/blender/bmesh/intern/bmesh_inline.h @@ -44,7 +44,7 @@ BLI_INLINE char _bm_elem_flag_test(const BMHeader *head, const char hflag) return head->hflag & hflag; } -BLI_INLINE short _bm_elem_flag_test_bool(const BMHeader *head, const char hflag) +BLI_INLINE bool _bm_elem_flag_test_bool(const BMHeader *head, const char hflag) { return (head->hflag & hflag) != 0; } diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c index 1afaf851e2a..44b8baace4c 100644 --- a/source/blender/bmesh/intern/bmesh_interp.c +++ b/source/blender/bmesh/intern/bmesh_interp.c @@ -599,7 +599,7 @@ void BM_loop_interp_multires(BMesh *bm, BMLoop *target, BMFace *source) * if do_vertex is true, target's vert data will also get interpolated. */ void BM_loop_interp_from_face(BMesh *bm, BMLoop *target, BMFace *source, - int do_vertex, int do_multires) + const bool do_vertex, const bool do_multires) { BMLoop *l_iter; BMLoop *l_first; diff --git a/source/blender/bmesh/intern/bmesh_interp.h b/source/blender/bmesh/intern/bmesh_interp.h index 8be963f5798..3563ed1f40e 100644 --- a/source/blender/bmesh/intern/bmesh_interp.h +++ b/source/blender/bmesh/intern/bmesh_interp.h @@ -44,7 +44,7 @@ void BM_elem_float_data_set(CustomData *cd, void *element, int type, const floa void BM_face_interp_from_face(BMesh *bm, BMFace *target, BMFace *source); void BM_loop_interp_from_face(BMesh *bm, BMLoop *target, BMFace *source, - int do_vertex, int do_multires); + const bool do_vertex, const bool do_multires); void BM_face_multires_bounds_smooth(BMesh *bm, BMFace *f); diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c index c3f33eb95e1..44b76df7432 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.c +++ b/source/blender/bmesh/intern/bmesh_iterators.c @@ -164,14 +164,12 @@ void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len, * * Counts how many flagged / unflagged items are found in this element. */ -int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const short value) +int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const bool value) { BMIter iter; BMElem *ele; int count = 0; - BLI_assert(ELEM(value, TRUE, FALSE)); - for (ele = BM_iter_new(&iter, NULL, itype, data); ele; ele = BM_iter_step(&iter)) { if (BM_elem_flag_test_bool(ele, hflag) == value) { count++; @@ -186,14 +184,12 @@ int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, cons * * Counts how many flagged / unflagged items are found in this mesh. */ -int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const short value) +int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const bool value) { BMIter iter; BMElem *ele; int count = 0; - BLI_assert(ELEM(value, TRUE, FALSE)); - for (ele = BM_iter_new(&iter, bm, itype, NULL); ele; ele = BM_iter_step(&iter)) { if (BM_elem_flag_test_bool(ele, hflag) == value) { count++; diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h index 7291bca6356..3b795a253bd 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.h +++ b/source/blender/bmesh/intern/bmesh_iterators.h @@ -131,8 +131,8 @@ void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len, __attribute__((warn_unused_result)) #endif ; -int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const short value); -int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const short value); +int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const bool value); +int BM_iter_mesh_count_flag(const char itype, BMesh *bm, const char hflag, const bool value); /* private for bmesh_iterators_inline.c */ void bmiter__vert_of_mesh_begin(struct BMIter *iter); diff --git a/source/blender/bmesh/intern/bmesh_iterators_inline.h b/source/blender/bmesh/intern/bmesh_iterators_inline.h index 96816521493..d9784ac9b2a 100644 --- a/source/blender/bmesh/intern/bmesh_iterators_inline.h +++ b/source/blender/bmesh/intern/bmesh_iterators_inline.h @@ -50,7 +50,7 @@ BLI_INLINE void *BM_iter_step(BMIter *iter) * it with the appropriate function pointers based * upon its type. */ -BLI_INLINE int BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *data) +BLI_INLINE bool BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *data) { /* int argtype; */ iter->itype = itype; @@ -77,91 +77,61 @@ BLI_INLINE int BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *dat iter->step = bmiter__face_of_mesh_step; break; case BM_EDGES_OF_VERT: - if (UNLIKELY(!data)) { - return FALSE; - } - + BLI_assert(data != NULL); iter->begin = bmiter__edge_of_vert_begin; iter->step = bmiter__edge_of_vert_step; iter->vdata = data; break; case BM_FACES_OF_VERT: - if (UNLIKELY(!data)) { - return FALSE; - } - + BLI_assert(data != NULL); iter->begin = bmiter__face_of_vert_begin; iter->step = bmiter__face_of_vert_step; iter->vdata = data; break; case BM_LOOPS_OF_VERT: - if (UNLIKELY(!data)) { - return FALSE; - } - + BLI_assert(data != NULL); iter->begin = bmiter__loop_of_vert_begin; iter->step = bmiter__loop_of_vert_step; iter->vdata = data; break; case BM_VERTS_OF_EDGE: - if (UNLIKELY(!data)) { - return FALSE; - } - + BLI_assert(data != NULL); iter->begin = bmiter__vert_of_edge_begin; iter->step = bmiter__vert_of_edge_step; iter->edata = data; break; case BM_FACES_OF_EDGE: - if (UNLIKELY(!data)) { - return FALSE; - } - + BLI_assert(data != NULL); iter->begin = bmiter__face_of_edge_begin; iter->step = bmiter__face_of_edge_step; iter->edata = data; break; case BM_VERTS_OF_FACE: - if (UNLIKELY(!data)) { - return FALSE; - } - + BLI_assert(data != NULL); iter->begin = bmiter__vert_of_face_begin; iter->step = bmiter__vert_of_face_step; iter->pdata = data; break; case BM_EDGES_OF_FACE: - if (UNLIKELY(!data)) { - return FALSE; - } - + BLI_assert(data != NULL); iter->begin = bmiter__edge_of_face_begin; iter->step = bmiter__edge_of_face_step; iter->pdata = data; break; case BM_LOOPS_OF_FACE: - if (UNLIKELY(!data)) { - return FALSE; - } - + BLI_assert(data != NULL); iter->begin = bmiter__loop_of_face_begin; iter->step = bmiter__loop_of_face_step; iter->pdata = data; break; case BM_LOOPS_OF_LOOP: - if (UNLIKELY(!data)) { - return FALSE; - } - + BLI_assert(data != NULL); iter->begin = bmiter__loops_of_loop_begin; iter->step = bmiter__loops_of_loop_step; iter->ldata = data; break; case BM_LOOPS_OF_EDGE: - if (UNLIKELY(!data)) { - return FALSE; - } - + BLI_assert(data != NULL); iter->begin = bmiter__loops_of_edge_begin; iter->step = bmiter__loops_of_edge_step; iter->edata = data; @@ -169,13 +139,13 @@ BLI_INLINE int BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *dat default: /* should never happen */ BLI_assert(0); - return FALSE; + return false; break; } iter->begin(iter); - return TRUE; + return true; } /** diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c index a2510129df6..68f8f38fb26 100644 --- a/source/blender/bmesh/intern/bmesh_log.c +++ b/source/blender/bmesh/intern/bmesh_log.c @@ -215,7 +215,8 @@ static BMLogFace *bm_log_face_alloc(BMLog *log, BMFace *f) BLI_assert(f->len == 3); - BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3); + // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, f, (void **)v, 3); + BM_face_as_array_vert_tri(f, v); lf->v_ids[0] = bm_log_vert_id_get(log, v[0]); lf->v_ids[1] = bm_log_vert_id_get(log, v[1]); @@ -276,11 +277,11 @@ static void bm_log_faces_restore(BMesh *bm, BMLog *log, GHash *faces) void *key = BLI_ghashIterator_getKey(&gh_iter); BMLogFace *lf = BLI_ghashIterator_getValue(&gh_iter); BMVert *v[3] = {bm_log_vert_from_id(log, lf->v_ids[0]), - bm_log_vert_from_id(log, lf->v_ids[1]), - bm_log_vert_from_id(log, lf->v_ids[2])}; + bm_log_vert_from_id(log, lf->v_ids[1]), + bm_log_vert_from_id(log, lf->v_ids[2])}; BMFace *f; - f = BM_face_create_quad_tri_v(bm, v, 3, NULL, FALSE); + f = BM_face_create_quad_tri_v(bm, v, 3, NULL, false); bm_log_face_id_set(log, f, GET_INT_FROM_POINTER(key)); } } @@ -805,8 +806,11 @@ void BM_log_vert_removed(BMesh *bm, BMLog *log, BMVert *v) unsigned int v_id = bm_log_vert_id_get(log, v); void *key = SET_INT_IN_POINTER(v_id); - if (BLI_ghash_lookup(entry->added_verts, key)) { - BLI_ghash_remove(entry->added_verts, key, NULL, NULL); + /* if it has a key, it shouldn't be NULL */ + BLI_assert(!!BLI_ghash_lookup(entry->added_verts, key) == + !!BLI_ghash_haskey(entry->added_verts, key)); + + if (BLI_ghash_remove(entry->added_verts, key, NULL, NULL)) { range_tree_uint_release(log->unused_ids, v_id); } else { @@ -843,8 +847,11 @@ void BM_log_face_removed(BMLog *log, BMFace *f) unsigned int f_id = bm_log_face_id_get(log, f); void *key = SET_INT_IN_POINTER(f_id); - if (BLI_ghash_lookup(entry->added_faces, key)) { - BLI_ghash_remove(entry->added_faces, key, NULL, NULL); + /* if it has a key, it shouldn't be NULL */ + BLI_assert(!!BLI_ghash_lookup(entry->added_faces, key) == + !!BLI_ghash_haskey(entry->added_faces, key)); + + if (BLI_ghash_remove(entry->added_faces, key, NULL, NULL)) { range_tree_uint_release(log->unused_ids, f_id); } else { diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c index 669be315cc6..4e29756104a 100644 --- a/source/blender/bmesh/intern/bmesh_marking.c +++ b/source/blender/bmesh/intern/bmesh_marking.c @@ -107,18 +107,18 @@ void BM_mesh_select_mode_flush_ex(BMesh *bm, const short selectmode) #pragma omp section { BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - int ok = TRUE; + bool ok = true; if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) { - ok = FALSE; + ok = false; break; } } while ((l_iter = l_iter->next) != l_first); } else { - ok = FALSE; + ok = false; } BM_elem_flag_set(f, BM_ELEM_SELECT, ok); @@ -129,18 +129,18 @@ void BM_mesh_select_mode_flush_ex(BMesh *bm, const short selectmode) } else if (selectmode & SCE_SELECT_EDGE) { BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - int ok = TRUE; + bool ok = true; if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { if (!BM_elem_flag_test(l_iter->e, BM_ELEM_SELECT)) { - ok = FALSE; + ok = false; break; } } while ((l_iter = l_iter->next) != l_first); } else { - ok = FALSE; + ok = false; } BM_elem_flag_set(f, BM_ELEM_SELECT, ok); @@ -171,7 +171,7 @@ void BM_mesh_deselect_flush(BMesh *bm) BMIter eiter; BMIter fiter; - int ok; + bool ok; /* we can use 2 sections here because the second loop isnt checking edge selection */ #pragma omp parallel sections if (bm->totedge + bm->totface >= BM_OMP_LIMIT) @@ -191,21 +191,21 @@ void BM_mesh_deselect_flush(BMesh *bm) #pragma omp section { BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - ok = TRUE; + ok = true; if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) { - ok = FALSE; + ok = false; break; } } while ((l_iter = l_iter->next) != l_first); } else { - ok = FALSE; + ok = false; } - if (ok == FALSE) { + if (ok == false) { BM_elem_flag_disable(f, BM_ELEM_SELECT); } } @@ -233,7 +233,7 @@ void BM_mesh_select_flush(BMesh *bm) BMIter eiter; BMIter fiter; - int ok; + bool ok; /* we can use 2 sections here because the second loop isnt checking edge selection */ #pragma omp parallel sections if (bm->totedge + bm->totface >= BM_OMP_LIMIT) @@ -253,18 +253,18 @@ void BM_mesh_select_flush(BMesh *bm) #pragma omp section { BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - ok = TRUE; + ok = true; if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) { - ok = FALSE; + ok = false; break; } } while ((l_iter = l_iter->next) != l_first); } else { - ok = FALSE; + ok = false; } if (ok) { @@ -283,7 +283,7 @@ void BM_mesh_select_flush(BMesh *bm) * Changes selection state of a single vertex * in a mesh */ -void BM_vert_select_set(BMesh *bm, BMVert *v, int select) +void BM_vert_select_set(BMesh *bm, BMVert *v, const bool select) { BLI_assert(v->head.htype == BM_VERT); @@ -310,7 +310,7 @@ void BM_vert_select_set(BMesh *bm, BMVert *v, int select) * * Changes selection state of a single edge in a mesh. */ -void BM_edge_select_set(BMesh *bm, BMEdge *e, int select) +void BM_edge_select_set(BMesh *bm, BMEdge *e, const bool select) { BLI_assert(e->head.htype == BM_EDGE); @@ -322,8 +322,8 @@ void BM_edge_select_set(BMesh *bm, BMEdge *e, int select) if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) bm->totedgesel += 1; BM_elem_flag_enable(e, BM_ELEM_SELECT); - BM_vert_select_set(bm, e->v1, TRUE); - BM_vert_select_set(bm, e->v2, TRUE); + BM_vert_select_set(bm, e->v1, true); + BM_vert_select_set(bm, e->v2, true); } else { if (BM_elem_flag_test(e, BM_ELEM_SELECT)) bm->totedgesel -= 1; @@ -354,13 +354,13 @@ void BM_edge_select_set(BMesh *bm, BMEdge *e, int select) } if (deselect) { - BM_vert_select_set(bm, verts[i], FALSE); + BM_vert_select_set(bm, verts[i], false); } } } else { - BM_vert_select_set(bm, e->v1, FALSE); - BM_vert_select_set(bm, e->v2, FALSE); + BM_vert_select_set(bm, e->v1, false); + BM_vert_select_set(bm, e->v2, false); } } @@ -372,7 +372,7 @@ void BM_edge_select_set(BMesh *bm, BMEdge *e, int select) * Changes selection state of a single * face in a mesh. */ -void BM_face_select_set(BMesh *bm, BMFace *f, int select) +void BM_face_select_set(BMesh *bm, BMFace *f, const bool select) { BMLoop *l_iter; BMLoop *l_first; @@ -391,8 +391,8 @@ void BM_face_select_set(BMesh *bm, BMFace *f, int select) BM_elem_flag_enable(f, BM_ELEM_SELECT); l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { - BM_vert_select_set(bm, l_iter->v, TRUE); - BM_edge_select_set(bm, l_iter->e, TRUE); + BM_vert_select_set(bm, l_iter->v, true); + BM_edge_select_set(bm, l_iter->e, true); } while ((l_iter = l_iter->next) != l_first); } else { @@ -412,7 +412,7 @@ void BM_face_select_set(BMesh *bm, BMFace *f, int select) } if (!f2) { - BM_edge_select_set(bm, l->e, FALSE); + BM_edge_select_set(bm, l->e, false); } } @@ -426,7 +426,7 @@ void BM_face_select_set(BMesh *bm, BMFace *f, int select) } if (!e) { - BM_vert_select_set(bm, l->v, FALSE); + BM_vert_select_set(bm, l->v, false); } } } @@ -467,7 +467,7 @@ void BM_mesh_select_mode_set(BMesh *bm, int selectmode) BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { - BM_edge_select_set(bm, (BMEdge *)ele, TRUE); + BM_edge_select_set(bm, (BMEdge *)ele, true); } } BM_mesh_select_mode_flush(bm); @@ -481,7 +481,7 @@ void BM_mesh_select_mode_set(BMesh *bm, int selectmode) #endif BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { - BM_face_select_set(bm, (BMFace *)ele, TRUE); + BM_face_select_set(bm, (BMFace *)ele, true); } } BM_mesh_select_mode_flush(bm); @@ -492,14 +492,12 @@ void BM_mesh_select_mode_set(BMesh *bm, int selectmode) * counts number of elements with flag enabled/disabled */ static int bm_mesh_flag_count(BMesh *bm, const char htype, const char hflag, - const short respecthide, const short test_for_enabled) + const short respecthide, const bool test_for_enabled) { BMElem *ele; BMIter iter; int tot = 0; - BLI_assert(ELEM(test_for_enabled, TRUE, FALSE)); - if (htype & BM_VERT) { for (ele = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL); ele; ele = BM_iter_step(&iter)) { if (respecthide && BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) continue; @@ -522,21 +520,21 @@ static int bm_mesh_flag_count(BMesh *bm, const char htype, const char hflag, return tot; } -int BM_mesh_elem_hflag_count_enabled(BMesh *bm, const char htype, const char hflag, int respecthide) +int BM_mesh_elem_hflag_count_enabled(BMesh *bm, const char htype, const char hflag, const bool respecthide) { - return bm_mesh_flag_count(bm, htype, hflag, respecthide, TRUE); + return bm_mesh_flag_count(bm, htype, hflag, respecthide, true); } -int BM_mesh_elem_hflag_count_disabled(BMesh *bm, const char htype, const char hflag, int respecthide) +int BM_mesh_elem_hflag_count_disabled(BMesh *bm, const char htype, const char hflag, const bool respecthide) { - return bm_mesh_flag_count(bm, htype, hflag, respecthide, FALSE); + return bm_mesh_flag_count(bm, htype, hflag, respecthide, false); } /** * \note use BM_elem_flag_test(ele, BM_ELEM_SELECT) to test selection * \note by design, this will not touch the editselection history stuff */ -void BM_elem_select_set(BMesh *bm, BMElem *ele, int select) +void BM_elem_select_set(BMesh *bm, BMElem *ele, const bool select) { switch (ele->head.htype) { case BM_VERT: @@ -560,12 +558,12 @@ void BM_active_face_set(BMesh *bm, BMFace *efa) bm->act_face = efa; } -BMFace *BM_active_face_get(BMesh *bm, int sloppy, int selected) +BMFace *BM_active_face_get(BMesh *bm, const bool is_sloppy, const bool is_selected) { - if (bm->act_face && (!selected || BM_elem_flag_test(bm->act_face, BM_ELEM_SELECT))) { + if (bm->act_face && (!is_selected || BM_elem_flag_test(bm->act_face, BM_ELEM_SELECT))) { return bm->act_face; } - else if (sloppy) { + else if (is_sloppy) { BMIter iter; BMFace *f = NULL; BMEditSelection *ese; @@ -579,7 +577,7 @@ BMFace *BM_active_face_get(BMesh *bm, int sloppy, int selected) if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { f = NULL; } - else if (selected && !BM_elem_flag_test(f, BM_ELEM_SELECT)) { + else if (is_selected && !BM_elem_flag_test(f, BM_ELEM_SELECT)) { f = NULL; } else { @@ -712,12 +710,13 @@ void BM_editselection_plane(BMEditSelection *ese, float r_plane[3]) cross_v3_v3v3(r_plane, efa->no, vec); } else { - BMVert *verts[4] = {NULL}; - - BM_iter_as_array(NULL, BM_VERTS_OF_FACE, efa, (void **)verts, 4); - if (efa->len == 4) { + BMVert *verts[4] = {NULL}; float vecA[3], vecB[3]; + + // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, efa, (void **)verts, 4); + BM_face_as_array_vert_quad(efa, verts); + sub_v3_v3v3(vecA, verts[3]->co, verts[2]->co); sub_v3_v3v3(vecB, verts[0]->co, verts[1]->co); add_v3_v3v3(r_plane, vecA, vecB); @@ -743,20 +742,20 @@ void BM_editselection_plane(BMEditSelection *ese, float r_plane[3]) /* --- macro wrapped funcs --- */ -int _bm_select_history_check(BMesh *bm, const BMHeader *ele) +bool _bm_select_history_check(BMesh *bm, const BMHeader *ele) { return (BLI_findptr(&bm->selected, ele, offsetof(BMEditSelection, ele)) != NULL); } -int _bm_select_history_remove(BMesh *bm, BMHeader *ele) +bool _bm_select_history_remove(BMesh *bm, BMHeader *ele) { BMEditSelection *ese = BLI_findptr(&bm->selected, ele, offsetof(BMEditSelection, ele)); if (ese) { BLI_freelinkN(&bm->selected, ese); - return TRUE; + return true; } else { - return FALSE; + return false; } } @@ -800,10 +799,10 @@ void BM_select_history_validate(BMesh *bm) } /* utility function */ -int BM_select_history_active_get(BMesh *bm, BMEditSelection *ese) +bool BM_select_history_active_get(BMesh *bm, BMEditSelection *ese) { BMEditSelection *ese_last = bm->selected.last; - BMFace *efa = BM_active_face_get(bm, FALSE, FALSE); + BMFace *efa = BM_active_face_get(bm, false, false); ese->next = ese->prev = NULL; @@ -828,14 +827,14 @@ int BM_select_history_active_get(BMesh *bm, BMEditSelection *ese) } else { ese->ele = NULL; - return FALSE; + return false; } - return TRUE; + return true; } void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hflag, - int respecthide, const char hflag_test) + const bool respecthide, const char hflag_test) { const char iter_types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, @@ -851,7 +850,7 @@ void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hfl if ((htype == (BM_VERT | BM_EDGE | BM_FACE)) && (hflag == BM_ELEM_SELECT) && - (respecthide == FALSE) && + (respecthide == false) && (hflag_test == 0)) { /* fast path for deselect all, avoid topology loops @@ -887,7 +886,7 @@ void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hfl } if (hflag & BM_ELEM_SELECT) { - BM_elem_select_set(bm, ele, FALSE); + BM_elem_select_set(bm, ele, false); } BM_elem_flag_disable(ele, hflag); } @@ -897,7 +896,7 @@ void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hfl } void BM_mesh_elem_hflag_enable_test(BMesh *bm, const char htype, const char hflag, - int respecthide, const char hflag_test) + const bool respecthide, const char hflag_test) { const char iter_types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, @@ -935,7 +934,7 @@ void BM_mesh_elem_hflag_enable_test(BMesh *bm, const char htype, const char hfla } if (hflag & BM_ELEM_SELECT) { - BM_elem_select_set(bm, ele, TRUE); + BM_elem_select_set(bm, ele, true); } BM_elem_flag_enable(ele, hflag_nosel); } @@ -944,14 +943,14 @@ void BM_mesh_elem_hflag_enable_test(BMesh *bm, const char htype, const char hfla } void BM_mesh_elem_hflag_disable_all(BMesh *bm, const char htype, const char hflag, - int respecthide) + const bool respecthide) { /* call with 0 hflag_test */ BM_mesh_elem_hflag_disable_test(bm, htype, hflag, respecthide, 0); } void BM_mesh_elem_hflag_enable_all(BMesh *bm, const char htype, const char hflag, - int respecthide) + const bool respecthide) { /* call with 0 hflag_test */ BM_mesh_elem_hflag_enable_test(bm, htype, hflag, respecthide, 0); @@ -963,7 +962,7 @@ static void vert_flush_hide_set(BMVert *v) { BMIter iter; BMEdge *e; - int hide = TRUE; + bool hide = true; BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { hide = hide && BM_elem_flag_test(e, BM_ELEM_HIDDEN); @@ -976,7 +975,7 @@ static void edge_flush_hide(BMEdge *e) { BMIter iter; BMFace *f; - int hide = TRUE; + bool hide = true; BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) { hide = hide && BM_elem_flag_test(f, BM_ELEM_HIDDEN); @@ -985,13 +984,15 @@ static void edge_flush_hide(BMEdge *e) BM_elem_flag_set(e, BM_ELEM_HIDDEN, hide); } -void BM_vert_hide_set(BMVert *v, int hide) +void BM_vert_hide_set(BMVert *v, const bool hide) { /* vert hiding: vert + surrounding edges and faces */ BMIter iter, fiter; BMEdge *e; BMFace *f; + BLI_assert(v->head.htype == BM_VERT); + BM_elem_flag_set(v, BM_ELEM_HIDDEN, hide); BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { @@ -1003,12 +1004,14 @@ void BM_vert_hide_set(BMVert *v, int hide) } } -void BM_edge_hide_set(BMEdge *e, int hide) +void BM_edge_hide_set(BMEdge *e, const bool hide) { BMIter iter; BMFace *f; /* BMVert *v; */ + BLI_assert(e->head.htype == BM_EDGE); + /* edge hiding: faces around the edge */ BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) { BM_elem_flag_set(f, BM_ELEM_HIDDEN, hide); @@ -1021,11 +1024,13 @@ void BM_edge_hide_set(BMEdge *e, int hide) vert_flush_hide_set(e->v2); } -void BM_face_hide_set(BMFace *f, int hide) +void BM_face_hide_set(BMFace *f, const bool hide) { BMIter iter; BMLoop *l; + BLI_assert(f->head.htype == BM_FACE); + BM_elem_flag_set(f, BM_ELEM_HIDDEN, hide); BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) { @@ -1037,21 +1042,21 @@ void BM_face_hide_set(BMFace *f, int hide) } } -void _bm_elem_hide_set(BMesh *bm, BMHeader *head, int hide) +void _bm_elem_hide_set(BMesh *bm, BMHeader *head, const bool hide) { /* Follow convention of always deselecting before * hiding an element */ switch (head->htype) { case BM_VERT: - if (hide) BM_vert_select_set(bm, (BMVert *)head, FALSE); + if (hide) BM_vert_select_set(bm, (BMVert *)head, false); BM_vert_hide_set((BMVert *)head, hide); break; case BM_EDGE: - if (hide) BM_edge_select_set(bm, (BMEdge *)head, FALSE); + if (hide) BM_edge_select_set(bm, (BMEdge *)head, false); BM_edge_hide_set((BMEdge *)head, hide); break; case BM_FACE: - if (hide) BM_face_select_set(bm, (BMFace *)head, FALSE); + if (hide) BM_face_select_set(bm, (BMFace *)head, false); BM_face_hide_set((BMFace *)head, hide); break; default: diff --git a/source/blender/bmesh/intern/bmesh_marking.h b/source/blender/bmesh/intern/bmesh_marking.h index 8d4397794d5..a3d2d4a6985 100644 --- a/source/blender/bmesh/intern/bmesh_marking.h +++ b/source/blender/bmesh/intern/bmesh_marking.h @@ -35,29 +35,29 @@ typedef struct BMEditSelection { /* geometry hiding code */ #define BM_elem_hide_set(bm, ele, hide) _bm_elem_hide_set(bm, &(ele)->head, hide) -void _bm_elem_hide_set(BMesh *bm, BMHeader *ele, int hide); -void BM_vert_hide_set(BMVert *v, int hide); -void BM_edge_hide_set(BMEdge *e, int hide); -void BM_face_hide_set(BMFace *f, int hide); +void _bm_elem_hide_set(BMesh *bm, BMHeader *ele, const bool hide); +void BM_vert_hide_set(BMVert *v, const bool hide); +void BM_edge_hide_set(BMEdge *e, const bool hide); +void BM_face_hide_set(BMFace *f, const bool hide); /* Selection code */ -void BM_elem_select_set(BMesh *bm, BMElem *ele, int select); +void BM_elem_select_set(BMesh *bm, BMElem *ele, const bool select); void BM_mesh_elem_hflag_enable_test(BMesh *bm, const char htype, const char hflag, - int respecthide, const char hflag_test); + const bool respecthide, const char hflag_test); void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hflag, - int respecthide, const char hflag_test); + const bool respecthide, const char hflag_test); void BM_mesh_elem_hflag_enable_all(BMesh *bm, const char htype, const char hflag, - int respecthide); + const bool respecthide); void BM_mesh_elem_hflag_disable_all(BMesh *bm, const char htype, const char hflag, - int respecthide); + const bool respecthide); /* individual element select functions, BM_elem_select_set is a shortcut for these * that automatically detects which one to use*/ -void BM_vert_select_set(BMesh *bm, BMVert *v, int select); -void BM_edge_select_set(BMesh *bm, BMEdge *e, int select); -void BM_face_select_set(BMesh *bm, BMFace *f, int select); +void BM_vert_select_set(BMesh *bm, BMVert *v, const bool select); +void BM_edge_select_set(BMesh *bm, BMEdge *e, const bool select); +void BM_face_select_set(BMesh *bm, BMFace *f, const bool select); void BM_mesh_select_mode_set(BMesh *bm, int selectmode); void BM_mesh_select_mode_flush_ex(BMesh *bm, const short selectmode); @@ -66,12 +66,12 @@ void BM_mesh_select_mode_flush(BMesh *bm); void BM_mesh_deselect_flush(BMesh *bm); void BM_mesh_select_flush(BMesh *bm); -int BM_mesh_elem_hflag_count_enabled(BMesh *bm, const char htype, const char hflag, int respecthide); -int BM_mesh_elem_hflag_count_disabled(BMesh *bm, const char htype, const char hflag, int respecthide); +int BM_mesh_elem_hflag_count_enabled(BMesh *bm, const char htype, const char hflag, const bool respecthide); +int BM_mesh_elem_hflag_count_disabled(BMesh *bm, const char htype, const char hflag, const bool respecthide); /* edit selection stuff */ void BM_active_face_set(BMesh *bm, BMFace *f); -BMFace *BM_active_face_get(BMesh *bm, int sloppy, int selected); +BMFace *BM_active_face_get(BMesh *bm, const bool is_sloppy, const bool is_selected); void BM_editselection_center(BMEditSelection *ese, float r_center[3]); void BM_editselection_normal(BMEditSelection *ese, float r_normal[3]); @@ -82,13 +82,13 @@ void BM_editselection_plane(BMEditSelection *ese, float r_plane[3]); #define BM_select_history_store_notest(bm, ele) _bm_select_history_store_notest(bm, &(ele)->head) #define BM_select_history_store(bm, ele) _bm_select_history_store(bm, &(ele)->head) -int _bm_select_history_check(BMesh *bm, const BMHeader *ele); -int _bm_select_history_remove(BMesh *bm, BMHeader *ele); +bool _bm_select_history_check(BMesh *bm, const BMHeader *ele); +bool _bm_select_history_remove(BMesh *bm, BMHeader *ele); void _bm_select_history_store_notest(BMesh *bm, BMHeader *ele); void _bm_select_history_store(BMesh *bm, BMHeader *ele); void BM_select_history_validate(BMesh *bm); void BM_select_history_clear(BMesh *em); -int BM_select_history_active_get(BMesh *bm, struct BMEditSelection *ese); +bool BM_select_history_active_get(BMesh *bm, struct BMEditSelection *ese); #endif /* __BMESH_MARKING_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index 769ede0c2ca..e72ad5dae3c 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -261,7 +261,7 @@ void BM_mesh_free(BMesh *bm) * * Updates the normals of a mesh. */ -void BM_mesh_normals_update(BMesh *bm, const short skip_hidden) +void BM_mesh_normals_update(BMesh *bm, const bool skip_hidden) { BMVert *v; BMFace *f; @@ -362,8 +362,8 @@ static void UNUSED_FUNCTION(bm_mdisps_space_set)(Object *ob, BMesh *bm, int from { /* switch multires data out of tangent space */ if (CustomData_has_layer(&bm->ldata, CD_MDISPS)) { - BMEditMesh *em = BMEdit_Create(bm, FALSE); - DerivedMesh *dm = CDDM_from_editbmesh(em, TRUE, FALSE); + BMEditMesh *em = BMEdit_Create(bm, false); + DerivedMesh *dm = CDDM_from_editbmesh(em, true, false); MDisps *mdisps; BMFace *f; BMIter iter; @@ -455,7 +455,7 @@ void bmesh_edit_end(BMesh *bm, int UNUSED(flag)) #endif /* compute normals, clear temp flags and flush selections */ - BM_mesh_normals_update(bm, TRUE); + BM_mesh_normals_update(bm, true); BM_mesh_select_mode_flush(bm); } @@ -553,12 +553,12 @@ void BM_mesh_elem_index_validate(BMesh *bm, const char *location, const char *fu BMIter iter; BMElem *ele; int i; - int is_any_error = 0; + bool is_any_error = 0; for (i = 0; i < 3; i++) { - const int is_dirty = (flag_types[i] & bm->elem_index_dirty); + const bool is_dirty = (flag_types[i] & bm->elem_index_dirty); int index = 0; - int is_error = FALSE; + bool is_error = false; int err_val = 0; int err_idx = 0; @@ -567,7 +567,7 @@ void BM_mesh_elem_index_validate(BMesh *bm, const char *location, const char *fu if (BM_elem_index_get(ele) != index) { err_val = BM_elem_index_get(ele); err_idx = index; - is_error = TRUE; + is_error = true; } } @@ -575,13 +575,13 @@ void BM_mesh_elem_index_validate(BMesh *bm, const char *location, const char *fu index++; } - if ((is_error == TRUE) && (is_dirty == FALSE)) { - is_any_error = TRUE; + if ((is_error == true) && (is_dirty == false)) { + is_any_error = true; fprintf(stderr, "Invalid Index: at %s, %s, %s[%d] invalid index %d, '%s', '%s'\n", location, func, type_names[i], err_idx, err_val, msg_a, msg_b); } - else if ((is_error == FALSE) && (is_dirty == TRUE)) { + else if ((is_error == false) && (is_dirty == true)) { #if 0 /* mostly annoying */ diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h index 8baba568fb8..35ce1859c2b 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.h +++ b/source/blender/bmesh/intern/bmesh_mesh.h @@ -37,7 +37,7 @@ void BM_mesh_free(BMesh *bm); void BM_mesh_data_free(BMesh *bm); void BM_mesh_clear(BMesh *bm); -void BM_mesh_normals_update(BMesh *bm, const short skip_hidden); +void BM_mesh_normals_update(BMesh *bm, const bool skip_hidden); void bmesh_edit_begin(BMesh *bm, int type_flag); void bmesh_edit_end(BMesh *bm, int type_flag); diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index 8198e30bac6..a63b715fd14 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -163,7 +163,7 @@ char BM_mesh_cd_flag_from_bmesh(BMesh *bm) } /* Mesh -> BMesh */ -void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) +void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, bool set_key, int act_key_nr) { MVert *mvert; BLI_array_declare(verts); @@ -174,7 +174,6 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) BMVert *v, **vt = NULL, **verts = NULL; BMEdge *e, **fedges = NULL, **et = NULL; BMFace *f; - BMLoop *l; BLI_array_declare(fedges); float (*keyco)[3] = NULL; int *keyi; @@ -280,7 +279,7 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) /* this is necessary for selection counts to work properly */ if (mvert->flag & SELECT) { - BM_vert_select_set(bm, v, TRUE); + BM_vert_select_set(bm, v, true); } normal_short_to_float_v3(v->no, mvert->no); @@ -328,7 +327,7 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) /* this is necessary for selection counts to work properly */ if (medge->flag & SELECT) { - BM_edge_select_set(bm, e, TRUE); + BM_edge_select_set(bm, e, true); } /* Copy Custom Data */ @@ -343,7 +342,8 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) mpoly = me->mpoly; for (i = 0; i < me->totpoly; i++, mpoly++) { - BMIter iter; + BMLoop *l_iter; + BMLoop *l_first; BLI_array_empty(fedges); BLI_array_empty(verts); @@ -395,17 +395,18 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) /* this is necessary for selection counts to work properly */ if (mpoly->flag & ME_FACE_SEL) { - BM_face_select_set(bm, f, TRUE); + BM_face_select_set(bm, f, true); } f->mat_nr = mpoly->mat_nr; if (i == me->act_face) bm->act_face = f; - j = 0; - BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, j) { + j = mpoly->loopstart; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { /* Save index of correspsonding MLoop */ - CustomData_to_bmesh_block(&me->ldata, &bm->ldata, mpoly->loopstart + j, &l->head.data, true); - } + CustomData_to_bmesh_block(&me->ldata, &bm->ldata, j++, &l_iter->head.data, true); + } while ((l_iter = l_iter->next) != l_first); /* Copy Custom Data */ CustomData_to_bmesh_block(&me->pdata, &bm->pdata, i, &f->head.data, true); @@ -415,22 +416,20 @@ void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, int set_key, int act_key_nr) if (me->mselect && me->totselect != 0) { - BMVert **vert_array = MEM_callocN(sizeof(BMVert *) * bm->totvert, - "Selection Conversion Vertex Pointer Array"); - BMEdge **edge_array = MEM_callocN(sizeof(BMEdge *) * bm->totedge, - "Selection Conversion Edge Pointer Array"); - BMFace **face_array = MEM_callocN(sizeof(BMFace *) * bm->totface, - "Selection Conversion Face Pointer Array"); - - BMIter iter; - BMVert *vert; - BMEdge *edge; - BMFace *face; + BMVert **vert_array = MEM_mallocN(sizeof(BMVert *) * bm->totvert, "VSelConv"); + BMEdge **edge_array = MEM_mallocN(sizeof(BMEdge *) * bm->totedge, "ESelConv"); + BMFace **face_array = MEM_mallocN(sizeof(BMFace *) * bm->totface, "FSelConv"); MSelect *msel; - BM_ITER_MESH_INDEX (vert, &iter, bm, BM_VERTS_OF_MESH, i) { vert_array[i] = vert; } - BM_ITER_MESH_INDEX (edge, &iter, bm, BM_EDGES_OF_MESH, i) { edge_array[i] = edge; } - BM_ITER_MESH_INDEX (face, &iter, bm, BM_FACES_OF_MESH, i) { face_array[i] = face; } +#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT) + { +#pragma omp section + { BM_iter_as_array(bm, BM_VERTS_OF_MESH, NULL, (void **)vert_array, bm->totvert); } +#pragma omp section + { BM_iter_as_array(bm, BM_EDGES_OF_MESH, NULL, (void **)edge_array, bm->totedge); } +#pragma omp section + { BM_iter_as_array(bm, BM_FACES_OF_MESH, NULL, (void **)face_array, bm->totface); } + } for (i = 0, msel = me->mselect; i < me->totselect; i++, msel++) { switch (msel->type) { @@ -549,7 +548,7 @@ BLI_INLINE void bmesh_quick_edgedraw_flag(MEdge *med, BMEdge *e) } } -void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, int dotess) +void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, bool do_tessface) { MLoop *mloop; MPoly *mpoly; @@ -620,6 +619,8 @@ void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, int dotess) CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, mloop, me->totloop); CustomData_add_layer(&me->pdata, CD_MPOLY, CD_ASSIGN, mpoly, me->totpoly); + me->cd_flag = BM_mesh_cd_flag_from_bmesh(bm); + /* this is called again, 'dotess' arg is used there */ mesh_update_customdata_pointers(me, 0); @@ -755,11 +756,11 @@ void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, int dotess) if (vertMap) MEM_freeN(vertMap); } - if (dotess) { + if (do_tessface) { BKE_mesh_tessface_calc(me); } - mesh_update_customdata_pointers(me, dotess); + mesh_update_customdata_pointers(me, do_tessface); { BMEditSelection *selected; @@ -823,12 +824,12 @@ void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, int dotess) * bmesh and the mesh are out of sync */ (oldverts != NULL)) /* not used here, but 'oldverts' is used later for applying 'ofs' */ { - int act_is_basis = FALSE; + bool act_is_basis = false; /* find if this key is a basis for any others */ for (currkey = me->key->block.first; currkey; currkey = currkey->next) { if (bm->shapenr - 1 == currkey->relative) { - act_is_basis = TRUE; + act_is_basis = true; break; } } diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.h b/source/blender/bmesh/intern/bmesh_mesh_conv.h index 55ac39c6745..7fe4b8fe58b 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.h +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.h @@ -38,7 +38,7 @@ void BM_mesh_cd_flag_ensure(BMesh *bm, struct Mesh *mesh, const char cd_flag); void BM_mesh_cd_flag_apply(BMesh *bm, const char cd_flag); char BM_mesh_cd_flag_from_bmesh(BMesh *bm); -void BM_mesh_bm_from_me(BMesh *bm, struct Mesh *me, int set_key, int act_key_nr); -void BM_mesh_bm_to_me(BMesh *bm, struct Mesh *me, int dotess); +void BM_mesh_bm_from_me(BMesh *bm, struct Mesh *me, bool set_key, int act_key_nr); +void BM_mesh_bm_to_me(BMesh *bm, struct Mesh *me, bool do_tessface); #endif /* __BMESH_MESH_CONV_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_mesh_validate.c b/source/blender/bmesh/intern/bmesh_mesh_validate.c index 8ab5f10361f..e6eee16e49c 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_validate.c +++ b/source/blender/bmesh/intern/bmesh_mesh_validate.c @@ -49,9 +49,9 @@ /** * Check of this BMesh is valid, this function can be slow since its intended to help with debugging. * - * \return TRUE when the mesh is valid. + * \return true when the mesh is valid. */ -int BM_mesh_validate(BMesh *bm) +bool BM_mesh_validate(BMesh *bm) { int errtot; @@ -106,11 +106,11 @@ int BM_mesh_validate(BMesh *bm) if (l_iter->e != e) { ERRMSG("edge %d: has invalid loop, loop is of face %d", i, BM_elem_index_get(l_iter->f)); } - else if (BM_vert_in_edge(e, l_iter->v) == FALSE) { + else if (BM_vert_in_edge(e, l_iter->v) == false) { ERRMSG("edge %d: has invalid loop with vert not in edge, loop is of face %d", i, BM_elem_index_get(l_iter->f)); } - else if (BM_vert_in_edge(e, l_iter->next->v) == FALSE) { + else if (BM_vert_in_edge(e, l_iter->next->v) == false) { ERRMSG("edge %d: has invalid loop with next vert not in edge, loop is of face %d", i, BM_elem_index_get(l_iter->f)); } @@ -181,7 +181,7 @@ int BM_mesh_validate(BMesh *bm) ERRMSG("Finished - errors %d", errtot); - return TRUE; + return true; } diff --git a/source/blender/bmesh/intern/bmesh_mesh_validate.h b/source/blender/bmesh/intern/bmesh_mesh_validate.h index 6839dc74d25..f89141387d8 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_validate.h +++ b/source/blender/bmesh/intern/bmesh_mesh_validate.h @@ -30,6 +30,6 @@ * \ingroup bmesh */ -int BM_mesh_validate(BMesh *bm); +bool BM_mesh_validate(BMesh *bm); #endif /* __BMESH_MESH_VALIDATE_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index 9a99d5b96d1..d98598cac89 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -64,36 +64,36 @@ * \note dissolves vert, in more situations then BM_disk_dissolve * (e.g. if the vert is part of a wire edge, etc). */ -int BM_vert_dissolve(BMesh *bm, BMVert *v) +bool BM_vert_dissolve(BMesh *bm, BMVert *v) { const int len = BM_vert_edge_count(v); if (len == 1) { BM_vert_kill(bm, v); /* will kill edges too */ - return TRUE; + return true; } else if (!BM_vert_is_manifold(v)) { if (!v->e) { BM_vert_kill(bm, v); - return TRUE; + return true; } else if (!v->e->l) { if (len == 2) { - return (BM_vert_collapse_edge(bm, v->e, v, TRUE) != NULL); + return (BM_vert_collapse_edge(bm, v->e, v, true) != NULL); } else { /* used to kill the vertex here, but it may be connected to faces. * so better do nothing */ - return FALSE; + return false; } } else { - return FALSE; + return false; } } else if (len == 2 && BM_vert_face_count(v) == 1) { /* boundary vertex on a face */ - return (BM_vert_collapse_edge(bm, v->e, v, TRUE) != NULL); + return (BM_vert_collapse_edge(bm, v->e, v, true) != NULL); } else { return BM_disk_dissolve(bm, v); @@ -103,14 +103,14 @@ int BM_vert_dissolve(BMesh *bm, BMVert *v) /** * dissolves all faces around a vert, and removes it. */ -int BM_disk_dissolve(BMesh *bm, BMVert *v) +bool BM_disk_dissolve(BMesh *bm, BMVert *v) { BMFace *f, *f2; BMEdge *e, *keepedge = NULL, *baseedge = NULL; int len = 0; if (!BM_vert_is_manifold(v)) { - return FALSE; + return false; } if (v->e) { @@ -135,62 +135,62 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v) * increasing valence to four. this may be hackish. . */ BMLoop *loop = e->l; if (loop->v == v) loop = loop->next; - if (!BM_face_split(bm, loop->f, v, loop->v, NULL, NULL, FALSE)) - return FALSE; + if (!BM_face_split(bm, loop->f, v, loop->v, NULL, NULL, false)) + return false; if (!BM_disk_dissolve(bm, v)) { - return FALSE; + return false; } #else - if (UNLIKELY(!BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, TRUE))) { - return FALSE; + if (UNLIKELY(!BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, true))) { + return false; } - else if (UNLIKELY(!BM_vert_collapse_faces(bm, v->e, v, 1.0, FALSE, TRUE))) { - return FALSE; + else if (UNLIKELY(!BM_vert_collapse_faces(bm, v->e, v, 1.0, false, true))) { + return false; } #endif - return TRUE; + return true; } else if (keepedge == NULL && len == 2) { /* collapse the vertex */ - e = BM_vert_collapse_faces(bm, v->e, v, 1.0, TRUE, TRUE); + e = BM_vert_collapse_faces(bm, v->e, v, 1.0, true, true); if (!e) { - return FALSE; + return false; } /* handle two-valence */ f = e->l->f; f2 = e->l->radial_next->f; - if (f != f2 && !BM_faces_join_pair(bm, f, f2, e, TRUE)) { - return FALSE; + if (f != f2 && !BM_faces_join_pair(bm, f, f2, e, true)) { + return false; } - return TRUE; + return true; } if (keepedge) { - int done = FALSE; + bool done = false; while (!done) { - done = TRUE; + done = true; e = v->e; do { f = NULL; len = bmesh_radial_length(e->l); if (len == 2 && (e != baseedge) && (e != keepedge)) { - f = BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, TRUE); + f = BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, true); /* return if couldn't join faces in manifold * conditions */ /* !disabled for testing why bad things happen */ if (!f) { - return FALSE; + return false; } } if (f) { - done = FALSE; + done = false; break; } e = bmesh_disk_edge_next(e, v); @@ -199,10 +199,10 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v) /* collapse the vertex */ /* note, the baseedge can be a boundary of manifold, use this as join_faces arg */ - e = BM_vert_collapse_faces(bm, baseedge, v, 1.0, !BM_edge_is_boundary(baseedge), TRUE); + e = BM_vert_collapse_faces(bm, baseedge, v, 1.0, !BM_edge_is_boundary(baseedge), true); if (!e) { - return FALSE; + return false; } /* get remaining two faces */ @@ -211,13 +211,13 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v) if (f != f2) { /* join two remaining faces */ - if (!BM_faces_join_pair(bm, f, f2, e, TRUE)) { - return FALSE; + if (!BM_faces_join_pair(bm, f, f2, e, true)) { + return false; } } } - return TRUE; + return true; } /** @@ -235,7 +235,7 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v) * * \return pointer to the combined face */ -BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e, const short do_del) +BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e, const bool do_del) { BMLoop *l1, *l2; BMEdge *jed = NULL; @@ -302,7 +302,7 @@ BMEdge *BM_verts_connect(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **r_f) if (v_iter == v2) { BMLoop *nl; - f_iter = BM_face_split(bm, f_iter, v1, v2, &nl, NULL, FALSE); + f_iter = BM_face_split(bm, f_iter, v1, v2, &nl, NULL, false); if (r_f) { *r_f = f_iter; @@ -336,22 +336,22 @@ BMEdge *BM_verts_connect(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **r_f) * other side). NULL if the split fails. */ BMFace *BM_face_split(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **r_l, - BMEdge *example, const short nodouble) + BMEdge *example, const bool no_double) { - const int has_mdisp = CustomData_has_layer(&bm->ldata, CD_MDISPS); + const bool has_mdisp = CustomData_has_layer(&bm->ldata, CD_MDISPS); BMFace *nf, *of; BLI_assert(v1 != v2); /* do we have a multires layer? */ if (has_mdisp) { - of = BM_face_copy(bm, f, FALSE, FALSE); + of = BM_face_copy(bm, f, false, false); } #ifdef USE_BMESH_HOLES - nf = bmesh_sfme(bm, f, v1, v2, r_l, NULL, example, nodouble); + nf = bmesh_sfme(bm, f, v1, v2, r_l, NULL, example, no_double); #else - nf = bmesh_sfme(bm, f, v1, v2, r_l, example, nodouble); + nf = bmesh_sfme(bm, f, v1, v2, r_l, example, no_double); #endif if (nf) { @@ -414,15 +414,15 @@ BMFace *BM_face_split_n(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, float cos[ BLI_assert(v1 != v2); - of = BM_face_copy(bm, f, TRUE, TRUE); + of = BM_face_copy(bm, f, true, true); if (!r_l) r_l = &l_dummy; #ifdef USE_BMESH_HOLES - nf = bmesh_sfme(bm, f, v1, v2, r_l, NULL, example, FALSE); + nf = bmesh_sfme(bm, f, v1, v2, r_l, NULL, example, false); #else - nf = bmesh_sfme(bm, f, v1, v2, r_l, example, FALSE); + nf = bmesh_sfme(bm, f, v1, v2, r_l, example, false); #endif /* bmesh_sfme returns in r_l a Loop for nf going from v1 to v2. * The radial_next is for f and goes from v2 to v1 */ @@ -445,7 +445,7 @@ BMFace *BM_face_split_n(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, float cos[ do { if (l_iter->v == newv) { /* this interpolates both loop and vertex data */ - BM_loop_interp_from_face(bm, l_iter, of, TRUE, TRUE); + BM_loop_interp_from_face(bm, l_iter, of, true, true); } } while ((l_iter = l_iter->radial_next) != e_iter->l); } @@ -482,7 +482,7 @@ BMFace *BM_face_split_n(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, float cos[ * \returns The New Edge */ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac, - const short join_faces, const short kill_degenerate_faces) + const bool join_faces, const bool kill_degenerate_faces) { BMEdge *ne = NULL; BMVert *tv = bmesh_edge_other_vert_get(ke, kv); @@ -534,10 +534,10 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac, } if (BLI_array_count(faces) >= 2) { - BMFace *f2 = BM_faces_join(bm, faces, BLI_array_count(faces), TRUE); + BMFace *f2 = BM_faces_join(bm, faces, BLI_array_count(faces), true); if (f2) { BMLoop *nl = NULL; - if (BM_face_split(bm, f2, tv, tv2, &nl, NULL, FALSE)) { + if (BM_face_split(bm, f2, tv, tv2, &nl, NULL, false)) { ne = nl->e; } } @@ -549,7 +549,7 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac, /* single face or no faces */ /* same as BM_vert_collapse_edge() however we already * have vars to perform this operation so don't call. */ - ne = bmesh_jekv(bm, ke, kv, TRUE); + ne = bmesh_jekv(bm, ke, kv, true); /* ne = BM_edge_exists(tv, tv2); */ /* same as return above */ if (ne && kill_degenerate_faces) { @@ -589,7 +589,7 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac, * \return The New Edge */ BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *ke, BMVert *kv, - const short kill_degenerate_faces) + const bool kill_degenerate_faces) { /* nice example implementation but we want loops to have their customdata * accounted for */ @@ -618,7 +618,7 @@ BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *ke, BMVert *kv, #else /* with these args faces are never joined, same as above * but account for loop customdata */ - return BM_vert_collapse_faces(bm, ke, kv, 1.0f, FALSE, kill_degenerate_faces); + return BM_vert_collapse_faces(bm, ke, kv, 1.0f, false, kill_degenerate_faces); #endif } @@ -641,7 +641,7 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float perce BMFace **oldfaces = NULL; BMEdge *e_dummy; BLI_array_staticdeclare(oldfaces, 32); - const int do_mdisp = (e->l && CustomData_has_layer(&bm->ldata, CD_MDISPS)); + const bool do_mdisp = (e->l && CustomData_has_layer(&bm->ldata, CD_MDISPS)); /* we need this for handling multi-res */ if (!r_e) { @@ -662,7 +662,7 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float perce /* flag existing faces so we can differentiate oldfaces from new faces */ for (i = 0; i < BLI_array_count(oldfaces); i++) { BM_ELEM_API_FLAG_ENABLE(oldfaces[i], _FLAG_OVERLAP); - oldfaces[i] = BM_face_copy(bm, oldfaces[i], TRUE, TRUE); + oldfaces[i] = BM_face_copy(bm, oldfaces[i], true, true); BM_ELEM_API_FLAG_DISABLE(oldfaces[i], _FLAG_OVERLAP); } } @@ -761,16 +761,18 @@ BMVert *BM_edge_split_n(BMesh *bm, BMEdge *e, int numcuts) return nv; } +#if 0 /** * Checks if a face is valid in the data structure */ -int BM_face_validate(BMFace *face, FILE *err) +bool BM_face_validate(BMFace *face, FILE *err) { BMIter iter; BLI_array_declare(verts); BMVert **verts = NULL; BMLoop *l; - int ret = 1, i, j; + int i, j; + bool ret = true; if (face->len == 2) { fprintf(err, "warning: found two-edged face. face ptr: %p\n", face); @@ -784,7 +786,7 @@ int BM_face_validate(BMFace *face, FILE *err) fprintf(err, "Found bmesh edge with identical verts!\n"); fprintf(err, " edge ptr: %p, vert: %p\n", l->e, l->e->v1); fflush(err); - ret = 0; + ret = false; } } @@ -798,7 +800,7 @@ int BM_face_validate(BMFace *face, FILE *err) fprintf(err, "Found duplicate verts in bmesh face!\n"); fprintf(err, " face ptr: %p, vert: %p\n", face, verts[i]); fflush(err); - ret = 0; + ret = false; } } } @@ -806,7 +808,7 @@ int BM_face_validate(BMFace *face, FILE *err) BLI_array_free(verts); return ret; } - +#endif /** * Calculate the 2 loops which _would_ make up the newly rotated Edge @@ -822,14 +824,14 @@ int BM_face_validate(BMFace *face, FILE *err) * * \note #BM_edge_rotate_check must have already run. */ -void BM_edge_calc_rotate(BMEdge *e, int ccw, +void BM_edge_calc_rotate(BMEdge *e, const bool ccw, BMLoop **r_l1, BMLoop **r_l2) { BMVert *v1, *v2; BMFace *fa, *fb; /* this should have already run */ - BLI_assert(BM_edge_rotate_check(e) == TRUE); + BLI_assert(BM_edge_rotate_check(e) == true); /* we know this will work */ BM_edge_face_pair(e, &fa, &fb); @@ -855,7 +857,7 @@ void BM_edge_calc_rotate(BMEdge *e, int ccw, * Quick check to see if we could rotate the edge, * use this to avoid calling exceptions on common cases. */ -int BM_edge_rotate_check(BMEdge *e) +bool BM_edge_rotate_check(BMEdge *e) { BMFace *fa, *fb; if (BM_edge_face_pair(e, &fa, &fb)) { @@ -868,7 +870,7 @@ int BM_edge_rotate_check(BMEdge *e) * (ie - the next edge doesn't share the same faces). * since we can't rotate usefully in this case. */ if (la->v == lb->v) { - return FALSE; + return false; } /* mirror of the check above but in the opposite direction */ @@ -876,13 +878,13 @@ int BM_edge_rotate_check(BMEdge *e) lb = BM_face_other_vert_loop(fb, e->v1, e->v2); if (la->v == lb->v) { - return FALSE; + return false; } - return TRUE; + return true; } else { - return FALSE; + return false; } } @@ -897,7 +899,7 @@ int BM_edge_rotate_check(BMEdge *e) * \param l1,l2 are the loops of the proposed verts to rotate too and should * be the result of calling #BM_edge_calc_rotate */ -int BM_edge_rotate_check_degenerate(BMEdge *e, BMLoop *l1, BMLoop *l2) +bool BM_edge_rotate_check_degenerate(BMEdge *e, BMLoop *l1, BMLoop *l2) { /* note: for these vars 'old' just means initial edge state. */ @@ -924,7 +926,7 @@ int BM_edge_rotate_check_degenerate(BMEdge *e, BMLoop *l1, BMLoop *l2) BMVert *v1_alt, *v2_alt; /* this should have already run */ - BLI_assert(BM_edge_rotate_check(e) == TRUE); + BLI_assert(BM_edge_rotate_check(e) == true); BM_edge_ordered_verts(e, &v1_old, &v2_old); @@ -965,12 +967,12 @@ int BM_edge_rotate_check_degenerate(BMEdge *e, BMLoop *l1, BMLoop *l2) cross_v3_v3v3(cross_old, ed_dir_old, ed_dir_v1_old); cross_v3_v3v3(cross_new, ed_dir_new, ed_dir_v1_new); if (dot_v3v3(cross_old, cross_new) < 0.0f) { /* does this flip? */ - return FALSE; + return false; } cross_v3_v3v3(cross_old, ed_dir_old, ed_dir_v2_old); cross_v3_v3v3(cross_new, ed_dir_new, ed_dir_v2_new); if (dot_v3v3(cross_old, cross_new) < 0.0f) { /* does this flip? */ - return FALSE; + return false; } negate_v3_v3(ed_dir_new_flip, ed_dir_new); @@ -979,14 +981,14 @@ int BM_edge_rotate_check_degenerate(BMEdge *e, BMLoop *l1, BMLoop *l2) if ((dot_v3v3(ed_dir_new, ed_dir_v1_new) > 0.999f) || (dot_v3v3(ed_dir_new_flip, ed_dir_v2_new) > 0.999f)) { - return FALSE; + return false; } - return TRUE; + return true; } -int BM_edge_rotate_check_beauty(BMEdge *e, - BMLoop *l1, BMLoop *l2) +bool BM_edge_rotate_check_beauty(BMEdge *e, + BMLoop *l1, BMLoop *l2) { /* Stupid check for now: * Could compare angles of surrounding edges @@ -1009,7 +1011,7 @@ int BM_edge_rotate_check_beauty(BMEdge *e, * * \see header definition for \a check_flag enum. */ -BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const short ccw, const short check_flag) +BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_flag) { BMVert *v1, *v2; BMLoop *l1, *l2; @@ -1066,7 +1068,7 @@ BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const short ccw, const short check_ f_hflag_prev_2 = l2->f->head.hflag; /* don't delete the edge, manually remove the egde after so we can copy its attributes */ - f = BM_faces_join_pair(bm, l1->f, l2->f, NULL, TRUE); + f = BM_faces_join_pair(bm, l1->f, l2->f, NULL, true); if (f == NULL) { return NULL; @@ -1075,7 +1077,7 @@ BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const short ccw, const short check_ /* note, this assumes joining the faces _didnt_ also remove the verts. * the #BM_edge_rotate_check will ensure this, but its possibly corrupt state or future edits * break this */ - if (!BM_face_split(bm, f, v1, v2, NULL, NULL, TRUE)) { + if (!BM_face_split(bm, f, v1, v2, NULL, NULL, true)) { return NULL; } else { diff --git a/source/blender/bmesh/intern/bmesh_mods.h b/source/blender/bmesh/intern/bmesh_mods.h index 790f0cb6267..358268cb589 100644 --- a/source/blender/bmesh/intern/bmesh_mods.h +++ b/source/blender/bmesh/intern/bmesh_mods.h @@ -29,18 +29,18 @@ #include <stdio.h> -int BM_vert_dissolve(BMesh *bm, BMVert *v); +bool BM_vert_dissolve(BMesh *bm, BMVert *v); -int BM_disk_dissolve(BMesh *bm, BMVert *v); +bool BM_disk_dissolve(BMesh *bm, BMVert *v); -BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e, const short do_del); +BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e, const bool do_del); BMEdge *BM_verts_connect(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **r_f); BMFace *BM_face_split(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **r_l, - BMEdge *example, const short nodouble); + BMEdge *example, const bool no_double); BMFace *BM_face_split_n(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, @@ -48,25 +48,25 @@ BMFace *BM_face_split_n(BMesh *bm, BMFace *f, BMLoop **r_l, BMEdge *example); BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac, - const short join_faces, const short kill_degenerate_faces); + const bool join_faces, const bool kill_degenerate_faces); BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *ke, BMVert *kv, - const short kill_degenerate_faces); + const bool kill_degenerate_faces); BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float percent); BMVert *BM_edge_split_n(BMesh *bm, BMEdge *e, int numcuts); -int BM_face_validate(BMFace *face, FILE *err); +bool BM_face_validate(BMFace *face, FILE *err); -void BM_edge_calc_rotate(BMEdge *e, int ccw, +void BM_edge_calc_rotate(BMEdge *e, const bool ccw, BMLoop **r_l1, BMLoop **r_l2); -int BM_edge_rotate_check(BMEdge *e); -int BM_edge_rotate_check_degenerate(BMEdge *e, +bool BM_edge_rotate_check(BMEdge *e); +bool BM_edge_rotate_check_degenerate(BMEdge *e, BMLoop *l1, BMLoop *l2); -int BM_edge_rotate_check_beauty(BMEdge *e, +bool BM_edge_rotate_check_beauty(BMEdge *e, BMLoop *l1, BMLoop *l2); -BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const short ccw, const short check_flag); +BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_flag); /* flags for BM_edge_rotate */ enum { diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 8461ec6fe08..4147da82363 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -1536,27 +1536,6 @@ static BMOpDefine bmo_wireframe_def = { 0 }; -/* - * Vertex Slide. - * - * Translates verts along an edge - */ -static BMOpDefine bmo_slide_vert_def = { - "slide_vert", - /* slots_in */ - {{"vert", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BMO_OP_SLOT_SUBTYPE_ELEM_IS_SINGLE}}, - {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, - {"factor", BMO_OP_SLOT_FLT}, - {{'\0'}}, - }, - /* slots_out */ - {{"verts.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, - {{'\0'}}, - }, - bmo_slide_vert_exec, - BMO_OP_FLAG_UNTAN_MULTIRES -}; - #ifdef WITH_BULLET /* * Convex Hull @@ -1676,7 +1655,6 @@ const BMOpDefine *bmo_opdefines[] = { &bmo_similar_edges_def, &bmo_similar_faces_def, &bmo_similar_verts_def, - &bmo_slide_vert_def, &bmo_smooth_vert_def, &bmo_smooth_laplacian_vert_def, &bmo_solidify_def, diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h index b8fbfbee37f..fd6571d136e 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.h +++ b/source/blender/bmesh/intern/bmesh_operator_api.h @@ -244,19 +244,19 @@ void BMO_push(BMesh *bm, BMOperator *op); void BMO_pop(BMesh *bm); /*executes an operator*/ -int BMO_op_callf(BMesh *bm, const int flag, const char *fmt, ...); +bool BMO_op_callf(BMesh *bm, const int flag, const char *fmt, ...); /* initializes, but doesn't execute an operator. this is so you can * gain access to the outputs of the operator. note that you have * to execute/finish (BMO_op_exec and BMO_op_finish) yourself. */ -int BMO_op_initf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, ...); +bool BMO_op_initf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, ...); /* va_list version, used to implement the above two functions, * plus EDBM_op_callf in editmesh_utils.c. */ -int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, va_list vlist); +bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, va_list vlist); /* test whether a named slot exists */ -int BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier); +bool BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier); /* get a pointer to a slot. this may be removed layer on from the public API. */ BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier); @@ -301,8 +301,8 @@ void BMO_slot_float_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_ float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i); int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); -void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i); -int BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const bool i); +bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); void *BMO_slot_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int *len); @@ -360,11 +360,11 @@ void BMO_slot_buffer_flag_disable(BMesh *bm, /* tool-flags all elements inside an element slot array with flag flag. */ void BMO_slot_buffer_hflag_enable(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag, const char do_flush); + const char htype, const char hflag, const bool do_flush); /* clears tool-flag flag from all elements inside a slot array. */ void BMO_slot_buffer_hflag_disable(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag, const char do_flush); + const char htype, const char hflag, const bool do_flush); /* puts every element of type 'type' (which is a bitmask) with header * flag 'flag', into a slot. note: ignores hidden elements diff --git a/source/blender/bmesh/intern/bmesh_operator_api_inline.h b/source/blender/bmesh/intern/bmesh_operator_api_inline.h index ad116011421..053d70349e8 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api_inline.h +++ b/source/blender/bmesh/intern/bmesh_operator_api_inline.h @@ -80,7 +80,7 @@ BLI_INLINE void BMO_slot_map_bool_insert(BMOperator *op, BMOpSlot *slot, void *element, const int val) { BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL); - BLI_assert(val == FALSE || val == TRUE); + BLI_assert(val == false || val == true); BMO_slot_map_insert(op, slot, element, &val, sizeof(int)); } @@ -173,16 +173,16 @@ BLI_INLINE int BMO_slot_map_int_get(BMOpSlot *slot, const void *element) return 0; } -BLI_INLINE int BMO_slot_map_bool_get(BMOpSlot *slot, const void *element) +BLI_INLINE bool BMO_slot_map_bool_get(BMOpSlot *slot, const void *element) { int *val; BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL); val = (int *) BMO_slot_map_data_get(slot, element); - BLI_assert(val == NULL || *val == FALSE || *val == TRUE); - if (val) return *val; + BLI_assert(val == NULL || *val == false || *val == true); + if (val) return (bool)*val; - return 0; + return false; } BLI_INLINE void *BMO_slot_map_ptr_get(BMOpSlot *slot, const void *element) diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index fbf51b7dfdf..3308a014d25 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -238,7 +238,7 @@ void BMO_op_finish(BMesh *bm, BMOperator *op) * * \return Success if the slot if found. */ -int BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier) +bool BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier) { int slot_code = bmo_name_to_slotcode(slot_args, identifier); return (slot_code >= 0); @@ -390,7 +390,7 @@ void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_nam slot->data.i = i; } -void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i) +void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const bool i) { BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_BOOL); @@ -495,7 +495,7 @@ int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name return slot->data.i; } -int BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) +bool BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_BOOL); @@ -549,7 +549,7 @@ void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_nam */ static int bmo_mesh_flag_count(BMesh *bm, const char htype, const short oflag, - const short test_for_enabled) + const bool test_for_enabled) { const char iter_types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, @@ -562,7 +562,7 @@ static int bmo_mesh_flag_count(BMesh *bm, const char htype, const short oflag, BMElemF *ele_f; int i; - BLI_assert(ELEM(TRUE, FALSE, test_for_enabled)); + BLI_assert(ELEM(true, false, test_for_enabled)); for (i = 0; i < 3; i++) { if (htype & flag_types[i]) { @@ -579,12 +579,12 @@ static int bmo_mesh_flag_count(BMesh *bm, const char htype, const short oflag, int BMO_mesh_enabled_flag_count(BMesh *bm, const char htype, const short oflag) { - return bmo_mesh_flag_count(bm, htype, oflag, TRUE); + return bmo_mesh_flag_count(bm, htype, oflag, true); } int BMO_mesh_disabled_flag_count(BMesh *bm, const char htype, const short oflag) { - return bmo_mesh_flag_count(bm, htype, oflag, FALSE); + return bmo_mesh_flag_count(bm, htype, oflag, false); } void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char htype, const short oflag) @@ -795,14 +795,12 @@ void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_ */ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag, - const short test_for_enabled) + const bool test_for_enabled) { BMOpSlot *output = BMO_slot_get(slot_args, slot_name); int totelement = 0, i = 0; const int respecthide = (op->flag & BMO_FLAG_RESPECT_HIDE) != 0; - BLI_assert(ELEM(test_for_enabled, TRUE, FALSE)); - if (test_for_enabled) totelement = BM_mesh_elem_hflag_count_enabled(bm, htype, hflag, respecthide); else @@ -858,14 +856,14 @@ void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag) { - bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, TRUE); + bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, true); } void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag) { - bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, FALSE); + bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, false); } void BMO_slot_buffer_from_single(BMOperator *op, BMOpSlot *slot, BMHeader *ele) @@ -934,13 +932,13 @@ void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const cha static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag, - const short test_for_enabled) + const bool test_for_enabled) { BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); int totelement, i = 0; BLI_assert(op->slots_in == slot_args || op->slots_out == slot_args); - BLI_assert(ELEM(TRUE, FALSE, test_for_enabled)); + BLI_assert(ELEM(true, false, test_for_enabled)); if (test_for_enabled) totelement = BMO_mesh_enabled_flag_count(bm, htype, oflag); @@ -997,14 +995,14 @@ void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag) { - bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, TRUE); + bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, true); } void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag) { - bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, FALSE); + bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, false); } /** @@ -1015,13 +1013,13 @@ void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, */ void BMO_slot_buffer_hflag_enable(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag, const char do_flush) + const char htype, const char hflag, const bool do_flush) { BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BMElem **data = (BMElem **)slot->data.buf; int i; - const char do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT)); - const char do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN)); + const bool do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT)); + const bool do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN)); BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); @@ -1031,11 +1029,11 @@ void BMO_slot_buffer_hflag_enable(BMesh *bm, continue; if (do_flush_select) { - BM_elem_select_set(bm, *data, TRUE); + BM_elem_select_set(bm, *data, true); } if (do_flush_hide) { - BM_elem_hide_set(bm, *data, FALSE); + BM_elem_hide_set(bm, *data, false); } BM_elem_flag_enable(*data, hflag); @@ -1050,13 +1048,13 @@ void BMO_slot_buffer_hflag_enable(BMesh *bm, */ void BMO_slot_buffer_hflag_disable(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag, const char do_flush) + const char htype, const char hflag, const bool do_flush) { BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BMElem **data = (BMElem **)slot->data.buf; int i; - const char do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT)); - const char do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN)); + const bool do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT)); + const bool do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN)); BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); BLI_assert(((slot->slot_subtype.elem & BM_ALL_NOLOOP) & htype) == htype); @@ -1066,11 +1064,11 @@ void BMO_slot_buffer_hflag_disable(BMesh *bm, continue; if (do_flush_select) { - BM_elem_select_set(bm, *data, FALSE); + BM_elem_select_set(bm, *data, false); } if (do_flush_hide) { - BM_elem_hide_set(bm, *data, FALSE); + BM_elem_hide_set(bm, *data, false); } BM_elem_flag_disable(*data, hflag); @@ -1482,7 +1480,7 @@ void BMO_error_raise(BMesh *bm, BMOperator *owner, int errcode, const char *msg) BLI_addhead(&bm->errorstack, err); } -int BMO_error_occurred(BMesh *bm) +bool BMO_error_occurred(BMesh *bm) { return bm->errorstack.first != NULL; } @@ -1616,7 +1614,7 @@ static int bmo_opname_to_opcode(const char *opname) * Order is not important so `Hfev` is also valid (all unflagged verts, edges and faces). */ -int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, va_list vlist) +bool BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, va_list vlist) { // BMOpDefine *def; char *opname, *ofmt, *fmt; @@ -1653,7 +1651,7 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v if (i == -1) { MEM_freeN(ofmt); - return FALSE; + return false; } BMO_op_init(bm, op, flag, opname); @@ -1816,7 +1814,7 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v } MEM_freeN(ofmt); - return TRUE; + return true; error: /* non urgent todo - explain exactly what is failing */ @@ -1841,14 +1839,14 @@ error: MEM_freeN(ofmt); BMO_op_finish(bm, op); - return FALSE; + return false; #undef GOTO_ERROR } -int BMO_op_initf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, ...) +bool BMO_op_initf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, ...) { va_list list; @@ -1856,14 +1854,14 @@ int BMO_op_initf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, ... if (!BMO_op_vinitf(bm, op, flag, fmt, list)) { printf("%s: failed\n", __func__); va_end(list); - return FALSE; + return false; } va_end(list); - return TRUE; + return true; } -int BMO_op_callf(BMesh *bm, const int flag, const char *fmt, ...) +bool BMO_op_callf(BMesh *bm, const int flag, const char *fmt, ...) { va_list list; BMOperator op; @@ -1872,12 +1870,12 @@ int BMO_op_callf(BMesh *bm, const int flag, const char *fmt, ...) if (!BMO_op_vinitf(bm, &op, flag, fmt, list)) { printf("%s: failed, format is:\n \"%s\"\n", __func__, fmt); va_end(list); - return FALSE; + return false; } BMO_op_exec(bm, &op); BMO_op_finish(bm, &op); va_end(list); - return TRUE; + return true; } diff --git a/source/blender/bmesh/intern/bmesh_operators_private.h b/source/blender/bmesh/intern/bmesh_operators_private.h index 9175af1c822..ea9ad2ed151 100644 --- a/source/blender/bmesh/intern/bmesh_operators_private.h +++ b/source/blender/bmesh/intern/bmesh_operators_private.h @@ -89,7 +89,6 @@ void bmo_shortest_path_exec(BMesh *bm, BMOperator *op); void bmo_similar_edges_exec(BMesh *bm, BMOperator *op); void bmo_similar_faces_exec(BMesh *bm, BMOperator *op); void bmo_similar_verts_exec(BMesh *bm, BMOperator *op); -void bmo_slide_vert_exec(BMesh *bm, BMOperator *op); void bmo_smooth_vert_exec(BMesh *bm, BMOperator *op); void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op); void bmo_solidify_face_region_exec(BMesh *bm, BMOperator *op); diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 4545c9bb564..5c3d164c768 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -50,7 +50,7 @@ * Used for tessellator */ -static short testedgesidef(const float v1[2], const float v2[2], const float v3[2]) +static bool testedgesidef(const float v1[2], const float v2[2], const float v3[2]) { /* is v3 to the right of v1 - v2 ? With exception: v3 == v1 || v3 == v2 */ double inp; @@ -59,13 +59,13 @@ static short testedgesidef(const float v1[2], const float v2[2], const float v3[ inp = (v2[0] - v1[0]) * (v1[1] - v3[1]) + (v1[1] - v2[1]) * (v1[0] - v3[0]); if (inp < 0.0) { - return FALSE; + return false; } else if (inp == 0) { - if (v1[0] == v3[0] && v1[1] == v3[1]) return FALSE; - if (v2[0] == v3[0] && v2[1] == v3[1]) return FALSE; + if (v1[0] == v3[0] && v1[1] == v3[1]) return false; + if (v2[0] == v3[0] && v2[1] == v3[1]) return false; } - return TRUE; + return true; } /** @@ -319,7 +319,7 @@ void poly_rotate_plane(const float normal[3], float (*verts)[3], const int nvert if (angle < FLT_EPSILON) return; - if (len_v3(axis) < FLT_EPSILON) { + if (len_squared_v3(axis) < FLT_EPSILON) { axis[0] = 0.0f; axis[1] = 1.0f; axis[2] = 0.0f; @@ -498,7 +498,7 @@ void BM_face_normal_flip(BMesh *bm, BMFace *f) /* detects if two line segments cross each other (intersects). * note, there could be more winding cases then there needs to be. */ -static int line_crosses_v2f(const float v1[2], const float v2[2], const float v3[2], const float v4[2]) +static bool line_crosses_v2f(const float v1[2], const float v2[2], const float v3[2], const float v4[2]) { #define GETMIN2_AXIS(a, b, ma, mb, axis) \ @@ -526,7 +526,7 @@ static int line_crosses_v2f(const float v1[2], const float v2[2], const float v3 w5 = !testedgesidef(v3, v1, v4); if (w1 == w2 && w2 == w3 && w3 == w4 && w4 == w5) { - return TRUE; + return true; } GETMIN2(v1, v2, mv1, mv2); @@ -549,7 +549,7 @@ static int line_crosses_v2f(const float v1[2], const float v2[2], const float v3 return (mv4[1] >= mv1[1] && mv3[1] <= mv2[1]); } - return FALSE; + return false; #undef GETMIN2_AXIS #undef GETMIN2 @@ -567,7 +567,7 @@ static int line_crosses_v2f(const float v1[2], const float v2[2], const float v3 * instead of projecting co directly into f's orientation space, * so there might be accuracy issues. */ -int BM_face_point_inside_test(BMFace *f, const float co[3]) +bool BM_face_point_inside_test(BMFace *f, const float co[3]) { int ax, ay; float co2[2], cent[2] = {0.0f, 0.0f}, out[2] = {FLT_MAX * 0.5f, FLT_MAX * 0.5f}; @@ -614,7 +614,7 @@ int BM_face_point_inside_test(BMFace *f, const float co[3]) return crosses % 2 != 0; } -static int bm_face_goodline(float const (*projectverts)[3], BMFace *f, int v1i, int v2i, int v3i) +static bool bm_face_goodline(float const (*projectverts)[3], BMFace *f, int v1i, int v2i, int v3i) { BMLoop *l_iter; BMLoop *l_first; @@ -627,7 +627,7 @@ static int bm_face_goodline(float const (*projectverts)[3], BMFace *f, int v1i, /* v3 must be on the left side of [v1, v2] line, else we know [v1, v3] is outside of f! */ if (testedgesidef(v1, v2, v3)) { - return FALSE; + return false; } l_iter = l_first = BM_FACE_FIRST_LOOP(f); @@ -649,10 +649,10 @@ static int bm_face_goodline(float const (*projectverts)[3], BMFace *f, int v1i, else printf("%d in (%d, %d, %d)\n", v1i, i, v3i, v2i); #endif - return FALSE; + return false; } } while ((l_iter = l_iter->next) != l_first); - return TRUE; + return true; } /** @@ -665,7 +665,7 @@ static int bm_face_goodline(float const (*projectverts)[3], BMFace *f, int v1i, * \param abscoss Must be allocated by caller, and at least f->len length * (allow to avoid allocating a new one for each tri!). */ -static BMLoop *find_ear(BMFace *f, float (*verts)[3], const int use_beauty, float *abscoss) +static BMLoop *find_ear(BMFace *f, float (*verts)[3], const bool use_beauty, float *abscoss) { BMLoop *bestear = NULL; @@ -726,7 +726,8 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], const int use_beauty, floa /* float angle, bestangle = 180.0f; */ float cos, tcos, bestcos = 1.0f; float *tcoss; - int isear, i = 0, j, len; + bool is_ear; + int i = 0, j, len; /* Compute cos of all corners! */ l_iter = l_first = BM_FACE_FIRST_LOOP(f); @@ -745,7 +746,7 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], const int use_beauty, floa l_iter = l_first; tcoss = abscoss; do { - isear = TRUE; + is_ear = true; v1 = l_iter->prev->v; v2 = l_iter->v; @@ -753,7 +754,7 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], const int use_beauty, floa /* We may have already internal edges... */ if (BM_edge_exists(v1, v3)) { - isear = FALSE; + is_ear = false; } else if (!bm_face_goodline((float const (*)[3])verts, f, BM_elem_index_get(v1), BM_elem_index_get(v2), BM_elem_index_get(v3))) @@ -762,10 +763,10 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], const int use_beauty, floa printf("(%d, %d, %d) would not be a valid tri!\n", BM_elem_index_get(v1), BM_elem_index_get(v2), BM_elem_index_get(v3)); #endif - isear = FALSE; + is_ear = false; } - if (isear) { + if (is_ear) { #if 0 /* Old, already commented code */ /* if this code comes back, it needs to be converted to radians */ angle = angle_v3v3v3(verts[v1->head.eflag2], verts[v2->head.eflag2], verts[v3->head.eflag2]); @@ -845,9 +846,10 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], const int use_beauty, floa * \note newedgeflag sets a flag layer flag, obviously not the header flag. */ void BM_face_triangulate(BMesh *bm, BMFace *f, float (*projectverts)[3], const short newedge_oflag, - const short newface_oflag, BMFace **newfaces, const short use_beauty) + const short newface_oflag, BMFace **newfaces, const bool use_beauty) { - int i, done, nvert, nf_i = 0; + int i, nvert, nf_i = 0; + bool done; BMLoop *newl; BMLoop *l_iter; BMLoop *l_first; @@ -877,14 +879,20 @@ void BM_face_triangulate(BMesh *bm, BMFace *f, float (*projectverts)[3], const s projectverts[i][2] = 0.0f; } - done = FALSE; + done = false; while (!done && f->len > 3) { - done = TRUE; + done = true; l_iter = find_ear(f, projectverts, use_beauty, abscoss); - if (l_iter) { - done = FALSE; + + /* force triangulation - if we can't find an ear the face is degenerate */ + if (l_iter == NULL) { + l_iter = BM_FACE_FIRST_LOOP(f); + } + + { + done = false; /* printf("Subdividing face...\n");*/ - f = BM_face_split(bm, l_iter->f, l_iter->prev->v, l_iter->next->v, &newl, NULL, TRUE); + f = BM_face_split(bm, l_iter->f, l_iter->prev->v, l_iter->next->v, &newl, NULL, true); if (UNLIKELY(!f)) { fprintf(stderr, "%s: triangulator failed to split face! (bmesh internal error)\n", __func__); @@ -912,13 +920,15 @@ void BM_face_triangulate(BMesh *bm, BMFace *f, float (*projectverts)[3], const s } } + BLI_assert(f->len == 3); + #if 0 /* XXX find_ear should now always return a corner, so no more need for this piece of code... */ if (f->len > 3) { l_iter = BM_FACE_FIRST_LOOP(f); while (l_iter->f->len > 3) { nextloop = l_iter->next->next; f = BM_face_split(bm, l_iter->f, l_iter->v, nextloop->v, - &newl, NULL, TRUE); + &newl, NULL, true); if (!f) { printf("triangle fan step of triangulator failed.\n"); @@ -1078,3 +1088,37 @@ void BM_face_legal_splits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len) } } } + + +/** + * Small utility functions for fast access + * + * faster alternative to: + * BM_iter_as_array(bm, BM_VERTS_OF_FACE, f, (void**)v, 3); + */ +void BM_face_as_array_vert_tri(BMFace *f, BMVert *r_verts[3]) +{ + BMLoop *l = BM_FACE_FIRST_LOOP(f); + + BLI_assert(f->len == 3); + + r_verts[0] = l->v; l = l->next; + r_verts[1] = l->v; l = l->next; + r_verts[2] = l->v; +} + +/** + * faster alternative to: + * BM_iter_as_array(bm, BM_VERTS_OF_FACE, f, (void**)v, 4); + */ +void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4]) +{ + BMLoop *l = BM_FACE_FIRST_LOOP(f); + + BLI_assert(f->len == 4); + + r_verts[0] = l->v; l = l->next; + r_verts[1] = l->v; l = l->next; + r_verts[2] = l->v; l = l->next; + r_verts[3] = l->v; +} diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h index e5777d3611b..a0c6ac5eeaa 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.h +++ b/source/blender/bmesh/intern/bmesh_polygon.h @@ -42,12 +42,15 @@ void BM_vert_normal_update(BMVert *v); void BM_vert_normal_update_all(BMVert *v); void BM_face_normal_flip(BMesh *bm, BMFace *f); -int BM_face_point_inside_test(BMFace *f, const float co[3]); +bool BM_face_point_inside_test(BMFace *f, const float co[3]); void BM_face_triangulate(BMesh *bm, BMFace *f, float (*projectverts)[3], const short newedge_oflag, const short newface_oflag, BMFace **newfaces, - const short use_beauty); + const bool use_beauty); void BM_face_legal_splits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len); +void BM_face_as_array_vert_tri(BMFace *f, BMVert *r_verts[3]); +void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4]); + #endif /* __BMESH_POLYGON_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index b5b6c69bd7e..7ed23aaf1f8 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -43,7 +43,7 @@ * Returns whether or not a given vertex is * is part of a given edge. */ -int BM_vert_in_edge(BMEdge *e, BMVert *v) +bool BM_vert_in_edge(BMEdge *e, BMVert *v) { return bmesh_vert_in_edge(e, v); } @@ -208,9 +208,9 @@ BMLoop *BM_vert_find_first_loop(BMVert *v) } /** - * Returns TRUE if the vertex is used in a given face. + * Returns true if the vertex is used in a given face. */ -int BM_vert_in_face(BMFace *f, BMVert *v) +bool BM_vert_in_face(BMFace *f, BMVert *v) { BMLoop *l_iter, *l_first; @@ -226,19 +226,19 @@ int BM_vert_in_face(BMFace *f, BMVert *v) #endif do { if (l_iter->v == v) { - return TRUE; + return true; } } while ((l_iter = l_iter->next) != l_first); } - return FALSE; + return false; } /** * Compares the number of vertices in an array * that appear in a given face */ -int BM_verts_in_face(BMFace *f, BMVert **varr, int len) +int BM_verts_in_face_count(BMFace *f, BMVert **varr, int len) { BMLoop *l_iter, *l_first; @@ -278,10 +278,64 @@ int BM_verts_in_face(BMFace *f, BMVert **varr, int len) return count; } + +/** + * Return true if all verts are in the face. + */ +bool BM_verts_in_face(BMFace *f, BMVert **varr, int len) +{ + BMLoop *l_iter, *l_first; + +#ifdef USE_BMESH_HOLES + BMLoopList *lst; +#endif + + int i; + bool ok = true; + + /* simple check, we know can't succeed */ + if (f->len < len) { + return false; + } + + for (i = 0; i < len; i++) { + BM_ELEM_API_FLAG_ENABLE(varr[i], _FLAG_OVERLAP); + } + +#ifdef USE_BMESH_HOLES + for (lst = f->loops.first; lst; lst = lst->next) +#endif + { + +#ifdef USE_BMESH_HOLES + l_iter = l_first = lst->first; +#else + l_iter = l_first = f->l_first; +#endif + + do { + if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP)) { + /* pass */ + } + else { + ok = false; + break; + } + + } while ((l_iter = l_iter->next) != l_first); + } + + for (i = 0; i < len; i++) { + BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP); + } + + return ok; +} + /** * Returns whether or not a given edge is is part of a given face. */ -int BM_edge_in_face(BMFace *f, BMEdge *e) +bool BM_edge_in_face(BMFace *f, BMEdge *e) { BMLoop *l_iter; BMLoop *l_first; @@ -290,17 +344,17 @@ int BM_edge_in_face(BMFace *f, BMEdge *e) do { if (l_iter->e == e) { - return TRUE; + return true; } } while ((l_iter = l_iter->next) != l_first); - return FALSE; + return false; } /** * Returns whether or not a given edge is is part of a given loop. */ -int BM_edge_in_loop(BMEdge *e, BMLoop *l) +bool BM_edge_in_loop(BMEdge *e, BMLoop *l) { return (l->e == e || l->prev->e == e); } @@ -309,7 +363,7 @@ int BM_edge_in_loop(BMEdge *e, BMLoop *l) * Returns whether or not two vertices are in * a given edge */ -int BM_verts_in_edge(BMVert *v1, BMVert *v2, BMEdge *e) +bool BM_verts_in_edge(BMVert *v1, BMVert *v2, BMEdge *e) { return bmesh_verts_in_edge(v1, v2, e); } @@ -487,9 +541,9 @@ float BM_edge_calc_length_squared(BMEdge *e) * Utility function, since enough times we have an edge * and want to access 2 connected faces. * - * \return TRUE when only 2 faces are found. + * \return true when only 2 faces are found. */ -int BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb) +bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb) { BMLoop *la, *lb; @@ -500,12 +554,12 @@ int BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb) { *r_fa = la->f; *r_fb = lb->f; - return TRUE; + return true; } else { *r_fa = NULL; *r_fb = NULL; - return FALSE; + return false; } } @@ -513,9 +567,9 @@ int BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb) * Utility function, since enough times we have an edge * and want to access 2 connected loops. * - * \return TRUE when only 2 faces are found. + * \return true when only 2 faces are found. */ -int BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb) +bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb) { BMLoop *la, *lb; @@ -526,12 +580,12 @@ int BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb) { *r_la = la; *r_lb = lb; - return TRUE; + return true; } else { *r_la = NULL; *r_lb = NULL; - return FALSE; + return false; } } @@ -589,7 +643,7 @@ int BM_vert_face_count(BMVert *v) * Tests whether or not the vertex is part of a wire edge. * (ie: has no faces attached to it) */ -int BM_vert_is_wire(BMVert *v) +bool BM_vert_is_wire(BMVert *v) { if (v->e) { BMEdge *e_first, *e_iter; @@ -597,14 +651,14 @@ int BM_vert_is_wire(BMVert *v) e_first = e_iter = v->e; do { if (e_iter->l) { - return FALSE; + return false; } } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); - return TRUE; + return true; } else { - return FALSE; + return false; } } @@ -612,9 +666,9 @@ int BM_vert_is_wire(BMVert *v) * Tests whether or not the edge is part of a wire. * (ie: has no faces attached to it) */ -int BM_edge_is_wire(BMEdge *e) +bool BM_edge_is_wire(BMEdge *e) { - return (e->l) ? FALSE : TRUE; + return (e->l == NULL); } /** @@ -624,7 +678,7 @@ int BM_edge_is_wire(BMEdge *e) * 3: Is part of a an edge with more than 2 faces. * 4: Is part of a wire edge. */ -int BM_vert_is_manifold(BMVert *v) +bool BM_vert_is_manifold(BMVert *v) { BMEdge *e, *oe; BMLoop *l; @@ -632,7 +686,7 @@ int BM_vert_is_manifold(BMVert *v) if (v->e == NULL) { /* loose vert */ - return FALSE; + return false; } /* count edges while looking for non-manifold edges */ @@ -643,7 +697,7 @@ int BM_vert_is_manifold(BMVert *v) * edges with 1 face user are OK, otherwise we could * use BM_edge_is_manifold() here */ if (e->l == NULL || bmesh_radial_length(e->l) > 2) { - return FALSE; + return false; } len++; } while ((e = bmesh_disk_edge_next(e, v)) != oe); @@ -677,10 +731,10 @@ int BM_vert_is_manifold(BMVert *v) if (count < len) { /* vert shared by multiple regions */ - return FALSE; + return false; } - return TRUE; + return true; } /** @@ -689,7 +743,7 @@ int BM_vert_is_manifold(BMVert *v) */ #if 1 /* fast path for checking manifold */ -int BM_edge_is_manifold(BMEdge *e) +bool BM_edge_is_manifold(BMEdge *e) { const BMLoop *l = e->l; return (l && (l->radial_next != l) && /* not 0 or 1 face users */ @@ -700,10 +754,10 @@ int BM_edge_is_manifold(BMEdge *e) { int count = BM_edge_face_count(e); if (count == 2) { - return TRUE; + return true; } else { - return FALSE; + return false; } } #endif @@ -714,7 +768,7 @@ int BM_edge_is_manifold(BMEdge *e) */ #if 1 /* fast path for checking boundary */ -int BM_edge_is_boundary(BMEdge *e) +bool BM_edge_is_boundary(BMEdge *e) { const BMLoop *l = e->l; return (l && (l->radial_next == l)); @@ -724,10 +778,10 @@ int BM_edge_is_boundary(BMEdge *e) { int count = BM_edge_face_count(e); if (count == 1) { - return TRUE; + return true; } else { - return FALSE; + return false; } } #endif @@ -757,7 +811,7 @@ int BM_face_share_face_count(BMFace *f1, BMFace *f2) /** * same as #BM_face_share_face_count but returns a bool */ -int BM_face_share_face_check(BMFace *f1, BMFace *f2) +bool BM_face_share_face_check(BMFace *f1, BMFace *f2) { BMIter iter1, iter2; BMEdge *e; @@ -766,11 +820,11 @@ int BM_face_share_face_check(BMFace *f1, BMFace *f2) BM_ITER_ELEM (e, &iter1, f1, BM_EDGES_OF_FACE) { BM_ITER_ELEM (f, &iter2, e, BM_FACES_OF_EDGE) { if (f != f1 && f != f2 && BM_face_share_edge_check(f, f2)) - return TRUE; + return true; } } - return FALSE; + return false; } /** @@ -793,9 +847,9 @@ int BM_face_share_edge_count(BMFace *f1, BMFace *f2) } /** - * Returns TRUE if the faces share an edge + * Returns true if the faces share an edge */ -int BM_face_share_edge_check(BMFace *f1, BMFace *f2) +bool BM_face_share_edge_check(BMFace *f1, BMFace *f2) { BMLoop *l_iter; BMLoop *l_first; @@ -803,17 +857,17 @@ int BM_face_share_edge_check(BMFace *f1, BMFace *f2) l_iter = l_first = BM_FACE_FIRST_LOOP(f1); do { if (bmesh_radial_face_find(l_iter->e, f2)) { - return TRUE; + return true; } } while ((l_iter = l_iter->next) != l_first); - return FALSE; + return false; } /** - * Test if e1 shares any faces with e2 + * Test if e1 shares any faces with e2 */ -int BM_edge_share_face_check(BMEdge *e1, BMEdge *e2) +bool BM_edge_share_face_check(BMEdge *e1, BMEdge *e2) { BMLoop *l; BMFace *f; @@ -823,18 +877,18 @@ int BM_edge_share_face_check(BMEdge *e1, BMEdge *e2) do { f = l->f; if (bmesh_radial_face_find(e2, f)) { - return TRUE; + return true; } l = l->radial_next; } while (l != e1->l); } - return FALSE; + return false; } /** * Test if e1 shares any quad faces with e2 */ -int BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2) +bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2) { BMLoop *l; BMFace *f; @@ -845,19 +899,19 @@ int BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2) f = l->f; if (f->len == 4) { if (bmesh_radial_face_find(e2, f)) { - return TRUE; + return true; } } l = l->radial_next; } while (l != e1->l); } - return FALSE; + return false; } /** * Tests to see if e1 shares a vertex with e2 */ -int BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2) +bool BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2) { return (e1->v1 == e2->v1 || e1->v1 == e2->v2 || @@ -1007,7 +1061,7 @@ void BM_loop_calc_face_tangent(BMLoop *l, float r_tangent[3]) normalize_v3(v_prev); normalize_v3(v_next); - if (compare_v3v3(v_prev, v_next, FLT_EPSILON) == FALSE) { + if (compare_v3v3(v_prev, v_next, FLT_EPSILON) == false) { float dir[3]; float nor[3]; /* for this purpose doesn't need to be normalized */ add_v3_v3v3(dir, v_prev, v_next); @@ -1273,67 +1327,94 @@ BMEdge *BM_edge_find_double(BMEdge *e) } /** - * Given a set of vertices \a varr, find out if - * all those vertices overlap an existing face. - * - * \note Making a face here is valid but in some cases you wont want to - * make a face thats part of another. - * - * \returns TRUE for overlap + * Given a set of vertices (varr), find out if + * there is a face with exactly those vertices + * (and only those vertices). * + * \note there used to be a BM_face_exists_overlap function that checked for partial overlap, + * however this is no longer used, simple to add back. */ -int BM_face_exists_overlap(BMVert **varr, int len, BMFace **r_overlapface) +bool BM_face_exists(BMVert **varr, int len, BMFace **r_existface) { + BMVert *v_search = varr[0]; /* we can search any of the verts in the array */ BMIter viter; BMFace *f; - int i, amount; - for (i = 0; i < len; i++) { - BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) { - amount = BM_verts_in_face(f, varr, len); - if (amount >= len) { - if (r_overlapface) { - *r_overlapface = f; + +#if 0 + BM_ITER_ELEM (f, &viter, v_search, BM_FACES_OF_VERT) { + if (f->len == len) { + if (BM_verts_in_face(f, varr, len)) { + if (r_existface) { + *r_existface = f; } - return TRUE; + return true; } } } - if (r_overlapface) { - *r_overlapface = NULL; + if (r_existface) { + *r_existface = NULL; } + return false; - return FALSE; -} +#else -/** - * Given a set of vertices (varr), find out if - * there is a face with exactly those vertices - * (and only those vertices). - */ -int BM_face_exists(BMVert **varr, int len, BMFace **r_existface) -{ - BMIter viter; - BMFace *f; - int i, amount; + /* faster to do the flagging once, and inline */ + bool is_init = false; + bool is_found = false; + int i; - for (i = 0; i < len; i++) { - BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) { - amount = BM_verts_in_face(f, varr, len); - if (amount == len && amount == f->len) { + + BM_ITER_ELEM (f, &viter, v_search, BM_FACES_OF_VERT) { + if (f->len == len) { + if (is_init == false) { + is_init = true; + for (i = 0; i < len; i++) { + BLI_assert(!BM_ELEM_API_FLAG_TEST(varr[i], _FLAG_OVERLAP)); + BM_ELEM_API_FLAG_ENABLE(varr[i], _FLAG_OVERLAP); + } + } + + is_found = true; + + { + BMLoop *l_iter; + BMLoop *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + + do { + if (!BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP)) { + is_found = false; + break; + } + } while ((l_iter = l_iter->next) != l_first); + } + + if (is_found) { if (r_existface) { *r_existface = f; } - return TRUE; + break; } } } - if (r_existface) { - *r_existface = NULL; + if (is_found == false) { + if (r_existface) { + *r_existface = NULL; + } } - return FALSE; + + if (is_init == true) { + for (i = 0; i < len; i++) { + BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP); + } + } + + return is_found; +#endif } @@ -1349,12 +1430,12 @@ int BM_face_exists(BMVert **varr, int len, BMFace **r_existface) * * \a earr and \a varr can be in any order, however they _must_ form a closed loop. */ -int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len) +bool BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len) { BMFace *f; BMEdge *e; BMVert *v; - int ok; + bool ok; int tot_tag; BMIter fiter; @@ -1394,10 +1475,10 @@ int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len) for (i = 0; i < len; i++) { BM_ITER_ELEM (f, &fiter, earr[i], BM_FACES_OF_EDGE) { if (!BM_elem_flag_test(f, BM_ELEM_INTERNAL_TAG)) { - ok = TRUE; + ok = true; BM_ITER_ELEM (v, &viter, f, BM_VERTS_OF_FACE) { if (!BM_elem_flag_test(v, BM_ELEM_INTERNAL_TAG)) { - ok = FALSE; + ok = false; break; } } @@ -1416,20 +1497,20 @@ int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len) if (tot_tag == 0) { /* no faces use only boundary verts, quit early */ - return FALSE; + return false; } /* 2) loop over non-boundary edges that use boundary verts, * check each have 2 tagges faces connected (faces that only use 'varr' verts) */ - ok = TRUE; + ok = true; for (i = 0; i < len; i++) { BM_ITER_ELEM (e, &fiter, varr[i], BM_EDGES_OF_VERT) { if (/* non-boundary edge */ - BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG) == FALSE && + BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG) == false && /* ...using boundary verts */ - BM_elem_flag_test(e->v1, BM_ELEM_INTERNAL_TAG) == TRUE && - BM_elem_flag_test(e->v2, BM_ELEM_INTERNAL_TAG) == TRUE) + BM_elem_flag_test(e->v1, BM_ELEM_INTERNAL_TAG) == true && + BM_elem_flag_test(e->v2, BM_ELEM_INTERNAL_TAG) == true) { int tot_face_tag = 0; BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) { @@ -1439,14 +1520,14 @@ int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len) } if (tot_face_tag != 2) { - ok = FALSE; + ok = false; break; } } } - if (ok == FALSE) { + if (ok == false) { break; } } @@ -1455,25 +1536,25 @@ int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len) } /* same as 'BM_face_exists_multi' but built vert array from edges */ -int BM_face_exists_multi_edge(BMEdge **earr, int len) +bool BM_face_exists_multi_edge(BMEdge **earr, int len) { BMVert **varr = BLI_array_alloca(varr, len); - int ok; + bool ok; int i, i_next; /* first check if verts have edges, if not we can bail out early */ - ok = TRUE; + ok = true; for (i = len - 1, i_next = 0; i_next < len; (i = i_next++)) { if (!(varr[i] = BM_edge_share_vert(earr[i], earr[i_next]))) { - ok = FALSE; + ok = false; break; } } - if (ok == FALSE) { + if (ok == false) { BMESH_ASSERT(0); - return FALSE; + return false; } ok = BM_face_exists_multi(varr, earr, len); @@ -1482,13 +1563,13 @@ int BM_face_exists_multi_edge(BMEdge **earr, int len) } /* convenience functions for checking flags */ -int BM_edge_is_any_vert_flag_test(BMEdge *e, const char hflag) +bool BM_edge_is_any_vert_flag_test(BMEdge *e, const char hflag) { return (BM_elem_flag_test(e->v1, hflag) || BM_elem_flag_test(e->v2, hflag)); } -int BM_face_is_any_vert_flag_test(BMFace *f, const char hflag) +bool BM_face_is_any_vert_flag_test(BMFace *f, const char hflag) { BMLoop *l_iter; BMLoop *l_first; @@ -1496,13 +1577,13 @@ int BM_face_is_any_vert_flag_test(BMFace *f, const char hflag) l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { if (BM_elem_flag_test(l_iter->v, hflag)) { - return TRUE; + return true; } } while ((l_iter = l_iter->next) != l_first); - return FALSE; + return false; } -int BM_face_is_any_edge_flag_test(BMFace *f, const char hflag) +bool BM_face_is_any_edge_flag_test(BMFace *f, const char hflag) { BMLoop *l_iter; BMLoop *l_first; @@ -1510,8 +1591,8 @@ int BM_face_is_any_edge_flag_test(BMFace *f, const char hflag) l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { if (BM_elem_flag_test(l_iter->e, hflag)) { - return TRUE; + return true; } } while ((l_iter = l_iter->next) != l_first); - return FALSE; + return false; } diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index a9d6719c491..9892700162e 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -27,19 +27,20 @@ * \ingroup bmesh */ -int BM_vert_in_face(BMFace *f, BMVert *v); -int BM_verts_in_face(BMFace *f, BMVert **varr, int len); +bool BM_vert_in_face(BMFace *f, BMVert *v); +int BM_verts_in_face_count(BMFace *f, BMVert **varr, int len); +bool BM_verts_in_face(BMFace *f, BMVert **varr, int len); -int BM_edge_in_face(BMFace *f, BMEdge *e); -int BM_edge_in_loop(BMEdge *e, BMLoop *l); +bool BM_edge_in_face(BMFace *f, BMEdge *e); +bool BM_edge_in_loop(BMEdge *e, BMLoop *l); -int BM_vert_in_edge(BMEdge *e, BMVert *v); -int BM_verts_in_edge(BMVert *v1, BMVert *v2, BMEdge *e); +bool BM_vert_in_edge(BMEdge *e, BMVert *v); +bool BM_verts_in_edge(BMVert *v1, BMVert *v2, BMEdge *e); float BM_edge_calc_length(BMEdge *e); float BM_edge_calc_length_squared(BMEdge *e); -int BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb); -int BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb); +bool BM_edge_face_pair(BMEdge *e, BMFace **r_fa, BMFace **r_fb); +bool BM_edge_loop_pair(BMEdge *e, BMLoop **r_la, BMLoop **r_lb); BMVert *BM_edge_other_vert(BMEdge *e, BMVert *v); BMLoop *BM_edge_other_loop(BMEdge *e, BMLoop *l); BMLoop *BM_face_other_edge_loop(BMFace *f, BMEdge *e, BMVert *v); @@ -54,12 +55,12 @@ int BM_edge_face_count(BMEdge *e); int BM_vert_face_count(BMVert *v); BMEdge *BM_vert_other_disk_edge(BMVert *v, BMEdge *e); -int BM_vert_is_wire(BMVert *v); -int BM_edge_is_wire(BMEdge *e); +bool BM_vert_is_wire(BMVert *v); +bool BM_edge_is_wire(BMEdge *e); -int BM_vert_is_manifold(BMVert *v); -int BM_edge_is_manifold(BMEdge *e); -int BM_edge_is_boundary(BMEdge *e); +bool BM_vert_is_manifold(BMVert *v); +bool BM_edge_is_manifold(BMEdge *e); +bool BM_edge_is_boundary(BMEdge *e); float BM_loop_calc_face_angle(BMLoop *l); void BM_loop_calc_face_normal(BMLoop *l, float r_normal[3]); @@ -79,21 +80,19 @@ BMLoop *BM_face_find_longest_loop(BMFace *f); BMEdge *BM_edge_exists(BMVert *v1, BMVert *v2); BMEdge *BM_edge_find_double(BMEdge *e); -int BM_face_exists_overlap(BMVert **varr, int len, BMFace **r_existface); +bool BM_face_exists(BMVert **varr, int len, BMFace **r_existface); -int BM_face_exists(BMVert **varr, int len, BMFace **r_existface); - -int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len); -int BM_face_exists_multi_edge(BMEdge **earr, int len); +bool BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len); +bool BM_face_exists_multi_edge(BMEdge **earr, int len); int BM_face_share_face_count(BMFace *f1, BMFace *f2); int BM_face_share_edge_count(BMFace *f1, BMFace *f2); -int BM_face_share_face_check(BMFace *f1, BMFace *f2); -int BM_face_share_edge_check(BMFace *f1, BMFace *f2); -int BM_edge_share_face_check(BMEdge *e1, BMEdge *e2); -int BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2); -int BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2); +bool BM_face_share_face_check(BMFace *f1, BMFace *f2); +bool BM_face_share_edge_check(BMFace *f1, BMFace *f2); +bool BM_edge_share_face_check(BMEdge *e1, BMEdge *e2); +bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2); +bool BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2); BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2); BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v); @@ -103,8 +102,8 @@ void BM_edge_ordered_verts(BMEdge *edge, BMVert **r_v1, BMVert **r_v2); void BM_edge_ordered_verts_ex(BMEdge *edge, BMVert **r_v1, BMVert **r_v2, BMLoop *edge_loop); -int BM_edge_is_any_vert_flag_test(BMEdge *e, const char hflag); -int BM_face_is_any_vert_flag_test(BMFace *f, const char hflag); -int BM_face_is_any_edge_flag_test(BMFace *f, const char hflag); +bool BM_edge_is_any_vert_flag_test(BMEdge *e, const char hflag); +bool BM_face_is_any_vert_flag_test(BMFace *f, const char hflag); +bool BM_face_is_any_edge_flag_test(BMFace *f, const char hflag); #endif /* __BMESH_QUERIES_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_structure.c b/source/blender/bmesh/intern/bmesh_structure.c index b58e61a3066..2f568a498c5 100644 --- a/source/blender/bmesh/intern/bmesh_structure.c +++ b/source/blender/bmesh/intern/bmesh_structure.c @@ -40,16 +40,16 @@ * MISC utility functions. */ -int bmesh_vert_in_edge(BMEdge *e, BMVert *v) +bool bmesh_vert_in_edge(BMEdge *e, BMVert *v) { - if (e->v1 == v || e->v2 == v) return TRUE; - return FALSE; + if (e->v1 == v || e->v2 == v) return true; + return false; } -int bmesh_verts_in_edge(BMVert *v1, BMVert *v2, BMEdge *e) +bool bmesh_verts_in_edge(BMVert *v1, BMVert *v2, BMEdge *e) { - if (e->v1 == v1 && e->v2 == v2) return TRUE; - else if (e->v1 == v2 && e->v2 == v1) return TRUE; - return FALSE; + if (e->v1 == v1 && e->v2 == v2) return true; + else if (e->v1 == v2 && e->v2 == v1) return true; + return false; } BMVert *bmesh_edge_other_vert_get(BMEdge *e, BMVert *v) @@ -63,19 +63,19 @@ BMVert *bmesh_edge_other_vert_get(BMEdge *e, BMVert *v) return NULL; } -int bmesh_edge_swapverts(BMEdge *e, BMVert *orig, BMVert *newv) +bool bmesh_edge_swapverts(BMEdge *e, BMVert *orig, BMVert *newv) { if (e->v1 == orig) { e->v1 = newv; e->v1_disk_link.next = e->v1_disk_link.prev = NULL; - return TRUE; + return true; } else if (e->v2 == orig) { e->v2 = newv; e->v2_disk_link.next = e->v2_disk_link.prev = NULL; - return TRUE; + return true; } - return FALSE; + return false; } /** @@ -165,7 +165,7 @@ BLI_INLINE BMDiskLink *bmesh_disk_edge_link_from_vert(BMEdge *e, BMVert *v) } } -int bmesh_disk_edge_append(BMEdge *e, BMVert *v) +void bmesh_disk_edge_append(BMEdge *e, BMVert *v) { if (!v->e) { BMDiskLink *dl1 = bmesh_disk_edge_link_from_vert(e, v); @@ -187,8 +187,6 @@ int bmesh_disk_edge_append(BMEdge *e, BMVert *v) if (dl3) dl3->next = e; } - - return TRUE; } void bmesh_disk_edge_remove(BMEdge *e, BMVert *v) @@ -280,23 +278,23 @@ int bmesh_disk_count(BMVert *v) } } -int bmesh_disk_validate(int len, BMEdge *e, BMVert *v) +bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v) { BMEdge *e_iter; if (!BM_vert_in_edge(e, v)) - return FALSE; + return false; if (bmesh_disk_count(v) != len || len == 0) - return FALSE; + return false; e_iter = e; do { if (len != 1 && bmesh_disk_edge_prev(e_iter, v) == e_iter) { - return FALSE; + return false; } } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e); - return TRUE; + return true; } /** @@ -362,34 +360,34 @@ BMEdge *bmesh_disk_faceedge_find_next(BMEdge *e, BMVert *v) } /*****radial cycle functions, e.g. loops surrounding edges**** */ -int bmesh_radial_validate(int radlen, BMLoop *l) +bool bmesh_radial_validate(int radlen, BMLoop *l) { BMLoop *l_iter = l; int i = 0; if (bmesh_radial_length(l) != radlen) - return FALSE; + return false; do { if (UNLIKELY(!l_iter)) { BMESH_ASSERT(0); - return FALSE; + return false; } if (l_iter->e != l->e) - return FALSE; + return false; if (l_iter->v != l->e->v1 && l_iter->v != l->e->v2) - return FALSE; + return false; if (UNLIKELY(i > BM_LOOP_RADIAL_MAX)) { BMESH_ASSERT(0); - return FALSE; + return false; } i++; } while ((l_iter = l_iter->radial_next) != l); - return TRUE; + return true; } /** @@ -511,7 +509,7 @@ void bmesh_radial_append(BMEdge *e, BMLoop *l) l->e = e; } -int bmesh_radial_face_find(BMEdge *e, BMFace *f) +bool bmesh_radial_face_find(BMEdge *e, BMFace *f) { BMLoop *l_iter; int i, len; @@ -519,9 +517,9 @@ int bmesh_radial_face_find(BMEdge *e, BMFace *f) len = bmesh_radial_length(e->l); for (i = 0, l_iter = e->l; i < len; i++, l_iter = l_iter->radial_next) { if (l_iter->f == f) - return TRUE; + return true; } - return FALSE; + return false; } /** @@ -545,7 +543,7 @@ int bmesh_radial_facevert_count(BMLoop *l, BMVert *v) } /*****loop cycle functions, e.g. loops surrounding a face**** */ -int bmesh_loop_validate(BMFace *f) +bool bmesh_loop_validate(BMFace *f) { int i; int len = f->len; @@ -554,7 +552,7 @@ int bmesh_loop_validate(BMFace *f) l_first = BM_FACE_FIRST_LOOP(f); if (l_first == NULL) { - return FALSE; + return false; } /* Validate that the face loop cycle is the length specified by f->len */ @@ -562,22 +560,22 @@ int bmesh_loop_validate(BMFace *f) if ((l_iter->f != f) || (l_iter == l_first)) { - return FALSE; + return false; } } if (l_iter != l_first) { - return FALSE; + return false; } /* Validate the loop->prev links also form a cycle of length f->len */ for (i = 1, l_iter = l_first->prev; i < len; i++, l_iter = l_iter->prev) { if (l_iter == l_first) { - return FALSE; + return false; } } if (l_iter != l_first) { - return FALSE; + return false; } - return TRUE; + return true; } diff --git a/source/blender/bmesh/intern/bmesh_structure.h b/source/blender/bmesh/intern/bmesh_structure.h index b19df4660b8..e67f1e4fb49 100644 --- a/source/blender/bmesh/intern/bmesh_structure.h +++ b/source/blender/bmesh/intern/bmesh_structure.h @@ -42,10 +42,10 @@ struct ListBase; /* LOOP CYCLE MANAGEMENT */ -int bmesh_loop_validate(BMFace *f); +bool bmesh_loop_validate(BMFace *f); /* DISK CYCLE MANAGMENT */ -int bmesh_disk_edge_append(BMEdge *e, BMVert *v); +void bmesh_disk_edge_append(BMEdge *e, BMVert *v); void bmesh_disk_edge_remove(BMEdge *e, BMVert *v); BMEdge *bmesh_disk_edge_next(BMEdge *e, BMVert *v); BMEdge *bmesh_disk_edge_prev(BMEdge *e, BMVert *v); @@ -60,19 +60,19 @@ void bmesh_radial_loop_remove(BMLoop *l, BMEdge *e); * bmesh_radial_loop_next(BMLoop *l) / prev. * just use member access l->radial_next, l->radial_prev now */ -int bmesh_radial_face_find(BMEdge *e, BMFace *f); +bool bmesh_radial_face_find(BMEdge *e, BMFace *f); int bmesh_radial_facevert_count(BMLoop *l, BMVert *v); BMLoop *bmesh_radial_faceloop_find_first(BMLoop *l, BMVert *v); BMLoop *bmesh_radial_faceloop_find_next(BMLoop *l, BMVert *v); BMLoop *bmesh_radial_faceloop_find_vert(BMFace *f, BMVert *v); -int bmesh_radial_validate(int radlen, BMLoop *l); +bool bmesh_radial_validate(int radlen, BMLoop *l); /* EDGE UTILITIES */ -int bmesh_vert_in_edge(BMEdge *e, BMVert *v); -int bmesh_verts_in_edge(BMVert *v1, BMVert *v2, BMEdge *e); -int bmesh_edge_swapverts(BMEdge *e, BMVert *orig, BMVert *newv); /*relink edge*/ +bool bmesh_vert_in_edge(BMEdge *e, BMVert *v); +bool bmesh_verts_in_edge(BMVert *v1, BMVert *v2, BMEdge *e); +bool bmesh_edge_swapverts(BMEdge *e, BMVert *orig, BMVert *newv); /* relink edge */ BMVert *bmesh_edge_other_vert_get(BMEdge *e, BMVert *v); BMEdge *bmesh_disk_edge_exists(BMVert *v1, BMVert *v2); -int bmesh_disk_validate(int len, BMEdge *e, BMVert *v); +bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v); #endif /* __BMESH_STRUCTURE_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_walkers.h b/source/blender/bmesh/intern/bmesh_walkers.h index 4f81f38aeb3..8be362b5afa 100644 --- a/source/blender/bmesh/intern/bmesh_walkers.h +++ b/source/blender/bmesh/intern/bmesh_walkers.h @@ -100,10 +100,9 @@ void BMW_reset(BMWalker *walker); * BMFace *f; * * BMW_init(&walker, bm, BMW_ISLAND, SOME_OP_FLAG); - * f = BMW_begin(&walker, some_start_face); - * for (; f; f = BMW_step(&walker)) - * { - * //do something with f + * + * for (f = BMW_begin(&walker, some_start_face); f; f = BMW_step(&walker)) { + * // do something with f * } * BMW_end(&walker); */ diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c index 538a9058ed5..bbe02a49967 100644 --- a/source/blender/bmesh/intern/bmesh_walkers_impl.c +++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c @@ -34,42 +34,42 @@ #include "intern/bmesh_private.h" #include "intern/bmesh_walkers_private.h" -static int bmw_mask_check_vert(BMWalker *walker, BMVert *v) +static bool bmw_mask_check_vert(BMWalker *walker, BMVert *v) { if ((walker->flag & BMW_FLAG_TEST_HIDDEN) && BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { - return FALSE; + return false; } else if (walker->mask_vert && !BMO_elem_flag_test(walker->bm, v, walker->mask_vert)) { - return FALSE; + return false; } else { - return TRUE; + return true; } } -static int bmw_mask_check_edge(BMWalker *walker, BMEdge *e) +static bool bmw_mask_check_edge(BMWalker *walker, BMEdge *e) { if ((walker->flag & BMW_FLAG_TEST_HIDDEN) && BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { - return FALSE; + return false; } else if (walker->mask_edge && !BMO_elem_flag_test(walker->bm, e, walker->mask_edge)) { - return FALSE; + return false; } else { - return TRUE; + return true; } } -static int bmw_mask_check_face(BMWalker *walker, BMFace *f) +static bool bmw_mask_check_face(BMWalker *walker, BMFace *f) { if ((walker->flag & BMW_FLAG_TEST_HIDDEN) && BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - return FALSE; + return false; } else if (walker->mask_face && !BMO_elem_flag_test(walker->bm, f, walker->mask_face)) { - return FALSE; + return false; } else { - return TRUE; + return true; } } @@ -164,7 +164,7 @@ static void *bmw_ShellWalker_step(BMWalker *walker) { BMEdge *curedge, *next = NULL; BMVert *ov = NULL; - int restrictpass = 1; + bool restrictpass = true; BMwShellWalker shellWalk = *((BMwShellWalker *)BMW_current_state(walker)); if (!BLI_ghash_haskey(walker->visithash, shellWalk.base)) { @@ -447,7 +447,7 @@ static void bmw_LoopWalker_begin(BMWalker *walker, void *data) lwalk->is_single = (vert_edge_count[0] == 2 && vert_edge_count[1] == 2); /* could also check that vertex*/ - if ((lwalk->is_boundary == FALSE) && + if ((lwalk->is_boundary == false) && (vert_edge_count[0] == 3 || vert_edge_count[1] == 3)) { BMIter iter; @@ -548,19 +548,19 @@ static void *bmw_LoopWalker_step(BMWalker *walker) /* typical loopiong over edges in the middle of a mesh */ /* however, why use 2 here at all? I guess for internal ngon loops it can be useful. Antony R. */ - ((vert_edge_tot == 4 || vert_edge_tot == 2) && owalk.is_boundary == FALSE) || + ((vert_edge_tot == 4 || vert_edge_tot == 2) && owalk.is_boundary == false) || /* walk over boundary of faces but stop at corners */ - (owalk.is_boundary == TRUE && owalk.is_single == FALSE && vert_edge_tot > 2) || + (owalk.is_boundary == true && owalk.is_single == false && vert_edge_tot > 2) || /* initial edge was a boundary, so is this edge and vertex is only apart of this face * this lets us walk over the the boundary of an ngon which is handy */ - (owalk.is_boundary == TRUE && owalk.is_single == TRUE && vert_edge_tot == 2 && BM_edge_is_boundary(e))) + (owalk.is_boundary == true && owalk.is_single == true && vert_edge_tot == 2 && BM_edge_is_boundary(e))) { i = 0; stopi = vert_edge_tot / 2; while (1) { - if ((owalk.is_boundary == FALSE) && (i == stopi)) { + if ((owalk.is_boundary == false) && (i == stopi)) { break; } @@ -589,7 +589,7 @@ static void *bmw_LoopWalker_step(BMWalker *walker) bmw_mask_check_edge(walker, l->e) && !BLI_ghash_haskey(walker->visithash, l->e)) { - if (!(owalk.is_boundary == FALSE && i != stopi)) { + if (!(owalk.is_boundary == false && i != stopi)) { lwalk = BMW_state_add(walker); lwalk->cur = l->e; lwalk->lastv = v; @@ -642,47 +642,47 @@ static void *bmw_LoopWalker_step(BMWalker *walker) /* Check whether the face loop should includes the face specified * by the given BMLoop */ -static int bmw_FaceLoopWalker_include_face(BMWalker *walker, BMLoop *l) +static bool bmw_FaceLoopWalker_include_face(BMWalker *walker, BMLoop *l) { /* face must have degree 4 */ if (l->f->len != 4) { - return FALSE; + return false; } if (!bmw_mask_check_face(walker, l->f)) { - return FALSE; + return false; } /* the face must not have been already visite */ if (BLI_ghash_haskey(walker->visithash, l->f) && BLI_ghash_haskey(walker->secvisithash, l->e)) { - return FALSE; + return false; } - return TRUE; + return true; } /* Check whether the face loop can start from the given edge */ -static int bmw_FaceLoopWalker_edge_begins_loop(BMWalker *walker, BMEdge *e) +static bool bmw_FaceLoopWalker_edge_begins_loop(BMWalker *walker, BMEdge *e) { /* There is no face loop starting from a wire edge */ if (BM_edge_is_wire(e)) { - return FALSE; + return false; } /* Don't start a loop from a boundary edge if it cannot * be extended to cover any faces */ if (BM_edge_is_boundary(e)) { if (!bmw_FaceLoopWalker_include_face(walker, e->l)) { - return FALSE; + return false; } } /* Don't start a face loop from non-manifold edges */ if (!BM_edge_is_manifold(e)) { - return FALSE; + return false; } - return TRUE; + return true; } static void bmw_FaceLoopWalker_begin(BMWalker *walker, void *data) @@ -697,7 +697,7 @@ static void bmw_FaceLoopWalker_begin(BMWalker *walker, void *data) lwalk = BMW_state_add(walker); lwalk->l = e->l; - lwalk->nocalc = 0; + lwalk->no_calc = false; BLI_ghash_insert(walker->visithash, lwalk->l->f, NULL); /* rewin */ @@ -708,7 +708,7 @@ static void bmw_FaceLoopWalker_begin(BMWalker *walker, void *data) lwalk = BMW_state_add(walker); *lwalk = owalk; - lwalk->nocalc = 0; + lwalk->no_calc = false; BLI_ghash_free(walker->secvisithash, NULL, NULL); walker->secvisithash = BLI_ghash_ptr_new("bmesh walkers 3"); @@ -740,7 +740,7 @@ static void *bmw_FaceLoopWalker_step(BMWalker *walker) l = l->radial_next; - if (lwalk->nocalc) { + if (lwalk->no_calc) { return f; } @@ -758,11 +758,11 @@ static void *bmw_FaceLoopWalker_step(BMWalker *walker) lwalk->l = l; if (l->f->len != 4) { - lwalk->nocalc = 1; + lwalk->no_calc = true; lwalk->l = origl; } else { - lwalk->nocalc = 0; + lwalk->no_calc = false; } BLI_ghash_insert(walker->secvisithash, l->e, NULL); diff --git a/source/blender/bmesh/intern/bmesh_walkers_private.h b/source/blender/bmesh/intern/bmesh_walkers_private.h index fc563932c3c..09dd4f18d89 100644 --- a/source/blender/bmesh/intern/bmesh_walkers_private.h +++ b/source/blender/bmesh/intern/bmesh_walkers_private.h @@ -62,14 +62,14 @@ typedef struct BMwLoopWalker { BMEdge *cur, *start; BMVert *lastv, *startv; BMFace *f_hub; - short is_boundary; /* boundary looping changes behavior */ - short is_single; /* single means the edge verts are only connected to 1 face */ + bool is_boundary; /* boundary looping changes behavior */ + bool is_single; /* single means the edge verts are only connected to 1 face */ } BMwLoopWalker; typedef struct BMwFaceLoopWalker { BMwGenericWalker header; BMLoop *l; - int nocalc; + bool no_calc; } BMwFaceLoopWalker; typedef struct BMwEdgeringWalker { diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c index eb8e84da63f..c56af821a93 100644 --- a/source/blender/bmesh/operators/bmo_bevel.c +++ b/source/blender/bmesh/operators/bmo_bevel.c @@ -34,7 +34,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op) { const float offset = BMO_slot_float_get(op->slots_in, "offset"); const int seg = BMO_slot_int_get(op->slots_in, "segments"); - const int vonly = BMO_slot_bool_get(op->slots_in, "vertex_only"); + const bool vonly = BMO_slot_bool_get(op->slots_in, "vertex_only"); if (offset > 0) { BMOIter siter; @@ -43,7 +43,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op) /* first flush 'geom' into flags, this makes it possible to check connected data, * BM_FACE is cleared so we can put newly created faces into a bmesh slot. */ - 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_TAG, false); BMO_ITER (v, &siter, op->slots_in, "geom", BM_VERT) { BM_elem_flag_enable(v, BM_ELEM_TAG); diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c index c7cd1e742d8..3a0e18b9ee5 100644 --- a/source/blender/bmesh/operators/bmo_connect.c +++ b/source/blender/bmesh/operators/bmo_connect.c @@ -106,7 +106,7 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op) } for (i = 0; i < BLI_array_count(verts_pair); i++) { - nf = BM_face_split(bm, f, verts_pair[i][0], verts_pair[i][1], &nl, NULL, FALSE); + nf = BM_face_split(bm, f, verts_pair[i][0], verts_pair[i][1], &nl, NULL, false); f = nf; if (!nl || !nf) { @@ -221,7 +221,7 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op) int c = 0, cl1 = 0, cl2 = 0; /* merge-bridge support */ - const int use_merge = BMO_slot_bool_get(op->slots_in, "use_merge"); + const bool use_merge = BMO_slot_bool_get(op->slots_in, "use_merge"); const float merge_factor = BMO_slot_float_get(op->slots_in, "merge_factor"); BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK); @@ -508,7 +508,7 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op) vv2[i2], vv2[i2next], vv1[i1next], - f_example, TRUE); + f_example, true); if (UNLIKELY((f == NULL) || (f->len != 4))) { fprintf(stderr, "%s: in bridge! (bmesh internal error)\n", __func__); } diff --git a/source/blender/bmesh/operators/bmo_create.c b/source/blender/bmesh/operators/bmo_create.c index 2ea5914ca92..ae07c2cf0bc 100644 --- a/source/blender/bmesh/operators/bmo_create.c +++ b/source/blender/bmesh/operators/bmo_create.c @@ -87,8 +87,8 @@ BLI_INLINE BMDiskLink *rs_edge_link_get(BMEdge *e, BMVert *v, EdgeData *e_data) &(((EdgeData *)e_data)->v2_disk_link); } -static int rotsys_append_edge(BMEdge *e, BMVert *v, - EdgeData *edata, VertData *vdata) +static bool rotsys_append_edge(BMEdge *e, BMVert *v, + EdgeData *edata, VertData *vdata) { EdgeData *ed = &edata[BM_elem_index_get(e)]; VertData *vd = &vdata[BM_elem_index_get(v)]; @@ -116,7 +116,7 @@ static int rotsys_append_edge(BMEdge *e, BMVert *v, } } - return TRUE; + return true; } static void UNUSED_FUNCTION(rotsys_remove_edge)(BMEdge *e, BMVert *v, @@ -613,10 +613,10 @@ static void init_rotsys(BMesh *bm, EdgeData *edata, VertData *vdata) BM_elem_index_set(v2, -1); /* set_dirty! */ //BM_edge_create(bm, cv, v2, NULL, 0); - BM_vert_select_set(bm, v2, TRUE); + BM_vert_select_set(bm, v2, true); if (lastv) { e2 = BM_edge_create(bm, lastv, v2, NULL, 0); - BM_edge_select_set(bm, e2, TRUE); + BM_edge_select_set(bm, e2, true); } lastv = v2; @@ -742,7 +742,7 @@ static EPath *edge_find_shortest_path(BMesh *bm, BMOperator *op, BMEdge *edge, E BMVert *endv; EPathNode *node; int i; - const int use_restrict = BMO_slot_bool_get(op->slots_in, "use_restrict"); + const bool use_restrict = BMO_slot_bool_get(op->slots_in, "use_restrict"); BMOpSlot *slot_restrict = BMO_slot_get(op->slots_in, "restrict"); @@ -899,10 +899,10 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) BMEdge **edges = NULL; PathBase *pathbase; BLI_array_declare(edges); - int use_restrict = BMO_slot_bool_get(op->slots_in, "use_restrict"); - int use_fill_check = BMO_slot_bool_get(op->slots_in, "use_fill_check"); - const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr"); - const short use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth"); + const bool use_restrict = BMO_slot_bool_get(op->slots_in, "use_restrict"); + const bool use_fill_check = BMO_slot_bool_get(op->slots_in, "use_fill_check"); + const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr"); + const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth"); int i, j, group = 0; unsigned int winding[2]; /* accumulte winding directions for each edge which has a face */ BMOpSlot *slot_restrict = BMO_slot_get(op->slots_in, "restrict"); @@ -1047,9 +1047,9 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) v2 = verts[0]; } - if ((use_fill_check == FALSE) || + if ((use_fill_check == false) || /* fairly expensive check - see if there are already faces filling this area */ - (BM_face_exists_multi_edge(edges, i) == FALSE)) + (BM_face_exists_multi_edge(edges, i) == false)) { f = BM_face_create_ngon(bm, v1, v2, edges, i, BM_CREATE_NO_DOUBLE); if (f && !BMO_elem_flag_test(bm, f, ELE_ORIG)) { @@ -1287,7 +1287,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) BMFace *f; int totv = 0, tote = 0, totf = 0, amount; const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr"); - const short use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth"); + const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth"); /* count number of each element type we were passe */ BMO_ITER (h, &oiter, op->slots_in, "geom", BM_VERT | BM_EDGE | BM_FACE) { @@ -1321,7 +1321,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) if (totf == 0 && totv >= 4 && totv == tote + 2) { /* find a free standing vertex and 2 endpoint verts */ BMVert *v_free = NULL, *v_a = NULL, *v_b = NULL; - int ok = TRUE; + bool ok = true; BMO_ITER (v, &oiter, op->slots_in, "geom", BM_VERT) { @@ -1339,26 +1339,26 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) if (tot_edges == 0) { /* only accept 1 free vert */ if (v_free == NULL) v_free = v; - else ok = FALSE; /* only ever want one of these */ + else ok = false; /* only ever want one of these */ } else if (tot_edges == 1) { if (v_a == NULL) v_a = v; else if (v_b == NULL) v_b = v; - else ok = FALSE; /* only ever want 2 of these */ + else ok = false; /* only ever want 2 of these */ } else if (tot_edges == 2) { /* do nothing, regular case */ } else { - ok = FALSE; /* if a vertex has 3+ edge users then cancel - this is only simple cases */ + ok = false; /* if a vertex has 3+ edge users then cancel - this is only simple cases */ } - if (ok == FALSE) { + if (ok == false) { break; } } - if (ok == TRUE && v_free && v_a && v_b) { + if (ok == true && v_free && v_a && v_b) { e = BM_edge_create(bm, v_free, v_a, NULL, BM_CREATE_NO_DOUBLE); BMO_elem_flag_enable(bm, e, ELE_NEW); @@ -1377,7 +1377,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) BMO_op_initf(bm, &op2, op->flag, "edgenet_fill edges=%fe use_fill_check=%b mat_nr=%i use_smooth=%b", - ELE_NEW, TRUE, mat_nr, use_smooth); + ELE_NEW, true, mat_nr, use_smooth); BMO_op_exec(bm, &op2); diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c index 7c3bcd60daa..47b2497816f 100644 --- a/source/blender/bmesh/operators/bmo_dissolve.c +++ b/source/blender/bmesh/operators/bmo_dissolve.c @@ -41,7 +41,7 @@ #define VERT_MARK 1 -static int UNUSED_FUNCTION(check_hole_in_region) (BMesh * bm, BMFace * f) +static bool UNUSED_FUNCTION(check_hole_in_region) (BMesh * bm, BMFace * f) { BMWalker regwalker; BMIter liter2; @@ -55,23 +55,21 @@ static int UNUSED_FUNCTION(check_hole_in_region) (BMesh * bm, BMFace * f) BMW_FLAG_NOP, BMW_NIL_LAY); - f2 = BMW_begin(®walker, f); - for ( ; f2; f2 = BMW_step(®walker)) { - l2 = BM_iter_new(&liter2, bm, BM_LOOPS_OF_FACE, f2); - for ( ; l2; l2 = BM_iter_step(&liter2)) { + for (f2 = BMW_begin(®walker, f); f2; f2 = BMW_step(®walker)) { + BM_ITER_ELEM (l2, &liter2, f2, BM_LOOPS_OF_FACE) { l3 = l2->radial_next; if (BMO_elem_flag_test(bm, l3->f, FACE_MARK) != BMO_elem_flag_test(bm, l2->f, FACE_MARK)) { if (!BMO_elem_flag_test(bm, l2->e, EDGE_MARK)) { - return FALSE; + return false; } } } } BMW_end(®walker); - return TRUE; + return true; } void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) @@ -85,7 +83,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) BMWalker regwalker; int i; - int use_verts = BMO_slot_bool_get(op->slots_in, "use_verts"); + const bool use_verts = BMO_slot_bool_get(op->slots_in, "use_verts"); if (use_verts) { /* tag verts that start out with only 2 edges, @@ -115,8 +113,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) BMW_FLAG_NOP, /* no need to check BMW_FLAG_TEST_HIDDEN, faces are already marked by the bmo */ BMW_NIL_LAY); - f2 = BMW_begin(®walker, f); - for ( ; f2; f2 = BMW_step(®walker)) { + for (f2 = BMW_begin(®walker, f); f2; f2 = BMW_step(®walker)) { BLI_array_append(faces, f2); } BMW_end(®walker); @@ -150,7 +147,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) while (faces[tot]) tot++; - f = BM_faces_join(bm, faces, tot, TRUE); + f = BM_faces_join(bm, faces, tot, true); if (!f) { BMO_error_raise(bm, op, BMERR_DISSOLVEFACES_FAILED, "Could not create merged face"); @@ -174,7 +171,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { if (BMO_elem_flag_test(bm, v, VERT_MARK)) { if (BM_vert_edge_count(v) == 2) { - BM_vert_collapse_edge(bm, v->e, v, TRUE); + BM_vert_collapse_edge(bm, v->e, v, true); } } } @@ -215,7 +212,7 @@ void bmo_dissolve_edgeloop_exec(BMesh *bm, BMOperator *op) /* BMESH_TODO - check on delaying edge removal since we may end up removing more then * one edge, and later reference a removed edge */ - BM_faces_join_pair(bm, fa, fb, e, TRUE); + BM_faces_join_pair(bm, fa, fb, e, true); } } @@ -228,7 +225,7 @@ void bmo_dissolve_edgeloop_exec(BMesh *bm, BMOperator *op) /* clean up extreneous 2-valence vertice */ for (i = 0; i < BLI_array_count(verts); i++) { if (verts[i]->e) { - BM_vert_collapse_edge(bm, verts[i]->e, verts[i], TRUE); + BM_vert_collapse_edge(bm, verts[i]->e, verts[i], true); } } @@ -254,7 +251,7 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op) BMIter viter; BMVert *v; - int use_verts = BMO_slot_bool_get(op->slots_in, "use_verts"); + const bool use_verts = BMO_slot_bool_get(op->slots_in, "use_verts"); if (use_verts) { BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { @@ -271,7 +268,7 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op) /* BMESH_TODO - check on delaying edge removal since we may end up removing more then * one edge, and later reference a removed edge */ - BM_faces_join_pair(bm, fa, fb, e, TRUE); + BM_faces_join_pair(bm, fa, fb, e, true); } } @@ -279,20 +276,20 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op) BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { if (BMO_elem_flag_test(bm, v, VERT_MARK)) { if (BM_vert_edge_count(v) == 2) { - BM_vert_collapse_edge(bm, v->e, v, TRUE); + BM_vert_collapse_edge(bm, v->e, v, true); } } } } } -static int test_extra_verts(BMesh *bm, BMVert *v) +static bool test_extra_verts(BMesh *bm, BMVert *v) { BMIter iter, liter, iter2, iter3; BMFace *f, *f2; BMLoop *l; BMEdge *e; - int found; + bool found; /* test faces around verts for verts that would be wrongly killed * by dissolve faces. */ @@ -305,31 +302,31 @@ static int test_extra_verts(BMesh *bm, BMVert *v) * then dissolve faces won't destroy it. * also if it forms a boundary with one * of the face region */ - found = FALSE; + found = false; e = BM_iter_new(&iter2, bm, BM_EDGES_OF_VERT, l->v); for ( ; e; e = BM_iter_step(&iter2)) { if (BM_edge_is_boundary(e)) { - found = TRUE; + found = true; } f2 = BM_iter_new(&iter3, bm, BM_FACES_OF_EDGE, e); for ( ; f2; f2 = BM_iter_step(&iter3)) { if (!BMO_elem_flag_test(bm, f2, FACE_MARK)) { - found = TRUE; + found = true; break; } } - if (found == TRUE) { + if (found == true) { break; } } - if (found == FALSE) { - return FALSE; + if (found == false) { + return false; } } } } - return TRUE; + return true; } void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op) { @@ -349,9 +346,9 @@ void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op) /* previously the faces were joined, but collapsing between 2 edges * gives some advantage/difference in using vertex-dissolve over edge-dissolve */ #if 0 - BM_vert_collapse_faces(bm, v->e, v, 1.0f, TRUE, TRUE); + BM_vert_collapse_faces(bm, v->e, v, 1.0f, true, true); #else - BM_vert_collapse_edge(bm, v->e, v, TRUE); + BM_vert_collapse_edge(bm, v->e, v, true); #endif continue; @@ -483,7 +480,7 @@ void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op) BMOpSlot *vinput = BMO_slot_get(op->slots_in, "verts"); const float angle_max = (float)M_PI / 2.0f; const float angle_limit = min_ff(angle_max, BMO_slot_float_get(op->slots_in, "angle_limit")); - const int do_dissolve_boundaries = BMO_slot_bool_get(op->slots_in, "use_dissolve_boundaries"); + const bool do_dissolve_boundaries = BMO_slot_bool_get(op->slots_in, "use_dissolve_boundaries"); BM_mesh_decimate_dissolve_ex(bm, angle_limit, do_dissolve_boundaries, (BMVert **)BMO_SLOT_AS_BUFFER(vinput), vinput->len, diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c index f288901c272..1448129ccde 100644 --- a/source/blender/bmesh/operators/bmo_dupe.c +++ b/source/blender/bmesh/operators/bmo_dupe.c @@ -213,13 +213,13 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst) !BMO_elem_flag_test(bm_src, v, DUPE_DONE)) { BMIter iter; - int isolated = 1; + bool isolated = true; v2 = copy_vertex(bm_src, v, bm_dst, vhash); BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) { if (BMO_elem_flag_test(bm_src, f, DUPE_INPUT)) { - isolated = 0; + isolated = false; break; } } @@ -227,7 +227,7 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst) if (isolated) { BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { if (BMO_elem_flag_test(bm_src, e, DUPE_INPUT)) { - isolated = 0; + isolated = false; break; } } @@ -386,7 +386,7 @@ void bmo_split_exec(BMesh *bm, BMOperator *op) BMOperator *splitop = op; BMOperator dupeop; BMOperator delop; - const short use_only_faces = BMO_slot_bool_get(op->slots_in, "use_only_faces"); + const bool use_only_faces = BMO_slot_bool_get(op->slots_in, "use_only_faces"); /* initialize our sub-operator */ BMO_op_init(bm, &dupeop, op->flag, "duplicate"); diff --git a/source/blender/bmesh/operators/bmo_edgesplit.c b/source/blender/bmesh/operators/bmo_edgesplit.c index b4b50a60877..378f790ef32 100644 --- a/source/blender/bmesh/operators/bmo_edgesplit.c +++ b/source/blender/bmesh/operators/bmo_edgesplit.c @@ -37,17 +37,17 @@ /* keep this operator fast, its used in a modifier */ void bmo_split_edges_exec(BMesh *bm, BMOperator *op) { - const int use_verts = BMO_slot_bool_get(op->slots_in, "use_verts"); + const bool use_verts = BMO_slot_bool_get(op->slots_in, "use_verts"); - BMO_slot_buffer_hflag_enable(bm, op->slots_in, "edges", BM_EDGE, BM_ELEM_TAG, FALSE); + BMO_slot_buffer_hflag_enable(bm, op->slots_in, "edges", BM_EDGE, BM_ELEM_TAG, false); if (use_verts) { /* this slows down the operation but its ok because the modifier doesn't use */ - BMO_slot_buffer_hflag_enable(bm, op->slots_in, "verts", BM_VERT, BM_ELEM_TAG, FALSE); + BMO_slot_buffer_hflag_enable(bm, op->slots_in, "verts", BM_VERT, BM_ELEM_TAG, false); } /* this is where everything happens */ - BM_mesh_edgesplit(bm, use_verts, TRUE); + BM_mesh_edgesplit(bm, use_verts, true); BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "edges.out", BM_EDGE, BM_ELEM_INTERNAL_TAG); } diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c index 2cca3fcb24a..4fde6150f05 100644 --- a/source/blender/bmesh/operators/bmo_extrude.c +++ b/source/blender/bmesh/operators/bmo_extrude.c @@ -112,7 +112,7 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op) l3 = l->next; l4 = l2->next; - f3 = BM_face_create_quad_tri(bm, l3->v, l4->v, l2->v, l->v, f, FALSE); + f3 = BM_face_create_quad_tri(bm, l3->v, l4->v, l2->v, l->v, f, false); /* XXX, no error check here, why? - Campbell */ l_tmp = BM_FACE_FIRST_LOOP(f3); @@ -225,7 +225,7 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op) f_verts[3] = e_new->v2; } /* not sure what to do about example face, pass NULL for now */ - f = BM_face_create_quad_tri_v(bm, f_verts, 4, NULL, FALSE); + f = BM_face_create_quad_tri_v(bm, f_verts, 4, NULL, false); bm_extrude_copy_face_loop_attributes(bm, f); if (BMO_elem_flag_test(bm, e, EXT_INPUT)) @@ -248,7 +248,7 @@ void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op) BMOIter siter; BMVert *v, *dupev; BMEdge *e; - const int has_vskin = CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN); + const bool has_vskin = CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN); for (v = BMO_iter_new(&siter, op->slots_in, "verts", BM_VERT); v; v = BMO_iter_step(&siter)) { dupev = BM_vert_create(bm, v->co, v, 0); @@ -273,7 +273,7 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) BMEdge *e, *e_new; BMVert *v, *v2; BMFace *f; - int found, fwd, delorig = FALSE; + bool found, fwd, delorig = false; BMOpSlot *slot_facemap_out; BMOpSlot *slot_edges_exclude; @@ -293,20 +293,20 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) continue; } - found = FALSE; /* found a face that isn't input? */ + found = false; /* found a face that isn't input? */ edge_face_tot = 0; /* edge/face count */ BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) { if (!BMO_elem_flag_test(bm, f, EXT_INPUT)) { - found = TRUE; - delorig = TRUE; + found = true; + delorig = true; break; } edge_face_tot++; } - if ((edge_face_tot > 1) && (found == FALSE)) { + if ((edge_face_tot > 1) && (found == false)) { /* edge has a face user, that face isn't extrude input */ BMO_elem_flag_enable(bm, e, EXT_DEL); } @@ -316,26 +316,26 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) /* calculate verts to delete */ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { if (v->e) { /* only deal with verts attached to geometry [#33651] */ - found = FALSE; + found = false; BM_ITER_ELEM (e, &viter, v, BM_EDGES_OF_VERT) { if (!BMO_elem_flag_test(bm, e, EXT_INPUT) || !BMO_elem_flag_test(bm, e, EXT_DEL)) { - found = TRUE; + found = true; break; } } /* avoid an extra loop */ - if (found == TRUE) { + if (found == true) { BM_ITER_ELEM (f, &viter, v, BM_FACES_OF_VERT) { if (!BMO_elem_flag_test(bm, f, EXT_INPUT)) { - found = TRUE; + found = true; break; } } } - if (found == FALSE) { + if (found == false) { BMO_elem_flag_enable(bm, v, EXT_DEL); } } @@ -347,7 +347,7 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) } } - if (delorig == TRUE) { + if (delorig == true) { BMO_op_initf(bm, &delop, op->flag, "delete geom=%fvef context=%i", EXT_DEL, DEL_ONLYTAGGED); @@ -435,7 +435,7 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) } /* not sure what to do about example face, pass NULL for now */ - f = BM_face_create_quad_tri_v(bm, f_verts, 4, NULL, FALSE); + f = BM_face_create_quad_tri_v(bm, f_verts, 4, NULL, false); bm_extrude_copy_face_loop_attributes(bm, f); } @@ -665,7 +665,7 @@ void bmo_solidify_face_region_exec(BMesh *bm, BMOperator *op) BMO_op_finish(bm, &reverseop); /* Extrude the region */ - BMO_op_initf(bm, &extrudeop, op->flag, "extrude_face_region use_keep_orig=%b", TRUE); + BMO_op_initf(bm, &extrudeop, op->flag, "extrude_face_region use_keep_orig=%b", true); BMO_slot_copy(op, slots_in, "geom", &extrudeop, slots_in, "geom"); BMO_op_exec(bm, &extrudeop); diff --git a/source/blender/bmesh/operators/bmo_hull.c b/source/blender/bmesh/operators/bmo_hull.c index e2da4f4f89c..5d8689b9da6 100644 --- a/source/blender/bmesh/operators/bmo_hull.c +++ b/source/blender/bmesh/operators/bmo_hull.c @@ -136,12 +136,12 @@ static void hull_output_triangles(BMesh *bm, GHash *hull_triangles) } /* Create new hull face */ - f = BM_face_create_quad_tri_v(bm, t->v, 3, example, TRUE); + f = BM_face_create_quad_tri_v(bm, t->v, 3, example, true); BM_face_copy_shared(bm, f); } /* Mark face for 'geom.out' slot and select */ BMO_elem_flag_enable(bm, f, HULL_FLAG_OUTPUT_GEOM); - BM_face_select_set(bm, f, TRUE); + BM_face_select_set(bm, f, true); /* Mark edges for 'geom.out' slot */ for (i = 0; i < 3; i++) { @@ -200,7 +200,7 @@ static int hull_final_edges_lookup(HullFinalEdges *final_edges, adj = BLI_ghash_lookup(final_edges->edges, v1); if (!adj) - return FALSE; + return false; return !!final_edges_find_link(adj, v2); } @@ -268,17 +268,17 @@ static void hull_remove_overlapping(BMesh *bm, GHash *hull_triangles, HullTriangle *t = BLI_ghashIterator_getKey(&hull_iter); BMIter bm_iter1, bm_iter2; BMFace *f; - int f_on_hull; + bool f_on_hull; BM_ITER_ELEM (f, &bm_iter1, t->v[0], BM_FACES_OF_VERT) { BMEdge *e; /* Check that all the face's edges are on the hull, * otherwise can't reuse it */ - f_on_hull = TRUE; + f_on_hull = true; BM_ITER_ELEM (e, &bm_iter2, f, BM_EDGES_OF_FACE) { if (!hull_final_edges_lookup(final_edges, e->v1, e->v2)) { - f_on_hull = FALSE; + f_on_hull = false; break; } } @@ -288,7 +288,7 @@ static void hull_remove_overlapping(BMesh *bm, GHash *hull_triangles, if (BM_vert_in_face(f, t->v[1]) && BM_vert_in_face(f, t->v[2]) && f_on_hull) { - t->skip = TRUE; + t->skip = true; BMO_elem_flag_disable(bm, f, HULL_FLAG_INTERIOR_ELE); BMO_elem_flag_enable(bm, f, HULL_FLAG_HOLE); } @@ -330,18 +330,18 @@ static void hull_tag_unused(BMesh *bm, BMOperator *op) * input set */ BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) { if (BMO_elem_flag_test(bm, v, HULL_FLAG_INTERIOR_ELE)) { - int del = TRUE; + bool del = true; BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { if (!BMO_elem_flag_test(bm, e, HULL_FLAG_INPUT)) { - del = FALSE; + del = false; break; } } BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) { if (!BMO_elem_flag_test(bm, f, HULL_FLAG_INPUT)) { - del = FALSE; + del = false; break; } } @@ -353,11 +353,11 @@ static void hull_tag_unused(BMesh *bm, BMOperator *op) BMO_ITER (e, &oiter, op->slots_in, "input", BM_EDGE) { if (BMO_elem_flag_test(bm, e, HULL_FLAG_INTERIOR_ELE)) { - int del = TRUE; + bool del = true; BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) { if (!BMO_elem_flag_test(bm, f, HULL_FLAG_INPUT)) { - del = FALSE; + del = false; break; } } @@ -396,13 +396,13 @@ static void hull_tag_holes(BMesh *bm, BMOperator *op) /* Mark edges too if all adjacent faces are holes and the edge is * not already isolated */ BMO_ITER (e, &oiter, op->slots_in, "input", BM_EDGE) { - int hole = TRUE; - int any_faces = FALSE; + bool hole = true; + bool any_faces = false; BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) { - any_faces = TRUE; + any_faces = true; if (!BMO_elem_flag_test(bm, f, HULL_FLAG_HOLE)) { - hole = FALSE; + hole = false; break; } } diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c index cef1181f63b..ef99dae5ac9 100644 --- a/source/blender/bmesh/operators/bmo_inset.c +++ b/source/blender/bmesh/operators/bmo_inset.c @@ -92,13 +92,13 @@ static BMLoop *bm_edge_is_mixed_face_tag(BMLoop *l) void bmo_inset_exec(BMesh *bm, BMOperator *op) { - const int use_outset = BMO_slot_bool_get(op->slots_in, "use_outset"); - const int use_boundary = BMO_slot_bool_get(op->slots_in, "use_boundary") && (use_outset == FALSE); - const int use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset"); - const int use_even_boundry = use_even_offset; /* could make own option */ - const int use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset"); - const float thickness = BMO_slot_float_get(op->slots_in, "thickness"); - const float depth = BMO_slot_float_get(op->slots_in, "depth"); + const bool use_outset = BMO_slot_bool_get(op->slots_in, "use_outset"); + const bool use_boundary = BMO_slot_bool_get(op->slots_in, "use_boundary") && (use_outset == false); + const bool use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset"); + const bool use_even_boundry = use_even_offset; /* could make own option */ + const bool use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset"); + const float thickness = BMO_slot_float_get(op->slots_in, "thickness"); + const float depth = BMO_slot_float_get(op->slots_in, "depth"); int edge_info_len = 0; @@ -111,13 +111,13 @@ void bmo_inset_exec(BMesh *bm, BMOperator *op) BMFace *f; int i, j, k; - if (use_outset == FALSE) { - BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, FALSE); - BMO_slot_buffer_hflag_enable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, FALSE); + if (use_outset == false) { + BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false); + BMO_slot_buffer_hflag_enable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, false); } else { - BM_mesh_elem_hflag_enable_all(bm, BM_FACE, BM_ELEM_TAG, FALSE); - BMO_slot_buffer_hflag_disable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, FALSE); + BM_mesh_elem_hflag_enable_all(bm, BM_FACE, BM_ELEM_TAG, false); + BMO_slot_buffer_hflag_disable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, false); } /* first count all inset edges we will split */ @@ -411,11 +411,11 @@ void bmo_inset_exec(BMesh *bm, BMOperator *op) /* this saves expensive/slow glue check for common cases */ if (r_vout_len > 2) { - int ok = TRUE; + bool ok = true; /* last step, NULL this vertex if has a tagged face */ BM_ITER_ELEM (f, &iter, v_split, BM_FACES_OF_VERT) { if (BM_elem_flag_test(f, BM_ELEM_TAG)) { - ok = FALSE; + ok = false; break; } } @@ -471,7 +471,7 @@ void bmo_inset_exec(BMesh *bm, BMOperator *op) #endif /* no need to check doubles, we KNOW there won't be any */ /* yes - reverse face is correct in this case */ - f = BM_face_create_quad_tri_v(bm, varr, j, es->l->f, FALSE); + f = BM_face_create_quad_tri_v(bm, varr, j, es->l->f, false); BMO_elem_flag_enable(bm, f, ELE_NEW); /* copy for loop data, otherwise UV's and vcols are no good. @@ -548,7 +548,7 @@ void bmo_inset_exec(BMesh *bm, BMOperator *op) /* done correcting edge verts normals */ /* untag verts */ - BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, FALSE); + BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, false); /* tag face verts */ BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) { diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c index 45ecdee014e..e052968a6a0 100644 --- a/source/blender/bmesh/operators/bmo_join_triangles.c +++ b/source/blender/bmesh/operators/bmo_join_triangles.c @@ -105,7 +105,7 @@ static float measure_facepair(BMVert *v1, BMVert *v2, #define T2QUV_LIMIT 0.005f #define T2QCOL_LIMIT 3 -static int bm_edge_faces_cmp(BMesh *bm, BMEdge *e, const int do_uv, const int do_tf, const int do_vcol) +static bool bm_edge_faces_cmp(BMesh *bm, BMEdge *e, const bool do_uv, const bool do_tf, const bool do_vcol) { /* first get loops */ BMLoop *l[4]; @@ -138,7 +138,7 @@ static int bm_edge_faces_cmp(BMesh *bm, BMEdge *e, const int do_uv, const int do if (luv[0] && (!compare_v2v2(luv[0]->uv, luv[2]->uv, T2QUV_LIMIT) || !compare_v2v2(luv[1]->uv, luv[3]->uv, T2QUV_LIMIT))) { - return FALSE; + return false; } } @@ -149,7 +149,7 @@ static int bm_edge_faces_cmp(BMesh *bm, BMEdge *e, const int do_uv, const int do }; if (tp[0] && (tp[0]->tpage != tp[1]->tpage)) { - return FALSE; + return false; } } @@ -166,12 +166,12 @@ static int bm_edge_faces_cmp(BMesh *bm, BMEdge *e, const int do_uv, const int do if (!compare_rgb_uchar((unsigned char *)&lcol[0]->r, (unsigned char *)&lcol[2]->r, T2QCOL_LIMIT) || !compare_rgb_uchar((unsigned char *)&lcol[1]->r, (unsigned char *)&lcol[3]->r, T2QCOL_LIMIT)) { - return FALSE; + return false; } } } - return TRUE; + return true; } typedef struct JoinEdge { @@ -197,6 +197,13 @@ static int fplcmp(const void *v1, const void *v2) void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) { + const bool do_sharp = BMO_slot_bool_get(op->slots_in, "cmp_sharp"); + const bool do_uv = BMO_slot_bool_get(op->slots_in, "cmp_uvs"); + const bool do_tf = do_uv; /* texture face, make make its own option eventually */ + const bool do_vcol = BMO_slot_bool_get(op->slots_in, "cmp_vcols"); + const bool do_mat = BMO_slot_bool_get(op->slots_in, "cmp_materials"); + const float limit = BMO_slot_float_get(op->slots_in, "limit"); + BMIter iter, liter; BMOIter siter; BMFace *f; @@ -204,12 +211,6 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) BMEdge *e; BLI_array_declare(jedges); JoinEdge *jedges = NULL; - int do_sharp = BMO_slot_bool_get(op->slots_in, "cmp_sharp"); - int do_uv = BMO_slot_bool_get(op->slots_in, "cmp_uvs"); - int do_tf = do_uv; /* texture face, make make its own option eventually */ - int do_vcol = BMO_slot_bool_get(op->slots_in, "cmp_vcols"); - int do_mat = BMO_slot_bool_get(op->slots_in, "cmp_materials"); - float limit = BMO_slot_float_get(op->slots_in, "limit"); int i, totedge; /* flag all edges of all input face */ @@ -265,7 +266,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) if (do_mat && f1->mat_nr != f2->mat_nr) continue; - if ((do_uv || do_tf || do_vcol) && (bm_edge_faces_cmp(bm, e, do_uv, do_tf, do_vcol) == FALSE)) + if ((do_uv || do_tf || do_vcol) && (bm_edge_faces_cmp(bm, e, do_uv, do_tf, do_vcol) == false)) continue; measure = measure_facepair(v1, v2, v3, v4, limit); @@ -308,7 +309,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) BM_edge_face_pair(e, &f1, &f2); /* checked above */ - BM_faces_join_pair(bm, f1, f2, e, TRUE); + BM_faces_join_pair(bm, f1, f2, e, true); } BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { @@ -342,7 +343,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) continue; } - BM_faces_join_pair(bm, f1, f2, e, TRUE); + BM_faces_join_pair(bm, f1, f2, e, true); } } diff --git a/source/blender/bmesh/operators/bmo_mesh_conv.c b/source/blender/bmesh/operators/bmo_mesh_conv.c index 4b897a24c8a..0976c4cdfbb 100644 --- a/source/blender/bmesh/operators/bmo_mesh_conv.c +++ b/source/blender/bmesh/operators/bmo_mesh_conv.c @@ -36,6 +36,9 @@ #include "DNA_key_types.h" #include "DNA_modifier_types.h" +#include "BLI_math.h" +#include "BLI_array.h" + #include "BKE_mesh.h" #include "BLI_listbase.h" #include "BKE_global.h" @@ -43,9 +46,6 @@ #include "BKE_main.h" #include "BKE_customdata.h" -#include "BLI_math.h" -#include "BLI_array.h" - #include "bmesh.h" #include "intern/bmesh_private.h" @@ -53,9 +53,9 @@ void bmo_mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) { - Object *ob = BMO_slot_ptr_get(op->slots_in, "object"); - Mesh *me = BMO_slot_ptr_get(op->slots_in, "mesh"); - int set_key = BMO_slot_bool_get(op->slots_in, "use_shapekey"); + Object *ob = BMO_slot_ptr_get(op->slots_in, "object"); + Mesh *me = BMO_slot_ptr_get(op->slots_in, "mesh"); + bool set_key = BMO_slot_bool_get(op->slots_in, "use_shapekey"); BM_mesh_bm_from_me(bm, me, set_key, ob->shapenr); @@ -72,14 +72,14 @@ void bmo_object_load_bmesh_exec(BMesh *bm, BMOperator *op) BMO_op_callf(bm, op->flag, "bmesh_to_mesh mesh=%p object=%p skip_tessface=%b", - me, ob, TRUE); + me, ob, true); } void bmo_bmesh_to_mesh_exec(BMesh *bm, BMOperator *op) { Mesh *me = BMO_slot_ptr_get(op->slots_in, "mesh"); /* Object *ob = BMO_slot_ptr_get(op, "object"); */ - int dotess = !BMO_slot_bool_get(op->slots_in, "skip_tessface"); + const bool dotess = !BMO_slot_bool_get(op->slots_in, "skip_tessface"); BM_mesh_bm_to_me(bm, me, dotess); } diff --git a/source/blender/bmesh/operators/bmo_mirror.c b/source/blender/bmesh/operators/bmo_mirror.c index 61b061dd21f..48b2f76665c 100644 --- a/source/blender/bmesh/operators/bmo_mirror.c +++ b/source/blender/bmesh/operators/bmo_mirror.c @@ -53,8 +53,8 @@ void bmo_mirror_exec(BMesh *bm, BMOperator *op) float dist = BMO_slot_float_get(op->slots_in, "merge_dist"); int i, ototvert /*, ototedge */; int axis = BMO_slot_int_get(op->slots_in, "axis"); - int mirroru = BMO_slot_bool_get(op->slots_in, "mirror_u"); - int mirrorv = BMO_slot_bool_get(op->slots_in, "mirror_v"); + bool mirror_u = BMO_slot_bool_get(op->slots_in, "mirror_u"); + bool mirror_v = BMO_slot_bool_get(op->slots_in, "mirror_v"); BMOpSlot *slot_targetmap; ototvert = bm->totvert; @@ -97,7 +97,7 @@ void bmo_mirror_exec(BMesh *bm, BMOperator *op) v = BM_iter_step(&iter); } - if (mirroru || mirrorv) { + if (mirror_u || mirror_v) { BMFace *f; BMLoop *l; MLoopUV *luv; @@ -109,9 +109,9 @@ void bmo_mirror_exec(BMesh *bm, BMOperator *op) totlayer = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV); for (i = 0; i < totlayer; i++) { luv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i); - if (mirroru) + if (mirror_u) luv->uv[0] = 1.0f - luv->uv[0]; - if (mirrorv) + if (mirror_v) luv->uv[1] = 1.0f - luv->uv[1]; } } diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c index c582f710f43..011002718d3 100644 --- a/source/blender/bmesh/operators/bmo_primitive.c +++ b/source/blender/bmesh/operators/bmo_primitive.c @@ -420,7 +420,7 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op) v2 = eva[icoface[a][1]]; v3 = eva[icoface[a][2]]; - eftemp = BM_face_create_quad_tri(bm, v1, v2, v3, NULL, NULL, FALSE); + eftemp = BM_face_create_quad_tri(bm, v1, v2, v3, NULL, NULL, false); BM_ITER_ELEM (l, &liter, eftemp, BM_LOOPS_OF_FACE) { BMO_elem_flag_enable(bm, l->e, EDGE_MARK); @@ -438,7 +438,7 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op) "cuts=%i " "use_grid_fill=%b use_sphere=%b", EDGE_MARK, dia, (1 << (subdiv - 1)) - 1, - TRUE, TRUE); + true, true); BMO_op_exec(bm, &bmop); BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_VERT, VERT_MARK); @@ -488,14 +488,14 @@ void bmo_create_monkey_exec(BMesh *bm, BMOperator *op) tv[monkeyf[i][1] + i - monkeyo], tv[monkeyf[i][2] + i - monkeyo], (monkeyf[i][3] != monkeyf[i][2]) ? tv[monkeyf[i][3] + i - monkeyo] : NULL, - NULL, FALSE); + NULL, false); BM_face_create_quad_tri(bm, tv[monkeynv + monkeyf[i][2] + i - monkeyo], tv[monkeynv + monkeyf[i][1] + i - monkeyo], tv[monkeynv + monkeyf[i][0] + i - monkeyo], (monkeyf[i][3] != monkeyf[i][2]) ? tv[monkeynv + monkeyf[i][3] + i - monkeyo] : NULL, - NULL, FALSE); + NULL, false); } MEM_freeN(tv); @@ -508,8 +508,8 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op) { const float dia = BMO_slot_float_get(op->slots_in, "diameter"); const int segs = BMO_slot_int_get(op->slots_in, "segments"); - const int cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends"); - const int cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris"); + const bool cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends"); + const bool cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris"); BMVert *v1, *lastv1 = NULL, *cent1, *firstv1 = NULL; float vec[3], mat[4][4], phi, phid; @@ -547,7 +547,7 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op) if (a && cap_ends) { BMFace *f; - f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, NULL, NULL, FALSE); + f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, NULL, NULL, false); BMO_elem_flag_enable(bm, f, FACE_NEW); } @@ -565,7 +565,7 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op) if (cap_ends) { BMFace *f; - f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, FALSE); + f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, false); BMO_elem_flag_enable(bm, f, FACE_NEW); } @@ -584,8 +584,8 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op) float dia2 = BMO_slot_float_get(op->slots_in, "diameter2"); float depth = BMO_slot_float_get(op->slots_in, "depth"); int segs = BMO_slot_int_get(op->slots_in, "segments"); - int cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends"); - int cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris"); + const bool cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends"); + const bool cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris"); int a; if (!segs) @@ -634,12 +634,12 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op) if (cap_ends) { BMFace *f; - f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, NULL, NULL, FALSE); + f = BM_face_create_quad_tri(bm, cent1, lastv1, v1, NULL, NULL, false); BMO_elem_flag_enable(bm, f, FACE_NEW); - f = BM_face_create_quad_tri(bm, cent2, v2, lastv2, NULL, NULL, FALSE); + f = BM_face_create_quad_tri(bm, cent2, v2, lastv2, NULL, NULL, false); BMO_elem_flag_enable(bm, f, FACE_NEW); } - BM_face_create_quad_tri(bm, lastv1, lastv2, v2, v1, NULL, FALSE); + BM_face_create_quad_tri(bm, lastv1, lastv2, v2, v1, NULL, false); } else { firstv1 = v1; @@ -656,9 +656,9 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op) if (cap_ends) { BMFace *f; - f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, FALSE); + f = BM_face_create_quad_tri(bm, cent1, v1, firstv1, NULL, NULL, false); BMO_elem_flag_enable(bm, f, FACE_NEW); - f = BM_face_create_quad_tri(bm, cent2, firstv2, v2, NULL, NULL, FALSE); + f = BM_face_create_quad_tri(bm, cent2, firstv2, v2, NULL, NULL, false); BMO_elem_flag_enable(bm, f, FACE_NEW); } @@ -666,7 +666,7 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op) BMO_op_callf(bm, op->flag, "dissolve_faces faces=%ff", FACE_NEW); } - BM_face_create_quad_tri(bm, v1, v2, firstv2, firstv1, NULL, FALSE); + BM_face_create_quad_tri(bm, v1, v2, firstv2, firstv1, NULL, false); BMO_op_callf(bm, op->flag, "remove_doubles verts=%fv dist=%f", VERT_MARK, 0.000001); BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); @@ -738,14 +738,14 @@ void bmo_create_cube_exec(BMesh *bm, BMOperator *op) BMO_elem_flag_enable(bm, v8, VERT_MARK); /* the four sides */ - BM_face_create_quad_tri(bm, v5, v6, v2, v1, NULL, FALSE); - BM_face_create_quad_tri(bm, v6, v7, v3, v2, NULL, FALSE); - BM_face_create_quad_tri(bm, v7, v8, v4, v3, NULL, FALSE); - BM_face_create_quad_tri(bm, v8, v5, v1, v4, NULL, FALSE); + BM_face_create_quad_tri(bm, v5, v6, v2, v1, NULL, false); + BM_face_create_quad_tri(bm, v6, v7, v3, v2, NULL, false); + BM_face_create_quad_tri(bm, v7, v8, v4, v3, NULL, false); + BM_face_create_quad_tri(bm, v8, v5, v1, v4, NULL, false); /* top/bottom */ - BM_face_create_quad_tri(bm, v1, v2, v3, v4, NULL, FALSE); - BM_face_create_quad_tri(bm, v8, v7, v6, v5, NULL, FALSE); + BM_face_create_quad_tri(bm, v1, v2, v3, v4, NULL, false); + BM_face_create_quad_tri(bm, v8, v7, v6, v5, NULL, false); BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c index 87e26f11d4b..7beac676868 100644 --- a/source/blender/bmesh/operators/bmo_removedoubles.c +++ b/source/blender/bmesh/operators/bmo_removedoubles.c @@ -41,7 +41,7 @@ static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op, BMOpSlot BMIter liter; BMLoop *l; BMVert *v2, *doub; - int split = FALSE; + bool split = false; BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { v2 = BMO_slot_map_elem_get(slot_targetmap, l->v); @@ -52,14 +52,14 @@ static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op, BMOpSlot (v2 != l->next->v)) { doub = l->v; - split = TRUE; + split = true; break; } } if (split && doub != v2) { BMLoop *nl; - BMFace *f2 = BM_face_split(bm, f, doub, v2, &nl, NULL, FALSE); + BMFace *f2 = BM_face_split(bm, f, doub, v2, &nl, NULL, false); remdoubles_splitface(f, bm, op, slot_targetmap); remdoubles_splitface(f2, bm, op, slot_targetmap); @@ -87,12 +87,12 @@ int remdoubles_face_overlaps(BMesh *bm, BMVert **varr, amount = BM_verts_in_face(bm, f, varr, len); if (amount >= len) { if (overlapface) *overlapface = f; - return TRUE; + return true; } f = BM_iter_step(&vertfaces); } } - return FALSE; + return false; } #endif @@ -394,11 +394,10 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op) if (!BMO_elem_flag_test(bm, e, EDGE_MARK)) continue; - e = BMW_begin(&walker, e->v1); BLI_array_empty(edges); INIT_MINMAX(min, max); - for (tot = 0; e; tot++, e = BMW_step(&walker)) { + for (e = BMW_begin(&walker, e->v1), tot = 0; e; e = BMW_step(&walker), tot++) { BLI_array_grow_one(edges); edges[tot] = e; @@ -454,11 +453,9 @@ static void bmo_collapsecon_do_layer(BMesh *bm, BMOperator *op, int layer) if (BMO_elem_flag_test(bm, l->e, EDGE_MARK)) { /* walk */ BLI_array_empty(blocks); - tot = 0; - l2 = BMW_begin(&walker, l); CustomData_data_initminmax(type, &min, &max); - for (tot = 0; l2; tot++, l2 = BMW_step(&walker)) { + for (l2 = BMW_begin(&walker, l), tot = 0; l2; l2 = BMW_step(&walker), tot++) { BLI_array_grow_one(blocks); blocks[tot] = CustomData_bmesh_get_layer_n(&bm->ldata, l2->head.data, layer); CustomData_data_dominmax(type, blocks[tot], &min, &max); diff --git a/source/blender/bmesh/operators/bmo_similar.c b/source/blender/bmesh/operators/bmo_similar.c index a8cc152bd4e..454f9ab2ad3 100644 --- a/source/blender/bmesh/operators/bmo_similar.c +++ b/source/blender/bmesh/operators/bmo_similar.c @@ -185,21 +185,21 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op) for (i = 0; i < num_total; i++) { fm = f_ext[i].f; if (!BMO_elem_flag_test(bm, fm, FACE_MARK) && !BM_elem_flag_test(fm, BM_ELEM_HIDDEN)) { - int cont = TRUE; - for (idx = 0; idx < num_sels && cont == TRUE; idx++) { + bool cont = true; + for (idx = 0; idx < num_sels && cont == true; idx++) { fs = f_ext[indices[idx]].f; switch (type) { case SIMFACE_MATERIAL: if (fm->mat_nr == fs->mat_nr) { BMO_elem_flag_enable(bm, fm, FACE_MARK); - cont = FALSE; + cont = false; } break; case SIMFACE_IMAGE: if (f_ext[i].t == f_ext[indices[idx]].t) { BMO_elem_flag_enable(bm, fm, FACE_MARK); - cont = FALSE; + cont = false; } break; @@ -207,7 +207,7 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op) angle = angle_normalized_v3v3(fs->no, fm->no); /* if the angle between the normals -> 0 */ if (angle <= thresh_radians) { BMO_elem_flag_enable(bm, fm, FACE_MARK); - cont = FALSE; + cont = false; } break; @@ -217,7 +217,7 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op) delta_fl = f_ext[i].d - f_ext[indices[idx]].d; if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) { BMO_elem_flag_enable(bm, fm, FACE_MARK); - cont = FALSE; + cont = false; } } break; @@ -226,7 +226,7 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op) delta_fl = f_ext[i].area - f_ext[indices[idx]].area; if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) { BMO_elem_flag_enable(bm, fm, FACE_MARK); - cont = FALSE; + cont = false; } break; @@ -234,7 +234,7 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op) delta_i = fm->len - fs->len; if (bm_sel_similar_cmp_i(delta_i, compare)) { BMO_elem_flag_enable(bm, fm, FACE_MARK); - cont = FALSE; + cont = false; } break; @@ -242,7 +242,7 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op) delta_fl = f_ext[i].perim - f_ext[indices[idx]].perim; if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) { BMO_elem_flag_enable(bm, fm, FACE_MARK); - cont = FALSE; + cont = false; } break; #ifdef WITH_FREESTYLE @@ -381,15 +381,15 @@ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op) for (i = 0; i < num_total; i++) { e = e_ext[i].e; if (!BMO_elem_flag_test(bm, e, EDGE_MARK) && !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { - int cont = TRUE; - for (idx = 0; idx < num_sels && cont == TRUE; idx++) { + bool cont = true; + for (idx = 0; idx < num_sels && cont == true; idx++) { es = e_ext[indices[idx]].e; switch (type) { case SIMEDGE_LENGTH: delta_fl = e_ext[i].length - e_ext[indices[idx]].length; if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) { BMO_elem_flag_enable(bm, e, EDGE_MARK); - cont = FALSE; + cont = false; } break; @@ -402,7 +402,7 @@ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op) if (angle / (float)(M_PI / 2.0) <= thresh) { BMO_elem_flag_enable(bm, e, EDGE_MARK); - cont = FALSE; + cont = false; } break; @@ -410,7 +410,7 @@ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op) delta_i = e_ext[i].faces - e_ext[indices[idx]].faces; if (bm_sel_similar_cmp_i(delta_i, compare)) { BMO_elem_flag_enable(bm, e, EDGE_MARK); - cont = FALSE; + cont = false; } break; @@ -419,12 +419,12 @@ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op) if (e_ext[indices[idx]].faces == 2) { if (fabsf(e_ext[i].angle - e_ext[indices[idx]].angle) <= thresh) { BMO_elem_flag_enable(bm, e, EDGE_MARK); - cont = FALSE; + cont = false; } } } else { - cont = FALSE; + cont = false; } break; @@ -438,7 +438,7 @@ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op) if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) { BMO_elem_flag_enable(bm, e, EDGE_MARK); - cont = FALSE; + cont = false; } } break; @@ -453,7 +453,7 @@ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op) if (bm_sel_similar_cmp_fl(delta_fl, thresh, compare)) { BMO_elem_flag_enable(bm, e, EDGE_MARK); - cont = FALSE; + cont = false; } } break; @@ -461,14 +461,14 @@ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op) case SIMEDGE_SEAM: if (BM_elem_flag_test(e, BM_ELEM_SEAM) == BM_elem_flag_test(es, BM_ELEM_SEAM)) { BMO_elem_flag_enable(bm, e, EDGE_MARK); - cont = FALSE; + cont = false; } break; case SIMEDGE_SHARP: if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) == BM_elem_flag_test(es, BM_ELEM_SMOOTH)) { BMO_elem_flag_enable(bm, e, EDGE_MARK); - cont = FALSE; + cont = false; } break; #ifdef WITH_FREESTYLE @@ -578,15 +578,15 @@ void bmo_similar_verts_exec(BMesh *bm, BMOperator *op) for (i = 0; i < num_total; i++) { v = v_ext[i].v; if (!BMO_elem_flag_test(bm, v, VERT_MARK) && !BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { - int cont = TRUE; - for (idx = 0; idx < num_sels && cont == TRUE; idx++) { + bool cont = true; + for (idx = 0; idx < num_sels && cont == true; idx++) { vs = v_ext[indices[idx]].v; switch (type) { case SIMVERT_NORMAL: /* compare the angle between the normals */ if (angle_normalized_v3v3(v->no, vs->no) <= thresh_radians) { BMO_elem_flag_enable(bm, v, VERT_MARK); - cont = FALSE; + cont = false; } break; case SIMVERT_FACE: @@ -594,7 +594,7 @@ void bmo_similar_verts_exec(BMesh *bm, BMOperator *op) delta_i = v_ext[i].num_faces - v_ext[indices[idx]].num_faces; if (bm_sel_similar_cmp_i(delta_i, compare)) { BMO_elem_flag_enable(bm, v, VERT_MARK); - cont = FALSE; + cont = false; } break; @@ -602,7 +602,7 @@ void bmo_similar_verts_exec(BMesh *bm, BMOperator *op) if (v_ext[i].dvert != NULL && v_ext[indices[idx]].dvert != NULL) { if (defvert_find_shared(v_ext[i].dvert, v_ext[indices[idx]].dvert) != -1) { BMO_elem_flag_enable(bm, v, VERT_MARK); - cont = FALSE; + cont = false; } } break; @@ -611,7 +611,7 @@ void bmo_similar_verts_exec(BMesh *bm, BMOperator *op) delta_i = v_ext[i].num_edges - v_ext[indices[idx]].num_edges; if (bm_sel_similar_cmp_i(delta_i, compare)) { BMO_elem_flag_enable(bm, v, VERT_MARK); - cont = FALSE; + cont = false; } break; default: diff --git a/source/blender/bmesh/operators/bmo_slide.c b/source/blender/bmesh/operators/bmo_slide.c deleted file mode 100644 index ea9f9bf9eba..00000000000 --- a/source/blender/bmesh/operators/bmo_slide.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributor(s): Francisco De La Cruz - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/bmesh/operators/bmo_slide.c - * \ingroup bmesh - */ - -#include "MEM_guardedalloc.h" - -#include "BKE_global.h" - -#include "BLI_math.h" - -#include "bmesh.h" -#include "intern/bmesh_operators_private.h" /* own include */ - -#define EDGE_MARK 1 -#define VERT_MARK 2 - -/* - * Slides a vertex along a connected edge - * - */ -void bmo_slide_vert_exec(BMesh *bm, BMOperator *op) -{ - BMOIter oiter; - BMIter iter; - BMHeader *h; - BMVert *vertex; - BMEdge *edge; - BMEdge *slide_edge; - - /* Selection counts */ - int selected_edges = 0; - - /* Get slide amount */ - const float factor = BMO_slot_float_get(op->slots_in, "factor"); - - /* Get start vertex */ - vertex = BMO_slot_buffer_get_single(BMO_slot_get(op->slots_in, "vert")); - - if (!vertex) { - if (G.debug & G_DEBUG) { - fprintf(stderr, "slide_vert: No vertex selected..."); - } - BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Vertex Slide error: invalid selection"); - return; - } - - /* BMESH_TODO - this is odd, it only uses one edge, why take a list at all? */ - /* Count selected edges */ - BMO_ITER (h, &oiter, op->slots_in, "edges", BM_EDGE) { - selected_edges++; - /* Mark all selected edges (cast BMHeader->BMEdge) */ - BMO_elem_flag_enable(bm, (BMElemF *)h, EDGE_MARK); - break; - } - - /* Only allow sliding if an edge is selected */ - if (selected_edges == 0) { - if (G.debug & G_DEBUG) { - fprintf(stderr, "slide_vert: select a single edge\n"); - } - BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Vertex Slide error: invalid selection"); - return; - } - - /* Make sure we get the correct edge. */ - slide_edge = NULL; - BM_ITER_ELEM (edge, &iter, vertex, BM_EDGES_OF_VERT) { - if (BMO_elem_flag_test(bm, edge, EDGE_MARK) && BM_vert_in_edge(edge, vertex)) { - slide_edge = edge; - break; - } - } - - /* Found edge */ - if (slide_edge) { - BMVert *other = BM_edge_other_vert(slide_edge, vertex); - - /* mark */ - BMO_elem_flag_enable(bm, vertex, VERT_MARK); - - /* Interpolate */ - interp_v3_v3v3(vertex->co, vertex->co, other->co, factor); - } - - /* Return the new edge. The same previously marked with VERT_MARK */ - BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); - return; -} - -#undef EDGE_MARK -#undef VERT_MARK diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c index ce584686757..ba755a866de 100644 --- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c +++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c @@ -180,7 +180,7 @@ static void init_laplacian_matrix(LaplacianSystem *sys) float *v1, *v2, *v3, *v4; float w1, w2, w3, w4; int i, j; - int has_4_vert; + bool has_4_vert; unsigned int idv1, idv2, idv3, idv4, idv[4]; BMEdge *e; BMFace *f; @@ -297,7 +297,7 @@ static void fill_laplacian_matrix(LaplacianSystem *sys) float *v1, *v2, *v3, *v4; float w2, w3, w4; int i, j; - int has_4_vert; + bool has_4_vert; unsigned int idv1, idv2, idv3, idv4, idv[4]; BMEdge *e; @@ -537,7 +537,7 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) { int i; int m_vertex_id; - int usex, usey, usez, preserve_volume; + bool usex, usey, usez, preserve_volume; float lambda_factor, lambda_border; float w; BMOIter siter; diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index 7407eb4423a..c7c33aa2775 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -90,7 +90,7 @@ static BMEdge *connect_smallest_face(BMesh *bm, BMVert *v1, BMVert *v2, BMFace * } if (curf) { - face = BM_face_split(bm, curf, v1, v2, &nl, NULL, FALSE); + face = BM_face_split(bm, curf, v1, v2, &nl, NULL, false); if (r_nf) *r_nf = face; return nl ? nl->e : NULL; @@ -715,8 +715,8 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) BMFace *face; BLI_array_declare(verts); float smooth, fractal, along_normal; - int use_sphere, cornertype, use_single_edge, use_grid_fill, use_only_quads; - int skey, seed, i, j, matched, a, b, numcuts, totesel; + bool use_sphere, use_single_edge, use_grid_fill, use_only_quads; + int cornertype, skey, seed, i, j, matched, a, b, numcuts, totesel; BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, SUBD_SPLIT); @@ -912,6 +912,10 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) j = BLI_array_count(facedata) - 1; BMO_elem_flag_enable(bm, face, SUBD_SPLIT); + + /* must initialize all members here */ + facedata[j].start = NULL; + facedata[j].pat = NULL; facedata[j].totedgesel = totesel; facedata[j].face = face; } @@ -983,7 +987,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) BLI_array_grow_items(loops_split, numcuts); for (j = 0; j < numcuts; j++) { - int ok = TRUE; + bool ok = true; /* Check for special case: [#32500] * This edge pair could be used by more then one face, @@ -1006,7 +1010,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) BLI_assert(other_loop->prev->v != loops[a]->v); BLI_assert(other_loop->next->v != loops[a]->v); - ok = FALSE; + ok = false; break; } } @@ -1014,7 +1018,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) } - if (ok == TRUE) { + if (ok == true) { loops_split[j][0] = loops[a]; loops_split[j][1] = loops[b]; } @@ -1036,10 +1040,10 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) for (j = 0; j < BLI_array_count(loops_split); j++) { if (loops_split[j][0]) { - BLI_assert(BM_edge_exists(loops_split[j][0]->v, loops_split[j][1]->v) == FALSE); + BLI_assert(BM_edge_exists(loops_split[j][0]->v, loops_split[j][1]->v) == NULL); /* BMFace *nf = */ /* UNUSED */ - BM_face_split(bm, face, loops_split[j][0]->v, loops_split[j][1]->v, &nl, NULL, FALSE); + BM_face_split(bm, face, loops_split[j][0]->v, loops_split[j][1]->v, &nl, NULL, false); } } @@ -1123,7 +1127,7 @@ void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, BMElem *ele; for (ele = BMO_iter_new(&iter, op.slots_out, "geom_inner.out", BM_EDGE | BM_VERT); ele; ele = BMO_iter_step(&iter)) { - BM_elem_select_set(bm, ele, TRUE); + BM_elem_select_set(bm, ele, true); } } else if (seltype == SUBDIV_SELECT_LOOPCUT) { @@ -1131,10 +1135,10 @@ void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, BMElem *ele; /* deselect input */ - BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, FALSE); + BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false); for (ele = BMO_iter_new(&iter, op.slots_out, "geom_inner.out", BM_EDGE | BM_VERT); ele; ele = BMO_iter_step(&iter)) { - BM_elem_select_set(bm, ele, TRUE); + BM_elem_select_set(bm, ele, true); if (ele->head.htype == BM_VERT) { BMEdge *e; @@ -1145,13 +1149,13 @@ void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, BM_elem_flag_test(e->v1, BM_ELEM_SELECT) && BM_elem_flag_test(e->v2, BM_ELEM_SELECT)) { - BM_edge_select_set(bm, e, TRUE); + BM_edge_select_set(bm, e, true); } else if (BM_elem_flag_test(e, BM_ELEM_SELECT) && (!BM_elem_flag_test(e->v1, BM_ELEM_SELECT) || !BM_elem_flag_test(e->v2, BM_ELEM_SELECT))) { - BM_edge_select_set(bm, e, FALSE); + BM_edge_select_set(bm, e, false); } } } diff --git a/source/blender/bmesh/operators/bmo_symmetrize.c b/source/blender/bmesh/operators/bmo_symmetrize.c index 172f0d40b27..0bfc81f83cf 100644 --- a/source/blender/bmesh/operators/bmo_symmetrize.c +++ b/source/blender/bmesh/operators/bmo_symmetrize.c @@ -176,7 +176,7 @@ static void symm_split_asymmetric_edges(Symm *symm) plane_co[symm->axis][0], plane_co[symm->axis][1], plane_co[symm->axis][2], - &lambda, TRUE); + &lambda, true); BLI_assert(r); madd_v3_v3v3fl(co, e->v1->co, edge_dir, lambda); @@ -244,7 +244,7 @@ typedef struct { int len; /* True only if none of the polygon's edges were split */ - int already_symmetric; + bool already_symmetric; BMFace *src_face; } SymmPoly; @@ -261,11 +261,11 @@ static void symm_poly_with_splits(const Symm *symm, /* Count vertices and check for edge splits */ out->len = f->len; - out->already_symmetric = TRUE; + out->already_symmetric = true; BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) { if (BLI_ghash_haskey(symm->edge_split_map, l->e)) { out->len++; - out->already_symmetric = FALSE; + out->already_symmetric = false; } } @@ -332,11 +332,11 @@ static BMVert *symm_poly_mirror_dst(const Symm *symm, return NULL; } -static int symm_poly_next_crossing(const Symm *symm, - const SymmPoly *sp, - int start, - int *l1, - int *l2) +static bool symm_poly_next_crossing(const Symm *symm, + const SymmPoly *sp, + int start, + int *l1, + int *l2) { int i; @@ -347,12 +347,12 @@ static int symm_poly_next_crossing(const Symm *symm, if ((symm_poly_co_side(symm, sp, *l1) == SYMM_SIDE_KILL) ^ (symm_poly_co_side(symm, sp, *l2) == SYMM_SIDE_KILL)) { - return TRUE; + return true; } } BLI_assert(!"symm_poly_next_crossing failed"); - return FALSE; + return false; } static BMFace *symm_face_create_v(BMesh *bm, BMFace *example, @@ -378,7 +378,7 @@ static BMFace *symm_face_create_v(BMesh *bm, BMFace *example, f_new = BM_face_create(bm, fv, fe, len, BM_CREATE_NO_DOUBLE); if (example) BM_elem_attrs_copy(bm, bm, example, f_new); - BM_face_select_set(bm, f_new, TRUE); + BM_face_select_set(bm, f_new, true); BMO_elem_flag_enable(bm, f_new, SYMM_OUTPUT_GEOM); return f_new; @@ -465,15 +465,15 @@ static void symm_mirror_polygons(Symm *symm) BMO_ITER (f, &oiter, symm->op->slots_in, "input", BM_FACE) { BMIter iter; BMLoop *l; - int mirror_all = TRUE, ignore_all = TRUE; + bool mirror_all = true, ignore_all = true; /* Check if entire polygon can be mirrored or ignored */ BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) { const SymmSide side = symm_co_side(symm, l->v->co); if (side == SYMM_SIDE_KILL) - mirror_all = FALSE; + mirror_all = false; else if (side == SYMM_SIDE_KEEP) - ignore_all = FALSE; + ignore_all = false; } if (mirror_all) { diff --git a/source/blender/bmesh/operators/bmo_triangulate.c b/source/blender/bmesh/operators/bmo_triangulate.c index 663ee463a2c..744f706681d 100644 --- a/source/blender/bmesh/operators/bmo_triangulate.c +++ b/source/blender/bmesh/operators/bmo_triangulate.c @@ -52,7 +52,7 @@ void bmo_triangulate_exec(BMesh *bm, BMOperator *op) float (*projectverts)[3] = NULL; BLI_array_declare(projectverts); int i; - const int use_beauty = BMO_slot_bool_get(op->slots_in, "use_beauty"); + const bool use_beauty = BMO_slot_bool_get(op->slots_in, "use_beauty"); BMOpSlot *slot_facemap_out = BMO_slot_get(op->slots_out, "face_map.out"); for (face = BMO_iter_new(&siter, op->slots_in, "faces", BM_FACE); face; face = BMO_iter_step(&siter)) { @@ -138,7 +138,7 @@ void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op) fac2 = opp1 / (len2 + len3 + len6) + opp2 / (len4 + len1 + len6); if (fac1 > fac2) { - e = BM_edge_rotate(bm, e, FALSE, BM_EDGEROT_CHECK_EXISTS); + e = BM_edge_rotate(bm, e, false, BM_EDGEROT_CHECK_EXISTS); if (e) { BMO_elem_flag_enable(bm, e, ELE_NEW); @@ -195,7 +195,7 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op) for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) { BMFace *f = BM_face_create_quad_tri(bm, sf_tri->v1->tmp.p, sf_tri->v2->tmp.p, sf_tri->v3->tmp.p, NULL, - NULL, TRUE); + NULL, true); BMLoop *l; BMIter liter; diff --git a/source/blender/bmesh/operators/bmo_unsubdivide.c b/source/blender/bmesh/operators/bmo_unsubdivide.c index fae7db3d175..784e695efb0 100644 --- a/source/blender/bmesh/operators/bmo_unsubdivide.c +++ b/source/blender/bmesh/operators/bmo_unsubdivide.c @@ -55,5 +55,5 @@ void bmo_unsubdivide_exec(BMesh *bm, BMOperator *op) } /* do all the real work here */ - BM_mesh_decimate_unsubdivide_ex(bm, iterations, TRUE); + BM_mesh_decimate_unsubdivide_ex(bm, iterations, true); } diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c index 64dbf0cc0e7..6398d9d04b1 100644 --- a/source/blender/bmesh/operators/bmo_utils.c +++ b/source/blender/bmesh/operators/bmo_utils.c @@ -122,8 +122,8 @@ void bmo_rotate_edges_exec(BMesh *bm, BMOperator *op) { BMOIter siter; BMEdge *e, *e2; - const int use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw"); - const int is_single = BMO_slot_buffer_count(op->slots_in, "edges") == 1; + const bool use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw"); + const bool is_single = BMO_slot_buffer_count(op->slots_in, "edges") == 1; short check_flag = is_single ? BM_EDGEROT_CHECK_EXISTS : BM_EDGEROT_CHECK_EXISTS | BM_EDGEROT_CHECK_DEGENERATE; @@ -140,8 +140,8 @@ void bmo_rotate_edges_exec(BMesh *bm, BMOperator *op) if (BM_edge_face_pair(e, &fa, &fb)) { /* check we're untouched */ - if (BMO_elem_flag_test(bm, fa, FACE_TAINT) == FALSE && - BMO_elem_flag_test(bm, fb, FACE_TAINT) == FALSE) + if (BMO_elem_flag_test(bm, fa, FACE_TAINT) == false && + BMO_elem_flag_test(bm, fb, FACE_TAINT) == false) { if (!(e2 = BM_edge_rotate(bm, e, use_ccw, check_flag))) { @@ -172,14 +172,14 @@ void bmo_rotate_edges_exec(BMesh *bm, BMOperator *op) #define SEL_FLAG 1 #define SEL_ORIG 2 -static void bmo_region_extend_extend(BMesh *bm, BMOperator *op, int usefaces) +static void bmo_region_extend_extend(BMesh *bm, BMOperator *op, const bool use_faces) { BMVert *v; BMEdge *e; BMIter eiter; BMOIter siter; - if (!usefaces) { + if (!use_faces) { BMO_ITER (v, &siter, op->slots_in, "geom", BM_VERT) { BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) @@ -216,14 +216,14 @@ static void bmo_region_extend_extend(BMesh *bm, BMOperator *op, int usefaces) } } -static void bmo_region_extend_constrict(BMesh *bm, BMOperator *op, int usefaces) +static void bmo_region_extend_constrict(BMesh *bm, BMOperator *op, const bool use_faces) { BMVert *v; BMEdge *e; BMIter eiter; BMOIter siter; - if (!usefaces) { + if (!use_faces) { BMO_ITER (v, &siter, op->slots_in, "geom", BM_VERT) { BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) @@ -265,8 +265,8 @@ static void bmo_region_extend_constrict(BMesh *bm, BMOperator *op, int usefaces) void bmo_region_extend_exec(BMesh *bm, BMOperator *op) { - int use_faces = BMO_slot_bool_get(op->slots_in, "use_faces"); - int constrict = BMO_slot_bool_get(op->slots_in, "use_constrict"); + const bool use_faces = BMO_slot_bool_get(op->slots_in, "use_faces"); + const bool constrict = BMO_slot_bool_get(op->slots_in, "use_constrict"); BMO_slot_buffer_flag_enable(bm, op->slots_in, "geom", BM_ALL_NOLOOP, SEL_ORIG); @@ -314,7 +314,8 @@ void bmo_recalc_face_normals_exec(BMesh *bm, BMOperator *op) BLI_array_declare(fstack); BMLoop *l, *l2; float maxx, maxx_test, cent[3]; - int i, i_max, flagflip = BMO_slot_bool_get(op->slots_in, "use_flip"); + int i, i_max; + const bool use_flip = BMO_slot_bool_get(op->slots_in, "use_flip"); startf = NULL; maxx = -1.0e10; @@ -349,7 +350,7 @@ void bmo_recalc_face_normals_exec(BMesh *bm, BMOperator *op) BM_face_normal_flip(bm, startf); BMO_elem_flag_toggle(bm, startf, FACE_FLIP); - if (flagflip) + if (use_flip) BM_elem_flag_toggle(startf, BM_ELEM_TAG); } @@ -381,11 +382,11 @@ void bmo_recalc_face_normals_exec(BMesh *bm, BMOperator *op) BM_face_normal_flip(bm, l2->f); BMO_elem_flag_toggle(bm, l2->f, FACE_FLIP); - if (flagflip) + if (use_flip) BM_elem_flag_toggle(l2->f, BM_ELEM_TAG); } else if (BM_elem_flag_test(l2->f, BM_ELEM_TAG) || BM_elem_flag_test(l->f, BM_ELEM_TAG)) { - if (flagflip) { + if (use_flip) { BM_elem_flag_disable(l->f, BM_ELEM_TAG); BM_elem_flag_disable(l2->f, BM_ELEM_TAG); } @@ -436,9 +437,11 @@ void bmo_smooth_vert_exec(BMesh *UNUSED(bm), BMOperator *op) i = 0; BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { BLI_array_grow_one(cos); + co = cos[i]; - - j = 0; + zero_v3(co); + + j = 0; BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { co2 = BM_edge_other_vert(e, v)->co; add_v3_v3v3(co, co, co2); @@ -489,11 +492,11 @@ void bmo_rotate_uvs_exec(BMesh *bm, BMOperator *op) BMFace *fs; /* current face */ BMIter l_iter; /* iteration loop */ - const int use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw"); + const bool use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw"); BMO_ITER (fs, &fs_iter, op->slots_in, "faces", BM_FACE) { if (CustomData_has_layer(&(bm->ldata), CD_MLOOPUV)) { - if (use_ccw == FALSE) { /* same loops direction */ + if (use_ccw == false) { /* same loops direction */ BMLoop *lf; /* current face loops */ MLoopUV *f_luv; /* first face loop uv */ float p_uv[2]; /* previous uvs */ @@ -594,11 +597,11 @@ void bmo_rotate_colors_exec(BMesh *bm, BMOperator *op) BMFace *fs; /* current face */ BMIter l_iter; /* iteration loop */ - const int use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw"); + const bool use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw"); BMO_ITER (fs, &fs_iter, op->slots_in, "faces", BM_FACE) { if (CustomData_has_layer(&(bm->ldata), CD_MLOOPCOL)) { - if (use_ccw == FALSE) { /* same loops direction */ + if (use_ccw == false) { /* same loops direction */ BMLoop *lf; /* current face loops */ MLoopCol *f_lcol; /* first face loop color */ MLoopCol p_col; /* previous color */ diff --git a/source/blender/bmesh/operators/bmo_wireframe.c b/source/blender/bmesh/operators/bmo_wireframe.c index 7401704310f..0d603faf3c4 100644 --- a/source/blender/bmesh/operators/bmo_wireframe.c +++ b/source/blender/bmesh/operators/bmo_wireframe.c @@ -134,34 +134,34 @@ static void bm_vert_boundary_tangent(BMVert *v, float r_no[3], float r_no_face[3 } /* check if we are the only tagged loop-face around this edge */ -static int bm_loop_is_radial_boundary(BMLoop *l_first) +static bool bm_loop_is_radial_boundary(BMLoop *l_first) { BMLoop *l = l_first->radial_next; if (l == l_first) { - return TRUE; /* a real boundary */ + return true; /* a real boundary */ } else { do { if (BM_elem_flag_test(l->f, BM_ELEM_TAG)) { - return FALSE; + return false; } } while ((l = l->radial_next) != l_first); } - return TRUE; + return true; } extern float BM_vert_calc_mean_tagged_edge_length(BMVert *v); void bmo_wireframe_exec(BMesh *bm, BMOperator *op) { - const int use_boundary = BMO_slot_bool_get(op->slots_in, "use_boundary"); - const int use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset"); - const int use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset"); - const int use_crease = (BMO_slot_bool_get(op->slots_in, "use_crease") && - CustomData_has_layer(&bm->edata, CD_CREASE)); - const float depth = BMO_slot_float_get(op->slots_in, "thickness"); - const float inset = depth; + const bool use_boundary = BMO_slot_bool_get(op->slots_in, "use_boundary"); + const bool use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset"); + const bool use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset"); + const bool use_crease = (BMO_slot_bool_get(op->slots_in, "use_crease") && + CustomData_has_layer(&bm->edata, CD_CREASE)); + const float depth = BMO_slot_float_get(op->slots_in, "thickness"); + const float inset = depth; const int totvert_orig = bm->totvert; @@ -203,7 +203,7 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) } /* setup tags, all faces and verts will be tagged which will be duplicated */ - BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, FALSE); + BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false); BMO_ITER (f_src, &oiter, op->slots_in, "faces", BM_FACE) { verts_loop_tot += f_src->len; @@ -239,13 +239,13 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) } /* conflicts with BM_vert_calc_mean_tagged_edge_length */ - if (use_relative_offset == FALSE) { + if (use_relative_offset == false) { BM_elem_flag_disable(v_src, BM_ELEM_TAG); } } if (use_relative_offset) { - BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, FALSE); + BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, false); } verts_loop = MEM_mallocN(sizeof(BMVert **) * verts_loop_tot, __func__); @@ -332,7 +332,7 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) BMVert *v_pos1 = verts_pos[i_1]; BMVert *v_pos2 = verts_pos[i_2]; - f_new = BM_face_create_quad_tri(bm, v_l1, v_l2, v_neg2, v_neg1, f_src, FALSE); + f_new = BM_face_create_quad_tri(bm, v_l1, v_l2, v_neg2, v_neg1, f_src, false); BM_elem_flag_enable(f_new, BM_ELEM_TAG); l_new = BM_FACE_FIRST_LOOP(f_new); @@ -341,7 +341,7 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) BM_elem_attrs_copy(bm, bm, l_next, l_new->next); BM_elem_attrs_copy(bm, bm, l_next, l_new->next->next); - f_new = BM_face_create_quad_tri(bm, v_l2, v_l1, v_pos1, v_pos2, f_src, FALSE); + f_new = BM_face_create_quad_tri(bm, v_l2, v_l1, v_pos1, v_pos2, f_src, false); BM_elem_flag_enable(f_new, BM_ELEM_TAG); l_new = BM_FACE_FIRST_LOOP(f_new); @@ -357,7 +357,7 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) BMVert *v_b1 = verts_boundary[i_1]; BMVert *v_b2 = verts_boundary[i_2]; - f_new = BM_face_create_quad_tri(bm, v_b2, v_b1, v_neg1, v_neg2, f_src, FALSE); + f_new = BM_face_create_quad_tri(bm, v_b2, v_b1, v_neg1, v_neg2, f_src, false); BM_elem_flag_enable(f_new, BM_ELEM_TAG); l_new = BM_FACE_FIRST_LOOP(f_new); @@ -366,7 +366,7 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) BM_elem_attrs_copy(bm, bm, l, l_new->next); BM_elem_attrs_copy(bm, bm, l, l_new->next->next); - f_new = BM_face_create_quad_tri(bm, v_b1, v_b2, v_pos2, v_pos1, f_src, FALSE); + f_new = BM_face_create_quad_tri(bm, v_b1, v_b2, v_pos2, v_pos1, f_src, false); BM_elem_flag_enable(f_new, BM_ELEM_TAG); l_new = BM_FACE_FIRST_LOOP(f_new); diff --git a/source/blender/bmesh/tools/BME_bevel.c b/source/blender/bmesh/tools/BME_bevel.c index 5e1d58150fa..47b507603f4 100644 --- a/source/blender/bmesh/tools/BME_bevel.c +++ b/source/blender/bmesh/tools/BME_bevel.c @@ -90,7 +90,7 @@ static BME_TransData *BME_assign_transdata(BME_TransData_Head *td, BMesh *bm, BM float factor, float weight, float maxfactor, float *max) { BME_TransData *vtd; - int is_new = 0; + int is_new = false; if (v == NULL) { return NULL; @@ -100,7 +100,7 @@ static BME_TransData *BME_assign_transdata(BME_TransData_Head *td, BMesh *bm, BM vtd = BLI_memarena_alloc(td->ma, sizeof(*vtd)); BLI_ghash_insert(td->gh, v, vtd); td->len++; - is_new = 1; + is_new = true; } vtd->bm = bm; @@ -151,12 +151,12 @@ static void BME_Bevel_Dissolve_Disk(BMesh *bm, BMVert *v) { BMFace *f; BMEdge *e; - int done; + bool done; if (v->e) { - done = FALSE; + done = false; while (!done) { - done = TRUE; + done = true; e = v->e; /*loop the edge looking for a edge to dissolve*/ do { f = NULL; @@ -164,14 +164,14 @@ static void BME_Bevel_Dissolve_Disk(BMesh *bm, BMVert *v) f = bmesh_jfke(bm, e->l->f, e->l->radial_next->f, e); } if (f) { - done = FALSE; + done = false; break; } e = bmesh_disk_edge_next(e, v); } while (e != v->e); } - BM_vert_collapse_edge(bm, v->e, v, TRUE); - // bmesh_jekv(bm, v->e, v, FALSE); + BM_vert_collapse_edge(bm, v->e, v, true); + // bmesh_jekv(bm, v->e, v, false); } } @@ -539,18 +539,18 @@ static BMLoop *BME_bevel_edge(BMesh *bm, BMLoop *l, float value, int UNUSED(opti se = l->next->e; jf = NULL; if (kl->v == kv) { - BM_face_split(bm, kl->f, kl->prev->v, kl->next->v, &nl, kl->prev->e, TRUE); + BM_face_split(bm, kl->f, kl->prev->v, kl->next->v, &nl, kl->prev->e, true); ke = kl->e; /* BMESH-TODO: jfke doesn't handle customdata */ jf = bmesh_jfke(bm, kl->prev->radial_next->f, kl->f, kl->prev->e); - BM_vert_collapse_edge(bm, ke, kv, FALSE); + BM_vert_collapse_edge(bm, ke, kv, false); } else { - BM_face_split(bm, kl->f, kl->next->next->v, kl->v, &nl, kl->next->e, TRUE); + BM_face_split(bm, kl->f, kl->next->next->v, kl->v, &nl, kl->next->e, true); ke = kl->e; /* BMESH-TODO: jfke doesn't handle customdata */ jf = bmesh_jfke(bm, kl->next->radial_next->f, kl->f, kl->next->e); - BM_vert_collapse_edge(bm, ke, kv, FALSE); + BM_vert_collapse_edge(bm, ke, kv, false); } /* find saved loop pointer */ l = se->l; @@ -585,18 +585,18 @@ static BMLoop *BME_bevel_edge(BMesh *bm, BMLoop *l, float value, int UNUSED(opti se = l->e; jf = NULL; if (kl->v == kv) { - BM_face_split(bm, kl->f, kl->prev->v, kl->next->v, &nl, kl->prev->e, TRUE); + BM_face_split(bm, kl->f, kl->prev->v, kl->next->v, &nl, kl->prev->e, true); ke = kl->e; /* BMESH-TODO: jfke doesn't handle customdata */ jf = bmesh_jfke(bm, kl->prev->radial_next->f, kl->f, kl->prev->e); - BM_vert_collapse_edge(bm, ke, kv, FALSE); + BM_vert_collapse_edge(bm, ke, kv, false); } else { - BM_face_split(bm, kl->f, kl->next->next->v, kl->v, &nl, kl->next->e, TRUE); + BM_face_split(bm, kl->f, kl->next->next->v, kl->v, &nl, kl->next->e, true); ke = kl->e; /* BMESH-TODO: jfke doesn't handle customdata */ jf = bmesh_jfke(bm, kl->next->radial_next->f, kl->f, kl->next->e); - BM_vert_collapse_edge(bm, ke, kv, FALSE); + BM_vert_collapse_edge(bm, ke, kv, false); } /* find saved loop pointer */ l = se->l; @@ -607,7 +607,7 @@ static BMLoop *BME_bevel_edge(BMesh *bm, BMLoop *l, float value, int UNUSED(opti } if (!BMO_elem_flag_test(bm, v1, BME_BEVEL_NONMAN) || !BMO_elem_flag_test(bm, v2, BME_BEVEL_NONMAN)) { - BM_face_split(bm, f, v2, v1, &l, e, TRUE); + BM_face_split(bm, f, v2, v1, &l, e, true); BMO_elem_flag_enable(bm, l->e, BME_BEVEL_BEVEL); l = l->radial_next; } @@ -636,7 +636,7 @@ static BMLoop *BME_bevel_vert(BMesh *bm, BMLoop *l, float value, int UNUSED(opti l = l->next->next; /* "cut off" this corner */ - /* f = */ BM_face_split(bm, l->f, v2, v1, NULL, l->e, TRUE); + /* f = */ BM_face_split(bm, l->f, v2, v1, NULL, l->e, true); return l; } @@ -1069,7 +1069,7 @@ static BMesh *BME_bevel_mesh(BMesh *bm, float value, int UNUSED(res), int option /* get rid of beveled edge */ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (BMO_elem_flag_test(bm, e, BME_BEVEL_BEVEL) && BMO_elem_flag_test(bm, e, BME_BEVEL_ORIG)) { - BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, TRUE); + BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, true); } } @@ -1083,9 +1083,9 @@ static BMesh *BME_bevel_mesh(BMesh *bm, float value, int UNUSED(res), int option if (l->v != v) l = l->next; if (l2->v != v) l2 = l2->next; if (l->f->len > 3) - BM_face_split(bm, l->f, l->next->v, l->prev->v, &l, l->e, TRUE); /* clip this corner off */ + BM_face_split(bm, l->f, l->next->v, l->prev->v, &l, l->e, true); /* clip this corner off */ if (l2->f->len > 3) - BM_face_split(bm, l2->f, l2->next->v, l2->prev->v, &l, l2->e, TRUE); /* clip this corner off */ + BM_face_split(bm, l2->f, l2->next->v, l2->prev->v, &l, l2->e, true); /* clip this corner off */ curedge = bmesh_disk_edge_next(curedge, v); } while (curedge != v->e); BME_Bevel_Dissolve_Disk(bm, v); diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index a593e40d850..5461e5fe788 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -41,10 +41,8 @@ -/* experemental - Campbell */ -// #define USE_ALTERNATE_ADJ - -#define BEVEL_EPSILON 1e-6 +#define BEVEL_EPSILON_D 1e-6 +#define BEVEL_EPSILON 1e-6f /* for testing */ // #pragma GCC diagnostic error "-Wpadded" @@ -94,7 +92,7 @@ typedef struct VMesh { M_NONE, /* no polygon mesh needed */ M_POLY, /* a simple polygon */ M_ADJ, /* "adjacent edges" mesh pattern */ -// M_CROSS, /* "cross edges" mesh pattern */ + M_ADJ_SUBDIV, /* like M_ADJ, but using subdivision */ M_TRI_FAN, /* a simple polygon - fan filled */ M_QUAD_STRIP, /* a simple polygon - cut into paralelle strips */ } mesh_kind; @@ -124,7 +122,7 @@ typedef struct BevelParams { // #pragma GCC diagnostic ignored "-Wpadded" -//#include "bevdebug.c" +// #include "bevdebug.c" /* Make a new BoundVert of the given kind, insert it at the end of the circular linked * list with entry point bv->boundstart, and return it. */ @@ -323,7 +321,7 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, sub_v3_v3v3(dir1, v->co, BM_edge_other_vert(e1->e, v)->co); sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co); - if (angle_v3v3(dir1, dir2) < 100.0f * (float)BEVEL_EPSILON) { + if (angle_v3v3(dir1, dir2) < 100.0f * BEVEL_EPSILON) { /* special case: e1 and e2 are parallel; put offset point perp to both, from v. * need to find a suitable plane. * if offsets are different, we're out of luck: just use e1->offset */ @@ -409,7 +407,7 @@ static void offset_in_two_planes(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, madd_v3_v3fl(off2a, norm_perp2, e2->offset); add_v3_v3v3(off2b, off2a, dir2); - if (angle_v3v3(dir1, dir2) < 100.0f * (float)BEVEL_EPSILON) { + if (angle_v3v3(dir1, dir2) < 100.0f * BEVEL_EPSILON) { /* lines are parallel; off1a is a good meet point */ copy_v3_v3(meetco, off1a); } @@ -421,7 +419,7 @@ static void offset_in_two_planes(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, } else if (iret == 2) { /* lines are not coplanar; meetco and isect2 are nearest to first and second lines */ - if (len_v3v3(meetco, isect2) > 100.0f * (float)BEVEL_EPSILON) { + if (len_v3v3(meetco, isect2) > 100.0f * BEVEL_EPSILON) { /* offset lines don't meet: project average onto emid; this is not ideal (see TODO above) */ mid_v3_v3v3(co, meetco, isect2); closest_to_line_v3(meetco, co, v->co, BM_edge_other_vert(emid->e, v)->co); @@ -470,7 +468,7 @@ static void slide_dist(EdgeHalf *e, BMVert *v, float d, float slideco[3]) sub_v3_v3v3(dir, v->co, BM_edge_other_vert(e->e, v)->co); len = normalize_v3(dir); if (d > len) - d = len - (float)(50.0 * BEVEL_EPSILON); + d = len - (float)(50.0 * BEVEL_EPSILON_D); copy_v3_v3(slideco, v->co); madd_v3_v3fl(slideco, dir, -d); } @@ -501,79 +499,6 @@ static int bev_ccw_test(BMEdge *a, BMEdge *b, BMFace *f) return lb->next == la ? 1 : -1; } -#ifdef USE_ALTERNATE_ADJ - -static void vmesh_cent(VMesh *vm, float r_cent[3]) -{ - BoundVert *v; - zero_v3(r_cent); - - v = vm->boundstart; - do { - add_v3_v3(r_cent, v->nv.co); - } while ((v = v->next) != vm->boundstart); - mul_v3_fl(r_cent, 1.0f / (float)vm->count); -} - -/** - * - * This example shows a tri fan of quads, - * but could be an NGon fan of quads too. - * <pre> - * The whole triangle X - * represents the / \ - * new bevel face. / \ - * / \ - * Split into / \ - * a quad fan. / \ - * / \ - * / \ - * / \ - * co_prev +-. .-+ - * / `-._ _.-' \ - * / co_cent`-+-' \ - * / | \ - * Quad of / | \ - * interest -- / ---> X | \ - * / | \ - * / | \ - * / co_next| \ - * co_orig +-----------------+-----------------+ - * - * For each quad, calcualte UV's based on the following: - * U = k / (vm->seg * 2) - * V = ring / (vm->seg * 2) - * quad = (co_orig, co_prev, co_cent, co_next) - * ... note that co_cent is the same for all quads in the fan. - * </pre> - * - */ - -static void get_point_uv(float uv[2], - /* all these args are int's originally - * but pass as floats to the function */ - const float seg, const float ring, const float k) -{ - uv[0] = (ring / seg) * 2.0f; - uv[1] = (k / seg) * 2.0f; -} - -/* TODO: make this a lot smarter!, - * this is the main reason USE_ALTERNATE_ADJ isn't so good right now :S */ -static float get_point_uv_factor(const float uv[2]) -{ - return sinf(1.0f - max_ff(uv[0], uv[1]) / 2.0f); -} - -static void get_point_on_round_edge(const float uv[2], - float quad[4][3], - float r_co[3]) -{ - interp_bilinear_quad_v3(quad, uv[0], uv[1], r_co); -} - -#else /* USE_ALTERNATE_ADJ */ - /* Fill matrix r_mat so that a point in the sheared parallelogram with corners * va, vmid, vb (and the 4th that is implied by it being a parallelogram) * is transformed to the unit square by multiplication with r_mat. @@ -601,7 +526,7 @@ static int make_unit_square_map(const float va[3], const float vmid[3], const fl sub_v3_v3v3(va_vmid, vmid, va); sub_v3_v3v3(vb_vmid, vmid, vb); - if (fabsf(angle_v3v3(va_vmid, vb_vmid) - (float)M_PI) > 100.f *(float)BEVEL_EPSILON) { + if (fabsf(angle_v3v3(va_vmid, vb_vmid) - (float)M_PI) > 100.0f * BEVEL_EPSILON) { sub_v3_v3v3(vo, va, vb_vmid); cross_v3_v3v3(vddir, vb_vmid, va_vmid); normalize_v3(vddir); @@ -694,8 +619,6 @@ static void snap_to_edge_profile(EdgeHalf *e, const float va[3], const float vb[ } } -#endif /* !USE_ALTERNATE_ADJ */ - /* Make a circular list of BoundVerts for bv, each of which has the coordinates * of a vertex on the the boundary of the beveled vertex bv->v. * Also decide on the mesh pattern that will be used inside the boundary. @@ -811,7 +734,10 @@ static void build_boundary(BevelParams *bp, BevVert *bv) } while ((e = e->next) != efirst); BLI_assert(vm->count >= 2); - if (vm->count == 2 && bv->edgecount == 3) { + if (bp->vertex_only) { + vm->mesh_kind = bp->seg > 1 ? M_ADJ_SUBDIV : M_POLY; + } + else if (vm->count == 2 && bv->edgecount == 3) { vm->mesh_kind = M_NONE; } else if (bv->selcount == 2) { @@ -846,19 +772,6 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) float co[3], coa[3], cob[3], midco[3]; float va_pipe[3], vb_pipe[3]; -#ifdef USE_ALTERNATE_ADJ - /* ordered as follows (orig, prev, center, next)*/ - float quad_plane[4][3]; - float quad_orig[4][3]; -#endif - - -#ifdef USE_ALTERNATE_ADJ - /* the rest are initialized inline, this remains the same for all */ - vmesh_cent(vm, quad_plane[2]); - copy_v3_v3(quad_orig[2], bv->v->co); -#endif - n = vm->count; ns = vm->seg; ns2 = ns / 2; @@ -875,7 +788,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) float dir1[3], dir2[3]; sub_v3_v3v3(dir1, bv->v->co, BM_edge_other_vert(e1->e, bv->v)->co); sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, bv->v)->co, bv->v->co); - if (angle_v3v3(dir1, dir2) < 100.0f * (float)BEVEL_EPSILON) { + if (angle_v3v3(dir1, dir2) < 100.0f * BEVEL_EPSILON) { epipe = e1; break; } @@ -918,37 +831,6 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) copy_v3_v3(nv->co, cob); nv->v = nvnext->v; -#ifdef USE_ALTERNATE_ADJ - /* plane */ - copy_v3_v3(quad_plane[0], v->nv.co); - mid_v3_v3v3(quad_plane[1], v->nv.co, v->prev->nv.co); - /* quad[2] is set */ - mid_v3_v3v3(quad_plane[3], v->nv.co, v->next->nv.co); - - /* orig */ - copy_v3_v3(quad_orig[0], v->nv.co); /* only shared location between 2 quads */ - project_to_edge(v->ebev->prev->e, v->nv.co, v->prev->nv.co, quad_orig[1]); - project_to_edge(v->ebev->e, v->nv.co, v->next->nv.co, quad_orig[3]); - - //bl_debug_draw_quad_add(UNPACK4(quad_plane)); - //bl_debug_draw_quad_add(UNPACK4(quad_orig)); -#endif - -#ifdef USE_ALTERNATE_ADJ - for (k = 1; k < ns; k++) { - float uv[2]; - float fac; - float co_plane[3]; - float co_orig[3]; - - get_point_uv(uv, v->ebev->seg, ring, k); - get_point_on_round_edge(uv, quad_plane, co_plane); - get_point_on_round_edge(uv, quad_orig, co_orig); - fac = get_point_uv_factor(uv); - interp_v3_v3v3(co, co_plane, co_orig, fac); - copy_v3_v3(mesh_vert(vm, i, ring, k)->co, co); - } -#else /* TODO: better calculation of new midarc point? */ project_to_edge(v->ebev->e, coa, cob, midco); @@ -962,7 +844,6 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) copy_v3_v3(va_pipe, mesh_vert(vm, i, 0, 0)->co); copy_v3_v3(vb_pipe, mesh_vert(vm, i, 0, ns)->co); } -#endif } } while ((v = v->next) != vm->boundstart); } @@ -990,9 +871,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) if (epipe) snap_to_edge_profile(epipe, va_pipe, vb_pipe, co); -#ifndef USE_ALTERNATE_ADJ copy_v3_v3(nv->co, co); -#endif BLI_assert(nv->v == NULL && nvprev->v == NULL); create_mesh_bmvert(bm, vm, i, ring, k, bv->v); copy_mesh_vert(vm, vprev->index, k, ns - ring, i, ring, k); @@ -1041,9 +920,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) mid_v3_v3v3v3(co, nvprev->co, nv->co, nvnext->co); if (epipe) snap_to_edge_profile(epipe, va_pipe, vb_pipe, co); -#ifndef USE_ALTERNATE_ADJ copy_v3_v3(nv->co, co); -#endif create_mesh_bmvert(bm, vm, i, k, ns2, bv->v); copy_mesh_vert(vm, vprev->index, ns2, ns - k, i, k, ns2); copy_mesh_vert(vm, vnext->index, ns2, k, i, k, ns2); @@ -1053,9 +930,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) mid_v3_v3v3(co, nvprev->co, nv->co); if (epipe) snap_to_edge_profile(epipe, va_pipe, vb_pipe, co); -#ifndef USE_ALTERNATE_ADJ copy_v3_v3(nv->co, co); -#endif create_mesh_bmvert(bm, vm, i, k, ns2, bv->v); copy_mesh_vert(vm, vprev->index, ns2, ns - k, i, k, ns2); @@ -1065,9 +940,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) mid_v3_v3v3(co, nv->co, nvnext->co); if (epipe) snap_to_edge_profile(epipe, va_pipe, vb_pipe, co); -#ifndef USE_ALTERNATE_ADJ copy_v3_v3(nv->co, co); -#endif create_mesh_bmvert(bm, vm, i, k, ns2, bv->v); copy_mesh_vert(vm, vnext->index, ns2, k, i, k, ns2); @@ -1220,6 +1093,413 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) } } +static VMesh *new_adj_subdiv_vmesh(MemArena *mem_arena, int count, int seg, BoundVert *bounds) +{ + VMesh *vm; + + vm = (VMesh *)BLI_memarena_alloc(mem_arena, sizeof(VMesh)); + vm->count = count; + vm->seg = seg; + vm->boundstart = bounds; + vm->mesh = (NewVert *)BLI_memarena_alloc(mem_arena, count * (1 + seg / 2) * (1 + seg) * sizeof(NewVert)); + vm->mesh_kind = M_ADJ_SUBDIV; + return vm; +} + +/* VMesh verts for vertex i have data for (i, 0 <= j <= ns2, 0 <= k <= ns), where ns2 = floor(nseg / 2). + * But these overlap data from previous and next i: there are some forced equivalences. + * Let's call these indices the canonical ones: we will just calculate data for these + * 0 <= j <= ns2, 0 <= k < ns2 (for odd ns2) + * 0 <= j < ns2, 0 <= k <= ns2 (for even ns2) + * also (j=ns2, k=ns2) at i=0 (for even ns2) + * This function returns the canonical one for any i, j, k in [0,n],[0,ns],[0,ns] */ +static NewVert *mesh_vert_canon(VMesh *vm, int i, int j, int k) +{ + int n, ns, ns2, odd; + NewVert *ans; + + n = vm->count; + ns = vm->seg; + ns2 = ns / 2; + odd = ns % 2; + BLI_assert(0 <= i && i <= n && 0 <= j && j <= ns && 0 <= k && k <= ns); + + if (!odd && j == ns2 && k == ns2) + ans = mesh_vert(vm, 0, j, k); + else if (j <= ns2 - 1 + odd && k <= ns2) + ans = mesh_vert(vm, i, j, k); + else if (k <= ns2) + ans = mesh_vert(vm, (i + n - 1) % n, k, ns - j); + else + ans = mesh_vert(vm, (i + 1) % n, ns - k, j); + return ans; +} + +static int is_canon(VMesh *vm, int i, int j, int k) +{ + int ns2 = vm->seg / 2; + if (vm->seg % 2 == 1) + return (j <= ns2 && k <= ns2); + else + return ((j < ns2 && k <= ns2) || (j == ns2 && k == ns2 && i == 0)); +} + +/* Copy the vertex data to all of vm verts from canonical ones */ +static void vmesh_copy_equiv_verts(VMesh *vm) +{ + int n, ns, ns2, i, j, k; + NewVert *v0, *v1; + + n = vm->count; + ns = vm->seg; + ns2 = ns / 2; + for (i = 0; i < n; i++) { + for (j = 0; j <= ns2; j++) { + for (k = 0; k <= ns; k++) { + if (is_canon(vm, i, j, k)) + continue; + v1 = mesh_vert(vm, i, j, k); + v0 = mesh_vert_canon(vm, i, j, k); + copy_v3_v3(v1->co, v0->co); + v1->v = v0->v; + } + } + } +} + +/* Calculate and return in r_cent the centroid of the center poly */ +static void vmesh_center(VMesh *vm, float r_cent[3]) +{ + int n, ns2, i; + + n = vm->count; + ns2 = vm->seg / 2; + if (vm->seg % 2) { + zero_v3(r_cent); + for (i = 0; i < n; i++) { + add_v3_v3(r_cent, mesh_vert(vm, i, ns2, ns2)->co); + } + mul_v3_fl(r_cent, 1.0f / (float) n); + } + else { + copy_v3_v3(r_cent, mesh_vert(vm, 0, ns2, ns2)->co); + } +} + +/* Do one step of quadratic subdivision (Doo-Sabin), with special rules at boundaries. + * For now, this is written assuming vm0->nseg is odd. + * See Hwang-Chuang 2003 paper: "N-sided hole filling and vertex blending using subdivision surfaces" */ +static VMesh *quadratic_subdiv(MemArena *mem_arena, VMesh *vm0) +{ + int n, ns0, ns20, ns1 /*, ns21 */; + int i, j, k, j1, k1; + VMesh *vm1; + float co[3], co1[3], co2[3], co3[3], co4[3]; + float co11[3], co21[3], co31[3], co41[3]; + float denom; + const float wcorner[4] = {0.25f, 0.25f, 0.25f, 0.25f}; + const float wboundary[4] = {0.375f, 0.375f, 0.125f, 0.125f}; /* {3, 3, 1, 1}/8 */ + const float winterior[4] = {0.5625f, 0.1875f, 0.1875f, 0.0625f}; /* {9, 3, 3, 1}/16 */ + + n = vm0->count; + ns0 = vm0->seg; + ns20 = ns0 / 2; + BLI_assert(ns0 % 2 == 1); + + ns1 = 2 * ns0 - 1; + // ns21 = ns1 / 2; /* UNUSED */ + vm1 = new_adj_subdiv_vmesh(mem_arena, n, ns1, vm0->boundstart); + + for (i = 0; i < n; i ++) { + /* For handle vm0 polys with lower left corner at (i,j,k) for + * j in [0, ns20], k in [0, ns20]; then the center ngon. + * but only fill in data for canonical verts of v1. */ + for (j = 0; j <= ns20; j++) { + for (k = 0; k <= ns20; k++) { + if (j == ns20 && k == ns20) + continue; /* center ngon is special */ + copy_v3_v3(co1, mesh_vert_canon(vm0, i, j, k)->co); + copy_v3_v3(co2, mesh_vert_canon(vm0, i, j, k + 1)->co); + copy_v3_v3(co3, mesh_vert_canon(vm0, i, j + 1, k + 1)->co); + copy_v3_v3(co4, mesh_vert_canon(vm0, i, j + 1, k)->co); + if (j == 0 && k == 0) { + /* corner */ + copy_v3_v3(co11, co1); + interp_v3_v3v3(co21, co1, co2, 0.5f); + interp_v3_v3v3v3v3(co31, co1, co2, co3, co4, wcorner); + interp_v3_v3v3(co41, co1, co4, 0.5f); + } + else if (j == 0) { + /* ring 0 boundary */ + interp_v3_v3v3(co11, co1, co2, 0.25f); + interp_v3_v3v3(co21, co1, co2, 0.75f); + interp_v3_v3v3v3v3(co31, co2, co3, co1, co4, wboundary); + interp_v3_v3v3v3v3(co41, co1, co4, co2, co3, wboundary); + } + else if (k == 0) { + /* ring-starts boundary */ + interp_v3_v3v3(co11, co1, co4, 0.25f); + interp_v3_v3v3v3v3(co21, co1, co2, co3, co4, wboundary); + interp_v3_v3v3v3v3(co31, co3, co4, co1, co2, wboundary); + interp_v3_v3v3(co41, co1, co4, 0.75f); + } + else { + /* interior */ + interp_v3_v3v3v3v3(co11, co1, co2, co4, co3, winterior); + interp_v3_v3v3v3v3(co21, co2, co1, co3, co4, winterior); + interp_v3_v3v3v3v3(co31, co3, co2, co4, co1, winterior); + interp_v3_v3v3v3v3(co41, co4, co1, co3, co2, winterior); + } + j1 = 2 * j; + k1 = 2 * k; + if (is_canon(vm1, i, j1, k1)) + copy_v3_v3(mesh_vert(vm1, i, j1, k1)->co, co11); + if (is_canon(vm1, i, j1, k1 + 1)) + copy_v3_v3(mesh_vert(vm1, i, j1, k1 + 1)->co, co21); + if (is_canon(vm1, i, j1 + 1, k1 + 1)) + copy_v3_v3(mesh_vert(vm1, i, j1 + 1, k1 + 1)->co, co31); + if (is_canon(vm1, i, j1 + 1, k1)) + copy_v3_v3(mesh_vert(vm1, i, j1 + 1, k1)->co, co41); + } + } + + /* center ngon */ + denom = 8.0f * (float) n; + zero_v3(co); + for (j = 0; j < n; j++) { + copy_v3_v3(co1, mesh_vert(vm0, j, ns20, ns20)->co); + if (i == j) + madd_v3_v3fl(co, co1, (4.0f * (float) n + 2.0f) / denom); + else if ((i + 1) % n == j || (i + n - 1) % n == j) + madd_v3_v3fl(co, co1, ((float) n + 2.0f) / denom); + else + madd_v3_v3fl(co, co1, 2.0f / denom); + } + copy_v3_v3(mesh_vert(vm1, i, 2 * ns20, 2 * ns20)->co, co); + } + + vmesh_copy_equiv_verts(vm1); + return vm1; +} + +/* After a step of quadratic_subdiv, adjust the ring 1 verts to be on the planes of their respective faces, + * so that the cross-tangents will match on further subdivision. */ +static void fix_vmesh_tangents(VMesh *vm, BevVert *bv) +{ + int i, n; + NewVert *v; + BoundVert *bndv; + float co[3]; + + n = vm->count; + bndv = vm->boundstart; + do { + i = bndv->index; + + /* (i, 1, 1) snap to edge line */ + v = mesh_vert(vm, i, 1, 1); + closest_to_line_v3(co, v->co, bndv->nv.co, bv->v->co); + copy_v3_v3(v->co, co); + copy_v3_v3(mesh_vert(vm, (i + n -1) % n, 1, vm->seg - 1)->co, co); + + /* Also want (i, 1, k) snapped to plane of adjacent face for + * 1 < k < ns - 1, but current initial cage and subdiv rules + * ensure this, so nothing to do */ + } while ((bndv = bndv->next) != vm->boundstart); +} + +/* Fill frac with fractions of way along ring 0 for vertex i, for use with interp_range function */ +static void fill_vmesh_fracs(VMesh *vm, float *frac, int i) +{ + int k, ns; + float total = 0.0f; + + ns = vm->seg; + frac[0] = 0.0f; + for (k = 0; k < ns; k++) { + total += len_v3v3(mesh_vert(vm, i, 0, k)->co, mesh_vert(vm, i, 0, k + 1)->co); + frac[k + 1] = total; + } + if (total > BEVEL_EPSILON) { + for (k = 1; k <= ns; k++) + frac[k] /= total; + } +} + +/* Return i such that frac[i] <= f <= frac[i + 1], where frac[n] == 1.0 + * and put fraction of rest of way between frac[i] and frac[i + 1] into r_rest */ +static int interp_range(const float *frac, int n, const float f, float *r_rest) +{ + int i; + float rest; + + /* could binary search in frac, but expect n to be reasonably small */ + for (i = 0; i < n; i++) { + if (f <= frac[i + 1]) { + rest = f - frac[i]; + if (rest == 0) + *r_rest = 0.0f; + else + *r_rest = rest / (frac[i + 1] - frac[i]); + return i; + } + } + *r_rest = 0.0f; + return n; +} + +/* Interpolate given vmesh to make one with target nseg and evenly spaced border vertices */ +static VMesh *interp_vmesh(MemArena *mem_arena, VMesh *vm0, int nseg) +{ + int n, ns0, nseg2, odd, i, j, k, j0, k0; + float *prev_frac, *frac, f, restj, restk; + float quad[4][3], co[3], center[3]; + VMesh *vm1; + + n = vm0->count; + ns0 = vm0->seg; + nseg2 = nseg / 2; + odd = nseg % 2; + vm1 = new_adj_subdiv_vmesh(mem_arena, n, nseg, vm0->boundstart); + prev_frac = (float *)BLI_memarena_alloc(mem_arena, (ns0 + 1 ) *sizeof(float)); + frac = (float *)BLI_memarena_alloc(mem_arena, (ns0 + 1 ) *sizeof(float)); + + fill_vmesh_fracs(vm0, prev_frac, n - 1); + fill_vmesh_fracs(vm0, frac, 0); + for (i = 0; i < n; i++) { + for (j = 0; j <= nseg2 -1 + odd; j++) { + for (k = 0; k <= nseg2; k++) { + f = (float) k / (float) nseg; + k0 = interp_range(frac, ns0, f, &restk); + f = 1.0f - (float) j / (float) nseg; + j0 = interp_range(prev_frac, ns0, f, &restj); + if (restj < BEVEL_EPSILON) { + j0 = ns0 - j0; + restj = 0.0f; + } + else { + j0 = ns0 - j0 - 1; + restj = 1.0f - restj; + } + /* Use bilinear interpolation within the source quad; could be smarter here */ + if (restj < BEVEL_EPSILON && restk < BEVEL_EPSILON) { + copy_v3_v3(co, mesh_vert_canon(vm0, i, j0, k0)->co); + } + else { + copy_v3_v3(quad[0], mesh_vert_canon(vm0, i, j0, k0)->co); + copy_v3_v3(quad[1], mesh_vert_canon(vm0, i, j0, k0 + 1)->co); + copy_v3_v3(quad[2], mesh_vert_canon(vm0, i, j0 + 1, k0 + 1)->co); + copy_v3_v3(quad[3], mesh_vert_canon(vm0, i, j0 + 1, k0)->co); + interp_bilinear_quad_v3(quad, restk, restj, co); + } + copy_v3_v3(mesh_vert(vm1, i, j, k)->co, co); + } + } + } + if (!odd) { + vmesh_center(vm0, center); + copy_v3_v3(mesh_vert(vm1, 0, nseg2, nseg2)->co, center); + } + vmesh_copy_equiv_verts(vm1); + return vm1; +} + +/* + * Given that the boundary is built and the boundary BMVerts have been made, + * calculate the positions of the interior mesh points for the M_ADJ_SUBDIV pattern, + * then make the BMVerts and the new faces. */ +static void bevel_build_rings_subdiv(BevelParams *bp, BMesh *bm, BevVert *bv) +{ + int n, ns, ns2, odd, i, j, k; + VMesh *vm0, *vm1, *vm; + float coa[3], cob[3], coc[3]; + BoundVert *v; + BMVert *bmv1, *bmv2, *bmv3, *bmv4; + BMFace *f; + MemArena *mem_arena = bp->mem_arena; + const float fullness = 0.5f; + + n = bv->edgecount; + ns = bv->vmesh->seg; + ns2 = ns / 2; + odd = ns % 2; + BLI_assert(n >= 3 && ns > 1); + + /* First construct an initial control mesh, with nseg==3 */ + vm0 = new_adj_subdiv_vmesh(mem_arena, n, 3, bv->vmesh->boundstart); + + for (i = 0; i < n; i++) { + /* Boundaries just divide input polygon edges into 3 even segments */ + copy_v3_v3(coa, mesh_vert(bv->vmesh, i, 0, 0)->co); + copy_v3_v3(cob, mesh_vert(bv->vmesh, (i + 1) % n, 0, 0)->co); + copy_v3_v3(coc, mesh_vert(bv->vmesh, (i + n -1) % n, 0, 0)->co); + copy_v3_v3(mesh_vert(vm0, i, 0, 0)->co, coa); + interp_v3_v3v3(mesh_vert(vm0, i, 0, 1)->co, coa, cob, 1.0f / 3.0f); + interp_v3_v3v3(mesh_vert(vm0, i, 1, 0)->co, coa, coc, 1.0f / 3.0f); + interp_v3_v3v3(mesh_vert(vm0, i, 1, 1)->co, coa, bv->v->co, fullness); + } + vmesh_copy_equiv_verts(vm0); + + vm1 = vm0; + do { + vm1 = quadratic_subdiv(mem_arena, vm1); + fix_vmesh_tangents(vm1, bv); + } while (vm1->seg <= ns); + vm1 = interp_vmesh(mem_arena, vm1, ns); + + /* copy final vmesh into bv->vmesh, make BMVerts and BMFaces */ + vm = bv->vmesh; + for (i = 0; i < n; i ++) { + for (j = 0; j <= ns2; j++) { + for (k = 0; k <= ns; k++) { + if (j == 0 && (k == 0 || k == ns)) + continue; /* boundary corners already made */ + if (!is_canon(vm, i, j, k)) + continue; + copy_v3_v3(mesh_vert(vm, i, j, k)->co, mesh_vert(vm1, i, j, k)->co); + create_mesh_bmvert(bm, vm, i, j, k, bv->v); + } + } + } + vmesh_copy_equiv_verts(vm); + /* make the polygons */ + v = vm->boundstart; + do { + i = v->index; + f = boundvert_rep_face(v); + /* For odd ns, make polys with lower left corner at (i,j,k) for + * j in [0, ns2-1], k in [0, ns2]. And then the center ngon. + * For even ns, + * j in [0, ns2-1], k in [0, ns2-1] */ + for (j = 0; j < ns2; j++) { + for (k = 0; k < ns2 + odd; k++) { + bmv1 = mesh_vert(vm, i, j, k)->v; + bmv2 = mesh_vert(vm, i, j, k + 1)->v; + bmv3 = mesh_vert(vm, i, j + 1, k + 1)->v; + bmv4 = mesh_vert(vm, i, j + 1, k)->v; + BLI_assert(bmv1 && bmv2 && bmv3 && bmv4); + bev_create_quad_tri(bm, bmv1, bmv2, bmv3, bmv4, f); + } + } + } while ((v = v->next) != vm->boundstart); + + /* center ngon */ + if (odd) { + BMVert **vv = NULL; + BLI_array_staticdeclare(vv, BM_DEFAULT_NGON_STACK_SIZE); + + v = vm->boundstart; + do { + i = v->index; + BLI_array_append(vv, mesh_vert(vm, i, ns2, ns2)->v); + } while ((v = v->next) != vm->boundstart); + f = boundvert_rep_face(vm->boundstart); + bev_create_ngon(bm, vv, BLI_array_count(vv), f); + + BLI_array_free(vv); + } +} + static BMFace *bevel_build_poly_ex(BMesh *bm, BevVert *bv) { BMFace *f; @@ -1339,24 +1619,7 @@ static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv) BoundVert *v, *weld1, *weld2; int n, ns, ns2, i, k, weld; float *va, *vb, co[3]; - -#ifdef USE_ALTERNATE_ADJ - /* ordered as follows (orig, prev, center, next)*/ - float quad_plane[4][3]; - float quad_orig_a[4][3]; - float quad_orig_b[4][3]; - const int is_odd = (vm->seg % 2); -#else float midco[3]; -#endif - -#ifdef USE_ALTERNATE_ADJ - /* the rest are initialized inline, this remains the same for all */ - /* NOTE; in this usage we only interpolate on the 'V' so cent and next points are unused (2,3)*/ - vmesh_cent(vm, quad_plane[2]); - copy_v3_v3(quad_orig_a[2], bv->v->co); - copy_v3_v3(quad_orig_b[2], bv->v->co); -#endif n = vm->count; ns = vm->seg; @@ -1389,59 +1652,6 @@ static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv) i = v->index; copy_mesh_vert(vm, i, 0, ns, v->next->index, 0, 0); if (v->ebev) { - -#ifdef USE_ALTERNATE_ADJ - copy_v3_v3(quad_plane[0], v->nv.co); - mid_v3_v3v3(quad_plane[1], v->nv.co, v->prev->nv.co); - /* quad[2] is set */ - mid_v3_v3v3(quad_plane[3], v->nv.co, v->next->nv.co); - - /* orig 'A' */ - copy_v3_v3(quad_orig_a[0], v->nv.co); /* only shared location between 2 quads */ - project_to_edge(v->ebev->prev->e, v->nv.co, v->prev->nv.co, quad_orig_a[1]); - project_to_edge(v->ebev->e, v->nv.co, v->next->nv.co, quad_orig_a[3]); - - /* orig 'B' */ - copy_v3_v3(quad_orig_b[3], v->next->nv.co); /* only shared location between 2 quads */ - project_to_edge(v->ebev->prev->e, v->nv.co, v->prev->nv.co, quad_orig_b[1]); - project_to_edge(v->ebev->e, v->nv.co, v->next->nv.co, quad_orig_b[0]); - - //bl_debug_draw_quad_add(UNPACK4(quad_plane)); - //bl_debug_draw_quad_add(UNPACK4(quad_orig_a)); - //bl_debug_draw_quad_add(UNPACK4(quad_orig_b)); -#endif /* USE_ALTERNATE_ADJ */ - -#ifdef USE_ALTERNATE_ADJ - for (k = 1; k < ns; k++) { - float uv[2]; - float fac; - float co_plane[3]; - float co_orig[3]; - - /* quad_plane */ - get_point_uv(uv, v->ebev->seg, 0, k); - get_point_on_round_edge(uv, quad_plane, co_plane); - - /* quad_orig */ - /* each half has different UV's */ - if (k <= ns2) { - get_point_uv(uv, v->ebev->seg, 0, k); - get_point_on_round_edge(uv, quad_orig_a, co_orig); - } - else { - get_point_uv(uv, v->ebev->seg, 0, (k - ns2) - (is_odd ? 0.5f : 0.0f)); - get_point_on_round_edge(uv, quad_orig_b, co_orig); - uv[1] = 1.0f - uv[1]; /* so we can get the factor */ - } - fac = get_point_uv_factor(uv); - - /* done. interp */ - interp_v3_v3v3(co, co_plane, co_orig, fac); - copy_v3_v3(mesh_vert(vm, i, 0, k)->co, co); - if (!weld) - create_mesh_bmvert(bm, vm, i, 0, k, bv->v); - } -#else /* USE_ALTERNATE_ADJ */ va = mesh_vert(vm, i, 0, 0)->co; vb = mesh_vert(vm, i, 0, ns)->co; project_to_edge(v->ebev->e, va, vb, midco); @@ -1451,7 +1661,6 @@ static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv) if (!weld) create_mesh_bmvert(bm, vm, i, 0, k, bv->v); } -#endif /* !USE_ALTERNATE_ADJ */ } } while ((v = v->next) != vm->boundstart); @@ -1478,6 +1687,9 @@ static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv) case M_ADJ: bevel_build_rings(bm, bv); break; + case M_ADJ_SUBDIV: + bevel_build_rings_subdiv(bp, bm, bv); + break; case M_TRI_FAN: bevel_build_trifan(bm, bv); break; @@ -1687,6 +1899,14 @@ static int bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) BLI_array_append(vv, bmv); } } + else if (bp->vertex_only && vm->mesh_kind == M_ADJ_SUBDIV && vm->seg > 1) { + BLI_assert(v->prev == vend); + i = vend->index; + for (k = vm->seg - 1; k > 0; k--) { + bmv = mesh_vert(vm, i, 0, k)->v; + BLI_array_append(vv, bmv); + } + } v = v->prev; BLI_array_append(vv, v->nv.v); } diff --git a/source/blender/bmesh/tools/bmesh_decimate.h b/source/blender/bmesh/tools/bmesh_decimate.h index 4a557c20ae3..d3eaf1c6670 100644 --- a/source/blender/bmesh/tools/bmesh_decimate.h +++ b/source/blender/bmesh/tools/bmesh_decimate.h @@ -27,15 +27,15 @@ * \ingroup bmesh */ -void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, const int do_triangulate); +void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, const bool do_triangulate); -void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int tag_only); +void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool tag_only); void BM_mesh_decimate_unsubdivide(BMesh *bm, const int iterations); -void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries, +void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, BMVert **vinput_arr, const int vinput_len, BMEdge **einput_arr, const int einput_len); -void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries); +void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries); /* these weights are accumulated so too high values may reach 'inf' too quickly */ #define BM_MESH_DECIM_WEIGHT_MAX 100000.0f diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c index 794afb3e0d2..e94bb9f5417 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c @@ -134,7 +134,7 @@ static void bm_decim_calc_target_co(BMEdge *e, float optimize_co[3], } } -static int bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_co[3]) +static bool bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_co[3]) { BMIter liter; BMLoop *l; @@ -175,13 +175,13 @@ static int bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_c * (first making it zero area, then flipping again) */ if (dot_v3v3(cross_exist, cross_optim) <= FLT_EPSILON) { //printf("no flip\n"); - return TRUE; + return true; } } } } - return FALSE; + return false; } static void bm_decim_build_edge_cost_single(BMEdge *e, @@ -291,15 +291,15 @@ static void bm_decim_build_edge_cost(BMesh *bm, * collapsing edges so even has some advantage over decimating quads * directly. * - * \return TRUE if any faces were triangulated. + * \return true if any faces were triangulated. */ -static int bm_decim_triangulate_begin(BMesh *bm) +static bool bm_decim_triangulate_begin(BMesh *bm) { BMIter iter; BMFace *f; - // int has_quad; // could optimize this a little - int has_cut = FALSE; + // bool has_quad; // could optimize this a little + bool has_cut = false; BLI_assert((bm->elem_index_dirty & BM_VERT) == 0); @@ -345,7 +345,7 @@ static int bm_decim_triangulate_begin(BMesh *bm) } #ifdef USE_SAFETY_CHECKS - if (BM_edge_exists(l_a->v, l_b->v) == FALSE) + if (BM_edge_exists(l_a->v, l_b->v) == false) #endif { BMFace *f_new; @@ -355,7 +355,7 @@ static int bm_decim_triangulate_begin(BMesh *bm) * - if there is a quad that has a free standing edge joining it along * where we want to split the face, there isnt a good way we can handle this. * currently that edge will get removed when joining the tris back into a quad. */ - f_new = BM_face_split(bm, f, l_a->v, l_b->v, &l_new, NULL, FALSE); + f_new = BM_face_split(bm, f, l_a->v, l_b->v, &l_new, NULL, false); if (f_new) { /* the value of this doesn't matter, only that the 2 loops match and have unique values */ @@ -370,7 +370,7 @@ static int bm_decim_triangulate_begin(BMesh *bm) BM_face_normal_update(f); BM_face_normal_update(f_new); - has_cut = TRUE; + has_cut = true; } } } @@ -410,15 +410,15 @@ static void bm_decim_triangulate_end(BMesh *bm) BM_vert_in_edge(e, l_b->next->v) ? l_b->prev->v : l_b->next->v, }; - BLI_assert(ELEM3(vquad[0], vquad[1], vquad[2], vquad[3]) == FALSE); - BLI_assert(ELEM3(vquad[1], vquad[0], vquad[2], vquad[3]) == FALSE); - BLI_assert(ELEM3(vquad[2], vquad[1], vquad[0], vquad[3]) == FALSE); - BLI_assert(ELEM3(vquad[3], vquad[1], vquad[2], vquad[0]) == FALSE); + BLI_assert(ELEM3(vquad[0], vquad[1], vquad[2], vquad[3]) == false); + BLI_assert(ELEM3(vquad[1], vquad[0], vquad[2], vquad[3]) == false); + BLI_assert(ELEM3(vquad[2], vquad[1], vquad[0], vquad[3]) == false); + BLI_assert(ELEM3(vquad[3], vquad[1], vquad[2], vquad[0]) == false); if (is_quad_convex_v3(vquad[0]->co, vquad[1]->co, vquad[2]->co, vquad[3]->co)) { /* highly unlikely to fail, but prevents possible double-ups */ BMFace *f[2] = {l_a->f, l_b->f}; - BM_faces_join(bm, f, 2, TRUE); + BM_faces_join(bm, f, 2, true); } } } @@ -445,7 +445,7 @@ static void bm_edge_collapse_loop_customdata(BMesh *bm, BMLoop *l, BMVert *v_cle //#define USE_SEAM /* these don't need to be updated, since they will get removed when the edge collapses */ BMLoop *l_clear, *l_other; - const int is_manifold = BM_edge_is_manifold(l->e); + const bool is_manifold = BM_edge_is_manifold(l->e); int side; /* l defines the vert to collapse into */ @@ -467,7 +467,7 @@ static void bm_edge_collapse_loop_customdata(BMesh *bm, BMLoop *l, BMVert *v_cle /* now we have both corners of the face 'l->f' */ for (side = 0; side < 2; side++) { #ifdef USE_SEAM - int is_seam = FALSE; + bool is_seam = false; #endif void *src[2]; BMFace *f_exit = is_manifold ? l->radial_next->f : NULL; @@ -507,7 +507,7 @@ static void bm_edge_collapse_loop_customdata(BMesh *bm, BMLoop *l, BMVert *v_cle #ifdef USE_SEAM /* break out unless we find a match */ - is_seam = TRUE; + is_seam = true; #endif /* ok. we have a loop. now be smart with it! */ @@ -517,13 +517,13 @@ static void bm_edge_collapse_loop_customdata(BMesh *bm, BMLoop *l, BMVert *v_cle const int type = bm->ldata.layers[i].type; void *cd_src[2] = {(char *)src[0] + offset, (char *)src[1] + offset}; - void *cd_iter = (char *)l_iter->head.data + offset;; + void *cd_iter = (char *)l_iter->head.data + offset; /* detect seams */ if (CustomData_data_equals(type, cd_src[0], cd_iter)) { CustomData_bmesh_interp_n(&bm->ldata, cd_src, w, NULL, 2, l_iter->head.data, i); #ifdef USE_SEAM - is_seam = FALSE; + is_seam = false; #endif } } @@ -598,7 +598,7 @@ BLI_INLINE int bm_edge_is_manifold_or_boundary(BMLoop *l) #endif } -static int bm_edge_collapse_is_degenerate_topology(BMEdge *e_first) +static bool bm_edge_collapse_is_degenerate_topology(BMEdge *e_first) { /* simply check that there is no overlap between faces and edges of each vert, * (excluding the 2 faces attached to 'e' and 'e' its self) */ @@ -609,7 +609,7 @@ static int bm_edge_collapse_is_degenerate_topology(BMEdge *e_first) e_iter = e_first; do { if (!bm_edge_is_manifold_or_boundary(e_iter->l)) { - return TRUE; + return true; } bm_edge_tag_disable(e_iter); } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v1)) != e_first); @@ -617,7 +617,7 @@ static int bm_edge_collapse_is_degenerate_topology(BMEdge *e_first) e_iter = e_first; do { if (!bm_edge_is_manifold_or_boundary(e_iter->l)) { - return TRUE; + return true; } bm_edge_tag_disable(e_iter); } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v2)) != e_first); @@ -673,11 +673,11 @@ static int bm_edge_collapse_is_degenerate_topology(BMEdge *e_first) e_iter = e_first; do { if (bm_edge_tag_test(e_iter)) { - return TRUE; + return true; } } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v2)) != e_first); - return FALSE; + return false; } /** @@ -690,13 +690,13 @@ static int bm_edge_collapse_is_degenerate_topology(BMEdge *e_first) * \param e_clear_other let caller know what edges we remove besides \a e_clear * \param customdata_flag merge factor, scales from 0 - 1 ('v_clear' -> 'v_other') */ -static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e_clear_other[2], +static bool bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e_clear_other[2], #ifdef USE_CUSTOMDATA - const CD_UseFlag customdata_flag, - const float customdata_fac + const CD_UseFlag customdata_flag, + const float customdata_fac #else - const CD_UseFlag UNUSED(customdata_flag), - const float UNUSED(customdata_fac) + const CD_UseFlag UNUSED(customdata_flag), + const float UNUSED(customdata_fac) #endif ) { @@ -708,11 +708,11 @@ static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e if (BM_edge_is_manifold(e_clear)) { BMLoop *l_a, *l_b; BMEdge *e_a_other[2], *e_b_other[2]; - int ok; + bool ok; ok = BM_edge_loop_pair(e_clear, &l_a, &l_b); - BLI_assert(ok == TRUE); + BLI_assert(ok == true); BLI_assert(l_a->f->len == 3); BLI_assert(l_b->f->len == 3); @@ -749,7 +749,7 @@ static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e if (ELEM(e_a_other[0], e_b_other[0], e_b_other[1]) || ELEM(e_a_other[1], e_b_other[0], e_b_other[1])) { - return FALSE; + return false; } r_e_clear_other[0] = BM_elem_index_get(e_a_other[0]); @@ -782,7 +782,7 @@ static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e // BM_mesh_validate(bm); - return TRUE; + return true; } else if (BM_edge_is_boundary(e_clear)) { /* same as above but only one triangle */ @@ -829,10 +829,10 @@ static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e // BM_mesh_validate(bm); - return TRUE; + return true; } else { - return FALSE; + return false; } } @@ -869,7 +869,7 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, } /* use for customdata merging */ - if (LIKELY(compare_v3v3(e->v1->co, e->v2->co, FLT_EPSILON) == FALSE)) { + if (LIKELY(compare_v3v3(e->v1->co, e->v2->co, FLT_EPSILON) == false)) { customdata_fac = line_point_factor_v3(optimize_co, e->v1->co, e->v2->co); #if 0 /* simple test for stupid collapse */ @@ -946,7 +946,7 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, else e_outer = l->prev->e; - BLI_assert(BM_vert_in_edge(e_outer, l->v) == FALSE); + BLI_assert(BM_vert_in_edge(e_outer, l->v) == false); bm_decim_build_edge_cost_single(e_outer, vquadrics, vweights, eheap, eheap_table); } @@ -972,14 +972,14 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, * \param vweights Optional array of vertex aligned weights [0 - 1], * a vertex group is the usual source for this. */ -void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, const int do_triangulate) +void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, const bool do_triangulate) { Heap *eheap; /* edge heap */ HeapNode **eheap_table; /* edge index aligned table pointing to the eheap */ Quadric *vquadrics; /* vert index aligned quadrics */ int tot_edge_orig; int face_tot_target; - int use_triangulate; + bool use_triangulate; CD_UseFlag customdata_flag = 0; @@ -1015,7 +1015,7 @@ void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, c /* iterative edge collapse and maintain the eheap */ while ((bm->totface > face_tot_target) && - (BLI_heap_is_empty(eheap) == FALSE) && + (BLI_heap_is_empty(eheap) == false) && (BLI_heap_node_value(BLI_heap_top(eheap)) != COST_INVALID)) { // const float value = BLI_heap_node_value(BLI_heap_top(eheap)); @@ -1033,7 +1033,7 @@ void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, c #ifdef USE_TRIANGULATE - if (do_triangulate == FALSE) { + if (do_triangulate == false) { /* its possible we only had triangles, skip this step in that case */ if (LIKELY(use_triangulate)) { /* temp convert quads to triangles */ diff --git a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c index f67f01e4585..3a724769f2a 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c +++ b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c @@ -69,7 +69,7 @@ static int dissolve_elem_cmp(const void *a1, const void *a2) return 0; } -void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries, +void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, BMVert **vinput_arr, const int vinput_len, BMEdge **einput_arr, const int einput_len) { @@ -117,7 +117,7 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int BMFace *nf = BM_faces_join_pair(bm, e->l->f, e->l->radial_next->f, e, - FALSE); /* join faces */ + false); /* join faces */ /* there may be some errors, we don't mind, just move on */ if (nf) { @@ -148,7 +148,7 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int for (i = bm->totedge - 1; i != -1; i--) { e_iter = earray[i]; - if (BM_edge_is_wire(e_iter) && (BM_elem_flag_test(e_iter, BM_ELEM_TAG) == FALSE)) { + if (BM_edge_is_wire(e_iter) && (BM_elem_flag_test(e_iter, BM_ELEM_TAG) == false)) { /* edge has become wire */ int vidx_reverse; BMVert *v1 = e_iter->v1; @@ -179,7 +179,7 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int if (LIKELY(v != NULL) && BM_vert_edge_count(v) == 2) { - BM_vert_collapse_edge(bm, v->e, v, TRUE); /* join edges */ + BM_vert_collapse_edge(bm, v->e, v, true); /* join edges */ } } } @@ -210,7 +210,7 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int /* check twice because cumulative effect could dissolve over angle limit */ bm_vert_edge_face_angle(v) < angle_limit) { - BMEdge *ne = BM_vert_collapse_edge(bm, v->e, v, TRUE); /* join edges */ + BMEdge *ne = BM_vert_collapse_edge(bm, v->e, v, true); /* join edges */ if (ne && ne->l) { BM_edge_normals_update(ne); @@ -223,7 +223,7 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int MEM_freeN(weight_elems); } -void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries) +void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries) { int vinput_len; int einput_len; diff --git a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c index 71c1cedbd5e..9dc4b596568 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c +++ b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c @@ -36,7 +36,7 @@ #include "intern/bmesh_operators_private.h" /* own include */ -static int bm_vert_dissolve_fan_test(BMVert *v) +static bool bm_vert_dissolve_fan_test(BMVert *v) { /* check if we should walk over these verts */ BMIter iter; @@ -61,21 +61,21 @@ static int bm_vert_dissolve_fan_test(BMVert *v) } if ((tot_edge == 4) && (tot_edge_boundary == 0) && (tot_edge_manifold == 4)) { - return TRUE; + return true; } else if ((tot_edge == 3) && (tot_edge_boundary == 0) && (tot_edge_manifold == 3)) { - return TRUE; + return true; } else if ((tot_edge == 3) && (tot_edge_boundary == 2) && (tot_edge_manifold == 1)) { - return TRUE; + return true; } else if ((tot_edge == 2) && (tot_edge_wire == 2)) { - return TRUE; + return true; } - return FALSE; + return false; } -static int bm_vert_dissolve_fan(BMesh *bm, BMVert *v) +static bool bm_vert_dissolve_fan(BMesh *bm, BMVert *v) { /* collapse under 2 conditions. * - vert connects to 4 manifold edges (and 4 faces). @@ -110,7 +110,7 @@ static int bm_vert_dissolve_fan(BMesh *bm, BMVert *v) if (tot_edge == 2) { /* check for 2 wire verts only */ if (tot_edge_wire == 2) { - return (BM_vert_collapse_edge(bm, v->e, v, TRUE) != NULL); + return (BM_vert_collapse_edge(bm, v->e, v, true) != NULL); } } else if (tot_edge == 4) { @@ -145,7 +145,7 @@ static int bm_vert_dissolve_fan(BMesh *bm, BMVert *v) if (l->f->len > 3) { BMLoop *l_new; BLI_assert(l->prev->v != l->next->v); - BM_face_split(bm, l->f, l->prev->v, l->next->v, &l_new, NULL, TRUE); + BM_face_split(bm, l->f, l->prev->v, l->next->v, &l_new, NULL, true); BM_elem_flag_merge_into(l_new->e, l->e, l->prev->e); } } @@ -153,7 +153,7 @@ static int bm_vert_dissolve_fan(BMesh *bm, BMVert *v) return BM_vert_dissolve(bm, v); } - return FALSE; + return false; } enum { @@ -170,7 +170,7 @@ enum { /** * \param tag_only so we can call this from an operator */ -void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int tag_only) +void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool tag_only) { #ifdef USE_WALKER # define ELE_VERT_TAG 1 @@ -191,14 +191,14 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int /* if tag_only is set, we assyme the caller knows what verts to tag * needed for the operator */ - if (tag_only == FALSE) { + if (tag_only == false) { BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { BM_elem_flag_enable(v, BM_ELEM_TAG); } } for (iter_step = 0; iter_step < iterations; iter_step++) { - int iter_done; + bool iter_done; BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(v, BM_ELEM_TAG) && bm_vert_dissolve_fan_test(v)) { @@ -215,7 +215,7 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int /* main loop, keep tagging until we can't tag any more islands */ - while (TRUE) { + while (true) { #ifdef USE_WALKER BMWalker walker; #else @@ -273,7 +273,7 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int vert_seek_b_tot = 0; vert_seek_b[vert_seek_b_tot++] = v_first; - while (TRUE) { + while (true) { BMEdge *e; if ((offset + depth) % nth) { @@ -318,14 +318,16 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int } /* now we tagged all verts -1 for removal, lets loop over and rebuild faces */ - iter_done = FALSE; + iter_done = false; BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_index_get(v) == VERT_INDEX_DO_COLLAPSE) { - iter_done |= bm_vert_dissolve_fan(bm, v); + if (bm_vert_dissolve_fan(bm, v)) { + iter_done = true; + } } } - if (iter_done == FALSE) { + if (iter_done == false) { break; } } @@ -340,5 +342,5 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int void BM_mesh_decimate_unsubdivide(BMesh *bm, const int iterations) { - BM_mesh_decimate_unsubdivide_ex(bm, iterations, FALSE); + BM_mesh_decimate_unsubdivide_ex(bm, iterations, false); } diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.c b/source/blender/bmesh/tools/bmesh_edgesplit.c index b6a8c7985d6..1d3f973dbc0 100644 --- a/source/blender/bmesh/tools/bmesh_edgesplit.c +++ b/source/blender/bmesh/tools/bmesh_edgesplit.c @@ -98,14 +98,14 @@ static void bm_edgesplit_validate_seams(BMesh *bm) MEM_freeN(vtouch); } -void BM_mesh_edgesplit(BMesh *bm, const int use_verts, const int tag_only) +void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only) { BMIter iter; BMEdge *e; - if (tag_only == FALSE) { - BM_mesh_elem_hflag_enable_all(bm, BM_EDGE | (use_verts ? BM_VERT : 0), BM_ELEM_TAG, FALSE); + if (tag_only == false) { + BM_mesh_elem_hflag_enable_all(bm, BM_EDGE | (use_verts ? BM_VERT : 0), BM_ELEM_TAG, false); } if (use_verts) { @@ -117,8 +117,8 @@ void BM_mesh_edgesplit(BMesh *bm, const int use_verts, const int tag_only) */ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(e, BM_ELEM_TAG)) { - if (UNLIKELY(((BM_elem_flag_test(e->v1, BM_ELEM_TAG) == FALSE) && - (BM_elem_flag_test(e->v2, BM_ELEM_TAG) == FALSE)))) + if (UNLIKELY(((BM_elem_flag_test(e->v1, BM_ELEM_TAG) == false) && + (BM_elem_flag_test(e->v2, BM_ELEM_TAG) == false)))) { BM_elem_flag_enable(e->v1, BM_ELEM_TAG); BM_elem_flag_enable(e->v2, BM_ELEM_TAG); @@ -146,10 +146,10 @@ void BM_mesh_edgesplit(BMesh *bm, const int use_verts, const int tag_only) if (use_verts) { BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e->v1, BM_ELEM_TAG) == FALSE) { + if (BM_elem_flag_test(e->v1, BM_ELEM_TAG) == false) { BM_elem_flag_disable(e->v1, BM_ELEM_TAG); } - if (BM_elem_flag_test(e->v2, BM_ELEM_TAG) == FALSE) { + if (BM_elem_flag_test(e->v2, BM_ELEM_TAG) == false) { BM_elem_flag_disable(e->v2, BM_ELEM_TAG); } } diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.h b/source/blender/bmesh/tools/bmesh_edgesplit.h index 687fdac0e00..8c1231dd794 100644 --- a/source/blender/bmesh/tools/bmesh_edgesplit.h +++ b/source/blender/bmesh/tools/bmesh_edgesplit.h @@ -27,6 +27,6 @@ * \ingroup bmesh */ -void BM_mesh_edgesplit(BMesh *bm, const int use_verts, const int tag_only); +void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only); #endif /* __BMESH_EDGESPLIT_H__ */ diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp index 26b5edf7ea6..493d15135a7 100644 --- a/source/blender/collada/AnimationExporter.cpp +++ b/source/blender/collada/AnimationExporter.cpp @@ -24,6 +24,8 @@ #include "AnimationExporter.h" #include "MaterialExporter.h" +Global G; + template<class Functor> void forEachObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set) { @@ -82,7 +84,12 @@ void AnimationExporter::operator()(Object *ob) } } - + + export_object_constraint_animation(ob); + + //This needs to be handled by extra profiles, so postponed for now + //export_morph_animation(ob); + //Export Lamp parameter animations if ( (ob->type == OB_LAMP) && ((Lamp *)ob->data)->adt && ((Lamp *)ob->data)->adt->action) { fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first); @@ -134,7 +141,69 @@ void AnimationExporter::operator()(Object *ob) fcu = fcu->next; } } + } + + +} + +void AnimationExporter::export_object_constraint_animation(Object *ob) +{ + std::vector<float> fra; + //Takes frames of target animations + make_anim_frames_from_targets(ob, fra); + + if (fra.size()) + dae_baked_object_animation(fra, ob); +} + +void AnimationExporter::export_morph_animation(Object *ob) +{ + FCurve *fcu; + char *transformName; + Key *key = BKE_key_from_object(ob); + if(!key) return; + + if(key->adt && key->adt->action){ + fcu = (FCurve *)key->adt->action->curves.first; + + while (fcu) { + transformName = extract_transform_name(fcu->rna_path); + + dae_animation(ob, fcu, transformName, true); + + fcu = fcu->next; + } + } + +} +void AnimationExporter::make_anim_frames_from_targets(Object *ob, std::vector<float> &frames ){ + + ListBase *conlist = get_active_constraints(ob); + if(conlist == NULL) return; + bConstraint *con; + for (con = (bConstraint*)conlist->first; con; con = con->next) { + ListBase targets = {NULL, NULL}; + + bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con); + + if(!validateConstraints(con)) continue; + + if (cti && cti->get_constraint_targets) { + bConstraintTarget *ct; + Object *obtar; + /* get targets + * - constraints should use ct->matrix, not directly accessing values + * - ct->matrix members have not yet been calculated here! + */ + cti->get_constraint_targets(con, &targets); + if(cti){ + for (ct = (bConstraintTarget*)targets.first; ct; ct = ct->next){ + obtar = ct->tar; + find_frames(obtar, frames); + } + } + } } } @@ -320,6 +389,9 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa if (ma) target = translate_id(id_name(ma)) + "-effect" + "/common/" /*profile common is only supported */ + get_transform_sid(fcu->rna_path, -1, axis_name, true); + //if shape key animation, this is the main problem, how to define the channel targets. + /*target = get_morph_id(ob) + + "/value" +*/ } addChannel(COLLADABU::URI(empty, sampler_id), target); @@ -368,18 +440,23 @@ void AnimationExporter::sample_and_write_bone_animation_matrix(Object *ob_arm, B //char prefix[256]; FCurve *fcu = (FCurve *)ob_arm->adt->action->curves.first; - while (fcu) { + + //Check if there is a fcurve in the armature for the bone in param + //when baking this check is not needed, solve every bone for every frame. + /*while (fcu) { std::string bone_name = getObjectBoneName(ob_arm, fcu); int val = BLI_strcasecmp((char *)bone_name.c_str(), bone->name); if (val == 0) break; fcu = fcu->next; } - if (!(fcu)) return; + if (!(fcu)) return;*/ + bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name); if (!pchan) return; + //every inserted keyframe of bones. find_frames(ob_arm, fra); if (flag & ARM_RESTPOS) { @@ -415,7 +492,8 @@ void AnimationExporter::dae_baked_animation(std::vector<float> &fra, Object *ob_ // create output source std::string output_id; - output_id = create_4x4_source(fra, ob_arm, bone, anim_id); + + output_id = create_4x4_source(fra, ob_arm, bone, anim_id); // create interpolations source std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, ""); @@ -439,6 +517,48 @@ void AnimationExporter::dae_baked_animation(std::vector<float> &fra, Object *ob_ closeAnimation(); } +void AnimationExporter::dae_baked_object_animation(std::vector<float> &fra, Object *ob) +{ + std::string ob_name = id_name(ob); + char anim_id[200]; + + if (!fra.size()) + return; + + BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s", (char*)translate_id(ob_name).c_str(), + "object_matrix"); + + openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING); + + // create input source + std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, false, anim_id, ""); + + // create output source + std::string output_id; + output_id = create_4x4_source( fra, ob, NULL, anim_id); + + // create interpolations source + std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, ""); + + std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX; + COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id); + std::string empty; + sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id)); + sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id)); + + // TODO create in/out tangents source + + // this input is required + sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id)); + + addSampler(sampler); + + std::string target = translate_id(ob_name) + "/transform"; + addChannel(COLLADABU::URI(empty, sampler_id), target); + + closeAnimation(); +} + // dae_bone_animation -> add_bone_animation // (blend this into dae_bone_animation) void AnimationExporter::dae_bone_animation(std::vector<float> &fra, float *values, int tm_type, int axis, std::string ob_name, std::string bone_name) @@ -762,7 +882,8 @@ std::string AnimationExporter::create_source_from_vector(COLLADASW::InputSemanti return source_id; } -std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Object *ob_arm, Bone *bone, const std::string& anim_id) + +std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Object * ob, Bone *bone, const std::string& anim_id) { COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT; std::string source_id = anim_id + get_semantic_suffix(semantic); @@ -777,74 +898,94 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj add_source_parameters(param, semantic, false, NULL, true); source.prepareToAppendValues(); - + bPoseChannel *parchan = NULL; bPoseChannel *pchan = NULL; - bPose *pose = ob_arm->pose; + bPoseChannel *rootchan = NULL; + + if (ob->type == OB_ARMATURE ){ + bPose *pose = ob->pose; + pchan = BKE_pose_channel_find_name(pose, bone->name); + if (!pchan) + return ""; - pchan = BKE_pose_channel_find_name(pose, bone->name); - - if (!pchan) - return ""; - - parchan = pchan->parent; - - enable_fcurves(ob_arm->adt->action, bone->name); + parchan = pchan->parent; + enable_fcurves(ob->adt->action, bone->name); + } + std::vector<float>::iterator it; int j = 0; for (it = frames.begin(); it != frames.end(); it++) { float mat[4][4], ipar[4][4]; - + float ctime = BKE_scene_frame_get_from_ctime(scene, *it); - - BKE_animsys_evaluate_animdata(scene, &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM); - BKE_pose_where_is_bone(scene, ob_arm, pchan, ctime, 1); - - // compute bone local mat - if (bone->parent) { - invert_m4_m4(ipar, parchan->pose_mat); - mult_m4_m4m4(mat, ipar, pchan->pose_mat); - } - else - copy_m4_m4(mat, pchan->pose_mat); - UnitConverter converter; - + CFRA = BKE_scene_frame_get_from_ctime(scene, *it); + //BKE_scene_update_for_newframe(G.main,scene,scene->lay); + BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL); + + if (bone){ + if( pchan->flag & POSE_CHAIN) + { + enable_fcurves(ob->adt->action, NULL); + BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL); + BKE_pose_where_is(scene, ob); + } + else + BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1); + + // compute bone local mat + if (bone->parent) { + invert_m4_m4(ipar, parchan->pose_mat); + mult_m4_m4m4(mat, ipar, pchan->pose_mat); + } + else + copy_m4_m4(mat, pchan->pose_mat); + // SECOND_LIFE_COMPATIBILITY // AFAIK animation to second life is via BVH, but no // reason to not have the collada-animation be correct - if (export_settings->second_life) { - float temp[4][4]; - copy_m4_m4(temp, bone->arm_mat); - temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; - invert_m4(temp); + if (export_settings->second_life) { + float temp[4][4]; + copy_m4_m4(temp, bone->arm_mat); + temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; + invert_m4(temp); - mult_m4_m4m4(mat, mat, temp); + mult_m4_m4m4(mat, mat, temp); - if (bone->parent) { - copy_m4_m4(temp, bone->parent->arm_mat); - temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; + if (bone->parent) { + copy_m4_m4(temp, bone->parent->arm_mat); + temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; - mult_m4_m4m4(mat, temp, mat); + mult_m4_m4m4(mat, temp, mat); + } } - } - float outmat[4][4]; - converter.mat4_to_dae(outmat, mat); + } + else { + calc_ob_mat_at_time(ob, ctime, mat); + } + + UnitConverter converter; + double outmat[4][4]; + converter.mat4_to_dae_double(outmat, mat); source.appendValues(outmat); - j++; + + BIK_release_tree(scene, ob, ctime); } - enable_fcurves(ob_arm->adt->action, NULL); + enable_fcurves(ob->adt->action, NULL); source.finish(); return source_id; } + + // only used for sources with OUTPUT semantic ( locations and scale) std::string AnimationExporter::create_xyz_source(float *v, int tot, const std::string& anim_id) { @@ -1184,6 +1325,12 @@ bool AnimationExporter::hasAnimations(Scene *sce) } } + //check shape key animation + if(!fcu){ + Key *key = BKE_key_from_object(ob); + if(key && key->adt && key->adt->action) + fcu = (FCurve *)key->adt->action->curves.first; + } if (fcu) return true; } @@ -1351,3 +1498,42 @@ void AnimationExporter::sample_animation(float *v, std::vector<float> &frames, i enable_fcurves(ob_arm->adt->action, NULL); } + +bool AnimationExporter::validateConstraints(bConstraint *con){ + + bool valid = true; + bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con); + /* these we can skip completely (invalid constraints...) */ + if (cti == NULL) valid = false; + if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) valid = false; + /* these constraints can't be evaluated anyway */ + if (cti->evaluate_constraint == NULL) valid = false; + /* influence == 0 should be ignored */ + if (con->enforce == 0.0f) valid = false; + + return valid; +} + +void AnimationExporter::calc_ob_mat_at_time(Object *ob, float ctime , float mat[][4]){ + ListBase *conlist = get_active_constraints(ob); + bConstraint *con; + for (con = (bConstraint*)conlist->first; con; con = con->next) { + ListBase targets = {NULL, NULL}; + + bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con); + + if (cti && cti->get_constraint_targets) { + bConstraintTarget *ct; + Object *obtar; + cti->get_constraint_targets(con, &targets); + for (ct = (bConstraintTarget*)targets.first; ct; ct = ct->next){ + obtar = ct->tar; + BKE_animsys_evaluate_animdata(scene, &obtar->id, obtar->adt, ctime, ADT_RECALC_ANIM); + BKE_object_where_is_calc_time(scene, obtar, ctime); + } + } + } + BKE_object_where_is_calc_time(scene, ob, ctime); + copy_m4_m4(mat, ob->obmat); +} + diff --git a/source/blender/collada/AnimationExporter.h b/source/blender/collada/AnimationExporter.h index 349930dea8f..d2f50b22d02 100644 --- a/source/blender/collada/AnimationExporter.h +++ b/source/blender/collada/AnimationExporter.h @@ -34,6 +34,7 @@ extern "C" #include "DNA_camera_types.h" #include "DNA_armature_types.h" #include "DNA_material_types.h" +#include "DNA_constraint_types.h" #include "BLI_math.h" #include "BLI_string.h" @@ -47,6 +48,10 @@ extern "C" #include "BKE_action.h" // pose functions #include "BKE_armature.h" #include "BKE_object.h" +#include "BKE_constraint.h" +#include "BIK_api.h" +#include "BKE_global.h" +#include "ED_object.h" #ifdef NAN_BUILDINFO extern char build_rev[]; @@ -73,9 +78,13 @@ extern char build_rev[]; #include "collada_internal.h" +#include "IK_solver.h" + #include <vector> #include <algorithm> // std::find + + class AnimationExporter: COLLADASW::LibraryAnimations { private: @@ -98,6 +107,10 @@ protected: const ExportSettings *export_settings; void dae_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma = NULL); + + void export_object_constraint_animation(Object *ob); + + void export_morph_animation(Object *ob); void write_bone_animation_matrix(Object *ob_arm, Bone *bone); @@ -119,6 +132,8 @@ protected: void dae_baked_animation(std::vector<float> &fra, Object *ob_arm, Bone *bone); + void dae_baked_object_animation(std::vector<float> &fra, Object *ob); + float convert_time(float frame); float convert_angle(float angle); @@ -130,7 +145,7 @@ protected: void get_source_values(BezTriple *bezt, COLLADASW::InputSemantic::Semantics semantic, bool rotation, float *values, int *length); - float * get_eul_source_for_quat(Object *ob ); + float* get_eul_source_for_quat(Object *ob ); std::string create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name); @@ -143,17 +158,21 @@ protected: std::string create_xyz_source(float *v, int tot, const std::string& anim_id); std::string create_4x4_source(std::vector<float> &frames, Object * ob_arm, Bone *bone, const std::string& anim_id); - + std::string create_interpolation_source(FCurve *fcu, const std::string& anim_id, const char *axis_name, bool *has_tangents); std::string fake_interpolation_source(int tot, const std::string& anim_id, const char *axis_name); + // for rotation, axis name is always appended and the value of append_axis is ignored std::string get_transform_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis); std::string get_light_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis); std::string get_camera_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis); + void find_frames(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name); void find_frames(Object *ob, std::vector<float> &fra); + void make_anim_frames_from_targets(Object *ob, std::vector<float> &frames ); + void find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode); // enable fcurves driving a specific bone, disable all the rest @@ -165,4 +184,11 @@ protected: char *extract_transform_name(char *rna_path); std::string getObjectBoneName(Object *ob, const FCurve * fcu); + + void getBakedPoseData(Object *obarm, int startFrame, int endFrame, bool ActionBake, bool ActionBakeFirstFrame); + + bool validateConstraints(bConstraint *con); + + void calc_ob_mat_at_time(Object *ob, float ctime , float mat[][4]); + }; diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp index 3d0ceb560ed..943c4fb574d 100644 --- a/source/blender/collada/AnimationImporter.cpp +++ b/source/blender/collada/AnimationImporter.cpp @@ -937,10 +937,9 @@ void AnimationImporter::translate_Animations(COLLADAFW::Node *node, if (is_matrix) { apply_matrix_curves(ob, animcurves, root, node, transform); } - else { + else { if (is_joint) { - add_bone_animation_sampled(ob, animcurves, root, node, transform); } else { @@ -1676,8 +1675,6 @@ void AnimationImporter::evaluate_transform_at_frame(float mat[4][4], COLLADAFW:: default: fprintf(stderr, "unsupported transformation type %d\n", type); } - // dae_matrix_to_mat4(tm, m); - } float temp[4][4]; diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp index 134fd639a73..36993eae7b6 100644 --- a/source/blender/collada/ArmatureExporter.cpp +++ b/source/blender/collada/ArmatureExporter.cpp @@ -75,12 +75,6 @@ void ArmatureExporter::add_armature_bones(Object *ob_arm, Scene *sce, } } -bool ArmatureExporter::is_skinned_mesh(Object *ob) -{ - return bc_get_assigned_armature(ob) != NULL; -} - - void ArmatureExporter::write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone) { if (bc_is_root_bone(bone, this->export_settings->deform_bones_only)) @@ -110,31 +104,17 @@ bool ArmatureExporter::add_instance_controller(Object *ob) for (bone = (Bone *)arm->bonebase.first; bone; bone = bone->next) { write_bone_URLs(ins, ob_arm, bone); } - + InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob, this->export_settings->active_uv_only); ins.add(); return true; } -void ArmatureExporter::export_controllers(Scene *sce) -{ - scene = sce; - - openLibrary(); - - GeometryFunctor gf; - gf.forEachMeshObjectInExportSet<ArmatureExporter>(sce, *this, this->export_settings->export_set); - - closeLibrary(); -} - void ArmatureExporter::operator()(Object *ob) { Object *ob_arm = bc_get_assigned_armature(ob); - if (ob_arm /*&& !already_written(ob_arm)*/) - export_controller(ob, ob_arm); } #if 0 @@ -187,67 +167,67 @@ void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene *sce, node.setNodeName(node_name); node.setNodeSid(node_sid); -#if 0 +#if 0 if (bone->childbase.first == NULL || BLI_countlist(&(bone->childbase)) >= 2) { add_blender_leaf_bone( bone, ob_arm, node); } - else { + else{ #endif - node.start(); + node.start(); - add_bone_transform(ob_arm, bone, node); + add_bone_transform(ob_arm, bone, node); - // Write nodes of childobjects, remove written objects from list - std::list<Object *>::iterator i = child_objects.begin(); + // Write nodes of childobjects, remove written objects from list + std::list<Object *>::iterator i = child_objects.begin(); - while (i != child_objects.end()) { - if ((*i)->partype == PARBONE && (0 == strcmp((*i)->parsubstr, bone->name))) { - float backup_parinv[4][4]; - copy_m4_m4(backup_parinv, (*i)->parentinv); + while (i != child_objects.end()) { + if ((*i)->partype == PARBONE && (0 == strcmp((*i)->parsubstr, bone->name))) { + float backup_parinv[4][4]; + copy_m4_m4(backup_parinv, (*i)->parentinv); - // crude, temporary change to parentinv - // so transform gets exported correctly. + // crude, temporary change to parentinv + // so transform gets exported correctly. - // Add bone tail- translation... don't know why - // bone parenting is against the tail of a bone - // and not it's head, seems arbitrary. - (*i)->parentinv[3][1] += bone->length; + // Add bone tail- translation... don't know why + // bone parenting is against the tail of a bone + // and not it's head, seems arbitrary. + (*i)->parentinv[3][1] += bone->length; - // SECOND_LIFE_COMPATIBILITY - // TODO: when such objects are animated as - // single matrix the tweak must be applied - // to the result. - if (export_settings->second_life) { - // tweak objects parentinverse to match compatibility - float temp[4][4]; + // SECOND_LIFE_COMPATIBILITY + // TODO: when such objects are animated as + // single matrix the tweak must be applied + // to the result. + if (export_settings->second_life) { + // tweak objects parentinverse to match compatibility + float temp[4][4]; - copy_m4_m4(temp, bone->arm_mat); - temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; + copy_m4_m4(temp, bone->arm_mat); + temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; - mult_m4_m4m4((*i)->parentinv, temp, (*i)->parentinv); - } + mult_m4_m4m4((*i)->parentinv, temp, (*i)->parentinv); + } - se->writeNodes(*i, sce); + se->writeNodes(*i, sce); - copy_m4_m4((*i)->parentinv, backup_parinv); - child_objects.erase(i++); + copy_m4_m4((*i)->parentinv, backup_parinv); + child_objects.erase(i++); + } + else i++; } - else i++; - } - for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { - add_bone_node(child, ob_arm, sce, se, child_objects); + for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { + add_bone_node(child, ob_arm, sce, se, child_objects); + } + node.end(); } - node.end(); - } - else { - for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { - add_bone_node(child, ob_arm, sce, se, child_objects); + else { + for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { + add_bone_node(child, ob_arm, sce, se, child_objects); + } } - } } -#if 0 +//#if 1 void ArmatureExporter::add_blender_leaf_bone(Bone *bone, Object *ob_arm, COLLADASW::Node& node) { node.start(); @@ -258,13 +238,13 @@ void ArmatureExporter::add_blender_leaf_bone(Bone *bone, Object *ob_arm, COLLADA node.addExtraTechniqueParameter("blender", "tip_y", bone->tail[1]); node.addExtraTechniqueParameter("blender", "tip_z", bone->tail[2]); - for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { + /*for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { add_bone_node(child, ob_arm, sce, se, child_objects); - } + }*/ node.end(); } -#endif +//#endif void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node& node) { @@ -273,22 +253,27 @@ void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW: float mat[4][4]; if (bone->parent) { - // get bone-space matrix from armature-space - bPoseChannel *parchan = BKE_pose_channel_find_name(ob_arm->pose, bone->parent->name); - + // get bone-space matrix from parent pose + /*bPoseChannel *parchan = BKE_pose_channel_find_name(ob_arm->pose, bone->parent->name); float invpar[4][4]; invert_m4_m4(invpar, parchan->pose_mat); - mult_m4_m4m4(mat, invpar, pchan->pose_mat); + mult_m4_m4m4(mat, invpar, pchan->pose_mat);*/ + + float invpar[4][4]; + invert_m4_m4(invpar, bone->parent->arm_mat); + mult_m4_m4m4(mat, invpar, bone->arm_mat); + } else { - copy_m4_m4(mat, pchan->pose_mat); - // Why? Joint's localspace is still it's parent node - //get world-space from armature-space - //mult_m4_m4m4(mat, ob_arm->obmat, pchan->pose_mat); + + //copy_m4_m4(mat, pchan->pose_mat); + //pose mat is object space + //New change: export bone->arm_mat + copy_m4_m4(mat, bone->arm_mat); } // SECOND_LIFE_COMPATIBILITY - if (export_settings->second_life) { + if (export_settings->second_life) { // Remove rotations vs armature from transform // parent_rest_rot * mat * irest_rot float temp[4][4]; @@ -313,315 +298,3 @@ std::string ArmatureExporter::get_controller_id(Object *ob_arm, Object *ob) { return translate_id(id_name(ob_arm)) + "_" + translate_id(id_name(ob)) + SKIN_CONTROLLER_ID_SUFFIX; } - -// ob should be of type OB_MESH -// both args are required -void ArmatureExporter::export_controller(Object *ob, Object *ob_arm) -{ - // joint names - // joint inverse bind matrices - // vertex weights - - // input: - // joint names: ob -> vertex group names - // vertex group weights: me->dvert -> groups -> index, weight - -#if 0 - me->dvert : - - typedef struct MDeformVert { - struct MDeformWeight *dw; - int totweight; - int flag; // flag only in use for weightpaint now - } MDeformVert; - - typedef struct MDeformWeight { - int def_nr; - float weight; - } MDeformWeight; -#endif - - bool use_instantiation = this->export_settings->use_object_instantiation; - Mesh *me; - - if (this->export_settings->apply_modifiers) { - me = bc_to_mesh_apply_modifiers(scene, ob, this->export_settings->export_mesh_type); - } - else { - me = (Mesh *)ob->data; - } - BKE_mesh_tessface_ensure(me); - - if (!me->dvert) return; - - std::string controller_name = id_name(ob_arm); - std::string controller_id = get_controller_id(ob_arm, ob); - - openSkin(controller_id, controller_name, - COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, use_instantiation))); - - add_bind_shape_mat(ob); - - std::string joints_source_id = add_joints_source(ob_arm, &ob->defbase, controller_id); - std::string inv_bind_mat_source_id = add_inv_bind_mats_source(ob_arm, &ob->defbase, controller_id); - - std::list<int> vcounts; - std::list<int> joints; - std::list<float> weights; - - { - int i, j; - - // def group index -> joint index - std::vector<int> joint_index_by_def_index; - bDeformGroup *def; - - for (def = (bDeformGroup *)ob->defbase.first, i = 0, j = 0; def; def = def->next, i++) { - if (is_bone_defgroup(ob_arm, def)) - joint_index_by_def_index.push_back(j++); - else - joint_index_by_def_index.push_back(-1); - } - - for (i = 0; i < me->totvert; i++) { - MDeformVert *vert = &me->dvert[i]; - std::map<int, float> jw; - - // We're normalizing the weights later - float sumw = 0.0f; - - for (j = 0; j < vert->totweight; j++) { - int joint_index = joint_index_by_def_index[vert->dw[j].def_nr]; - if (joint_index != -1 && vert->dw[j].weight > 0.0f) { - jw[joint_index] += vert->dw[j].weight; - sumw += vert->dw[j].weight; - } - } - - if (sumw > 0.0f) { - float invsumw = 1.0f / sumw; - vcounts.push_back(jw.size()); - for (std::map<int, float>::iterator m = jw.begin(); m != jw.end(); ++m) { - joints.push_back((*m).first); - weights.push_back(invsumw * (*m).second); - } - } - else { - vcounts.push_back(0); -#if 0 - vcounts.push_back(1); - joints.push_back(-1); - weights.push_back(1.0f); -#endif - } - } - } - - std::string weights_source_id = add_weights_source(me, controller_id, weights); - add_joints_element(&ob->defbase, joints_source_id, inv_bind_mat_source_id); - add_vertex_weights_element(weights_source_id, joints_source_id, vcounts, joints); - - if (this->export_settings->apply_modifiers) - { - BKE_libblock_free_us(&(G.main->mesh), me); - } - closeSkin(); - closeController(); -} - -void ArmatureExporter::add_joints_element(ListBase *defbase, - const std::string& joints_source_id, const std::string& inv_bind_mat_source_id) -{ - COLLADASW::JointsElement joints(mSW); - COLLADASW::InputList &input = joints.getInputList(); - - input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::JOINT, // constant declared in COLLADASWInputList.h - COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id))); - input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::BINDMATRIX, - COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, inv_bind_mat_source_id))); - joints.add(); -} - -void ArmatureExporter::add_bind_shape_mat(Object *ob) -{ - double bind_mat[4][4]; - - converter.mat4_to_dae_double(bind_mat, ob->obmat); - - addBindShapeTransform(bind_mat); -} - -std::string ArmatureExporter::add_joints_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id) -{ - std::string source_id = controller_id + JOINTS_SOURCE_ID_SUFFIX; - - int totjoint = 0; - bDeformGroup *def; - for (def = (bDeformGroup *)defbase->first; def; def = def->next) { - if (is_bone_defgroup(ob_arm, def)) - totjoint++; - } - - COLLADASW::NameSource source(mSW); - source.setId(source_id); - source.setArrayId(source_id + ARRAY_ID_SUFFIX); - source.setAccessorCount(totjoint); - source.setAccessorStride(1); - - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - param.push_back("JOINT"); - - source.prepareToAppendValues(); - - for (def = (bDeformGroup *)defbase->first; def; def = def->next) { - Bone *bone = get_bone_from_defgroup(ob_arm, def); - if (bone) - source.appendValues(get_joint_sid(bone, ob_arm)); - } - - source.finish(); - - return source_id; -} - -std::string ArmatureExporter::add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id) -{ - std::string source_id = controller_id + BIND_POSES_SOURCE_ID_SUFFIX; - - int totjoint = 0; - for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) { - if (is_bone_defgroup(ob_arm, def)) - totjoint++; - } - - COLLADASW::FloatSourceF source(mSW); - source.setId(source_id); - source.setArrayId(source_id + ARRAY_ID_SUFFIX); - source.setAccessorCount(totjoint); //BLI_countlist(defbase)); - source.setAccessorStride(16); - - source.setParameterTypeName(&COLLADASW::CSWC::CSW_VALUE_TYPE_FLOAT4x4); - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - param.push_back("TRANSFORM"); - - source.prepareToAppendValues(); - - bPose *pose = ob_arm->pose; - bArmature *arm = (bArmature *)ob_arm->data; - - int flag = arm->flag; - - // put armature in rest position - if (!(arm->flag & ARM_RESTPOS)) { - arm->flag |= ARM_RESTPOS; - BKE_pose_where_is(scene, ob_arm); - } - - for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) { - if (is_bone_defgroup(ob_arm, def)) { - bPoseChannel *pchan = BKE_pose_channel_find_name(pose, def->name); - - float mat[4][4]; - float world[4][4]; - float inv_bind_mat[4][4]; - - // SECOND_LIFE_COMPATIBILITY - if (export_settings->second_life) { - // Only translations, no rotation vs armature - float temp[4][4]; - unit_m4(temp); - copy_v3_v3(temp[3], pchan->bone->arm_mat[3]); - mult_m4_m4m4(world, ob_arm->obmat, temp); - } - else { - // make world-space matrix, arm_mat is armature-space - mult_m4_m4m4(world, ob_arm->obmat, pchan->bone->arm_mat); - } - - invert_m4_m4(mat, world); - converter.mat4_to_dae(inv_bind_mat, mat); - - source.appendValues(inv_bind_mat); - } - } - - // back from rest positon - if (!(flag & ARM_RESTPOS)) { - arm->flag = flag; - BKE_pose_where_is(scene, ob_arm); - } - - source.finish(); - - return source_id; -} - -Bone *ArmatureExporter::get_bone_from_defgroup(Object *ob_arm, bDeformGroup *def) -{ - bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, def->name); - return pchan ? pchan->bone : NULL; -} - -bool ArmatureExporter::is_bone_defgroup(Object *ob_arm, bDeformGroup *def) -{ - return get_bone_from_defgroup(ob_arm, def) != NULL; -} - -std::string ArmatureExporter::add_weights_source(Mesh *me, const std::string& controller_id, const std::list<float>& weights) -{ - std::string source_id = controller_id + WEIGHTS_SOURCE_ID_SUFFIX; - - COLLADASW::FloatSourceF source(mSW); - source.setId(source_id); - source.setArrayId(source_id + ARRAY_ID_SUFFIX); - source.setAccessorCount(weights.size()); - source.setAccessorStride(1); - - COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - param.push_back("WEIGHT"); - - source.prepareToAppendValues(); - - for (std::list<float>::const_iterator i = weights.begin(); i != weights.end(); ++i) { - source.appendValues(*i); - } - - source.finish(); - - return source_id; -} - -void ArmatureExporter::add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id, - const std::list<int>& vcounts, - const std::list<int>& joints) -{ - COLLADASW::VertexWeightsElement weightselem(mSW); - COLLADASW::InputList &input = weightselem.getInputList(); - - int offset = 0; - input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::JOINT, // constant declared in COLLADASWInputList.h - COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id), offset++)); - input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::WEIGHT, - COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, weights_source_id), offset++)); - - weightselem.setCount(vcounts.size()); - - // write number of deformers per vertex - COLLADASW::PrimitivesBase::VCountList vcountlist; - - vcountlist.resize(vcounts.size()); - std::copy(vcounts.begin(), vcounts.end(), vcountlist.begin()); - - weightselem.prepareToAppendVCountValues(); - weightselem.appendVertexCount(vcountlist); - - weightselem.CloseVCountAndOpenVElement(); - - // write deformer index - weight index pairs - int weight_index = 0; - for (std::list<int>::const_iterator i = joints.begin(); i != joints.end(); ++i) { - weightselem.appendValues(*i, weight_index++); - } - - weightselem.finish(); -} diff --git a/source/blender/collada/ArmatureExporter.h b/source/blender/collada/ArmatureExporter.h index 086c16f0cd5..e2496a4e578 100644 --- a/source/blender/collada/ArmatureExporter.h +++ b/source/blender/collada/ArmatureExporter.h @@ -41,6 +41,7 @@ #include "DNA_listBase.h" #include "DNA_mesh_types.h" #include "DNA_object_types.h" +#include "DNA_constraint_types.h" #include "DNA_scene_types.h" #include "TransformWriter.h" @@ -62,11 +63,9 @@ public: void add_armature_bones(Object *ob_arm, Scene *sce, SceneExporter *se, std::list<Object *>& child_objects); - bool is_skinned_mesh(Object *ob); - bool add_instance_controller(Object *ob); - void export_controllers(Scene *sce); + //void export_controllers(Scene *sce);*/ void operator()(Object *ob); @@ -98,29 +97,6 @@ private: std::string get_controller_id(Object *ob_arm, Object *ob); - // ob should be of type OB_MESH - // both args are required - void export_controller(Object *ob, Object *ob_arm); - - void add_joints_element(ListBase *defbase, - const std::string& joints_source_id, const std::string& inv_bind_mat_source_id); - - void add_bind_shape_mat(Object *ob); - - std::string add_joints_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id); - - std::string add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id); - - Bone *get_bone_from_defgroup(Object *ob_arm, bDeformGroup *def); - - bool is_bone_defgroup(Object *ob_arm, bDeformGroup *def); - - std::string add_weights_source(Mesh *me, const std::string& controller_id, - const std::list<float>& weights); - - void add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id, - const std::list<int>& vcount, const std::list<int>& joints); - void write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone); }; diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp index f1cf732e695..58c3f34e093 100644 --- a/source/blender/collada/ArmatureImporter.cpp +++ b/source/blender/collada/ArmatureImporter.cpp @@ -78,84 +78,8 @@ JointData *ArmatureImporter::get_joint_data(COLLADAFW::Node *node); return &joint_index_to_joint_info_map[joint_index]; } #endif -void ArmatureImporter::create_unskinned_bone(COLLADAFW::Node *node, EditBone *parent, int totchild, - float parent_mat[4][4], Object *ob_arm) -{ - std::vector<COLLADAFW::Node *>::iterator it; - it = std::find(finished_joints.begin(), finished_joints.end(), node); - if (it != finished_joints.end()) return; - - float mat[4][4]; - float obmat[4][4]; - - // object-space - get_node_mat(obmat, node, NULL, NULL); - - EditBone *bone = ED_armature_edit_bone_add((bArmature *)ob_arm->data, (char *)bc_get_joint_name(node)); - totbone++; - - if (parent) bone->parent = parent; - - float angle = 0; - // get world-space - if (parent) { - mult_m4_m4m4(mat, parent_mat, obmat); - - } - else { - copy_m4_m4(mat, obmat); - - } - float loc[3], size[3], rot[3][3]; - mat4_to_loc_rot_size(loc, rot, size, obmat); - mat3_to_vec_roll(rot, NULL, &angle); - bone->roll = angle; - // set head - copy_v3_v3(bone->head, mat[3]); - - // set tail, don't set it to head because 0-length bones are not allowed - float vec[3] = {0.0f, 0.5f, 0.0f}; - add_v3_v3v3(bone->tail, bone->head, vec); - - // set parent tail - if (parent && totchild == 1) { - copy_v3_v3(parent->tail, bone->head); - - // not setting BONE_CONNECTED because this would lock child bone location with respect to parent - // bone->flag |= BONE_CONNECTED; - - // XXX increase this to prevent "very" small bones? - const float epsilon = 0.000001f; - - // derive leaf bone length - float length = len_v3v3(parent->head, parent->tail); - if ((length < leaf_bone_length || totbone == 0) && length > epsilon) { - leaf_bone_length = length; - } - - // treat zero-sized bone like a leaf bone - if (length <= epsilon) { - add_leaf_bone(parent_mat, parent, node); - } - - } - - COLLADAFW::NodePointerArray& children = node->getChildNodes(); - for (unsigned int i = 0; i < children.getCount(); i++) { - create_unskinned_bone(children[i], bone, children.getCount(), mat, ob_arm); - } - - // in second case it's not a leaf bone, but we handle it the same way - if (!children.getCount() || children.getCount() > 1) { - add_leaf_bone(mat, bone, node); - } - - finished_joints.push_back(node); - -} - -void ArmatureImporter::create_bone(SkinInfo& skin, COLLADAFW::Node *node, EditBone *parent, int totchild, +void ArmatureImporter::create_bone(SkinInfo* skin, COLLADAFW::Node *node, EditBone *parent, int totchild, float parent_mat[4][4], bArmature *arm) { //Checking if bone is already made. @@ -168,50 +92,51 @@ void ArmatureImporter::create_bone(SkinInfo& skin, COLLADAFW::Node *node, EditBo // JointData* jd = get_joint_data(node); float mat[4][4]; - + float obmat[4][4]; + // TODO rename from Node "name" attrs later EditBone *bone = ED_armature_edit_bone_add(arm, (char *)bc_get_joint_name(node)); totbone++; - if (skin.get_joint_inv_bind_matrix(joint_inv_bind_mat, node)) { + if (skin && skin->get_joint_inv_bind_matrix(joint_inv_bind_mat, node)) { // get original world-space matrix invert_m4_m4(mat, joint_inv_bind_mat); } // create a bone even if there's no joint data for it (i.e. it has no influence) else { - float obmat[4][4]; - - // object-space + // bone-space get_node_mat(obmat, node, NULL, NULL); - + // get world-space - if (parent) + if (parent){ mult_m4_m4m4(mat, parent_mat, obmat); + } else copy_m4_m4(mat, obmat); - - float loc[3], size[3], rot[3][3], angle; - mat4_to_loc_rot_size(loc, rot, size, obmat); - mat3_to_vec_roll(rot, NULL, &angle); - bone->roll = angle; } - if (parent) bone->parent = parent; + float loc[3], size[3], rot[3][3]; + float angle; + float vec[3] = {0.0f, 0.5f, 0.0f}; + mat4_to_loc_rot_size(loc, rot, size, mat); + //copy_m3_m4(bonemat,mat); + mat3_to_vec_roll(rot, vec, &angle); + + bone->roll = angle; // set head copy_v3_v3(bone->head, mat[3]); // set tail, don't set it to head because 0-length bones are not allowed - float vec[3] = {0.0f, 0.5f, 0.0f}; add_v3_v3v3(bone->tail, bone->head, vec); // set parent tail if (parent && totchild == 1) { - copy_v3_v3(parent->tail, bone->head); + copy_v3_v3(parent->tail, bone->head); // not setting BONE_CONNECTED because this would lock child bone location with respect to parent - // bone->flag |= BONE_CONNECTED; + bone->flag |= BONE_CONNECTED; // XXX increase this to prevent "very" small bones? const float epsilon = 0.000001f; @@ -227,32 +152,6 @@ void ArmatureImporter::create_bone(SkinInfo& skin, COLLADAFW::Node *node, EditBo add_leaf_bone(parent_mat, parent, node); } - /* -#if 0 - // and which row in mat is bone direction - float vec[3]; - sub_v3_v3v3(vec, parent->tail, parent->head); -#ifdef COLLADA_DEBUG - print_v3("tail - head", vec); - print_m4("matrix", parent_mat); -#endif - for (int i = 0; i < 3; i++) { -#ifdef COLLADA_DEBUG - char *axis_names[] = {"X", "Y", "Z"}; - printf("%s-axis length is %f\n", axis_names[i], len_v3(parent_mat[i])); -#endif - float angle = angle_v2v2(vec, parent_mat[i]); - if (angle < min_angle) { -#ifdef COLLADA_DEBUG - print_v3("picking", parent_mat[i]); - printf("^ %s axis of %s's matrix\n", axis_names[i], get_dae_name(node)); -#endif - bone_direction_row = i; - min_angle = angle; - } - } -#endif - */ } COLLADAFW::NodePointerArray& children = node->getChildNodes(); @@ -265,6 +164,8 @@ void ArmatureImporter::create_bone(SkinInfo& skin, COLLADAFW::Node *node, EditBo add_leaf_bone(mat, bone, node); } + bone->length = len_v3v3(bone->head, bone->tail); + finished_joints.push_back(node); } @@ -299,7 +200,7 @@ void ArmatureImporter::add_leaf_bone(float mat[4][4], EditBone *bone, COLLADAFW void ArmatureImporter::fix_leaf_bones( ) { // just setting tail for leaf bones here - + float correctionMin = 1.0f; std::vector<LeafBone>::iterator it; for (it = leaf_bones.begin(); it != leaf_bones.end(); it++) { LeafBone& leaf = *it; @@ -307,12 +208,11 @@ void ArmatureImporter::fix_leaf_bones( ) // pointing up float vec[3] = {0.0f, 0.0f, 0.1f}; - // if parent: take parent length and direction - if (leaf.bone->parent) sub_v3_v3v3(vec, leaf.bone->parent->tail, leaf.bone->parent->head); + sub_v3_v3v3(vec, leaf.bone->tail , leaf.bone->head); + mul_v3_fl(vec, leaf_bone_length); + add_v3_v3v3(leaf.bone->tail, leaf.bone->head , vec); - copy_v3_v3(leaf.bone->tail, leaf.bone->head); - add_v3_v3v3(leaf.bone->tail, leaf.bone->head, vec); - } + } } #if 0 @@ -410,40 +310,36 @@ ArmatureJoints& ArmatureImporter::get_armature_joints(Object *ob_arm) void ArmatureImporter::create_armature_bones( ) { std::vector<COLLADAFW::Node *>::iterator ri; + + leaf_bone_length = FLT_MAX; //if there is an armature created for root_joint next root_joint for (ri = root_joints.begin(); ri != root_joints.end(); ri++) { if (get_armature_for_joint(*ri) != NULL) continue; - //add armature object for current joint - //Object *ob_arm = bc_add_object(scene, OB_ARMATURE, NULL); - Object *ob_arm = joint_parent_map[(*ri)->getUniqueId()]; if (!ob_arm) continue; - - //ob_arm->type = OB_ARMATURE; + ED_armature_to_edit(ob_arm); - // min_angle = 360.0f; // minimum angle between bone head-tail and a row of bone matrix - - // create unskinned bones /* * TODO: * check if bones have already been created for a given joint */ - leaf_bone_length = FLT_MAX; - create_unskinned_bone(*ri, NULL, (*ri)->getChildNodes().getCount(), NULL, ob_arm); + create_bone(NULL, *ri , NULL, (*ri)->getChildNodes().getCount(), NULL, (bArmature *)ob_arm->data); + + //leaf bone tails are derived from the matrix, so no need of this. fix_leaf_bones(); // exit armature edit mode - unskinned_armature_map[(*ri)->getUniqueId()] = ob_arm; ED_armature_from_edit(ob_arm); - - set_pose(ob_arm, *ri, NULL, NULL); + + //This serves no purpose, as pose is automatically reset later, in BKE_where_is_bone() + //set_pose(ob_arm, *ri, NULL, NULL); ED_armature_edit_free(ob_arm); DAG_id_tag_update(&ob_arm->id, OB_RECALC_OB | OB_RECALC_DATA); @@ -533,7 +429,6 @@ void ArmatureImporter::create_armature_bones(SkinInfo& skin) totbone = 0; // bone_direction_row = 1; // TODO: don't default to Y but use asset and based on it decide on default row leaf_bone_length = FLT_MAX; - // min_angle = 360.0f; // minimum angle between bone head-tail and a row of bone matrix // create bones /* @@ -549,7 +444,7 @@ void ArmatureImporter::create_armature_bones(SkinInfo& skin) // since root_joints may contain joints for multiple controllers, we need to filter if (skin.uses_joint_or_descendant(*ri)) { - create_bone(skin, *ri, NULL, (*ri)->getChildNodes().getCount(), NULL, (bArmature *)ob_arm->data); + create_bone(&skin, *ri, NULL, (*ri)->getChildNodes().getCount(), NULL, (bArmature *)ob_arm->data); if (joint_parent_map.find((*ri)->getUniqueId()) != joint_parent_map.end() && !skin.get_parent()) skin.set_parent(joint_parent_map[(*ri)->getUniqueId()]); @@ -563,22 +458,14 @@ void ArmatureImporter::create_armature_bones(SkinInfo& skin) ED_armature_edit_free(ob_arm); DAG_id_tag_update(&ob_arm->id, OB_RECALC_OB | OB_RECALC_DATA); - // set_leaf_bone_shapes(ob_arm); - // set_euler_rotmode(); } - -// root - if this joint is the top joint in hierarchy, if a joint -// is a child of a node (not joint), root should be true since -// this is where we build armature bones from - void ArmatureImporter::set_pose(Object *ob_arm, COLLADAFW::Node *root_node, const char *parentname, float parent_mat[4][4]) { char *bone_name = (char *) bc_get_joint_name(root_node); float mat[4][4]; float obmat[4][4]; - float ax[3]; float angle = 0.0f; // object-space @@ -597,14 +484,16 @@ void ArmatureImporter::set_pose(Object *ob_arm, COLLADAFW::Node *root_node, con } else { + copy_m4_m4(mat, obmat); float invObmat[4][4]; invert_m4_m4(invObmat, ob_arm->obmat); mult_m4_m4m4(pchan->pose_mat, invObmat, mat); + } - mat4_to_axis_angle(ax, &angle, mat); - pchan->bone->roll = angle; + ///*mat4_to_axis_angle(ax, &angle, mat); + //pchan->bone->roll = angle;*/ COLLADAFW::NodePointerArray& children = root_node->getChildNodes(); @@ -614,6 +503,10 @@ void ArmatureImporter::set_pose(Object *ob_arm, COLLADAFW::Node *root_node, con } + +// root - if this joint is the top joint in hierarchy, if a joint +// is a child of a node (not joint), root should be true since +// this is where we build armature bones from void ArmatureImporter::add_joint(COLLADAFW::Node *node, bool root, Object *parent, Scene *sce) { joint_by_uid[node->getUniqueId()] = node; @@ -729,13 +622,12 @@ bool ArmatureImporter::write_skin_controller_data(const COLLADAFW::SkinControlle bool ArmatureImporter::write_controller(const COLLADAFW::Controller *controller) { // - create and store armature object - - const COLLADAFW::UniqueId& skin_id = controller->getUniqueId(); + const COLLADAFW::UniqueId& con_id = controller->getUniqueId(); if (controller->getControllerType() == COLLADAFW::Controller::CONTROLLER_TYPE_SKIN) { COLLADAFW::SkinController *co = (COLLADAFW::SkinController *)controller; // to be able to find geom id by controller id - geom_uid_by_controller_uid[skin_id] = co->getSource(); + geom_uid_by_controller_uid[con_id] = co->getSource(); const COLLADAFW::UniqueId& data_uid = co->getSkinControllerData(); if (skin_by_data_uid.find(data_uid) == skin_by_data_uid.end()) { @@ -746,14 +638,60 @@ bool ArmatureImporter::write_controller(const COLLADAFW::Controller *controller) skin_by_data_uid[data_uid].set_controller(co); } // morph controller - else { - // shape keys? :) - fprintf(stderr, "Morph controller is not supported yet.\n"); + else if (controller->getControllerType() == COLLADAFW::Controller::CONTROLLER_TYPE_MORPH) { + COLLADAFW::MorphController *co = (COLLADAFW::MorphController *)controller; + // to be able to find geom id by controller id + geom_uid_by_controller_uid[con_id] = co->getSource(); + //Shape keys are applied in DocumentImporter->finish() + morph_controllers.push_back(co); } return true; } +void ArmatureImporter::make_shape_keys(){ + std::vector<COLLADAFW::MorphController *>::iterator mc; + float weight; + + for (mc = morph_controllers.begin(); mc != morph_controllers.end(); mc++) { + //Controller data + COLLADAFW::UniqueIdArray& morphTargetIds = (*mc)->getMorphTargets(); + COLLADAFW::FloatOrDoubleArray& morphWeights = (*mc)->getMorphWeights(); + + //Prereq: all the geometries must be imported and mesh objects must be made + Object *source_ob = this->mesh_importer->get_object_by_geom_uid((*mc)->getSource()); + + Mesh *source_me = (Mesh*) source_ob->data; + //insert key to source mesh + Key *key = source_me->key = BKE_key_add((ID *)source_me); + key->type = KEY_RELATIVE; + KeyBlock *kb; + + //insert basis key + kb = BKE_keyblock_add_ctime(key, "Basis", FALSE); + BKE_key_convert_from_mesh(source_me, kb); + + //insert other shape keys + for ( int i = 0 ; i < morphTargetIds.getCount() ; i++ ){ + //better to have a seperate map of morph objects, + //This'll do for now since only mesh morphing is imported + Mesh *me = this->mesh_importer->get_mesh_by_geom_uid(morphTargetIds[i]); + + if(me){ + me->key = key; + kb = BKE_keyblock_add_ctime(key, me->id.name, FALSE); + BKE_key_convert_from_mesh(me, kb); + + //apply weights + weight = morphWeights.getFloatValues()->getData()[i]; + kb->curval = weight; + } + else + fprintf(stderr, "Morph target geometry not found.\n"); + } + } +} + COLLADAFW::UniqueId *ArmatureImporter::get_geometry_uid(const COLLADAFW::UniqueId& controller_uid) { diff --git a/source/blender/collada/ArmatureImporter.h b/source/blender/collada/ArmatureImporter.h index bb710f09490..b07edfbf34d 100644 --- a/source/blender/collada/ArmatureImporter.h +++ b/source/blender/collada/ArmatureImporter.h @@ -29,13 +29,16 @@ #include "COLLADAFWNode.h" #include "COLLADAFWUniqueId.h" +#include "COLLADAFWMorphController.h" extern "C" { #include "BKE_context.h" +#include "BKE_key.h" #include "DNA_armature_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "DNA_key_types.h" #include "ED_armature.h" } @@ -88,6 +91,7 @@ private: std::map<COLLADAFW::UniqueId, COLLADAFW::Node*> joint_by_uid; // contains all joints std::vector<COLLADAFW::Node*> root_joints; std::vector<COLLADAFW::Node*> finished_joints; + std::vector<COLLADAFW::MorphController*> morph_controllers; std::map<COLLADAFW::UniqueId, Object*> joint_parent_map; std::map<COLLADAFW::UniqueId, Object*> unskinned_armature_map; @@ -103,12 +107,9 @@ private: JointData *get_joint_data(COLLADAFW::Node *node); #endif - void create_bone(SkinInfo& skin, COLLADAFW::Node *node, EditBone *parent, int totchild, + void create_bone(SkinInfo* skin, COLLADAFW::Node *node, EditBone *parent, int totchild, float parent_mat[4][4], bArmature *arm); - void create_unskinned_bone(COLLADAFW::Node *node, EditBone *parent, int totchild, - float parent_mat[4][4], Object * ob_arm); - void add_leaf_bone(float mat[4][4], EditBone *bone, COLLADAFW::Node * node); void fix_leaf_bones(); @@ -140,9 +141,6 @@ public: ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, AnimationImporterBase *anim, Scene *sce); ~ArmatureImporter(); - // root - if this joint is the top joint in hierarchy, if a joint - // is a child of a node (not joint), root should be true since - // this is where we build armature bones from void add_joint(COLLADAFW::Node *node, bool root, Object *parent, Scene *sce); #if 0 @@ -152,6 +150,8 @@ public: // here we add bones to armatures, having armatures previously created in write_controller void make_armatures(bContext *C); + void make_shape_keys(); + #if 0 // link with meshes, create vertex groups, assign weights void link_armature(Object *ob_arm, const COLLADAFW::UniqueId& geom_id, const COLLADAFW::UniqueId& controller_data_id); diff --git a/source/blender/collada/CMakeLists.txt b/source/blender/collada/CMakeLists.txt index 0091df3c502..7f389346a81 100644 --- a/source/blender/collada/CMakeLists.txt +++ b/source/blender/collada/CMakeLists.txt @@ -36,6 +36,9 @@ set(INC ../windowmanager ../imbuf ../../../intern/guardedalloc + ../ikplugin + ../../../intern/iksolver/extern + ) set(INC_SYS @@ -48,6 +51,7 @@ set(SRC ArmatureExporter.cpp ArmatureImporter.cpp CameraExporter.cpp + ControllerExporter.cpp DocumentExporter.cpp DocumentImporter.cpp EffectExporter.cpp @@ -74,6 +78,7 @@ set(SRC ArmatureExporter.h ArmatureImporter.h CameraExporter.h + ControllerExporter.h DocumentExporter.h DocumentImporter.h EffectExporter.h diff --git a/source/blender/collada/CameraExporter.cpp b/source/blender/collada/CameraExporter.cpp index 7d438f7f12f..fc56ff8c63c 100644 --- a/source/blender/collada/CameraExporter.cpp +++ b/source/blender/collada/CameraExporter.cpp @@ -70,7 +70,8 @@ void CamerasExporter::operator()(Object *ob, Scene *sce) switch (cam->type) { case CAM_PANO: - case CAM_PERSP: { + case CAM_PERSP: + { COLLADASW::PerspectiveOptic persp(mSW); persp.setXFov(RAD2DEGF(focallength_to_fov(cam->lens, cam->sensor_x)), "xfov"); persp.setAspectRatio((float)(sce->r.xsch) / (float)(sce->r.ysch), false, "aspect_ratio"); diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp new file mode 100644 index 00000000000..d41c907ee98 --- /dev/null +++ b/source/blender/collada/ControllerExporter.cpp @@ -0,0 +1,598 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Jan Diederich, Tod Liverseed, + * Nathan Letwory, Sukhitha Jayathilake + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/collada/ControllerExporter.cpp + * \ingroup collada + */ + +#include "COLLADASWBaseInputElement.h" +#include "COLLADASWInstanceController.h" +#include "COLLADASWPrimitves.h" +#include "COLLADASWSource.h" + +#include "DNA_action_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" + +#include "BKE_action.h" +#include "BKE_armature.h" + +extern "C" { +#include "BKE_main.h" +#include "BKE_mesh.h" +#include "BKE_global.h" +#include "BKE_library.h" +} + +#include "ED_armature.h" + +#include "BLI_listbase.h" + +#include "GeometryExporter.h" +#include "ArmatureExporter.h" +#include "ControllerExporter.h" +#include "SceneExporter.h" + +#include "collada_utils.h" + +// XXX exporter writes wrong data for shared armatures. A separate +// controller should be written for each armature-mesh binding how do +// we make controller ids then? +ControllerExporter::ControllerExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryControllers(sw), export_settings(export_settings) { +} + +bool ControllerExporter::is_skinned_mesh(Object *ob) +{ + return bc_get_assigned_armature(ob) != NULL; +} + + +void ControllerExporter::write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone) +{ + if (bc_is_root_bone(bone, this->export_settings->deform_bones_only)) + ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_joint_id(bone, ob_arm))); + else { + for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) { + write_bone_URLs(ins, ob_arm, child); + } + } +} + +bool ControllerExporter::add_instance_controller(Object *ob) +{ + Object *ob_arm = bc_get_assigned_armature(ob); + bArmature *arm = (bArmature *)ob_arm->data; + + const std::string& controller_id = get_controller_id(ob_arm, ob); + + COLLADASW::InstanceController ins(mSW); + ins.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, controller_id)); + + Mesh *me = (Mesh *)ob->data; + if (!me->dvert) return false; + + // write root bone URLs + Bone *bone; + for (bone = (Bone *)arm->bonebase.first; bone; bone = bone->next) { + write_bone_URLs(ins, ob_arm, bone); + } + + InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob, this->export_settings->active_uv_only); + + ins.add(); + return true; +} + +void ControllerExporter::export_controllers(Scene *sce) +{ + scene = sce; + + openLibrary(); + + GeometryFunctor gf; + gf.forEachMeshObjectInExportSet<ControllerExporter>(sce, *this, this->export_settings->export_set); + + closeLibrary(); +} + +void ControllerExporter::operator()(Object *ob) +{ + Object *ob_arm = bc_get_assigned_armature(ob); + Key *key = BKE_key_from_object(ob); + + if (ob_arm) + export_skin_controller(ob, ob_arm); + if(key){ + export_morph_controller(ob, key); + } +} +#if 0 + +bool ArmatureExporter::already_written(Object *ob_arm) +{ + return std::find(written_armatures.begin(), written_armatures.end(), ob_arm) != written_armatures.end(); +} + +void ArmatureExporter::wrote(Object *ob_arm) +{ + written_armatures.push_back(ob_arm); +} + +void ArmatureExporter::find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce) +{ + objects.clear(); + + Base *base = (Base *) sce->base.first; + while (base) { + Object *ob = base->object; + + if (ob->type == OB_MESH && get_assigned_armature(ob) == ob_arm) { + objects.push_back(ob); + } + + base = base->next; + } +} +#endif + +std::string ControllerExporter::get_joint_sid(Bone *bone, Object *ob_arm) +{ + return get_joint_id(bone, ob_arm); +} + +std::string ControllerExporter::get_controller_id(Object *ob_arm, Object *ob) +{ + return translate_id(id_name(ob_arm)) + "_" + translate_id(id_name(ob)) + SKIN_CONTROLLER_ID_SUFFIX; +} + +std::string ControllerExporter::get_controller_id(Key *key, Object *ob) +{ + return translate_id(id_name(ob)) + MORPH_CONTROLLER_ID_SUFFIX; +} + +// ob should be of type OB_MESH +// both args are required +void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm) +{ + // joint names + // joint inverse bind matrices + // vertex weights + + // input: + // joint names: ob -> vertex group names + // vertex group weights: me->dvert -> groups -> index, weight + +#if 0 + me->dvert : + + typedef struct MDeformVert { + struct MDeformWeight *dw; + int totweight; + int flag; // flag only in use for weightpaint now + } MDeformVert; + + typedef struct MDeformWeight { + int def_nr; + float weight; + } MDeformWeight; +#endif + + bool use_instantiation = this->export_settings->use_object_instantiation; + Mesh *me; + + if (this->export_settings->apply_modifiers) + me = bc_to_mesh_apply_modifiers(scene, ob, this->export_settings->export_mesh_type); + else + me = (Mesh *)ob->data; + + BKE_mesh_tessface_ensure(me); + + if (!me->dvert) return; + + std::string controller_name = id_name(ob_arm); + std::string controller_id = get_controller_id(ob_arm, ob); + + openSkin(controller_id, controller_name, + COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, use_instantiation))); + + add_bind_shape_mat(ob); + + std::string joints_source_id = add_joints_source(ob_arm, &ob->defbase, controller_id); + std::string inv_bind_mat_source_id = add_inv_bind_mats_source(ob_arm, &ob->defbase, controller_id); + + std::list<int> vcounts; + std::list<int> joints; + std::list<float> weights; + + { + int i, j; + + // def group index -> joint index + std::vector<int> joint_index_by_def_index; + bDeformGroup *def; + + for (def = (bDeformGroup *)ob->defbase.first, i = 0, j = 0; def; def = def->next, i++) { + if (is_bone_defgroup(ob_arm, def)) + joint_index_by_def_index.push_back(j++); + else + joint_index_by_def_index.push_back(-1); + } + + for (i = 0; i < me->totvert; i++) { + MDeformVert *vert = &me->dvert[i]; + std::map<int, float> jw; + + // We're normalizing the weights later + float sumw = 0.0f; + + for (j = 0; j < vert->totweight; j++) { + int joint_index = joint_index_by_def_index[vert->dw[j].def_nr]; + if (joint_index != -1 && vert->dw[j].weight > 0.0f) { + jw[joint_index] += vert->dw[j].weight; + sumw += vert->dw[j].weight; + } + } + + if (sumw > 0.0f) { + float invsumw = 1.0f / sumw; + vcounts.push_back(jw.size()); + for (std::map<int, float>::iterator m = jw.begin(); m != jw.end(); ++m) { + joints.push_back((*m).first); + weights.push_back(invsumw * (*m).second); + } + } + else { + vcounts.push_back(0); +#if 0 + vcounts.push_back(1); + joints.push_back(-1); + weights.push_back(1.0f); +#endif + } + } + } + + std::string weights_source_id = add_weights_source(me, controller_id, weights); + add_joints_element(&ob->defbase, joints_source_id, inv_bind_mat_source_id); + add_vertex_weights_element(weights_source_id, joints_source_id, vcounts, joints); + + if (this->export_settings->apply_modifiers) + { + BKE_libblock_free_us(&(G.main->mesh), me); + } + closeSkin(); + closeController(); +} + +void ControllerExporter::export_morph_controller(Object *ob, Key *key) +{ + bool use_instantiation = this->export_settings->use_object_instantiation; + Mesh *me; + + if (this->export_settings->apply_modifiers) { + me = bc_to_mesh_apply_modifiers(scene, ob, this->export_settings->export_mesh_type); + } + else { + me = (Mesh *)ob->data; + } + BKE_mesh_tessface_ensure(me); + + std::string controller_name = id_name(ob) + "-morph"; + std::string controller_id = get_controller_id(key, ob); + + openMorph(controller_id, controller_name, + COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, use_instantiation))); + + std::string targets_id = add_morph_targets(key, ob); + std::string morph_weights_id = add_morph_weights(key, ob); + + COLLADASW::TargetsElement targets(mSW); + + COLLADASW::InputList &input = targets.getInputList(); + + input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::MORPH_TARGET, // constant declared in COLLADASWInputList.h + COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, targets_id))); + input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::MORPH_WEIGHT, + COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, morph_weights_id))); + targets.add(); + + if (this->export_settings->apply_modifiers) + { + BKE_libblock_free_us(&(G.main->mesh), me); + } + + //support for animations + //can also try the base element and param alternative + add_weight_extras(key); + closeMorph(); + closeController(); +} + +std::string ControllerExporter::add_morph_targets(Key *key, Object *ob) +{ + std::string source_id = translate_id(id_name(ob)) + TARGETS_SOURCE_ID_SUFFIX; + + COLLADASW::IdRefSource source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(key->totkey - 1); + source.setAccessorStride(1); + + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + param.push_back("IDREF"); + + source.prepareToAppendValues(); + + KeyBlock * kb = (KeyBlock*)key->block.first; + //skip the basis + kb = kb->next; + for (; kb; kb = kb->next) { + std::string geom_id = get_geometry_id(ob, false) + "_morph_" + translate_id(kb->name); + source.appendValues(geom_id); + + } + + source.finish(); + + return source_id; +} + +std::string ControllerExporter::add_morph_weights(Key *key, Object *ob) +{ + std::string source_id = translate_id(id_name(ob)) + WEIGHTS_SOURCE_ID_SUFFIX; + + COLLADASW::FloatSourceF source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(key->totkey - 1); + source.setAccessorStride(1); + + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + param.push_back("MORPH_WEIGHT"); + + source.prepareToAppendValues(); + + KeyBlock * kb = (KeyBlock*)key->block.first; + //skip the basis + kb = kb->next; + for (; kb; kb = kb->next) { + float weight = kb->curval; + source.appendValues(weight); + } + source.finish(); + + return source_id; +} + +//Added to implemente support for animations. +void ControllerExporter::add_weight_extras(Key *key){ + // can also try the base element and param alternative + COLLADASW::BaseExtraTechnique extra; + + KeyBlock * kb = (KeyBlock*)key->block.first; + //skip the basis + kb = kb->next; + for (; kb; kb = kb->next) { + float weight = kb->curval; + extra.addExtraTechniqueParameter ("KHR", "morph_weights" , 0.000, "MORPH_WEIGHT_TO_TARGET"); + } +} + + + +void ControllerExporter::add_joints_element(ListBase *defbase, + const std::string& joints_source_id, const std::string& inv_bind_mat_source_id) +{ + COLLADASW::JointsElement joints(mSW); + COLLADASW::InputList &input = joints.getInputList(); + + input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::JOINT, // constant declared in COLLADASWInputList.h + COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id))); + input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::BINDMATRIX, + COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, inv_bind_mat_source_id))); + joints.add(); +} + +void ControllerExporter::add_bind_shape_mat(Object *ob) +{ + double bind_mat[4][4]; + + converter.mat4_to_dae_double(bind_mat, ob->obmat); + + addBindShapeTransform(bind_mat); +} + +std::string ControllerExporter::add_joints_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id) +{ + std::string source_id = controller_id + JOINTS_SOURCE_ID_SUFFIX; + + int totjoint = 0; + bDeformGroup *def; + for (def = (bDeformGroup *)defbase->first; def; def = def->next) { + if (is_bone_defgroup(ob_arm, def)) + totjoint++; + } + + COLLADASW::NameSource source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(totjoint); + source.setAccessorStride(1); + + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + param.push_back("JOINT"); + + source.prepareToAppendValues(); + + for (def = (bDeformGroup *)defbase->first; def; def = def->next) { + Bone *bone = get_bone_from_defgroup(ob_arm, def); + if (bone) + source.appendValues(get_joint_sid(bone, ob_arm)); + } + + source.finish(); + + return source_id; +} + +std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id) +{ + std::string source_id = controller_id + BIND_POSES_SOURCE_ID_SUFFIX; + + int totjoint = 0; + for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) { + if (is_bone_defgroup(ob_arm, def)) + totjoint++; + } + + COLLADASW::FloatSourceF source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(totjoint); //BLI_countlist(defbase)); + source.setAccessorStride(16); + + source.setParameterTypeName(&COLLADASW::CSWC::CSW_VALUE_TYPE_FLOAT4x4); + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + param.push_back("TRANSFORM"); + + source.prepareToAppendValues(); + + bPose *pose = ob_arm->pose; + bArmature *arm = (bArmature *)ob_arm->data; + + int flag = arm->flag; + + // put armature in rest position + if (!(arm->flag & ARM_RESTPOS)) { + arm->flag |= ARM_RESTPOS; + BKE_pose_where_is(scene, ob_arm); + } + + for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) { + if (is_bone_defgroup(ob_arm, def)) { + bPoseChannel *pchan = BKE_pose_channel_find_name(pose, def->name); + + float mat[4][4]; + float world[4][4]; + float inv_bind_mat[4][4]; + + // SECOND_LIFE_COMPATIBILITY + if (export_settings->second_life) { + // Only translations, no rotation vs armature + float temp[4][4]; + unit_m4(temp); + copy_v3_v3(temp[3], pchan->bone->arm_mat[3]); + mult_m4_m4m4(world, ob_arm->obmat, temp); + } + else { + // make world-space matrix, arm_mat is armature-space + mult_m4_m4m4(world, ob_arm->obmat, pchan->bone->arm_mat); + } + + invert_m4_m4(mat, world); + converter.mat4_to_dae(inv_bind_mat, mat); + + source.appendValues(inv_bind_mat); + } + } + + // back from rest positon + if (!(flag & ARM_RESTPOS)) { + arm->flag = flag; + BKE_pose_where_is(scene, ob_arm); + } + + source.finish(); + + return source_id; +} + +Bone *ControllerExporter::get_bone_from_defgroup(Object *ob_arm, bDeformGroup *def) +{ + bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, def->name); + return pchan ? pchan->bone : NULL; +} + +bool ControllerExporter::is_bone_defgroup(Object *ob_arm, bDeformGroup *def) +{ + return get_bone_from_defgroup(ob_arm, def) != NULL; +} + +std::string ControllerExporter::add_weights_source(Mesh *me, const std::string& controller_id, const std::list<float>& weights) +{ + std::string source_id = controller_id + WEIGHTS_SOURCE_ID_SUFFIX; + + COLLADASW::FloatSourceF source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(weights.size()); + source.setAccessorStride(1); + + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + param.push_back("WEIGHT"); + + source.prepareToAppendValues(); + + for (std::list<float>::const_iterator i = weights.begin(); i != weights.end(); ++i) { + source.appendValues(*i); + } + + source.finish(); + + return source_id; +} + +void ControllerExporter::add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id, + const std::list<int>& vcounts, + const std::list<int>& joints) +{ + COLLADASW::VertexWeightsElement weightselem(mSW); + COLLADASW::InputList &input = weightselem.getInputList(); + + int offset = 0; + input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::JOINT, // constant declared in COLLADASWInputList.h + COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id), offset++)); + input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::WEIGHT, + COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, weights_source_id), offset++)); + + weightselem.setCount(vcounts.size()); + + // write number of deformers per vertex + COLLADASW::PrimitivesBase::VCountList vcountlist; + + vcountlist.resize(vcounts.size()); + std::copy(vcounts.begin(), vcounts.end(), vcountlist.begin()); + + weightselem.prepareToAppendVCountValues(); + weightselem.appendVertexCount(vcountlist); + + weightselem.CloseVCountAndOpenVElement(); + + // write deformer index - weight index pairs + int weight_index = 0; + for (std::list<int>::const_iterator i = joints.begin(); i != joints.end(); ++i) { + weightselem.appendValues(*i, weight_index++); + } + + weightselem.finish(); +} diff --git a/source/blender/collada/ControllerExporter.h b/source/blender/collada/ControllerExporter.h new file mode 100644 index 00000000000..0be51187f6f --- /dev/null +++ b/source/blender/collada/ControllerExporter.h @@ -0,0 +1,127 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Jan Diederich, Tod Liverseed, + * Nathan Letwory, Sukhitha Jayathilake + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file ControllerExporter.h + * \ingroup collada + */ + +#ifndef __CONTROLLEREXPORTER_H__ +#define __CONTROLLEREXPORTER_H__ + +#include <list> +#include <string> +//#include <vector> + +#include "COLLADASWStreamWriter.h" +#include "COLLADASWLibraryControllers.h" +#include "COLLADASWInstanceController.h" +#include "COLLADASWInputList.h" +#include "COLLADASWNode.h" +#include "COLLADASWExtraTechnique.h" + +#include "DNA_armature_types.h" +#include "DNA_listBase.h" +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" +#include "DNA_constraint_types.h" +#include "DNA_scene_types.h" +#include "DNA_key_types.h" + +#include "TransformWriter.h" +#include "InstanceWriter.h" + +#include "ExportSettings.h" + +#include "BKE_key.h" + +class SceneExporter; + +class ControllerExporter : public COLLADASW::LibraryControllers, protected TransformWriter, protected InstanceWriter +{ +public: + ControllerExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings); + + bool is_skinned_mesh(Object *ob); + + bool add_instance_controller(Object *ob); + + void export_controllers(Scene *sce); + + void operator()(Object *ob); + +private: + Scene *scene; + UnitConverter converter; + const ExportSettings *export_settings; + +#if 0 + std::vector<Object *> written_armatures; + + bool already_written(Object *ob_arm); + + void wrote(Object *ob_arm); + + void find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce); +#endif + + std::string get_joint_sid(Bone *bone, Object *ob_arm); + + std::string get_controller_id(Object *ob_arm, Object *ob); + + std::string get_controller_id(Key *key, Object *ob); + + // ob should be of type OB_MESH + // both args are required + void export_skin_controller(Object *ob, Object *ob_arm); + + void export_morph_controller(Object *ob, Key *key); + + void add_joints_element(ListBase *defbase, + const std::string& joints_source_id, const std::string& inv_bind_mat_source_id); + + void add_bind_shape_mat(Object *ob); + + std::string add_morph_targets(Key *key, Object *ob); + + std::string add_morph_weights(Key *key, Object *ob); + + void add_weight_extras(Key *key); + + std::string add_joints_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id); + + std::string add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id); + + Bone *get_bone_from_defgroup(Object *ob_arm, bDeformGroup *def); + + bool is_bone_defgroup(Object *ob_arm, bDeformGroup *def); + + std::string add_weights_source(Mesh *me, const std::string& controller_id, + const std::list<float>& weights); + + void add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id, + const std::list<int>& vcount, const std::list<int>& joints); + + void write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone); +}; + +#endif diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp index c491326519f..71909b33db8 100644 --- a/source/blender/collada/DocumentExporter.cpp +++ b/source/blender/collada/DocumentExporter.cpp @@ -123,6 +123,7 @@ extern bool bc_has_object_type(LinkNode *export_set, short obtype); #include "ArmatureExporter.h" #include "AnimationExporter.h" #include "CameraExporter.h" +#include "ControllerExporter.h" #include "EffectExporter.h" #include "GeometryExporter.h" #include "ImageExporter.h" @@ -269,11 +270,15 @@ void DocumentExporter::exportCurrentScene(Scene *sce) // <library_controllers> ArmatureExporter arm_exporter(&sw, this->export_settings); - if (bc_has_object_type(export_set, OB_ARMATURE)) { - arm_exporter.export_controllers(sce); - } + ControllerExporter controller_exporter(&sw , this->export_settings); + //for Morph controller export, removing the check + /*if (bc_has_object_type(export_set, OB_ARMATURE)) + {*/ + controller_exporter.export_controllers(sce); + //} // <library_visual_scenes> + SceneExporter se(&sw, &arm_exporter, this->export_settings); se.exportScene(sce); diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index b7797b51252..1d8be5910c6 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -210,10 +210,11 @@ void DocumentImporter::finish() } - mesh_importer.optimize_material_assignments(); + mesh_importer.optimize_material_assignements(); armature_importer.set_tags_map(this->uid_tags_map); armature_importer.make_armatures(mContext); + armature_importer.make_shape_keys(); #if 0 armature_importer.fix_animation(); @@ -256,7 +257,7 @@ void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW { // The split in #29246, rootmap must point at actual root when - // calculating bones in apply_curves_as_matrix. + // calculating bones in apply_curves_as_matrix. - actual root is the root node. // This has to do with inverse bind poses being world space // (the sources for skinned bones' restposes) and the way // non-skinning nodes have their "restpose" recursively calculated. @@ -265,7 +266,7 @@ void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW if (par) { // && par->getType() == COLLADAFW::Node::JOINT) { // par is root if there's no corresp. key in root_map if (root_map.find(par->getUniqueId()) == root_map.end()) - root_map[node->getUniqueId()] = par; + root_map[node->getUniqueId()] = node; else root_map[node->getUniqueId()] = root_map[par->getUniqueId()]; } @@ -376,8 +377,8 @@ Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Nod anim_importer.read_node_transform(source_node, obn); } - DAG_scene_sort(CTX_data_main(mContext), sce); - DAG_ids_flush_update(CTX_data_main(mContext), 0); + /*DAG_scene_sort(CTX_data_main(mContext), sce); + DAG_ids_flush_update(CTX_data_main(mContext), 0);*/ COLLADAFW::NodePointerArray &children = source_node->getChildNodes(); if (children.getCount()) { @@ -406,22 +407,29 @@ Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Nod return obn; } +// to create constraints off node <extra> tags. Assumes only constraint data in +// current <extra> with blender profile. +void DocumentImporter::create_constraints(ExtraTags *et, Object *ob){ + if ( et && et->isProfile("blender")){ + std::string name; + short* type = 0; + et->setData("type", type); + bConstraint * con = BKE_add_ob_constraint(ob, "Test_con", *type); + + } +} + void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent_node, Scene *sce, Object *par, bool is_library_node) { Object *ob = NULL; bool is_joint = node->getType() == COLLADAFW::Node::JOINT; bool read_transform = true; - std::vector<Object *> *objects_done = new std::vector<Object *>(); + ExtraTags *et = getExtraTags(node->getUniqueId()); + std::vector<Object *> *objects_done = new std::vector<Object *>(); + if (is_joint) { - if (par) { - Object *empty = par; - par = bc_add_object(sce, OB_ARMATURE, NULL); - bc_set_parent(par, empty->parent, mContext); - //remove empty : todo - object_map.insert(std::make_pair<COLLADAFW::UniqueId, Object *>(parent_node->getUniqueId(), par)); - } armature_importer.add_joint(node, parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT, par, sce); } else { @@ -487,10 +495,15 @@ void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent read_transform = false; } + // if node is empty - create empty object // XXX empty node may not mean it is empty object, not sure about this if ( (geom_done + camera_done + lamp_done + controller_done + inst_done) < 1) { - ob = bc_add_object(sce, OB_EMPTY, NULL); + //Check if Object is armature, by checking if immediate child is a JOINT node. + if(is_armature(node)) + ob = bc_add_object(sce, OB_ARMATURE, NULL); + else ob = bc_add_object(sce, OB_EMPTY, NULL); + objects_done->push_back(ob); } @@ -508,6 +521,8 @@ void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent libnode_ob.push_back(ob); } + //create_constraints(et,ob); + } for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); ++it) { @@ -959,11 +974,12 @@ bool DocumentImporter::writeLight(const COLLADAFW::Light *light) Lamp *lamp = NULL; std::string la_id, la_name; - TagsMap::iterator etit; + ExtraTags *et = getExtraTags(light->getUniqueId()); + /*TagsMap::iterator etit; ExtraTags *et = 0; etit = uid_tags_map.find(light->getUniqueId().toAscii()); if (etit != uid_tags_map.end()) - et = etit->second; + et = etit->second;*/ la_id = light->getOriginalId(); la_name = light->getName(); @@ -1183,3 +1199,14 @@ bool DocumentImporter::addExtraTags(const COLLADAFW::UniqueId &uid, ExtraTags *e return true; } +bool DocumentImporter::is_armature(COLLADAFW::Node *node){ + COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes(); + for (unsigned int i = 0; i < child_nodes.getCount(); i++) { + if(child_nodes[i]->getType() == COLLADAFW::Node::JOINT) return true; + else continue; + } + + //no child is JOINT + return false; + +} diff --git a/source/blender/collada/DocumentImporter.h b/source/blender/collada/DocumentImporter.h index d54b8db9f00..7e3476fb7e0 100644 --- a/source/blender/collada/DocumentImporter.h +++ b/source/blender/collada/DocumentImporter.h @@ -40,10 +40,12 @@ #include "BKE_object.h" +#include "BKE_constraint.h" #include "TransformReader.h" #include "AnimationImporter.h" #include "ArmatureImporter.h" +#include "ControllerExporter.h" #include "MeshImporter.h" @@ -73,9 +75,11 @@ public: Object* create_camera_object(COLLADAFW::InstanceCamera*, Scene*); Object* create_lamp_object(COLLADAFW::InstanceLight*, Scene*); Object* create_instance_node(Object*, COLLADAFW::Node*, COLLADAFW::Node*, Scene*, bool); + void create_constraints(ExtraTags *et, Object *ob); void write_node(COLLADAFW::Node*, COLLADAFW::Node*, Scene*, Object*, bool); MTex* create_texture(COLLADAFW::EffectCommon*, COLLADAFW::Texture&, Material*, int, TexIndexTextureArrayMap&); void write_profile_COMMON(COLLADAFW::EffectCommon*, Material*); + void translate_anim_recursive(COLLADAFW::Node*, COLLADAFW::Node*, Object*); /** @@ -128,6 +132,10 @@ public: /** Get an extisting ExtraTags for uid */ ExtraTags* getExtraTags(const COLLADAFW::UniqueId &uid); + bool is_armature(COLLADAFW::Node * node); + + + private: /** Current import stage we're in. */ diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h index 2504c276036..cf45b9b8391 100644 --- a/source/blender/collada/ExportSettings.h +++ b/source/blender/collada/ExportSettings.h @@ -37,6 +37,7 @@ public: bool selected; bool include_children; bool include_armatures; + bool include_shapekeys; bool deform_bones_only; bool active_uv_only; diff --git a/source/blender/collada/ExtraHandler.cpp b/source/blender/collada/ExtraHandler.cpp index df49b4fe8b4..bcf7e573d24 100644 --- a/source/blender/collada/ExtraHandler.cpp +++ b/source/blender/collada/ExtraHandler.cpp @@ -74,6 +74,7 @@ bool ExtraHandler::parseElement( if (!et) { et = new ExtraTags(std::string(profileName)); dimp->addExtraTags(uniqueId, et); + } currentExtraTags = et; return true; diff --git a/source/blender/collada/ExtraHandler.h b/source/blender/collada/ExtraHandler.h index 900e7b70331..aa1ae52a521 100644 --- a/source/blender/collada/ExtraHandler.h +++ b/source/blender/collada/ExtraHandler.h @@ -31,6 +31,7 @@ #include "COLLADASaxFWLIExtraDataCallbackHandler.h" #include "COLLADASaxFWLFilePartLoader.h" +#include "COLLADASWInstanceController.h" #include "DocumentImporter.h" #include "AnimationImporter.h" diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp index f33f0fa110d..6673e1de815 100644 --- a/source/blender/collada/GeometryExporter.cpp +++ b/source/blender/collada/GeometryExporter.cpp @@ -69,9 +69,8 @@ void GeometryExporter::exportGeom(Scene *sce) } void GeometryExporter::operator()(Object *ob) -{ +{ // XXX don't use DerivedMesh, Mesh instead? - #if 0 DerivedMesh *dm = mesh_get_derived_final(mScene, ob, CD_MASK_BAREMESH); #endif @@ -155,17 +154,92 @@ void GeometryExporter::operator()(Object *ob) closeGeometry(); - if (this->export_settings->apply_modifiers) - { + if (this->export_settings->apply_modifiers) { BKE_libblock_free_us(&(G.main->mesh), me); } - - + + if (this->export_settings->include_shapekeys) { + Key * key = BKE_key_from_object(ob); + if(key) { + KeyBlock * kb = (KeyBlock*)key->block.first; + //skip the basis + kb = kb->next; + for (; kb; kb = kb->next) { + BKE_key_convert_to_mesh(kb, me); + export_key_mesh(ob, me, kb); + } + } + } #if 0 dm->release(dm); #endif } +void GeometryExporter::export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb){ + std::string geom_id = get_geometry_id(ob, false) + "_morph_" + translate_id(kb->name); + std::vector<Normal> nor; + std::vector<Face> norind; + + if (exportedGeometry.find(geom_id) != exportedGeometry.end()) + { + return; + } + + std::string geom_name = id_name(ob) + "_morph_" + kb->name; + + exportedGeometry.insert(geom_id); + + bool has_color = (bool)CustomData_has_layer(&me->fdata, CD_MCOL); + + create_normals(nor, norind, me); + + // openMesh(geoId, geoName, meshId) + openMesh(geom_id, geom_name); + + // writes <source> for vertex coords + createVertsSource(geom_id, me); + + // writes <source> for normal coords + createNormalsSource(geom_id, me, nor); + + bool has_uvs = (bool)CustomData_has_layer(&me->fdata, CD_MTFACE); + + // writes <source> for uv coords if mesh has uv coords + if (has_uvs) + createTexcoordsSource(geom_id, me); + + if (has_color) + createVertexColorSource(geom_id, me); + + // <vertices> + + COLLADASW::Vertices verts(mSW); + verts.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX)); + COLLADASW::InputList &input_list = verts.getInputList(); + COLLADASW::Input input(COLLADASW::InputSemantic::POSITION, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::POSITION)); + input_list.push_back(input); + verts.add(); + + //createLooseEdgeList(ob, me, geom_id, norind); + + // XXX slow + if (ob->totcol) { + for (int a = 0; a < ob->totcol; a++) { + createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind); + } + } + else { + createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind); + } + + closeMesh(); + + if (me->flag & ME_TWOSIDED) { + mSW->appendTextBlock("<extra><technique profile=\"MAYA\"><double_sided>1</double_sided></technique></extra>"); + } + + closeGeometry(); +} void GeometryExporter::createLooseEdgeList(Object *ob, Mesh *me, diff --git a/source/blender/collada/GeometryExporter.h b/source/blender/collada/GeometryExporter.h index 7161bb751dd..7cbbf0da8fa 100644 --- a/source/blender/collada/GeometryExporter.h +++ b/source/blender/collada/GeometryExporter.h @@ -39,9 +39,12 @@ #include "DNA_mesh_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "DNA_key_types.h" #include "ExportSettings.h" +#include "BKE_key.h" + extern Object *bc_get_highest_selected_ancestor_or_self(Object *ob); // TODO: optimize UV sets by making indexed list with duplicates removed @@ -100,6 +103,8 @@ public: COLLADASW::URI getUrlBySemantics(std::string geom_id, COLLADASW::InputSemantic::Semantics type, std::string other_suffix = ""); COLLADASW::URI makeUrl(std::string id); + + void export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb); /* int getTriCount(MFace *faces, int totface);*/ private: diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp index 8256618bfa3..febfb772430 100644 --- a/source/blender/collada/MeshImporter.cpp +++ b/source/blender/collada/MeshImporter.cpp @@ -946,6 +946,13 @@ Object *MeshImporter::get_object_by_geom_uid(const COLLADAFW::UniqueId& geom_uid return NULL; } +Mesh *MeshImporter::get_mesh_by_geom_uid(const COLLADAFW::UniqueId& mesh_uid) +{ + if (uid_mesh_map.find(mesh_uid) != uid_mesh_map.end()) + return uid_mesh_map[mesh_uid]; + return NULL; +} + MTex *MeshImporter::assign_textures_to_uvlayer(COLLADAFW::TextureCoordinateBinding &ctexture, Mesh *me, TexIndexTextureArrayMap& texindex_texarray_map, MTex *color_texture) @@ -1061,7 +1068,7 @@ std::vector<Object *> MeshImporter::get_all_users_of(Mesh *reference_mesh) * * During import all materials have been assigned to Object. * Now we iterate over the imported objects and optimize - * the assignments as follows: + * the assignements as follows: * * for each imported geometry: * if number of users is 1: @@ -1075,7 +1082,7 @@ std::vector<Object *> MeshImporter::get_all_users_of(Mesh *reference_mesh) * adjust all other users accordingly. * **/ -void MeshImporter::optimize_material_assignments() +void MeshImporter::optimize_material_assignements() { for (std::vector<Object *>::iterator it = imported_objects.begin(); it != imported_objects.end(); ++it) @@ -1119,7 +1126,7 @@ void MeshImporter::optimize_material_assignments() * come along with different materials. So we first create the objects * and assign the materials to Object, then in a later cleanup we decide * which materials shall be moved to the created geometries. Also see - * optimize_material_assignments() above. + * optimize_material_assignements() above. */ MTFace *MeshImporter::assign_material_to_geom(COLLADAFW::MaterialBinding cmaterial, std::map<COLLADAFW::UniqueId, Material *>& uid_material_map, diff --git a/source/blender/collada/MeshImporter.h b/source/blender/collada/MeshImporter.h index 746b0738108..946f9ff99e3 100644 --- a/source/blender/collada/MeshImporter.h +++ b/source/blender/collada/MeshImporter.h @@ -59,6 +59,7 @@ class MeshImporterBase { public: virtual Object *get_object_by_geom_uid(const COLLADAFW::UniqueId& geom_uid) = 0; + virtual Mesh *get_mesh_by_geom_uid(const COLLADAFW::UniqueId& mesh_uid) = 0; }; class UVDataWrapper @@ -106,10 +107,10 @@ private: #endif void set_face_uv(MTFace *mtface, UVDataWrapper &uvs, - COLLADAFW::IndexList& index_list, unsigned int *tris_indices); + COLLADAFW::IndexList& index_list, unsigned int *tris_indices); void set_face_uv(MTFace *mtface, UVDataWrapper &uvs, - COLLADAFW::IndexList& index_list, int index, bool quad); + COLLADAFW::IndexList& index_list, int index, bool quad); #ifdef COLLADA_DEBUG void print_index_list(COLLADAFW::IndexList& index_list); @@ -132,7 +133,7 @@ private: CustomData create_edge_custom_data(EdgeHash *eh); - void allocate_face_data(COLLADAFW::Mesh *mesh, Mesh *me, int new_tris); + void allocate_face_data(COLLADAFW::Mesh *mesh, Mesh *me, int new_tris); // TODO: import uv set names void read_faces(COLLADAFW::Mesh *mesh, Mesh *me, int new_tris); @@ -151,24 +152,26 @@ public: void bmeshConversion(); virtual Object *get_object_by_geom_uid(const COLLADAFW::UniqueId& geom_uid); + + virtual Mesh *get_mesh_by_geom_uid(const COLLADAFW::UniqueId& geom_uid); MTex *assign_textures_to_uvlayer(COLLADAFW::TextureCoordinateBinding &ctexture, - Mesh *me, TexIndexTextureArrayMap& texindex_texarray_map, - MTex *color_texture); + Mesh *me, TexIndexTextureArrayMap& texindex_texarray_map, + MTex *color_texture); - void optimize_material_assignments(); + void optimize_material_assignements(); MTFace *assign_material_to_geom(COLLADAFW::MaterialBinding cmaterial, - std::map<COLLADAFW::UniqueId, Material*>& uid_material_map, - Object *ob, const COLLADAFW::UniqueId *geom_uid, - MTex **color_texture, char *layername, MTFace *texture_face, - std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map, short mat_index); + std::map<COLLADAFW::UniqueId, Material*>& uid_material_map, + Object *ob, const COLLADAFW::UniqueId *geom_uid, + MTex **color_texture, char *layername, MTFace *texture_face, + std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map, short mat_index); Object *create_mesh_object(COLLADAFW::Node *node, COLLADAFW::InstanceGeometry *geom, - bool isController, - std::map<COLLADAFW::UniqueId, Material*>& uid_material_map, - std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map); + bool isController, + std::map<COLLADAFW::UniqueId, Material*>& uid_material_map, + std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map); // create a mesh storing a pointer in a map so it can be retrieved later by geometry UID bool write_geometry(const COLLADAFW::Geometry* geom); diff --git a/source/blender/collada/SConscript b/source/blender/collada/SConscript index 1351441e41b..18ef62e6c85 100644 --- a/source/blender/collada/SConscript +++ b/source/blender/collada/SConscript @@ -33,9 +33,9 @@ defs = [] # TODO sanitize inc path building # relative paths to include dirs, space-separated, string if env['OURPLATFORM']=='darwin': - incs = '../blenlib ../blenkernel ../windowmanager ../blenloader ../makesdna ../makesrna ../editors/include ../imbuf ../../../intern/guardedalloc [OPENCOLLADA]/COLLADAStreamWriter [OPENCOLLADA]/COLLADABaseUtils [OPENCOLLADA]/COLLADAFramework [OPENCOLLADA]/COLLADASaxFrameworkLoader [OPENCOLLADA]/GeneratedSaxParser '.replace('[OPENCOLLADA]', env['BF_OPENCOLLADA_INC']) + incs = '../ikplugin ../../../intern/iksolver/extern ../blenlib ../blenkernel ../windowmanager ../blenloader ../makesdna ../makesrna ../editors/include ../imbuf ../../../intern/guardedalloc [OPENCOLLADA]/COLLADAStreamWriter [OPENCOLLADA]/COLLADABaseUtils [OPENCOLLADA]/COLLADAFramework [OPENCOLLADA]/COLLADASaxFrameworkLoader [OPENCOLLADA]/GeneratedSaxParser '.replace('[OPENCOLLADA]', env['BF_OPENCOLLADA_INC']) else: - incs = '../blenlib ../blenkernel ../windowmanager ../makesdna ../blenloader ../makesrna ../editors/include ../imbuf ../../../intern/guardedalloc [OPENCOLLADA]/COLLADAStreamWriter/include [OPENCOLLADA]/COLLADABaseUtils/include [OPENCOLLADA]/COLLADAFramework/include [OPENCOLLADA]/COLLADASaxFrameworkLoader/include [OPENCOLLADA]/GeneratedSaxParser/include '.replace('[OPENCOLLADA]', env['BF_OPENCOLLADA_INC']) + incs = '../ikplugin ../../../intern/iksolver/extern ../blenlib ../blenkernel ../windowmanager ../makesdna ../blenloader ../makesrna ../editors/include ../imbuf ../../../intern/guardedalloc [OPENCOLLADA]/COLLADAStreamWriter/include [OPENCOLLADA]/COLLADABaseUtils/include [OPENCOLLADA]/COLLADAFramework/include [OPENCOLLADA]/COLLADASaxFrameworkLoader/include [OPENCOLLADA]/GeneratedSaxParser/include '.replace('[OPENCOLLADA]', env['BF_OPENCOLLADA_INC']) if env['BF_BUILDINFO']: defs.append('WITH_BUILDINFO') diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp index 6d239ae0fb1..bb33e4084e0 100644 --- a/source/blender/collada/SceneExporter.cpp +++ b/source/blender/collada/SceneExporter.cpp @@ -182,6 +182,46 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce) colladaNode.end(); } + if (ob->constraints.first != NULL ){ + bConstraint *con = (bConstraint*) ob->constraints.first; + while(con){ + std::string con_name(id_name(con)); + std::string con_tag = con_name + "_constraint"; + colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"type",con->type); + colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"enforce",con->enforce); + colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"flag",con->flag); + colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"headtail",con->headtail); + colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"lin_error",con->lin_error); + colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"own_space",con->ownspace); + colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"rot_error",con->rot_error); + colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"tar_space",con->tarspace); + colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"lin_error",con->lin_error); + + //not ideal: add the target object name as another parameter. + //No real mapping in the .dae + //Need support for multiple target objects also. + bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con); + ListBase targets = {NULL, NULL}; + if (cti && cti->get_constraint_targets) { + + bConstraintTarget *ct; + Object *obtar; + + cti->get_constraint_targets(con, &targets); + if(cti){ + int i = 1; + for (ct = (bConstraintTarget*)targets.first; ct; ct = ct->next){ + obtar = ct->tar; + std::string tar_id(id_name(obtar)); + colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"target_id",tar_id); + } + } + } + + con = con->next; + } + } + for (std::list<Object *>::iterator i = child_objects.begin(); i != child_objects.end(); ++i) { if (bc_is_marked(*i)) { bc_remove_mark(*i); @@ -189,8 +229,7 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce) } } - if (ob->type != OB_ARMATURE) { + if (ob->type != OB_ARMATURE) colladaNode.end(); - } } diff --git a/source/blender/collada/SceneExporter.h b/source/blender/collada/SceneExporter.h index 31b471a3e4c..f438c002f91 100644 --- a/source/blender/collada/SceneExporter.h +++ b/source/blender/collada/SceneExporter.h @@ -43,6 +43,7 @@ extern "C" { #include "DNA_anim_types.h" #include "DNA_action_types.h" #include "DNA_curve_types.h" +#include "DNA_constraint_types.h" #include "DNA_armature_types.h" #include "DNA_modifier_types.h" #include "DNA_userdef_types.h" @@ -51,6 +52,7 @@ extern "C" { #include "BKE_fcurve.h" #include "BKE_animsys.h" #include "BLI_path_util.h" +#include "BKE_constraint.h" #include "BLI_fileops.h" #include "ED_keyframing.h" } diff --git a/source/blender/collada/TransformReader.cpp b/source/blender/collada/TransformReader.cpp index 5bc135e9b67..24124c7b58d 100644 --- a/source/blender/collada/TransformReader.cpp +++ b/source/blender/collada/TransformReader.cpp @@ -45,29 +45,31 @@ void TransformReader::get_node_mat(float mat[4][4], COLLADAFW::Node *node, std:: COLLADAFW::Transformation *tm = node->getTransformations()[i]; COLLADAFW::Transformation::TransformationType type = tm->getTransformationType(); - - switch (type) { - case COLLADAFW::Transformation::TRANSLATE: - dae_translate_to_mat4(tm, cur); - break; - case COLLADAFW::Transformation::ROTATE: - dae_rotate_to_mat4(tm, cur); - break; - case COLLADAFW::Transformation::SCALE: - dae_scale_to_mat4(tm, cur); - break; - case COLLADAFW::Transformation::MATRIX: - dae_matrix_to_mat4(tm, cur); - break; - case COLLADAFW::Transformation::LOOKAT: - case COLLADAFW::Transformation::SKEW: - fprintf(stderr, "LOOKAT and SKEW transformations are not supported yet.\n"); - break; + + if(type == COLLADAFW::Transformation::MATRIX){ + dae_matrix_to_mat4(tm, mat); + return; } - - copy_m4_m4(copy, mat); - mult_m4_m4m4(mat, copy, cur); - + else{ + switch (type) { + case COLLADAFW::Transformation::TRANSLATE: + dae_translate_to_mat4(tm, cur); + break; + case COLLADAFW::Transformation::ROTATE: + dae_rotate_to_mat4(tm, cur); + break; + case COLLADAFW::Transformation::SCALE: + dae_scale_to_mat4(tm, cur); + break; + case COLLADAFW::Transformation::LOOKAT: + case COLLADAFW::Transformation::SKEW: + fprintf(stderr, "LOOKAT and SKEW transformations are not supported yet.\n"); + break; + } + copy_m4_m4(copy, mat); + mult_m4_m4m4(mat, copy, cur); + } + if (animation_map) { // AnimationList that drives this Transformation const COLLADAFW::UniqueId& anim_list_id = tm->getAnimationList(); diff --git a/source/blender/collada/TransformWriter.cpp b/source/blender/collada/TransformWriter.cpp index 3fe3f620a68..f06c8cb9e00 100644 --- a/source/blender/collada/TransformWriter.cpp +++ b/source/blender/collada/TransformWriter.cpp @@ -52,9 +52,9 @@ void TransformWriter::add_node_transform(COLLADASW::Node& node, float mat[4][4], TransformBase::decompose(local, loc, rot, NULL, scale); if (node.getType() == COLLADASW::Node::JOINT) - node.addMatrix("transform", dmat); + node.addMatrix("transform", dmat); else - add_transform(node, loc, rot, scale); + add_transform(node, loc, rot, scale); } void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob) @@ -93,12 +93,13 @@ void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob) add_transform(node, loc, rot, scale); #endif - + UnitConverter converter; + /* Using parentinv should allow use of existing curves */ if (ob->parent) { // If parentinv is identity don't add it. bool add_parinv = false; - + for (int i = 0; i < 16; ++i) { float f = (i % 4 == i / 4) ? 1.0f : 0.0f; add_parinv |= (ob->parentinv[i % 4][i / 4] != f); @@ -106,12 +107,14 @@ void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob) if (add_parinv) { double dmat[4][4]; - UnitConverter converter; converter.mat4_to_dae_double(dmat, ob->parentinv); node.addMatrix("parentinverse", dmat); } } - + + double d_obmat[4][4]; + converter.mat4_to_dae_double(d_obmat, ob->obmat); + node.addMatrix("transform",d_obmat); add_transform(node, ob->loc, ob->rot, ob->size); } @@ -123,7 +126,6 @@ void TransformWriter::add_node_transform_identity(COLLADASW::Node& node) void TransformWriter::add_transform(COLLADASW::Node& node, float loc[3], float rot[3], float scale[3]) { - node.addTranslate("location", loc[0], loc[1], loc[2]); #if 0 node.addRotateZ("rotationZ", COLLADABU::Math::Utils::radToDegF(rot[2])); node.addRotateY("rotationY", COLLADABU::Math::Utils::radToDegF(rot[1])); @@ -132,6 +134,7 @@ void TransformWriter::add_transform(COLLADASW::Node& node, float loc[3], float r node.addRotateZ("rotationZ", RAD2DEGF(rot[2])); node.addRotateY("rotationY", RAD2DEGF(rot[1])); node.addRotateX("rotationX", RAD2DEGF(rot[0])); - node.addScale("scale", scale[0], scale[1], scale[2]); + node.addTranslate("location", loc[0], loc[1], loc[2]); + } diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp index fbb18887d1b..ef34c55bbe6 100644 --- a/source/blender/collada/collada.cpp +++ b/source/blender/collada/collada.cpp @@ -59,6 +59,7 @@ int collada_export(Scene *sce, int selected, int include_children, int include_armatures, + int include_shapekeys, int deform_bones_only, int active_uv_only, @@ -89,6 +90,7 @@ int collada_export(Scene *sce, export_settings.selected = selected != 0; export_settings.include_children = include_children != 0; export_settings.include_armatures = include_armatures != 0; + export_settings.include_shapekeys = include_shapekeys != 0; export_settings.deform_bones_only = deform_bones_only != 0; export_settings.active_uv_only = active_uv_only != 0; diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h index 13f8151da3d..a02e3e007ae 100644 --- a/source/blender/collada/collada.h +++ b/source/blender/collada/collada.h @@ -55,6 +55,7 @@ int collada_export(Scene *sce, int selected, int include_children, int include_armatures, + int include_shapekeys, int deform_bones_only, int active_uv_only, diff --git a/source/blender/collada/collada_internal.cpp b/source/blender/collada/collada_internal.cpp index 51d81dc164b..64c567384a1 100644 --- a/source/blender/collada/collada_internal.cpp +++ b/source/blender/collada/collada_internal.cpp @@ -283,3 +283,9 @@ std::string get_material_id(Material *mat) { return translate_id(id_name(mat)) + "-material"; } + +std::string get_morph_id(Object *ob) +{ + return translate_id(id_name(ob)) + "-morph"; +} + diff --git a/source/blender/collada/collada_internal.h b/source/blender/collada/collada_internal.h index d92f53f714c..ba077628499 100644 --- a/source/blender/collada/collada_internal.h +++ b/source/blender/collada/collada_internal.h @@ -99,4 +99,6 @@ extern std::string get_camera_id(Object *ob); extern std::string get_material_id(Material *mat); +extern std::string get_morph_id(Object *ob); + #endif /* __COLLADA_INTERNAL_H__ */ diff --git a/source/blender/compositor/nodes/COM_ScaleNode.cpp b/source/blender/compositor/nodes/COM_ScaleNode.cpp index 6f7bd33db6f..e139eb83e04 100644 --- a/source/blender/compositor/nodes/COM_ScaleNode.cpp +++ b/source/blender/compositor/nodes/COM_ScaleNode.cpp @@ -43,7 +43,8 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c bNode *bnode = this->getbNode(); switch (bnode->custom1) { - case CMP_SCALE_RELATIVE: { + case CMP_SCALE_RELATIVE: + { ScaleOperation *operation = new ScaleOperation(); inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph); @@ -51,9 +52,10 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c inputYSocket->relinkConnections(operation->getInputSocket(2), 2, graph); scaleoperation = operation; + break; } - break; - case CMP_SCALE_SCENEPERCENT: { + case CMP_SCALE_SCENEPERCENT: + { SetValueOperation *scaleFactorOperation = new SetValueOperation(); scaleFactorOperation->setValue(context->getRenderData()->size / 100.0f); ScaleOperation *operation = new ScaleOperation(); @@ -63,10 +65,10 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c graph->addOperation(scaleFactorOperation); scaleoperation = operation; + break; } - break; - - case CMP_SCALE_RENDERPERCENT: { + case CMP_SCALE_RENDERPERCENT: + { const RenderData *rd = context->getRenderData(); ScaleFixedSizeOperation *operation = new ScaleFixedSizeOperation(); @@ -81,10 +83,10 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c operation->getInputSocket(0)->getConnection()->setIgnoreResizeCheck(true); scaleoperation = operation; + break; } - break; - - case CMP_SCALE_ABSOLUTE: { + case CMP_SCALE_ABSOLUTE: + { ScaleAbsoluteOperation *operation = new ScaleAbsoluteOperation(); // TODO: what is the use of this one.... perhaps some issues when the ui was updated.... inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph); @@ -92,8 +94,8 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c inputYSocket->relinkConnections(operation->getInputSocket(2), 2, graph); scaleoperation = operation; + break; } - break; } outputSocket->relinkConnections(scaleoperation->getOutputSocket(0)); diff --git a/source/blender/compositor/operations/COM_ChannelMatteOperation.cpp b/source/blender/compositor/operations/COM_ChannelMatteOperation.cpp index 234a1c7b1e5..84cc8aad950 100644 --- a/source/blender/compositor/operations/COM_ChannelMatteOperation.cpp +++ b/source/blender/compositor/operations/COM_ChannelMatteOperation.cpp @@ -38,7 +38,8 @@ void ChannelMatteOperation::initExecution() switch (this->m_limit_method) { /* SINGLE */ - case 0: { + case 0: + { /* 123 / RGB / HSV / YUV / YCC */ const int matte_channel = this->m_matte_channel - 1; const int limit_channel = this->m_limit_channel - 1; @@ -48,21 +49,25 @@ void ChannelMatteOperation::initExecution() break; } /* MAX */ - case 1: { + case 1: + { switch (this->m_matte_channel) { - case 1: { + case 1: + { this->m_ids[0] = 0; this->m_ids[1] = 1; this->m_ids[2] = 2; break; } - case 2: { + case 2: + { this->m_ids[0] = 1; this->m_ids[1] = 0; this->m_ids[2] = 2; break; } - case 3: { + case 3: + { this->m_ids[0] = 2; this->m_ids[1] = 0; this->m_ids[2] = 1; diff --git a/source/blender/compositor/operations/COM_CompositorOperation.cpp b/source/blender/compositor/operations/COM_CompositorOperation.cpp index 141d071dddc..e6a49082a71 100644 --- a/source/blender/compositor/operations/COM_CompositorOperation.cpp +++ b/source/blender/compositor/operations/COM_CompositorOperation.cpp @@ -91,14 +91,14 @@ void CompositorOperation::deinitExecution() } } - BLI_lock_thread(LOCK_DRAW_IMAGE); - BKE_image_signal(BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"), NULL, IMA_SIGNAL_FREE); - BLI_unlock_thread(LOCK_DRAW_IMAGE); - if (re) { RE_ReleaseResult(re); re = NULL; } + + BLI_lock_thread(LOCK_DRAW_IMAGE); + BKE_image_signal(BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"), NULL, IMA_SIGNAL_FREE); + BLI_unlock_thread(LOCK_DRAW_IMAGE); } else { if (this->m_outputBuffer) { diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp index f0fffa770f8..07b958cc335 100644 --- a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp +++ b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp @@ -337,38 +337,73 @@ void *DilateStepOperation::initializeTileData(rcti *rect) MemoryBuffer *buffer = (MemoryBuffer *)this->m_inputProgram->initializeTileData(NULL); float *rectf = buffer->convertToValueBuffer(); int x, y, i; - float *p; int bwidth = buffer->getWidth(); int bheight = buffer->getHeight(); - for (i = 0; i < this->m_iterations; i++) { - for (y = 0; y < bheight; y++) { - for (x = 0; x < bwidth - 1; x++) { - p = rectf + (bwidth * y + x); - *p = max(*p, *(p + 1)); + + /* + The following is based on the van Herk/Gil-Werman algorithm for morphology operations. + */ + int half_window = this->m_iterations; + int window = half_window * 2 + 1; + float *temp = (float *)MEM_mallocN((2*window - 1) * sizeof(float), "dilate erode temp"); + float *buf = (float *)MEM_mallocN((max(bwidth, bheight) + 5*half_window) * sizeof(float), "dilate erode buf"); + + for (y = 0; y < bheight; y++) { + for (x = 0; x < window - 1; x++) { + buf[x] = -MAXFLOAT; + } + for (x = 0; x < bwidth; x++) { + buf[x + window - 1] = rectf[bwidth * y + x]; + } + for (x = bwidth + window - 1; x < bwidth + 5*half_window; x++) { + buf[x] = -MAXFLOAT; + } + + for(i = 0; i < (bwidth + 3*half_window) / window; i++) { + int start = (i + 1) * window - 1; + + temp[window - 1] = buf[start]; + for (x = 1; x < window; x++) { + temp[window - 1 - x] = max(temp[window - x], buf[start - x]); + temp[window - 1 + x] = max(temp[window + x - 2], buf[start + x]); + } + + start = half_window + (i-1) * window + 1; + for (x = -min(0, start); x < window - max(0, start+window - bwidth); x++) { + rectf[bwidth * y + (start + x)] = max(temp[x], temp[x + window - 1]); } } - + } + + for (x = 0; x < bwidth; x++) { + for (y = 0; y < window - 1; y++) { + buf[y] = -MAXFLOAT; + } for (y = 0; y < bheight; y++) { - for (x = bwidth - 1; x >= 1; x--) { - p = rectf + (bwidth * y + x); - *p = max(*p, *(p - 1)); - } + buf[y + window - 1] = rectf[bwidth * y + x]; } - - for (x = 0; x < bwidth; x++) { - for (y = 0; y < bheight - 1; y++) { - p = rectf + (bwidth * y + x); - *p = max(*p, *(p + bwidth)); - } + for (y = bheight + window - 1; y < bheight + 5*half_window; y++) { + buf[y] = -MAXFLOAT; } - - for (x = 0; x < bwidth; x++) { - for (y = bheight - 1; y >= 1; y--) { - p = rectf + (bwidth * y + x); - *p = max(*p, *(p - bwidth)); + + for(i = 0; i < (bheight + 3*half_window) / window; i++) { + int start = (i + 1) * window - 1; + + temp[window - 1] = buf[start]; + for (y = 1; y < window; y++) { + temp[window - 1 - y] = max(temp[window - y], buf[start - y]); + temp[window - 1 + y] = max(temp[window + y - 2], buf[start + y]); + } + + start = half_window + (i-1) * window + 1; + for (y = -min(0, start); y < window - max(0, start+window - bheight); y++) { + rectf[bwidth * (y + start) + x] = max(temp[y], temp[y + window - 1]); } } } + + MEM_freeN(temp); + MEM_freeN(buf); this->m_cached_buffer = rectf; } unlockMutex(); @@ -424,38 +459,70 @@ void *ErodeStepOperation::initializeTileData(rcti *rect) MemoryBuffer *buffer = (MemoryBuffer *)this->m_inputProgram->initializeTileData(NULL); float *rectf = buffer->convertToValueBuffer(); int x, y, i; - float *p; int bwidth = buffer->getWidth(); int bheight = buffer->getHeight(); - for (i = 0; i < this->m_iterations; i++) { - for (y = 0; y < bheight; y++) { - for (x = 0; x < bwidth - 1; x++) { - p = rectf + (bwidth * y + x); - *p = MIN2(*p, *(p + 1)); + + int half_window = this->m_iterations; + int window = half_window * 2 + 1; + float *temp = (float *)MEM_mallocN((2*window - 1) * sizeof(float), "dilate erode temp"); + float *buf = (float *)MEM_mallocN((max(bwidth, bheight) + 5*half_window) * sizeof(float), "dilate erode buf"); + + for (y = 0; y < bheight; y++) { + for (x = 0; x < window - 1; x++) { + buf[x] = MAXFLOAT; + } + for (x = 0; x < bwidth; x++) { + buf[x + window - 1] = rectf[bwidth * y + x]; + } + for (x = bwidth + window - 1; x < bwidth + 5*half_window; x++) { + buf[x] = MAXFLOAT; + } + + for(i = 0; i < (bwidth + 3*half_window) / window; i++) { + int start = (i + 1) * window - 1; + + temp[window - 1] = buf[start]; + for (x = 1; x < window; x++) { + temp[window - 1 - x] = min(temp[window - x], buf[start - x]); + temp[window - 1 + x] = min(temp[window + x - 2], buf[start + x]); } + + start = half_window + (i-1) * window + 1; + for (x = -min(0, start); x < window - max(0, start+window - bwidth); x++) { + rectf[bwidth * y + (start + x)] = min(temp[x], temp[x + window - 1]); + } + } + } + + for (x = 0; x < bwidth; x++) { + for (y = 0; y < window - 1; y++) { + buf[y] = MAXFLOAT; } - for (y = 0; y < bheight; y++) { - for (x = bwidth - 1; x >= 1; x--) { - p = rectf + (bwidth * y + x); - *p = MIN2(*p, *(p - 1)); - } + buf[y + window - 1] = rectf[bwidth * y + x]; } - - for (x = 0; x < bwidth; x++) { - for (y = 0; y < bheight - 1; y++) { - p = rectf + (bwidth * y + x); - *p = MIN2(*p, *(p + bwidth)); - } + for (y = bheight + window - 1; y < bheight + 5*half_window; y++) { + buf[y] = MAXFLOAT; } - - for (x = 0; x < bwidth; x++) { - for (y = bheight - 1; y >= 1; y--) { - p = rectf + (bwidth * y + x); - *p = MIN2(*p, *(p - bwidth)); + + for(i = 0; i < (bheight + 3*half_window) / window; i++) { + int start = (i + 1) * window - 1; + + temp[window - 1] = buf[start]; + for (y = 1; y < window; y++) { + temp[window - 1 - y] = min(temp[window - y], buf[start - y]); + temp[window - 1 + y] = min(temp[window + y - 2], buf[start + y]); + } + + start = half_window + (i-1) * window + 1; + for (y = -min(0, start); y < window - max(0, start+window - bheight); y++) { + rectf[bwidth * (y + start) + x] = min(temp[y], temp[y + window - 1]); } } } + + MEM_freeN(temp); + MEM_freeN(buf); this->m_cached_buffer = rectf; } unlockMutex(); diff --git a/source/blender/compositor/operations/COM_TextureOperation.cpp b/source/blender/compositor/operations/COM_TextureOperation.cpp index f8d6c0cfc01..23a3abe61ee 100644 --- a/source/blender/compositor/operations/COM_TextureOperation.cpp +++ b/source/blender/compositor/operations/COM_TextureOperation.cpp @@ -23,6 +23,7 @@ #include "COM_TextureOperation.h" #include "BLI_listbase.h" +#include "BKE_image.h" TextureBaseOperation::TextureBaseOperation() : NodeOperation() { @@ -46,11 +47,14 @@ void TextureBaseOperation::initExecution() { this->m_inputOffset = getInputSocketReader(0); this->m_inputSize = getInputSocketReader(1); + this->m_pool = BKE_image_pool_new(); } void TextureBaseOperation::deinitExecution() { this->m_inputSize = NULL; this->m_inputOffset = NULL; + BKE_image_pool_free(this->m_pool); + this->m_pool = NULL; } void TextureBaseOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) @@ -95,7 +99,7 @@ void TextureBaseOperation::executePixel(float output[4], float x, float y, Pixel vec[1] = textureSize[1] * (v + textureOffset[1]); vec[2] = textureSize[2] * textureOffset[2]; - retval = multitex_ext(this->m_texture, vec, NULL, NULL, 0, &texres); + retval = multitex_ext(this->m_texture, vec, NULL, NULL, 0, &texres, m_pool); if (texres.talpha) output[3] = texres.ta; diff --git a/source/blender/compositor/operations/COM_TextureOperation.h b/source/blender/compositor/operations/COM_TextureOperation.h index f8435ecdaa2..227ad37579a 100644 --- a/source/blender/compositor/operations/COM_TextureOperation.h +++ b/source/blender/compositor/operations/COM_TextureOperation.h @@ -45,6 +45,7 @@ private: const RenderData *m_rd; SocketReader *m_inputSize; SocketReader *m_inputOffset; + struct ImagePool *m_pool; protected: diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c index 37314373e98..ca2fe48543a 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -2002,7 +2002,7 @@ float ED_rollBoneToVector(EditBone *bone, const float align_axis[3], const short sub_v3_v3v3(nor, bone->tail, bone->head); vec_roll_to_mat3(nor, 0.0f, mat); - + /* check the bone isn't aligned with the axis */ if (!is_zero_v3(align_axis) && angle_v3v3(align_axis, mat[2]) > FLT_EPSILON) { float vec[3], align_axis_proj[3], roll; @@ -4349,7 +4349,7 @@ void ARMATURE_OT_select_hierarchy(wmOperatorType *ot) /* props */ RNA_def_enum(ot->srna, "direction", direction_items, BONE_SELECT_PARENT, "Direction", ""); - RNA_def_boolean(ot->srna, "extend", 0, "Add to Selection", ""); + RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection"); } /* ***************** EditBone Alignment ********************* */ @@ -4997,13 +4997,18 @@ void create_vgroups_from_armature(ReportList *reports, Scene *scene, Object *ob, bArmature *arm = par->data; if (mode == ARM_GROUPS_NAME) { + const int defbase_tot = BLI_countlist(&ob->defbase); + int defbase_add; /* Traverse the bone list, trying to create empty vertex * groups corresponding to the bone. */ - bone_looper(ob, arm->bonebase.first, NULL, vgroup_add_unique_bone_cb); + defbase_add = bone_looper(ob, arm->bonebase.first, NULL, vgroup_add_unique_bone_cb); - if (ob->type == OB_MESH) - ED_vgroup_data_create(ob->data); + if (defbase_add) { + /* its possible there are DWeight's outside the range of the current + * objects deform groups, in this case the new groups wont be empty [#33889] */ + ED_vgroup_data_clamp_range(ob->data, defbase_tot); + } } else if (mode == ARM_GROUPS_ENVELOPE || mode == ARM_GROUPS_AUTO) { /* Traverse the bone list, trying to create vertex groups diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c index 49d4b670cde..38924105316 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -576,7 +576,7 @@ void POSE_OT_select_hierarchy(wmOperatorType *ot) /* props */ ot->prop = RNA_def_enum(ot->srna, "direction", direction_items, BONE_SELECT_PARENT, "Direction", ""); - RNA_def_boolean(ot->srna, "extend", 0, "Add to Selection", ""); + RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection"); } /* ******************* select grouped operator ************* */ diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 53e610401b7..a67bf00a559 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -1279,8 +1279,24 @@ void CU_deselect_all(Object *obedit) ListBase *editnurb = object_editcurve_get(obedit); if (editnurb) { - selectend_nurb(obedit, FIRST, 0, DESELECT); /* set first control points as unselected */ - select_adjacent_cp(editnurb, 1, 1, DESELECT); /* cascade selection */ + Nurb *nu; + int a; + for (nu = editnurb->first; nu; nu = nu->next) { + if (nu->bezt) { + BezTriple *bezt; + for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) { + bezt->f1 &= ~SELECT; + bezt->f2 &= ~SELECT; + bezt->f3 &= ~SELECT; + } + } + else if (nu->bp) { + BPoint *bp; + for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) { + bp->f1 &= ~SELECT; + } + } + } } } @@ -1289,8 +1305,27 @@ void CU_select_all(Object *obedit) ListBase *editnurb = object_editcurve_get(obedit); if (editnurb) { - selectend_nurb(obedit, FIRST, 0, SELECT); /* set first control points as unselected */ - select_adjacent_cp(editnurb, 1, 1, SELECT); /* cascade selection */ + Nurb *nu; + int a; + for (nu = editnurb->first; nu; nu = nu->next) { + if (nu->bezt) { + BezTriple *bezt; + for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) { + if (bezt->hide == 0) { + bezt->f1 |= SELECT; + bezt->f2 |= SELECT; + bezt->f3 |= SELECT; + } + } + } + else if (nu->bp) { + BPoint *bp; + for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) { + if (bp->hide == 0) + bp->f1 |= SELECT; + } + } + } } } @@ -5510,7 +5545,7 @@ void CURVE_OT_select_random(wmOperatorType *ot) /* properties */ RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f, "Percent", "Percentage of elements to select randomly", 0.f, 100.0f); - RNA_def_boolean(ot->srna, "extend", FALSE, "Extend Selection", "Extend selection instead of deselecting everything first"); + RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection"); } /********************* every nth number of point *******************/ diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt index 6d6b7ecdd82..e9b33a6c2a6 100644 --- a/source/blender/editors/datafiles/CMakeLists.txt +++ b/source/blender/editors/datafiles/CMakeLists.txt @@ -81,6 +81,25 @@ if(WITH_BLENDER) data_to_c_simple(../../../../release/datafiles/brushicons/thumb.png SRC) data_to_c_simple(../../../../release/datafiles/brushicons/twist.png SRC) data_to_c_simple(../../../../release/datafiles/brushicons/vertexdraw.png SRC) + + # matcap + data_to_c_simple(../../../../release/datafiles/matcaps/mc01.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc02.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc03.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc04.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc05.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc06.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc07.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc08.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc09.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc10.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc11.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc12.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc13.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc14.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc15.jpg SRC) + data_to_c_simple(../../../../release/datafiles/matcaps/mc16.jpg SRC) + endif() data_to_c_simple(../../../../release/datafiles/startup.blend SRC) diff --git a/source/blender/editors/datafiles/SConscript b/source/blender/editors/datafiles/SConscript index cb6fe11dbb2..49888d573a0 100644 --- a/source/blender/editors/datafiles/SConscript +++ b/source/blender/editors/datafiles/SConscript @@ -77,6 +77,24 @@ sources.extend(( os.path.join(env['DATA_SOURCES'], "thumb.png.c"), os.path.join(env['DATA_SOURCES'], "twist.png.c"), os.path.join(env['DATA_SOURCES'], "vertexdraw.png.c"), + + os.path.join(env['DATA_SOURCES'], "mc01.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc02.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc03.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc04.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc05.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc06.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc07.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc08.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc09.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc10.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc11.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc12.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc13.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc14.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc15.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc16.jpg.c"), + )) env.BlenderLib ( 'bf_editor_datafiles', sources, Split(incs), [], libtype=['core', 'player'], priority=[235, 30] ) diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index e4e640eeefc..671adfb8d1e 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -1387,12 +1387,15 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG static int gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOperator *op) { Scene *scene = CTX_data_scene(C); - bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0); - bGPDstroke *gps = gpf->strokes.first; + bGPDframe *gpf = NULL; + bGPDstroke *gps = NULL; bGPDspoint *pt; double base_time, cur_time, prev_time = -1.0; int i, valid = TRUE; + if (!gpl || !(gpf = gpencil_layer_getframe(gpl, CFRA, 0)) || !(gps = gpf->strokes.first)) + return FALSE; + do { base_time = cur_time = gps->inittime; if (cur_time <= prev_time) { @@ -1438,11 +1441,19 @@ static void gp_convert_set_end_frame(struct Main *UNUSED(main), struct Scene *UN static int gp_convert_poll(bContext *C) { bGPdata *gpd = gpencil_data_get_active(C); + bGPDlayer *gpl = NULL; + bGPDframe *gpf = NULL; ScrArea *sa = CTX_wm_area(C); Scene *scene = CTX_data_scene(C); - /* only if there's valid data, and the current view is 3D View */ - return ((sa && sa->spacetype == SPACE_VIEW3D) && gpencil_layer_getactive(gpd) && (scene->obedit == NULL)); + /* only if the current view is 3D View, if there's valid data (i.e. at least one stroke!), + * and if we are not in edit mode! + */ + return ((sa && sa->spacetype == SPACE_VIEW3D) && + (gpl = gpencil_layer_getactive(gpd)) && + (gpf = gpencil_layer_getframe(gpl, CFRA, 0)) && + (gpf->strokes.first) && + (scene->obedit == NULL)); } static int gp_convert_layer_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index c40312758fc..41ef4bd0b95 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -1564,8 +1564,8 @@ static void gpencil_draw_apply_event(wmOperator *op, wmEvent *event) p->curtime = PIL_check_seconds_timer(); /* handle pressure sensitivity (which is supplied by tablets) */ - if (event->custom == EVT_DATA_TABLET) { - wmTabletData *wmtab = event->customdata; + if (event->tablet_data) { + wmTabletData *wmtab = event->tablet_data; tablet = (wmtab->Active != EVT_TABLET_NONE); p->pressure = wmtab->Pressure; diff --git a/source/blender/editors/include/ED_datafiles.h b/source/blender/editors/include/ED_datafiles.h index 6d7bcecc630..afe23090ae3 100644 --- a/source/blender/editors/include/ED_datafiles.h +++ b/source/blender/editors/include/ED_datafiles.h @@ -150,6 +150,57 @@ extern char datatoc_twist_png[]; extern int datatoc_vertexdraw_png_size; extern char datatoc_vertexdraw_png[]; +/* Matcap files */ + +extern int datatoc_mc01_jpg_size; +extern char datatoc_mc01_jpg[]; + +extern int datatoc_mc02_jpg_size; +extern char datatoc_mc02_jpg[]; + +extern int datatoc_mc03_jpg_size; +extern char datatoc_mc03_jpg[]; + +extern int datatoc_mc04_jpg_size; +extern char datatoc_mc04_jpg[]; + +extern int datatoc_mc05_jpg_size; +extern char datatoc_mc05_jpg[]; + +extern int datatoc_mc06_jpg_size; +extern char datatoc_mc06_jpg[]; + +extern int datatoc_mc07_jpg_size; +extern char datatoc_mc07_jpg[]; + +extern int datatoc_mc08_jpg_size; +extern char datatoc_mc08_jpg[]; + +extern int datatoc_mc09_jpg_size; +extern char datatoc_mc09_jpg[]; + +extern int datatoc_mc10_jpg_size; +extern char datatoc_mc10_jpg[]; + +extern int datatoc_mc11_jpg_size; +extern char datatoc_mc11_jpg[]; + +extern int datatoc_mc12_jpg_size; +extern char datatoc_mc12_jpg[]; + +extern int datatoc_mc13_jpg_size; +extern char datatoc_mc13_jpg[]; + +extern int datatoc_mc14_jpg_size; +extern char datatoc_mc14_jpg[]; + +extern int datatoc_mc15_jpg_size; +extern char datatoc_mc15_jpg[]; + +extern int datatoc_mc16_jpg_size; +extern char datatoc_mc16_jpg[]; + + #endif /* __ED_DATAFILES_H__ */ diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index f5ab002e0ef..d3de2593b9d 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -119,7 +119,7 @@ int EDBM_vert_color_check(struct BMEditMesh *em); void EDBM_mesh_hide(struct BMEditMesh *em, int swap); void EDBM_mesh_reveal(struct BMEditMesh *em); -void EDBM_update_generic(struct BMEditMesh *em, const short do_tessface, const short is_destructive); +void EDBM_update_generic(struct BMEditMesh *em, const bool do_tessface, const bool is_destructive); struct UvElementMap *EDBM_uv_element_map_create(struct BMEditMesh *em, int selected, int doIslands); void EDBM_uv_element_map_free(struct UvElementMap *vmap); @@ -130,7 +130,7 @@ struct MTexPoly *EDBM_mtexpoly_active_get(struct BMEditMesh *em, struct BMFace * void EDBM_uv_vert_map_free(struct UvVertMap *vmap); struct UvMapVert *EDBM_uv_vert_map_at_index(struct UvVertMap *vmap, unsigned int v); -struct UvVertMap *EDBM_uv_vert_map_create(struct BMEditMesh *em, int selected, const float limit[2]); +struct UvVertMap *EDBM_uv_vert_map_create(struct BMEditMesh *em, bool use_select, const float limit[2]); void EDBM_flag_enable_all(struct BMEditMesh *em, const char hflag); void EDBM_flag_disable_all(struct BMEditMesh *em, const char hflag); @@ -227,6 +227,7 @@ void ED_vgroup_delete(struct Object *ob, struct bDeformGroup *de void ED_vgroup_clear(struct Object *ob); void ED_vgroup_select_by_name(struct Object *ob, const char *name); int ED_vgroup_data_create(struct ID *id); +void ED_vgroup_data_clamp_range(struct ID *id, const int total); int ED_vgroup_give_array(struct ID *id, struct MDeformVert **dvert_arr, int *dvert_tot); int ED_vgroup_copy_array(struct Object *ob, struct Object *ob_from); void ED_vgroup_mirror(struct Object *ob, const short mirror_weights, const short flip_vgroups, const short all_vgroups); diff --git a/source/blender/editors/include/ED_physics.h b/source/blender/editors/include/ED_physics.h index cd9ddd3d7d1..192bcd8f712 100644 --- a/source/blender/editors/include/ED_physics.h +++ b/source/blender/editors/include/ED_physics.h @@ -32,13 +32,26 @@ #ifndef __ED_PHYSICS_H__ #define __ED_PHYSICS_H__ +struct bContext; +struct wmOperator; struct wmKeyConfig; +struct Scene; +struct Object; + /* particle_edit.c */ int PE_poll(struct bContext *C); int PE_hair_poll(struct bContext *C); int PE_poll_view3d(struct bContext *C); +/* rigidbody_object.c */ +void ED_rigidbody_ob_add(struct wmOperator *op, struct Scene *scene, struct Object *ob, int type); +void ED_rigidbody_ob_remove(struct Scene *scene, struct Object *ob); + +/* rigidbody_constraint.c */ +void ED_rigidbody_con_add(struct wmOperator *op, struct Scene *scene, struct Object *ob, int type); +void ED_rigidbody_con_remove(struct Scene *scene, struct Object *ob); + /* operators */ void ED_operatortypes_physics(void); void ED_keymap_physics(struct wmKeyConfig *keyconf); diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index 03c1dd5a86d..a41aaca15bd 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -83,6 +83,7 @@ enum { TFM_BWEIGHT, TFM_ALIGN, TFM_EDGE_SLIDE, + TFM_VERT_SLIDE, TFM_SEQ_SLIDE } TfmMode; diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index 0a794040692..f5ac3f19b5b 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -990,11 +990,29 @@ DEF_ICON(BRUSH_THUMB) DEF_ICON(BRUSH_ROTATE) DEF_ICON(BRUSH_VERTEXDRAW) + /* Matcaps */ +DEF_ICON(MATCAP_01) +DEF_ICON(MATCAP_02) +DEF_ICON(MATCAP_03) +DEF_ICON(MATCAP_04) +DEF_ICON(MATCAP_05) +DEF_ICON(MATCAP_06) +DEF_ICON(MATCAP_07) +DEF_ICON(MATCAP_08) +DEF_ICON(MATCAP_09) +DEF_ICON(MATCAP_10) +DEF_ICON(MATCAP_11) +DEF_ICON(MATCAP_12) +DEF_ICON(MATCAP_13) +DEF_ICON(MATCAP_14) +DEF_ICON(MATCAP_15) +DEF_ICON(MATCAP_16) + /* vector icons, VICO_ prefix added */ DEF_VICO(VIEW3D_VEC) DEF_VICO(EDIT_VEC) -DEF_VICO(EDITMODE_DEHLT) -DEF_VICO(EDITMODE_HLT) +DEF_VICO(EDITMODE_VEC_DEHLT) +DEF_VICO(EDITMODE_VEC_HLT) DEF_VICO(DISCLOSURE_TRI_RIGHT_VEC) DEF_VICO(DISCLOSURE_TRI_DOWN_VEC) DEF_VICO(MOVE_UP_VEC) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 292cc4cdca0..e9cb2eff7e3 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -807,6 +807,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, struct bContext *C, struct Pointe uiLayout *uiTemplateConstraint(uiLayout *layout, struct PointerRNA *ptr); void uiTemplatePreview(uiLayout *layout, struct ID *id, int show_buttons, struct ID *parent, struct MTex *slot); void uiTemplateColorRamp(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int expand); +void uiTemplateIconView(uiLayout *layout, struct PointerRNA *ptr, const char *propname); void uiTemplateHistogram(uiLayout *layout, struct PointerRNA *ptr, const char *propname); void uiTemplateWaveform(uiLayout *layout, struct PointerRNA *ptr, const char *propname); void uiTemplateVectorscope(uiLayout *layout, struct PointerRNA *ptr, const char *propname); diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h index f578d68b852..10026bbd50f 100644 --- a/source/blender/editors/include/UI_interface_icons.h +++ b/source/blender/editors/include/UI_interface_icons.h @@ -39,6 +39,7 @@ struct World; struct Tex; struct Lamp; struct Material; +struct PreviewImage; struct PointerRNA; typedef struct IconFile { @@ -76,6 +77,8 @@ void UI_icons_free_drawinfo(void *drawinfo); struct ListBase *UI_iconfile_list(void); int UI_iconfile_get_index(const char *filename); +struct PreviewImage *UI_icon_to_preview(int icon_id); + int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, int big); #endif /* __UI_INTERFACE_ICONS_H__ */ diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index 29b1a74e859..df07e05ec06 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -147,6 +147,8 @@ enum { TH_NODE_CONVERTOR, TH_NODE_GROUP, TH_NODE_FRAME, + TH_NODE_MATTE, + TH_NODE_DISTORT, TH_CONSOLE_OUTPUT, TH_CONSOLE_INPUT, diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index c87bb2a97a1..0d65cd19034 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -1416,11 +1416,11 @@ static int ui_textedit_delete_selection(uiBut *but, uiHandleButtonData *data) } /* note, but->block->aspect is used here, when drawing button style is getting scaled too */ -static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, short x) +static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, const float x) { uiStyle *style = UI_GetStyle(); // XXX pass on as arg uiFontStyle *fstyle = &style->widget; - int startx = but->rect.xmin; + float startx = but->rect.xmin; char *origstr, password_str[UI_MAX_DRAW_STR]; uiStyleFontSet(fstyle); @@ -1430,24 +1430,27 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho ui_button_text_password_hide(password_str, but, FALSE); - origstr = MEM_callocN(sizeof(char) * data->maxlen, "ui_textedit origstr"); + origstr = MEM_mallocN(sizeof(char) * data->maxlen, "ui_textedit origstr"); BLI_strncpy(origstr, but->drawstr, data->maxlen); - /* XXX solve generic */ - if (but->type == NUM || but->type == NUMSLI) + /* XXX solve generic, see: #widget_draw_text_icon */ + if (but->type == NUM || but->type == NUMSLI) { startx += (int)(0.5f * (BLI_rctf_size_y(&but->rect))); + } else if (ELEM3(but->type, TEX, SEARCH_MENU, SEARCH_MENU_UNLINK)) { - startx += 5; - if (but->flag & UI_HAS_ICON) + if (but->flag & UI_HAS_ICON) { startx += UI_DPI_ICON_SIZE; + } + /* but this extra .05 makes clicks inbetween characters feel nicer */ + startx += ((UI_TEXT_MARGIN_X + 0.05f) * U.widget_unit); } /* mouse dragged outside the widget to the left */ - if (x < startx && but->ofs > 0) { + if (x < startx) { int i = but->ofs; - origstr[but->ofs] = 0; + origstr[but->ofs] = '\0'; while (i > 0) { if (BLI_str_cursor_step_prev_utf8(origstr, but->ofs, &i)) { @@ -1463,21 +1466,18 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho but->ofs = i; but->pos = but->ofs; } - /* mouse inside the widget */ - else if (x >= startx) { + /* 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; - - const float aspect_sqrt = sqrtf(but->block->aspect); but->pos = pos_prev = strlen(origstr) - but->ofs; - while (TRUE) { - /* XXX does not take zoom level into account */ - cdist = startx + aspect_sqrt * BLF_width(fstyle->uifont_id, origstr + but->ofs); + while (true) { + cdist = startx + BLF_width(fstyle->uifont_id, origstr + but->ofs); /* check if position is found */ if (cdist < x) { @@ -1513,7 +1513,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho MEM_freeN(origstr); } -static void ui_textedit_set_cursor_select(uiBut *but, uiHandleButtonData *data, short x) +static void ui_textedit_set_cursor_select(uiBut *but, uiHandleButtonData *data, const float x) { if (x > data->selstartx) data->selextend = EXTEND_RIGHT; else if (x < data->selstartx) data->selextend = EXTEND_LEFT; @@ -2593,6 +2593,7 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i { float deler, tempf, softmin, softmax, softrange; int lvalue, temp, changed = 0; + const bool is_float = ui_is_but_float(but); if (mx == data->draglastx) return changed; @@ -2614,7 +2615,7 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i if (ui_is_a_warp_but(but)) { /* Mouse location isn't screen clamped to the screen so use a linear mapping * 2px == 1-int, or 1px == 1-ClickStep */ - if (ui_is_but_float(but)) { + if (is_float) { fac *= 0.01f * but->a1; tempf = (float)data->startvalue + ((float)(mx - data->dragstartx) * fac); tempf = ui_numedit_apply_snapf(but, tempf, softmin, softmax, softrange, snap); @@ -2671,21 +2672,21 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i else { /* Use a non-linear mapping of the mouse drag especially for large floats (normal behavior) */ deler = 500; - if (!ui_is_but_float(but)) { + if (!is_float) { /* prevent large ranges from getting too out of control */ - if (softrange > 600) deler = powf(softrange, 0.75); - else if (softrange < 100) deler = 200.0; + if (softrange > 600) deler = powf(softrange, 0.75f); else if (softrange < 25) deler = 50.0; + else if (softrange < 100) deler = 100.0; } deler /= fac; - if (softrange > 11) { + if ((is_float == true) && (softrange > 11)) { /* non linear change in mouse input- good for high precicsion */ - data->dragf += (((float)(mx - data->draglastx)) / deler) * (fabsf(data->dragstartx - mx) * 0.002f); + data->dragf += (((float)(mx - data->draglastx)) / deler) * (fabsf(mx - data->dragstartx) / 500.0f); } - else if (softrange > 129) { /* only scale large int buttons */ + else if ((is_float == false) && (softrange > 129)) { /* only scale large int buttons */ /* non linear change in mouse input- good for high precicsionm ints need less fine tuning */ - data->dragf += (((float)(mx - data->draglastx)) / deler) * (fabsf(data->dragstartx - mx) * 0.004f); + data->dragf += (((float)(mx - data->draglastx)) / deler) * (fabsf(mx - data->dragstartx) / 250.0f); } else { /*no scaling */ @@ -2697,7 +2698,7 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i tempf = (softmin + data->dragf * softrange); - if (!ui_is_but_float(but)) { + if (!is_float) { temp = floorf(tempf + 0.5f); temp = ui_numedit_apply_snap(temp, softmin, softmax, snap); @@ -6559,6 +6560,7 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle ui_pan_to_scroll(event, &type, &val); if (val == KM_PRESS) { + const eButType type_flip = BUT | ROW; PASS_EVENT_TO_PARENT_IF_NONACTIVE; @@ -6571,13 +6573,13 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle { /* the following is just a hack - uiBut->type set to BUT and BUTM have there menus built * opposite ways - this should be changed so that all popup-menus use the same uiBlock->direction */ - if (but->type & BUT) + if (but->type & type_flip) but = ui_but_next(but); else but = ui_but_prev(but); } else { - if (but->type & BUT) + if (but->type & type_flip) but = ui_but_prev(but); else but = ui_but_next(but); @@ -6594,7 +6596,7 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle ((ELEM(type, UPARROWKEY, WHEELUPMOUSE)) && (block->direction & UI_RIGHT)) || ((ELEM(type, DOWNARROWKEY, WHEELDOWNMOUSE)) && (block->direction & UI_TOP))) { - if ((bt = ui_but_first(block)) && (bt->type & BUT)) { + if ((bt = ui_but_first(block)) && (bt->type & type_flip)) { bt = ui_but_last(block); } else { @@ -6602,7 +6604,7 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle } } else { - if ((bt = ui_but_first(block)) && (bt->type & BUT)) { + if ((bt = ui_but_first(block)) && (bt->type & type_flip)) { /* keep ui_but_first() */ } else { diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 68780083b97..8b4b1752774 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -75,10 +75,6 @@ #include "interface_intern.h" - -// #define ICON_IMAGE_W 600 -// #define ICON_IMAGE_H 640 - #define ICON_GRID_COLS 26 #define ICON_GRID_ROWS 30 @@ -89,7 +85,9 @@ typedef struct IconImage { int w; int h; - unsigned int *rect; + unsigned int *rect; + unsigned char *datatoc_rect; + int datatoc_size; } IconImage; typedef void (*VectorDrawFunc)(int x, int y, int w, int h, float alpha); @@ -132,13 +130,12 @@ static IconTexture icongltex = {0, 0, 0, 0.0f, 0.0f}; /* **************************************************** */ -static void def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, int size, int type) + +static DrawInfo *def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, int size, int type) { Icon *new_icon = NULL; IconImage *iimg = NULL; DrawInfo *di; - int y = 0; - int imgsize = 0; new_icon = MEM_callocN(sizeof(Icon), "texicon"); @@ -155,17 +152,27 @@ static void def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, int di->data.texture.h = size; } else if (type == ICON_TYPE_BUFFER) { - iimg = MEM_mallocN(sizeof(IconImage), "icon_img"); - iimg->rect = MEM_mallocN(size * size * sizeof(unsigned int), "icon_rect"); + iimg = MEM_callocN(sizeof(IconImage), "icon_img"); iimg->w = size; iimg->h = size; - /* Here we store the rect in the icon - same as before */ - imgsize = bbuf->x; - for (y = 0; y < size; y++) { - memcpy(&iimg->rect[y * size], &bbuf->rect[(y + yofs) * imgsize + xofs], size * sizeof(int)); + /* icon buffers can get initialized runtime now, via datatoc */ + if (bbuf) { + int y, imgsize; + + iimg->rect = MEM_mallocN(size * size * sizeof(unsigned int), "icon_rect"); + + /* Here we store the rect in the icon - same as before */ + if (size == bbuf->x && size == bbuf->y && xofs == 0 && yofs == 0) + memcpy(iimg->rect, bbuf->rect, size * size * sizeof(int)); + else { + /* this code assumes square images */ + imgsize = bbuf->x; + for (y = 0; y < size; y++) { + memcpy(&iimg->rect[y * size], &bbuf->rect[(y + yofs) * imgsize + xofs], imgsize * sizeof(int)); + } + } } - di->data.buffer.image = iimg; } @@ -173,6 +180,8 @@ static void def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs, int new_icon->drawinfo = di; BKE_icon_set(icon_id, new_icon); + + return di; } static void def_internal_vicon(int icon_id, VectorDrawFunc drawFunc) @@ -463,21 +472,19 @@ static void vicon_move_down_draw(int x, int y, int w, int h, float UNUSED(alpha) static void init_brush_icons(void) { -#define INIT_BRUSH_ICON(icon_id, name) \ - { \ - bbuf = IMB_ibImageFromMemory((unsigned char *)datatoc_ ##name## _png, \ - datatoc_ ##name## _png_size, \ - IB_rect, NULL, "<brush icon>"); \ - if (bbuf) { \ - IMB_premultiply_alpha(bbuf); \ - def_internal_icon(bbuf, icon_id, 0, 0, w, ICON_TYPE_BUFFER); \ - } \ - IMB_freeImBuf(bbuf); \ - } (void)0 +#define INIT_BRUSH_ICON(icon_id, name) \ + { \ + unsigned char *rect = (unsigned char *)datatoc_ ##name## _png; \ + int size = datatoc_ ##name## _png_size; \ + DrawInfo *di; \ + \ + di = def_internal_icon(NULL, icon_id, 0, 0, w, ICON_TYPE_BUFFER); \ + di->data.buffer.image->datatoc_rect = rect; \ + di->data.buffer.image->datatoc_size = size; \ + } /* end INIT_BRUSH_ICON */ - ImBuf *bbuf; - const int w = 96; + const int w = 96; /* warning, brush size hardcoded in C, but it gets scaled */ INIT_BRUSH_ICON(ICON_BRUSH_ADD, add); INIT_BRUSH_ICON(ICON_BRUSH_BLOB, blob); @@ -513,6 +520,60 @@ static void init_brush_icons(void) #undef INIT_BRUSH_ICON } +static void icon_verify_datatoc(IconImage *iimg) +{ + /* if it has own rect, things are all OK */ + if (iimg->rect) + return; + + if (iimg->datatoc_rect) { + ImBuf *bbuf = IMB_ibImageFromMemory(iimg->datatoc_rect, + iimg->datatoc_size, IB_rect, NULL, "<matcap icon>"); + /* w and h were set on initialize */ + if (bbuf->x != iimg->h && bbuf->y != iimg->w) + IMB_scalefastImBuf(bbuf, iimg->w, iimg->h); + + iimg->rect = bbuf->rect; + bbuf->rect = NULL; + IMB_freeImBuf(bbuf); + } +} + +static void init_matcap_icons(void) +{ + /* dynamic allocation now, tucking datatoc pointers in DrawInfo */ +#define INIT_MATCAP_ICON(icon_id, name) \ + { \ + unsigned char *rect = (unsigned char *)datatoc_ ##name## _jpg; \ + int size = datatoc_ ##name## _jpg_size; \ + DrawInfo *di; \ + \ + di = def_internal_icon(NULL, icon_id, 0, 0, 128, ICON_TYPE_BUFFER); \ + di->data.buffer.image->datatoc_rect = rect; \ + di->data.buffer.image->datatoc_size = size; \ + } (void)0 + + INIT_MATCAP_ICON(ICON_MATCAP_01, mc01); + INIT_MATCAP_ICON(ICON_MATCAP_02, mc02); + INIT_MATCAP_ICON(ICON_MATCAP_03, mc03); + INIT_MATCAP_ICON(ICON_MATCAP_04, mc04); + INIT_MATCAP_ICON(ICON_MATCAP_05, mc05); + INIT_MATCAP_ICON(ICON_MATCAP_06, mc06); + INIT_MATCAP_ICON(ICON_MATCAP_07, mc07); + INIT_MATCAP_ICON(ICON_MATCAP_08, mc08); + INIT_MATCAP_ICON(ICON_MATCAP_09, mc09); + INIT_MATCAP_ICON(ICON_MATCAP_10, mc10); + INIT_MATCAP_ICON(ICON_MATCAP_11, mc11); + INIT_MATCAP_ICON(ICON_MATCAP_12, mc12); + INIT_MATCAP_ICON(ICON_MATCAP_13, mc13); + INIT_MATCAP_ICON(ICON_MATCAP_14, mc14); + INIT_MATCAP_ICON(ICON_MATCAP_15, mc15); + INIT_MATCAP_ICON(ICON_MATCAP_16, mc16); + +#undef INIT_MATCAP_ICON + +} + static void init_internal_icons(void) { // bTheme *btheme = UI_GetTheme(); @@ -613,8 +674,8 @@ static void init_internal_icons(void) def_internal_vicon(VICO_VIEW3D_VEC, vicon_view3d_draw); def_internal_vicon(VICO_EDIT_VEC, vicon_edit_draw); - def_internal_vicon(VICO_EDITMODE_DEHLT, vicon_editmode_dehlt_draw); - def_internal_vicon(VICO_EDITMODE_HLT, vicon_editmode_hlt_draw); + def_internal_vicon(VICO_EDITMODE_VEC_DEHLT, vicon_editmode_dehlt_draw); + def_internal_vicon(VICO_EDITMODE_VEC_HLT, vicon_editmode_hlt_draw); def_internal_vicon(VICO_DISCLOSURE_TRI_RIGHT_VEC, vicon_disclosure_tri_right_draw); def_internal_vicon(VICO_DISCLOSURE_TRI_DOWN_VEC, vicon_disclosure_tri_down_draw); def_internal_vicon(VICO_MOVE_UP_VEC, vicon_move_up_draw); @@ -762,7 +823,8 @@ void UI_icons_free_drawinfo(void *drawinfo) if (di) { if (di->type == ICON_TYPE_BUFFER) { if (di->data.buffer.image) { - MEM_freeN(di->data.buffer.image->rect); + if (di->data.buffer.image->rect) + MEM_freeN(di->data.buffer.image->rect); MEM_freeN(di->data.buffer.image); } } @@ -842,6 +904,7 @@ void UI_icons_init(int first_dyn_id) BKE_icons_init(first_dyn_id); init_internal_icons(); init_brush_icons(); + init_matcap_icons(); #endif } @@ -891,6 +954,34 @@ static void icon_set_image(bContext *C, ID *id, PreviewImage *prv_img, enum eIco prv_img->w[size], prv_img->h[size]); } +PreviewImage *UI_icon_to_preview(int icon_id) +{ + Icon *icon = BKE_icon_get(icon_id); + + if (icon) { + DrawInfo *di = (DrawInfo *)icon->drawinfo; + if (di && di->data.buffer.image) { + ImBuf *bbuf; + + bbuf = IMB_ibImageFromMemory(di->data.buffer.image->datatoc_rect, di->data.buffer.image->datatoc_size, IB_rect, NULL, "<matcap buffer>"); + if (bbuf) { + PreviewImage *prv = BKE_previewimg_create(); + + prv->rect[0] = bbuf->rect; + + prv->w[0] = bbuf->x; + prv->h[0] = bbuf->y; + + bbuf->rect = NULL; + IMB_freeImBuf(bbuf); + + return prv; + } + } + } + return NULL; +} + static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), int rw, int rh, unsigned int *rect, float alpha, const float rgb[3], short is_preview) { @@ -994,6 +1085,8 @@ static int get_draw_size(enum eIconSizes size) return 0; } + + static void icon_draw_size(float x, float y, int icon_id, float aspect, float alpha, const float rgb[3], enum eIconSizes size, int draw_size, int UNUSED(nocreate), short is_preview) { @@ -1029,7 +1122,7 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, float al if (di->type == ICON_TYPE_VECTOR) { /* vector icons use the uiBlock transformation, they are not drawn * with untransformed coordinates like the other icons */ - di->data.vector.func((int)x, (int)y, ICON_DEFAULT_HEIGHT, ICON_DEFAULT_HEIGHT, 1.0f); + di->data.vector.func((int)x, (int)y, w, h, 1.0f); } else if (di->type == ICON_TYPE_TEXTURE) { /* texture image use premul alpha for correct scaling */ @@ -1042,6 +1135,8 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, float al /* it is a builtin icon */ iimg = di->data.buffer.image; + icon_verify_datatoc(iimg); + if (!iimg->rect) return; /* something has gone wrong! */ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 706301dc060..0b94a0dabdc 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -537,6 +537,8 @@ extern unsigned char checker_stipple_sml[32 * 32 / 8]; #define UI_TRANSP_DARK 100 #define UI_TRANSP_LIGHT 160 +#define UI_TEXT_MARGIN_X 0.4f + /* interface_style.c */ void uiStyleInit(void); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 3b0a1cd3eb5..10375824518 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -491,7 +491,14 @@ static void ui_item_enum_expand(uiLayout *layout, uiBlock *block, PointerRNA *pt RNA_property_enum_items_gettexted(block->evil_C, ptr, prop, &item, &totitem, &free); - uiBlockSetCurLayout(block, ui_item_local_sublayout(layout, layout, 1)); + /* we dont want nested rows, cols in menus */ + if (layout->root->type != UI_LAYOUT_MENU) { + uiBlockSetCurLayout(block, ui_item_local_sublayout(layout, layout, 1)); + } + else { + uiBlockSetCurLayout(block, layout); + } + for (a = 0; a < totitem; a++) { if (!item[a].identifier[0]) continue; @@ -1456,6 +1463,7 @@ void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propna block = uiLayoutGetBlock(layout); ui_item_rna_size(layout, name, icon, ptr, prop, 0, 0, &w, &h); + w += UI_UNIT_X; /* X icon needs more space */ but = ui_item_with_label(layout, block, name, icon, ptr, prop, 0, 0, 0, w, h, 0); ui_but_add_search(but, ptr, prop, searchptr, searchprop); diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 9fbf2fe8898..00c45e41587 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -522,11 +522,9 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, rcti *rect) float y = headrect.ymax; glEnable(GL_BLEND); - if (UI_GetThemeValue(TH_PANEL_SHOW_HEADER)) { /* draw with background color */ - glEnable(GL_BLEND); UI_ThemeColor4(TH_PANEL_HEADER); glRectf(minx, headrect.ymin + 1, maxx, y); @@ -542,7 +540,6 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, rcti *rect) fdrawline(minx, y, maxx, y); glColor4f(1.0f, 1.0f, 1.0f, 0.25f); fdrawline(minx, y - 1, maxx, y - 1); - glDisable(GL_BLEND); } glDisable(GL_BLEND); @@ -1157,6 +1154,9 @@ int ui_handler_panel_region(bContext *C, wmEvent *event) if (block->rect.xmin <= mx && block->rect.xmin + PNL_HEADER >= mx) inside_header = 1; } + else if (block->rect.xmin > mx || block->rect.xmax < mx) { + /* outside left/right side */ + } else if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my)) { inside_header = 1; } diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index ca5e2a1926c..e846fc3f078 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -651,7 +651,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but) ofsx = 0; //(but->block->panel) ? but->block->panel->ofsx : 0; ofsy = 0; //(but->block->panel) ? but->block->panel->ofsy : 0; - rect_fl.xmin = (but->rect.xmin + but->rect.xmax) * 0.5f + ofsx - TIP_BORDER_X; + rect_fl.xmin = BLI_rctf_cent_x(&but->rect) + ofsx - TIP_BORDER_X; rect_fl.xmax = rect_fl.xmin + fontw + TIP_BORDER_X; rect_fl.ymax = but->rect.ymin + ofsy - TIP_BORDER_Y; rect_fl.ymin = rect_fl.ymax - fonth - TIP_BORDER_Y; diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index f704ac0e203..ec2b4f5adf0 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -34,11 +34,14 @@ #include "DNA_dynamicpaint_types.h" #include "DNA_scene_types.h" #include "DNA_object_types.h" +#include "DNA_object_force.h" #include "BLI_utildefines.h" #include "BLI_string.h" #include "BLI_ghash.h" #include "BLI_rect.h" +#include "BLI_math.h" +#include "BLI_listbase.h" #include "BLF_api.h" #include "BLF_translation.h" @@ -46,22 +49,26 @@ #include "BKE_animsys.h" #include "BKE_colortools.h" #include "BKE_context.h" +#include "BKE_depsgraph.h" +#include "BKE_displist.h" #include "BKE_dynamicpaint.h" #include "BKE_global.h" #include "BKE_library.h" #include "BKE_main.h" -#include "BKE_object.h" #include "BKE_material.h" -#include "BKE_texture.h" +#include "BKE_modifier.h" +#include "BKE_object.h" +#include "BKE_particle.h" #include "BKE_report.h" -#include "BKE_displist.h" #include "BKE_sca.h" #include "BKE_scene.h" #include "BKE_screen.h" +#include "BKE_texture.h" #include "ED_screen.h" #include "ED_object.h" #include "ED_render.h" +#include "ED_util.h" #include "RNA_access.h" #include "RNA_enum_types.h" @@ -726,21 +733,6 @@ void uiTemplatePathBuilder(uiLayout *layout, PointerRNA *ptr, const char *propna #define ERROR_LIBDATA_MESSAGE "Can't edit external libdata" -#include <string.h> - -#include "DNA_object_force.h" - -#include "BKE_depsgraph.h" -#include "BKE_modifier.h" -#include "BKE_particle.h" - -#include "ED_util.h" - -#include "BLI_math.h" -#include "BLI_listbase.h" - -#include "ED_object.h" - static void modifiers_setOnCage(bContext *C, void *ob_v, void *md_v) { Scene *scene = CTX_data_scene(C); @@ -1564,6 +1556,88 @@ void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, const char *propname MEM_freeN(cb); } + +/********************* Icon viewer Template ************************/ + +/* ID Search browse menu, open */ +static uiBlock *icon_view_menu(bContext *C, ARegion *ar, void *arg_litem) +{ + static RNAUpdateCb cb; + uiBlock *block; + uiBut *but; + int icon; + EnumPropertyItem *item; + int a, free; + + /* arg_litem is malloced, can be freed by parent button */ + cb = *((RNAUpdateCb *)arg_litem); + + icon = RNA_property_enum_get(&cb.ptr, cb.prop); + + block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS); + uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_REDRAW); + + + RNA_property_enum_items(C, &cb.ptr, cb.prop, &item, NULL, &free); + + for (a = 0; item[a].identifier; a++) { + int x, y; + + x = (a % 8) * UI_UNIT_X * 6; + y = (a / 8) * UI_UNIT_X * 6; + + icon = item[a].icon; + but = uiDefIconButR_prop(block, ROW, 0, icon, x, y, UI_UNIT_X * 6, UI_UNIT_Y * 6, &cb.ptr, cb.prop, -1, 0, icon, -1, -1, NULL); + uiButSetFlag(but, UI_HAS_ICON | UI_ICON_PREVIEW); + } + + uiBoundsBlock(block, 0.3f * U.widget_unit); + uiBlockSetDirection(block, UI_TOP); + uiEndBlock(C, block); + + if (free) { + MEM_freeN(item); + } + + return block; +} + +void uiTemplateIconView(uiLayout *layout, PointerRNA *ptr, const char *propname) +{ + PropertyRNA *prop = RNA_struct_find_property(ptr, propname); + RNAUpdateCb *cb; + uiBlock *block; + uiBut *but; +// rctf rect; /* UNUSED */ + int icon; + + if (!prop || RNA_property_type(prop) != PROP_ENUM) + return; + + icon = RNA_property_enum_get(ptr, prop); + + cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb"); + cb->ptr = *ptr; + cb->prop = prop; + +// rect.xmin = 0; rect.xmax = 10.0f * UI_UNIT_X; +// rect.ymin = 0; rect.ymax = 10.0f * UI_UNIT_X; + + block = uiLayoutAbsoluteBlock(layout); + + but = uiDefBlockButN(block, icon_view_menu, MEM_dupallocN(cb), "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, ""); + + +// but = uiDefIconButR_prop(block, ROW, 0, icon, 0, 0, BLI_rctf_size_x(&rect), BLI_rctf_size_y(&rect), ptr, prop, -1, 0, icon, -1, -1, NULL); + + but->icon = icon; + uiButSetFlag(but, UI_HAS_ICON | UI_ICON_PREVIEW); + + uiButSetNFunc(but, rna_update_cb, MEM_dupallocN(cb), NULL); + + MEM_freeN(cb); +} + /********************* Histogram Template ************************/ void uiTemplateHistogram(uiLayout *layout, PointerRNA *ptr, const char *propname) @@ -2030,16 +2104,22 @@ static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labe } if (cmp) { - const float range_clamp[2] = {0.0f, 1.0f}; - const float range_unclamp[2] = {-1000.0f, 1000.0f}; /* arbitrary limits here */ - const float *range = (cumap->flag & CUMA_DO_CLIP) ? range_clamp : range_unclamp; + rctf bounds; + + if (cumap->flag & CUMA_DO_CLIP) { + bounds = cumap->clipr; + } + else { + bounds.xmin = bounds.ymin = -1000.0; + bounds.xmax = bounds.ymax = 1000.0; + } uiLayoutRow(layout, TRUE); uiBlockSetNFunc(block, curvemap_buttons_update, MEM_dupallocN(cb), cumap); bt = uiDefButF(block, NUM, 0, "X", 0, 2 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, - &cmp->x, range[0], range[1], 1, 5, ""); + &cmp->x, bounds.xmin, bounds.xmax, 1, 5, ""); bt = uiDefButF(block, NUM, 0, "Y", 0, 1 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, - &cmp->y, range[0], range[1], 1, 5, ""); + &cmp->y, bounds.ymin, bounds.ymax, 1, 5, ""); } /* black/white levels */ diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 6b44a82a52a..142ea5128c0 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -346,7 +346,7 @@ static void round_box__edges(uiWidgetBase *wt, int roundboxalign, const rcti *re (roundboxalign & (UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT)) == (UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT)) ? 1 : 2; minsize = min_ii(BLI_rcti_size_x(rect) * hnum, - BLI_rcti_size_y(rect) * vnum); + BLI_rcti_size_y(rect) * vnum); if (2.0f * rad > minsize) rad = 0.5f * minsize; @@ -1325,11 +1325,11 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB rect->xmin += (int)(0.8f * BLI_rcti_size_y(rect)); if (but->editstr || (but->flag & UI_TEXT_LEFT)) { - rect->xmin += (0.4f * U.widget_unit) / but->block->aspect; + rect->xmin += (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect; } } else if ((but->flag & UI_TEXT_LEFT)) { - rect->xmin += (0.4f * U.widget_unit) / but->block->aspect; + rect->xmin += (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect; } /* unlink icon for this button type */ @@ -1794,11 +1794,19 @@ static void widget_state_menu_item(uiWidgetType *wt, int state) { wt->wcol = *(wt->wcol_theme); - if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) { - wt->wcol.text[0] = 0.5f * (wt->wcol.text[0] + wt->wcol.text_sel[0]); - wt->wcol.text[1] = 0.5f * (wt->wcol.text[1] + wt->wcol.text_sel[1]); - wt->wcol.text[2] = 0.5f * (wt->wcol.text[2] + wt->wcol.text_sel[2]); + /* active and disabled (not so common) */ + if ((state & UI_BUT_DISABLED) && (state & UI_ACTIVE)) { + widget_state_blend(wt->wcol.text, wt->wcol.text_sel, 0.5f); + /* draw the backdrop at low alpha, helps navigating with keys + * when disabled items are active */ + copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel); + wt->wcol.inner[3] = 64; + } + /* regular disabled */ + else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) { + widget_state_blend(wt->wcol.text, wt->wcol.text_sel, 0.5f); } + /* regular active */ else if (state & UI_ACTIVE) { copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel); copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel); @@ -3443,7 +3451,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic uiWidgetType *wt = widget_type(UI_WTYPE_MENU_ITEM); rcti _rect = *rect; char *cpoin; - + wt->state(wt, state); wt->draw(&wt->wcol, rect, 0, 0); diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 471193d10d8..7efda2f56c3 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -395,6 +395,10 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo cp = ts->syntaxc; break; case TH_NODE_FRAME: cp = ts->movie; break; + case TH_NODE_MATTE: + cp = ts->syntaxs; break; + case TH_NODE_DISTORT: + cp = ts->syntaxd; break; case TH_NODE_CURVING: cp = &ts->noodle_curving; break; @@ -2116,7 +2120,7 @@ void init_userdef_do_versions(void) btheme->tclip.panelcolors = btheme->tui.panel; } } - + if (bmain->versionfile < 266) { bTheme *btheme; @@ -2145,6 +2149,14 @@ void init_userdef_do_versions(void) } } + if (!MAIN_VERSION_ATLEAST(bmain, 265, 9)) { + bTheme *btheme; + for (btheme = U.themes.first; btheme; btheme = btheme->next) { + rgba_char_args_test_set(btheme->tnode.syntaxs, 151, 116, 116, 255); /* matte nodes */ + rgba_char_args_test_set(btheme->tnode.syntaxd, 116, 151, 151, 255); /* distort nodes */ + } + } + if (U.pixelsize == 0.0f) U.pixelsize = 1.0f; diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 9236800c16b..fbbcb650e68 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -952,6 +952,13 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, wmEvent *event) fac = 0.01f * (event->prevy - event->y); dy = fac * BLI_rctf_size_y(&v2d->cur) / 10.0f; + /* support trackpad zoom to always zoom entirely - the v2d code uses portrait or landscape exceptions */ + if (v2d->keepzoom & V2D_KEEPASPECT) { + if (fabsf(dx) > fabsf(dy)) + dy = dx; + else + dx = dy; + } RNA_float_set(op->ptr, "deltax", dx); RNA_float_set(op->ptr, "deltay", dy); @@ -1039,6 +1046,14 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, wmEvent *event) } + /* support zoom to always zoom entirely - the v2d code uses portrait or landscape exceptions */ + if (v2d->keepzoom & V2D_KEEPASPECT) { + if (fabsf(dx) > fabsf(dy)) + dy = dx; + else + dx = dy; + } + /* set transform amount, and add current deltas to stored total delta (for redo) */ RNA_float_set(op->ptr, "deltax", dx); RNA_float_set(op->ptr, "deltay", dy); diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index ba93206e63a..f53672b7092 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -84,6 +84,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) int selected; int include_children; int include_armatures; + int include_shapekeys; int deform_bones_only; int include_uv_textures; @@ -109,6 +110,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) selected = RNA_boolean_get(op->ptr, "selected"); include_children = RNA_boolean_get(op->ptr, "include_children"); include_armatures = RNA_boolean_get(op->ptr, "include_armatures"); + include_shapekeys = RNA_boolean_get(op->ptr, "include_shapekeys"); deform_bones_only = RNA_boolean_get(op->ptr, "deform_bones_only"); include_uv_textures = RNA_boolean_get(op->ptr, "include_uv_textures"); @@ -130,6 +132,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) selected, include_children, include_armatures, + include_shapekeys, deform_bones_only, active_uv_only, @@ -176,6 +179,10 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) uiItemR(row, imfptr, "include_armatures", 0, NULL, ICON_NONE); uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected")); + row = uiLayoutRow(box, FALSE); + uiItemR(row, imfptr, "include_shapekeys", 0, NULL, ICON_NONE); + uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected")); + /* Texture options */ box = uiLayoutBox(layout); row = uiLayoutRow(box, FALSE); @@ -266,6 +273,9 @@ void WM_OT_collada_export(wmOperatorType *ot) RNA_def_boolean(ot->srna, "include_armatures", 0, "Include Armatures", "Export related armatures (even if not selected)"); + RNA_def_boolean(ot->srna, "include_shapekeys", 1, "Include Shape Keys", + "Export all Shape Keys from Mesh Objects"); + RNA_def_boolean(ot->srna, "deform_bones_only", 0, "Deform Bones only", "Only export deforming bones with armatures"); diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index 74cdf4c2a11..af9d3341e61 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -409,7 +409,7 @@ static void draw_spline_curve(const bContext *C, MaskLayer *masklay, MaskSpline int width, int height) { const unsigned int resol = max_ii(BKE_mask_spline_feather_resolution(spline, width, height), - BKE_mask_spline_resolution(spline, width, height)); + BKE_mask_spline_resolution(spline, width, height)); unsigned char rgb_tmp[4]; diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt index 3180886b2b6..b51d55aaf0e 100644 --- a/source/blender/editors/mesh/CMakeLists.txt +++ b/source/blender/editors/mesh/CMakeLists.txt @@ -48,7 +48,6 @@ set(SRC editmesh_select.c editmesh_tools.c editmesh_utils.c - editmesh_slide.c mesh_data.c mesh_ops.c meshtools.c diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 5e1d954a2ea..e49dc3c28f9 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -128,7 +128,7 @@ typedef struct KnifePosData { BMFace *bmface; int is_space; - int mval[2]; /* mouse screen position */ + float mval[2]; /* mouse screen position (may be non-integral if snapped to something) */ } KnifePosData; /* struct for properties used while drawing */ @@ -204,10 +204,10 @@ typedef struct KnifeTool_OpData { static ListBase *knife_get_face_kedges(KnifeTool_OpData *kcd, BMFace *f); #if 0 -static void knife_input_ray_cast(KnifeTool_OpData *kcd, const int mval_i[2], +static void knife_input_ray_cast(KnifeTool_OpData *kcd, const float mval[2], float r_origin[3], float r_ray[3]); #endif -static void knife_input_ray_segment(KnifeTool_OpData *kcd, const int mval_i[2], const float ofs, +static void knife_input_ray_segment(KnifeTool_OpData *kcd, const float mval[2], const float ofs, float r_origin[3], float r_dest[3]); static void knife_update_header(bContext *C, KnifeTool_OpData *kcd) @@ -225,6 +225,10 @@ static void knife_update_header(bContext *C, KnifeTool_OpData *kcd) ED_area_headerprint(CTX_wm_area(C), header); } +BLI_INLINE int round_ftoi(float x) +{ + return x > 0.0f ? (int)(x + 0.5f) : (int)(x - 0.5f); +} static void knife_project_v3(KnifeTool_OpData *kcd, const float co[3], float sco[3]) { @@ -238,8 +242,8 @@ static void knife_pos_data_clear(KnifePosData *kpd) kpd->vert = NULL; kpd->edge = NULL; kpd->bmface = NULL; - kpd->mval[0] = 0; - kpd->mval[1] = 0; + kpd->mval[0] = 0.0f; + kpd->mval[1] = 0.0f; } static ListBase *knife_empty_list(KnifeTool_OpData *kcd) @@ -1420,17 +1424,14 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) /* this works but gives numeric problems [#33400] */ #if 0 -static void knife_input_ray_cast(KnifeTool_OpData *kcd, const int mval_i[2], +static void knife_input_ray_cast(KnifeTool_OpData *kcd, const float mval[2], float r_origin[3], float r_ray[3]) { bglMats mats; - float mval[2], imat[3][3]; + float imat[3][3]; knife_bgl_get_mats(kcd, &mats); - mval[0] = (float)mval_i[0]; - mval[1] = (float)mval_i[1]; - /* unproject to find view ray */ ED_view3d_unproject(&mats, r_origin, mval[0], mval[1], 0.0f); @@ -1452,23 +1453,19 @@ static void knife_input_ray_cast(KnifeTool_OpData *kcd, const int mval_i[2], } #endif -static void knife_input_ray_segment(KnifeTool_OpData *kcd, const int mval_i[2], const float ofs, +static void knife_input_ray_segment(KnifeTool_OpData *kcd, const float mval[2], const float ofs, float r_origin[3], float r_origin_ofs[3]) { bglMats mats; - float mval[2]; knife_bgl_get_mats(kcd, &mats); - mval[0] = (float)mval_i[0]; - mval[1] = (float)mval_i[1]; - /* unproject to find view ray */ ED_view3d_unproject(&mats, r_origin, mval[0], mval[1], 0.0f); ED_view3d_unproject(&mats, r_origin_ofs, mval[0], mval[1], ofs); /* transform into object space */ - invert_m4_m4(kcd->ob->imat, kcd->ob->obmat); + invert_m4_m4(kcd->ob->imat, kcd->ob->obmat); mul_m4_v3(kcd->ob->imat, r_origin); mul_m4_v3(kcd->ob->imat, r_origin_ofs); @@ -1483,7 +1480,7 @@ static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float float ray[3]; /* unproject to find view ray */ - knife_input_ray_segment(kcd, kcd->vc.mval, 1.0f, origin, origin_ofs); + knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs); sub_v3_v3v3(ray, origin_ofs, origin); f = BMBVH_RayCast(kcd->bmbvh, origin, ray, co, cageco); @@ -1641,8 +1638,8 @@ static KnifeEdge *knife_find_closest_edge(KnifeTool_OpData *kcd, float p[3], flo /* update mouse coordinates to the snapped-to edge's screen coordinates * this is important for angle snap, which uses the previous mouse position */ edgesnap = new_knife_vert(kcd, p, cagep); - kcd->curr.mval[0] = (int)edgesnap->sco[0]; - kcd->curr.mval[1] = (int)edgesnap->sco[1]; + kcd->curr.mval[0] = edgesnap->sco[0]; + kcd->curr.mval[1] = edgesnap->sco[1]; } else { @@ -1720,8 +1717,8 @@ static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], flo /* update mouse coordinates to the snapped-to vertex's screen coordinates * this is important for angle snap, which uses the previous mouse position */ - kcd->curr.mval[0] = (int)curv->sco[0]; - kcd->curr.mval[1] = (int)curv->sco[1]; + kcd->curr.mval[0] = curv->sco[0]; + kcd->curr.mval[1] = curv->sco[1]; } return curv; @@ -1740,48 +1737,56 @@ static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], flo return NULL; } +/* update both kcd->curr.mval and kcd->vc.mval to snap to required angle */ static void knife_snap_angle(KnifeTool_OpData *kcd) { - int dx, dy; + float dx, dy; float w, abs_tan; - dx = kcd->vc.mval[0] - kcd->prev.mval[0]; - dy = kcd->vc.mval[1] - kcd->prev.mval[1]; - if (dx == 0 || dy == 0) + dx = kcd->curr.mval[0] - kcd->prev.mval[0]; + dy = kcd->curr.mval[1] - kcd->prev.mval[1]; + if (dx == 0.0f && dy == 0.0f) return; - w = (float)dy / (float)dx; + if (dx == 0.0f) { + kcd->angle_snapping = ANGLE_90; + kcd->curr.mval[0] = kcd->prev.mval[0]; + } + + w = dy / dx; abs_tan = fabsf(w); if (abs_tan <= 0.4142f) { /* tan(22.5 degrees) = 0.4142 */ kcd->angle_snapping = ANGLE_0; - kcd->vc.mval[1] = kcd->prev.mval[1]; + kcd->curr.mval[1] = kcd->prev.mval[1]; } else if (abs_tan < 2.4142f) { /* tan(67.5 degrees) = 2.4142 */ if (w > 0) { kcd->angle_snapping = ANGLE_45; - kcd->vc.mval[1] = kcd->prev.mval[1] + dx; + kcd->curr.mval[1] = kcd->prev.mval[1] + dx; } else { kcd->angle_snapping = ANGLE_135; - kcd->vc.mval[1] = kcd->prev.mval[1] - dx; + kcd->curr.mval[1] = kcd->prev.mval[1] - dx; } } else { kcd->angle_snapping = ANGLE_90; - kcd->vc.mval[0] = kcd->prev.mval[0]; + kcd->curr.mval[0] = kcd->prev.mval[0]; } + + kcd->vc.mval[0] = round_ftoi(kcd->curr.mval[0]); + kcd->vc.mval[1] = round_ftoi(kcd->curr.mval[1]); } /* update active knife edge/vert pointers */ static int knife_update_active(KnifeTool_OpData *kcd) { + knife_pos_data_clear(&kcd->curr); + kcd->curr.mval[0] = (float)kcd->vc.mval[0]; + kcd->curr.mval[1] = (float)kcd->vc.mval[1]; if (kcd->angle_snapping != ANGLE_FREE && kcd->mode == MODE_DRAGGING) knife_snap_angle(kcd); - knife_pos_data_clear(&kcd->curr); - kcd->curr.mval[0] = kcd->vc.mval[0]; - kcd->curr.mval[1] = kcd->vc.mval[1]; - /* XXX knife_snap_angle updates the view coordinate mouse values to constrained angles, * which current mouse values are set to current mouse values are then used * for vertex and edge snap detection, without regard to the exact angle constraint */ @@ -1799,7 +1804,7 @@ static int knife_update_active(KnifeTool_OpData *kcd) float origin[3]; float origin_ofs[3]; - knife_input_ray_segment(kcd, kcd->vc.mval, 1.0f, origin, origin_ofs); + knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs); closest_to_line_v3(kcd->curr.cage, kcd->prev.cage, origin_ofs, origin); } @@ -2929,11 +2934,11 @@ static void cage_mapped_verts_callback(void *userData, int index, const float co } } -static void knifetool_update_mval(KnifeTool_OpData *kcd, int mval[2]) +static void knifetool_update_mval(KnifeTool_OpData *kcd, int mval_i[2]) { knife_recalc_projmat(kcd); - kcd->vc.mval[0] = mval[0]; - kcd->vc.mval[1] = mval[1]; + kcd->vc.mval[0] = mval_i[0]; + kcd->vc.mval[1] = mval_i[1]; if (knife_update_active(kcd)) { ED_region_tag_redraw(kcd->ar); diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 5f923dd65c6..d1373363992 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -154,9 +154,9 @@ static void edgering_find_order(BMEdge *lasteed, BMEdge *eed, static void edgering_sel(RingSelOpData *lcd, int previewlines, int select) { BMEditMesh *em = lcd->em; - BMEdge *startedge = lcd->eed; - BMEdge *eed, *lasteed; - BMVert *v[2][2], *lastv1; + BMEdge *eed_start = lcd->eed; + BMEdge *eed, *eed_last; + BMVert *v[2][2], *v_last; BMWalker walker; float (*edges)[2][3] = NULL; BLI_array_declare(edges); @@ -164,7 +164,7 @@ static void edgering_sel(RingSelOpData *lcd, int previewlines, int select) memset(v, 0, sizeof(v)); - if (!startedge) + if (!eed_start) return; if (lcd->edges) { @@ -183,8 +183,7 @@ static void edgering_sel(RingSelOpData *lcd, int previewlines, int select) BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); - eed = BMW_begin(&walker, startedge); - for ( ; eed; eed = BMW_step(&walker)) { + for (eed = BMW_begin(&walker, eed_start); eed; eed = BMW_step(&walker)) { BM_edge_select_set(em->bm, eed, TRUE); } BMW_end(&walker); @@ -197,22 +196,23 @@ static void edgering_sel(RingSelOpData *lcd, int previewlines, int select) BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); - eed = startedge = BMW_begin(&walker, startedge); - lastv1 = NULL; - for (lasteed = NULL; eed; eed = BMW_step(&walker)) { - if (lasteed) { - if (lastv1) { + v_last = NULL; + eed_last = NULL; + + for (eed = eed_start = BMW_begin(&walker, eed_start); eed; eed = BMW_step(&walker)) { + if (eed_last) { + if (v_last) { v[1][0] = v[0][0]; v[1][1] = v[0][1]; } else { - v[1][0] = lasteed->v1; - v[1][1] = lasteed->v2; - lastv1 = lasteed->v1; + v[1][0] = eed_last->v1; + v[1][1] = eed_last->v2; + v_last = eed_last->v1; } - edgering_find_order(lasteed, eed, lastv1, v); - lastv1 = v[0][0]; + edgering_find_order(eed_last, eed, v_last, v); + v_last = v[0][0]; BLI_array_grow_items(edges, previewlines); @@ -223,18 +223,18 @@ static void edgering_sel(RingSelOpData *lcd, int previewlines, int select) tot++; } } - lasteed = eed; + eed_last = eed; } #ifdef BMW_EDGERING_NGON if (lasteed != startedge && BM_edge_share_face_check(lasteed, startedge)) { #else - if (lasteed != startedge && BM_edge_share_quad_check(lasteed, startedge)) { + if (eed_last != eed_start && BM_edge_share_quad_check(eed_last, eed_start)) { #endif v[1][0] = v[0][0]; v[1][1] = v[0][1]; - edgering_find_order(lasteed, startedge, lastv1, v); + edgering_find_order(eed_last, eed_start, v_last, v); BLI_array_grow_items(edges, previewlines); @@ -502,7 +502,8 @@ static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event) ED_region_tag_redraw(lcd->ar); break; - case MOUSEMOVE: { /* mouse moved somewhere to select another loop */ + case MOUSEMOVE: /* mouse moved somewhere to select another loop */ + { float dist = 75.0f; BMEdge *edge; diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 38887307a76..88d826c2f98 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -995,8 +995,8 @@ static void walker_select(BMEditMesh *em, int walkercode, void *start, int selec BMW_MASK_NOP, BMW_MASK_NOP, BMW_MASK_NOP, BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); - ele = BMW_begin(&walker, start); - for (; ele; ele = BMW_step(&walker)) { + + for (ele = BMW_begin(&walker, start); ele; ele = BMW_step(&walker)) { if (!select) { BM_select_history_remove(bm, ele); } @@ -1782,7 +1782,7 @@ void MESH_OT_select_shortest_path(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); + RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection"); } /* ************************************************** */ @@ -2286,8 +2286,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent * BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); - efa = BMW_begin(&walker, efa); - for (; efa; efa = BMW_step(&walker)) { + for (efa = BMW_begin(&walker, efa); efa; efa = BMW_step(&walker)) { BM_face_select_set(bm, efa, sel); } BMW_end(&walker); @@ -2308,8 +2307,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent * BMW_FLAG_TEST_HIDDEN, BMW_NIL_LAY); - e = BMW_begin(&walker, eed->v1); - for (; e; e = BMW_step(&walker)) { + for (e = BMW_begin(&walker, eed->v1); e; e = BMW_step(&walker)) { BM_edge_select_set(bm, e, sel); } BMW_end(&walker); @@ -2380,8 +2378,7 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { - efa = BMW_begin(&walker, efa); - for (; efa; efa = BMW_step(&walker)) { + for (efa = BMW_begin(&walker, efa); efa; efa = BMW_step(&walker)) { BM_face_select_set(bm, efa, TRUE); } } @@ -2409,10 +2406,8 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(v, BM_ELEM_TAG)) { - e = BMW_begin(&walker, v); - for (; e; e = BMW_step(&walker)) { - BM_vert_select_set(em->bm, e->v1, TRUE); - BM_vert_select_set(em->bm, e->v2, TRUE); + for (e = BMW_begin(&walker, v); e; e = BMW_step(&walker)) { + BM_edge_select_set(em->bm, e, true); } } } @@ -2859,6 +2854,9 @@ static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op) BMEdge *e; BMIter iter; + if (!RNA_boolean_get(op->ptr, "extend")) + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + /* Selects isolated verts, and edges that do not have 2 neighboring * faces */ @@ -2898,6 +2896,9 @@ void MESH_OT_select_non_manifold(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* props */ + RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend the selection"); } static int edbm_select_random_exec(bContext *C, wmOperator *op) @@ -2962,8 +2963,7 @@ void MESH_OT_select_random(wmOperatorType *ot) /* props */ RNA_def_float_percentage(ot->srna, "percent", 50.f, 0.0f, 100.0f, "Percent", "Percentage of elements to select randomly", 0.f, 100.0f); - RNA_def_boolean(ot->srna, "extend", 0, - "Extend Selection", "Extend selection instead of deselecting everything first"); + RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection"); } static int edbm_select_next_loop_exec(bContext *C, wmOperator *UNUSED(op)) diff --git a/source/blender/editors/mesh/editmesh_slide.c b/source/blender/editors/mesh/editmesh_slide.c deleted file mode 100644 index eb0a21261ce..00000000000 --- a/source/blender/editors/mesh/editmesh_slide.c +++ /dev/null @@ -1,793 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributor(s): Francisco De La Cruz - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/editors/mesh/editmesh_slide.c - * \ingroup edmesh - */ - -/* Takes heavily from editmesh_loopcut.c */ - -#include "DNA_object_types.h" -#include "DNA_mesh_types.h" - -#include "MEM_guardedalloc.h" - -#include "BLI_array.h" -#include "BLI_math.h" - -#include "BLF_translation.h" - -#include "BKE_context.h" -#include "BKE_report.h" -#include "BKE_tessmesh.h" - -#include "BIF_gl.h" -#include "BIF_glutil.h" - -#include "ED_screen.h" -#include "ED_view3d.h" -#include "ED_mesh.h" -#include "ED_space_api.h" - -#include "UI_resources.h" - -#include "RNA_access.h" -#include "RNA_define.h" - -#include "WM_api.h" -#include "WM_types.h" - -#include "mesh_intern.h" - -#define VTX_SLIDE_SNAP_THRSH 15 - -/* Cusom VertexSlide Operator data */ -typedef struct VertexSlideOp { - /* Starting Vertex */ - BMVert *start_vtx; - BMEdge *sel_edge; - - ViewContext *view_context; - ARegion *active_region; - - /* Draw callback handle */ - void *draw_handle; - - /* Active Object */ - Object *obj; - - /* Are we in slide mode */ - int slide_mode; - int snap_n_merge; - int snap_to_end_vtx; - int snap_to_mid; - - /* Snap threshold */ - float snap_threshold; - - float distance; - float interp[3]; - - /* Edge Frame Count */ - int disk_edges; - - /* Edges */ - BMEdge **edge_frame; - - /* Slide Frame Endpoints */ - float (*vtx_frame)[3]; - - /* Mouse Click 2d pos */ - int m_co[2]; - -} VertexSlideOp; - -static void vtx_slide_draw(const bContext *C, ARegion *ar, void *arg); -static int edbm_vertex_slide_exec_ex(bContext *C, wmOperator *op, const int do_update); -static void vtx_slide_exit(const bContext *C, wmOperator *op); -static int vtx_slide_set_frame(VertexSlideOp *vso); - -static int vtx_slide_init(bContext *C, wmOperator *op) -{ - Object *obedit = CTX_data_edit_object(C); - BMEditMesh *em = BMEdit_FromObject(obedit); - BMEditSelection *ese; - - /* Custom data */ - VertexSlideOp *vso; - - const char *header_str = TIP_("Vertex Slide: Hover over an edge and left-click to select slide edge. " - "Left-Shift: Midpoint Snap, Left-Alt: Snap, Left-Ctrl: Snap & Merge"); - - if (!obedit) { - BKE_report(op->reports, RPT_ERROR, "Vertex slide error: no object in context"); - return FALSE; - } - - EDBM_selectmode_flush(em); - ese = em->bm->selected.last; - - /* Is there a starting vertex ? */ - if (ese == NULL || (ese->htype != BM_VERT && ese->htype != BM_EDGE)) { - BKE_report(op->reports, RPT_ERROR_INVALID_INPUT, "Vertex slide error: select a (single) vertex"); - return FALSE; - } - - vso = MEM_callocN(sizeof(VertexSlideOp), "Vertex Slide Operator"); - vso->view_context = MEM_callocN(sizeof(ViewContext), "Vertex Slide View Context"); - - op->customdata = vso; - - /* Set the start vertex */ - vso->start_vtx = (BMVert *)ese->ele; - - vso->sel_edge = NULL; - - /* Edges */ - vso->edge_frame = NULL; - - vso->vtx_frame = NULL; - - vso->disk_edges = 0; - - vso->slide_mode = FALSE; - - vso->snap_n_merge = FALSE; - - vso->snap_to_end_vtx = FALSE; - - vso->snap_to_mid = FALSE; - - vso->distance = 0.0f; - - vso->snap_threshold = 0.2f; - - /* Notify the viewport */ - view3d_operator_needs_opengl(C); - - /* Set the drawing region */ - vso->active_region = CTX_wm_region(C); - - /* Set the draw callback */ - vso->draw_handle = ED_region_draw_cb_activate(vso->active_region->type, vtx_slide_draw, vso, REGION_DRAW_POST_VIEW); - - ED_area_headerprint(CTX_wm_area(C), header_str); - - em_setup_viewcontext(C, vso->view_context); - - /* Set the object */ - vso->obj = obedit; - - /* Init frame */ - if (!vtx_slide_set_frame(vso)) { - BKE_report(op->reports, RPT_ERROR_INVALID_INPUT, "Vertex slide error: cannot find starting vertex!"); - vtx_slide_exit(C, op); - return FALSE; - } - - /* Add handler for the vertex sliding */ - WM_event_add_modal_handler(C, op); - - /* Tag for redraw */ - ED_region_tag_redraw(vso->active_region); - - return TRUE; -} - -static void vtx_slide_confirm(bContext *C, wmOperator *op) -{ - VertexSlideOp *vso = op->customdata; - BMEditMesh *em = BMEdit_FromObject(vso->obj); - BMesh *bm = em->bm; - BMVert *other = NULL; - - BMVert *mirr_vtx = NULL; - BMVert *mirr_vtx_other = NULL; - - /* Select new edge */ - BM_edge_select_set(bm, vso->sel_edge, TRUE); - - if (vso->snap_n_merge) { - other = BM_edge_other_vert(vso->sel_edge, vso->start_vtx); - } - - if (((Mesh *)em->ob->data)->editflag & ME_EDIT_MIRROR_X) { - EDBM_verts_mirror_cache_begin(em, TRUE); - - mirr_vtx = EDBM_verts_mirror_get(em, vso->start_vtx); - if (vso->snap_n_merge) { - mirr_vtx_other = EDBM_verts_mirror_get(em, other); - } - } - - /* Invoke operator - warning */ - edbm_vertex_slide_exec_ex(C, op, FALSE); - - if (mirr_vtx) { - mirr_vtx->co[0] = -vso->start_vtx->co[0]; - mirr_vtx->co[1] = vso->start_vtx->co[1]; - mirr_vtx->co[2] = vso->start_vtx->co[2]; - } - - if (vso->snap_n_merge) { - float other_d; - other_d = len_v3v3(vso->interp, other->co); - - /* Only snap if within threshold */ - if (other_d < vso->snap_threshold) { - BM_vert_select_set(bm, other, TRUE); - BM_vert_select_set(bm, vso->start_vtx, TRUE); - EDBM_op_callf(em, op, "pointmerge verts=%hv merge_co=%v", BM_ELEM_SELECT, other->co); - EDBM_flag_disable_all(em, BM_ELEM_SELECT); - - if (mirr_vtx_other) { - BM_vert_select_set(bm, mirr_vtx, TRUE); - BM_vert_select_set(bm, mirr_vtx_other, TRUE); - EDBM_op_callf(em, op, "pointmerge verts=%hv merge_co=%v", BM_ELEM_SELECT, mirr_vtx_other->co); - EDBM_flag_disable_all(em, BM_ELEM_SELECT); - } - } - else { - /* Store in historty if not merging */ - BM_select_history_store(em->bm, vso->start_vtx); - } - } - else { - /* Store edit selection of the active vertex, allows other - * ops to run without reselecting */ - BM_select_history_store(em->bm, vso->start_vtx); - } - - if (((Mesh *)em->ob->data)->editflag & ME_EDIT_MIRROR_X) { - EDBM_verts_mirror_cache_end(em); - } - - EDBM_selectmode_flush(em); - - /* NC_GEOM | ND_DATA & Retess */ - EDBM_update_generic(em, TRUE, FALSE); - - ED_region_tag_redraw(vso->active_region); -} - -static void vtx_slide_exit(const bContext *C, wmOperator *op) -{ - /* Fetch custom data */ - VertexSlideOp *vso = op->customdata; - - /* Clean-up the custom data */ - ED_region_draw_cb_exit(vso->active_region->type, vso->draw_handle); - - /* Free Custom Data - * - */ - MEM_freeN(vso->view_context); - - vso->view_context = NULL; - - if (vso->edge_frame) { - MEM_freeN(vso->edge_frame); - } - - if (vso->vtx_frame) { - MEM_freeN(vso->vtx_frame); - } - - vso->edge_frame = NULL; - - vso->vtx_frame = NULL; - - vso->slide_mode = FALSE; - - MEM_freeN(vso); - vso = NULL; - op->customdata = NULL; - - /* Clear the header */ - ED_area_headerprint(CTX_wm_area(C), NULL); -} - -static void vtx_slide_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) -{ - VertexSlideOp *vso = arg; - - /* Have an edge to draw */ - if (vso && vso->sel_edge) { - /* Get 3d view */ - View3D *view3d = CTX_wm_view3d(C); - const float outline_w = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.8f; - const float pt_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f; - - int i = 0; - - if (view3d && view3d->zbuf) - glDisable(GL_DEPTH_TEST); - - glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT | GL_POINT_BIT); - - glPushMatrix(); - glMultMatrixf(vso->obj->obmat); - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - - if (vso->slide_mode && vso->disk_edges > 0) { - /* Draw intermediate edge frame */ - UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 50, -50); - - for (i = 0; i < vso->disk_edges; i++) { - glBegin(GL_LINES); - glVertex3fv(vso->vtx_frame[i]); - glVertex3fv(vso->interp); - glEnd(); - } - } - - /* Draw selected edge - * Add color offset and reduce alpha */ - UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 40, -50); - - glLineWidth(outline_w); - - glBegin(GL_LINES); - bglVertex3fv(vso->sel_edge->v1->co); - bglVertex3fv(vso->sel_edge->v2->co); - glEnd(); - - if (vso->slide_mode) { - /* Draw interpolated vertex */ - - UI_ThemeColorShadeAlpha(TH_FACE_DOT, -80, -50); - - glPointSize(pt_size); - - bglBegin(GL_POINTS); - bglVertex3fv(vso->interp); - bglEnd(); - } - - glDisable(GL_BLEND); - glPopMatrix(); - glPopAttrib(); - - if (view3d && view3d->zbuf) - glEnable(GL_DEPTH_TEST); - } -} - -static BMEdge *vtx_slide_nrst_in_frame(VertexSlideOp *vso, const float mval[2]) -{ - BMEdge *cl_edge = NULL; - if (vso->disk_edges > 0) { - int i = 0; - BMEdge *edge = NULL; - - float v1_proj[3], v2_proj[3]; - float min_dist = FLT_MAX; - - for (i = 0; i < vso->disk_edges; i++) { - edge = vso->edge_frame[i]; - - mul_v3_m4v3(v1_proj, vso->obj->obmat, edge->v1->co); - mul_v3_m4v3(v2_proj, vso->obj->obmat, edge->v2->co); - - /* we could use ED_view3d_project_float_object here, but for now dont since we dont have the context */ - if ((ED_view3d_project_float_global(vso->active_region, v1_proj, v1_proj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) && - (ED_view3d_project_float_global(vso->active_region, v2_proj, v2_proj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK)) - { - const float dist = dist_to_line_segment_v2(mval, v1_proj, v2_proj); - if (dist < min_dist) { - min_dist = dist; - cl_edge = edge; - } - } - } - } - return cl_edge; -} - -static void vtx_slide_find_edge(VertexSlideOp *vso, wmEvent *event) -{ - /* Nearest edge */ - BMEdge *nst_edge = NULL; - - const float mval_float[2] = {(float)event->mval[0], - (float)event->mval[1]}; - - /* Set mouse coords */ - copy_v2_v2_int(vso->view_context->mval, event->mval); - - /* Find nearest edge */ - nst_edge = vtx_slide_nrst_in_frame(vso, mval_float); - - if (nst_edge) { - /* Find a connected edge */ - if (BM_vert_in_edge(nst_edge, vso->start_vtx)) { - - /* Save mouse coords */ - copy_v2_v2_int(vso->m_co, event->mval); - - /* Set edge */ - vso->sel_edge = nst_edge; - } - } -} - -/* Updates the status of the operator - Invoked on mouse movement */ -static void vtx_slide_update(VertexSlideOp *vso, wmEvent *event) -{ - BMEdge *edge; - - /* Find nearest edge */ - edge = vso->sel_edge; - - if (edge) { - float edge_other_proj[3]; - float start_vtx_proj[3]; - float edge_len; - BMVert *other; - - float interp[3]; - - /* Calculate interpolation value for preview */ - float t_val; - - float mval_float[2] = { (float)event->mval[0], (float)event->mval[1]}; - float closest_2d[2]; - - other = BM_edge_other_vert(edge, vso->start_vtx); - - /* Project points onto screen and do interpolation in 2D */ - mul_v3_m4v3(start_vtx_proj, vso->obj->obmat, vso->start_vtx->co); - mul_v3_m4v3(edge_other_proj, vso->obj->obmat, other->co); - - if ((ED_view3d_project_float_global(vso->active_region, edge_other_proj, edge_other_proj, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) || - (ED_view3d_project_float_global(vso->active_region, start_vtx_proj, start_vtx_proj, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK)) - { - /* not much we can do here */ - return; - } - - closest_to_line_v2(closest_2d, mval_float, start_vtx_proj, edge_other_proj); - - t_val = line_point_factor_v2(closest_2d, start_vtx_proj, edge_other_proj); - - /* Set snap threshold to be proportional to edge length */ - edge_len = len_v3v3(start_vtx_proj, edge_other_proj); - - if (edge_len <= 0.0f) - edge_len = VTX_SLIDE_SNAP_THRSH; - - edge_len = (BM_edge_calc_length(edge) * VTX_SLIDE_SNAP_THRSH) / edge_len; - - vso->snap_threshold = edge_len; - - /* Snap to mid */ - if (vso->snap_to_mid) { - t_val = 0.5f; - } - - /* Interpolate preview vertex 3D */ - interp_v3_v3v3(interp, vso->start_vtx->co, other->co, t_val); - copy_v3_v3(vso->interp, interp); - - vso->distance = t_val; - - /* If snapping */ - if (vso->snap_to_end_vtx) { - int start_at_v1 = edge->v1 == vso->start_vtx; - float v1_d = len_v3v3(vso->interp, edge->v1->co); - float v2_d = len_v3v3(vso->interp, edge->v2->co); - - if (v1_d > v2_d && v2_d < vso->snap_threshold) { - copy_v3_v3(vso->interp, edge->v2->co); - - if (start_at_v1) - vso->distance = 1.0f; - else - vso->distance = 0.0f; - } - if (v2_d > v1_d && v1_d < vso->snap_threshold) { - copy_v3_v3(vso->interp, edge->v1->co); - if (start_at_v1) - vso->distance = 0.0f; - else - vso->distance = 1.0f; - } - } - } -} - -/* Sets the outline frame */ -static int vtx_slide_set_frame(VertexSlideOp *vso) -{ - BMEdge *edge; - float (*vtx_frame)[3] = NULL; - BMEdge **edge_frame = NULL; - BMVert *curr_vert = NULL; - BLI_array_declare(vtx_frame); - BLI_array_declare(edge_frame); - BMIter iter; - BMVert *sel_vtx = vso->start_vtx; - int idx = 0; - - vso->disk_edges = 0; - - if (vso->edge_frame) { - MEM_freeN(vso->edge_frame); - vso->edge_frame = NULL; - } - - if (vso->vtx_frame) { - MEM_freeN(vso->vtx_frame); - vso->vtx_frame = NULL; - } - - /* Iterate over edges of vertex and copy them */ - BM_ITER_ELEM_INDEX (edge, &iter, sel_vtx, BM_EDGES_OF_VERT, idx) { - curr_vert = BM_edge_other_vert(edge, sel_vtx); - if (curr_vert) { - BLI_array_grow_one(vtx_frame); - - copy_v3_v3(vtx_frame[idx], curr_vert->co); - - BLI_array_append(edge_frame, edge); - vso->disk_edges++; - } - } - - vso->edge_frame = edge_frame; - vso->vtx_frame = vtx_frame; - - /* Set the interp at starting vtx */ - copy_v3_v3(vso->interp, sel_vtx->co); - - return vso->disk_edges > 0; -} - -static int edbm_vertex_slide_modal(bContext *C, wmOperator *op, wmEvent *event) -{ - VertexSlideOp *vso = op->customdata; - char buff[128]; - - if (!vso) - return OPERATOR_CANCELLED; - - /* Notify the viewport */ - view3d_operator_needs_opengl(C); - - switch (event->type) { - case LEFTSHIFTKEY: - { - switch (event->val) { - case KM_PRESS: - vso->snap_to_mid = TRUE; - break; - case KM_RELEASE: - vso->snap_to_mid = FALSE; - break; - } - - break; - } - case LEFTCTRLKEY: - { - switch (event->val) { - case KM_PRESS: - vso->snap_n_merge = TRUE; - vso->snap_to_end_vtx = TRUE; - break; - case KM_RELEASE: - vso->snap_n_merge = FALSE; - vso->snap_to_end_vtx = FALSE; - break; - } - - break; - } - case LEFTALTKEY: - { - switch (event->val) { - case KM_PRESS: - vso->snap_to_end_vtx = TRUE; - break; - case KM_RELEASE: - vso->snap_to_end_vtx = FALSE; - break; - } - - break; - } - case RIGHTMOUSE: - case ESCKEY: - { - /* Enforce redraw */ - ED_region_tag_redraw(vso->active_region); - - /* Clean-up */ - vtx_slide_exit(C, op); - - return OPERATOR_CANCELLED; - } - case LEFTMOUSE: - { - if (event->val == KM_PRESS) { - /* Update mouse coords */ - copy_v2_v2_int(vso->m_co, event->mval); - - if (vso->slide_mode) { - vtx_slide_confirm(C, op); - /* Clean-up */ - vtx_slide_exit(C, op); - return OPERATOR_FINISHED; - } - else if (vso->sel_edge) { - vso->slide_mode = TRUE; - } - } - - ED_region_tag_redraw(vso->active_region); - break; - - } - case MOUSEMOVE: - { - sprintf(buff, "Vertex Slide: %f", vso->distance); - if (!vso->slide_mode) { - vtx_slide_find_edge(vso, event); - } - else { - vtx_slide_update(vso, event); - } - ED_area_headerprint(CTX_wm_area(C), buff); - ED_region_tag_redraw(vso->active_region); - break; - } - } - - return OPERATOR_RUNNING_MODAL; -} - -static int edbm_vertex_slide_cancel(bContext *C, wmOperator *op) -{ - /* Exit the modal */ - vtx_slide_exit(C, op); - - return OPERATOR_CANCELLED; -} - -static int edbm_vertex_slide_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) -{ - /* Initialize the operator */ - if (vtx_slide_init(C, op)) - return OPERATOR_RUNNING_MODAL; - else - return OPERATOR_CANCELLED; -} - -/* Vertex Slide */ -static int edbm_vertex_slide_exec_ex(bContext *C, wmOperator *op, const int do_update) -{ - Object *obedit = CTX_data_edit_object(C); - BMEditMesh *em = BMEdit_FromObject(obedit); - BMesh *bm = em->bm; - BMVert *start_vert; - BMOperator bmop; - BMEditSelection *ese = (BMEditSelection *)em->bm->selected.last; - - float factor = 0.0f; - - /* Invoked modally? */ - if (op->type->modal == edbm_vertex_slide_modal && op->customdata) { - VertexSlideOp *vso = (VertexSlideOp *)op->customdata; - - if (bm->totedgesel > 1) { - /* Reset selections */ - EDBM_flag_disable_all(em, BM_ELEM_SELECT); - BM_edge_select_set(bm, vso->sel_edge, TRUE); - BM_vert_select_set(bm, vso->start_vtx, TRUE); - - BM_select_history_store(em->bm, vso->sel_edge); - BM_select_history_store(em->bm, vso->start_vtx); - ese = (BMEditSelection *)em->bm->selected.last; - } - factor = vso->distance; - RNA_float_set(op->ptr, "factor", factor); - } - else { - /* Get Properties */ - factor = RNA_float_get(op->ptr, "factor"); - } - - /* Is there a starting vertex ? */ - if ((ese == NULL) || (ese->htype != BM_VERT && ese->htype != BM_EDGE)) { - BKE_report(op->reports, RPT_ERROR_INVALID_INPUT, "Vertex slide error: select a (single) vertex"); - return OPERATOR_CANCELLED; - } - - start_vert = (BMVert *)ese->ele; - - /* Prepare operator */ - if (!EDBM_op_init(em, &bmop, op, - "slide_vert vert=%e edges=%he factor=%f", - start_vert, BM_ELEM_SELECT, factor)) - { - return OPERATOR_CANCELLED; - } - /* Execute operator */ - BMO_op_exec(bm, &bmop); - - /* Deselect the input edges */ - BMO_slot_buffer_hflag_disable(bm, bmop.slots_in, "edges", BM_EDGE, BM_ELEM_SELECT, TRUE); - - /* Select the output vert */ - BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, TRUE); - - /* Flush the select buffers */ - EDBM_selectmode_flush(em); - - if (!EDBM_op_finish(em, &bmop, op, TRUE)) { - return OPERATOR_CANCELLED; - } - - if (do_update) { - /* Update Geometry */ - EDBM_update_generic(em, TRUE, FALSE); - } - - return OPERATOR_FINISHED; -} - -#if 0 -static int edbm_vertex_slide_exec(bContext *C, wmOperator *op) -{ - return edbm_vertex_slide_exec_ex(C, op, TRUE); -} -#endif - -void MESH_OT_vert_slide(wmOperatorType *ot) -{ - PropertyRNA *prop; - - /* identifiers */ - ot->name = "Vertex Slide"; - ot->idname = "MESH_OT_vert_slide"; - ot->description = "Vertex slide"; - - /* api callback */ - ot->invoke = edbm_vertex_slide_invoke; - ot->modal = edbm_vertex_slide_modal; - ot->cancel = edbm_vertex_slide_cancel; - ot->poll = ED_operator_editmesh_region_view3d; - - /* ot->exec = edbm_vertex_slide_exec; - * ot->poll = ED_operator_editmesh; */ - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* Properties for vertex slide */ - prop = RNA_def_float(ot->srna, "factor", 0.0f, -FLT_MAX, FLT_MAX, "Distance", "Distance", -5.0f, 5.0f); - RNA_def_property_ui_range(prop, -5.0f, 5.0f, 0.1, 4); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); -} diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 27c68ce21bc..b411cd2bd27 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -387,7 +387,7 @@ static short edbm_extrude_edge(Object *obedit, BMEditMesh *em, const char hflag, if (ele->head.htype == BM_FACE) { f = (BMFace *)ele; add_normal_aligned(nor, f->no); - }; + } } normalize_v3(nor); @@ -3190,8 +3190,7 @@ static int mesh_separate_loose(Main *bmain, Scene *scene, Base *base_old, BMesh BMW_FLAG_NOP, BMW_NIL_LAY); - e = BMW_begin(&walker, v_seed); - for (; e; e = BMW_step(&walker)) { + for (e = BMW_begin(&walker, v_seed); e; e = BMW_step(&walker)) { if (!BM_elem_flag_test(e->v1, BM_ELEM_TAG)) { BM_elem_flag_enable(e->v1, BM_ELEM_TAG); tot++; } if (!BM_elem_flag_test(e->v2, BM_ELEM_TAG)) { BM_elem_flag_enable(e->v2, BM_ELEM_TAG); tot++; } } @@ -3838,6 +3837,9 @@ static int edbm_select_face_by_sides_exec(bContext *C, wmOperator *op) const int numverts = RNA_int_get(op->ptr, "number"); const int type = RNA_enum_get(op->ptr, "type"); + if (!RNA_boolean_get(op->ptr, "extend")) + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { int select; @@ -3897,9 +3899,10 @@ void MESH_OT_select_face_by_sides(wmOperatorType *ot) /* properties */ RNA_def_int(ot->srna, "number", 4, 3, INT_MAX, "Number of Vertices", "", 3, INT_MAX); RNA_def_enum(ot->srna, "type", type_items, 1, "Type", "Type of comparison to make"); + RNA_def_boolean(ot->srna, "extend", TRUE, "Extend", "Extend the selection"); } -static int edbm_select_loose_verts_exec(bContext *C, wmOperator *UNUSED(op)) +static int edbm_select_loose_verts_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); @@ -3907,6 +3910,9 @@ static int edbm_select_loose_verts_exec(bContext *C, wmOperator *UNUSED(op)) BMEdge *eed; BMIter iter; + if (!RNA_boolean_get(op->ptr, "extend")) + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (!eve->e) { BM_vert_select_set(em->bm, eve, TRUE); @@ -3938,6 +3944,9 @@ void MESH_OT_select_loose_verts(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* props */ + RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection"); } static int edbm_select_mirror_exec(bContext *C, wmOperator *op) @@ -4593,7 +4602,7 @@ static int edbm_noise_exec(bContext *C, wmOperator *op) BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { float tin, dum; - externtex(ma->mtex[0], eve->co, &tin, &dum, &dum, &dum, &dum, 0); + externtex(ma->mtex[0], eve->co, &tin, &dum, &dum, &dum, &dum, 0, NULL); eve->co[2] += fac * tin; } } diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index b95c8a05353..d62eba9728c 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -682,8 +682,10 @@ void undo_push_mesh(bContext *C, const char *name) undo_editmode_push(C, name, getEditMesh, free_undo, undoMesh_to_editbtMesh, editbtMesh_to_undoMesh, NULL); } -/* write comment here */ -UvVertMap *EDBM_uv_vert_map_create(BMEditMesh *em, int selected, const float limit[2]) +/** + * Return a new UVVertMap from the editmesh + */ +UvVertMap *EDBM_uv_vert_map_create(BMEditMesh *em, bool use_select, const float limit[2]) { BMVert *ev; BMFace *efa; @@ -696,6 +698,7 @@ UvVertMap *EDBM_uv_vert_map_create(BMEditMesh *em, int selected, const float lim MLoopUV *luv; unsigned int a; int totverts, i, totuv; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE); @@ -704,8 +707,9 @@ UvVertMap *EDBM_uv_vert_map_create(BMEditMesh *em, int selected, const float lim /* generate UvMapVert array */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!selected || ((!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) && BM_elem_flag_test(efa, BM_ELEM_SELECT))) + if ((use_select == false) || BM_elem_flag_test(efa, BM_ELEM_SELECT)) { totuv += efa->len; + } } if (totuv == 0) { @@ -726,7 +730,7 @@ UvVertMap *EDBM_uv_vert_map_create(BMEditMesh *em, int selected, const float lim a = 0; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!selected || ((!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) && BM_elem_flag_test(efa, BM_ELEM_SELECT))) { + if ((use_select == false) || BM_elem_flag_test(efa, BM_ELEM_SELECT)) { i = 0; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { buf->tfindex = i; @@ -761,7 +765,7 @@ UvVertMap *EDBM_uv_vert_map_create(BMEditMesh *em, int selected, const float lim /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */ l = BM_iter_at_index(em->bm, BM_LOOPS_OF_FACE, efa, v->tfindex); - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); uv = luv->uv; lastv = NULL; @@ -773,7 +777,7 @@ UvVertMap *EDBM_uv_vert_map_create(BMEditMesh *em, int selected, const float lim /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */ l = BM_iter_at_index(em->bm, BM_LOOPS_OF_FACE, efa, iterv->tfindex); - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); uv2 = luv->uv; sub_v2_v2v2(uvdiff, uv2, uv); @@ -831,6 +835,8 @@ UvElementMap *EDBM_uv_element_map_create(BMEditMesh *em, int selected, int do_is BMFace **stack; int stacksize = 0; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE); totverts = em->bm->totvert; @@ -843,8 +849,9 @@ UvElementMap *EDBM_uv_element_map_create(BMEditMesh *em, int selected, int do_is /* generate UvElement array */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!selected || ((!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) && BM_elem_flag_test(efa, BM_ELEM_SELECT))) + if (!selected || BM_elem_flag_test(efa, BM_ELEM_SELECT)) { totuv += efa->len; + } } if (totuv == 0) { @@ -869,7 +876,7 @@ UvElementMap *EDBM_uv_element_map_create(BMEditMesh *em, int selected, int do_is j = 0; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { island_number[j++] = INVALID_ISLAND; - if (!selected || ((!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) && BM_elem_flag_test(efa, BM_ELEM_SELECT))) { + if (!selected || BM_elem_flag_test(efa, BM_ELEM_SELECT)) { BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { buf->l = l; buf->separate = 0; @@ -898,7 +905,7 @@ UvElementMap *EDBM_uv_element_map_create(BMEditMesh *em, int selected, int do_is newvlist = v; l = v->l; - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); uv = luv->uv; lastv = NULL; @@ -908,7 +915,7 @@ UvElementMap *EDBM_uv_element_map_create(BMEditMesh *em, int selected, int do_is next = iterv->next; l = iterv->l; - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); uv2 = luv->uv; sub_v2_v2v2(uvdiff, uv2, uv); @@ -1339,7 +1346,7 @@ void EDBM_mesh_reveal(BMEditMesh *em) /* so many tools call these that we better make it a generic function. */ -void EDBM_update_generic(BMEditMesh *em, const short do_tessface, const short is_destructive) +void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_destructive) { Object *ob = em->ob; /* order of calling isn't important */ diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 790a7eae487..fe4917acdac 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -216,7 +216,6 @@ void MESH_OT_bevel(struct wmOperatorType *ot); void MESH_OT_bridge_edge_loops(struct wmOperatorType *ot); void MESH_OT_inset(struct wmOperatorType *ot); void MESH_OT_wireframe(struct wmOperatorType *ot); -void MESH_OT_vert_slide(struct wmOperatorType *ot); void MESH_OT_convex_hull(struct wmOperatorType *ot); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 372d6feec0c..9403299b0cd 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -154,7 +154,6 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_solidify); WM_operatortype_append(MESH_OT_select_nth); WM_operatortype_append(MESH_OT_vert_connect); - WM_operatortype_append(MESH_OT_vert_slide); WM_operatortype_append(MESH_OT_knife_tool); WM_operatortype_append(MESH_OT_bevel); @@ -269,10 +268,14 @@ void ED_keymap_mesh(wmKeyConfig *keyconf) keymap = WM_keymap_find(keyconf, "Mesh", 0, 0); keymap->poll = ED_operator_editmesh; - WM_keymap_add_item(keymap, "MESH_OT_loopcut_slide", RKEY, KM_PRESS, KM_CTRL, 0); - WM_keymap_add_item(keymap, "MESH_OT_bevel", BKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "MESH_OT_loopcut_slide", RKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "MESH_OT_inset", IKEY, KM_PRESS, 0, 0); + kmi = WM_keymap_add_item(keymap, "MESH_OT_bevel", BKEY, KM_PRESS, KM_CTRL, 0); + RNA_boolean_set(kmi->ptr, "vertex_only", FALSE); + kmi = WM_keymap_add_item(keymap, "MESH_OT_bevel", BKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "vertex_only", TRUE); + /* selecting */ /* standard mouse selection goes via space_view3d */ kmi = WM_keymap_add_item(keymap, "MESH_OT_loop_select", SELECTMOUSE, KM_PRESS, KM_ALT, 0); @@ -366,7 +369,7 @@ void ED_keymap_mesh(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "MESH_OT_vert_connect", JKEY, KM_PRESS, 0, 0); /* Vertex Slide */ - WM_keymap_add_item(keymap, "MESH_OT_vert_slide", VKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "TRANSFORM_OT_vert_slide", VKEY, KM_PRESS, KM_SHIFT, 0); /* use KM_CLICK because same key is used for tweaks */ kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0); RNA_boolean_set(kmi->ptr, "rotate_source", TRUE); diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 4db416b6f72..8457b278c6c 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -941,7 +941,7 @@ static void object_delete_check_glsl_update(Object *ob) void ED_base_object_free_and_unlink(Main *bmain, Scene *scene, Base *base) { DAG_id_type_tag(bmain, ID_OB); - BLI_remlink(&scene->base, base); + BKE_scene_base_unlink(scene, base); object_delete_check_glsl_update(base->object); BKE_libblock_free_us(&bmain->object, base->object); if (scene->basact == base) scene->basact = NULL; @@ -1698,7 +1698,11 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base BLI_addhead(&scene->base, basen); /* addhead: prevent eternal loop */ basen->object = obn; - if (basen->flag & OB_FROMGROUP) { + /* 1) duplis should end up in same group as the original + * 2) Rigid Body sim participants MUST always be part of a group... + */ + // XXX: is 2) really a good measure here? + if ((basen->flag & OB_FROMGROUP) || ob->rigidbody_object || ob->rigidbody_constraint) { Group *group; for (group = bmain->group.first; group; group = group->id.next) { if (object_in_group(ob, group)) diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index f36c6d79783..322ba99593e 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -610,7 +610,12 @@ static void finish_bake_internal(BakeRender *bkr) /* freed when baking is done, but if its canceled we need to free here */ if (ibuf) { if (ibuf->userdata) { - MEM_freeN(ibuf->userdata); + BakeImBufuserData *userdata = (BakeImBufuserData *) ibuf->userdata; + if (userdata->mask_buffer) + MEM_freeN(userdata->mask_buffer); + if (userdata->displacement_buffer) + MEM_freeN(userdata->displacement_buffer); + MEM_freeN(userdata); ibuf->userdata = NULL; } } diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index fcc3b5d012e..5e5e38c3e43 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -376,7 +376,7 @@ void ED_object_exit_editmode(bContext *C, int flag) scene->obedit = NULL; // XXX for context /* flag object caches as outdated */ - BKE_ptcache_ids_from_object(&pidlist, obedit, NULL, 0); + BKE_ptcache_ids_from_object(&pidlist, obedit, scene, 0); for (pid = pidlist.first; pid; pid = pid->next) { if (pid->type != PTCACHE_TYPE_PARTICLES) /* particles don't need reset on geometry change */ pid->cache->flag |= PTCACHE_OUTDATED; diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 03b50c05071..5c65e543cc9 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -394,6 +394,12 @@ void ED_keymap_object(wmKeyConfig *keyconf) WM_keymap_verify_item(keymap, "GROUP_OT_objects_remove_all", GKEY, KM_PRESS, KM_SHIFT | KM_CTRL | KM_ALT, 0); WM_keymap_verify_item(keymap, "GROUP_OT_objects_add_active", GKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0); WM_keymap_verify_item(keymap, "GROUP_OT_objects_remove_active", GKEY, KM_PRESS, KM_SHIFT | KM_ALT, 0); + + kmi = WM_keymap_add_item(keymap, "RIGIDBODY_OT_objects_add", RKEY, KM_PRESS, KM_CTRL, 0); + RNA_enum_set(kmi->ptr, "type", 0); /* active */ + kmi = WM_keymap_add_item(keymap, "RIGIDBODY_OT_objects_add", RKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0); + RNA_enum_set(kmi->ptr, "type", 1); /* passive */ + kmi = WM_keymap_add_item(keymap, "RIGIDBODY_OT_objects_remove", RKEY, KM_PRESS, KM_CTRL | KM_ALT, 0); WM_keymap_add_menu(keymap, "VIEW3D_MT_object_specials", WKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index fa44d3d7fb4..9749494bc66 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -354,7 +354,7 @@ static int make_proxy_exec(bContext *C, wmOperator *op) /* remove base, leave user count of object, it gets linked in BKE_object_make_proxy */ if (gob == NULL) { - BLI_remlink(&scene->base, oldbase); + BKE_scene_base_unlink(scene, oldbase); MEM_freeN(oldbase); } diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index e7c619acb67..a1fb0eb98d2 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -82,6 +82,7 @@ static void vgroup_remap_update_users(Object *ob, int *map); static void vgroup_delete_edit_mode(Object *ob, bDeformGroup *defgroup); static void vgroup_delete_object_mode(Object *ob, bDeformGroup *dg); static void vgroup_delete_all(Object *ob); +static int ED_vgroup_give_parray(ID *id, MDeformVert ***dvert_arr, int *dvert_tot, const short use_vert_sel); static int vertex_group_use_vert_sel(Object *ob) { @@ -183,6 +184,29 @@ int ED_vgroup_data_create(ID *id) } } +/** + * Removes out of range MDeformWeights + */ +void ED_vgroup_data_clamp_range(ID *id, const int total) +{ + MDeformVert **dvert_arr; + int dvert_tot; + + if (ED_vgroup_give_parray(id, &dvert_arr, &dvert_tot, false)) { + int i; + for (i = 0; i < dvert_tot; i++) { + MDeformVert *dv = dvert_arr[i]; + int j; + for (j = 0; j < dv->totweight; j++) { + if (dv->dw[j].def_nr >= total) { + defvert_remove_group(dv, &dv->dw[j]); + j--; + } + } + } + } +} + static int ED_vgroup_give_parray(ID *id, MDeformVert ***dvert_arr, int *dvert_tot, const short use_vert_sel) { *dvert_tot = 0; @@ -2725,7 +2749,7 @@ void OBJECT_OT_vertex_group_remove_from(wmOperatorType *ot) /* identifiers */ ot->name = "Remove from Vertex Group"; ot->idname = "OBJECT_OT_vertex_group_remove_from"; - ot->description = "Remove the selected vertices from the active vertex group"; + ot->description = "Remove the selected vertices from active or all vertex group(s)"; /* api callbacks */ ot->poll = vertex_group_poll_edit_or_wpaint_vert_select; diff --git a/source/blender/editors/physics/CMakeLists.txt b/source/blender/editors/physics/CMakeLists.txt index da12a26e747..435327319aa 100644 --- a/source/blender/editors/physics/CMakeLists.txt +++ b/source/blender/editors/physics/CMakeLists.txt @@ -43,6 +43,9 @@ set(SRC physics_fluid.c physics_ops.c physics_pointcache.c + rigidbody_constraint.c + rigidbody_object.c + rigidbody_world.c physics_intern.h ) @@ -59,4 +62,11 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() +if(WITH_BULLET) + list(APPEND INC + ../../rigidbody + ) + add_definitions(-DWITH_BULLET) +endif() + blender_add_lib(bf_editor_physics "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/physics/SConscript b/source/blender/editors/physics/SConscript index 293f7769a6a..b68cc944925 100644 --- a/source/blender/editors/physics/SConscript +++ b/source/blender/editors/physics/SConscript @@ -33,6 +33,7 @@ incs = '../include ../../blenfont ../../blenlib ../../blenkernel ../../makesdna incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' incs += ' ../../gpu ../../blenloader ../../bmesh' incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern' +incs += ' ../../rigidbody' defs = [] diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 9dbc0f9a10c..deddc649956 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -2004,7 +2004,7 @@ static int rekey_exec(bContext *C, wmOperator *op) PE_set_data(C, &data); data.dval= 1.0f / (float)(data.totrekey-1); - data.totrekey= RNA_int_get(op->ptr, "keys"); + data.totrekey= RNA_int_get(op->ptr, "keys_number"); foreach_selected_point(&data, rekey_particle); @@ -2031,7 +2031,7 @@ void PARTICLE_OT_rekey(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; /* properties */ - RNA_def_int(ot->srna, "keys", 2, 2, INT_MAX, "Number of Keys", "", 2, 100); + RNA_def_int(ot->srna, "keys_number", 2, 2, INT_MAX, "Number of Keys", "", 2, 100); } static void rekey_particle_to_time(Scene *scene, Object *ob, int pa_index, float path_time) @@ -3254,7 +3254,7 @@ static int brush_add(PEData *data, short number) ParticleEditSettings *pset= PE_settings(scene); int i, k, n= 0, totpart= psys->totpart; float mco[2]; - short dmx= 0, dmy= 0; + float dmx, dmy; float co1[3], co2[3], min_d, imat[4][4]; float framestep, timestep; short size= pset->brush[PE_BRUSH_ADD].size; @@ -3282,12 +3282,19 @@ static int brush_add(PEData *data, short number) for (i=0; i<number; i++) { if (number>1) { - dmx=dmy=size; - while (dmx*dmx+dmy*dmy>size2) { - dmx=(short)((2.0f*BLI_frand()-1.0f)*size); - dmy=(short)((2.0f*BLI_frand()-1.0f)*size); + dmx = size; + dmy = size; + + /* rejection sampling to get points in circle */ + while (dmx*dmx + dmy*dmy > size2) { + dmx= (2.0f*BLI_frand() - 1.0f)*size; + dmy= (2.0f*BLI_frand() - 1.0f)*size; } } + else { + dmx = 0.0f; + dmy = 0.0f; + } mco[0] = data->mval[0] + dmx; mco[1] = data->mval[1] + dmy; @@ -3307,8 +3314,8 @@ static int brush_add(PEData *data, short number) int newtotpart=totpart+n; float hairmat[4][4], cur_co[3]; KDTree *tree=0; - ParticleData *pa, *new_pars= MEM_callocN(newtotpart*sizeof(ParticleData), "ParticleData new"); - PTCacheEditPoint *point, *new_points= MEM_callocN(newtotpart*sizeof(PTCacheEditPoint), "PTCacheEditPoint array new"); + ParticleData *pa, *new_pars = MEM_callocN(newtotpart*sizeof(ParticleData), "ParticleData new"); + PTCacheEditPoint *point, *new_points = MEM_callocN(newtotpart*sizeof(PTCacheEditPoint), "PTCacheEditPoint array new"); PTCacheEditKey *key; HairKey *hkey; @@ -3343,8 +3350,8 @@ static int brush_add(PEData *data, short number) edit->totpoint= psys->totpart= newtotpart; /* create new elements */ - pa= psys->particles + totpart; - point= edit->points + totpart; + pa = psys->particles + totpart; + point = edit->points + totpart; for (i=totpart; i<newtotpart; i++, pa++, point++) { memcpy(pa, add_pars + i - totpart, sizeof(ParticleData)); @@ -3390,8 +3397,14 @@ static int brush_add(PEData *data, short number) weight[w] = 0.0f; } - for (w=0; w<maxw; w++) - weight[w] /= totw; + if(totw > 0.0f) { + for (w=0; w<maxw; w++) + weight[w] /= totw; + } + else { + for (w=0; w<maxw; w++) + weight[w] = 1.0f/maxw; + } ppa= psys->particles+ptn[0].index; @@ -3403,7 +3416,7 @@ static int brush_add(PEData *data, short number) psys_get_particle_on_path(&sim, ptn[0].index, key3, 0); mul_v3_fl(key3[0].co, weight[0]); - /* TODO: interpolatint the weight would be nicer */ + /* TODO: interpolating the weight would be nicer */ thkey->weight= (ppa->hair+MIN2(k, ppa->totkey-1))->weight; if (maxw>1) { @@ -4147,8 +4160,8 @@ int PE_minmax(Scene *scene, float min[3], float max[3]) /* initialize needed data for bake edit */ static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys) { - PTCacheEdit *edit= (psys)? psys->edit : cache->edit; - ParticleSystemModifierData *psmd= (psys)? psys_get_modifier(ob, psys): NULL; + PTCacheEdit *edit; + ParticleSystemModifierData *psmd = (psys) ? psys_get_modifier(ob, psys) : NULL; POINT_P; KEY_K; ParticleData *pa = NULL; HairKey *hkey; @@ -4164,6 +4177,8 @@ static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, if (psys == NULL && (cache && cache->mem_cache.first == NULL)) return; + edit = (psys) ? psys->edit : cache->edit; + if (!edit) { totpoint = psys ? psys->totpart : (int)((PTCacheMem *)cache->mem_cache.first)->totpoint; diff --git a/source/blender/editors/physics/physics_intern.h b/source/blender/editors/physics/physics_intern.h index 75779cf6102..77ce5a334e6 100644 --- a/source/blender/editors/physics/physics_intern.h +++ b/source/blender/editors/physics/physics_intern.h @@ -105,5 +105,23 @@ void PTCACHE_OT_bake_from_cache(struct wmOperatorType *ot); void PTCACHE_OT_add(struct wmOperatorType *ot); void PTCACHE_OT_remove(struct wmOperatorType *ot); -#endif /* __PHYSICS_INTERN_H__ */ +/* rigidbody_object.c */ +void RIGIDBODY_OT_object_add(struct wmOperatorType *ot); +void RIGIDBODY_OT_object_remove(struct wmOperatorType *ot); + +void RIGIDBODY_OT_objects_add(struct wmOperatorType *ot); +void RIGIDBODY_OT_objects_remove(struct wmOperatorType *ot); + +void RIGIDBODY_OT_shape_change(struct wmOperatorType *ot); +void RIGIDBODY_OT_mass_calculate(struct wmOperatorType *ot); +/* rigidbody_constraint.c */ +void RIGIDBODY_OT_constraint_add(struct wmOperatorType *ot); +void RIGIDBODY_OT_constraint_remove(struct wmOperatorType *ot); + +/*rigidbody_world.c */ +void RIGIDBODY_OT_world_add(struct wmOperatorType *ot); +void RIGIDBODY_OT_world_remove(struct wmOperatorType *ot); +void RIGIDBODY_OT_world_export(struct wmOperatorType *ot); + +#endif /* __PHYSICS_INTERN_H__ */ diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c index fb99d296a54..51a66886c6e 100644 --- a/source/blender/editors/physics/physics_ops.c +++ b/source/blender/editors/physics/physics_ops.c @@ -86,6 +86,22 @@ static void operatortypes_particle(void) WM_operatortype_append(PARTICLE_OT_dupliob_remove); WM_operatortype_append(PARTICLE_OT_dupliob_move_up); WM_operatortype_append(PARTICLE_OT_dupliob_move_down); + + WM_operatortype_append(RIGIDBODY_OT_object_add); + WM_operatortype_append(RIGIDBODY_OT_object_remove); + + WM_operatortype_append(RIGIDBODY_OT_objects_add); + WM_operatortype_append(RIGIDBODY_OT_objects_remove); + + WM_operatortype_append(RIGIDBODY_OT_shape_change); + WM_operatortype_append(RIGIDBODY_OT_mass_calculate); + + WM_operatortype_append(RIGIDBODY_OT_constraint_add); + WM_operatortype_append(RIGIDBODY_OT_constraint_remove); + + WM_operatortype_append(RIGIDBODY_OT_world_add); + WM_operatortype_append(RIGIDBODY_OT_world_remove); +// WM_operatortype_append(RIGIDBODY_OT_world_export); } static void keymap_particle(wmKeyConfig *keyconf) diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c new file mode 100644 index 00000000000..fac835a414a --- /dev/null +++ b/source/blender/editors/physics/rigidbody_constraint.c @@ -0,0 +1,202 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Sergej Reich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file rigidbody_constraint.c + * \ingroup editor_physics + * \brief Rigid Body constraint editing operators + */ + +#include <stdlib.h> +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_group_types.h" +#include "DNA_object_types.h" +#include "DNA_rigidbody_types.h" +#include "DNA_scene_types.h" + +#include "BLI_blenlib.h" +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_depsgraph.h" +#include "BKE_group.h" +#include "BKE_object.h" +#include "BKE_report.h" +#include "BKE_rigidbody.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_physics.h" +#include "ED_screen.h" + +#include "physics_intern.h" + +/* ********************************************** */ +/* Helper API's for RigidBody Constraint Editing */ + +static int ED_operator_rigidbody_con_active_poll(bContext *C) +{ + if (ED_operator_object_active_editable(C)) { + Object *ob = CTX_data_active_object(C); + return (ob && ob->rigidbody_constraint); + } + else + return 0; +} + + +void ED_rigidbody_con_add(wmOperator *op, Scene *scene, Object *ob, int type) +{ + RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene); + + /* check that object doesn't already have a constraint */ + if (ob->rigidbody_constraint) { + BKE_reportf(op->reports, RPT_INFO, "Object '%s' already has a Rigid Body Constraint", ob->id.name + 2); + return; + } + /* create constraint group if it doesn't already exits */ + if (rbw->constraints == NULL) { + rbw->constraints = add_group("RigidBodyConstraints"); + } + /* make rigidbody constraint settings */ + ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, type); + ob->rigidbody_constraint->flag |= RBC_FLAG_NEEDS_VALIDATE; + + /* add constraint to rigid body constraint group */ + add_to_group(rbw->constraints, ob, scene, NULL); +} + +void ED_rigidbody_con_remove(Scene *scene, Object *ob) +{ + RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene); + + BKE_rigidbody_remove_constraint(scene, ob); + if (rbw) + rem_from_group(rbw->constraints, ob, scene, NULL); + + DAG_id_tag_update(&ob->id, OB_RECALC_OB); +} + +/* ********************************************** */ +/* Active Object Add/Remove Operators */ + +/* ************ Add Rigid Body Constraint ************** */ + +static int rigidbody_con_add_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene); + Object *ob = (scene) ? OBACT : NULL; + int type = RNA_enum_get(op->ptr, "type"); + + /* sanity checks */ + if (ELEM(NULL, scene, rbw)) { + BKE_report(op->reports, RPT_ERROR, "No Rigid Body World to add Rigid Body Constraint to"); + return OPERATOR_CANCELLED; + } + /* apply to active object */ + ED_rigidbody_con_add(op, scene, ob, type); + + /* send updates */ + DAG_ids_flush_update(CTX_data_main(C), 0); + + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); + WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void RIGIDBODY_OT_constraint_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->idname = "RIGIDBODY_OT_constraint_add"; + ot->name = "Add Rigid Body Constraint"; + ot->description = "Add Rigid Body Constraint to active object"; + + /* callbacks */ + ot->exec = rigidbody_con_add_exec; + ot->poll = ED_operator_object_active_editable; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "type", rigidbody_con_type_items, RBC_TYPE_FIXED, "Rigid Body Constraint Type", ""); +} + +/* ************ Remove Rigid Body Constraint ************** */ + +static int rigidbody_con_remove_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Object *ob = (scene) ? OBACT : NULL; + + /* sanity checks */ + if (scene == NULL) + return OPERATOR_CANCELLED; + + /* apply to active object */ + if (ELEM(NULL, ob, ob->rigidbody_constraint)) { + BKE_report(op->reports, RPT_ERROR, "Object has no Rigid Body Constraint to remove"); + return OPERATOR_CANCELLED; + } + else { + ED_rigidbody_con_remove(scene, ob); + } + + /* send updates */ + DAG_ids_flush_update(CTX_data_main(C), 0); + + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); + WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void RIGIDBODY_OT_constraint_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->idname = "RIGIDBODY_OT_constraint_remove"; + ot->name = "Remove Rigid Body Constraint"; + ot->description = "Remove Rigid Body Constraint from Object"; + + /* callbacks */ + ot->exec = rigidbody_con_remove_exec; + ot->poll = ED_operator_rigidbody_con_active_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c new file mode 100644 index 00000000000..fc1e24840a4 --- /dev/null +++ b/source/blender/editors/physics/rigidbody_object.c @@ -0,0 +1,628 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joshua Leung, Sergej Reich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file rigidbody_object.c + * \ingroup editor_physics + * \brief Rigid Body object editing operators + */ + +#include <stdlib.h> +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_group_types.h" +#include "DNA_object_types.h" +#include "DNA_mesh_types.h" +#include "DNA_rigidbody_types.h" +#include "DNA_scene_types.h" + +#include "BLI_blenlib.h" +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_depsgraph.h" +#include "BKE_group.h" +#include "BKE_object.h" +#include "BKE_report.h" +#include "BKE_rigidbody.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_physics.h" +#include "ED_screen.h" + +#include "physics_intern.h" + +/* ********************************************** */ +/* Helper API's for RigidBody Objects Editing */ + +static int ED_operator_rigidbody_active_poll(bContext *C) +{ + if (ED_operator_object_active_editable(C)) { + Object *ob = CTX_data_active_object(C); + return (ob && ob->rigidbody_object); + } + else + return 0; +} + +static int ED_operator_rigidbody_add_poll(bContext *C) +{ + if (ED_operator_object_active_editable(C)) { + Object *ob = CTX_data_active_object(C); + return (ob && ob->type == OB_MESH); + } + else + return 0; +} + +/* ----------------- */ + +void ED_rigidbody_ob_add(wmOperator *op, Scene *scene, Object *ob, int type) +{ + RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene); + + /* check that object doesn't already belong to the current simulation */ + if (ob->rigidbody_object) { + BKE_reportf(op->reports, RPT_INFO, "Object '%s' already has a Rigid Body", ob->id.name + 2); + return; + } + if (ob->type != OB_MESH) { + BKE_report(op->reports, RPT_ERROR, "Can't add Rigid Body to non mesh object"); + return; + } + if (((Mesh *)ob->data)->totpoly == 0) { + BKE_report(op->reports, RPT_ERROR, "Can't create Rigid Body from mesh with no polygons"); + return; + } + + /* Add rigid body world and group if they don't exist for convenience */ + if (rbw == NULL) { + rbw = BKE_rigidbody_create_world(scene); + BKE_rigidbody_validate_sim_world(scene, rbw, false); + scene->rigidbody_world = rbw; + } + if (rbw->group == NULL) { + rbw->group = add_group("RigidBodyWorld"); + } + + /* make rigidbody object settings */ + ob->rigidbody_object = BKE_rigidbody_create_object(scene, ob, type); + ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_VALIDATE; + + /* add object to rigid body group */ + add_to_group(rbw->group, ob, scene, NULL); +} + +void ED_rigidbody_ob_remove(Scene *scene, Object *ob) +{ + RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene); + + BKE_rigidbody_remove_object(scene, ob); + if (rbw) + rem_from_group(rbw->group, ob, scene, NULL); + + DAG_id_tag_update(&ob->id, OB_RECALC_OB); +} + +/* ********************************************** */ +/* Active Object Add/Remove Operators */ + +/* ************ Add Rigid Body ************** */ + +static int rigidbody_ob_add_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Object *ob = (scene) ? OBACT : NULL; + int type = RNA_enum_get(op->ptr, "type"); + + /* apply to active object */ + ED_rigidbody_ob_add(op, scene, ob, type); + + /* send updates */ + DAG_ids_flush_update(CTX_data_main(C), 0); + + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); + WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void RIGIDBODY_OT_object_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->idname = "RIGIDBODY_OT_object_add"; + ot->name = "Add Rigid Body"; + ot->description = "Add active object as Rigid Body"; + + /* callbacks */ + ot->exec = rigidbody_ob_add_exec; + ot->poll = ED_operator_rigidbody_add_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "type", rigidbody_ob_type_items, RBO_TYPE_ACTIVE, "Rigid Body Type", ""); +} + +/* ************ Remove Rigid Body ************** */ + +static int rigidbody_ob_remove_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + Object *ob = (scene) ? OBACT : NULL; + + /* sanity checks */ + if (scene == NULL) + return OPERATOR_CANCELLED; + + /* apply to active object */ + if (ELEM(NULL, ob, ob->rigidbody_object)) { + BKE_report(op->reports, RPT_ERROR, "Object has no Rigid Body settings to remove"); + return OPERATOR_CANCELLED; + } + else + ED_rigidbody_ob_remove(scene, ob); + + /* send updates */ + DAG_ids_flush_update(CTX_data_main(C), 0); + + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); + WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void RIGIDBODY_OT_object_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->idname = "RIGIDBODY_OT_object_remove"; + ot->name = "Remove Rigid Body"; + ot->description = "Remove Rigid Body settings from Object"; + + /* callbacks */ + ot->exec = rigidbody_ob_remove_exec; + ot->poll = ED_operator_rigidbody_active_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* ********************************************** */ +/* Selected Object Add/Remove Operators */ + +/* ************ Add Rigid Bodies ************** */ + +static int rigidbody_obs_add_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + int type = RNA_enum_get(op->ptr, "type"); + + /* sanity check */ + if (scene == NULL) { + BKE_report(op->reports, RPT_ERROR, "No Scene to add Rigid Bodies to"); + return OPERATOR_CANCELLED; + } + /* create rigid body objects and add them to the world's group */ + CTX_DATA_BEGIN(C, Object *, ob, selected_objects) { + ED_rigidbody_ob_add(op, scene, ob, type); + } + CTX_DATA_END; + + /* send updates */ + DAG_ids_flush_update(CTX_data_main(C), 0); + + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); + WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void RIGIDBODY_OT_objects_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->idname = "RIGIDBODY_OT_objects_add"; + ot->name = "Add Rigid Bodies"; + ot->description = "Add selected objects as Rigid Bodies"; + + /* callbacks */ + ot->exec = rigidbody_obs_add_exec; + ot->poll = ED_operator_rigidbody_add_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "type", rigidbody_ob_type_items, RBO_TYPE_ACTIVE, "Rigid Body Type", ""); +} + +/* ************ Remove Rigid Bodies ************** */ + +static int rigidbody_obs_remove_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + + /* sanity checks */ + if (scene == NULL) + return OPERATOR_CANCELLED; + + /* apply this to all selected objects... */ + CTX_DATA_BEGIN(C, Object *, ob, selected_objects) + { + if (ob->rigidbody_object) { + ED_rigidbody_ob_remove(scene, ob); + } + } + CTX_DATA_END; + + /* send updates */ + DAG_ids_flush_update(CTX_data_main(C), 0); + + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); + WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void RIGIDBODY_OT_objects_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->idname = "RIGIDBODY_OT_objects_remove"; + ot->name = "Remove Rigid Bodies"; + ot->description = "Remove selected objects from Rigid Body simulation"; + + /* callbacks */ + ot->exec = rigidbody_obs_remove_exec; + ot->poll = ED_operator_rigidbody_active_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* ********************************************** */ +/* Utility Operators */ + +/* ************ Change Collision Shapes ************** */ + +static int rigidbody_obs_shape_change_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + int shape = RNA_enum_get(op->ptr, "type"); + + /* sanity checks */ + if (scene == NULL) + return OPERATOR_CANCELLED; + + /* apply this to all selected objects... */ + CTX_DATA_BEGIN(C, Object *, ob, selected_objects) + { + if (ob->rigidbody_object) { + PointerRNA ptr; + + /* use RNA-system to change the property and perform all necessary changes */ + RNA_pointer_create(&ob->id, &RNA_RigidBodyObject, ob->rigidbody_object, &ptr); + RNA_enum_set(&ptr, "collision_shape", shape); + } + } + CTX_DATA_END; + + /* send updates */ + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); // XXX: wrong notifiers for now, but these also do the job... + + /* done */ + return OPERATOR_FINISHED; +} + +void RIGIDBODY_OT_shape_change(wmOperatorType *ot) +{ + /* identifiers */ + ot->idname = "RIGIDBODY_OT_shape_change"; + ot->name = "Change Collision Shape"; + ot->description = "Change collision shapes for selected Rigid Body Objects"; + + /* callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = rigidbody_obs_shape_change_exec; + ot->poll = ED_operator_rigidbody_active_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "type", rigidbody_ob_shape_items, RB_SHAPE_TRIMESH, "Rigid Body Shape", ""); +} + +/* ************ Calculate Mass ************** */ + +/* Entry in material density table */ +typedef struct rbMaterialDensityItem { + const char *name; /* Name of material */ + float density; /* Density (kg/m^3) */ +} rbMaterialDensityItem; + +/* Preset density values for materials (kg/m^3) + * Selected values obtained from: + * 1) http://www.jaredzone.info/2010/09/densities.html + * 2) http://www.avlandesign.com/density_construction.htm + * 3) http://www.avlandesign.com/density_metal.htm + */ +static rbMaterialDensityItem RB_MATERIAL_DENSITY_TABLE[] = { + {"Air", 1.0f}, /* not quite; adapted from 1.43 for oxygen for use as default */ + {"Acrylic", 1400.0f}, + {"Asphalt (Crushed)", 721.0f}, + {"Bark", 240.0f}, + {"Beans (Cocoa)", 593.0f}, + {"Beans (Soy)", 721.0f}, + {"Brick (Pressed)", 2400.0f}, + {"Brick (Common)", 2000.0f}, + {"Brick (Soft)", 1600.0f}, + {"Brass", 8216.0f}, + {"Bronze", 8860.0f}, + {"Carbon (Solid)", 2146.0f}, + {"Cardboard", 689.0f}, + {"Cast Iron", 7150.0f}, + //{"Cement", 1442.0f}, + {"Chalk (Solid)", 2499.0f}, + //{"Coffee (Fresh/Roast)", ~500}, + {"Concrete", 2320.0f}, + {"Charcoal", 208.0f}, + {"Cork", 240.0f}, + {"Copper", 8933.0f}, + {"Garbage", 481.0f}, + {"Glass (Broken)", 1940.0f}, + {"Glass (Solid)", 2190.0f}, + {"Gold", 19282.0f}, + {"Granite (Broken)", 1650.0f}, + {"Granite (Solid)", 2691.0f}, + {"Gravel", 2780.0f}, + {"Ice (Crushed)", 593.0f}, + {"Ice (Solid)", 919.0f}, + {"Iron", 7874.0f}, + {"Lead", 11342.0f}, + {"Limestone (Broken)", 1554.0f}, + {"Limestone (Solid)", 2611.0f}, + {"Marble (Broken)", 1570.0f}, + {"Marble (Solid)", 2563.0f}, + {"Paper", 1201.0f}, + {"Peanuts (Shelled)", 641.0f}, + {"Peanuts (Not Shelled)", 272.0f}, + {"Plaster", 849.0f}, + {"Plastic", 1200.0f}, + {"Polystyrene", 1050.0f}, + {"Rubber", 1522.0f}, + {"Silver", 10501.0f}, + {"Steel", 7860.0f}, + {"Stone", 2515.0f}, + {"Stone (Crushed)", 1602.0f}, + {"Timber", 610.0f} +}; +static const int NUM_RB_MATERIAL_PRESETS = sizeof(RB_MATERIAL_DENSITY_TABLE) / sizeof(rbMaterialDensityItem); + + +/* dynamically generate list of items + * - Although there is a runtime cost, this has a lower maintenance cost + * in the long run than other two-list solutions... + */ +static EnumPropertyItem *rigidbody_materials_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free) +{ + EnumPropertyItem item_tmp = {0}; + EnumPropertyItem *item = NULL; + int totitem = 0; + int i = 0; + + /* add each preset to the list */ + for (i = 0; i < NUM_RB_MATERIAL_PRESETS; i++) { + rbMaterialDensityItem *preset = &RB_MATERIAL_DENSITY_TABLE[i]; + + item_tmp.identifier = item_tmp.name = preset->name; + item_tmp.value = i; + RNA_enum_item_add(&item, &totitem, &item_tmp); + } + + /* add special "custom" entry to the end of the list */ + { + item_tmp.identifier = item_tmp.name = "Custom"; + item_tmp.value = -1; + RNA_enum_item_add(&item, &totitem, &item_tmp); + } + + RNA_enum_item_end(&item, &totitem); + *free = 1; + + return item; +} + +/* ------------------------------------------ */ + +/* helper function to calculate volume of rigidbody object */ +// TODO: allow a parameter to specify method used to calculate this? +static float calc_rigidbody_ob_volume(Object *ob) +{ + RigidBodyOb *rbo = ob->rigidbody_object; + + float size[3] = {1.0f, 1.0f, 1.0f}; + float radius = 1.0f; + float height = 1.0f; + + float volume = 0.0f; + + /* if automatically determining dimensions, use the Object's boundbox + * - assume that all quadrics are standing upright on local z-axis + * - assume even distribution of mass around the Object's pivot + * (i.e. Object pivot is centralised in boundbox) + * - boundbox gives full width + */ + // XXX: all dimensions are auto-determined now... later can add stored settings for this + BKE_object_dimensions_get(ob, size); + + if (ELEM3(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) { + /* take radius as largest x/y dimension, and height as z-dimension */ + radius = MAX2(size[0], size[1]) * 0.5f; + height = size[2]; + } + else if (rbo->shape == RB_SHAPE_SPHERE) { + /* take radius to the the largest dimension to try and encompass everything */ + radius = max_fff(size[0], size[1], size[2]) * 0.5f; + } + + /* calculate volume as appropriate */ + switch (rbo->shape) { + case RB_SHAPE_BOX: + volume = size[0] * size[1] * size[2]; + break; + + case RB_SHAPE_SPHERE: + volume = 4.0f / 3.0f * (float)M_PI * radius * radius * radius; + break; + + /* for now, assume that capsule is close enough to a cylinder... */ + case RB_SHAPE_CAPSULE: + case RB_SHAPE_CYLINDER: + volume = (float)M_PI * radius * radius * height; + break; + + case RB_SHAPE_CONE: + volume = (float)M_PI / 3.0f * radius * radius * height; + break; + + /* for now, all mesh shapes are just treated as boxes... + * NOTE: this may overestimate the volume, but other methods are overkill + */ + case RB_SHAPE_CONVEXH: + case RB_SHAPE_TRIMESH: + volume = size[0] * size[1] * size[2]; + break; + +#if 0 // XXX: not defined yet + case RB_SHAPE_COMPOUND: + volume = 0.0f; + break; +#endif + } + + /* return the volume calculated */ + return volume; +} + +/* ------------------------------------------ */ + +static int rigidbody_obs_calc_mass_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + int material = RNA_enum_get(op->ptr, "material"); + float density; + + /* sanity checks */ + if (scene == NULL) + return OPERATOR_CANCELLED; + + /* get density (kg/m^3) to apply */ + if (material >= 0) { + /* get density from table, and store in props for later repeating */ + if (material >= NUM_RB_MATERIAL_PRESETS) + material = 0; + + density = RB_MATERIAL_DENSITY_TABLE[material].density; + RNA_float_set(op->ptr, "density", density); + } + else { + /* custom - grab from whatever value is set */ + density = RNA_float_get(op->ptr, "density"); + } + + /* apply this to all selected objects (with rigidbodies)... */ + CTX_DATA_BEGIN(C, Object *, ob, selected_objects) + { + if (ob->rigidbody_object) { + PointerRNA ptr; + + float volume; /* m^3 */ + float mass; /* kg */ + + /* mass is calculated from the approximate volume of the object, + * and the density of the material we're simulating + */ + volume = calc_rigidbody_ob_volume(ob); + mass = volume * density; + + /* use RNA-system to change the property and perform all necessary changes */ + RNA_pointer_create(&ob->id, &RNA_RigidBodyObject, ob->rigidbody_object, &ptr); + RNA_float_set(&ptr, "mass", mass); + } + } + CTX_DATA_END; + + /* send updates */ + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); // XXX: wrong notifiers for now, but these also do the job... + + /* done */ + return OPERATOR_FINISHED; +} + +void RIGIDBODY_OT_mass_calculate(wmOperatorType *ot) +{ + PropertyRNA *prop; + + /* identifiers */ + ot->idname = "RIGIDBODY_OT_mass_calculate"; + ot->name = "Calculate Mass"; + ot->description = "Automatically calculate mass values for Rigid Body Objects based on volume"; + + /* callbacks */ + ot->invoke = WM_menu_invoke; // XXX + ot->exec = rigidbody_obs_calc_mass_exec; + ot->poll = ED_operator_rigidbody_active_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = prop = RNA_def_enum(ot->srna, "material", + DummyRNA_DEFAULT_items, 0, + "Material Preset", + "Type of material that objects are made of. " + "Determines material density"); + RNA_def_enum_funcs(prop, rigidbody_materials_itemf); + + RNA_def_float(ot->srna, "density", 1.0, FLT_MIN, FLT_MAX, + "Density", + "Custom density value (kg/m^3) to use instead of material preset", + 1.0f, 2500.0f); +} + +/* ********************************************** */ diff --git a/source/blender/editors/physics/rigidbody_world.c b/source/blender/editors/physics/rigidbody_world.c new file mode 100644 index 00000000000..5ab8e7697c5 --- /dev/null +++ b/source/blender/editors/physics/rigidbody_world.c @@ -0,0 +1,213 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joshua Leung, Sergej Reich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file rigidbody_world.c + * \ingroup editor_physics + * \brief Rigid Body world editing operators + */ + +#include <stdlib.h> +#include <string.h> + +#include "DNA_object_types.h" +#include "DNA_rigidbody_types.h" +#include "DNA_scene_types.h" + +#include "BLI_blenlib.h" +#include "BLI_math.h" + +#ifdef WITH_BULLET +# include "RBI_api.h" +#endif + +#include "BKE_context.h" +#include "BKE_depsgraph.h" +#include "BKE_group.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_report.h" +#include "BKE_rigidbody.h" +#include "BKE_utildefines.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_physics.h" +#include "ED_screen.h" + +#include "physics_intern.h" + +/* ********************************************** */ +/* API */ + +/* check if there is an active rigid body world */ +static int ED_rigidbody_world_active_poll(bContext *C) +{ + Scene *scene = CTX_data_scene(C); + return (scene && scene->rigidbody_world); +} +static int ED_rigidbody_world_add_poll(bContext *C) +{ + Scene *scene = CTX_data_scene(C); + return (scene && scene->rigidbody_world == NULL); +} + +/* ********************************************** */ +/* OPERATORS - Management */ + +/* ********** Add RigidBody World **************** */ + +static int rigidbody_world_add_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + RigidBodyWorld *rbw; + + rbw = BKE_rigidbody_create_world(scene); +// BKE_rigidbody_validate_sim_world(scene, rbw, false); + scene->rigidbody_world = rbw; + + return OPERATOR_FINISHED; +} + +void RIGIDBODY_OT_world_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->idname = "RIGIDBODY_OT_world_add"; + ot->name = "Add Rigid Body World"; + ot->description = "Add Rigid Body simulation world to the current scene"; + + /* callbacks */ + ot->exec = rigidbody_world_add_exec; + ot->poll = ED_rigidbody_world_add_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/* ********** Remove RigidBody World ************* */ + +static int rigidbody_world_remove_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + RigidBodyWorld *rbw = scene->rigidbody_world; + + /* sanity checks */ + if (ELEM(NULL, scene, rbw)) { + BKE_report(op->reports, RPT_ERROR, "No Rigid Body World to remove"); + return OPERATOR_CANCELLED; + } + + BKE_rigidbody_free_world(rbw); + scene->rigidbody_world = NULL; + + /* send updates */ + WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void RIGIDBODY_OT_world_remove(wmOperatorType *ot) +{ + /* identifiers */ + ot->idname = "RIGIDBODY_OT_world_remove"; + ot->name = "Remove Rigid Body World"; + ot->description = "Remove Rigid Body simulation world from the current scene"; + + /* callbacks */ + ot->exec = rigidbody_world_remove_exec; + ot->poll = ED_rigidbody_world_active_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; +} + +/* ********************************************** */ +/* UTILITY OPERATORS */ + +/* ********** Export RigidBody World ************* */ + +static int rigidbody_world_export_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + RigidBodyWorld *rbw = scene->rigidbody_world; + char path[FILE_MAX]; + + /* sanity checks */ + if ELEM(NULL, scene, rbw) { + BKE_report(op->reports, RPT_ERROR, "No Rigid Body World to export"); + return OPERATOR_CANCELLED; + } + if (rbw->physics_world == NULL) { + BKE_report(op->reports, RPT_ERROR, "Rigid Body World has no associated physics data to export"); + return OPERATOR_CANCELLED; + } + + RNA_string_get(op->ptr, "filepath", path); +#ifdef WITH_BULLET + RB_dworld_export(rbw->physics_world, path); +#endif + return OPERATOR_FINISHED; +} + +static int rigidbody_world_export_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(evt)) +{ + if (!RNA_struct_property_is_set(op->ptr, "relative_path")) + RNA_boolean_set(op->ptr, "relative_path", (U.flag & USER_RELPATHS)); + + if (RNA_struct_property_is_set(op->ptr, "filepath")) + return rigidbody_world_export_exec(C, op); + + // TODO: use the actual rigidbody world's name + .bullet instead of this temp crap + RNA_string_set(op->ptr, "filepath", "rigidbodyworld_export.bullet"); + WM_event_add_fileselect(C, op); + + return OPERATOR_RUNNING_MODAL; +} + +void RIGIDBODY_OT_world_export(wmOperatorType *ot) +{ + /* identifiers */ + ot->idname = "RIGIDBODY_OT_world_export"; + ot->name = "Export Rigid Body World"; + ot->description = "Export Rigid Body world to simulator's own fileformat (i.e. '.bullet' for Bullet Physics)"; + + /* callbacks */ + ot->invoke = rigidbody_world_export_invoke; + ot->exec = rigidbody_world_export_exec; + ot->poll = ED_rigidbody_world_active_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + WM_operator_properties_filesel(ot, FOLDERFILE, FILE_SPECIAL, FILE_SAVE, FILE_RELPATH, FILE_DEFAULTDISPLAY); +} diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index f8154f4abda..deb6eaf2c22 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -73,6 +73,7 @@ #include "render_intern.h" /* Render Callbacks */ +static int render_break(void *rjv); /* called inside thread! */ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volatile rcti *renrect) @@ -210,7 +211,7 @@ static int screen_render_exec(bContext *C, wmOperator *op) lay = (v3d) ? v3d->lay : scene->lay; G.is_break = FALSE; - RE_test_break_cb(re, NULL, (int (*)(void *))blender_test_break); + RE_test_break_cb(re, NULL, render_break); ima = BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"); BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE); @@ -443,6 +444,15 @@ static int render_breakjob(void *rjv) return 0; } +/* for exec() when there is no render job + * note: this wont check for the escape key being pressed, but doing so isnt threadsafe */ +static int render_break(void *UNUSED(rjv)) +{ + if (G.is_break) + return 1; + return 0; +} + /* runs in thread, no cursor setting here works. careful with notifiers too (malloc conflicts) */ /* maybe need a way to get job send notifer? */ static void render_drawlock(void *UNUSED(rjv), int lock) diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index 38535eca918..16d7923baff 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -394,7 +394,14 @@ static void texture_changed(Main *bmain, Tex *tex) if (dm && totmaterial && material) { for (a = 0; a < *totmaterial; a++) { - if (material_uses_texture((*material)[a], tex)) { + Material *ma; + + if (ob->matbits && ob->matbits[a]) + ma = ob->mat[a]; + else + ma = (*material)[a]; + + if (ma && material_uses_texture(ma, tex)) { GPU_drawobject_free(dm); break; } diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index cea7b12a27d..8afe07b4689 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -1864,15 +1864,11 @@ void ED_region_info_draw(ARegion *ar, const char *text, int block, float alpha) /* background box */ ED_region_visible_rect(ar, &rect); - rect.xmin = 0; rect.ymin = BLI_rcti_size_y(&ar->winrct) - header_height; - if (block) { - rect.xmax = BLI_rcti_size_x(&ar->winrct); - } - else { - rect.xmax = rect.xmin + BLF_width(fontid, text) + 24; - } + /* box fill entire width or just around text */ + if (!block) + rect.xmax = min_ii(rect.xmax, rect.xmin + BLF_width(fontid, text) + 1.2f * U.widget_unit); rect.ymax = BLI_rcti_size_y(&ar->winrct); @@ -1884,8 +1880,13 @@ void ED_region_info_draw(ARegion *ar, const char *text, int block, float alpha) /* text */ UI_ThemeColor(TH_TEXT_HI); - BLF_position(fontid, 12, rect.ymin + 5, 0.0f); + BLF_clipping(fontid, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + BLF_enable(fontid, BLF_CLIPPING); + BLF_position(fontid, rect.xmin + 0.6f * U.widget_unit, rect.ymin + 0.3f * U.widget_unit, 0.0f); + BLF_draw(fontid, text, BLF_DRAW_STR_DUMMY_MAX); + + BLF_disable(fontid, BLF_CLIPPING); } void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy) diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index f073fdd5125..105c2dc88d1 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -38,13 +38,12 @@ #include "BLI_rect.h" #include "BLI_utildefines.h" +#include "BLI_math.h" +#include "BLI_threads.h" #include "BKE_blender.h" #include "BKE_colortools.h" -#include "BLI_math.h" -#include "BLI_threads.h" - #include "BIF_gl.h" #include "BIF_glutil.h" diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index 2982e1f21af..1763e62582a 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -86,8 +86,8 @@ static unsigned int *screenshot(bContext *C, int *dumpsx, int *dumpsy) x = 0; y = 0; - *dumpsx = win->sizex; - *dumpsy = win->sizey; + *dumpsx = WM_window_pixels_x(win); + *dumpsy = WM_window_pixels_y(win); if (*dumpsx && *dumpsy) { @@ -457,8 +457,8 @@ static int screencast_exec(bContext *C, wmOperator *op) wmWindow *win = CTX_wm_window(C); sj->x = 0; sj->y = 0; - sj->dumpsx = win->sizex; - sj->dumpsy = win->sizey; + sj->dumpsx = WM_window_pixels_x(win); + sj->dumpsy = WM_window_pixels_y(win); } else { ScrArea *curarea = CTX_wm_area(C); diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index 5e23a144408..ffea5af74a3 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -43,6 +43,7 @@ #include "BKE_brush.h" #include "BKE_context.h" +#include "BKE_image.h" #include "BKE_paint.h" #include "WM_api.h" @@ -116,7 +117,7 @@ static void make_snap(Snapshot *snap, Brush *brush, ViewContext *vc) snap->winy = vc->ar->winy; } -static int load_tex(Sculpt *sd, Brush *br, ViewContext *vc) +static int load_tex(Brush *br, ViewContext *vc) { static GLuint overlay_texture = 0; static int init = 0; @@ -130,10 +131,6 @@ static int load_tex(Sculpt *sd, Brush *br, ViewContext *vc) int size; int j; int refresh; - -#ifndef _OPENMP - (void)sd; /* quied unused warning */ -#endif if (br->mtex.brush_map_mode == MTEX_MAP_MODE_TILED && !br->mtex.tex) return 0; @@ -147,6 +144,8 @@ static int load_tex(Sculpt *sd, Brush *br, ViewContext *vc) !same_snap(&snap, br, vc); if (refresh) { + struct ImagePool *pool = NULL; + if (br->mtex.tex && br->mtex.tex->preview) tex_changed_timestamp = br->mtex.tex->preview->changed_timestamp[0]; @@ -186,7 +185,10 @@ static int load_tex(Sculpt *sd, Brush *br, ViewContext *vc) buffer = MEM_mallocN(sizeof(GLubyte) * size * size, "load_tex"); - #pragma omp parallel for schedule(static) if (sd->flags & SCULPT_USE_OPENMP) + if (br->mtex.tex) + pool = BKE_image_pool_new(); + + #pragma omp parallel for schedule(static) for (j = 0; j < size; j++) { int i; float y; @@ -236,7 +238,7 @@ static int load_tex(Sculpt *sd, Brush *br, ViewContext *vc) x += br->mtex.ofs[0]; y += br->mtex.ofs[1]; - avg = br->mtex.tex ? paint_get_tex_pixel(br, x, y) : 1; + avg = br->mtex.tex ? paint_get_tex_pixel(br, x, y, pool) : 1; avg += br->texture_sample_bias; @@ -251,6 +253,9 @@ static int load_tex(Sculpt *sd, Brush *br, ViewContext *vc) } } + if (pool) + BKE_image_pool_free(pool); + if (!overlay_texture) glGenTextures(1, &overlay_texture); } @@ -376,7 +381,7 @@ static int sculpt_get_brush_geometry(bContext *C, ViewContext *vc, /* Draw an overlay that shows what effect the brush's texture will * have on brush strength */ /* TODO: sculpt only for now */ -static void paint_draw_alpha_overlay(Sculpt *sd, Brush *brush, +static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush, ViewContext *vc, int x, int y) { rctf quad; @@ -401,7 +406,7 @@ static void paint_draw_alpha_overlay(Sculpt *sd, Brush *brush, GL_VIEWPORT_BIT | GL_TEXTURE_BIT); - if (load_tex(sd, brush, vc)) { + if (load_tex(brush, vc)) { glEnable(GL_BLEND); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); @@ -416,24 +421,24 @@ static void paint_draw_alpha_overlay(Sculpt *sd, Brush *brush, /* brush rotation */ glTranslatef(0.5, 0.5, 0); glRotatef((double)RAD2DEGF((brush->flag & BRUSH_RAKE) ? - sd->last_angle : sd->special_rotation), + ups->last_angle : ups->special_rotation), 0.0, 0.0, 1.0); glTranslatef(-0.5f, -0.5f, 0); /* scale based on tablet pressure */ - if (sd->draw_pressure && BKE_brush_use_size_pressure(vc->scene, brush)) { + if (ups->draw_pressure && BKE_brush_use_size_pressure(vc->scene, brush)) { glTranslatef(0.5f, 0.5f, 0); - glScalef(1.0f / sd->pressure_value, 1.0f / sd->pressure_value, 1); + glScalef(1.0f / ups->pressure_value, 1.0f / ups->pressure_value, 1); glTranslatef(-0.5f, -0.5f, 0); } - if (sd->draw_anchored) { - const float *aim = sd->anchored_initial_mouse; + if (ups->draw_anchored) { + const float *aim = ups->anchored_initial_mouse; const rcti *win = &vc->ar->winrct; - quad.xmin = aim[0] - sd->anchored_size - win->xmin; - quad.ymin = aim[1] - sd->anchored_size - win->ymin; - quad.xmax = aim[0] + sd->anchored_size - win->xmin; - quad.ymax = aim[1] + sd->anchored_size - win->ymin; + quad.xmin = aim[0] - ups->anchored_size - win->xmin; + quad.ymin = aim[1] - ups->anchored_size - win->ymin; + quad.xmax = aim[0] + ups->anchored_size - win->xmin; + quad.ymax = aim[1] + ups->anchored_size - win->ymin; } else { const int radius = BKE_brush_size_get(vc->scene, brush); @@ -476,7 +481,7 @@ static void paint_draw_alpha_overlay(Sculpt *sd, Brush *brush, /* Special actions taken when paint cursor goes over mesh */ /* TODO: sculpt only for now */ -static void paint_cursor_on_hit(Sculpt *sd, Brush *brush, ViewContext *vc, +static void paint_cursor_on_hit(UnifiedPaintSettings *ups, Brush *brush, ViewContext *vc, const float location[3]) { float unprojected_radius, projected_radius; @@ -484,8 +489,8 @@ static void paint_cursor_on_hit(Sculpt *sd, Brush *brush, ViewContext *vc, /* update the brush's cached 3D radius */ if (!BKE_brush_use_locked_size(vc->scene, brush)) { /* get 2D brush radius */ - if (sd->draw_anchored) - projected_radius = sd->anchored_size; + if (ups->draw_anchored) + projected_radius = ups->anchored_size; else { if (brush->flag & BRUSH_ANCHORED) projected_radius = 8; @@ -498,8 +503,8 @@ static void paint_cursor_on_hit(Sculpt *sd, Brush *brush, ViewContext *vc, projected_radius); /* scale 3D brush radius by pressure */ - if (sd->draw_pressure && BKE_brush_use_size_pressure(vc->scene, brush)) - unprojected_radius *= sd->pressure_value; + if (ups->draw_pressure && BKE_brush_use_size_pressure(vc->scene, brush)) + unprojected_radius *= ups->pressure_value; /* set cached value in either Brush or UnifiedPaintSettings */ BKE_brush_unprojected_radius_set(vc->scene, brush, unprojected_radius); @@ -509,6 +514,7 @@ static void paint_cursor_on_hit(Sculpt *sd, Brush *brush, ViewContext *vc, static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) { Scene *scene = CTX_data_scene(C); + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; Paint *paint = paint_get_active_from_context(C); Brush *brush = paint_brush(paint); ViewContext vc; @@ -534,7 +540,6 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) /* TODO: as sculpt and other paint modes are unified, this * special mode of drawing will go away */ if (vc.obact->sculpt) { - Sculpt *sd = CTX_data_tool_settings(C)->sculpt; float location[3]; int pixel_radius, hit; @@ -547,14 +552,14 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) const float v = 1 - u; const float r = 20; - const float dx = sd->last_x - x; - const float dy = sd->last_y - y; + const float dx = ups->last_x - x; + const float dy = ups->last_y - y; if (dx * dx + dy * dy >= r * r) { - sd->last_angle = atan2(dx, dy); + ups->last_angle = atan2(dx, dy); - sd->last_x = u * sd->last_x + v * x; - sd->last_y = u * sd->last_y + v * y; + ups->last_x = u * ups->last_x + v * x; + ups->last_y = u * ups->last_y + v * y; } } @@ -562,7 +567,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) hit = sculpt_get_brush_geometry(C, &vc, x, y, &pixel_radius, location); /* draw overlay */ - paint_draw_alpha_overlay(sd, brush, &vc, x, y); + paint_draw_alpha_overlay(ups, brush, &vc, x, y); if (BKE_brush_use_locked_size(scene, brush)) BKE_brush_size_set(scene, brush, pixel_radius); @@ -581,12 +586,12 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) /* only do if brush is over the mesh */ if (hit) - paint_cursor_on_hit(sd, brush, &vc, location); + paint_cursor_on_hit(ups, brush, &vc, location); - if (sd->draw_anchored) { - final_radius = sd->anchored_size; - translation[0] = sd->anchored_initial_mouse[0] - vc.ar->winrct.xmin; - translation[1] = sd->anchored_initial_mouse[1] - vc.ar->winrct.ymin; + if (ups->draw_anchored) { + final_radius = ups->anchored_size; + translation[0] = ups->anchored_initial_mouse[0] - vc.ar->winrct.xmin; + translation[1] = ups->anchored_initial_mouse[1] - vc.ar->winrct.ymin; } } @@ -599,6 +604,14 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) /* draw brush outline */ glTranslatef(translation[0], translation[1], 0); + + /* draw an inner brush */ + if (ups->draw_pressure && BKE_brush_use_size_pressure(scene, brush)) { + /* inner at full alpha */ + glutil_draw_lined_arc(0.0, M_PI * 2.0, final_radius * ups->pressure_value, 40); + /* outer at half alpha */ + glColor4f(outline_col[0], outline_col[1], outline_col[2], outline_alpha * 0.5f); + } glutil_draw_lined_arc(0.0, M_PI * 2.0, final_radius, 40); glTranslatef(-translation[0], -translation[1], 0); diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index d0f8e36e17d..c60097e20eb 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -316,7 +316,7 @@ typedef struct ProjPaintState { float normal_angle_range; /* difference between normal_angle and normal_angle_inner, for easy access */ short is_ortho; - short is_airbrush; /* only to avoid using (ps.brush->flag & BRUSH_AIRBRUSH) */ + bool do_masking; /* use masking during painting. Some operations such as airbrush may disable */ short is_texbrush; /* only to avoid running */ #ifndef PROJ_DEBUG_NOSEAMBLEED float seam_bleed_px; @@ -355,7 +355,7 @@ typedef union pixelStore { typedef struct ProjPixel { float projCoSS[2]; /* the floating point screen projection of this pixel */ - + float worldCoSS[3]; /* Only used when the airbrush is disabled. * Store the max mask value to avoid painting over an area with a lower opacity * with an advantage that we can avoid touching the pixel at all, if the @@ -1526,6 +1526,7 @@ static int project_paint_pixel_sizeof(const short tool) } } + /* run this function when we know a bucket's, face's pixel can be initialized, * return the ProjPixel which is added to 'ps->bucketRect[bucket_index]' */ static ProjPixel *project_paint_uvpixel_init( @@ -1537,6 +1538,7 @@ static ProjPixel *project_paint_uvpixel_init( const int face_index, const int image_index, const float pixelScreenCo[4], + const float world_spaceCo[3], const int side, const float w[3]) { @@ -1565,6 +1567,10 @@ static ProjPixel *project_paint_uvpixel_init( } /* screenspace unclamped, we could keep its z and w values but don't need them at the moment */ + if (ps->brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) { + copy_v3_v3(projPixel->worldCoSS, world_spaceCo); + } + copy_v2_v2(projPixel->projCoSS, pixelScreenCo); projPixel->x_px = x_px; @@ -2374,6 +2380,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i float *uv1co, *uv2co, *uv3co; /* for convenience only, these will be assigned to tf->uv[0],1,2 or tf->uv[0],2,3 */ float pixelScreenCo[4]; + bool do_3d_mapping = ps->brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D; rcti bounds_px; /* ispace bounds */ /* vars for getting uvspace bounds */ @@ -2449,7 +2456,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i v1coSS = ps->screenCoords[(*(&mf->v1 + i1))]; v2coSS = ps->screenCoords[(*(&mf->v1 + i2))]; v3coSS = ps->screenCoords[(*(&mf->v1 + i3))]; - + /* This funtion gives is a concave polyline in UV space from the clipped quad and tri*/ project_bucket_clip_face( is_ortho, bucket_bounds, @@ -2501,9 +2508,9 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i else screen_px_from_persp(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w); /* a pity we need to get the worldspace pixel location here */ - if (do_clip) { + if (do_clip || do_3d_mapping) { interp_v3_v3v3v3(wco, ps->dm_mvert[(*(&mf->v1 + i1))].co, ps->dm_mvert[(*(&mf->v1 + i2))].co, ps->dm_mvert[(*(&mf->v1 + i3))].co, w); - if (ED_view3d_clipping_test(ps->rv3d, wco, TRUE)) { + if (do_clip && ED_view3d_clipping_test(ps->rv3d, wco, TRUE)) { continue; /* Watch out that no code below this needs to run */ } } @@ -2514,13 +2521,13 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i if ((ps->do_occlude == FALSE) || !project_bucket_point_occluded(ps, bucketFaceNodes, face_index, pixelScreenCo)) { - mask = project_paint_uvpixel_mask(ps, face_index, side, w); - + if (mask > 0.0f) { BLI_linklist_prepend_arena( bucketPixelNodes, - project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, image_index, pixelScreenCo, side, w), + project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, + image_index, pixelScreenCo, wco, side, w), arena ); } @@ -2725,11 +2732,11 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i } /* a pity we need to get the worldspace pixel location here */ - if (do_clip) { + if (do_clip || do_3d_mapping) { if (side) interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v3].co, ps->dm_mvert[mf->v4].co, w); else interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, w); - if (ED_view3d_clipping_test(ps->rv3d, wco, TRUE)) { + if (do_clip && ED_view3d_clipping_test(ps->rv3d, wco, TRUE)) { continue; /* Watch out that no code below this needs to run */ } } @@ -2739,7 +2746,7 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i if (mask > 0.0f) { BLI_linklist_prepend_arena( bucketPixelNodes, - project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, image_index, pixelScreenCo, side, w), + project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, image_index, pixelScreenCo, wco, side, w), arena ); } @@ -3749,6 +3756,8 @@ typedef struct ProjectHandle { /* thread settings */ int thread_index; + + struct ImagePool *pool; } ProjectHandle; static void blend_color_mix(unsigned char cp[4], const unsigned char cp1[4], const unsigned char cp2[4], const int fac) @@ -3800,7 +3809,7 @@ static void blend_color_mix_accum_float(float cp[4], const float cp1[4], const u static void do_projectpaint_clone(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask) { - if (ps->is_airbrush == 0 && mask < 1.0f) { + if (ps->do_masking && mask < 1.0f) { projPixel->newColor.uint = IMB_blend_color(projPixel->newColor.uint, ((ProjPixelClone *)projPixel)->clonepx.uint, (int)(alpha * 255), ps->blend); blend_color_mix(projPixel->pixel.ch_pt, projPixel->origColor.ch, projPixel->newColor.ch, (int)(mask * 255)); } @@ -3811,7 +3820,7 @@ static void do_projectpaint_clone(ProjPaintState *ps, ProjPixel *projPixel, floa static void do_projectpaint_clone_f(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask) { - if (ps->is_airbrush == 0 && mask < 1.0f) { + if (ps->do_masking && mask < 1.0f) { IMB_blend_color_float(projPixel->newColor.f, projPixel->newColor.f, ((ProjPixelClone *)projPixel)->clonepx.f, alpha, ps->blend); blend_color_mix_float(projPixel->pixel.f_pt, projPixel->origColor.f, projPixel->newColor.f, mask); } @@ -3946,7 +3955,7 @@ static void do_projectpaint_draw(ProjPaintState *ps, ProjPixel *projPixel, const rgba_ub[3] = 255; } - if (ps->is_airbrush == 0 && mask < 1.0f) { + if (ps->do_masking && mask < 1.0f) { projPixel->newColor.uint = IMB_blend_color(projPixel->newColor.uint, *((unsigned int *)rgba_ub), (int)(alpha * 255), ps->blend); blend_color_mix(projPixel->pixel.ch_pt, projPixel->origColor.ch, projPixel->newColor.ch, (int)(mask * 255)); } @@ -3978,7 +3987,7 @@ static void do_projectpaint_draw_f(ProjPaintState *ps, ProjPixel *projPixel, flo rgba[3] = 1.0; } - if (ps->is_airbrush == 0 && mask < 1.0f) { + if (ps->do_masking && mask < 1.0f) { IMB_blend_color_float(projPixel->newColor.f, projPixel->newColor.f, rgba, alpha, ps->blend); blend_color_mix_float(projPixel->pixel.f_pt, projPixel->origColor.f, projPixel->newColor.f, mask); } @@ -3998,10 +4007,12 @@ static void *do_projectpaint_thread(void *ph_v) const float *lastpos = ((ProjectHandle *)ph_v)->prevmval; const float *pos = ((ProjectHandle *)ph_v)->mval; const int thread_index = ((ProjectHandle *)ph_v)->thread_index; + struct ImagePool *pool = ((ProjectHandle *)ph_v)->pool; /* Done with args from ProjectHandle */ LinkNode *node; ProjPixel *projPixel; + Brush *brush = ps->brush; int last_index = -1; ProjPaintImage *last_projIma = NULL; @@ -4021,10 +4032,10 @@ static void *do_projectpaint_thread(void *ph_v) float co[2]; float mask = 1.0f; /* airbrush wont use mask */ unsigned short mask_short; - const float radius = (float)BKE_brush_size_get(ps->scene, ps->brush); + const float radius = (float)BKE_brush_size_get(ps->scene, brush); const float radius_squared = radius * radius; /* avoid a square root with every dist comparison */ - short lock_alpha = ELEM(ps->brush->blend, IMB_BLEND_ERASE_ALPHA, IMB_BLEND_ADD_ALPHA) ? 0 : ps->brush->flag & BRUSH_LOCK_ALPHA; + short lock_alpha = ELEM(brush->blend, IMB_BLEND_ERASE_ALPHA, IMB_BLEND_ADD_ALPHA) ? 0 : brush->flag & BRUSH_LOCK_ALPHA; LinkNode *smearPixels = NULL; LinkNode *smearPixels_f = NULL; @@ -4105,23 +4116,36 @@ static void *do_projectpaint_thread(void *ph_v) /*if (dist < radius) {*/ /* correct but uses a sqrtf */ if (dist_nosqrt <= radius_squared) { + float samplecos[3]; dist = sqrtf(dist_nosqrt); falloff = BKE_brush_curve_strength_clamp(ps->brush, dist, radius); + if (ps->is_texbrush) { + MTex *mtex = &brush->mtex; + if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) { + sub_v2_v2v2(samplecos, projPixel->projCoSS, pos); + } + /* taking 3d copy to account for 3D mapping too. It gets concatenated during sampling */ + else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) + copy_v3_v3(samplecos, projPixel->worldCoSS); + else + copy_v3_v3(samplecos, projPixel->projCoSS); + } + if (falloff > 0.0f) { if (ps->is_texbrush) { /* note, for clone and smear, we only use the alpha, could be a special function */ - BKE_brush_sample_tex(ps->scene, ps->brush, projPixel->projCoSS, rgba, thread_index); + BKE_brush_sample_tex(ps->scene, brush, samplecos, rgba, thread_index, pool); alpha = rgba[3]; } else { alpha = 1.0f; } - if (ps->is_airbrush) { + if (!ps->do_masking) { /* for an aurbrush there is no real mask, so just multiply the alpha by it */ - alpha *= falloff * BKE_brush_alpha_get(ps->scene, ps->brush); + alpha *= falloff * BKE_brush_alpha_get(ps->scene, brush); mask = ((float)projPixel->mask) / 65535.0f; } else { @@ -4129,7 +4153,7 @@ static void *do_projectpaint_thread(void *ph_v) falloff = 1.0f - falloff; falloff = 1.0f - (falloff * falloff); - mask_short = (unsigned short)(projPixel->mask * (BKE_brush_alpha_get(ps->scene, ps->brush) * falloff)); + mask_short = (unsigned short)(projPixel->mask * (BKE_brush_alpha_get(ps->scene, brush) * falloff)); if (mask_short > projPixel->mask_max) { mask = ((float)mask_short) / 65535.0f; projPixel->mask_max = mask_short; @@ -4248,6 +4272,8 @@ static int project_paint_op(void *state, ImBuf *UNUSED(ibufb), const float lastp ListBase threads; int a, i; + struct ImagePool *pool; + if (!project_bucket_iter_init(ps, pos)) { return 0; } @@ -4255,6 +4281,8 @@ static int project_paint_op(void *state, ImBuf *UNUSED(ibufb), const float lastp if (ps->thread_tot > 1) BLI_init_threads(&threads, do_projectpaint_thread, ps->thread_tot); + pool = BKE_image_pool_new(); + /* get the threads running */ for (a = 0; a < ps->thread_tot; a++) { @@ -4278,6 +4306,8 @@ static int project_paint_op(void *state, ImBuf *UNUSED(ibufb), const float lastp memcpy(handles[a].projImages[i].partRedrawRect, ps->projImages[i].partRedrawRect, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED); } + handles[a].pool = pool; + if (ps->thread_tot > 1) BLI_insert_thread(&threads, &handles[a]); } @@ -4288,6 +4318,8 @@ static int project_paint_op(void *state, ImBuf *UNUSED(ibufb), const float lastp do_projectpaint_thread(&handles[0]); + BKE_image_pool_free(pool); + /* move threaded bounds back into ps->projectPartialRedraws */ for (i = 0; i < ps->image_tot; i++) { int touch = 0; @@ -4714,6 +4746,7 @@ static int imapaint_canvas_set(ImagePaintState *s, Image *ima) if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) { BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_release_ibuf(s->image, s->canvas, NULL); return 0; } @@ -4955,7 +4988,6 @@ typedef struct PaintOperation { int first; int prevmouse[2]; - float prev_pressure; /* need this since we don't get tablet events for pressure change */ int orig_brush_size; double starttime; @@ -4998,7 +5030,9 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps) ps->pixel_sizeof = project_paint_pixel_sizeof(ps->tool); BLI_assert(ps->pixel_sizeof >= sizeof(ProjPixel)); - ps->is_airbrush = (brush->flag & BRUSH_AIRBRUSH) ? 1 : 0; + /* disable for 3d mapping also because painting on mirrored mesh can create "stripes" */ + ps->do_masking = (brush->flag & BRUSH_AIRBRUSH || brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW || + brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) ? false : true; ps->is_texbrush = (brush->mtex.tex) ? 1 : 0; @@ -5173,6 +5207,11 @@ static int texture_paint_init(bContext *C, wmOperator *op) /* create painter */ pop->painter = BKE_brush_painter_new(scene, pop->s.brush); + { + UnifiedPaintSettings *ups = &settings->unified_paint_settings; + ups->draw_pressure = true; + } + return 1; } @@ -5261,6 +5300,11 @@ static void paint_exit(bContext *C, wmOperator *op) BKE_reportf(op->reports, RPT_WARNING, "Packed MultiLayer files cannot be painted: %s", pop->s.warnpackedfile); MEM_freeN(pop); + + { + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; + ups->draw_pressure = false; + } } static int paint_exec(bContext *C, wmOperator *op) @@ -5285,7 +5329,6 @@ static void paint_apply_event(bContext *C, wmOperator *op, wmEvent *event) { const Scene *scene = CTX_data_scene(C); PaintOperation *pop = op->customdata; - wmTabletData *wmtab; PointerRNA itemptr; float pressure, mousef[2]; double time; @@ -5296,16 +5339,17 @@ static void paint_apply_event(bContext *C, wmOperator *op, wmEvent *event) tablet = 0; pop->s.blend = pop->s.brush->blend; - if (event->custom == EVT_DATA_TABLET) { - wmtab = event->customdata; + if (event->tablet_data) { + wmTabletData *wmtab = event->tablet_data; tablet = (wmtab->Active != EVT_TABLET_NONE); pressure = wmtab->Pressure; if (wmtab->Active == EVT_TABLET_ERASER) pop->s.blend = IMB_BLEND_ERASE_ALPHA; } - else { /* otherwise airbrush becomes 1.0 pressure instantly */ - pressure = pop->prev_pressure ? pop->prev_pressure : 1.0f; + else { + BLI_assert(fabsf(WM_cursor_pressure(CTX_wm_window(C))) == 1.0f); + pressure = 1.0f; } if (pop->first) { @@ -5338,7 +5382,10 @@ static void paint_apply_event(bContext *C, wmOperator *op, wmEvent *event) /* apply */ paint_apply(C, op, &itemptr); - pop->prev_pressure = pressure; + { + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; + ups->pressure_value = pressure; + } } static int paint_invoke(bContext *C, wmOperator *op, wmEvent *event) @@ -5349,7 +5396,7 @@ static int paint_invoke(bContext *C, wmOperator *op, wmEvent *event) MEM_freeN(op->customdata); return OPERATOR_CANCELLED; } - + paint_apply_event(C, op, event); pop = op->customdata; @@ -5479,6 +5526,16 @@ static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata) glColor4f(brush->add_col[0], brush->add_col[1], brush->add_col[2], alpha); glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); + { + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; + /* hrmf, duplicate paint_draw_cursor logic here */ + if (ups->draw_pressure && BKE_brush_use_size_pressure(scene, brush)) { + /* inner at full alpha */ + glutil_draw_lined_arc(0, (float)(M_PI * 2.0), size * ups->pressure_value, 40); + /* outer at half alpha */ + glColor4f(brush->add_col[0], brush->add_col[1], brush->add_col[2], alpha * 0.5f); + } + } glutil_draw_lined_arc(0, (float)(M_PI * 2.0), size, 40); glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); @@ -5953,7 +6010,7 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op) /* override */ ps.is_texbrush = 0; - ps.is_airbrush = 1; + ps.do_masking = false; orig_brush_size = BKE_brush_size_get(scene, ps.brush); BKE_brush_size_set(scene, ps.brush, 32); /* cover the whole image */ diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c index dd7412cf3d5..0b76c88df66 100644 --- a/source/blender/editors/sculpt_paint/paint_image_2d.c +++ b/source/blender/editors/sculpt_paint/paint_image_2d.c @@ -205,7 +205,7 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, xy[0] = x + xoff; xy[1] = y + yoff; - BKE_brush_sample_tex(scene, brush, xy, tf, 0); + BKE_brush_sample_tex_2D(scene, brush, xy, tf, 0); } bf[0] = tf[0] * mf[0]; @@ -236,7 +236,7 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, xy[0] = x + xoff; xy[1] = y + yoff; - BKE_brush_sample_tex(scene, brush, xy, rgba, 0); + BKE_brush_sample_tex_2D(scene, brush, xy, rgba, 0); rgba_float_to_uchar(t, rgba); } @@ -314,6 +314,7 @@ static void brush_painter_refresh_cache(BrushPainter *painter, const float pos[2 short flt; const int diameter = 2 * BKE_brush_size_get(scene, brush); const float alpha = BKE_brush_alpha_get(scene, brush); + const bool do_tiled = ELEM(brush->mtex.brush_map_mode, MTEX_MAP_MODE_TILED, MTEX_MAP_MODE_3D); if (diameter != cache->lastsize || alpha != cache->lastalpha || @@ -331,7 +332,7 @@ static void brush_painter_refresh_cache(BrushPainter *painter, const float pos[2 flt = cache->flt; size = (cache->size) ? cache->size : diameter; - if (brush->flag & BRUSH_FIXED_TEX) { + if (do_tiled) { BKE_brush_imbuf_new(scene, brush, flt, 3, size, &cache->maskibuf, use_color_correction); brush_painter_fixed_tex_partial_update(painter, pos); } @@ -342,7 +343,7 @@ static void brush_painter_refresh_cache(BrushPainter *painter, const float pos[2 cache->lastalpha = alpha; cache->lastjitter = brush->jitter; } - else if ((brush->flag & BRUSH_FIXED_TEX) && mtex && mtex->tex) { + else if (do_tiled && mtex && mtex->tex) { int dx = (int)painter->lastpaintpos[0] - (int)pos[0]; int dy = (int)painter->lastpaintpos[1] - (int)pos[1]; @@ -539,7 +540,7 @@ unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side) co[2] = 0.0f; /* This is copied from displace modifier code */ - hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres); + hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres, NULL); /* if the texture gave an RGB value, we assume it didn't give a valid * intensity, so calculate one (formula from do_material_tex). diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index cf55c93efe4..faa9ce00da8 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -36,6 +36,7 @@ struct ARegion; struct bContext; struct bglMats; struct Brush; +struct ImagePool; struct ListBase; struct Mesh; struct Object; @@ -61,7 +62,8 @@ struct PaintStroke *paint_stroke_new(struct bContext *C, StrokeUpdateStep update_step, StrokeDone done, int event_type); void paint_stroke_data_free(struct wmOperator *op); -int paint_space_stroke_enabled(struct Brush *br); +bool paint_space_stroke_enabled(struct Brush *br); +bool paint_supports_dynamic_size(struct Brush *br); struct wmKeyMap *paint_stroke_modal_keymap(struct wmKeyConfig *keyconf); int paint_stroke_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event); @@ -139,7 +141,7 @@ void paint_calc_redraw_planes(float planes[4][4], void projectf(struct bglMats *mats, const float v[3], float p[2]); float paint_calc_object_space_radius(struct ViewContext *vc, const float center[3], float pixel_radius); -float paint_get_tex_pixel(struct Brush *br, float u, float v); +float paint_get_tex_pixel(struct Brush *br, float u, float v, struct ImagePool *pool); int imapaint_pick_face(struct ViewContext *vc, const int mval[2], unsigned int *index, unsigned int totface); void imapaint_pick_uv(struct Scene *scene, struct Object *ob, unsigned int faceindex, const int xy[2], float uv[2]); diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index e5d6a1820a2..618d545b084 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -681,6 +681,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf) keymap_brush_select(keymap, OB_MODE_SCULPT, SCULPT_TOOL_FLATTEN, TKEY, KM_SHIFT); keymap_brush_select(keymap, OB_MODE_SCULPT, SCULPT_TOOL_CLAY, CKEY, 0); keymap_brush_select(keymap, OB_MODE_SCULPT, SCULPT_TOOL_CREASE, CKEY, KM_SHIFT); + keymap_brush_select(keymap, OB_MODE_SCULPT, SCULPT_TOOL_SNAKE_HOOK, KKEY, 0); kmi = keymap_brush_select(keymap, OB_MODE_SCULPT, SCULPT_TOOL_MASK, MKEY, 0); RNA_boolean_set(kmi->ptr, "toggle", 1); RNA_boolean_set(kmi->ptr, "create_missing", 1); diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 2f4115dcd94..5d9313485d2 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -125,8 +125,8 @@ static float event_tablet_data(wmEvent *event, int *pen_flip) int erasor = 0; float pressure = 1; - if (event->custom == EVT_DATA_TABLET) { - wmTabletData *wmtab = event->customdata; + if (event->tablet_data) { + wmTabletData *wmtab = event->tablet_data; erasor = (wmtab->Active == EVT_TABLET_ERASER); pressure = (wmtab->Active != EVT_TABLET_NONE) ? wmtab->Pressure : 1; @@ -324,10 +324,15 @@ static void stroke_done(struct bContext *C, struct wmOperator *op) } /* Returns zero if the stroke dots should not be spaced, non-zero otherwise */ -int paint_space_stroke_enabled(Brush *br) +bool paint_space_stroke_enabled(Brush *br) { - return (br->flag & BRUSH_SPACE) && - !(br->flag & BRUSH_ANCHORED) && + return (br->flag & BRUSH_SPACE) && paint_supports_dynamic_size(br); +} + +/* return true if the brush size can change during paint (normally used for pressure) */ +bool paint_supports_dynamic_size(Brush *br) +{ + return !(br->flag & BRUSH_ANCHORED) && !ELEM4(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_THUMB, SCULPT_TOOL_ROTATE, SCULPT_TOOL_SNAKE_HOOK); } diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index e7d13bd080d..4f156276aac 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -173,13 +173,13 @@ float paint_calc_object_space_radius(ViewContext *vc, const float center[3], return len_v3(delta) / scale; } -float paint_get_tex_pixel(Brush *br, float u, float v) +float paint_get_tex_pixel(Brush *br, float u, float v, struct ImagePool *pool) { TexResult texres = {0}; float co[3] = {u, v, 0.0f}; int hasrgb; - hasrgb = multitex_ext(br->mtex.tex, co, NULL, NULL, 0, &texres); + hasrgb = multitex_ext(br->mtex.tex, co, NULL, NULL, 0, &texres, pool); if (hasrgb & TEX_RGB) texres.tin = rgb_to_grayscale(&texres.tr) * texres.ta; diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 08c26aaa755..5b04bdb8ee7 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -2172,6 +2172,11 @@ static int wpaint_stroke_test_start(bContext *C, wmOperator *op, const float UNU if (me->editflag & ME_EDIT_MIRROR_X) { wpd->vgroup_mirror = wpaint_mirror_vgroup_ensure(ob, wpd->vgroup_active); } + + { + UnifiedPaintSettings *ups = &ts->unified_paint_settings; + ups->draw_pressure = true; + } return TRUE; } @@ -2414,6 +2419,11 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P swap_m4m4(vc->rv3d->persmat, mat); + { + UnifiedPaintSettings *ups = &ts->unified_paint_settings; + ups->pressure_value = pressure; + } + DAG_id_tag_update(ob->data, 0); ED_region_tag_redraw(vc->ar); } @@ -2454,7 +2464,12 @@ static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke) } } } - + + { + UnifiedPaintSettings *ups = &ts->unified_paint_settings; + ups->draw_pressure = false; + } + DAG_id_tag_update(ob->data, 0); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); @@ -2583,9 +2598,8 @@ static int set_vpaint(bContext *C, wmOperator *op) /* toggle */ BKE_paint_init(&vp->paint, PAINT_CURSOR_VERTEX_PAINT); } - if (me) - /* update modifier stack for mapping requirements */ - DAG_id_tag_update(&me->id, 0); + /* update modifier stack for mapping requirements */ + DAG_id_tag_update(&me->id, 0); WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene); @@ -2735,6 +2749,11 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const fl invert_m4_m4(imat, mat); copy_m3_m4(vpd->vpimat, imat); + { + UnifiedPaintSettings *ups = &ts->unified_paint_settings; + ups->draw_pressure = true; + } + return 1; } @@ -2889,6 +2908,11 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P do_shared_vertexcol(me, do_tessface); } + { + UnifiedPaintSettings *ups = &ts->unified_paint_settings; + ups->pressure_value = pressure; + } + ED_region_tag_redraw(vc->ar); if (vpd->use_fast_update == FALSE) { @@ -2920,6 +2944,11 @@ static void vpaint_stroke_done(const bContext *C, struct PaintStroke *stroke) BLI_memarena_free(vpd->polyfacemap_arena); } + { + UnifiedPaintSettings *ups = &ts->unified_paint_settings; + ups->draw_pressure = false; + } + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); MEM_freeN(vpd); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 2dc4176dde3..ce7d72f9787 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -56,6 +56,7 @@ #include "BKE_cdderivedmesh.h" #include "BKE_context.h" #include "BKE_depsgraph.h" +#include "BKE_image.h" #include "BKE_key.h" #include "BKE_library.h" #include "BKE_mesh.h" @@ -430,7 +431,11 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob) BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode); - #pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP) + /* Disable OpenMP when dynamic-topology is enabled. Otherwise, new + * entries might be inserted by sculpt_undo_push_node() into the + * GHash used internally by BM_log_original_vert_co() by a + * different thread. [#33787] */ + #pragma omp parallel for schedule(guided) if (sd->flags & SCULPT_USE_OPENMP && !ss->bm) for (n = 0; n < totnode; n++) { SculptUndoNode *unode; SculptUndoType type = (brush->sculpt_tool == SCULPT_TOOL_MASK ? @@ -893,7 +898,7 @@ static float tex_strength(SculptSession *ss, Brush *br, /* Get strength by feeding the vertex * location directly into a texture */ externtex(mtex, point, &avg, - &jnk, &jnk, &jnk, &jnk, 0); + &jnk, &jnk, &jnk, &jnk, 0, ss->tex_pool); } else if (ss->texcache) { float rotation = -mtex->rot; @@ -979,7 +984,7 @@ static float tex_strength(SculptSession *ss, Brush *br, x += br->mtex.ofs[0]; y += br->mtex.ofs[1]; - avg = paint_get_tex_pixel(br, x, y); + avg = paint_get_tex_pixel(br, x, y, ss->tex_pool); } avg += br->texture_sample_bias; @@ -3372,11 +3377,17 @@ static void sculpt_update_tex(const Scene *scene, Sculpt *sd, SculptSession *ss) ss->texcache = NULL; } + if (ss->tex_pool) { + BKE_image_pool_free(ss->tex_pool); + ss->tex_pool = NULL; + } + /* Need to allocate a bigger buffer for bigger brush size */ ss->texcache_side = 2 * radius; if (!ss->texcache || ss->texcache_side > ss->texcache_actual) { ss->texcache = BKE_brush_gen_texture_cache(brush, radius); ss->texcache_actual = ss->texcache_side; + ss->tex_pool = BKE_image_pool_new(); } } @@ -3654,6 +3665,7 @@ static void sculpt_omp_done(SculptSession *ss) static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSession *ss, wmOperator *op, const float mouse[2]) { StrokeCache *cache = MEM_callocN(sizeof(StrokeCache), "stroke cache"); + UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings; Brush *brush = paint_brush(&sd->paint); ViewContext *vc = paint_stroke_view_context(op->customdata); Object *ob = CTX_data_active_object(C); @@ -3762,7 +3774,7 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio } } - cache->special_rotation = (brush->flag & BRUSH_RAKE) ? sd->last_angle : 0; + cache->special_rotation = (brush->flag & BRUSH_RAKE) ? ups->last_angle : 0; cache->first_time = 1; @@ -3771,7 +3783,7 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio sculpt_omp_start(sd, ss); } -static void sculpt_update_brush_delta(Sculpt *sd, Object *ob, Brush *brush) +static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Brush *brush) { SculptSession *ss = ob->sculpt; StrokeCache *cache = ss->cache; @@ -3836,17 +3848,17 @@ static void sculpt_update_brush_delta(Sculpt *sd, Object *ob, Brush *brush) copy_v3_v3(cache->old_grab_location, grab_location); if (tool == SCULPT_TOOL_GRAB) - copy_v3_v3(sd->anchored_location, cache->true_location); + copy_v3_v3(ups->anchored_location, cache->true_location); else if (tool == SCULPT_TOOL_THUMB) - copy_v3_v3(sd->anchored_location, cache->orig_grab_location); + copy_v3_v3(ups->anchored_location, cache->orig_grab_location); if (ELEM(tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_THUMB)) { /* location stays the same for finding vertices in brush radius */ copy_v3_v3(cache->true_location, cache->orig_grab_location); - sd->draw_anchored = 1; - copy_v2_v2(sd->anchored_initial_mouse, cache->initial_mouse); - sd->anchored_size = cache->pixel_radius; + ups->draw_anchored = 1; + copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse); + ups->anchored_size = cache->pixel_radius; } } } @@ -3857,6 +3869,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, PointerRNA *ptr) { Scene *scene = CTX_data_scene(C); + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; SculptSession *ss = ob->sculpt; StrokeCache *cache = ss->cache; Brush *brush = paint_brush(&sd->paint); @@ -3880,13 +3893,14 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, * brush coord/pressure/etc. * It's more an events design issue, which doesn't split coordinate/pressure/angle * changing events. We should avoid this after events system re-design */ - if (paint_space_stroke_enabled(brush) || cache->first_time) + if (paint_supports_dynamic_size(brush) || cache->first_time) { cache->pressure = RNA_float_get(ptr, "pressure"); + } /* Truly temporary data that isn't stored in properties */ - sd->draw_pressure = 1; - sd->pressure_value = cache->pressure; + ups->draw_pressure = 1; + ups->pressure_value = cache->pressure; cache->previous_pixel_radius = cache->pixel_radius; cache->pixel_radius = BKE_brush_size_get(scene, brush); @@ -3903,12 +3917,13 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, } } - if (BKE_brush_use_size_pressure(scene, brush)) { + if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush)) { cache->pixel_radius *= cache->pressure; cache->radius = cache->initial_radius * cache->pressure; } - else + else { cache->radius = cache->initial_radius; + } cache->radius_squared = cache->radius * cache->radius; @@ -3932,7 +3947,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, const float dx = cache->mouse[0] - cache->initial_mouse[0]; const float dy = cache->mouse[1] - cache->initial_mouse[1]; - sd->anchored_size = cache->pixel_radius = sqrt(dx * dx + dy * dy); + ups->anchored_size = cache->pixel_radius = sqrt(dx * dx + dy * dy); cache->special_rotation = atan2(dx, dy) + M_PI; @@ -3944,27 +3959,27 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, halfway[1] = dy * 0.5f + cache->initial_mouse[1]; if (sculpt_stroke_get_location(C, out, halfway)) { - copy_v3_v3(sd->anchored_location, out); - copy_v2_v2(sd->anchored_initial_mouse, halfway); + copy_v3_v3(ups->anchored_location, out); + copy_v2_v2(ups->anchored_initial_mouse, halfway); copy_v2_v2(cache->tex_mouse, halfway); - copy_v3_v3(cache->true_location, sd->anchored_location); - sd->anchored_size /= 2.0f; + copy_v3_v3(cache->true_location, ups->anchored_location); + ups->anchored_size /= 2.0f; cache->pixel_radius /= 2.0f; hit = 1; } } if (!hit) - copy_v2_v2(sd->anchored_initial_mouse, cache->initial_mouse); + copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse); cache->radius = paint_calc_object_space_radius(paint_stroke_view_context(stroke), cache->true_location, cache->pixel_radius); cache->radius_squared = cache->radius * cache->radius; - copy_v3_v3(sd->anchored_location, cache->true_location); + copy_v3_v3(ups->anchored_location, cache->true_location); - sd->draw_anchored = 1; + ups->draw_anchored = 1; } else if (brush->flag & BRUSH_RAKE) { const float u = 0.5f; @@ -3985,7 +4000,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, } } - sculpt_update_brush_delta(sd, ob, brush); + sculpt_update_brush_delta(ups, ob, brush); if (brush->sculpt_tool == SCULPT_TOOL_ROTATE) { const float dx = cache->mouse[0] - cache->initial_mouse[0]; @@ -3993,13 +4008,13 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, cache->vertex_rotation = -atan2f(dx, dy) * cache->bstrength; - sd->draw_anchored = 1; - copy_v2_v2(sd->anchored_initial_mouse, cache->initial_mouse); - copy_v3_v3(sd->anchored_location, cache->true_location); - sd->anchored_size = cache->pixel_radius; + ups->draw_anchored = 1; + copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse); + copy_v3_v3(ups->anchored_location, cache->true_location); + ups->anchored_size = cache->pixel_radius; } - sd->special_rotation = cache->special_rotation; + ups->special_rotation = cache->special_rotation; } /* Returns true iff any of the smoothing modes are active (currently @@ -4172,6 +4187,17 @@ static void sculpt_restore_mesh(Sculpt *sd, Object *ob) } } +/* Copy the PBVH bounding box into the object's bounding box */ +static void sculpt_update_object_bounding_box(Object *ob) +{ + if (ob->bb) { + float bb_min[3], bb_max[3]; + + BKE_pbvh_bounding_box(ob->sculpt->pbvh, bb_min, bb_max); + BKE_boundbox_init_from_minmax(ob->bb, bb_min, bb_max); + } +} + static void sculpt_flush_update(bContext *C) { Object *ob = CTX_data_active_object(C); @@ -4192,6 +4218,11 @@ static void sculpt_flush_update(bContext *C) rcti r; BKE_pbvh_update(ss->pbvh, PBVH_UpdateBB, NULL); + /* Update the object's bounding box too so that the object + * doesn't get incorrectly clipped during drawing in + * draw_mesh_object(). [#33790] */ + sculpt_update_object_bounding_box(ob); + if (sculpt_get_redraw_rect(ar, CTX_wm_region_view3d(C), ob, &r)) { if (ss->cache) ss->cache->previous_r = r; @@ -4289,6 +4320,7 @@ static void sculpt_brush_exit_tex(Sculpt *sd) static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(stroke)) { + UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings; Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; Sculpt *sd = CTX_data_tool_settings(C)->sculpt; @@ -4296,9 +4328,9 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str sculpt_omp_done(ss); /* reset values used to draw brush after completing the stroke */ - sd->draw_anchored = 0; - sd->draw_pressure = 0; - sd->special_rotation = 0; + ups->draw_anchored = 0; + ups->draw_pressure = 0; + ups->special_rotation = 0; /* Finished */ if (ss->cache) { @@ -4869,6 +4901,12 @@ static int sculpt_toggle_mode(bContext *C, wmOperator *UNUSED(op)) /* Enter sculptmode */ ob->mode |= OB_MODE_SCULPT; + /* Remove dynamic-topology flag; this will be enabled if the + * file was saved with dynamic topology on, but we don't + * automatically re-enter dynamic-topology mode when loading a + * file. */ + me->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY; + if (flush_recalc) DAG_id_tag_update(&ob->id, OB_RECALC_DATA); diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c index d40426a5bc9..54261974993 100644 --- a/source/blender/editors/space_buttons/buttons_ops.c +++ b/source/blender/editors/space_buttons/buttons_ops.c @@ -112,14 +112,22 @@ static int file_browse_exec(bContext *C, wmOperator *op) /* add slash for directories, important for some properties */ if (RNA_property_subtype(fbo->prop) == PROP_DIRPATH) { char name[FILE_MAX]; - + int is_relative = RNA_boolean_get(op->ptr, "relative_path"); id = fbo->ptr.id.data; BLI_strncpy(path, str, FILE_MAX); BLI_path_abs(path, id ? ID_BLEND_PATH(G.main, id) : G.main->name); if (BLI_is_dir(path)) { - str = MEM_reallocN(str, strlen(str) + 2); + if (is_relative) { + BLI_strncpy(path, str, FILE_MAX); + BLI_path_rel(path, G.main->name); + str = MEM_reallocN(str, strlen(path) + 2); + BLI_strncpy(str, path, FILE_MAX); + } + else { + str = MEM_reallocN(str, strlen(str) + 2); + } BLI_add_slash(str); } else diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 04154a27b74..927834a8924 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -33,13 +33,6 @@ #include "MEM_guardedalloc.h" -#include "BKE_main.h" -#include "BKE_mask.h" -#include "BKE_movieclip.h" -#include "BKE_context.h" -#include "BKE_tracking.h" -#include "BKE_library.h" - #include "DNA_mask_types.h" #include "DNA_object_types.h" /* SELECT */ @@ -48,6 +41,13 @@ #include "BLI_string.h" #include "BLI_rect.h" +#include "BKE_main.h" +#include "BKE_mask.h" +#include "BKE_movieclip.h" +#include "BKE_context.h" +#include "BKE_tracking.h" +#include "BKE_library.h" + #include "GPU_extensions.h" #include "IMB_imbuf_types.h" diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 060a181612b..afae9535fee 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -784,6 +784,8 @@ void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_man R_IMF_CHAN_DEPTH_32)) == 0) { row = uiLayoutRow(col, FALSE); + + uiItemL(row, IFACE_("Color Depth:"), ICON_NONE); uiItemR(row, imfptr, "color_depth", UI_ITEM_R_EXPAND, NULL, ICON_NONE); } diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 7b4814d1ab2..ba4f8287cd7 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -110,8 +110,8 @@ static void draw_render_info(Scene *scene, Image *ima, ARegion *ar, float zoomx, glScalef(zoomx, zoomy, 1.0f); if (scene->r.mode & R_BORDER) { - glTranslatef(-scene->r.border.xmin * scene->r.xsch * scene->r.size / 100.0f, - -scene->r.border.ymin * scene->r.ysch * scene->r.size / 100.0f, + glTranslatef((int)(-scene->r.border.xmin * scene->r.xsch * scene->r.size / 100.0f), + (int)(-scene->r.border.ymin * scene->r.ysch * scene->r.size / 100.0f), 0.0f); } @@ -834,7 +834,7 @@ void draw_image_main(const bContext *C, ARegion *ar) show_render = (show_viewer && ima->type == IMA_TYPE_R_RESULT); if (show_viewer) { - /* use locked draw for drawing viewer image buffer since the conpositor + /* use locked draw for drawing viewer image buffer since the compositor * is running in separated thread and compositor could free this buffers. * other images are not modifying in such a way so they does not require * lock (sergey) diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index eed15425441..23adf7eb575 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1109,6 +1109,11 @@ static int image_replace_exec(bContext *C, wmOperator *op) /* we cant do much if the str is longer then FILE_MAX :/ */ BLI_strncpy(sima->image->name, str, sizeof(sima->image->name)); + if (sima->image->source == IMA_SRC_GENERATED) { + sima->image->source = IMA_SRC_FILE; + BKE_image_signal(sima->image, &sima->iuser, IMA_SIGNAL_SRC_CHANGE); + } + if (BLI_testextensie_array(str, imb_ext_movie)) sima->image->source = IMA_SRC_MOVIE; else diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 9492e29734d..1c384ef38d7 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -38,6 +38,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BLI_threads.h" #include "BKE_colortools.h" #include "BKE_context.h" @@ -692,10 +693,25 @@ static void image_main_area_draw(const bContext *C, ARegion *ar) } if (mask) { - int width, height; + Image *image = ED_space_image(sima); + int width, height, show_viewer; float aspx, aspy; + + show_viewer = (image && image->source == IMA_SRC_VIEWER); + + if (show_viewer) { + /* ED_space_image_get* will acquire image buffer which requires + * lock here by the same reason why lock is needed in draw_image_main + */ + BLI_lock_thread(LOCK_DRAW_IMAGE); + } + ED_space_image_get_size(sima, &width, &height); ED_space_image_get_aspect(sima, &aspx, &aspy); + + if (show_viewer) + BLI_unlock_thread(LOCK_DRAW_IMAGE); + ED_mask_draw_region(mask, ar, sima->mask_info.draw_flag, sima->mask_info.draw_type, width, height, diff --git a/source/blender/editors/space_logic/logic_ops.c b/source/blender/editors/space_logic/logic_ops.c index 74be7c46d26..f28757bb431 100644 --- a/source/blender/editors/space_logic/logic_ops.c +++ b/source/blender/editors/space_logic/logic_ops.c @@ -54,6 +54,8 @@ #include "WM_api.h" #include "WM_types.h" +#include "UI_view2d.h" + #include "logic_intern.h" // temporary new includes for texface functions @@ -421,6 +423,10 @@ static int controller_add_exec(bContext *C, wmOperator *op) ob->scaflag |= OB_SHOWCONT; WM_event_add_notifier(C, NC_LOGIC, NULL); + + /* prevent the operator to get stuck with the "object" of the previous call - + * it only happens when it's called from the "smart controller", see bug #54102 */ + RNA_string_set(op->ptr, "object", ""); return OPERATOR_FINISHED; } @@ -723,6 +729,39 @@ static void LOGIC_OT_texface_convert(wmOperatorType *ot) } +/* ************************ view ********************* */ + +static int logic_view_all_exec(bContext *C, wmOperator *UNUSED(op)) +{ + ARegion *ar = CTX_wm_region(C); + rctf cur_new = ar->v2d.tot; + float aspect = BLI_rctf_size_y(&ar->v2d.cur) / BLI_rctf_size_x(&ar->v2d.cur); + + /* force the view2d code to zoom to width, not height */ + cur_new.ymin = cur_new.ymax - BLI_rctf_size_x(&cur_new) * aspect; + + UI_view2d_smooth_view(C, ar, &cur_new); + + return OPERATOR_FINISHED; +} + +static void LOGIC_OT_view_all(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "View All"; + ot->idname = "LOGIC_OT_view_all"; + ot->description = "Resize view so you can see all logic bricks"; + + /* api callbacks */ + ot->exec = logic_view_all_exec; + ot->poll = ED_operator_logic_active; + + /* flags */ + ot->flag = 0; +} + +/* ************************* */ + void ED_operatortypes_logic(void) { WM_operatortype_append(LOGIC_OT_sensor_remove); @@ -735,4 +774,5 @@ void ED_operatortypes_logic(void) WM_operatortype_append(LOGIC_OT_actuator_add); WM_operatortype_append(LOGIC_OT_actuator_move); WM_operatortype_append(LOGIC_OT_texface_convert); + WM_operatortype_append(LOGIC_OT_view_all); } diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c index a7599f21ad5..f46151fd33a 100644 --- a/source/blender/editors/space_logic/logic_window.c +++ b/source/blender/editors/space_logic/logic_window.c @@ -2226,6 +2226,7 @@ void logic_buttons(bContext *C, ARegion *ar) BLI_snprintf(uiblockstr, sizeof(uiblockstr), "buttonswin %p", (void *)ar); block= uiBeginBlock(C, ar, uiblockstr, UI_EMBOSS); uiBlockSetHandleFunc(block, do_logic_buts, NULL); + uiBoundsBlock(block, U.widget_unit/2); /* loop over all objects and set visible/linked flags for the logic bricks */ for (a=0; a<count; a++) { @@ -2516,7 +2517,7 @@ void logic_buttons(bContext *C, ARegion *ar) uiBlockLayoutResolve(block, NULL, &yco); /* stores final height in yco */ height = MIN2(height, yco); - UI_view2d_totRect_set(&ar->v2d, 57.5f * U.widget_unit, height); + UI_view2d_totRect_set(&ar->v2d, 57.5f * U.widget_unit, height - U.widget_unit); /* set the view */ UI_view2d_view_ortho(&ar->v2d); diff --git a/source/blender/editors/space_logic/space_logic.c b/source/blender/editors/space_logic/space_logic.c index 8795d655e77..3f3c81f2bfa 100644 --- a/source/blender/editors/space_logic/space_logic.c +++ b/source/blender/editors/space_logic/space_logic.c @@ -183,7 +183,7 @@ static void logic_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "LOGIC_OT_links_cut", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); WM_keymap_add_menu(keymap, "LOGIC_MT_logicbricks_add", AKEY, KM_PRESS, KM_SHIFT, 0); - WM_keymap_add_item(keymap, "VIEW2D_OT_reset", HOMEKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "LOGIC_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); } diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 0c89e3ecbcf..acfb4a51b14 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -874,7 +874,7 @@ static void draw_nla_channel_list_gl(bAnimContext *ac, ListBase *anim_data, View glVertex2f((float)v2d->cur.xmax - offset - 1, y + 0.45f * U.widget_unit); glVertex2f((float)v2d->cur.xmax - 1, y + 0.45f * U.widget_unit); glVertex2f((float)v2d->cur.xmax - 1, y - 0.35f * U.widget_unit); - glEnd(); // GL_LINES + glEnd(); /* 'push down' icon for normal active-actions */ UI_icon_draw((float)v2d->cur.xmax - offset, ydatac, ICON_FREEZE); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 981a1775b51..cca1858f112 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1121,8 +1121,10 @@ static void node_update_reroute(const bContext *UNUSED(C), bNodeTree *UNUSED(ntr static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(snode), bNodeTree *ntree, bNode *node) { bNodeSocket *sock; -#if 0 /* UNUSED */ + char showname[128]; /* 128 used below */ rctf *rct = &node->totr; + +#if 0 /* UNUSED */ float size = NODE_REROUTE_SIZE; #endif float socket_size = NODE_SOCKSIZE; @@ -1163,6 +1165,15 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED( } #endif + if (node->label[0] != '\0') { + /* draw title (node label) */ + BLI_strncpy(showname, node->label, sizeof(showname)); + uiDefBut(node->block, LABEL, 0, showname, + (int)(rct->xmin - NODE_DYS), (int)(rct->ymax), + (short)512, (short)NODE_DY, + NULL, 0, 0, 0, 0, NULL); + } + /* only draw input socket. as they all are placed on the same position. * highlight also if node itself is selected, since we don't display the node body separately! */ diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index e1d5e4200b8..d5d2ace6fa7 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -454,8 +454,8 @@ static void node_update_hidden(bNode *node) for (nsock = node->outputs.first; nsock; nsock = nsock->next) { if (!nodeSocketIsHidden(nsock)) { - nsock->locx = node->totr.xmax - hiddenrad + (float)sin(rad) * hiddenrad; - nsock->locy = node->totr.ymin + hiddenrad + (float)cos(rad) * hiddenrad; + nsock->locx = node->totr.xmax - hiddenrad + sinf(rad) * hiddenrad; + nsock->locy = node->totr.ymin + hiddenrad + cosf(rad) * hiddenrad; rad += drad; } } @@ -465,8 +465,8 @@ static void node_update_hidden(bNode *node) for (nsock = node->inputs.first; nsock; nsock = nsock->next) { if (!nodeSocketIsHidden(nsock)) { - nsock->locx = node->totr.xmin + hiddenrad + (float)sin(rad) * hiddenrad; - nsock->locy = node->totr.ymin + hiddenrad + (float)cos(rad) * hiddenrad; + nsock->locx = node->totr.xmin + hiddenrad + sinf(rad) * hiddenrad; + nsock->locy = node->totr.ymin + hiddenrad + cosf(rad) * hiddenrad; rad += drad; } } @@ -501,21 +501,18 @@ int node_tweak_area_default(bNode *node, int x, int y) int node_get_colorid(bNode *node) { - if (node->typeinfo->nclass == NODE_CLASS_INPUT) - return TH_NODE_IN_OUT; - if (node->typeinfo->nclass == NODE_CLASS_OUTPUT) { - if (node->flag & NODE_DO_OUTPUT) - return TH_NODE_IN_OUT; - else - return TH_NODE; + switch (node->typeinfo->nclass) { + case NODE_CLASS_INPUT: return TH_NODE_IN_OUT; + case NODE_CLASS_OUTPUT: return (node->flag & NODE_DO_OUTPUT) ? TH_NODE_IN_OUT : TH_NODE; + case NODE_CLASS_CONVERTOR: return TH_NODE_CONVERTOR; + case NODE_CLASS_OP_COLOR: + case NODE_CLASS_OP_VECTOR: + case NODE_CLASS_OP_FILTER: return TH_NODE_OPERATOR; + case NODE_CLASS_GROUP: return TH_NODE_GROUP; + case NODE_CLASS_MATTE: return TH_NODE_MATTE; + case NODE_CLASS_DISTORT: return TH_NODE_DISTORT; + default: return TH_NODE; } - if (node->typeinfo->nclass == NODE_CLASS_CONVERTOR) - return TH_NODE_CONVERTOR; - if (ELEM3(node->typeinfo->nclass, NODE_CLASS_OP_COLOR, NODE_CLASS_OP_VECTOR, NODE_CLASS_OP_FILTER)) - return TH_NODE_OPERATOR; - if (node->typeinfo->nclass == NODE_CLASS_GROUP) - return TH_NODE_GROUP; - return TH_NODE; } /* note: in cmp_util.c is similar code, for node_compo_pass_on() @@ -704,6 +701,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN if (node->flag & NODE_MUTED) UI_ThemeColorBlend(color_id, TH_REDALERT, 0.5f); + #ifdef WITH_COMPOSITOR if (ntree->type == NTREE_COMPOSIT && (snode->flag & SNODE_SHOW_HIGHLIGHT)) { @@ -798,6 +796,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN /* outline active and selected emphasis */ if (node->flag & SELECT) { + glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); @@ -805,6 +804,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -40); else UI_ThemeColorShadeAlpha(TH_SELECT, 0, -40); + uiSetRoundBox(UI_CNR_ALL); uiDrawBox(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD); diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index ae95d9ae074..2fae92d674c 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -550,6 +550,12 @@ void snode_set_context(SpaceNode *snode, Scene *scene) snode->id = snode->from = NULL; if (snode->treetype == NTREE_SHADER) { + /* we use this to signal warnings, when node shaders are drawn in wrong render engine */ + if (BKE_scene_use_new_shading_nodes(scene)) + snode->flag |= SNODE_NEW_SHADERS; + else + snode->flag &= ~SNODE_NEW_SHADERS; + /* need active object, or we allow pinning... */ if (snode->shaderfrom == SNODE_SHADER_OBJECT) { if (ob) { diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index a3efa15c54a..7d2b80d50ba 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -30,14 +30,14 @@ #include "DNA_node_types.h" -#include "BKE_context.h" -#include "BKE_main.h" -#include "BKE_node.h" - #include "BLI_rect.h" #include "BLI_lasso.h" #include "BLI_utildefines.h" +#include "BKE_context.h" +#include "BKE_main.h" +#include "BKE_node.h" + #include "ED_node.h" /* own include */ #include "ED_screen.h" #include "ED_types.h" diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 1a058104c78..b64019b01be 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -1066,7 +1066,8 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto UI_icon_draw(x, y, ICON_MOD_SKIN); break; case eModifierType_Triangulate: UI_icon_draw(x, y, ICON_MOD_TRIANGULATE); break; - + case eModifierType_MeshCache: + UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */ /* Default */ case eModifierType_None: case eModifierType_ShapeKey: diff --git a/source/blender/editors/space_text/CMakeLists.txt b/source/blender/editors/space_text/CMakeLists.txt index a33a9abada1..1a6b8eaa753 100644 --- a/source/blender/editors/space_text/CMakeLists.txt +++ b/source/blender/editors/space_text/CMakeLists.txt @@ -39,6 +39,7 @@ set(SRC text_autocomplete.c text_draw.c text_format.c + text_format_lua.c text_format_osl.c text_format_py.c text_header.c diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index fa3eefcc0f7..ff9d1329721 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -232,6 +232,12 @@ static void text_keymap(struct wmKeyConfig *keyconf) wmKeyMap *keymap; wmKeyMapItem *kmi; + keymap = WM_keymap_find(keyconf, "Text Generic", SPACE_TEXT, 0); + WM_keymap_add_item(keymap, "TEXT_OT_properties", FKEY, KM_PRESS, KM_CTRL, 0); +#ifdef __APPLE__ + WM_keymap_add_item(keymap, "TEXT_OT_properties", FKEY, KM_PRESS, KM_OSKEY, 0); +#endif + keymap = WM_keymap_find(keyconf, "Text", SPACE_TEXT, 0); #ifdef __APPLE__ @@ -256,7 +262,6 @@ static void text_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "TEXT_OT_cut", XKEY, KM_PRESS, KM_OSKEY, 0); WM_keymap_add_item(keymap, "TEXT_OT_copy", CKEY, KM_PRESS, KM_OSKEY, 0); WM_keymap_add_item(keymap, "TEXT_OT_paste", VKEY, KM_PRESS, KM_OSKEY, 0); - WM_keymap_add_item(keymap, "TEXT_OT_properties", FKEY, KM_PRESS, KM_OSKEY, 0); WM_keymap_add_item(keymap, "TEXT_OT_find_set_selected", EKEY, KM_PRESS, KM_OSKEY, 0); WM_keymap_add_item(keymap, "TEXT_OT_find", GKEY, KM_PRESS, KM_OSKEY, 0); WM_keymap_add_item(keymap, "TEXT_OT_select_all", AKEY, KM_PRESS, KM_OSKEY, 0); @@ -305,7 +310,6 @@ static void text_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "TEXT_OT_jump", JKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "TEXT_OT_find", GKEY, KM_PRESS, KM_CTRL, 0); - WM_keymap_add_item(keymap, "TEXT_OT_properties", FKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "TEXT_OT_replace", HKEY, KM_PRESS, KM_CTRL, 0); kmi = WM_keymap_add_item(keymap, "TEXT_OT_to_3d_object", MKEY, KM_PRESS, KM_ALT, 0); @@ -413,6 +417,8 @@ static void text_main_area_init(wmWindowManager *wm, ARegion *ar) UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy); /* own keymap */ + keymap = WM_keymap_find(wm->defaultconf, "Text Generic", SPACE_TEXT, 0); + WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); keymap = WM_keymap_find(wm->defaultconf, "Text", SPACE_TEXT, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); @@ -496,6 +502,11 @@ static void text_header_area_draw(const bContext *C, ARegion *ar) /* add handlers, stuff you only do once or on area/region changes */ static void text_properties_area_init(wmWindowManager *wm, ARegion *ar) { + wmKeyMap *keymap; + + keymap = WM_keymap_find(wm->defaultconf, "Text Generic", SPACE_TEXT, 0); + WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); + ED_region_panels_init(wm, ar); } @@ -560,5 +571,6 @@ void ED_spacetype_text(void) /* register formatters */ ED_text_format_register_py(); ED_text_format_register_osl(); + ED_text_format_register_lua(); } diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c index e406a1b7166..94977fc5f0f 100644 --- a/source/blender/editors/space_text/text_autocomplete.c +++ b/source/blender/editors/space_text/text_autocomplete.c @@ -167,7 +167,7 @@ static GHash *text_autocomplete_build(Text *text) while (i_start < linep->len) { /* seek identifier beginning */ - while (i_start < linep->len && !text_check_identifier(linep->line[i_start])) { + while (i_start < linep->len && !text_check_identifier_nodigit(linep->line[i_start])) { i_start++; } i_end = i_start; @@ -175,7 +175,11 @@ static GHash *text_autocomplete_build(Text *text) i_end++; } - if (i_start != i_end) { + if ((i_start != i_end) && + /* check we're at the beginning of a line or that the previous char is not an identifier + * this prevents digits from being added */ + ((i_start < 1) || !text_check_identifier(linep->line[i_start - 1]))) + { char *str_sub = &linep->line[i_start]; const int choice_len = i_end - i_start; diff --git a/source/blender/editors/space_text/text_format.c b/source/blender/editors/space_text/text_format.c index 294f94dd4b7..a8c2de193c4 100644 --- a/source/blender/editors/space_text/text_format.c +++ b/source/blender/editors/space_text/text_format.c @@ -140,6 +140,54 @@ int text_check_format_len(TextLine *line, unsigned int len) return 1; } +/** + * Fill the string with formatting constant, + * advancing \a str_p and \a fmt_p + * + * \param len length in bytes + */ +void text_format_fill(const char **str_p, char **fmt_p, const char type, const int len) +{ + const char *str = *str_p; + char *fmt = *fmt_p; + int i = 0; + + while (i < len) { + const int size = BLI_str_utf8_size_safe(str); + *fmt++ = type; + + str += size; + i += size; + } + + str--; + fmt--; + + BLI_assert(*str != '\0'); + + *str_p = str; + *fmt_p = fmt; +} +/** + * ascii version of #text_format_fill, + * use when we no the text being stepped over is ascii (as is the case for most keywords) + */ +void text_format_fill_ascii(const char **str_p, char **fmt_p, const char type, const int len) +{ + const char *str = *str_p; + char *fmt = *fmt_p; + + memset(fmt, type, len); + + str += len - 1; + fmt += len - 1; + + BLI_assert(*str != '\0'); + + *str_p = str; + *fmt_p = fmt; +} + /* *** Registration *** */ static ListBase tft_lb = {NULL, NULL}; void ED_text_format_register(TextFormatType *tft) @@ -149,14 +197,31 @@ void ED_text_format_register(TextFormatType *tft) TextFormatType *ED_text_format_get(Text *text) { - /* NOTE: once more types are added we'll need to return some type based on 'text' - * for now this function is more of a placeholder */ + TextFormatType *tft; + + if (text) { + const char *text_ext = strchr(text->id.name + 2, '.'); + if (text_ext) { + text_ext++; /* skip the '.' */ + /* Check all text formats in the static list */ + for (tft = tft_lb.first; tft; tft = tft->next) { + /* All formats should have an ext, but just in case */ + const char **ext; + for (ext = tft->ext; *ext; ext++) { + /* If extension matches text name, return the matching tft */ + if (BLI_strcasecmp(text_ext, *ext) == 0) { + return tft; + } + } + } + } - /* XXX, wrong, but OK for testing */ - if (text && BLI_testextensie(text->id.name + 2, ".osl")) { - return tft_lb.last; + /* If we make it here we never found an extension that worked - return + * the "default" text format */ + return tft_lb.first; } else { + /* Return the "default" text format */ return tft_lb.first; } } diff --git a/source/blender/editors/space_text/text_format.h b/source/blender/editors/space_text/text_format.h index e593e41d42c..808311cbb62 100644 --- a/source/blender/editors/space_text/text_format.h +++ b/source/blender/editors/space_text/text_format.h @@ -49,18 +49,18 @@ enum { FMT_CONT_TRIPLE = (1 << 2), /* triplets of quotes: """ or ''' */ FMT_CONT_QUOTESINGLE_TRIPLE = (FMT_CONT_TRIPLE | FMT_CONT_QUOTESINGLE), FMT_CONT_QUOTEDOUBLE_TRIPLE = (FMT_CONT_TRIPLE | FMT_CONT_QUOTEDOUBLE), - FMT_CONT_COMMENT_C = (1 << 3), /* multi-line comments, OSL only (C style) */ - FMT_CONT_COMMENT_CXX = (1 << 4), /* single-line comments, OSL only (C++ style) */ + FMT_CONT_COMMENT_C = (1 << 3) /* multi-line comments, OSL only (C style) */ }; #define FMT_CONT_ALL \ - (FMT_CONT_QUOTESINGLE | FMT_CONT_QUOTEDOUBLE | FMT_CONT_TRIPLE | FMT_CONT_COMMENT_C | FMT_CONT_COMMENT_CXX) + (FMT_CONT_QUOTESINGLE | FMT_CONT_QUOTEDOUBLE | FMT_CONT_TRIPLE | FMT_CONT_COMMENT_C) int flatten_string(struct SpaceText *st, FlattenString *fs, const char *in); void flatten_string_free(FlattenString *fs); int flatten_string_strlen(FlattenString *fs, const char *str); int text_check_format_len(TextLine *line, unsigned int len); - +void text_format_fill(const char **str_p, char **fmt_p, const char type, const int len); +void text_format_fill_ascii(const char **str_p, char **fmt_p, const char type, const int len); /* *** Generalize Formatting *** */ typedef struct TextFormatType { @@ -101,6 +101,7 @@ void ED_text_format_register(TextFormatType *tft); /* formatters */ void ED_text_format_register_py(void); void ED_text_format_register_osl(void); +void ED_text_format_register_lua(void); #define STR_LITERAL_STARTSWITH(str, str_literal, len_var) \ (strncmp(str, str_literal, len_var = (sizeof(str_literal) - 1)) == 0) diff --git a/source/blender/editors/space_text/text_format_lua.c b/source/blender/editors/space_text/text_format_lua.c new file mode 100644 index 00000000000..6c72e043930 --- /dev/null +++ b/source/blender/editors/space_text/text_format_lua.c @@ -0,0 +1,318 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * GNU General Public License for more details. + * + * 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. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_text/text_format_lua.c + * \ingroup sptext + */ + +#include <string.h> + +#include "BLI_blenlib.h" + +#include "DNA_text_types.h" +#include "DNA_space_types.h" + +#include "BKE_text.h" + +#include "text_format.h" + +/* *** Lua Keywords (for format_line) *** */ + +/* Checks the specified source string for a Lua keyword (minus boolean & 'nil'). + * This name must start at the beginning of the source string and must be + * followed by a non-identifier (see text_check_identifier(char)) or null char. + * + * If a keyword is found, the length of the matching word is returned. + * Otherwise, -1 is returned. + * + * See: + * http://www.lua.org/manual/5.1/manual.html#2.1 + */ + +static int txtfmt_lua_find_keyword(const char *string) +{ + int i, len; + + if (STR_LITERAL_STARTSWITH(string, "and", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "break", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "do", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "else", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "elseif", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "end", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "for", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "function", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "if", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "in", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "local", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "not", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "or", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "repeat", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "return", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "then", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "until", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "while", len)) i = len; + else i = 0; + + /* If next source char is an identifier (eg. 'i' in "definate") no match */ + if (i == 0 || text_check_identifier(string[i])) + return -1; + return i; +} + +/* Checks the specified source string for a Lua special name/function. This + * name must start at the beginning of the source string and must be followed + * by a non-identifier (see text_check_identifier(char)) or null character. + * + * If a special name is found, the length of the matching name is returned. + * Otherwise, -1 is returned. + * + * See: + * http://www.lua.org/manual/5.1/manual.html#5.1 + */ + +static int txtfmt_lua_find_specialvar(const char *string) +{ + int i, len; + + if (STR_LITERAL_STARTSWITH(string, "assert", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "collectgarbage", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "dofile", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "error", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "_G", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "getfenv", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "getmetatable", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "__index", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "ipairs", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "load", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "loadfile", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "loadstring", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "next", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "pairs", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "pcall", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "print", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "rawequal", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "rawget", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "rawset", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "select", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "setfenv", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "setmetatable", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "tonumber", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "tostring", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "type", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "unpack", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "_VERSION", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "xpcall", len)) i = len; + else i = 0; + + /* If next source char is an identifier (eg. 'i' in "definate") no match */ + if (i == 0 || text_check_identifier(string[i])) + return -1; + return i; +} + +static int txtfmt_lua_find_bool(const char *string) +{ + int i, len; + + if (STR_LITERAL_STARTSWITH(string, "nil", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "true", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "false", len)) i = len; + else i = 0; + + /* If next source char is an identifier (eg. 'i' in "Nonetheless") no match */ + if (i == 0 || text_check_identifier(string[i])) + return -1; + return i; +} + +static char txtfmt_lua_format_identifier(const char *str) +{ + char fmt; + if ((txtfmt_lua_find_specialvar(str)) != -1) fmt = FMT_TYPE_SPECIAL; + else if ((txtfmt_lua_find_keyword(str)) != -1) fmt = FMT_TYPE_KEYWORD; + else fmt = FMT_TYPE_DEFAULT; + return fmt; +} + +static void txtfmt_lua_format_line(SpaceText *st, TextLine *line, const int do_next) +{ + FlattenString fs; + const char *str; + char *fmt; + char cont_orig, cont, find, prev = ' '; + int len, i; + + /* Get continuation from previous line */ + if (line->prev && line->prev->format != NULL) { + fmt = line->prev->format; + cont = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */ + BLI_assert((FMT_CONT_ALL & cont) == cont); + } + else { + cont = FMT_CONT_NOP; + } + + /* Get original continuation from this line */ + if (line->format != NULL) { + fmt = line->format; + cont_orig = fmt[strlen(fmt) + 1]; /* Just after the null-terminator */ + BLI_assert((FMT_CONT_ALL & cont_orig) == cont_orig); + } + else { + cont_orig = 0xFF; + } + + len = flatten_string(st, &fs, line->line); + str = fs.buf; + if (!text_check_format_len(line, len)) { + flatten_string_free(&fs); + return; + } + fmt = line->format; + + while (*str) { + /* Handle escape sequences by skipping both \ and next char */ + if (*str == '\\') { + *fmt = prev; fmt++; str++; + if (*str == '\0') break; + *fmt = prev; fmt++; str += BLI_str_utf8_size_safe(str); + continue; + } + /* Handle continuations */ + else if (cont) { + /* Multi-line comments */ + if (cont & FMT_CONT_COMMENT_C) { + if (*str == ']' && *(str + 1) == ']') { + *fmt = FMT_TYPE_COMMENT; fmt++; str++; + *fmt = FMT_TYPE_COMMENT; + cont = FMT_CONT_NOP; + } + else { + *fmt = FMT_TYPE_COMMENT; + } + /* Handle other comments */ + } + else { + find = (cont & FMT_CONT_QUOTEDOUBLE) ? '"' : '\''; + if (*str == find) cont = 0; + *fmt = FMT_TYPE_STRING; + } + + str += BLI_str_utf8_size_safe(str) - 1; + } + /* Not in a string... */ + else { + /* Multi-line comments */ + if (*str == '-' && *(str + 1) == '-' && + *(str + 2) == '[' && *(str + 3) == '[') + { + cont = FMT_CONT_COMMENT_C; + *fmt = FMT_TYPE_COMMENT; fmt++; str++; + *fmt = FMT_TYPE_COMMENT; fmt++; str++; + *fmt = FMT_TYPE_COMMENT; fmt++; str++; + *fmt = FMT_TYPE_COMMENT; + } + /* Single line comment */ + else if (*str == '-' && *(str + 1) == '-') { + text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(str - fs.buf)); + } + else if (*str == '"' || *str == '\'') { + /* Strings */ + find = *str; + cont = (*str == '"') ? FMT_CONT_QUOTEDOUBLE : FMT_CONT_QUOTESINGLE; + *fmt = FMT_TYPE_STRING; + } + /* Whitespace (all ws. has been converted to spaces) */ + else if (*str == ' ') { + *fmt = FMT_TYPE_WHITESPACE; + } + /* Numbers (digits not part of an identifier and periods followed by digits) */ + else if ((prev != FMT_TYPE_DEFAULT && text_check_digit(*str)) || + (*str == '.' && text_check_digit(*(str + 1)))) + { + *fmt = FMT_TYPE_NUMERAL; + } + /* Booleans */ + else if (prev != FMT_TYPE_DEFAULT && (i = txtfmt_lua_find_bool(str)) != -1) { + if (i > 0) { + text_format_fill_ascii(&str, &fmt, FMT_TYPE_NUMERAL, i); + } + else { + str += BLI_str_utf8_size_safe(str) - 1; + *fmt = FMT_TYPE_DEFAULT; + } + } + /* Punctuation */ + else if ((*str != '#') && text_check_delim(*str)) { + *fmt = FMT_TYPE_SYMBOL; + } + /* Identifiers and other text (no previous ws. or delims. so text continues) */ + else if (prev == FMT_TYPE_DEFAULT) { + str += BLI_str_utf8_size_safe(str) - 1; + *fmt = FMT_TYPE_DEFAULT; + } + /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */ + else { + /* Special vars(v) or built-in keywords(b) */ + /* keep in sync with 'txtfmt_osl_format_identifier()' */ + if ((i = txtfmt_lua_find_specialvar(str)) != -1) prev = FMT_TYPE_SPECIAL; + else if ((i = txtfmt_lua_find_keyword(str)) != -1) prev = FMT_TYPE_KEYWORD; + + if (i > 0) { + text_format_fill_ascii(&str, &fmt, prev, i); + } + else { + str += BLI_str_utf8_size_safe(str) - 1; + *fmt = FMT_TYPE_DEFAULT; + } + } + } + prev = *fmt; fmt++; str++; + } + + /* Terminate and add continuation char */ + *fmt = '\0'; fmt++; + *fmt = cont; + + /* If continuation has changed and we're allowed, process the next line */ + if (cont != cont_orig && do_next && line->next) { + txtfmt_lua_format_line(st, line->next, do_next); + } + + flatten_string_free(&fs); +} + +void ED_text_format_register_lua(void) +{ + static TextFormatType tft = {0}; + static const char *ext[] = {"lua", NULL}; + + tft.format_identifier = txtfmt_lua_format_identifier; + tft.format_line = txtfmt_lua_format_line; + tft.ext = ext; + + ED_text_format_register(&tft); +} diff --git a/source/blender/editors/space_text/text_format_osl.c b/source/blender/editors/space_text/text_format_osl.c index 3120e88163e..7d493eb1f62 100644 --- a/source/blender/editors/space_text/text_format_osl.c +++ b/source/blender/editors/space_text/text_format_osl.c @@ -228,10 +228,7 @@ static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const int do_n /* Handle continuations */ else if (cont) { /* C-Style comments */ - if (cont & FMT_CONT_COMMENT_CXX) { - *fmt = FMT_TYPE_COMMENT; - } - else if (cont & FMT_CONT_COMMENT_C) { + if (cont & FMT_CONT_COMMENT_C) { if (*str == '*' && *(str + 1) == '/') { *fmt = FMT_TYPE_COMMENT; fmt++; str++; *fmt = FMT_TYPE_COMMENT; @@ -254,8 +251,8 @@ static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const int do_n else { /* Deal with comments first */ if (*str == '/' && *(str + 1) == '/') { - cont = FMT_CONT_COMMENT_CXX; - *fmt = FMT_TYPE_COMMENT; + /* fill the remaining line */ + text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(str - fs.buf)); } /* C-Style (multi-line) comments */ else if (*str == '/' && *(str + 1) == '*') { @@ -298,8 +295,12 @@ static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const int do_n else if ((i = txtfmt_osl_find_preprocessor(str)) != -1) prev = FMT_TYPE_DIRECTIVE; if (i > 0) { - memset(fmt, prev, i); - i--; fmt += i; str += i; + if (prev == FMT_TYPE_DIRECTIVE) { /* can contain utf8 */ + text_format_fill(&str, &fmt, prev, i); + } + else { + text_format_fill_ascii(&str, &fmt, prev, i); + } } else { str += BLI_str_utf8_size_safe(str) - 1; diff --git a/source/blender/editors/space_text/text_format_py.c b/source/blender/editors/space_text/text_format_py.c index cbccc6a770f..902d60dcb3e 100644 --- a/source/blender/editors/space_text/text_format_py.c +++ b/source/blender/editors/space_text/text_format_py.c @@ -231,9 +231,9 @@ static void txtfmt_py_format_line(SpaceText *st, TextLine *line, const int do_ne /* Not in a string... */ else { /* Deal with comments first */ - if (prev == FMT_TYPE_COMMENT || *str == '#') { - *fmt = FMT_TYPE_COMMENT; - str += BLI_str_utf8_size_safe(str) - 1; + if (*str == '#') { + /* fill the remaining line */ + text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(str - fs.buf)); } else if (*str == '"' || *str == '\'') { /* Strings */ @@ -259,8 +259,7 @@ static void txtfmt_py_format_line(SpaceText *st, TextLine *line, const int do_ne /* Booleans */ else if (prev != FMT_TYPE_DEFAULT && (i = txtfmt_py_find_bool(str)) != -1) { if (i > 0) { - memset(fmt, FMT_TYPE_NUMERAL, i); - i--; fmt += i; str += i; + text_format_fill_ascii(&str, &fmt, FMT_TYPE_NUMERAL, i); } else { str += BLI_str_utf8_size_safe(str) - 1; @@ -285,8 +284,12 @@ static void txtfmt_py_format_line(SpaceText *st, TextLine *line, const int do_ne else if ((i = txtfmt_py_find_decorator(str)) != -1) prev = FMT_TYPE_DIRECTIVE; if (i > 0) { - memset(fmt, prev, i); - i--; fmt += i; str += i; + if (prev == FMT_TYPE_DIRECTIVE) { /* can contain utf8 */ + text_format_fill(&str, &fmt, prev, i); + } + else { + text_format_fill_ascii(&str, &fmt, prev, i); + } } else { str += BLI_str_utf8_size_safe(str) - 1; diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c index 13c1938d77c..e5bd9e62c74 100644 --- a/source/blender/editors/space_time/space_time.c +++ b/source/blender/editors/space_time/space_time.c @@ -92,7 +92,7 @@ static void time_draw_sfra_efra(Scene *scene, View2D *v2d) #define CACHE_DRAW_HEIGHT 3.0f -static void time_draw_cache(SpaceTime *stime, Object *ob) +static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene) { PTCacheID *pid; ListBase pidlist; @@ -102,7 +102,7 @@ static void time_draw_cache(SpaceTime *stime, Object *ob) if (!(stime->cache_display & TIME_CACHE_DISPLAY) || (!ob)) return; - BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0); + BKE_ptcache_ids_from_object(&pidlist, ob, scene, 0); /* iterate over pointcaches on the active object, * add spacetimecache and vertex array for each */ @@ -128,6 +128,9 @@ static void time_draw_cache(SpaceTime *stime, Object *ob) case PTCACHE_TYPE_DYNAMICPAINT: if (!(stime->cache_display & TIME_CACHE_DYNAMICPAINT)) continue; break; + case PTCACHE_TYPE_RIGIDBODY: + if (!(stime->cache_display & TIME_CACHE_RIGIDBODY)) continue; + break; } if (pid->cache->cached_frames == NULL) @@ -193,6 +196,10 @@ static void time_draw_cache(SpaceTime *stime, Object *ob) col[0] = 1.0; col[1] = 0.1; col[2] = 0.75; col[3] = 0.1; break; + case PTCACHE_TYPE_RIGIDBODY: + col[0] = 1.0; col[1] = 0.6; col[2] = 0.0; + col[3] = 0.1; + break; default: BLI_assert(0); col[0] = 1.0; col[1] = 0.0; col[2] = 1.0; @@ -499,7 +506,7 @@ static void time_main_area_draw(const bContext *C, ARegion *ar) draw_markers_time(C, 0); /* caches */ - time_draw_cache(stime, obact); + time_draw_cache(stime, obact, scene); /* reset view matrix */ UI_view2d_view_restore(C); @@ -648,6 +655,7 @@ static void time_init(wmWindowManager *UNUSED(wm), ScrArea *sa) stime->cache_display |= TIME_CACHE_DISPLAY; stime->cache_display |= (TIME_CACHE_SOFTBODY | TIME_CACHE_PARTICLES); stime->cache_display |= (TIME_CACHE_CLOTH | TIME_CACHE_SMOKE | TIME_CACHE_DYNAMICPAINT); + stime->cache_display |= TIME_CACHE_RIGIDBODY; } static SpaceLink *time_duplicate(SpaceLink *sl) diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index fa72f28cc44..70e2e663b33 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -458,12 +458,15 @@ static DMDrawOption draw_mcol__set_draw_legacy(MTFace *UNUSED(tface), int has_mc return DM_DRAW_OPTION_NO_MCOL; } -static DMDrawOption draw_tface__set_draw(MTFace *UNUSED(tface), int UNUSED(has_mcol), int matnr) +static DMDrawOption draw_tface__set_draw(MTFace *tface, int UNUSED(has_mcol), int matnr) { Material *ma = give_current_material(Gtexdraw.ob, matnr + 1); if (ma && (ma->game.flag & GEMAT_INVISIBLE)) return 0; + if (tface) + set_draw_settings_cached(0, tface, ma, Gtexdraw); + /* always use color from mcol, as set in update_tface_color_layer */ return DM_DRAW_OPTION_NORMAL; } @@ -937,7 +940,8 @@ static int tex_mat_set_face_editmesh_cb(void *userData, int index) void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, DerivedMesh *dm, const int draw_flags) { - if ((!BKE_scene_use_new_shading_nodes(scene)) || (draw_flags & DRAW_MODIFIERS_PREVIEW)) { + /* if not cycles, or preview-modifiers, or drawing matcaps */ + if ((!BKE_scene_use_new_shading_nodes(scene)) || (draw_flags & DRAW_MODIFIERS_PREVIEW) || (v3d->flag2 & V3D_SHOW_SOLID_MATCAP)) { draw_mesh_textured_old(scene, v3d, rv3d, ob, dm, draw_flags); return; } diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 7ef8dc49a5d..fc8d5d26455 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -88,6 +88,7 @@ #include "ED_types.h" #include "UI_resources.h" +#include "UI_interface_icons.h" #include "WM_api.h" #include "BLF_api.h" @@ -172,17 +173,26 @@ static void ob_wire_color_blend_theme_id(const unsigned char ob_wire_col[4], con } /* this condition has been made more complex since editmode can draw textures */ -static int check_object_draw_texture(Scene *scene, View3D *v3d, int drawtype) +static bool check_object_draw_texture(Scene *scene, View3D *v3d, int drawtype) { /* texture and material draw modes */ - if (ELEM(v3d->drawtype, OB_TEXTURE, OB_MATERIAL) && drawtype > OB_SOLID) - return TRUE; + if (ELEM(v3d->drawtype, OB_TEXTURE, OB_MATERIAL) && drawtype > OB_SOLID) { + return true; + } /* textured solid */ - if (v3d->drawtype == OB_SOLID && (v3d->flag2 & V3D_SOLID_TEX) && !BKE_scene_use_new_shading_nodes(scene)) - return TRUE; + if ((v3d->drawtype == OB_SOLID) && + (v3d->flag2 & V3D_SOLID_TEX) && + (BKE_scene_use_new_shading_nodes(scene) == false)) + { + return true; + } - return FALSE; + if (v3d->flag2 & V3D_SHOW_SOLID_MATCAP) { + return true; + } + + return false; } static int check_ob_drawface_dot(Scene *sce, View3D *vd, char dt) @@ -210,7 +220,7 @@ static int check_ob_drawface_dot(Scene *sce, View3D *vd, char dt) /* check for glsl drawing */ -int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const short dt) +int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt) { if (!GPU_glsl_support()) return 0; @@ -220,6 +230,10 @@ int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const short dt) return 0; if (ob == OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT)) return 0; + + if (v3d->flag2 & V3D_SHOW_SOLID_MATCAP) + return 1; + if (BKE_scene_use_new_shading_nodes(scene)) return 0; @@ -1081,7 +1095,7 @@ static void draw_transp_spot_volume(Lamp *la, float x, float z) } static void drawlamp(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, - const short dt, const short dflag, const unsigned char ob_wire_col[4]) + const char dt, const short dflag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; const float pixsize = ED_view3d_pixel_size(rv3d, ob->obmat[3]); @@ -2677,16 +2691,21 @@ static void draw_em_measure_stats(View3D *v3d, Object *ob, BMEditMesh *em, UnitS BMFace *f; int n; -#define DRAW_EM_MEASURE_STATS_FACEAREA() \ - if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { \ - mul_v3_fl(vmid, 1.0f / (float)n); \ - if (unit->system) \ - bUnit_AsString(numstr, sizeof(numstr), \ - (double)(area * unit->scale_length), \ - 3, unit->system, B_UNIT_LENGTH, do_split, FALSE); \ - else \ - BLI_snprintf(numstr, sizeof(numstr), conv_float, area); \ - view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col); \ +#define DRAW_EM_MEASURE_STATS_FACEAREA() \ + if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { \ + mul_v3_fl(vmid, 1.0f / (float)n); \ + if (unit->system) { \ + bUnit_AsString(numstr, sizeof(numstr), \ + (double)(area * unit->scale_length * unit->scale_length), \ + 3, unit->system, B_UNIT_AREA, do_split, FALSE); \ + view3d_cached_text_draw_add(vmid, numstr, 0, \ + /* Metric system uses unicode "squared" sign! */ \ + txt_flag ^ V3D_CACHE_TEXT_ASCII, col); \ + } \ + else { \ + BLI_snprintf(numstr, sizeof(numstr), conv_float, area); \ + view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col); \ + } \ } (void)0 UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col); @@ -2858,7 +2877,7 @@ static DMDrawOption draw_em_fancy__setGLSLFaceOpts(void *userData, int index) } static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, - Object *ob, BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, const short dt) + Object *ob, BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, const char dt) { Mesh *me = ob->data; @@ -3094,7 +3113,7 @@ static void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm) } static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, - const short dt, const unsigned char ob_wire_col[4], const short dflag) + const char dt, const unsigned char ob_wire_col[4], const short dflag) { Object *ob = base->object; Mesh *me = ob->data; @@ -3303,7 +3322,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */ } - dm->drawEdges(dm, (dt == OB_WIRE || totface == 0), me->drawflag & ME_ALLEDGES); + dm->drawEdges(dm, (dt == OB_WIRE || totface == 0), (ob->dtx & OB_DRAW_ALL_EDGES)); if (dt != OB_WIRE && (draw_wire == OBDRAW_WIRE_ON_DEPTH)) { glDepthMask(1); @@ -3329,7 +3348,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D /* returns 1 if nothing was drawn, for detecting to draw an object center */ static int draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base, - const short dt, const unsigned char ob_wire_col[4], const short dflag) + const char dt, const unsigned char ob_wire_col[4], const short dflag) { Object *ob = base->object; Object *obedit = scene->obedit; @@ -3651,7 +3670,7 @@ static void drawCurveDMWired(Object *ob) } /* return 1 when nothing was drawn */ -static int drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, const short dt) +static int drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, const char dt) { Object *ob = base->object; DerivedMesh *dm = ob->derivedFinal; @@ -3687,7 +3706,7 @@ static int drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, B * \return 1 when nothing was drawn */ static int drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, - const short dt, const short dflag, const unsigned char ob_wire_col[4]) + const char dt, const short dflag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; ListBase *lb = NULL; @@ -3813,7 +3832,7 @@ static int drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d return FALSE; } static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, - const short dt, const short dflag, const unsigned char ob_wire_col[4]) + const char dt, const short dflag, const unsigned char ob_wire_col[4]) { int retval; @@ -4977,9 +4996,9 @@ static void ob_draw_RE_motion(float com[3], float rotscale[3][3], float itw, flo glEnd(); } -/*place to add drawers */ +/* place to add drawers */ -static void tekenhandlesN(Nurb *nu, short sel, short hide_handles) +static void drawhandlesN(Nurb *nu, short sel, short hide_handles) { BezTriple *bezt; float *fp; @@ -5039,7 +5058,7 @@ static void tekenhandlesN(Nurb *nu, short sel, short hide_handles) glEnd(); } -static void tekenhandlesN_active(Nurb *nu) +static void drawhandlesN_active(Nurb *nu) { BezTriple *bezt; float *fp; @@ -5074,7 +5093,7 @@ static void tekenhandlesN_active(Nurb *nu) glLineWidth(1); } -static void tekenvertsN(Nurb *nu, short sel, short hide_handles, void *lastsel) +static void drawvertsN(Nurb *nu, short sel, short hide_handles, void *lastsel) { BezTriple *bezt; BPoint *bp; @@ -5330,7 +5349,7 @@ static void draw_editnurb(Object *ob, Nurb *nurb, int sel) } static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb, - const short dt, const short dflag, const unsigned char ob_wire_col[4]) + const char dt, const short dflag, const unsigned char ob_wire_col[4]) { ToolSettings *ts = scene->toolsettings; Object *ob = base->object; @@ -5354,8 +5373,8 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, for (nu = nurb; nu; nu = nu->next) { if (nu->type == CU_BEZIER) { if (index == cu->actnu && !hide_handles) - tekenhandlesN_active(nu); - tekenhandlesN(nu, 0, hide_handles); + drawhandlesN_active(nu); + drawhandlesN(nu, 0, hide_handles); } index++; } @@ -5364,8 +5383,8 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, /* selected handles */ for (nu = nurb; nu; nu = nu->next) { if (nu->type == CU_BEZIER && (cu->drawflag & CU_HIDE_HANDLES) == 0) - tekenhandlesN(nu, 1, hide_handles); - tekenvertsN(nu, 0, hide_handles, NULL); + drawhandlesN(nu, 1, hide_handles); + drawvertsN(nu, 0, hide_handles, NULL); } if (v3d->zbuf) glEnable(GL_DEPTH_TEST); @@ -5416,7 +5435,7 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, if (v3d->zbuf) glDisable(GL_DEPTH_TEST); for (nu = nurb; nu; nu = nu->next) { - tekenvertsN(nu, 1, hide_handles, cu->lastsel); + drawvertsN(nu, 1, hide_handles, cu->lastsel); } if (v3d->zbuf) glEnable(GL_DEPTH_TEST); @@ -5478,39 +5497,6 @@ static void draw_empty_cone(float size) gluDeleteQuadric(qobj); } -/* draw points on curve speed handles */ -#if 0 /* XXX old animation system stuff */ -static void curve_draw_speed(Scene *scene, Object *ob) -{ - Curve *cu = ob->data; - IpoCurve *icu; - BezTriple *bezt; - float loc[4], dir[3]; - int a; - - if (cu->ipo == NULL) - return; - - icu = cu->ipo->curve.first; - if (icu == NULL || icu->totvert < 2) - return; - - glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); - bglBegin(GL_POINTS); - - for (a = 0, bezt = icu->bezt; a < icu->totvert; a++, bezt++) { - if (where_on_path(ob, bezt->vec[1][1], loc, dir)) { - UI_ThemeColor((bezt->f2 & SELECT) && ob == OBACT ? TH_VERTEX_SELECT : TH_VERTEX); - bglVertex3fv(loc); - } - } - - glPointSize(1.0); - bglEnd(); -} -#endif /* XXX old animation system stuff */ - - static void draw_textcurs(RegionView3D *rv3d, float textcurs[4][2]) { cpack(0); @@ -5614,7 +5600,7 @@ static void drawcircle_size(float size) } -/* needs fixing if non-identity matrice used */ +/* needs fixing if non-identity matrix used */ static void drawtube(const float vec[3], float radius, float height, float tmat[4][4]) { float cur[3]; @@ -5636,7 +5622,8 @@ static void drawtube(const float vec[3], float radius, float height, float tmat[ glVertex3f(cur[0], cur[1] - radius, cur[2]); glEnd(); } -/* needs fixing if non-identity matrice used */ + +/* needs fixing if non-identity matrix used */ static void drawcone(const float vec[3], float radius, float height, float tmat[4][4]) { float cur[3]; @@ -5657,9 +5644,10 @@ static void drawcone(const float vec[3], float radius, float height, float tmat[ glVertex3f(cur[0], cur[1] - radius, cur[2]); glEnd(); } + /* return TRUE if nothing was drawn */ static int drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, - const short dt, const short dflag, const unsigned char ob_wire_col[4]) + const char dt, const short dflag, const unsigned char ob_wire_col[4]) { Object *ob = base->object; MetaBall *mb; @@ -5705,7 +5693,6 @@ static int drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, } while (ml) { - /* draw radius */ if (mb->editelems) { if ((dflag & DRAW_CONSTCOLOR) == 0) { @@ -6292,6 +6279,34 @@ static void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_ r_ob_wire_col[3] = 255; } +static void draw_object_matcap_check(Scene *scene, View3D *v3d, Object *ob) +{ + /* fixed rule, active object draws as matcap */ + if (ob == OBACT) { + if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) + return; + + if (v3d->defmaterial == NULL) { + extern Material defmaterial; + + v3d->defmaterial = MEM_mallocN(sizeof(Material), "matcap material"); + *(v3d->defmaterial) = defmaterial; + v3d->defmaterial->gpumaterial.first = v3d->defmaterial->gpumaterial.last = NULL; + v3d->defmaterial->preview = NULL; + } + /* first time users */ + if (v3d->matcap_icon == 0) + v3d->matcap_icon = ICON_MATCAP_01; + + if (v3d->defmaterial->preview == NULL) + v3d->defmaterial->preview = UI_icon_to_preview(v3d->matcap_icon); + + /* signal to all material checks, gets cleared below */ + v3d->flag2 |= V3D_SHOW_SOLID_MATCAP; + } + +} + /** * main object drawing function, draws in selection * \param dflag (draw flag) can be DRAW_PICKING and/or DRAW_CONSTCOLOR, DRAW_SCENESET @@ -6308,7 +6323,9 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short unsigned char _ob_wire_col[4]; /* dont initialize this */ unsigned char *ob_wire_col = NULL; /* dont initialize this, use NULL crashes as a way to find invalid use */ int i, selstart, selend, empty_object = 0; - short dt, dtx, zbufoff = 0; + short dtx; + char dt; + short zbufoff = 0; const short is_obact = (ob == OBACT); /* only once set now, will be removed too, should become a global standard */ @@ -6379,6 +6396,10 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short dt = MIN2(dt, ob->dt); if (v3d->zbuf == 0 && dt > OB_WIRE) dt = OB_WIRE; dtx = 0; + + /* matcap check */ + if (dt == OB_SOLID && (v3d->flag2 & V3D_SOLID_MATCAP)) + draw_object_matcap_check(scene, v3d, ob); /* faceselect exception: also draw solid when (dt == wire), except in editmode */ if (is_obact && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) { @@ -6822,7 +6843,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short } if (ob->gameflag & OB_BOUNDS) { - if (ob->boundtype != ob->collision_boundtype || (dtx & OB_BOUNDBOX) == 0) { + if (ob->boundtype != ob->collision_boundtype || (dtx & OB_DRAWBOUNDOX) == 0) { setlinestyle(2); draw_bounding_volume(scene, ob, ob->collision_boundtype); @@ -6836,7 +6857,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short if (dtx & OB_AXIS) { drawaxes(1.0f, OB_ARROWS); } - if (dtx & OB_BOUNDBOX) { + if (dtx & OB_DRAWBOUNDOX) { draw_bounding_volume(scene, ob, ob->boundtype); } if (dtx & OB_TEXSPACE) { @@ -6879,7 +6900,9 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* return warning, this is cached text draw */ invert_m4_m4(ob->imat, ob->obmat); view3d_cached_text_draw_end(v3d, ar, 1, NULL); - + /* return warning, clear temp flag */ + v3d->flag2 &= ~V3D_SHOW_SOLID_MATCAP; + glLoadMatrixf(rv3d->viewmat); if (zbufoff) { @@ -7319,7 +7342,7 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r if (dm) dm->release(dm); } -void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const short dt, int outline) +void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const char dt, int outline) { if (ob == NULL) return; diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 1d87895d64a..b2d58cf41de 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -32,6 +32,7 @@ #include <string.h> #include <stdio.h> +#include "DNA_material_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -42,16 +43,18 @@ #include "BLI_rand.h" #include "BLI_utildefines.h" -#include "BKE_object.h" #include "BKE_context.h" +#include "BKE_icons.h" +#include "BKE_object.h" #include "BKE_screen.h" #include "ED_space_api.h" #include "ED_screen.h" #include "ED_object.h" -#include "BIF_gl.h" +#include "GPU_material.h" +#include "BIF_gl.h" #include "WM_api.h" #include "WM_types.h" @@ -335,6 +338,14 @@ static void view3d_free(SpaceLink *sl) if (vd->localvd) MEM_freeN(vd->localvd); if (vd->properties_storage) MEM_freeN(vd->properties_storage); + + /* matcap material, its preview rect gets freed via icons */ + if (vd->defmaterial) { + if (vd->defmaterial->gpumaterial.first) + GPU_material_free(vd->defmaterial); + BKE_previewimg_free(&vd->defmaterial->preview); + MEM_freeN(vd->defmaterial); + } } @@ -365,6 +376,8 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl) /* copy or clear inside new stuff */ + v3dn->defmaterial = NULL; + BLI_duplicatelist(&v3dn->bgpicbase, &v3do->bgpicbase); v3dn->properties_storage = NULL; @@ -584,6 +597,9 @@ static void view3d_main_area_free(ARegion *ar) if (rv3d->depths->depths) MEM_freeN(rv3d->depths->depths); MEM_freeN(rv3d->depths); } + if (rv3d->sms) { + MEM_freeN(rv3d->sms); + } MEM_freeN(rv3d); ar->regiondata = NULL; } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 67344a9804b..ff63f16d125 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1927,7 +1927,8 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas BoundBox bb, *bb_tmp; /* use a copy because draw_object, calls clear_mesh_caches */ GLuint displist = 0; short transflag, use_displist = -1; /* -1 is initialize */ - char dt, dtx; + char dt; + short dtx; if (base->object->restrictflag & OB_RESTRICT_VIEW) return; @@ -2882,7 +2883,7 @@ static int view3d_main_area_draw_engine(const bContext *C, ARegion *ar, int draw if (!(type->view_update && type->view_draw)) return 0; - engine = RE_engine_create(type); + engine = RE_engine_create_ex(type, TRUE); engine->tile_x = scene->r.tilex; engine->tile_y = scene->r.tiley; @@ -3458,14 +3459,14 @@ static void bl_debug_draw(void) if (_bl_debug_draw_quads_tot) { int i; cpack(0x00FF0000); - glBegin(GL_LINE_LOOP); for (i = 0; i < _bl_debug_draw_quads_tot; i ++) { + glBegin(GL_LINE_LOOP); glVertex3fv(_bl_debug_draw_quads[i][0]); glVertex3fv(_bl_debug_draw_quads[i][1]); glVertex3fv(_bl_debug_draw_quads[i][2]); glVertex3fv(_bl_debug_draw_quads[i][3]); + glEnd(); } - glEnd(); } if (_bl_debug_draw_edges_tot) { int i; diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index a6daf610052..c8f0fe44433 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -119,8 +119,8 @@ void draw_motion_paths_cleanup(View3D *v3d); /* drawobject.c */ void draw_object(Scene *scene, struct ARegion *ar, View3D *v3d, Base *base, const short dflag); -int draw_glsl_material(Scene *scene, struct Object *ob, View3D *v3d, const short dt); -void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob, const short dt, int outline); +int draw_glsl_material(Scene *scene, struct Object *ob, View3D *v3d, const char dt); +void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob, const char dt, int outline); void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob); void drawaxes(float size, char drawtype); diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 615ae71cf9b..bf1c5404c0e 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -39,14 +39,14 @@ #include "DNA_space_types.h" #include "DNA_view3d_types.h" -#include "BKE_blender.h" -#include "BKE_context.h" -#include "BKE_main.h" - #include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BKE_blender.h" +#include "BKE_context.h" +#include "BKE_main.h" + #include "RNA_access.h" #include "WM_api.h" diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 41d092ce2b1..fba1ce328ba 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -111,17 +111,43 @@ float *give_cursor(Scene *scene, View3D *v3d) /* ****************** smooth view operator ****************** */ /* This operator is one of the 'timer refresh' ones like animation playback */ +struct SmoothView3DState { + float dist; + float lens; + float quat[4]; + float ofs[3]; +}; + struct SmoothView3DStore { - float orig_dist, new_dist; - float orig_lens, new_lens; - float orig_quat[4], new_quat[4]; - float orig_ofs[3], new_ofs[3]; - - int to_camera, orig_view; - + /* source*/ + struct SmoothView3DState src; /* source */ + struct SmoothView3DState dst; /* destination */ + struct SmoothView3DState org; /* original */ + + bool to_camera; + char org_view; + double time_allowed; }; +static void view3d_smooth_view_state_backup(struct SmoothView3DState *sms_state, + const View3D *v3d, const RegionView3D *rv3d) +{ + copy_v3_v3(sms_state->ofs, rv3d->ofs); + copy_qt_qt(sms_state->quat, rv3d->viewquat); + sms_state->dist = rv3d->dist; + sms_state->lens = v3d->lens; +} + +static void view3d_smooth_view_state_restore(const struct SmoothView3DState *sms_state, + View3D *v3d, RegionView3D *rv3d) +{ + copy_v3_v3(rv3d->ofs, sms_state->ofs); + copy_qt_qt(rv3d->viewquat, sms_state->quat); + rv3d->dist = sms_state->dist; + v3d->lens = sms_state->lens; +} + /* will start timer if appropriate */ /* the arguments are the desired situation */ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera, Object *camera, @@ -132,15 +158,22 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera ScrArea *sa = CTX_wm_area(C); RegionView3D *rv3d = ar->regiondata; - struct SmoothView3DStore sms = {0}; - short ok = FALSE; + struct SmoothView3DStore sms = {{0}}; + bool ok = false; /* initialize sms */ - copy_v3_v3(sms.new_ofs, rv3d->ofs); - copy_qt_qt(sms.new_quat, rv3d->viewquat); - sms.new_dist = rv3d->dist; - sms.new_lens = v3d->lens; - sms.to_camera = FALSE; + view3d_smooth_view_state_backup(&sms.dst, v3d, rv3d); + view3d_smooth_view_state_backup(&sms.src, v3d, rv3d); + /* if smoothview runs multiple times... */ + if (rv3d->sms == NULL) { + view3d_smooth_view_state_backup(&sms.org, v3d, rv3d); + sms.org_view = rv3d->view; + } + else { + sms.org = rv3d->sms->org; + sms.org_view = rv3d->sms->org_view; + } + /* sms.to_camera = false; */ /* initizlized to zero anyway */ /* note on camera locking, this is a little confusing but works ok. * we may be changing the view 'as if' there is no active camera, but in fact @@ -155,50 +188,43 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera } /* store the options we want to end with */ - if (ofs) copy_v3_v3(sms.new_ofs, ofs); - if (quat) copy_qt_qt(sms.new_quat, quat); - if (dist) sms.new_dist = *dist; - if (lens) sms.new_lens = *lens; + if (ofs) copy_v3_v3(sms.dst.ofs, ofs); + if (quat) copy_qt_qt(sms.dst.quat, quat); + if (dist) sms.dst.dist = *dist; + if (lens) sms.dst.lens = *lens; if (camera) { - sms.new_dist = ED_view3d_offset_distance(camera->obmat, ofs, VIEW3D_DIST_FALLBACK); - ED_view3d_from_object(camera, sms.new_ofs, sms.new_quat, &sms.new_dist, &sms.new_lens); - sms.to_camera = TRUE; /* restore view3d values in end */ + sms.dst.dist = ED_view3d_offset_distance(camera->obmat, ofs, VIEW3D_DIST_FALLBACK); + ED_view3d_from_object(camera, sms.dst.ofs, sms.dst.quat, &sms.dst.dist, &sms.dst.lens); + sms.to_camera = true; /* restore view3d values in end */ } if (C && U.smooth_viewtx) { - int changed = FALSE; /* zero means no difference */ + bool changed = false; /* zero means no difference */ if (oldcamera != camera) - changed = TRUE; - else if (sms.new_dist != rv3d->dist) - changed = TRUE; - else if (sms.new_lens != v3d->lens) - changed = TRUE; - else if (!equals_v3v3(sms.new_ofs, rv3d->ofs)) - changed = TRUE; - else if (!equals_v4v4(sms.new_quat, rv3d->viewquat)) - changed = TRUE; + changed = true; + else if (sms.dst.dist != rv3d->dist) + changed = true; + else if (sms.dst.lens != v3d->lens) + changed = true; + else if (!equals_v3v3(sms.dst.ofs, rv3d->ofs)) + changed = true; + else if (!equals_v4v4(sms.dst.quat, rv3d->viewquat)) + changed = true; /* The new view is different from the old one * so animate the view */ if (changed) { - /* original values */ if (oldcamera) { - sms.orig_dist = ED_view3d_offset_distance(oldcamera->obmat, rv3d->ofs, 0.0f); - ED_view3d_from_object(oldcamera, sms.orig_ofs, sms.orig_quat, &sms.orig_dist, &sms.orig_lens); - } - else { - copy_v3_v3(sms.orig_ofs, rv3d->ofs); - copy_qt_qt(sms.orig_quat, rv3d->viewquat); - sms.orig_dist = rv3d->dist; - sms.orig_lens = v3d->lens; + sms.src.dist = ED_view3d_offset_distance(oldcamera->obmat, rv3d->ofs, 0.0f); + /* this */ + ED_view3d_from_object(oldcamera, sms.src.ofs, sms.src.quat, &sms.src.dist, &sms.src.lens); } /* grid draw as floor */ if ((rv3d->viewlock & RV3D_LOCKED) == 0) { /* use existing if exists, means multiple calls to smooth view wont loose the original 'view' setting */ - sms.orig_view = rv3d->sms ? rv3d->sms->orig_view : rv3d->view; rv3d->view = RV3D_VIEW_USER; } @@ -212,8 +238,8 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera float vec1[3] = {0, 0, 1}, vec2[3] = {0, 0, 1}; float q1[4], q2[4]; - invert_qt_qt(q1, sms.new_quat); - invert_qt_qt(q2, sms.orig_quat); + invert_qt_qt(q1, sms.dst.quat); + invert_qt_qt(q2, sms.src.quat); mul_qt_v3(q1, vec1); mul_qt_v3(q2, vec2); @@ -223,36 +249,45 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera } /* ensure it shows correct */ - if (sms.to_camera) rv3d->persp = RV3D_PERSP; + if (sms.to_camera) { + rv3d->persp = RV3D_PERSP; + } rv3d->rflag |= RV3D_NAVIGATING; + /* not essential but in some cases the caller will tag the area for redraw, + * and in that case we can get a ficker of the 'org' user view but we want to see 'src' */ + view3d_smooth_view_state_restore(&sms.src, v3d, rv3d); + /* keep track of running timer! */ - if (rv3d->sms == NULL) + if (rv3d->sms == NULL) { rv3d->sms = MEM_mallocN(sizeof(struct SmoothView3DStore), "smoothview v3d"); + } *rv3d->sms = sms; - if (rv3d->smooth_timer) + if (rv3d->smooth_timer) { WM_event_remove_timer(wm, win, rv3d->smooth_timer); + } /* TIMER1 is hardcoded in keymap */ rv3d->smooth_timer = WM_event_add_timer(wm, win, TIMER1, 1.0 / 100.0); /* max 30 frs/sec */ - - ok = TRUE; + + ok = true; } } /* if we get here nothing happens */ - if (ok == FALSE) { - if (sms.to_camera == FALSE) { - copy_v3_v3(rv3d->ofs, sms.new_ofs); - copy_qt_qt(rv3d->viewquat, sms.new_quat); - rv3d->dist = sms.new_dist; - v3d->lens = sms.new_lens; + if (ok == false) { + if (sms.to_camera == false) { + copy_v3_v3(rv3d->ofs, sms.dst.ofs); + copy_qt_qt(rv3d->viewquat, sms.dst.quat); + rv3d->dist = sms.dst.dist; + v3d->lens = sms.dst.lens; ED_view3d_camera_lock_sync(v3d, rv3d); } - if (rv3d->viewlock & RV3D_BOXVIEW) + if (rv3d->viewlock & RV3D_BOXVIEW) { view3d_boxview_copy(sa, ar); + } ED_region_tag_redraw(ar); } @@ -281,22 +316,16 @@ static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent /* if we went to camera, store the original */ if (sms->to_camera) { rv3d->persp = RV3D_CAMOB; - copy_v3_v3(rv3d->ofs, sms->orig_ofs); - copy_qt_qt(rv3d->viewquat, sms->orig_quat); - rv3d->dist = sms->orig_dist; - v3d->lens = sms->orig_lens; + view3d_smooth_view_state_restore(&sms->org, v3d, rv3d); } else { - copy_v3_v3(rv3d->ofs, sms->new_ofs); - copy_qt_qt(rv3d->viewquat, sms->new_quat); - rv3d->dist = sms->new_dist; - v3d->lens = sms->new_lens; + view3d_smooth_view_state_restore(&sms->dst, v3d, rv3d); ED_view3d_camera_lock_sync(v3d, rv3d); } if ((rv3d->viewlock & RV3D_LOCKED) == 0) { - rv3d->view = sms->orig_view; + rv3d->view = sms->org_view; } MEM_freeN(rv3d->sms); @@ -312,11 +341,11 @@ static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent step_inv = 1.0f - step; - interp_v3_v3v3(rv3d->ofs, sms->orig_ofs, sms->new_ofs, step); - interp_qt_qtqt(rv3d->viewquat, sms->orig_quat, sms->new_quat, step); + interp_v3_v3v3(rv3d->ofs, sms->src.ofs, sms->dst.ofs, step); + interp_qt_qtqt(rv3d->viewquat, sms->src.quat, sms->dst.quat, step); - rv3d->dist = sms->new_dist * step + sms->orig_dist * step_inv; - v3d->lens = sms->new_lens * step + sms->orig_lens * step_inv; + rv3d->dist = sms->dst.dist * step + sms->src.dist * step_inv; + v3d->lens = sms->dst.lens * step + sms->src.lens * step_inv; ED_view3d_camera_lock_sync(v3d, rv3d); } @@ -325,12 +354,16 @@ static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent view3d_boxview_copy(CTX_wm_area(C), CTX_wm_region(C)); /* note: this doesn't work right because the v3d->lens is now used in ortho mode r51636, - * when switching camera in quad-view the other ortho views would zoom & reset. */ -#if 0 - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); -#else - ED_region_tag_redraw(CTX_wm_region(C)); -#endif + * when switching camera in quad-view the other ortho views would zoom & reset. + * + * For now only redraw all regions when smoothview finishes. + */ + if (step >= 1.0f) { + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); + } + else { + ED_region_tag_redraw(CTX_wm_region(C)); + } return OPERATOR_FINISHED; } @@ -846,7 +879,8 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b ARegion *ar = vc->ar; rctf rect; short code, hits; - char dt, dtx; + char dt; + short dtx; G.f |= G_PICKSEL; diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 5b5e5206e9c..d29326db6b0 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -52,12 +52,14 @@ #include "DNA_movieclip_types.h" #include "DNA_scene_types.h" /* PET modes */ -#include "RNA_access.h" - -#include "BIF_gl.h" -#include "BIF_glutil.h" - -#include "BLF_api.h" +#include "BLI_utildefines.h" +#include "BLI_math.h" +#include "BLI_rect.h" +#include "BLI_listbase.h" +#include "BLI_string.h" +#include "BLI_ghash.h" +#include "BLI_linklist.h" +#include "BLI_smallhash.h" #include "BKE_nla.h" #include "BKE_bmesh.h" @@ -69,6 +71,9 @@ #include "BKE_unit.h" #include "BKE_mask.h" +#include "BIF_gl.h" +#include "BIF_glutil.h" + #include "ED_image.h" #include "ED_keyframing.h" #include "ED_screen.h" @@ -79,25 +84,25 @@ #include "ED_clip.h" #include "ED_mask.h" -#include "UI_view2d.h" #include "WM_types.h" #include "WM_api.h" -#include "BLI_math.h" -#include "BLI_blenlib.h" -#include "BLI_utildefines.h" -#include "BLI_ghash.h" -#include "BLI_linklist.h" -#include "BLI_smallhash.h" -#include "BLI_array.h" - +#include "UI_view2d.h" #include "UI_interface_icons.h" #include "UI_resources.h" +#include "RNA_access.h" + +#include "BLF_api.h" + #include "transform.h" static void drawTransformApply(const struct bContext *C, ARegion *ar, void *arg); static int doEdgeSlide(TransInfo *t, float perc); +static int doVertSlide(TransInfo *t, float perc); + +static void drawEdgeSlide(const struct bContext *C, TransInfo *t); +static void drawVertSlide(const struct bContext *C, TransInfo *t); /* ************************** SPACE DEPENDANT CODE **************************** */ @@ -875,19 +880,52 @@ int transformEvent(TransInfo *t, wmEvent *event) break; case TFM_MODAL_TRANSLATE: /* only switch when... */ - if (ELEM3(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL) ) { + if (ELEM5(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) { + if (t->mode == TFM_EDGE_SLIDE) { + freeEdgeSlideVerts(t); + } + else if (t->mode == TFM_VERT_SLIDE) { + freeVertSlideVerts(t); + } resetTransRestrictions(t); restoreTransObjects(t); initTranslation(t); initSnapping(t, NULL); // need to reinit after mode change t->redraw |= TREDRAW_HARD; + WM_event_add_mousemove(t->context); } - else if (t->mode == TFM_TRANSLATION) { - if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { - restoreTransObjects(t); + else { + if (t->obedit && t->obedit->type == OB_MESH) { + if ((t->mode == TFM_TRANSLATION) && (t->spacetype == SPACE_VIEW3D)) { + resetTransRestrictions(t); + restoreTransObjects(t); - t->flag ^= T_ALT_TRANSFORM; - t->redraw |= TREDRAW_HARD; + /* first try edge slide */ + initEdgeSlide(t); + /* if that fails, do vertex slide */ + if (t->state == TRANS_CANCEL) { + t->state = TRANS_STARTING; + initVertSlide(t); + } + /* vert slide can fail on unconnected vertices (rare but possible) */ + if (t->state == TRANS_CANCEL) { + t->state = TRANS_STARTING; + resetTransRestrictions(t); + restoreTransObjects(t); + initTranslation(t); + } + initSnapping(t, NULL); // need to reinit after mode change + t->redraw |= TREDRAW_HARD; + WM_event_add_mousemove(t->context); + } + } + else if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { + if (t->mode == TFM_TRANSLATION) { + restoreTransObjects(t); + + t->flag ^= T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + } } } break; @@ -1600,7 +1638,10 @@ static void drawTransformView(const struct bContext *C, ARegion *UNUSED(ar), voi drawConstraint(t); drawPropCircle(C, t); drawSnapping(C, t); - drawNonPropEdge(C, t); + + /* edge slide, vert slide */ + drawEdgeSlide(C, t); + drawVertSlide(C, t); } /* just draw a little warning message in the top-right corner of the viewport to warn that autokeying is enabled */ @@ -1949,6 +1990,9 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int case TFM_EDGE_SLIDE: initEdgeSlide(t); break; + case TFM_VERT_SLIDE: + initVertSlide(t); + break; case TFM_BONE_ROLL: initBoneRoll(t); break; @@ -2080,12 +2124,6 @@ void transformApply(bContext *C, TransInfo *t) t->state = TRANS_CONFIRM; } - if (BKE_ptcache_get_continue_physics()) { - // TRANSFORM_FIX_ME - //do_screenhandlers(G.curscreen); - t->redraw |= TREDRAW_HARD; - } - t->context = NULL; } @@ -4902,29 +4940,43 @@ static BMLoop *get_next_loop(BMVert *v, BMLoop *l, return NULL; } -static void calcNonProportionalEdgeSlide(TransInfo *t, SlideData *sld, const float mval[2]) +static void calcNonProportionalEdgeSlide(TransInfo *t, EdgeSlideData *sld, const float mval[2]) { - TransDataSlideVert *sv = sld->sv; + TransDataEdgeSlideVert *sv = sld->sv; if (sld->totsv > 0) { + ARegion *ar = t->ar; + RegionView3D *rv3d = NULL; + float projectMat[4][4]; + int i = 0; - float v_proj[3]; + float v_proj[2]; float dist = 0; float min_dist = FLT_MAX; + if (t->spacetype == SPACE_VIEW3D) { + /* background mode support */ + rv3d = t->ar ? t->ar->regiondata : NULL; + } + + if (!rv3d) { + /* ok, let's try to survive this */ + unit_m4(projectMat); + } + else { + ED_view3d_ob_project_mat_get(rv3d, t->obedit, projectMat); + } + for (i = 0; i < sld->totsv; i++, sv++) { /* Set length */ sv->edge_len = len_v3v3(sv->upvec, sv->downvec); - mul_v3_m4v3(v_proj, t->obedit->obmat, sv->v->co); - /* allow points behind the view [#33643] */ - if (ED_view3d_project_float_global(t->ar, v_proj, v_proj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - dist = len_squared_v2v2(mval, v_proj); - if (dist < min_dist) { - min_dist = dist; - sld->curr_sv_index = i; - } + ED_view3d_project_float_v2_m4(ar, sv->v->co, v_proj, projectMat); + dist = len_squared_v2v2(mval, v_proj); + if (dist < min_dist) { + min_dist = dist; + sld->curr_sv_index = i; } } } @@ -4933,17 +4985,17 @@ static void calcNonProportionalEdgeSlide(TransInfo *t, SlideData *sld, const flo } } -static int createSlideVerts(TransInfo *t) +static int createEdgeSlideVerts(TransInfo *t) { BMEditMesh *em = BMEdit_FromObject(t->obedit); BMesh *bm = em->bm; BMIter iter; BMEdge *e, *e1; BMVert *v, *v2, *first; - TransDataSlideVert *sv_array; + TransDataEdgeSlideVert *sv_array; BMBVHTree *btree; SmallHash table; - SlideData *sld = MEM_callocN(sizeof(*sld), "sld"); + EdgeSlideData *sld = MEM_callocN(sizeof(*sld), "sld"); View3D *v3d = NULL; RegionView3D *rv3d = NULL; ARegion *ar = t->ar; @@ -5040,7 +5092,7 @@ static int createSlideVerts(TransInfo *t) return 0; } - sv_array = MEM_callocN(sizeof(TransDataSlideVert) * j, "sv_array"); + sv_array = MEM_callocN(sizeof(TransDataEdgeSlideVert) * j, "sv_array"); loop_nr = 0; j = 0; @@ -5102,7 +5154,7 @@ static int createSlideVerts(TransInfo *t) /*iterate over the loop*/ first = v; do { - TransDataSlideVert *sv = sv_array + j; + TransDataEdgeSlideVert *sv = sv_array + j; sv->v = v; sv->origvert = *v; @@ -5272,7 +5324,7 @@ static int createSlideVerts(TransInfo *t) if (rv3d) calcNonProportionalEdgeSlide(t, sld, mval); - sld->origfaces_init = TRUE; + sld->origfaces_init = true; sld->em = em; /*zero out start*/ @@ -5305,10 +5357,10 @@ static int createSlideVerts(TransInfo *t) return 1; } -void projectSVData(TransInfo *t, int final) +void projectEdgeSlideData(TransInfo *t, bool is_final) { - SlideData *sld = t->customData; - TransDataSlideVert *sv; + EdgeSlideData *sld = t->customData; + TransDataEdgeSlideVert *sv; BMEditMesh *em = sld->em; SmallHash visit; int i; @@ -5435,7 +5487,7 @@ void projectSVData(TransInfo *t, int final) * and we do not want to mess up other shape keys */ BM_loop_interp_from_face(em->bm, l, f_copy_flip, FALSE, FALSE); - if (final) { + if (is_final) { BM_loop_interp_multires(em->bm, l, f_copy_flip); if (f_copy != f_copy_flip) { BM_loop_interp_multires(em->bm, l, f_copy); @@ -5459,7 +5511,7 @@ void projectSVData(TransInfo *t, int final) BLI_smallhash_release(&visit); } -void freeSlideTempFaces(SlideData *sld) +void freeEdgeSlideTempFaces(EdgeSlideData *sld) { if (sld->origfaces_init) { SmallHashIter hiter; @@ -5472,7 +5524,7 @@ void freeSlideTempFaces(SlideData *sld) BLI_smallhash_release(&sld->origfaces); - sld->origfaces_init = FALSE; + sld->origfaces_init = false; /* arrays are dirty from removing faces: EDBM_index_arrays_free */ EDBM_update_generic(sld->em, FALSE, TRUE); @@ -5480,13 +5532,13 @@ void freeSlideTempFaces(SlideData *sld) } -void freeSlideVerts(TransInfo *t) +void freeEdgeSlideVerts(TransInfo *t) { - SlideData *sld = t->customData; + EdgeSlideData *sld = t->customData; #if 0 /*BMESH_TODO*/ if (me->drawflag & ME_DRAWEXTRA_EDGELEN) { - TransDataSlideVert *sv; + TransDataEdgeSlideVert *sv; LinkNode *look = sld->vertlist; GHash *vertgh = sld->vhash; while (look) { @@ -5503,7 +5555,7 @@ void freeSlideVerts(TransInfo *t) if (!sld) return; - freeSlideTempFaces(sld); + freeEdgeSlideTempFaces(sld); bmesh_edit_end(sld->em->bm, BMO_OP_FLAG_UNTAN_MULTIRES); @@ -5519,13 +5571,13 @@ void freeSlideVerts(TransInfo *t) void initEdgeSlide(TransInfo *t) { - SlideData *sld; + EdgeSlideData *sld; t->mode = TFM_EDGE_SLIDE; t->transform = EdgeSlide; t->handleEvent = handleEventEdgeSlide; - if (!createSlideVerts(t)) { + if (!createEdgeSlideVerts(t)) { t->state = TRANS_CANCEL; return; } @@ -5535,7 +5587,7 @@ void initEdgeSlide(TransInfo *t) if (!sld) return; - t->customFree = freeSlideVerts; + t->customFree = freeEdgeSlideVerts; /* set custom point first if you want value to be initialized by init */ setCustomPoints(t, &t->mouse, sld->end, sld->start); @@ -5555,7 +5607,7 @@ void initEdgeSlide(TransInfo *t) int handleEventEdgeSlide(struct TransInfo *t, struct wmEvent *event) { if (t->mode == TFM_EDGE_SLIDE) { - SlideData *sld = t->customData; + EdgeSlideData *sld = t->customData; if (sld) { switch (event->type) { @@ -5598,17 +5650,17 @@ int handleEventEdgeSlide(struct TransInfo *t, struct wmEvent *event) return 0; } -void drawNonPropEdge(const struct bContext *C, TransInfo *t) +void drawEdgeSlide(const struct bContext *C, TransInfo *t) { if (t->mode == TFM_EDGE_SLIDE) { - SlideData *sld = (SlideData *)t->customData; + EdgeSlideData *sld = (EdgeSlideData *)t->customData; /* Non-Prop mode */ if (sld && sld->is_proportional == FALSE) { View3D *v3d = CTX_wm_view3d(C); float marker[3]; float v1[3], v2[3]; float interp_v; - TransDataSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; + TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f; const float guide_size = ctrl_size - 0.5f; const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f; @@ -5674,8 +5726,8 @@ void drawNonPropEdge(const struct bContext *C, TransInfo *t) static int doEdgeSlide(TransInfo *t, float perc) { - SlideData *sld = t->customData; - TransDataSlideVert *svlist = sld->sv, *sv; + EdgeSlideData *sld = t->customData; + TransDataEdgeSlideVert *svlist = sld->sv, *sv; int i; sld->perc = perc; @@ -5705,7 +5757,7 @@ static int doEdgeSlide(TransInfo *t, float perc) * \note len_v3v3(curr_sv->upvec, curr_sv->downvec) * is the same as the distance between the original vert locations, same goes for the lines below. */ - TransDataSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; + TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; const float curr_length_perc = curr_sv->edge_len * (((sld->flipped_vtx ? perc : -perc) + 1.0f) / 2.0f); float down_co[3]; @@ -5728,7 +5780,7 @@ static int doEdgeSlide(TransInfo *t, float perc) } } - projectSVData(t, 0); + projectEdgeSlideData(t, 0); return 1; } @@ -5737,9 +5789,9 @@ int EdgeSlide(TransInfo *t, const int UNUSED(mval[2])) { char str[128]; float final; - SlideData *sld = t->customData; - int flipped = sld->flipped_vtx; - int is_proportional = sld->is_proportional; + EdgeSlideData *sld = t->customData; + bool flipped = sld->flipped_vtx; + bool is_proportional = sld->is_proportional; final = t->values[0]; @@ -5782,6 +5834,498 @@ int EdgeSlide(TransInfo *t, const int UNUSED(mval[2])) return 1; } + +/* ******************** Vert Slide *************** */ +static void calcVertSlideCustomPoints(struct TransInfo *t) +{ + VertSlideData *sld = t->customData; + TransDataVertSlideVert *sv = &sld->sv[sld->curr_sv_index]; + float *co_orig = sv->co_orig_2d; + float *co_curr = sv->co_link_orig_2d[sv->co_link_curr]; + float co_curr_flip[2]; + + flip_v2_v2v2(co_curr_flip, co_orig, co_curr); + + { + const int start[2] = {co_orig[0], co_orig[1]}; + const int end[2] = {co_curr_flip[0], co_curr_flip[1]}; + if (!sld->flipped_vtx) { + setCustomPoints(t, &t->mouse, end, start); + } + else { + setCustomPoints(t, &t->mouse, start, end); + } + } +} + +/** + * Run once when initializing vert slide to find the reference edge + */ +static void calcVertSlideMouseActiveVert(struct TransInfo *t, const int mval[2]) +{ + VertSlideData *sld = t->customData; + float mval_fl[2] = {UNPACK2(mval)}; + TransDataVertSlideVert *sv; + + /* set the vertex to use as a reference for the mouse direction 'curr_sv_index' */ + float dist = 0.0f; + float min_dist = FLT_MAX; + int i; + + for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) { + dist = len_squared_v2v2(mval_fl, sv->co_orig_2d); + if (dist < min_dist) { + min_dist = dist; + sld->curr_sv_index = i; + } + } +} +/** + * Run while moving the mouse to slide along the edge matching the mouse direction + */ +static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2]) +{ + VertSlideData *sld = t->customData; + float mval_fl[2] = {UNPACK2(mval)}; + + float dir[2]; + TransDataVertSlideVert *sv; + int i; + + /* first get the direction of the original vertex */ + sub_v2_v2v2(dir, sld->sv[sld->curr_sv_index].co_orig_2d, mval_fl); + normalize_v2(dir); + + for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) { + if (sv->co_link_tot > 1) { + float dir_dot_best = -FLT_MAX; + int co_link_curr_best = -1; + int j; + + for (j = 0; j < sv->co_link_tot; j++) { + float tdir[2]; + float dir_dot; + sub_v2_v2v2(tdir, sv->co_orig_2d, sv->co_link_orig_2d[j]); + normalize_v2(tdir); + dir_dot = dot_v2v2(dir, tdir); + if (dir_dot > dir_dot_best) { + dir_dot_best = dir_dot; + co_link_curr_best = j; + } + } + + if (co_link_curr_best != -1) { + sv->co_link_curr = co_link_curr_best; + } + } + } +} + +static int createVertSlideVerts(TransInfo *t) +{ + BMEditMesh *em = BMEdit_FromObject(t->obedit); + BMesh *bm = em->bm; + BMIter iter; + BMIter eiter; + BMEdge *e; + BMVert *v; + TransDataVertSlideVert *sv_array; + VertSlideData *sld = MEM_callocN(sizeof(*sld), "sld"); +// View3D *v3d = NULL; + RegionView3D *rv3d = NULL; + ARegion *ar = t->ar; + float projectMat[4][4]; + int j; + + if (t->spacetype == SPACE_VIEW3D) { + /* background mode support */ +// v3d = t->sa ? t->sa->spacedata.first : NULL; + rv3d = t->ar ? t->ar->regiondata : NULL; + } + + sld->is_proportional = true; + sld->curr_sv_index = 0; + sld->flipped_vtx = false; + + if (!rv3d) { + /* ok, let's try to survive this */ + unit_m4(projectMat); + } + else { + ED_view3d_ob_project_mat_get(rv3d, t->obedit, projectMat); + } + + j = 0; + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + bool ok = false; + if (BM_elem_flag_test(v, BM_ELEM_SELECT) && v->e) { + BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { + if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { + ok = true; + break; + } + } + } + + if (ok) { + BM_elem_flag_enable(v, BM_ELEM_TAG); + j += 1; + } + else { + BM_elem_flag_disable(v, BM_ELEM_TAG); + } + } + + if (!j) { + MEM_freeN(sld); + return 0; + } + + sv_array = MEM_callocN(sizeof(TransDataVertSlideVert) * j, "sv_array"); + + j = 0; + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_TAG)) { + int k; + sv_array[j].v = v; + copy_v3_v3(sv_array[j].co_orig_3d, v->co); + + k = 0; + BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { + if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { + k++; + } + } + + sv_array[j].co_link_orig_3d = MEM_mallocN(sizeof(*sv_array[j].co_link_orig_3d) * k, __func__); + sv_array[j].co_link_orig_2d = MEM_mallocN(sizeof(*sv_array[j].co_link_orig_2d) * k, __func__); + sv_array[j].co_link_tot = k; + + k = 0; + BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { + if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { + BMVert *v_other = BM_edge_other_vert(e, v); + copy_v3_v3(sv_array[j].co_link_orig_3d[k], v_other->co); + ED_view3d_project_float_v2_m4(ar, + sv_array[j].co_link_orig_3d[k], + sv_array[j].co_link_orig_2d[k], + projectMat); + k++; + } + } + + ED_view3d_project_float_v2_m4(ar, + sv_array[j].co_orig_3d, + sv_array[j].co_orig_2d, + projectMat); + + j++; + } + } + + sld->sv = sv_array; + sld->totsv = j; + + sld->em = em; + + sld->perc = 0.0f; + + t->customData = sld; + + if (rv3d) { + calcVertSlideMouseActiveVert(t, t->mval); + calcVertSlideMouseActiveEdges(t, t->mval); + } + + return 1; +} + +void freeVertSlideVerts(TransInfo *t) +{ + VertSlideData *sld = t->customData; + + if (!sld) + return; + + + if (sld->totsv > 0) { + TransDataVertSlideVert *sv = sld->sv; + int i = 0; + for (i = 0; i < sld->totsv; i++, sv++) { + MEM_freeN(sv->co_link_orig_2d); + MEM_freeN(sv->co_link_orig_3d); + } + } + + MEM_freeN(sld->sv); + MEM_freeN(sld); + + t->customData = NULL; + + recalcData(t); +} + +void initVertSlide(TransInfo *t) +{ + VertSlideData *sld; + + t->mode = TFM_VERT_SLIDE; + t->transform = VertSlide; + t->handleEvent = handleEventVertSlide; + + if (!createVertSlideVerts(t)) { + t->state = TRANS_CANCEL; + return; + } + + sld = t->customData; + + if (!sld) + return; + + t->customFree = freeVertSlideVerts; + + /* set custom point first if you want value to be initialized by init */ + calcVertSlideCustomPoints(t); + initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO); + + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = 0.1f; + t->snap[2] = t->snap[1] * 0.1f; + + t->num.increment = t->snap[1]; + + t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; +} + +int handleEventVertSlide(struct TransInfo *t, struct wmEvent *event) +{ + if (t->mode == TFM_VERT_SLIDE) { + VertSlideData *sld = t->customData; + + if (sld) { + switch (event->type) { + case EKEY: + if (event->val == KM_PRESS) { + sld->is_proportional = !sld->is_proportional; + return 1; + } + break; + case FKEY: + { + if (event->val == KM_PRESS) { + if (sld->is_proportional == FALSE) { + sld->flipped_vtx = !sld->flipped_vtx; + calcVertSlideCustomPoints(t); + } + return 1; + } + break; + } +#if 0 + case EVT_MODAL_MAP: + { + switch (event->val) { + case TFM_MODAL_EDGESLIDE_DOWN: + { + sld->curr_sv_index = ((sld->curr_sv_index - 1) + sld->totsv) % sld->totsv; + break; + } + case TFM_MODAL_EDGESLIDE_UP: + { + sld->curr_sv_index = (sld->curr_sv_index + 1) % sld->totsv; + break; + } + } + } +#endif + case MOUSEMOVE: + { + /* don't recalculat the best edge */ + if (!(t->flag & T_ALT_TRANSFORM)) { + calcVertSlideMouseActiveEdges(t, event->mval); + } + calcVertSlideCustomPoints(t); + } + default: + break; + } + } + } + return 0; +} + +static void drawVertSlide(const struct bContext *C, TransInfo *t) +{ + if (t->mode == TFM_VERT_SLIDE) { + VertSlideData *sld = (VertSlideData *)t->customData; + /* Non-Prop mode */ + if (sld) { + View3D *v3d = CTX_wm_view3d(C); + TransDataVertSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; + TransDataVertSlideVert *sv; + const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f; + const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f; + const int alpha_shade = -30; + int i; + bool is_constrained = !(t->flag & T_ALT_TRANSFORM); + + if (v3d && v3d->zbuf) + glDisable(GL_DEPTH_TEST); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT | GL_POINT_BIT); + glPushMatrix(); + + glMultMatrixf(t->obedit->obmat); + + glLineWidth(line_size); + UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); + glBegin(GL_LINES); + if (is_constrained) { + sv = sld->sv; + for (i = 0; i < sld->totsv; i++, sv++) { + glVertex3fv(sv->co_orig_3d); + glVertex3fv(sv->co_link_orig_3d[sv->co_link_curr]); + } + } + else { + sv = sld->sv; + for (i = 0; i < sld->totsv; i++, sv++) { + float a[3], b[3]; + sub_v3_v3v3(a, sv->co_link_orig_3d[sv->co_link_curr], sv->co_orig_3d); + mul_v3_fl(a, 100.0f); + negate_v3_v3(b, a); + add_v3_v3(a, sv->co_orig_3d); + add_v3_v3(b, sv->co_orig_3d); + + glVertex3fv(a); + glVertex3fv(b); + } + } + bglEnd(); + + glPointSize(ctrl_size); + + bglBegin(GL_POINTS); + bglVertex3fv((sld->flipped_vtx && sld->is_proportional == FALSE) ? + curr_sv->co_link_orig_3d[curr_sv->co_link_curr] : + curr_sv->co_orig_3d); + bglEnd(); + + glPopMatrix(); + glPopAttrib(); + + glDisable(GL_BLEND); + + if (v3d && v3d->zbuf) + glEnable(GL_DEPTH_TEST); + } + } +} + +static int doVertSlide(TransInfo *t, float perc) +{ + VertSlideData *sld = t->customData; + TransDataVertSlideVert *svlist = sld->sv, *sv; + int i; + + sld->perc = perc; + sv = svlist; + + if (sld->is_proportional == TRUE) { + for (i = 0; i < sld->totsv; i++, sv++) { + interp_v3_v3v3(sv->v->co, sv->co_orig_3d, sv->co_link_orig_3d[sv->co_link_curr], perc); + } + } + else { + TransDataVertSlideVert *sv_curr = &sld->sv[sld->curr_sv_index]; + const float edge_len_curr = len_v3v3(sv_curr->co_orig_3d, sv_curr->co_link_orig_3d[sv_curr->co_link_curr]); + const float tperc = perc * edge_len_curr; + + for (i = 0; i < sld->totsv; i++, sv++) { + float edge_len; + float dir[3]; + + sub_v3_v3v3(dir, sv->co_link_orig_3d[sv->co_link_curr], sv->co_orig_3d); + edge_len = normalize_v3(dir); + + if (edge_len > FLT_EPSILON) { + if (sld->flipped_vtx) { + madd_v3_v3v3fl(sv->v->co, sv->co_link_orig_3d[sv->co_link_curr], dir, -tperc); + } + else { + madd_v3_v3v3fl(sv->v->co, sv->co_orig_3d, dir, tperc); + } + } + else { + copy_v3_v3(sv->v->co, sv->co_orig_3d); + } + } + } + + return 1; +} + +int VertSlide(TransInfo *t, const int UNUSED(mval[2])) +{ + char str[128]; + float final; + VertSlideData *sld = t->customData; + const bool flipped = sld->flipped_vtx; + const bool is_proportional = sld->is_proportional; + const bool is_constrained = !((t->flag & T_ALT_TRANSFORM) || hasNumInput(&t->num)); + + final = t->values[0]; + + snapGrid(t, &final); + + /* only do this so out of range values are not displayed */ + if (is_constrained) { + CLAMP(final, 0.0f, 1.0f); + } + + if (hasNumInput(&t->num)) { + char c[NUM_STR_REP_LEN]; + + applyNumInput(&t->num, &final); + + outputNumInput(&(t->num), c); + + BLI_snprintf(str, sizeof(str), "Vert Slide: %s (E)ven: %s, (F)lipped: %s, Alt Hold: %s", + &c[0], !is_proportional ? "ON" : "OFF", flipped ? "ON" : "OFF", (t->flag & T_ALT_TRANSFORM) ? "ON" : "OFF"); + } + else { + BLI_snprintf(str, sizeof(str), "Vert Slide: %.2f (E)ven: %s, (F)lipped: %s, Alt Hold: %s", + final, !is_proportional ? "ON" : "OFF", flipped ? "ON" : "OFF", (t->flag & T_ALT_TRANSFORM) ? "ON" : "OFF"); + } + + if (is_constrained) { + CLAMP(final, 0.0f, 1.0f); + } + + t->values[0] = final; + + /*do stuff here*/ + if (t->customData) + doVertSlide(t, final); + else { + strcpy(str, "Invalid Vert Selection"); + t->state = TRANS_CANCEL; + } + + recalcData(t); + + ED_area_headerprint(t->sa, str); + + return 1; +} + + /* ******************** EditBone roll *************** */ void initBoneRoll(TransInfo *t) diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 08fe1e7676b..c72c6a83d82 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -52,12 +52,7 @@ struct Object; struct View3D; struct ScrArea; struct Scene; -struct bPose; struct bConstraint; -struct BezTriple; -struct wmOperatorType; -struct wmOperator; -struct wmWindowManager; struct wmKeyMap; struct wmKeyConfig; struct bContext; @@ -65,7 +60,6 @@ struct wmEvent; struct wmTimer; struct ARegion; struct ReportList; -struct SmallHash; typedef struct TransSnapPoint { struct TransSnapPoint *next, *prev; @@ -108,15 +102,15 @@ typedef struct TransCon { int imval[2]; /* initial mouse value for visual calculation */ /* the one in TransInfo is not garanty to stay the same (Rotates change it) */ int mode; /* Mode flags of the Constraint */ - void (*drawExtra)(struct TransInfo *); + void (*drawExtra)(struct TransInfo *t); /* For constraints that needs to draw differently from the other * uses this instead of the generic draw function */ - void (*applyVec)(struct TransInfo *, struct TransData *, float *, float *, float *); + void (*applyVec)(struct TransInfo *t, struct TransData *td, const float in[3], float out[3], float pvec[3]); /* Apply function pointer for linear vectorial transformation */ /* The last three parameters are pointers to the in/out/printable vectors */ - void (*applySize)(struct TransInfo *, struct TransData *, float [3][3]); + void (*applySize)(struct TransInfo *t, struct TransData *td, float smat[3][3]); /* Apply function pointer for size transformation */ - void (*applyRot)(struct TransInfo *, struct TransData *, float [3], float *); + void (*applyRot)(struct TransInfo *t, struct TransData *td, float vec[3], float *angle); /* Apply function pointer for rotation transformation */ } TransCon; @@ -143,6 +137,7 @@ typedef struct TransDataExtension { * namely when a bone is in "NoLocal" or "Hinge" mode)... */ float r_smtx[3][3]; /* Invers of previous one. */ int rotOrder; /* rotation mode, as defined in eRotationModes (DNA_action_types.h) */ + float oloc[3], orot[3], oquat[4], orotAxis[3], orotAngle; /* Original object transformation used for rigid bodies */ } TransDataExtension; typedef struct TransData2D { @@ -188,7 +183,7 @@ typedef struct TransDataNla { struct LinkNode; struct GHash; -typedef struct TransDataSlideVert { +typedef struct TransDataEdgeSlideVert { struct BMVert vup, vdown; struct BMVert origvert; @@ -201,10 +196,10 @@ typedef struct TransDataSlideVert { float upvec[3], downvec[3]; int loop_nr; -} TransDataSlideVert; +} TransDataEdgeSlideVert; -typedef struct SlideData { - TransDataSlideVert *sv; +typedef struct EdgeSlideData { + TransDataEdgeSlideVert *sv; int totsv; struct SmallHash vhash; @@ -214,15 +209,40 @@ typedef struct SlideData { struct BMEditMesh *em; /* flag that is set when origfaces is initialized */ - int origfaces_init; + bool origfaces_init; float perc; - int is_proportional; - int flipped_vtx; + bool is_proportional; + bool flipped_vtx; int curr_sv_index; -} SlideData; +} EdgeSlideData; + + +typedef struct TransDataVertSlideVert { + BMVert *v; + float co_orig_3d[3]; + float co_orig_2d[2]; + float (*co_link_orig_3d)[3]; + float (*co_link_orig_2d)[2]; + int co_link_tot; + int co_link_curr; +} TransDataVertSlideVert; + +typedef struct VertSlideData { + TransDataVertSlideVert *sv; + int totsv; + + struct BMEditMesh *em; + + float perc; + + bool is_proportional; + bool flipped_vtx; + + int curr_sv_index; +} VertSlideData; typedef struct TransData { float dist; /* Distance needed to affect element (for Proportionnal Editing) */ @@ -246,8 +266,8 @@ typedef struct TransData { } TransData; typedef struct MouseInput { - void (*apply)(struct TransInfo *, struct MouseInput *, const int [2], float [3]); - void (*post)(struct TransInfo *, float [3]); + void (*apply)(struct TransInfo *t, struct MouseInput *mi, const int mval[2], float output[3]); + void (*post)(struct TransInfo *t, float values[3]); int imval[2]; /* initial mouse position */ char precision; @@ -530,6 +550,10 @@ void initEdgeSlide(TransInfo *t); int handleEventEdgeSlide(TransInfo *t, struct wmEvent *event); int EdgeSlide(TransInfo *t, const int mval[2]); +void initVertSlide(TransInfo *t); +int handleEventVertSlide(TransInfo *t, struct wmEvent *event); +int VertSlide(TransInfo *t, const int mval[2]); + void initTimeTranslate(TransInfo *t); int TimeTranslate(TransInfo *t, const int mval[2]); @@ -656,13 +680,13 @@ typedef enum { INPUT_CUSTOM_RATIO } MouseInputMode; -void initMouseInput(TransInfo *t, MouseInput *mi, int center[2], int mval[2]); +void initMouseInput(TransInfo *t, MouseInput *mi, const int center[2], const int mval[2]); void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode); int handleMouseInput(struct TransInfo *t, struct MouseInput *mi, struct wmEvent *event); void applyMouseInput(struct TransInfo *t, struct MouseInput *mi, const int mval[2], float output[3]); -void setCustomPoints(TransInfo *t, MouseInput *mi, int start[2], int end[2]); -void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *, float [3])); +void setCustomPoints(TransInfo *t, MouseInput *mi, const int start[2], const int end[2]); +void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *t, float values[3])); /*********************** Generics ********************************/ @@ -672,8 +696,6 @@ void resetTransRestrictions(TransInfo *t); void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis, short options); -void drawNonPropEdge(const struct bContext *C, TransInfo *t); - /* DRAWLINE options flags */ #define DRAWLIGHT 1 @@ -715,8 +737,10 @@ void applyTransformOrientation(const struct bContext *C, float mat[3][3], char * int getTransformOrientation(const struct bContext *C, float normal[3], float plane[3], int activeOnly); -void freeSlideTempFaces(SlideData *sld); -void freeSlideVerts(TransInfo *t); -void projectSVData(TransInfo *t, int final); +void freeEdgeSlideTempFaces(EdgeSlideData *sld); +void freeEdgeSlideVerts(TransInfo *t); +void projectEdgeSlideData(TransInfo *t, bool is_final); + +void freeVertSlideVerts(TransInfo *t); #endif diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 947bdf53bee..097e4592933 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -200,13 +200,14 @@ static void viewAxisCorrectCenter(TransInfo *t, float t_con_center[3]) } } -static void axisProjection(TransInfo *t, float axis[3], float in[3], float out[3]) +static void axisProjection(TransInfo *t, const float axis[3], const float in[3], float out[3]) { float norm[3], vec[3], factor, angle; float t_con_center[3]; - if (in[0] == 0.0f && in[1] == 0.0f && in[2] == 0.0f) + if (is_zero_v3(in)) { return; + } copy_v3_v3(t_con_center, t->con.center); @@ -278,7 +279,7 @@ static void axisProjection(TransInfo *t, float axis[3], float in[3], float out[3 } } -static void planeProjection(TransInfo *t, float in[3], float out[3]) +static void planeProjection(TransInfo *t, const float in[3], float out[3]) { float vec[3], factor, norm[3]; @@ -308,7 +309,7 @@ static void planeProjection(TransInfo *t, float in[3], float out[3]) * */ -static void applyAxisConstraintVec(TransInfo *t, TransData *td, float in[3], float out[3], float pvec[3]) +static void applyAxisConstraintVec(TransInfo *t, TransData *td, const float in[3], float out[3], float pvec[3]) { copy_v3_v3(out, in); if (!td && t->con.mode & CON_APPLY) { @@ -351,7 +352,7 @@ static void applyAxisConstraintVec(TransInfo *t, TransData *td, float in[3], flo * Further down, that vector is mapped to each data's space. */ -static void applyObjectConstraintVec(TransInfo *t, TransData *td, float in[3], float out[3], float pvec[3]) +static void applyObjectConstraintVec(TransInfo *t, TransData *td, const float in[3], float out[3], float pvec[3]) { copy_v3_v3(out, in); if (t->con.mode & CON_APPLY) { diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index d38bdb178fb..39c51ff456e 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -85,6 +85,7 @@ #include "BKE_particle.h" #include "BKE_pointcache.h" #include "BKE_report.h" +#include "BKE_rigidbody.h" #include "BKE_scene.h" #include "BKE_sequencer.h" #include "BKE_tessmesh.h" @@ -4541,6 +4542,27 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) short constinv; short skip_invert = 0; + if (ob->rigidbody_object) { + float rot[3][3], scale[3]; + + /* save original object transform */ + copy_v3_v3(td->ext->oloc, ob->loc); + + if (ob->rotmode > 0) { + copy_v3_v3(td->ext->orot, ob->rot); + } + else if (ob->rotmode == ROT_MODE_AXISANGLE) { + td->ext->orotAngle = ob->rotAngle; + copy_v3_v3(td->ext->orotAxis, ob->rotAxis); + } + else { + copy_qt_qt(td->ext->oquat, ob->quat); + } + /* update object's loc/rot to get current rigid body transform */ + mat4_to_loc_rot_size(ob->loc, rot, scale, ob->obmat); + BKE_object_mat3_to_rot(ob, rot, FALSE); + } + /* axismtx has the real orientation */ copy_m3_m4(td->axismtx, ob->obmat); normalize_m3(td->axismtx); @@ -5094,25 +5116,25 @@ void special_aftertrans_update(bContext *C, TransInfo *t) if (canceled == 0) { /* we need to delete the temporary faces before automerging */ if (t->mode == TFM_EDGE_SLIDE) { - SlideData *sld = t->customData; + EdgeSlideData *sld = t->customData; /* handle multires re-projection, done * on transform completion since it's * really slow -joeedh */ - projectSVData(t, TRUE); + projectEdgeSlideData(t, TRUE); /* free temporary faces to avoid automerging and deleting * during cleanup - psy-fi */ - freeSlideTempFaces(sld); + freeEdgeSlideTempFaces(sld); } EDBM_automerge(t->scene, t->obedit, TRUE); } else { if (t->mode == TFM_EDGE_SLIDE) { - SlideData *sld = t->customData; + EdgeSlideData *sld = t->customData; sld->perc = 0.0; - projectSVData(t, FALSE); + projectEdgeSlideData(t, FALSE); } } } @@ -5494,6 +5516,9 @@ void special_aftertrans_update(bContext *C, TransInfo *t) if (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) recalcObPaths = 1; } + /* restore rigid body transform */ + if (ob->rigidbody_object && canceled) + BKE_rigidbody_aftertrans_update(ob, td->ext->oloc, td->ext->orot, td->ext->oquat, td->ext->orotAxis, td->ext->orotAngle); } /* recalculate motion paths for objects (if necessary) diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 2591c61c5ab..ef775ae3128 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -550,13 +550,20 @@ static void recalcData_nla(TransInfo *t) break; } - /* use RNA to write the values... */ - // TODO: do we need to write in 2 passes to make sure that no truncation goes on? + /* Use RNA to write the values to ensure that constraints on these are obeyed + * (e.g. for transition strips, the values are taken from the neighbours) + * + * NOTE: we write these twice to avoid truncation errors which can arise when + * moving the strips a large distance using numeric input [#33852] + */ RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr); RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]); RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]); + RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]); + RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]); + /* flush transforms to child strips (since this should be a meta) */ BKE_nlameta_flush_transforms(strip); @@ -812,7 +819,7 @@ static void recalcData_view3d(TransInfo *t) mul_m3_v3(t->mat, up_axis); } - ebo->roll = ED_rollBoneToVector(ebo, up_axis, FALSE); + ebo->roll = ED_rollBoneToVector(ebo, up_axis, TRUE); } } } diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c index 69569251d01..c805dfe1b41 100644 --- a/source/blender/editors/transform/transform_input.c +++ b/source/blender/editors/transform/transform_input.c @@ -164,7 +164,7 @@ static void InputVerticalAbsolute(TransInfo *t, MouseInput *mi, const int mval[2 output[0] = dot_v3v3(t->viewinv[1], vec) * 2.0f; } -void setCustomPoints(TransInfo *UNUSED(t), MouseInput *mi, int start[2], int end[2]) +void setCustomPoints(TransInfo *UNUSED(t), MouseInput *mi, const int start[2], const int end[2]) { int *data; @@ -275,7 +275,7 @@ static void InputAngle(TransInfo *UNUSED(t), MouseInput *mi, const int mval[2], output[0] = *angle; } -void initMouseInput(TransInfo *UNUSED(t), MouseInput *mi, int center[2], int mval[2]) +void initMouseInput(TransInfo *UNUSED(t), MouseInput *mi, const int center[2], const int mval[2]) { mi->factor = 0; mi->precision = 0; @@ -368,7 +368,7 @@ void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode) applyMouseInput(t, mi, mi->imval, t->values); } -void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *, float[3])) +void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *t, float values[3])) { mi->post = post; } diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index 6b016bf4303..cd6035a232b 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -734,8 +734,8 @@ static void partial_doughnut(float radring, float radhole, int start, int end, i float cos_phi, sin_phi, dist; phi += side_delta; - cos_phi = (float)cos(phi); - sin_phi = (float)sin(phi); + cos_phi = cosf(phi); + sin_phi = sinf(phi); dist = radhole + radring * cos_phi; glVertex3f(cos_theta1 * dist, -sin_theta1 * dist, radring * sin_phi); @@ -749,8 +749,8 @@ static void partial_doughnut(float radring, float radhole, int start, int end, i float cos_phi, sin_phi, dist; phi += side_delta; - cos_phi = (float)cos(phi); - sin_phi = (float)sin(phi); + cos_phi = cosf(phi); + sin_phi = sinf(phi); dist = radhole + radring * cos_phi; glVertex3f(cos_theta1 * dist, -sin_theta1 * dist, radring * sin_phi); diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 916cf540589..32dc31954f2 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -73,6 +73,7 @@ static char OP_TILT[] = "TRANSFORM_OT_tilt"; static char OP_TRACKBALL[] = "TRANSFORM_OT_trackball"; static char OP_MIRROR[] = "TRANSFORM_OT_mirror"; static char OP_EDGE_SLIDE[] = "TRANSFORM_OT_edge_slide"; +static char OP_VERT_SLIDE[] = "TRANSFORM_OT_vert_slide"; static char OP_EDGE_CREASE[] = "TRANSFORM_OT_edge_crease"; static char OP_EDGE_BWEIGHT[] = "TRANSFORM_OT_edge_bevelweight"; static char OP_SEQ_SLIDE[] = "TRANSFORM_OT_seq_slide"; @@ -90,6 +91,7 @@ static void TRANSFORM_OT_tilt(struct wmOperatorType *ot); static void TRANSFORM_OT_trackball(struct wmOperatorType *ot); static void TRANSFORM_OT_mirror(struct wmOperatorType *ot); static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot); +static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot); static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot); static void TRANSFORM_OT_edge_bevelweight(struct wmOperatorType *ot); static void TRANSFORM_OT_seq_slide(struct wmOperatorType *ot); @@ -109,6 +111,7 @@ static TransformModeItem transform_modes[] = {OP_TRACKBALL, TFM_TRACKBALL, TRANSFORM_OT_trackball}, {OP_MIRROR, TFM_MIRROR, TRANSFORM_OT_mirror}, {OP_EDGE_SLIDE, TFM_EDGE_SLIDE, TRANSFORM_OT_edge_slide}, + {OP_VERT_SLIDE, TFM_VERT_SLIDE, TRANSFORM_OT_vert_slide}, {OP_EDGE_CREASE, TFM_CREASE, TRANSFORM_OT_edge_crease}, {OP_EDGE_BWEIGHT, TFM_BWEIGHT, TRANSFORM_OT_edge_bevelweight}, {OP_SEQ_SLIDE, TFM_SEQ_SLIDE, TRANSFORM_OT_seq_slide}, @@ -150,38 +153,6 @@ EnumPropertyItem transform_mode_types[] = {0, NULL, 0, NULL, NULL} }; -static int snap_type_exec(bContext *C, wmOperator *op) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - - ts->snap_mode = RNA_enum_get(op->ptr, "type"); - - WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ - - return OPERATOR_FINISHED; -} - -static void TRANSFORM_OT_snap_type(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Snap Type"; - ot->description = "Set the snap element type"; - ot->idname = "TRANSFORM_OT_snap_type"; - - /* api callbacks */ - ot->invoke = WM_menu_invoke; - ot->exec = snap_type_exec; - - ot->poll = ED_operator_areaactive; - - /* flags */ - ot->flag = OPTYPE_UNDO; - - /* props */ - ot->prop = RNA_def_enum(ot->srna, "type", snap_element_items, 0, "Type", "Set the snap element type"); - -} - static int select_orientation_exec(bContext *C, wmOperator *op) { int orientation = RNA_enum_get(op->ptr, "orientation"); @@ -793,6 +764,26 @@ static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot) Transform_Properties(ot, P_MIRROR | P_SNAP | P_CORRECT_UV); } +static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Vertex Slide"; + ot->description = "Slide a vertex along a mesh"; + ot->idname = OP_VERT_SLIDE; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; + + /* api callbacks */ + ot->invoke = transform_invoke; + ot->exec = transform_exec; + ot->modal = transform_modal; + ot->cancel = transform_cancel; + ot->poll = ED_operator_editmesh; + + RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f); + + Transform_Properties(ot, P_MIRROR | P_SNAP); +} + static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot) { /* identifiers */ @@ -891,8 +882,6 @@ void transform_operatortypes(void) WM_operatortype_append(TRANSFORM_OT_select_orientation); WM_operatortype_append(TRANSFORM_OT_create_orientation); WM_operatortype_append(TRANSFORM_OT_delete_orientation); - - WM_operatortype_append(TRANSFORM_OT_snap_type); } void transform_keymap_for_space(wmKeyConfig *keyconf, wmKeyMap *keymap, int spaceid) @@ -939,7 +928,9 @@ void transform_keymap_for_space(wmKeyConfig *keyconf, wmKeyMap *keymap, int spac kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", TABKEY, KM_PRESS, KM_SHIFT, 0); RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_snap"); - WM_keymap_add_item(keymap, "TRANSFORM_OT_snap_type", TABKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0); + kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", TABKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0); + RNA_string_set(kmi->ptr, "data_path", "tool_settings.snap_element"); + kmi = WM_keymap_add_item(keymap, OP_TRANSLATION, TKEY, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "texture_space", TRUE); @@ -1032,6 +1023,9 @@ void transform_keymap_for_space(wmKeyConfig *keyconf, wmKeyMap *keymap, int spac kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", TABKEY, KM_PRESS, KM_SHIFT, 0); RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_snap"); + + kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", TABKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0); + RNA_string_set(kmi->ptr, "data_path", "tool_settings.snap_uv_element"); break; case SPACE_CLIP: WM_keymap_add_item(keymap, OP_TRANSLATION, GKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index 023f281aea9..ea7e17af086 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -134,14 +134,15 @@ static void draw_uvs_shadow(Object *obedit) BMIter iter, liter; MLoopUV *luv; + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + /* draws the gray mesh when painting */ glColor3ub(112, 112, 112); BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { glBegin(GL_LINE_LOOP); BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); - + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); glVertex2fv(luv->uv); } glEnd(); @@ -173,6 +174,9 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe float aspx, aspy, col[4]; int i; + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY); + ED_space_image_get_uv_aspect(sima, &aspx, &aspy); switch (sima->dt_uvstretch) { @@ -184,10 +188,10 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe const int efa_len = efa->len; float (*tf_uv)[2] = BLI_array_alloca(tf_uv, efa_len); float (*tf_uvorig)[2] = BLI_array_alloca(tf_uvorig, efa_len); - tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); copy_v2_v2(tf_uvorig[i], luv->uv); } @@ -214,7 +218,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { glBegin(GL_POLYGON); BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); glVertex2fv(luv->uv); } glEnd(); @@ -231,7 +235,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe area = BM_face_calc_area(efa) / totarea; BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); copy_v2_v2(tf_uvorig[i], luv->uv); } @@ -251,7 +255,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe glBegin(GL_POLYGON); BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); glVertex2fv(luv->uv); } glEnd(); @@ -269,7 +273,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe glShadeModel(GL_SMOOTH); BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (uvedit_face_visible_test(scene, ima, efa, tf)) { const int efa_len = efa->len; @@ -284,7 +288,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe BM_elem_flag_enable(efa, BM_ELEM_TAG); BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); copy_v2_v2(tf_uvorig[i], luv->uv); } @@ -310,7 +314,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe glBegin(GL_POLYGON); BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); a = fabsf(uvang[i] - ang[i]) / (float)M_PI; weight_to_rgb(col, 1.0f - powf((1.0f - a), 2.0f)); glColor3fv(col); @@ -418,6 +422,9 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) int drawfaces, interpedges; Image *ima = sima->image; + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY); + activetf = EDBM_mtexpoly_active_get(em, &efa_act, FALSE, FALSE); /* will be set to NULL if hidden */ activef = BM_active_face_get(bm, FALSE, FALSE); ts = scene->toolsettings; @@ -467,7 +474,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) glEnable(GL_BLEND); BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (uvedit_face_visible_test(scene, ima, efa, tf)) { BM_elem_flag_enable(efa, BM_ELEM_TAG); @@ -480,7 +487,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) glBegin(GL_POLYGON); BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); glVertex2fv(luv->uv); } glEnd(); @@ -497,7 +504,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) /* would be nice to do this within a draw loop but most below are optional, so it would involve too many checks */ BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (uvedit_face_visible_test(scene, ima, efa, tf)) { BM_elem_flag_enable(efa, BM_ELEM_TAG); @@ -514,7 +521,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) /* 3. draw active face stippled */ if (activef) { - tf = CustomData_bmesh_get(&bm->pdata, activef->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(activef, cd_poly_tex_offset); if (uvedit_face_visible_test(scene, ima, activef, tf)) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -525,7 +532,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) glBegin(GL_POLYGON); BM_ITER_ELEM (l, &liter, activef, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); glVertex2fv(luv->uv); } glEnd(); @@ -548,14 +555,14 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) continue; - tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (tf) { cpack(0x111111); glBegin(GL_LINE_LOOP); BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); glVertex2fv(luv->uv); } glEnd(); @@ -565,20 +572,11 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) glBegin(GL_LINE_LOOP); BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); glVertex2fv(luv->uv); } glEnd(); -#if 0 - glBegin(GL_LINE_STRIP); - luv = CustomData_bmesh_get(&bm->ldata, efa->lbase->head.data, CD_MLOOPUV); - glVertex2fv(luv->uv); - luv = CustomData_bmesh_get(&bm->ldata, efa->lbase->next->head.data, CD_MLOOPUV); - glVertex2fv(luv->uv); - glEnd(); -#endif - setlinestyle(0); } } @@ -594,7 +592,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) glBegin(GL_LINE_LOOP); BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); glVertex2fv(luv->uv); } glEnd(); @@ -610,7 +608,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) glBegin(GL_LINE_LOOP); BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); glVertex2fv(luv->uv); } glEnd(); @@ -636,7 +634,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) sel = (uvedit_uv_select_test(em, scene, l) ? 1 : 0); glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); glVertex2fv(luv->uv); } glEnd(); @@ -656,9 +654,9 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) glColor4ubv(sel ? (GLubyte *)col1 : (GLubyte *)col2); lastsel = sel; } - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); glVertex2fv(luv->uv); - luv = CustomData_bmesh_get(&bm->ldata, l->next->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); glVertex2fv(luv->uv); } glEnd(); @@ -673,7 +671,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) glBegin(GL_LINE_LOOP); BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); glVertex2fv(luv->uv); } glEnd(); @@ -741,7 +739,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (!uvedit_uv_select_test(em, scene, l)) bglVertex2fv(luv->uv); } @@ -759,7 +757,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (luv->flag & MLOOPUV_PINNED) bglVertex2fv(luv->uv); @@ -777,7 +775,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (uvedit_uv_select_test(em, scene, l)) bglVertex2fv(luv->uv); diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h index b6d82451d2f..7faec33ca98 100644 --- a/source/blender/editors/uvedit/uvedit_intern.h +++ b/source/blender/editors/uvedit/uvedit_intern.h @@ -59,7 +59,7 @@ typedef struct NearestHit { struct BMFace *efa; struct MTexPoly *tf; struct BMLoop *l, *nextl; - struct MLoopUV *luv, *nextluv; + struct MLoopUV *luv, *luv_next; int lindex; //index of loop within face int vert1, vert2; //index in mesh of edge vertices } NearestHit; diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 2194ce28353..e158f8843b7 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -199,6 +199,8 @@ void ED_uvedit_assign_image(Main *bmain, Scene *scene, Object *obedit, Image *im else { BMFace *efa; + int cd_poly_tex_offset; + /* old shading system, assign image to selected faces */ #ifdef USE_SWITCH_ASPECT float prev_aspect[2], fprev_aspect; @@ -220,9 +222,11 @@ void ED_uvedit_assign_image(Main *bmain, Scene *scene, Object *obedit, Image *im update = 1; } + cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + /* now assign to all visible faces */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (uvedit_face_visible_test(scene, previma, efa, tf) && (selected == TRUE || uvedit_face_select_test(scene, em, efa))) @@ -243,7 +247,7 @@ void ED_uvedit_assign_image(Main *bmain, Scene *scene, Object *obedit, Image *im BMLoop *l; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->uv[0] *= fprev_aspect; luv->uv[0] /= faspect; @@ -274,6 +278,7 @@ static int uvedit_set_tile(Object *obedit, Image *ima, int curtile) BMFace *efa; BMIter iter; MTexPoly *tf; + int cd_poly_tex_offset; /* verify if we have something to do */ if (!ima || !ED_uvedit_test(obedit)) @@ -288,10 +293,12 @@ static int uvedit_set_tile(Object *obedit, Image *ima, int curtile) em = BMEdit_FromObject(obedit); + cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && BM_elem_flag_test(efa, BM_ELEM_SELECT)) + if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) tf->tile = curtile; /* set tile index */ } @@ -344,15 +351,18 @@ int uvedit_face_select_test(Scene *scene, BMEditMesh *em, BMFace *efa) { ToolSettings *ts = scene->toolsettings; - if (ts->uv_flag & UV_SYNC_SELECTION) + if (ts->uv_flag & UV_SYNC_SELECTION) { return (BM_elem_flag_test(efa, BM_ELEM_SELECT)); + } else { BMLoop *l; MLoopUV *luv; BMIter liter; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); /* TODO, pass this on */ + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (!(luv->flag & MLOOPUV_VERTSEL)) return 0; } @@ -376,8 +386,10 @@ int uvedit_face_select_enable(Scene *scene, BMEditMesh *em, BMFace *efa, const s MLoopUV *luv; BMIter liter; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); /* TODO, pass this on */ + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag |= MLOOPUV_VERTSEL; } @@ -399,8 +411,10 @@ int uvedit_face_select_disable(Scene *scene, BMEditMesh *em, BMFace *efa) MLoopUV *luv; BMIter liter; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); /* TODO, pass this on */ + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag &= ~MLOOPUV_VERTSEL; } @@ -503,7 +517,9 @@ int uvedit_uv_select_test(BMEditMesh *em, Scene *scene, BMLoop *l) return BM_elem_flag_test(l->v, BM_ELEM_SELECT); } else { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); /* TODO, pass this on */ + + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); return luv->flag & MLOOPUV_VERTSEL; } @@ -524,7 +540,8 @@ void uvedit_uv_select_enable(BMEditMesh *em, Scene *scene, BMLoop *l, const shor } } else { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); /* TODO, pass this on */ + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag |= MLOOPUV_VERTSEL; } @@ -541,7 +558,8 @@ void uvedit_uv_select_disable(BMEditMesh *em, Scene *scene, BMLoop *l) BM_vert_select_set(em->bm, l->v, FALSE); } else { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); /* TODO, pass this on */ + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag &= ~MLOOPUV_VERTSEL; } @@ -565,10 +583,12 @@ void uv_poly_center(BMEditMesh *em, BMFace *f, float r_cent[2]) MLoopUV *luv; BMIter liter; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); /* TODO, pass this on */ + zero_v2(r_cent); BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); add_v2_v2(r_cent, luv->uv); } @@ -594,17 +614,20 @@ int ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float r_min[2], f MLoopUV *luv; int sel; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + INIT_MINMAX2(r_min, r_max); sel = 0; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (uvedit_uv_select_test(em, scene, l)) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); minmax_v2v2_v2(r_min, r_max, luv->uv); sel = 1; } @@ -624,14 +647,17 @@ static int ED_uvedit_median(Scene *scene, Image *ima, Object *obedit, float co[2 MLoopUV *luv; unsigned int sel = 0; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + zero_v2(co); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (uvedit_uv_select_test(em, scene, l)) { add_v2_v2(co, luv->uv); sel++; @@ -672,26 +698,29 @@ void uv_find_nearest_edge(Scene *scene, Image *ima, BMEditMesh *em, const float BMFace *efa; BMLoop *l; BMIter iter, liter; - MLoopUV *luv, *nextluv; + MLoopUV *luv, *luv_next; float mindist_squared, dist_squared; int i; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + mindist_squared = 1e10f; memset(hit, 0, sizeof(*hit)); BM_mesh_elem_index_ensure(em->bm, BM_VERT); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; i = 0; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); - nextluv = CustomData_bmesh_get(&em->bm->ldata, l->next->head.data, CD_MLOOPUV); + 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); - dist_squared = dist_squared_to_line_segment_v2(co, luv->uv, nextluv->uv); + dist_squared = dist_squared_to_line_segment_v2(co, luv->uv, luv_next->uv); if (dist_squared < mindist_squared) { hit->tf = tf; @@ -700,7 +729,7 @@ void uv_find_nearest_edge(Scene *scene, Image *ima, BMEditMesh *em, const float hit->l = l; hit->nextl = l->next; hit->luv = luv; - hit->nextluv = nextluv; + hit->luv_next = luv_next; hit->lindex = i; hit->vert1 = BM_elem_index_get(hit->l->v); hit->vert2 = BM_elem_index_get(hit->l->next->v); @@ -720,16 +749,18 @@ static void find_nearest_uv_face(Scene *scene, Image *ima, BMEditMesh *em, const BMIter iter; float mindist, dist, cent[2]; + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + mindist = 1e10f; memset(hit, 0, sizeof(*hit)); /*this will fill in hit.vert1 and hit.vert2*/ uv_find_nearest_edge(scene, ima, em, co, hit); hit->l = hit->nextl = NULL; - hit->luv = hit->nextluv = NULL; + hit->luv = hit->luv_next = NULL; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; @@ -753,6 +784,7 @@ static int nearest_uv_between(BMEditMesh *em, BMFace *efa, int UNUSED(nverts), i BMIter iter; float m[2], v1[2], v2[2], c1, c2, *uv1 = NULL, /* *uv2, */ /* UNUSED */ *uv3 = NULL; int id1, id2, i; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); id1 = (id + efa->len - 1) % efa->len; id2 = (id + efa->len + 1) % efa->len; @@ -761,7 +793,7 @@ static int nearest_uv_between(BMEditMesh *em, BMFace *efa, int UNUSED(nverts), i i = 0; BM_ITER_ELEM (l, &iter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (i == id1) { uv1 = luv->uv; @@ -803,10 +835,13 @@ void uv_find_nearest_vert(Scene *scene, Image *ima, BMEditMesh *em, float mindist, dist; int i; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + /*this will fill in hit.vert1 and hit.vert2*/ uv_find_nearest_edge(scene, ima, em, co, hit); hit->l = hit->nextl = NULL; - hit->luv = hit->nextluv = NULL; + hit->luv = hit->luv_next = NULL; mindist = 1e10f; memset(hit, 0, sizeof(*hit)); @@ -814,13 +849,13 @@ void uv_find_nearest_vert(Scene *scene, Image *ima, BMEditMesh *em, BM_mesh_elem_index_ensure(em->bm, BM_VERT); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; i = 0; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (penalty && uvedit_uv_select_test(em, scene, l)) dist = fabsf(co[0] - luv->uv[0]) + penalty[0] + fabsf(co[1] - luv->uv[1]) + penalty[1]; @@ -839,7 +874,7 @@ void uv_find_nearest_vert(Scene *scene, Image *ima, BMEditMesh *em, hit->l = l; hit->nextl = l->next; hit->luv = luv; - hit->nextluv = CustomData_bmesh_get(&em->bm->ldata, l->next->head.data, CD_MLOOPUV); + hit->luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); hit->tf = tf; hit->efa = efa; hit->lindex = i; @@ -862,16 +897,19 @@ int ED_uvedit_nearest_uv(Scene *scene, Object *obedit, Image *ima, const float c float mindist, dist; int found = FALSE; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + mindist = 1e10f; copy_v2_v2(r_uv, co); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); dist = fabsf(co[0] - luv->uv[0]) + fabsf(co[1] - luv->uv[1]); if (dist <= mindist) { @@ -985,6 +1023,8 @@ static int select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestHit UvMapVert *iterv1, *iterv2; int a, looking, nverts, starttotf, select; + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + /* setup */ EDBM_index_arrays_ensure(em, BM_FACE); vmap = EDBM_uv_vert_map_create(em, 0, limit); @@ -1018,7 +1058,7 @@ static int select_edgeloop(Scene *scene, Image *ima, BMEditMesh *em, NearestHit /* 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) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!BM_elem_flag_test(efa, BM_ELEM_TAG) && uvedit_face_visible_test(scene, ima, efa, tf)) { nverts = efa->len; @@ -1097,6 +1137,9 @@ static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float unsigned int a; char *flag; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + EDBM_index_arrays_ensure(em, BM_FACE); /* we can use this too */ vmap = EDBM_uv_vert_map_create(em, 1, limit); @@ -1108,11 +1151,11 @@ static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float if (!hit) { BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (uvedit_face_visible_test(scene, ima, efa, tf)) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (luv->flag & MLOOPUV_VERTSEL) { stack[stacksize] = a; @@ -1186,7 +1229,7 @@ static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float a = 0; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (flag[a]) luv->flag |= MLOOPUV_VERTSEL; @@ -1205,7 +1248,7 @@ static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float } BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (luv->flag & MLOOPUV_VERTSEL) break; @@ -1226,7 +1269,7 @@ static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float } BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag &= ~MLOOPUV_VERTSEL; } @@ -1243,7 +1286,7 @@ static void select_linked(Scene *scene, Image *ima, BMEditMesh *em, const float } BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag |= MLOOPUV_VERTSEL; } @@ -1265,14 +1308,17 @@ static float *uv_sel_co_from_eve(Scene *scene, Image *ima, BMEditMesh *em, BMVer BMIter liter; BMLoop *l; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) { - MTexPoly *tf = CustomData_bmesh_get(&em->bm->pdata, l->f->head.data, CD_MTEXPOLY); + MTexPoly *tf = BM_ELEM_CD_GET_VOID_P(l->f, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, l->f, tf)) continue; if (uvedit_uv_select_test(em, scene, l)) { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); return luv->uv; } } @@ -1284,17 +1330,18 @@ static float *uv_sel_co_from_eve(Scene *scene, Image *ima, BMEditMesh *em, BMVer static void weld_align_uv(bContext *C, int tool) { + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = BMEdit_FromObject(obedit); SpaceImage *sima; Scene *scene; - Object *obedit; Image *ima; - BMEditMesh *em; MTexPoly *tf; float cent[2], min[2], max[2]; - + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + scene = CTX_data_scene(C); - obedit = CTX_data_edit_object(C); - em = BMEdit_FromObject(obedit); ima = CTX_data_edit_image(C); sima = CTX_wm_space_image(C); @@ -1306,14 +1353,14 @@ static void weld_align_uv(bContext *C, int tool) BMLoop *l; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (uvedit_uv_select_test(em, scene, l)) { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); minmax_v2v2_v2(min, max, luv->uv); } } @@ -1330,13 +1377,13 @@ static void weld_align_uv(bContext *C, int tool) BMLoop *l; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (uvedit_uv_select_test(em, scene, l)) { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->uv[0] = cent[0]; } @@ -1350,13 +1397,13 @@ static void weld_align_uv(bContext *C, int tool) BMLoop *l; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (uvedit_uv_select_test(em, scene, l)) { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->uv[1] = cent[1]; } @@ -1379,7 +1426,7 @@ static void weld_align_uv(bContext *C, int tool) /* tag verts with a selected UV */ BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) { - tf = CustomData_bmesh_get(&em->bm->pdata, l->f->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(l->f, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, l->f, tf)) continue; @@ -1469,13 +1516,13 @@ static void weld_align_uv(bContext *C, int tool) /* go over all verts except for endpoints */ for (i = 0; i < BLI_array_count(eve_line); i++) { BM_ITER_ELEM (l, &liter, eve_line[i], BM_LOOPS_OF_VERT) { - tf = CustomData_bmesh_get(&em->bm->pdata, l->f->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(l->f, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, l->f, tf)) continue; if (uvedit_uv_select_test(em, scene, l)) { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); /* Projection of point (x, y) over line (x1, y1, x2, y2) along X axis: * new_y = (y2 - y1) / (x2 - x1) * (x - x1) + y1 * Maybe this should be a BLI func? Or is it already existing? @@ -1554,9 +1601,9 @@ static int remove_doubles_exec(bContext *C, wmOperator *op) SpaceImage *sima; Scene *scene; - Object *obedit; + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = BMEdit_FromObject(obedit); Image *ima; - BMEditMesh *em; MTexPoly *tf; int uv_a_index; int uv_b_index; @@ -1567,10 +1614,11 @@ static int remove_doubles_exec(bContext *C, wmOperator *op) BMFace *efa; BMLoop *l; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + sima = CTX_wm_space_image(C); scene = CTX_data_scene(C); - obedit = CTX_data_edit_object(C); - em = BMEdit_FromObject(obedit); ima = CTX_data_edit_image(C); if (use_unselected == FALSE) { @@ -1581,13 +1629,13 @@ static int remove_doubles_exec(bContext *C, wmOperator *op) /* TODO, use qsort as with MESH_OT_remove_doubles, this isn't optimal */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (uvedit_uv_select_test(em, scene, l)) { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); UVvert vert; vert.uv_loop = luv; vert.weld = FALSE; @@ -1644,12 +1692,12 @@ static int remove_doubles_exec(bContext *C, wmOperator *op) BLI_array_declare(loop_arr_unselected); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (uvedit_uv_select_test(em, scene, l)) { BLI_array_append(loop_arr, luv); } @@ -1738,6 +1786,9 @@ static void select_all_perform(Scene *scene, Image *ima, BMEditMesh *em, int act MTexPoly *tf; MLoopUV *luv; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + if (ts->uv_flag & UV_SYNC_SELECTION) { switch (action) { @@ -1760,13 +1811,13 @@ static void select_all_perform(Scene *scene, Image *ima, BMEditMesh *em, int act if (action == SEL_TOGGLE) { action = SEL_SELECT; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (luv->flag & MLOOPUV_VERTSEL) { action = SEL_DESELECT; @@ -1778,13 +1829,13 @@ static void select_all_perform(Scene *scene, Image *ima, BMEditMesh *em, int act BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); switch (action) { case SEL_SELECT: @@ -1879,6 +1930,9 @@ static int mouse_select(bContext *C, const float co[2], int extend, int loop) BLI_array_declare(hituv); float penalty[2]; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + /* 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 @@ -1957,7 +2011,7 @@ static int mouse_select(bContext *C, const float co[2], int extend, int loop) hitv[hit.lindex] = hit.vert1; hitv[(hit.lindex + 1) % hit.efa->len] = hit.vert2; hituv[hit.lindex] = hit.luv->uv; - hituv[(hit.lindex + 1) % hit.efa->len] = hit.nextluv->uv; + hituv[(hit.lindex + 1) % hit.efa->len] = hit.luv_next->uv; hitlen = hit.efa->len; } @@ -1979,7 +2033,7 @@ static int mouse_select(bContext *C, const float co[2], int extend, int loop) BLI_array_grow_items(hituv, hit.efa->len); i = 0; BM_ITER_ELEM (l, &liter, hit.efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); hituv[i] = luv->uv; hitv[i] = BM_elem_index_get(l->v); i++; @@ -2065,12 +2119,12 @@ static int mouse_select(bContext *C, const float co[2], int extend, int loop) /* deselect */ if (select == 0) { BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (sticky_select(limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen)) uvedit_uv_select_disable(em, scene, l); } @@ -2080,12 +2134,12 @@ static int mouse_select(bContext *C, const float co[2], int extend, int loop) /* select */ else { BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (sticky_select(limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen)) uvedit_uv_select_enable(em, scene, l, FALSE); } @@ -2117,13 +2171,13 @@ static int mouse_select(bContext *C, const float co[2], int extend, int loop) /* select sticky uvs */ if (sticky != SI_STICKY_DISABLE) { BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (sticky == SI_STICKY_DISABLE) continue; - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (sticky_select(limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen)) uvedit_uv_select_enable(em, scene, l, FALSE); @@ -2380,23 +2434,27 @@ static int select_split_exec(bContext *C, wmOperator *op) MLoopUV *luv; short change = FALSE; + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY); + if (ts->uv_flag & UV_SYNC_SELECTION) { BKE_report(op->reports, RPT_ERROR, "Cannot split selection when sync selection is enabled"); return OPERATOR_CANCELLED; } + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { int is_sel = FALSE; int is_unsel = FALSE; - tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; /* are we all selected? */ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (luv->flag & MLOOPUV_VERTSEL) { is_sel = TRUE; @@ -2413,7 +2471,7 @@ static int select_split_exec(bContext *C, wmOperator *op) if (is_sel && is_unsel) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag &= ~MLOOPUV_VERTSEL; } @@ -2459,6 +2517,9 @@ static int unlink_selection_exec(bContext *C, wmOperator *op) MTexPoly *tf; MLoopUV *luv; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + if (ts->uv_flag & UV_SYNC_SELECTION) { BKE_report(op->reports, RPT_ERROR, "Cannot unlink selection when sync selection is enabled"); return OPERATOR_CANCELLED; @@ -2467,12 +2528,12 @@ static int unlink_selection_exec(bContext *C, wmOperator *op) BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { int desel = 0; - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (!(luv->flag & MLOOPUV_VERTSEL)) { desel = 1; @@ -2482,7 +2543,7 @@ static int unlink_selection_exec(bContext *C, wmOperator *op) if (desel) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag &= ~MLOOPUV_VERTSEL; } } @@ -2569,7 +2630,7 @@ static void uv_faces_do_sticky(SpaceImage *sima, Scene *scene, Object *obedit, s /* now select tagged verts */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */ + /* 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)) { @@ -2604,7 +2665,7 @@ static void uv_faces_do_sticky(SpaceImage *sima, Scene *scene, Object *obedit, s efa = BM_iter_new(&iter, em->bm, BM_FACES_OF_MESH, NULL); for (efa_index = 0; efa; efa = BM_iter_step(&iter), efa_index++) { if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { - /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */ + /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (select) @@ -2633,7 +2694,7 @@ static void uv_faces_do_sticky(SpaceImage *sima, Scene *scene, Object *obedit, s if (efa_index != vlist_iter->f) { BMLoop *l_other; efa_vlist = EDBM_face_at_index(em, vlist_iter->f); - /* tf_vlist = CustomData_bmesh_get(&em->bm->pdata, efa_vlist->head.data, CD_MTEXPOLY); */ /* UNUSED */ + /* 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->tfindex); @@ -2685,6 +2746,9 @@ static int border_select_exec(bContext *C, wmOperator *op) (ts->selectmode == SCE_SELECT_FACE) : (ts->uv_selectmode == UV_SELECT_FACE); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + /* get rectangle from operator */ WM_operator_properties_border_to_rcti(op, &rect); @@ -2710,7 +2774,7 @@ static int border_select_exec(bContext *C, wmOperator *op) /* assume not touched */ BM_elem_flag_disable(efa, BM_ELEM_TAG); - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (uvedit_face_visible_test(scene, ima, efa, tf)) { uv_poly_center(em, efa, cent); if (BLI_rctf_isect_pt_v(&rectf, cent)) { @@ -2730,11 +2794,11 @@ static int border_select_exec(bContext *C, wmOperator *op) change = 1; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (!pinned || (ts->uv_flag & UV_SYNC_SELECTION) ) { @@ -2834,6 +2898,8 @@ static int circle_select_exec(bContext *C, wmOperator *op) (ts->selectmode == SCE_SELECT_FACE) : (ts->uv_selectmode == UV_SELECT_FACE); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + /* get operator properties */ select = (gesture_mode == GESTURE_MODAL_SELECT); x = RNA_int_get(op->ptr, "x"); @@ -2874,7 +2940,7 @@ static int circle_select_exec(bContext *C, wmOperator *op) else { BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); change |= select_uv_inside_ellipse(em, scene, select, offset, ellipse, l, luv); } } @@ -2929,6 +2995,9 @@ static int do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mov (ts->selectmode == SCE_SELECT_FACE) : (ts->uv_selectmode == UV_SELECT_FACE); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + BMIter iter, liter; BMFace *efa; @@ -2964,11 +3033,11 @@ static int do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mov } else { /* Vert Sel */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (uvedit_face_visible_test(scene, ima, efa, tf)) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if ((select) != (uvedit_uv_select_test(em, scene, l))) { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); UI_view2d_view_to_region(&ar->v2d, luv->uv[0], luv->uv[1], &screen_uv[0], &screen_uv[1]); if (BLI_rcti_isect_pt_v(&rect, screen_uv) && BLI_lasso_is_point_inside(mcords, moves, screen_uv[0], screen_uv[1], V2D_IS_CLIPPED)) @@ -3119,14 +3188,17 @@ static int snap_uvs_to_cursor(Scene *scene, Image *ima, Object *obedit, SpaceIma MLoopUV *luv; short change = 0; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tface = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tface = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tface)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (uvedit_uv_select_test(em, scene, l)) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); copy_v2_v2(luv->uv, sima->cursor); change = 1; } @@ -3146,11 +3218,13 @@ static int snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obe MTexPoly *tface; MLoopUV *luv; short change = FALSE; + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY); /* index every vert that has a selected UV using it, but only once so as to * get unique indices and to count how much to malloc */ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - tface = CustomData_bmesh_get(&bm->pdata, f->head.data, CD_MTEXPOLY); + tface = BM_ELEM_CD_GET_VOID_P(f, cd_poly_tex_offset); if (uvedit_face_visible_test(scene, ima, f, tface)) { BM_elem_flag_enable(f, BM_ELEM_TAG); BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { @@ -3173,15 +3247,14 @@ static int snap_uvs_to_adjacent_unselected(Scene *scene, Image *ima, Object *obe if (BM_elem_flag_test(lsub->f, BM_ELEM_TAG) && /* face: visible */ !BM_elem_flag_test(lsub, BM_ELEM_TAG)) /* loop: unselected */ { - - luv = CustomData_bmesh_get(&bm->ldata, lsub->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(lsub, cd_loop_uv_offset); add_v2_v2(uv, luv->uv); uv_tot++; } } if (uv_tot) { - luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); mul_v2_v2fl(luv->uv, uv, 1.0f / (float)uv_tot); change = TRUE; } @@ -3206,18 +3279,21 @@ static int snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit) float w, h; short change = 0; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + ED_space_image_get_size(sima, &width, &height); w = (float)width; h = (float)height; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tface = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tface = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tface)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (uvedit_uv_select_test(em, scene, l)) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); snap_uv_to_pixel(luv->uv, w, h); } } @@ -3295,13 +3371,16 @@ static int pin_exec(bContext *C, wmOperator *op) MLoopUV *luv; int clear = RNA_boolean_get(op->ptr, "clear"); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tface = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tface = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tface)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (!clear) { if (uvedit_uv_select_test(em, scene, l)) @@ -3349,13 +3428,16 @@ static int select_pinned_exec(bContext *C, wmOperator *UNUSED(op)) MTexPoly *tface; MLoopUV *luv; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - tface = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tface = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tface)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + 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); @@ -3387,15 +3469,17 @@ static void UV_OT_select_pinned(wmOperatorType *ot) #define UV_SEL_TEST(luv, bool_test) ((((luv)->flag & MLOOPUV_VERTSEL) == MLOOPUV_VERTSEL) == bool_test) /* is every UV vert selected or unselected depending on bool_test */ -static int bm_face_is_all_uv_sel(BMesh *bm, BMFace *f, int bool_test) +static int bm_face_is_all_uv_sel(BMFace *f, bool select_test, + const int cd_loop_uv_offset) { BMLoop *l_iter; BMLoop *l_first; l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { - MLoopUV *luv = CustomData_bmesh_get(&bm->ldata, l_iter->head.data, CD_MLOOPUV); - if (!UV_SEL_TEST(luv, bool_test)) { + + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset); + if (!UV_SEL_TEST(luv, select_test)) { return FALSE; } } while ((l_iter = l_iter->next) != l_first); @@ -3419,6 +3503,9 @@ static int hide_exec(bContext *C, wmOperator *op) Image *ima = sima ? sima->image : NULL; const int use_face_center = (ts->uv_selectmode == UV_SELECT_FACE); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); + if (ts->uv_flag & UV_SYNC_SELECTION) { EDBM_mesh_hide(em, swap); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); @@ -3429,14 +3516,14 @@ static int hide_exec(bContext *C, wmOperator *op) BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { int hide = 0; - tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); + tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); if (!uvedit_face_visible_test(scene, ima, efa, tf)) { continue; } BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (UV_SEL_TEST(luv, !swap)) { hide = 1; @@ -3450,15 +3537,15 @@ static int hide_exec(bContext *C, wmOperator *op) if (use_face_center) { if (em->selectmode == SCE_SELECT_FACE) { /* check that every UV is selected */ - if (bm_face_is_all_uv_sel(em->bm, efa, TRUE) == !swap) { + if (bm_face_is_all_uv_sel(efa, true, cd_loop_uv_offset) == !swap) { BM_face_select_set(em->bm, efa, FALSE); } uvedit_face_select_disable(scene, em, efa); } else { - if (bm_face_is_all_uv_sel(em->bm, efa, TRUE) == !swap) { + if (bm_face_is_all_uv_sel(efa, true, cd_loop_uv_offset) == !swap) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (UV_SEL_TEST(luv, !swap)) { BM_vert_select_set(em->bm, l->v, FALSE); } @@ -3469,14 +3556,14 @@ static int hide_exec(bContext *C, wmOperator *op) } else if (em->selectmode == SCE_SELECT_FACE) { /* check if a UV is de-selected */ - if (bm_face_is_all_uv_sel(em->bm, efa, FALSE) != !swap) { + if (bm_face_is_all_uv_sel(efa, false, cd_loop_uv_offset) != !swap) { BM_face_select_set(em->bm, efa, FALSE); uvedit_face_select_disable(scene, em, efa); } } else { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); if (UV_SEL_TEST(luv, !swap)) { BM_vert_select_set(em->bm, l->v, FALSE); if (!swap) luv->flag &= ~MLOOPUV_VERTSEL; @@ -3530,6 +3617,8 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) const int use_face_center = (ts->uv_selectmode == UV_SELECT_FACE); const int stickymode = sima ? (sima->sticky != SI_STICKY_DISABLE) : 1; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + /* note on tagging, selecting faces needs to be delayed so it doesn't select the verts and * confuse our checks on selected verts. */ @@ -3546,7 +3635,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) BM_elem_flag_disable(efa, BM_ELEM_TAG); if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag |= MLOOPUV_VERTSEL; } /* BM_face_select_set(em->bm, efa, TRUE); */ @@ -3567,7 +3656,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) if (!totsel) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag |= MLOOPUV_VERTSEL; } /* BM_face_select_set(em->bm, efa, TRUE); */ @@ -3582,7 +3671,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (BM_elem_flag_test(l->v, BM_ELEM_SELECT) == 0) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag |= MLOOPUV_VERTSEL; } } @@ -3598,7 +3687,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) BM_elem_flag_disable(efa, BM_ELEM_TAG); if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag |= MLOOPUV_VERTSEL; } /* BM_face_select_set(em->bm, efa, TRUE); */ @@ -3612,7 +3701,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) { BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (BM_elem_flag_test(l->v, BM_ELEM_SELECT) == 0) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->flag |= MLOOPUV_VERTSEL; } } diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index 81f548b2b5d..00b82e26a05 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -161,13 +161,16 @@ static int ED_uvedit_ensure_uvs(bContext *C, Scene *scene, Object *obedit) /****************** Parametrizer Conversion ***************/ -static int uvedit_have_selection(Scene *scene, BMEditMesh *em, short implicit) +static bool uvedit_have_selection(Scene *scene, BMEditMesh *em, bool implicit) { BMFace *efa; BMLoop *l; BMIter iter, liter; - MLoopUV *luv; + if (!CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV)) { + return (em->bm->totfacesel != 0); + } + /* verify if we have any selected uv's before unwrapping, * so we can cancel the operator early */ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { @@ -175,14 +178,10 @@ static int uvedit_have_selection(Scene *scene, BMEditMesh *em, short implicit) if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) continue; } - else if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) || !BM_elem_flag_test(efa, BM_ELEM_SELECT)) + else if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); - if (!luv) - return 1; - if (uvedit_uv_select_test(em, scene, l)) break; } @@ -190,10 +189,10 @@ static int uvedit_have_selection(Scene *scene, BMEditMesh *em, short implicit) if (implicit && !l) continue; - return 1; + return true; } - return 0; + return false; } void uvedit_get_aspect(Scene *scene, Object *ob, BMEditMesh *em, float *aspx, float *aspy) @@ -226,6 +225,7 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh short implicit, short fill, short sel, short correct_aspect) { + BMesh *bm = em->bm; ScanFillContext sf_ctx; ParamHandle *handle; BMFace *efa; @@ -233,8 +233,11 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh BMEdge *eed; BMIter iter, liter; + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + handle = param_construct_begin(); + if (correct_aspect) { float aspx, aspy; @@ -284,7 +287,7 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh * about which split is best for unwrapping than scanfill */ i = 0; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); vkeys[i] = (ParamKey)BM_elem_index_get(l->v); co[i] = l->v->co; uv[i] = luv->uv; @@ -332,7 +335,7 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh ls[2] = sf_tri->v3->tmp.p; for (i = 0; i < 3; i++) { - MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, ls[i]->head.data, CD_MLOOPUV); + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(ls[i], cd_loop_uv_offset); vkeys[i] = (ParamKey)BM_elem_index_get(ls[i]->v); co[i] = ls[i]->v->co; uv[i] = luv->uv; @@ -364,7 +367,8 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMEditMesh } -static void texface_from_original_index(BMFace *efa, int index, float **uv, ParamBool *pin, ParamBool *select, Scene *scene, BMEditMesh *em) +static void texface_from_original_index(BMFace *efa, int index, float **uv, ParamBool *pin, ParamBool *select, + Scene *scene, BMEditMesh *em, const int cd_loop_uv_offset) { BMLoop *l; BMIter liter; @@ -379,10 +383,11 @@ static void texface_from_original_index(BMFace *efa, int index, float **uv, Para BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (BM_elem_index_get(l->v) == index) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); *uv = luv->uv; *pin = (luv->flag & MLOOPUV_PINNED) ? 1 : 0; *select = (uvedit_uv_select_test(em, scene, l) != 0); + break; } } } @@ -418,6 +423,8 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, B /* similar to the above, we need a way to map edges to their original ones */ BMEdge **edgeMap; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + handle = param_construct_begin(); if (correct_aspect) { @@ -506,10 +513,10 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene, Object *ob, B /* This is where all the magic is done. If the vertex exists in the, we pass the original uv pointer to the solver, thus * flushing the solution to the edit mesh. */ - texface_from_original_index(origFace, origVertIndices[face->v1], &uv[0], &pin[0], &select[0], scene, em); - texface_from_original_index(origFace, origVertIndices[face->v2], &uv[1], &pin[1], &select[1], scene, em); - texface_from_original_index(origFace, origVertIndices[face->v3], &uv[2], &pin[2], &select[2], scene, em); - texface_from_original_index(origFace, origVertIndices[face->v4], &uv[3], &pin[3], &select[3], scene, em); + texface_from_original_index(origFace, origVertIndices[face->v1], &uv[0], &pin[0], &select[0], scene, em, cd_loop_uv_offset); + texface_from_original_index(origFace, origVertIndices[face->v2], &uv[1], &pin[1], &select[1], scene, em, cd_loop_uv_offset); + texface_from_original_index(origFace, origVertIndices[face->v3], &uv[2], &pin[2], &select[2], scene, em, cd_loop_uv_offset); + texface_from_original_index(origFace, origVertIndices[face->v4], &uv[3], &pin[3], &select[3], scene, em, cd_loop_uv_offset); param_face_add(handle, key, 4, vkeys, co, uv, pin, select); } @@ -547,17 +554,17 @@ typedef struct MinStretch { wmTimer *timer; } MinStretch; -static int minimize_stretch_init(bContext *C, wmOperator *op) +static bool minimize_stretch_init(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); MinStretch *ms; int fill_holes = RNA_boolean_get(op->ptr, "fill_holes"); - short implicit = 1; + bool implicit = true; if (!uvedit_have_selection(scene, em, implicit)) { - return 0; + return false; } ms = MEM_callocN(sizeof(MinStretch), "MinStretch"); @@ -576,7 +583,7 @@ static int minimize_stretch_init(bContext *C, wmOperator *op) op->customdata = ms; - return 1; + return true; } static void minimize_stretch_iteration(bContext *C, wmOperator *op, int interactive) @@ -596,7 +603,7 @@ static void minimize_stretch_iteration(bContext *C, wmOperator *op, int interact param_flush(ms->handle); if (sa) { - BLI_snprintf(str, sizeof(str), "Minimize Stretch. Blend %.2f", ms->blend); + BLI_snprintf(str, sizeof(str), "Minimize Stretch. Blend %.2f (Press + and -, or scroll wheel to set)", ms->blend); ED_area_headerprint(sa, str); } @@ -679,20 +686,24 @@ static int minimize_stretch_modal(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_FINISHED; case PADPLUSKEY: case WHEELUPMOUSE: - if (ms->blend < 0.95f) { - ms->blend += 0.1f; - ms->lasttime = 0.0f; - RNA_float_set(op->ptr, "blend", ms->blend); - minimize_stretch_iteration(C, op, 1); + if (event->val == KM_PRESS) { + if (ms->blend < 0.95f) { + ms->blend += 0.1f; + ms->lasttime = 0.0f; + RNA_float_set(op->ptr, "blend", ms->blend); + minimize_stretch_iteration(C, op, 1); + } } break; case PADMINUS: case WHEELDOWNMOUSE: - if (ms->blend > 0.05f) { - ms->blend -= 0.1f; - ms->lasttime = 0.0f; - RNA_float_set(op->ptr, "blend", ms->blend); - minimize_stretch_iteration(C, op, 1); + if (event->val == KM_PRESS) { + if (ms->blend > 0.05f) { + ms->blend -= 0.1f; + ms->lasttime = 0.0f; + RNA_float_set(op->ptr, "blend", ms->blend); + minimize_stretch_iteration(C, op, 1); + } } break; case TIMER: @@ -750,7 +761,7 @@ static int pack_islands_exec(bContext *C, wmOperator *op) Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); ParamHandle *handle; - short implicit = 1; + bool implicit = true; if (!uvedit_have_selection(scene, em, implicit)) { return OPERATOR_CANCELLED; @@ -797,7 +808,7 @@ static int average_islands_scale_exec(bContext *C, wmOperator *UNUSED(op)) Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); ParamHandle *handle; - short implicit = 1; + bool implicit = true; if (!uvedit_have_selection(scene, em, implicit)) { return OPERATOR_CANCELLED; @@ -965,18 +976,18 @@ static void uv_map_rotation_matrix(float result[4][4], RegionView3D *rv3d, Objec /* this is "kanonen gegen spatzen", a few plus minus 1 will do here */ /* i wanted to keep the reason here, so we're rotating*/ sideangle = (float)M_PI * (sideangledeg + 180.0f) / 180.0f; - rotside[0][0] = (float)cos(sideangle); - rotside[0][1] = -(float)sin(sideangle); - rotside[1][0] = (float)sin(sideangle); - rotside[1][1] = (float)cos(sideangle); - rotside[2][2] = 1.0f; + rotside[0][0] = cosf(sideangle); + rotside[0][1] = -sinf(sideangle); + rotside[1][0] = sinf(sideangle); + rotside[1][1] = cosf(sideangle); + rotside[2][2] = 1.0f; upangle = (float)M_PI * upangledeg / 180.0f; - rotup[1][1] = (float)cos(upangle) / radius; - rotup[1][2] = -(float)sin(upangle) / radius; - rotup[2][1] = (float)sin(upangle) / radius; - rotup[2][2] = (float)cos(upangle) / radius; - rotup[0][0] = (float)1.0f / radius; + rotup[1][1] = cosf(upangle) / radius; + rotup[1][2] = -sinf(upangle) / radius; + rotup[2][1] = sinf(upangle) / radius; + rotup[2][2] = cosf(upangle) / radius; + rotup[0][0] = 1.0f / radius; /* calculate transforms*/ mul_serie_m4(result, rotup, rotside, viewmatrix, rotobj, NULL, NULL, NULL, NULL); @@ -1047,6 +1058,8 @@ static void correct_uv_aspect(Scene *scene, Object *ob, BMEditMesh *em) BMFace *efa; float scale, aspx, aspy; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + uvedit_get_aspect(scene, ob, em, &aspx, &aspy); if (aspx == aspy) @@ -1056,11 +1069,11 @@ static void correct_uv_aspect(Scene *scene, Object *ob, BMEditMesh *em) scale = aspy / aspx; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!BM_elem_flag_test(efa, BM_ELEM_SELECT) || BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) + if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->uv[0] = ((luv->uv[0] - 0.5f) * scale) + 0.5f; } } @@ -1069,11 +1082,11 @@ static void correct_uv_aspect(Scene *scene, Object *ob, BMEditMesh *em) scale = aspx / aspy; BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!BM_elem_flag_test(efa, BM_ELEM_SELECT) || BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) + if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->uv[1] = ((luv->uv[1] - 0.5f) * scale) + 0.5f; } } @@ -1103,6 +1116,8 @@ static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOper int clip_to_bounds = RNA_boolean_get(op->ptr, "clip_to_bounds"); int scale_to_bounds = RNA_boolean_get(op->ptr, "scale_to_bounds"); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + /* correct for image aspect ratio */ if (correct_aspect) correct_uv_aspect(scene, ob, em); @@ -1115,7 +1130,7 @@ static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOper continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); minmax_v2v2_v2(min, max, luv->uv); } } @@ -1134,7 +1149,7 @@ static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOper continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->uv[0] = (luv->uv[0] - min[0]) * dx; luv->uv[1] = (luv->uv[1] - min[1]) * dy; @@ -1148,7 +1163,7 @@ static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOper continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); CLAMP(luv->uv[0], 0.0f, 1.0f); CLAMP(luv->uv[1], 0.0f, 1.0f); } @@ -1198,7 +1213,7 @@ static int unwrap_exec(bContext *C, wmOperator *op) int use_subsurf = RNA_boolean_get(op->ptr, "use_subsurf_data"); short use_subsurf_final; float obsize[3]; - short implicit = 0; + bool implicit = false; if (!uvedit_have_selection(scene, em, implicit)) { return OPERATOR_CANCELLED; @@ -1296,11 +1311,15 @@ static int uv_from_view_exec(bContext *C, wmOperator *op) MLoopUV *luv; float rotmat[4][4]; + int cd_loop_uv_offset; + /* add uvs if they don't exist yet */ if (!ED_uvedit_ensure_uvs(C, scene, obedit)) { return OPERATOR_CANCELLED; } + cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + /* establish the camera object, so we can default to view mapping if anything is wrong with it */ if ((rv3d->persp == RV3D_CAMOB) && (v3d->camera) && (v3d->camera->type == OB_CAMERA)) { camera = v3d->camera->data; @@ -1314,7 +1333,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); BLI_uvproject_from_view_ortho(luv->uv, l->v->co, rotmat); } } @@ -1328,7 +1347,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); BLI_uvproject_from_camera(luv->uv, l->v->co, uci); } } @@ -1344,7 +1363,7 @@ static int uv_from_view_exec(bContext *C, wmOperator *op) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); BLI_uvproject_from_view(luv->uv, l->v->co, rv3d->persmat, rotmat, ar->winx, ar->winy); } } @@ -1448,11 +1467,11 @@ static void uv_map_mirror(BMEditMesh *em, BMFace *efa, MTexPoly *UNUSED(tf)) float dx; int i, mi; - i = 0; - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); uvs[i] = luv->uv; - i++; } mi = 0; @@ -1480,11 +1499,15 @@ static int sphere_project_exec(bContext *C, wmOperator *op) MLoopUV *luv; float center[3], rotmat[4][4]; + int cd_loop_uv_offset; + /* add uvs if they don't exist yet */ if (!ED_uvedit_ensure_uvs(C, scene, obedit)) { return OPERATOR_CANCELLED; } + cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + uv_map_transform(C, op, center, rotmat); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { @@ -1492,7 +1515,7 @@ static int sphere_project_exec(bContext *C, wmOperator *op) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); uv_sphere_project(luv->uv, l->v->co, center, rotmat); } @@ -1555,11 +1578,15 @@ static int cylinder_project_exec(bContext *C, wmOperator *op) MLoopUV *luv; float center[3], rotmat[4][4]; + int cd_loop_uv_offset; + /* add uvs if they don't exist yet */ if (!ED_uvedit_ensure_uvs(C, scene, obedit)) { return OPERATOR_CANCELLED; } + cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + uv_map_transform(C, op, center, rotmat); BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { @@ -1567,7 +1594,7 @@ static int cylinder_project_exec(bContext *C, wmOperator *op) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); uv_cylinder_project(luv->uv, l->v->co, center, rotmat); } @@ -1617,11 +1644,15 @@ static int cube_project_exec(bContext *C, wmOperator *op) float cube_size, *loc, dx, dy; int cox, coy; + int cd_loop_uv_offset; + /* add uvs if they don't exist yet */ if (!ED_uvedit_ensure_uvs(C, scene, obedit)) { return OPERATOR_CANCELLED; } + cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + loc = obedit->obmat[3]; cube_size = RNA_float_get(op->ptr, "cube_size"); @@ -1639,7 +1670,7 @@ static int cube_project_exec(bContext *C, wmOperator *op) dx = dy = 0; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); luv->uv[0] = 0.5f + 0.5f * cube_size * (loc[cox] + l->v->co[cox]); luv->uv[1] = 0.5f + 0.5f * cube_size * (loc[coy] + l->v->co[coy]); diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index 7eaa4084e61..66a7c917a55 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -38,7 +38,8 @@ extern "C" { struct Image; struct ImageUser; - +struct PreviewImage; + struct GPUTexture; typedef struct GPUTexture GPUTexture; @@ -112,6 +113,8 @@ GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]); GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]); GPUTexture *GPU_texture_from_blender(struct Image *ima, struct ImageUser *iuser, int isdata, double time, int mipmap); +GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap); + void GPU_texture_free(GPUTexture *tex); void GPU_texture_ref(GPUTexture *tex); diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 20791652735..17d3ce3cd73 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -54,6 +54,7 @@ struct GPUNodeStack; struct GPUMaterial; struct GPUTexture; struct GPULamp; +struct PreviewImage; typedef struct GPUNode GPUNode; typedef struct GPUNodeLink GPUNodeLink; @@ -108,6 +109,7 @@ GPUNodeLink *GPU_attribute(int type, const char *name); GPUNodeLink *GPU_uniform(float *num); GPUNodeLink *GPU_dynamic_uniform(float *num, int dynamictype, void *data); GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser, int isdata); +GPUNodeLink *GPU_image_preview(struct PreviewImage *prv); GPUNodeLink *GPU_texture(int size, float *pixels); GPUNodeLink *GPU_dynamic_texture(struct GPUTexture *tex, int dynamictype, void *data); GPUNodeLink *GPU_builtin(GPUBuiltin builtin); @@ -122,6 +124,7 @@ GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, float obcol[4]); /* High level functions to create and use GPU materials */ GPUMaterial *GPU_material_from_blender(struct Scene *scene, struct Material *ma); +GPUMaterial *GPU_material_matcap(struct Scene *scene, struct Material *ma); void GPU_material_free(struct Material *ma); void GPU_materials_free(void); @@ -234,6 +237,7 @@ int GPU_lamp_has_shadow_buffer(GPULamp *lamp); void GPU_lamp_update_buffer_mats(GPULamp *lamp); void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsize, float winmat[4][4]); void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp); +int GPU_lamp_shadow_buffer_type(GPULamp *lamp); void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4]); void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy); diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index 5f9f68e9c99..fedcb58e1a3 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -1922,20 +1922,6 @@ static int gpu_bmesh_vert_visible_count(GHash *bm_unique_verts, return totvert; } -/* Return TRUE if all vertices in the face are visible, FALSE otherwise */ -static int gpu_bmesh_face_visible(BMFace *f) -{ - BMIter bm_iter; - BMVert *v; - - BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) { - if (BM_elem_flag_test(v, BM_ELEM_HIDDEN)) - return FALSE; - } - - return TRUE; -} - /* Return the total number of visible faces */ static int gpu_bmesh_face_visible_count(GHash *bm_faces) { @@ -1945,7 +1931,7 @@ static int gpu_bmesh_face_visible_count(GHash *bm_faces) GHASH_ITER (gh_iter, bm_faces) { BMFace *f = BLI_ghashIterator_getKey(&gh_iter); - if (gpu_bmesh_face_visible(f)) + if (!paint_is_bmesh_face_hidden(f)) totface++; } @@ -2012,24 +1998,25 @@ void GPU_update_bmesh_buffers(GPU_Buffers *buffers, BLI_assert(f->len == 3); - if (gpu_bmesh_face_visible(f)) { + if (!paint_is_bmesh_face_hidden(f)) { BMVert *v[3]; float fmask = 0; int i; - BM_iter_as_array(bm, BM_VERTS_OF_FACE, f, (void**)v, 3); + // BM_iter_as_array(bm, BM_VERTS_OF_FACE, f, (void**)v, 3); + BM_face_as_array_vert_tri(f, v); /* Average mask value */ for (i = 0; i < 3; i++) { fmask += *((float*)CustomData_bmesh_get(&bm->vdata, - v[i]->head.data, - CD_PAINT_MASK)); + v[i]->head.data, + CD_PAINT_MASK)); } fmask /= 3.0f; for (i = 0; i < 3; i++) { gpu_bmesh_vert_to_buffer_copy(v[i], bm, vert_data, - &v_index, f->no, &fmask); + &v_index, f->no, &fmask); } } } @@ -2063,12 +2050,15 @@ void GPU_update_bmesh_buffers(GPU_Buffers *buffers, GHashIterator gh_iter; GHASH_ITER (gh_iter, bm_faces) { - BMIter bm_iter; BMFace *f = BLI_ghashIterator_getKey(&gh_iter); - BMVert *v; - if (gpu_bmesh_face_visible(f)) { - BM_ITER_ELEM (v, &bm_iter, f, BM_VERTS_OF_FACE) { + if (!paint_is_bmesh_face_hidden(f)) { + BMLoop *l_iter; + BMLoop *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + BMVert *v = l_iter->v; if (use_short) { unsigned short *elem = tri_data; (*elem) = BM_elem_index_get(v); @@ -2081,7 +2071,7 @@ void GPU_update_bmesh_buffers(GPU_Buffers *buffers, elem++; tri_data = elem; } - } + } while ((l_iter = l_iter->next) != l_first); } } diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 4432627ee7e..b27a4be9f21 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -68,6 +68,9 @@ static char *glsl_material_library = NULL; static const char* GPU_DATATYPE_STR[17] = {"", "float", "vec2", "vec3", "vec4", NULL, NULL, NULL, NULL, "mat3", NULL, NULL, NULL, NULL, NULL, NULL, "mat4"}; +#define LINK_IMAGE_BLENDER 1 +#define LINK_IMAGE_PREVIEW 2 + /* GLSL code parsing for finding function definitions. * These are stored in a hash for lookup when creating a material. */ @@ -339,7 +342,7 @@ static int codegen_input_has_texture(GPUInput *input) { if (input->link) return 0; - else if (input->ima) + else if (input->ima || input->prv) return 1; else return input->tex != NULL; @@ -411,6 +414,17 @@ static void codegen_set_unique_ids(ListBase *nodes) else input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->ima)); } + else if (input->prv) { + /* input is texture from preview render, assign only one texid per + * buffer to avoid sampling the same texture twice */ + if (!BLI_ghash_haskey(bindhash, input->prv)) { + input->texid = texid++; + input->bindtex = 1; + BLI_ghash_insert(bindhash, input->prv, SET_INT_IN_POINTER(input->texid)); + } + else + input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->prv)); + } else { if (!BLI_ghash_haskey(bindhash, input->tex)) { /* input is user created texture, check tex pointer */ @@ -718,7 +732,7 @@ static void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes) continue; } - if (input->ima || input->tex) + if (input->ima || input->tex || input->prv) BLI_snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid); else BLI_snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id); @@ -726,7 +740,7 @@ static void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes) /* pass non-dynamic uniforms to opengl */ extract = 0; - if (input->ima || input->tex) { + if (input->ima || input->tex || input->prv) { if (input->bindtex) extract = 1; } @@ -762,11 +776,14 @@ void GPU_pass_bind(GPUPass *pass, double time, int mipmap) for (input=inputs->first; input; input=input->next) { if (input->ima) input->tex = GPU_texture_from_blender(input->ima, input->iuser, input->image_isdata, time, mipmap); + else if (input->prv) + input->tex = GPU_texture_from_preview(input->prv, mipmap); if (input->tex && input->bindtex) { GPU_texture_bind(input->tex, input->texid); GPU_shader_uniform_texture(shader, input->shaderloc, input->tex); } + } } @@ -781,7 +798,7 @@ void GPU_pass_update_uniforms(GPUPass *pass) /* pass dynamic inputs to opengl, others were removed */ for (input=inputs->first; input; input=input->next) - if (!(input->ima || input->tex)) + if (!(input->ima || input->tex || input->prv)) GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1, input->dynamicvec); } @@ -799,7 +816,7 @@ void GPU_pass_unbind(GPUPass *pass) if (input->tex && input->bindtex) GPU_texture_unbind(input->tex); - if (input->ima) + if (input->ima || input->prv) input->tex = NULL; } @@ -915,9 +932,13 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type) input->type = GPU_VEC4; input->source = GPU_SOURCE_TEX; - input->ima = link->ptr1; - input->iuser = link->ptr2; - input->image_isdata = link->image_isdata; + if (link->image == LINK_IMAGE_PREVIEW) + input->prv = link->ptr1; + else { + input->ima = link->ptr1; + input->iuser = link->ptr2; + input->image_isdata = link->image_isdata; + } input->textarget = GL_TEXTURE_2D; input->textype = GPU_TEX2D; MEM_freeN(link); @@ -1117,7 +1138,7 @@ GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, int isdata) { GPUNodeLink *link = GPU_node_link_create(0); - link->image= 1; + link->image= LINK_IMAGE_BLENDER; link->ptr1= ima; link->ptr2= iuser; link->image_isdata= isdata; @@ -1125,6 +1146,17 @@ GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, int isdata) return link; } +GPUNodeLink *GPU_image_preview(PreviewImage *prv) +{ + GPUNodeLink *link = GPU_node_link_create(0); + + link->image= LINK_IMAGE_PREVIEW; + link->ptr1= prv; + + return link; +} + + GPUNodeLink *GPU_texture(int size, float *pixels) { GPUNodeLink *link = GPU_node_link_create(0); diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h index f61f34908c5..2e4cfe2e37c 100644 --- a/source/blender/gpu/intern/gpu_codegen.h +++ b/source/blender/gpu/intern/gpu_codegen.h @@ -43,6 +43,7 @@ struct GPUOutput; struct GPUNode; struct GPUVertexAttribs; struct GPUFrameBuffer; +struct PreviewImage; #define MAX_FUNCTION_NAME 64 #define MAX_PARAMETER 32 @@ -138,6 +139,7 @@ typedef struct GPUInput { struct Image *ima; /* image */ struct ImageUser *iuser;/* image user */ + struct PreviewImage *prv; /* preview images & icons */ int image_isdata; /* image does not contain color data */ float *dynamicvec; /* vector data in case it is dynamic */ int dynamictype; /* origin of the dynamic uniform (GPUDynamicType) */ diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 254899e6e07..63cde9c7d59 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -52,6 +52,9 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "BLI_threads.h" +#include "BLI_blenlib.h" + #include "BKE_bmfont.h" #include "BKE_global.h" #include "BKE_image.h" @@ -62,9 +65,6 @@ #include "BKE_scene.h" #include "BKE_DerivedMesh.h" -#include "BLI_threads.h" -#include "BLI_blenlib.h" - #include "GPU_buffers.h" #include "GPU_draw.h" #include "GPU_extensions.h" @@ -664,6 +664,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int return *bind; } +/* Image *ima can be NULL */ void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float * frect, int rectw, int recth, int mipmap, int use_high_bit_depth, Image *ima) { unsigned int *scalerect = NULL; @@ -723,7 +724,8 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float * frect, int glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); - ima->tpageflag |= IMA_MIPMAP_COMPLETE; + if (ima) + ima->tpageflag |= IMA_MIPMAP_COMPLETE; } if (GLEW_EXT_texture_filter_anisotropic) @@ -1283,10 +1285,9 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O GPUMaterial *gpumat; GPUBlendMode alphablend; int a; - int gamma = BKE_scene_check_color_management_enabled(scene); - int new_shading_nodes = BKE_scene_use_new_shading_nodes(scene); + int use_matcap = (v3d->flag2 & V3D_SHOW_SOLID_MATCAP); /* assumes v3d->defmaterial->preview is set */ /* initialize state */ memset(&GMS, 0, sizeof(GMS)); @@ -1298,7 +1299,7 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O GMS.gob = ob; GMS.gscene = scene; - GMS.totmat= ob->totcol+1; /* materials start from 1, default material is 0 */ + GMS.totmat= use_matcap? 1 : ob->totcol+1; /* materials start from 1, default material is 0 */ GMS.glay= (v3d->localvd)? v3d->localvd->lay: v3d->lay; /* keep lamps visible in local view */ GMS.gviewmat= rv3d->viewmat; GMS.gviewinv= rv3d->viewinv; @@ -1324,59 +1325,72 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O GMS.alphablend= GMS.alphablend_fixed; } - /* no materials assigned? */ - if (ob->totcol==0) { - gpu_material_to_fixed(&GMS.matbuf[0], &defmaterial, 0, ob, new_shading_nodes); - + /* viewport material, setup in space_view3d, defaults to matcap using ma->preview now */ + if (use_matcap) { + GMS.gmatbuf[0] = v3d->defmaterial; + GPU_material_matcap(scene, v3d->defmaterial); + /* do material 1 too, for displists! */ memcpy(&GMS.matbuf[1], &GMS.matbuf[0], sizeof(GPUMaterialFixed)); - - if (glsl) { - GMS.gmatbuf[0]= &defmaterial; - GPU_material_from_blender(GMS.gscene, &defmaterial); - } - + GMS.alphablend[0]= GPU_BLEND_SOLID; } + else { - /* setup materials */ - for (a=1; a<=ob->totcol; a++) { - /* find a suitable material */ - ma= give_current_material(ob, a); - if (!glsl && !new_shading_nodes) ma= gpu_active_node_material(ma); - if (ma==NULL) ma= &defmaterial; - - /* create glsl material if requested */ - gpumat = (glsl)? GPU_material_from_blender(GMS.gscene, ma): NULL; - - if (gpumat) { - /* do glsl only if creating it succeed, else fallback */ - GMS.gmatbuf[a]= ma; - alphablend = GPU_material_alpha_blend(gpumat, ob->col); - } - else { - /* fixed function opengl materials */ - gpu_material_to_fixed(&GMS.matbuf[a], ma, gamma, ob, new_shading_nodes); + /* no materials assigned? */ + if (ob->totcol==0) { + gpu_material_to_fixed(&GMS.matbuf[0], &defmaterial, 0, ob, new_shading_nodes); - if (GMS.use_alpha_pass) { - GMS.matbuf[a].diff[3]= ma->alpha; - alphablend = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA; + /* do material 1 too, for displists! */ + memcpy(&GMS.matbuf[1], &GMS.matbuf[0], sizeof(GPUMaterialFixed)); + + if (glsl) { + GMS.gmatbuf[0]= &defmaterial; + GPU_material_from_blender(GMS.gscene, &defmaterial); + } + + GMS.alphablend[0]= GPU_BLEND_SOLID; + } + + /* setup materials */ + for (a=1; a<=ob->totcol; a++) { + /* find a suitable material */ + ma= give_current_material(ob, a); + if (!glsl && !new_shading_nodes) ma= gpu_active_node_material(ma); + if (ma==NULL) ma= &defmaterial; + + /* create glsl material if requested */ + gpumat = (glsl)? GPU_material_from_blender(GMS.gscene, ma): NULL; + + if (gpumat) { + /* do glsl only if creating it succeed, else fallback */ + GMS.gmatbuf[a]= ma; + alphablend = GPU_material_alpha_blend(gpumat, ob->col); } else { - GMS.matbuf[a].diff[3]= 1.0f; - alphablend = GPU_BLEND_SOLID; + /* fixed function opengl materials */ + gpu_material_to_fixed(&GMS.matbuf[a], ma, gamma, ob, new_shading_nodes); + + if (GMS.use_alpha_pass) { + GMS.matbuf[a].diff[3]= ma->alpha; + alphablend = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA; + } + else { + GMS.matbuf[a].diff[3]= 1.0f; + alphablend = GPU_BLEND_SOLID; + } } - } - /* setting 'do_alpha_after = TRUE' indicates this object needs to be - * drawn in a second alpha pass for improved blending */ - if (do_alpha_after && !GMS.is_alpha_pass) - if (ELEM3(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ADD, GPU_BLEND_ALPHA_SORT)) - *do_alpha_after = TRUE; + /* setting 'do_alpha_after = TRUE' indicates this object needs to be + * drawn in a second alpha pass for improved blending */ + if (do_alpha_after && !GMS.is_alpha_pass) + if (ELEM3(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ADD, GPU_BLEND_ALPHA_SORT)) + *do_alpha_after = TRUE; - GMS.alphablend[a]= alphablend; + GMS.alphablend[a]= alphablend; + } } - + /* let's start with a clean state */ GPU_disable_material(); } diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index bc859d0ec07..e8e47013159 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -36,13 +36,12 @@ #include "MEM_guardedalloc.h" -#include "BKE_global.h" - - #include "BLI_blenlib.h" #include "BLI_utildefines.h" #include "BLI_math_base.h" +#include "BKE_global.h" + #include "GPU_draw.h" #include "GPU_extensions.h" #include "gpu_codegen.h" @@ -539,6 +538,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int isdata, d glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode); GPU_update_image_time(ima, time); + /* this binds a texture, so that's why to restore it with lastbindcode */ bindcode = GPU_verify_image(ima, iuser, 0, 0, mipmap, isdata); if (ima->gputexture) { @@ -579,6 +579,59 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int isdata, d return tex; } +GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap) +{ + GPUTexture *tex = prv->gputexture[0]; + GLint w, h, lastbindcode; + GLuint bindcode = 0; + + glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode); + + if (tex) + bindcode = tex->bindcode; + + /* this binds a texture, so that's why to restore it */ + if (bindcode == 0) { + GPU_create_gl_tex(&bindcode, prv->rect[0], NULL, prv->w[0], prv->h[0], mipmap, 0, NULL); + } + if (tex) { + tex->bindcode = bindcode; + glBindTexture(GL_TEXTURE_2D, lastbindcode); + return tex; + } + + /* error binding anything */ + if (!bindcode) { + glBindTexture(GL_TEXTURE_2D, lastbindcode); + return NULL; + } + + tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); + tex->bindcode = bindcode; + tex->number = -1; + tex->refcount = 1; + tex->target = GL_TEXTURE_2D; + + prv->gputexture[0]= tex; + + if (!glIsTexture(tex->bindcode)) { + GPU_print_error("Blender Texture"); + } + else { + glBindTexture(GL_TEXTURE_2D, tex->bindcode); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h); + + tex->w = w; + tex->h = h; + } + + glBindTexture(GL_TEXTURE_2D, lastbindcode); + + return tex; + +} + GPUTexture *GPU_texture_create_1D(int w, float *fpixels, char err_out[256]) { GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, err_out); diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index a2fc1eb05ec..9731d7a6b3a 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -1506,6 +1506,52 @@ static GPUNodeLink *gpu_material_diffuse_bsdf(GPUMaterial *mat, Material *ma) return outlink; } +static GPUNodeLink *gpu_material_preview_matcap(GPUMaterial *mat, Material *ma) +{ + GPUNodeLink *outlink; + + GPU_link(mat, "material_preview_matcap", GPU_uniform(&ma->r), GPU_image_preview(ma->preview), GPU_builtin(GPU_VIEW_NORMAL), &outlink); + + return outlink; +} + +/* new solid draw mode with glsl matcaps */ +GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma) +{ + GPUMaterial *mat; + GPUNodeLink *outlink; + LinkData *link; + + for (link=ma->gpumaterial.first; link; link=link->next) + if (((GPUMaterial*)link->data)->scene == scene) + return link->data; + + /* allocate material */ + mat = GPU_material_construct_begin(ma); + mat->scene = scene; + + if (ma->preview && ma->preview->rect[0]) { + outlink = gpu_material_preview_matcap(mat, ma); + } + else { + outlink = gpu_material_diffuse_bsdf(mat, ma); + } + + GPU_material_output_link(mat, outlink); + + GPU_material_construct_end(mat); + + /* note that even if building the shader fails in some way, we still keep + * it to avoid trying to compile again and again, and simple do not use + * the actual shader on drawing */ + + link = MEM_callocN(sizeof(LinkData), "GPUMaterialLink"); + link->data = mat; + BLI_addtail(&ma->gpumaterial, link); + + return mat; +} + GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma) { GPUMaterial *mat; @@ -1882,6 +1928,11 @@ void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp) glEnable(GL_SCISSOR_TEST); } +int GPU_lamp_shadow_buffer_type(GPULamp *lamp) +{ + return lamp->la->shadowmap_type; +} + int GPU_lamp_shadow_layer(GPULamp *lamp) { if (lamp->fb && lamp->tex && (lamp->mode & (LA_LAYER|LA_LAYER_SHADOW))) diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index e89be91c89a..45e7831d20d 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -2256,3 +2256,18 @@ void node_output_material(vec4 surface, vec4 volume, float displacement, out vec result = surface; } +/* ********************** matcap style render ******************** */ + +void material_preview_matcap(vec4 color, sampler2D ima, vec3 N, out vec4 result) +{ + vec2 tex; + + if (N.z < 0.0) { + N.z = 0.0; + N = normalize(N); + } + + tex.x = 0.5 + 0.49 * N.x; + tex.y = 0.5 + 0.49 * N.y; + result = texture2D(ima, tex); +} diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c index 8dfdbd4fddc..8d79482ed18 100644 --- a/source/blender/imbuf/intern/anim_movie.c +++ b/source/blender/imbuf/intern/anim_movie.c @@ -486,7 +486,7 @@ static int startffmpeg(struct anim *anim) return -1; } - if (av_find_stream_info(pFormatCtx) < 0) { + if (avformat_find_stream_info(pFormatCtx, NULL) < 0) { av_close_input_file(pFormatCtx); return -1; } @@ -523,7 +523,7 @@ static int startffmpeg(struct anim *anim) pCodecCtx->workaround_bugs = 1; - if (avcodec_open(pCodecCtx, pCodec) < 0) { + if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { av_close_input_file(pFormatCtx); return -1; } diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 2c6e46cb664..86f47fe07c4 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1222,7 +1222,7 @@ static void *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle) } else if (channels == 4) { rgba_uchar_to_float(fp, cp); - straight_to_premul_v4(fp, fp); + straight_to_premul_v4(fp); } else { BLI_assert(!"Buffers of 3 or 4 channels are only supported here"); @@ -2347,7 +2347,7 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe else if (byte_buffer) { rgba_uchar_to_float(pixel, byte_buffer + linear_index); IMB_colormanagement_colorspace_to_scene_linear_v3(pixel, rect_colorspace); - straight_to_premul_v4(pixel, pixel); + straight_to_premul_v4(pixel); } if (!is_data) { @@ -2361,7 +2361,7 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe } else { float pixel_straight[4]; - premul_to_straight_v4(pixel_straight, pixel); + premul_to_straight_v4_v4(pixel_straight, pixel); rgba_float_to_uchar(display_buffer + display_index, pixel_straight); } } diff --git a/source/blender/imbuf/intern/dds/Stream.cpp b/source/blender/imbuf/intern/dds/Stream.cpp index 00e1b679c69..57a251261a1 100644 --- a/source/blender/imbuf/intern/dds/Stream.cpp +++ b/source/blender/imbuf/intern/dds/Stream.cpp @@ -47,7 +47,7 @@ unsigned int mem_read(Stream & mem, unsigned long long & i) if (mem.pos + 8 > mem.size) { printf("DDS: trying to read beyond end of stream (corrupt file?)"); return(0); - }; + } memcpy(&i, mem.mem + mem.pos, 8); // @@ todo: make sure little endian mem.pos += 8; return(8); @@ -58,7 +58,7 @@ unsigned int mem_read(Stream & mem, unsigned int & i) if (mem.pos + 4 > mem.size) { printf("DDS: trying to read beyond end of stream (corrupt file?)"); return(0); - }; + } memcpy(&i, mem.mem + mem.pos, 4); // @@ todo: make sure little endian mem.pos += 4; return(4); @@ -69,7 +69,7 @@ unsigned int mem_read(Stream & mem, unsigned short & i) if (mem.pos + 2 > mem.size) { printf("DDS: trying to read beyond end of stream (corrupt file?)"); return(0); - }; + } memcpy(&i, mem.mem + mem.pos, 2); // @@ todo: make sure little endian mem.pos += 2; return(2); @@ -80,7 +80,7 @@ unsigned int mem_read(Stream & mem, unsigned char & i) if (mem.pos + 1 > mem.size) { printf("DDS: trying to read beyond end of stream (corrupt file?)"); return(0); - }; + } i = (mem.mem + mem.pos)[0]; mem.pos += 1; return(1); @@ -91,7 +91,7 @@ unsigned int mem_read(Stream & mem, unsigned char *i, unsigned int cnt) if (mem.pos + cnt > mem.size) { printf("DDS: trying to read beyond end of stream (corrupt file?)"); return(0); - }; + } memcpy(i, mem.mem + mem.pos, cnt); mem.pos += cnt; return(cnt); diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp index c41bbd594b3..4098b466377 100644 --- a/source/blender/imbuf/intern/dds/dds_api.cpp +++ b/source/blender/imbuf/intern/dds/dds_api.cpp @@ -136,9 +136,9 @@ struct ImBuf *imb_load_dds(unsigned char *mem, size_t size, int flags, char colo if (pixel.a != 255) { bits_per_pixel = 32; break; - }; - }; - }; + } + } + } ibuf = IMB_allocImBuf(dds.width(), dds.height(), bits_per_pixel, 0); if (ibuf == 0) return(0); /* memory allocation failed */ diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index 84339b51721..20d51fddb35 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -255,7 +255,7 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, /* no color space conversion */ if (dither && predivide) { for (x = 0; x < width; x++, from += 4, to += 4) { - premul_to_straight_v4(straight, from); + premul_to_straight_v4_v4(straight, from); float_to_byte_dither_v4(to, straight, di); } } @@ -265,7 +265,7 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, } else if (predivide) { for (x = 0; x < width; x++, from += 4, to += 4) { - premul_to_straight_v4(straight, from); + premul_to_straight_v4_v4(straight, from); rgba_float_to_uchar(to, straight); } } @@ -281,7 +281,7 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, if (dither && predivide) { for (x = 0; x < width; x++, from += 4, to += 4) { - premul_to_straight_v4(straight, from); + premul_to_straight_v4_v4(straight, from); linearrgb_to_srgb_ushort4(us, from); ushort_to_byte_dither_v4(to, us, di); } @@ -294,7 +294,7 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, } else if (predivide) { for (x = 0; x < width; x++, from += 4, to += 4) { - premul_to_straight_v4(straight, from); + premul_to_straight_v4_v4(straight, from); linearrgb_to_srgb_ushort4(us, from); ushort_to_byte_v4(to, us); } @@ -690,20 +690,20 @@ void IMB_buffer_float_clamp(float *buf, int width, int height) void IMB_buffer_float_unpremultiply(float *buf, int width, int height) { int total = width * height; - float *cp = buf; + float *fp = buf; while (total--) { - premul_to_straight_v4(cp, cp); - cp += 4; + premul_to_straight_v4(fp); + fp += 4; } } void IMB_buffer_float_premultiply(float *buf, int width, int height) { int total = width * height; - float *cp = buf; + float *fp = buf; while (total--) { - straight_to_premul_v4(cp, cp); - cp += 4; + straight_to_premul_v4(fp); + fp += 4; } } diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c index 277f50bcdbc..56e5be7c12a 100644 --- a/source/blender/imbuf/intern/indexer.c +++ b/source/blender/imbuf/intern/indexer.c @@ -332,7 +332,7 @@ int IMB_proxy_size_to_array_index(IMB_Proxy_Size pr_size) return 3; default: return 0; - }; + } return 0; } @@ -352,7 +352,7 @@ int IMB_timecode_to_array_index(IMB_Timecode_Type tc) return 3; default: return 0; - }; + } return 0; } @@ -496,7 +496,9 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg( fprintf(stderr, "Starting work on proxy: %s\n", rv->of->filename); - rv->st = av_new_stream(rv->of, 0); + rv->st = avformat_new_stream(rv->of, NULL); + rv->st->id = 0; + rv->c = rv->st->codec; rv->c->codec_type = AVMEDIA_TYPE_VIDEO; rv->c->codec_id = CODEC_ID_MJPEG; @@ -531,8 +533,8 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg( /* there's no way to set JPEG quality in the same way as in AVI JPEG and image sequence, * but this seems to be giving expected quality result */ ffmpeg_quality = (int)(1.0f + 30.0f * (1.0f - (float)quality / 100.0f) + 0.5f); - av_set_int(rv->c, "qmin", ffmpeg_quality); - av_set_int(rv->c, "qmax", ffmpeg_quality); + av_opt_set_int(rv->c, "qmin", ffmpeg_quality, 0); + av_opt_set_int(rv->c, "qmax", ffmpeg_quality, 0); if (rv->of->flags & AVFMT_GLOBALHEADER) { rv->c->flags |= CODEC_FLAG_GLOBAL_HEADER; @@ -545,7 +547,7 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg( return 0; } - avcodec_open(rv->c, rv->codec); + avcodec_open2(rv->c, rv->codec, NULL); rv->video_buffersize = 2000000; rv->video_buffer = (uint8_t *)MEM_mallocN( @@ -758,7 +760,7 @@ static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim, IMB_Tim return NULL; } - if (av_find_stream_info(context->iFormatCtx) < 0) { + if (avformat_find_stream_info(context->iFormatCtx, NULL) < 0) { av_close_input_file(context->iFormatCtx); MEM_freeN(context); return NULL; @@ -797,7 +799,7 @@ static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim, IMB_Tim context->iCodecCtx->workaround_bugs = 1; - if (avcodec_open(context->iCodecCtx, context->iCodec) < 0) { + if (avcodec_open2(context->iCodecCtx, context->iCodec, NULL) < 0) { av_close_input_file(context->iFormatCtx); MEM_freeN(context); return NULL; diff --git a/source/blender/imbuf/intern/jp2.c b/source/blender/imbuf/intern/jp2.c index 8d6218a389e..ff0aeb068e2 100644 --- a/source/blender/imbuf/intern/jp2.c +++ b/source/blender/imbuf/intern/jp2.c @@ -556,7 +556,7 @@ static float channel_colormanage_noop(float value) static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters) { unsigned char *rect_uchar; - float *rect_float; + float *rect_float, from_straight[4]; unsigned int subsampling_dx = parameters->subsampling_dx; unsigned int subsampling_dy = parameters->subsampling_dy; @@ -668,19 +668,21 @@ static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters) if (numcomps == 4) { PIXEL_LOOPER_BEGIN(rect_float) { - r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[2])); - a[i] = DOWNSAMPLE_FLOAT_TO_8BIT(rect_float[3]); + premul_to_straight_v4_v4(from_straight, rect_float); + r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[2])); + a[i] = DOWNSAMPLE_FLOAT_TO_8BIT(from_straight[3]); } PIXEL_LOOPER_END; } else { PIXEL_LOOPER_BEGIN(rect_float) { - r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(rect_float[2])); + premul_to_straight_v4_v4(from_straight, rect_float); + r[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_8BIT(chanel_colormanage_cb(from_straight[2])); } PIXEL_LOOPER_END; } @@ -690,19 +692,21 @@ static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters) if (numcomps == 4) { PIXEL_LOOPER_BEGIN(rect_float) { - r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[2])); - a[i] = DOWNSAMPLE_FLOAT_TO_12BIT(rect_float[3]); + premul_to_straight_v4_v4(from_straight, rect_float); + r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[2])); + a[i] = DOWNSAMPLE_FLOAT_TO_12BIT(from_straight[3]); } PIXEL_LOOPER_END; } else { PIXEL_LOOPER_BEGIN(rect_float) { - r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(rect_float[2])); + premul_to_straight_v4_v4(from_straight, rect_float); + r[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_12BIT(chanel_colormanage_cb(from_straight[2])); } PIXEL_LOOPER_END; } @@ -712,19 +716,21 @@ static opj_image_t *ibuftoimage(ImBuf *ibuf, opj_cparameters_t *parameters) if (numcomps == 4) { PIXEL_LOOPER_BEGIN(rect_float) { - r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[2])); - a[i] = DOWNSAMPLE_FLOAT_TO_16BIT(rect_float[3]); + premul_to_straight_v4_v4(from_straight, rect_float); + r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[2])); + a[i] = DOWNSAMPLE_FLOAT_TO_16BIT(from_straight[3]); } PIXEL_LOOPER_END; } else { PIXEL_LOOPER_BEGIN(rect_float) { - r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[0])); - g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[1])); - b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(rect_float[2])); + premul_to_straight_v4_v4(from_straight, rect_float); + r[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[0])); + g[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[1])); + b[i] = DOWNSAMPLE_FLOAT_TO_16BIT(chanel_colormanage_cb(from_straight[2])); } PIXEL_LOOPER_END; } diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c index bbe43132051..cc73f688e70 100644 --- a/source/blender/imbuf/intern/png.c +++ b/source/blender/imbuf/intern/png.c @@ -60,6 +60,11 @@ static void ReadData(png_structp png_ptr, png_bytep data, png_size_t length); static void WriteData(png_structp png_ptr, png_bytep data, png_size_t length); static void Flush(png_structp png_ptr); +BLI_INLINE unsigned short UPSAMPLE_8_TO_16(const unsigned char _val) +{ + return (_val << 8) + _val; +} + int imb_is_a_png(unsigned char *mem) { int ret_val = 0; @@ -102,6 +107,17 @@ static void ReadData(png_structp png_ptr, png_bytep data, png_size_t length) longjmp(png_jmpbuf(png_ptr), 1); } +static float channel_colormanage_noop(float value) +{ + return value; +} + +/* wrap to avoid macro calling functions multiple times */ +BLI_INLINE unsigned short ftoshort(float val) +{ + return FTOUSHORT(val); +} + int imb_savepng(struct ImBuf *ibuf, const char *name, int flags) { png_structp png_ptr; @@ -115,13 +131,25 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags) int i, bytesperpixel, color_type = PNG_COLOR_TYPE_GRAY; FILE *fp = NULL; - int is_16bit = (ibuf->ftype & PNG_16BIT) && ibuf->rect_float; + bool is_16bit = (ibuf->ftype & PNG_16BIT); + bool has_float = (ibuf->rect_float != NULL); + + float (*chanel_colormanage_cb)(float); /* use the jpeg quality setting for compression */ int compression; compression = (int)(((float)(ibuf->ftype & 0xff) / 11.1111f)); compression = compression < 0 ? 0 : (compression > 9 ? 9 : compression); + if (ibuf->float_colorspace) { + /* float buffer was managed already, no need in color space conversion */ + chanel_colormanage_cb = channel_colormanage_noop; + } + else { + /* standard linear-to-srgb conversion if float buffer wasn't managed */ + chanel_colormanage_cb = linearrgb_to_srgb; + } + /* for prints */ if (flags & IB_mem) name = "<memory>"; @@ -174,13 +202,24 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags) case 4: color_type = PNG_COLOR_TYPE_RGBA; if (is_16bit) { - for (i = ibuf->x * ibuf->y; i > 0; i--) { - premul_to_straight_v4(from_straight, from_float); - to16[0] = FTOUSHORT(from_straight[0]); - to16[1] = FTOUSHORT(from_straight[1]); - to16[2] = FTOUSHORT(from_straight[2]); - to16[3] = FTOUSHORT(from_straight[3]); - to16 += 4; from_float += 4; + if (has_float) { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + premul_to_straight_v4_v4(from_straight, from_float); + to16[0] = ftoshort(chanel_colormanage_cb(from_straight[0])); + to16[1] = ftoshort(chanel_colormanage_cb(from_straight[1])); + to16[2] = ftoshort(chanel_colormanage_cb(from_straight[2])); + to16[3] = ftoshort(chanel_colormanage_cb(from_straight[3])); + to16 += 4; from_float += 4; + } + } + else { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to16[0] = UPSAMPLE_8_TO_16(from[0]); + to16[1] = UPSAMPLE_8_TO_16(from[1]); + to16[2] = UPSAMPLE_8_TO_16(from[2]); + to16[3] = UPSAMPLE_8_TO_16(from[3]); + to16 += 4; from += 4; + } } } else { @@ -196,12 +235,22 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags) case 3: color_type = PNG_COLOR_TYPE_RGB; if (is_16bit) { - for (i = ibuf->x * ibuf->y; i > 0; i--) { - premul_to_straight_v4(from_straight, from_float); - to16[0] = FTOUSHORT(from_straight[0]); - to16[1] = FTOUSHORT(from_straight[1]); - to16[2] = FTOUSHORT(from_straight[2]); - to16 += 3; from_float += 4; + if (has_float) { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + premul_to_straight_v4_v4(from_straight, from_float); + to16[0] = ftoshort(chanel_colormanage_cb(from_straight[0])); + to16[1] = ftoshort(chanel_colormanage_cb(from_straight[1])); + to16[2] = ftoshort(chanel_colormanage_cb(from_straight[2])); + to16 += 3; from_float += 4; + } + } + else { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to16[0] = UPSAMPLE_8_TO_16(from[0]); + to16[1] = UPSAMPLE_8_TO_16(from[1]); + to16[2] = UPSAMPLE_8_TO_16(from[2]); + to16 += 3; from += 4; + } } } else { @@ -216,10 +265,18 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags) case 1: color_type = PNG_COLOR_TYPE_GRAY; if (is_16bit) { - for (i = ibuf->x * ibuf->y; i > 0; i--) { - premul_to_straight_v4(from_straight, from_float); - to16[0] = FTOUSHORT(from_straight[0]); - to16++; from_float += 4; + if (has_float) { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + premul_to_straight_v4_v4(from_straight, from_float); + to16[0] = ftoshort(chanel_colormanage_cb(from_straight[0])); + to16++; from_float += 4; + } + } + else { + for (i = ibuf->x * ibuf->y; i > 0; i--) { + to16[0] = UPSAMPLE_8_TO_16(from[0]); + to16++; from += 4; + } } } else { diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c index 42fb0c79b62..549a95e383d 100644 --- a/source/blender/imbuf/intern/util.c +++ b/source/blender/imbuf/intern/util.c @@ -306,8 +306,8 @@ static int isffmpeg(const char *filename) return 0; } - if (av_find_stream_info(pFormatCtx) < 0) { - if (UTIL_DEBUG) fprintf(stderr, "isffmpeg: av_find_stream_info failed\n"); + if (avformat_find_stream_info(pFormatCtx, NULL) < 0) { + if (UTIL_DEBUG) fprintf(stderr, "isffmpeg: avformat_find_stream_info failed\n"); av_close_input_file(pFormatCtx); return 0; } @@ -340,7 +340,7 @@ static int isffmpeg(const char *filename) return 0; } - if (avcodec_open(pCodecCtx, pCodec) < 0) { + if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { av_close_input_file(pFormatCtx); return 0; } diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 68896992287..a3a3d80133f 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -43,7 +43,8 @@ struct Library; struct FileData; struct ID; struct PackedFile; - +struct GPUTexture; + typedef struct IDPropertyData { void *pointer; ListBase group; @@ -154,6 +155,7 @@ typedef struct PreviewImage { short changed[2]; short changed_timestamp[2]; unsigned int *rect[2]; + struct GPUTexture *gputexture[2]; } PreviewImage; /** @@ -234,7 +236,8 @@ typedef struct PreviewImage { #ifdef GS # undef GS #endif -#define GS(a) (*((short *)(a))) +// #define GS(a) (*((short *)(a))) +#define GS(a) (CHECK_TYPE_INLINE(a, const char), (*((short *)(a)))) #define ID_NEW(a) if ( (a) && (a)->id.newid ) (a) = (void *)(a)->id.newid #define ID_NEW_US(a) if ( (a)->id.newid) { (a) = (void *)(a)->id.newid; (a)->id.us++; } diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index e3571c767bd..41c47f8de15 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -112,7 +112,7 @@ typedef enum BrushFlags { BRUSH_SIZE_PRESSURE = (1 << 3), BRUSH_JITTER_PRESSURE = (1 << 4), BRUSH_SPACING_PRESSURE = (1 << 5), - BRUSH_FIXED_TEX = (1 << 6), + // BRUSH_FIXED_TEX = (1 << 6), /* obsolete, use mtex->brush_map_mode = MTEX_MAP_MODE_TILED instead */ BRUSH_RAKE = (1 << 7), BRUSH_ANCHORED = (1 << 8), BRUSH_DIR_IN = (1 << 9), @@ -164,10 +164,12 @@ typedef enum BrushSculptTool { } BrushSculptTool; /* ImagePaintSettings.tool */ -#define PAINT_TOOL_DRAW 0 -#define PAINT_TOOL_SOFTEN 1 -#define PAINT_TOOL_SMEAR 2 -#define PAINT_TOOL_CLONE 3 +typedef enum BrushImagePaintTool{ + PAINT_TOOL_DRAW = 0, + PAINT_TOOL_SOFTEN = 1, + PAINT_TOOL_SMEAR = 2, + PAINT_TOOL_CLONE = 3 +} BrushImagePaintTool; /* direction that the brush displaces along */ enum { diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index 919aa092616..544535303bd 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -314,7 +314,7 @@ typedef struct Material { #define MA_SPEC_WARDISO 4 /* dynamode */ -#define MA_DRAW_DYNABUTS 1 /* deprecated */ +// #define MA_DRAW_DYNABUTS 1 /* deprecated */ #define MA_FH_NOR 2 /* ramps */ @@ -378,7 +378,7 @@ typedef struct Material { #define MAP_AMB 2048 #define MAP_DISPLACE 4096 #define MAP_WARP 8192 -#define MAP_LAYER 16384 /* unused */ +// #define MAP_LAYER 16384 /* unused */ /* volume mapto - reuse definitions for now - a bit naughty! */ #define MAP_DENSITY 128 diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index da666059601..042a353642a 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -186,7 +186,7 @@ typedef struct TFace { #define ME_DRAWNORMALS (1 << 2) #define ME_DRAW_VNORMALS (1 << 3) -#define ME_ALLEDGES (1 << 4) +// #define ME_ALLEDGES (1 << 4) #define ME_HIDDENEDGES (1 << 5) #define ME_DRAWCREASES (1 << 6) diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 089103c66e5..117eac0e42b 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -77,7 +77,8 @@ typedef enum ModifierType { eModifierType_Skin = 42, eModifierType_LaplacianSmooth = 43, eModifierType_Triangulate = 44, - eModifierType_UVWarp = 45, + eModifierType_UVWarp = 45, + eModifierType_MeshCache = 46, NUM_MODIFIER_TYPES } ModifierType; @@ -1133,6 +1134,7 @@ enum { #define MOD_LAPLACIANSMOOTH_Y (1<<2) #define MOD_LAPLACIANSMOOTH_Z (1<<3) #define MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME (1 << 4) +#define MOD_LAPLACIANSMOOTH_NORMALIZED (1 << 5) typedef struct LaplacianSmoothModifierData { ModifierData modifier; @@ -1157,4 +1159,64 @@ typedef struct UVWarpModifierData { char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ } UVWarpModifierData; +/* cache modifier */ +typedef struct MeshCacheModifierData { + ModifierData modifier; + char flag; + char type; /* file format */ + char time_mode; + char play_mode; + + /* axis conversion */ + char forward_axis; + char up_axis; + char flip_axis; + + char interp; + + float factor; + char deform_mode; + char pad[7]; + + /* play_mode == MOD_MESHCACHE_PLAY_CFEA */ + float frame_start; + float frame_scale; + + /* play_mode == MOD_MESHCACHE_PLAY_EVAL */ + /* we could use one float for all these but their purpose is very different */ + float eval_frame; + float eval_time; + float eval_factor; + + char filepath[1024]; // FILE_MAX +} MeshCacheModifierData; + +enum { + MOD_MESHCACHE_TYPE_MDD = 1, + MOD_MESHCACHE_TYPE_PC2 = 2 +}; + +enum { + MOD_MESHCACHE_DEFORM_OVERWRITE = 0, + MOD_MESHCACHE_DEFORM_INTEGRATE = 1 +}; + +enum { + MOD_MESHCACHE_INTERP_NONE = 0, + MOD_MESHCACHE_INTERP_LINEAR = 1, + // MOD_MESHCACHE_INTERP_CARDINAL = 2 +}; + +enum { + MOD_MESHCACHE_TIME_FRAME = 0, + MOD_MESHCACHE_TIME_SECONDS = 1, + MOD_MESHCACHE_TIME_FACTOR = 2, +}; + +enum { + MOD_MESHCACHE_PLAY_CFEA = 0, + MOD_MESHCACHE_PLAY_EVAL = 1, +}; + + #endif /* __DNA_MODIFIER_TYPES_H__ */ diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 559ba446740..de34f101c31 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -56,6 +56,7 @@ struct ParticleSystem; struct DerivedMesh; struct SculptSession; struct bGPdata; +struct RigidBodyOb; /* Vertex Groups - Name Info */ @@ -170,7 +171,7 @@ typedef struct Object { float sf; /* sf is time-offset */ short flag; /* copy of Base */ - short colbits DNA_DEPRECATED; /* deprecated */ + short colbits DNA_DEPRECATED; /* deprecated, use 'matbits' */ short transflag, protectflag; /* transformation settings and transform locks */ short trackflag, upflag; @@ -218,10 +219,8 @@ typedef struct Object { char boundtype; /* bounding box use for drawing */ char collision_boundtype; /* bounding box type used for collision */ - char restrictflag; /* for restricting view, select, render etc. accessible in outliner */ - + short dtx; /* viewport draw extra settings */ char dt; /* viewport draw type */ - char dtx; /* viewport draw extra settings */ char empty_drawtype; float empty_drawsize; float dupfacesca; /* dupliface scale */ @@ -241,8 +240,9 @@ typedef struct Object { struct BulletSoftBody *bsoft; /* settings for game engine bullet soft body */ + char restrictflag; /* for restricting view, select, render etc. accessible in outliner */ + char recalc; /* dependency flag */ short softflag; /* softbody settings */ - short recalc; /* dependency flag */ float anisotropicFriction[3]; ListBase constraints; /* object constraints */ @@ -271,6 +271,9 @@ typedef struct Object { ListBase gpulamp; /* runtime, for glsl lamp display only */ ListBase pc_ids; ListBase *duplilist; /* for temporary dupli list storage, only for use by RNA API */ + + struct RigidBodyOb *rigidbody_object; /* settings for Bullet rigid body */ + struct RigidBodyCon *rigidbody_constraint; /* settings for Bullet constraint */ float ima_ofs[2]; /* offset for image empties */ } Object; @@ -348,6 +351,9 @@ typedef struct DupliObject { #define OB_DATA_SUPPORT_ID(_id_type) \ (ELEM8(_id_type, ID_ME, ID_CU, ID_MB, ID_LA, ID_SPK, ID_CA, ID_LT, ID_AR)) +#define OB_DATA_SUPPORT_ID_CASE \ + ID_ME: case ID_CU: case ID_MB: case ID_LA: case ID_SPK: case ID_CA: case ID_LT: case ID_AR + /* partype: first 4 bits: type */ #define PARTYPE 15 #define PAROBJECT 0 @@ -406,17 +412,19 @@ typedef struct DupliObject { #define OB_PAINT 100 /* temporary used in draw code */ -/* dtx: flags, char! */ -#define OB_AXIS 2 -#define OB_TEXSPACE 4 -#define OB_DRAWNAME 8 -#define OB_DRAWIMAGE 16 +/* dtx: flags (short) */ +#define OB_DRAWBOUNDOX (1 << 0) +#define OB_AXIS (1 << 1) +#define OB_TEXSPACE (1 << 2) +#define OB_DRAWNAME (1 << 3) +#define OB_DRAWIMAGE (1 << 4) /* for solid+wire display */ -#define OB_DRAWWIRE 32 - /* for overdraw */ -#define OB_DRAWXRAY 64 +#define OB_DRAWWIRE (1 << 5) + /* for overdraw s*/ +#define OB_DRAWXRAY (1 << 6) /* enable transparent draw */ -#define OB_DRAWTRANSP 128 +#define OB_DRAWTRANSP (1 << 7) +#define OB_DRAW_ALL_EDGES (1 << 8) /* only for meshes currently */ /* empty_drawtype: no flags */ #define OB_ARROWS 1 diff --git a/source/blender/makesdna/DNA_rigidbody_types.h b/source/blender/makesdna/DNA_rigidbody_types.h new file mode 100644 index 00000000000..b70687be725 --- /dev/null +++ b/source/blender/makesdna/DNA_rigidbody_types.h @@ -0,0 +1,278 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joshua Leung, Sergej Reich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file DNA_rigidbody_types.h + * \ingroup DNA + * \brief Types and defines for representing Rigid Body entities + */ + +#ifndef __DNA_RIGIDBODY_TYPES_H__ +#define __DNA_RIGIDBODY_TYPES_H__ + +#include "DNA_listBase.h" + +struct Group; + +struct EffectorWeights; + +/* ******************************** */ +/* RigidBody World */ + +/* RigidBodyWorld (rbw) + * + * Represents a "simulation scene" existing within the parent scene. + */ +typedef struct RigidBodyWorld { + /* Sim World Settings ------------------------------------------------------------- */ + struct EffectorWeights *effector_weights; /* effectors info */ + + struct Group *group; /* Group containing objects to use for Rigid Bodies */ + struct Object **objects; /* Array to access group objects by index, only used at runtime */ + + struct Group *constraints; /* Group containing objects to use for Rigid Body Constraints*/ + + int pad; + float ltime; /* last frame world was evaluated for (internal) */ + + /* cache */ + struct PointCache *pointcache; + struct ListBase ptcaches; + int numbodies; /* number of objects in rigid body group */ + + short steps_per_second; /* number of simulation steps thaken per second */ + short num_solver_iterations;/* number of constraint solver iterations made per simulation step */ + + int flag; /* (eRigidBodyWorld_Flag) settings for this RigidBodyWorld */ + float time_scale; /* used to speed up or slow down the simulation */ + + /* References to Physics Sim objects. Exist at runtime only ---------------------- */ + void *physics_world; /* Physics sim world (i.e. btDiscreteDynamicsWorld) */ +} RigidBodyWorld; + +/* Flags for RigidBodyWorld */ +typedef enum eRigidBodyWorld_Flag { + /* should sim world be skipped when evaluating (user setting) */ + RBW_FLAG_MUTED = (1<<0), + /* sim data needs to be rebuilt */ + RBW_FLAG_NEEDS_REBUILD = (1<<1), + /* usse split impulse when stepping the simulation */ + RBW_FLAG_USE_SPLIT_IMPULSE = (1<<2) +} eRigidBodyWorld_Flag; + +/* ******************************** */ +/* RigidBody Object */ + +/* RigidBodyObject (rbo) + * + * Represents an object participating in a RigidBody sim. + * This is attached to each object that is currently + * participating in a sim. + */ +typedef struct RigidBodyOb { + /* References to Physics Sim objects. Exist at runtime only */ + void *physics_object; /* Physics object representation (i.e. btRigidBody) */ + void *physics_shape; /* Collision shape used by physics sim (i.e. btCollisionShape) */ + + /* General Settings for this RigidBodyOb */ + short type; /* (eRigidBodyOb_Type) role of RigidBody in sim */ + short shape; /* (eRigidBody_Shape) collision shape to use */ + + int flag; /* (eRigidBodyOb_Flag) */ + int col_groups; /* Collision groups that determines wich rigid bodies can collide with each other */ + int pad; + + /* Physics Parameters */ + float mass; /* how much object 'weighs' (i.e. absolute 'amount of stuff' it holds) */ + + float friction; /* resistance of object to movement */ + float restitution; /* how 'bouncy' object is when it collides */ + + float margin; /* tolerance for detecting collisions */ + + float lin_damping; /* damping for linear velocities */ + float ang_damping; /* damping for angular velocities */ + + float lin_sleep_thresh; /* deactivation threshold for linear velocities */ + float ang_sleep_thresh; /* deactivation threshold for angular velocities */ + + float orn[4]; /* rigid body orientation */ + float pos[3]; /* rigid body position */ + float pad1; +} RigidBodyOb; + + +/* Participation types for RigidBodyOb */ +typedef enum eRigidBodyOb_Type { + /* active geometry participant in simulation. is directly controlled by sim */ + RBO_TYPE_ACTIVE = 0, + /* passive geometry participant in simulation. is directly controlled by animsys */ + RBO_TYPE_PASSIVE +} eRigidBodyOb_Type; + +/* Flags for RigidBodyOb */ +typedef enum eRigidBodyOb_Flag { + /* rigidbody is kinematic (controlled by the animation system) */ + RBO_FLAG_KINEMATIC = (1 << 0), + /* rigidbody needs to be validated (usually set after duplicating and not hooked up yet) */ + RBO_FLAG_NEEDS_VALIDATE = (1 << 1), + /* rigidbody shape needs refreshing (usually after exiting editmode) */ + RBO_FLAG_NEEDS_RESHAPE = (1 << 2), + /* rigidbody can be deactivated */ + RBO_FLAG_USE_DEACTIVATION = (1 << 3), + /* rigidbody is deactivated at the beginning of simulation */ + RBO_FLAG_START_DEACTIVATED = (1 << 4), + /* rigidbody is not dynamically simulated */ + RBO_FLAG_DISABLED = (1 << 5), + /* collision margin is not embedded (only used by convex hull shapes for now) */ + RBO_FLAG_USE_MARGIN = (1 << 6) +} eRigidBodyOb_Flag; + +/* RigidBody Collision Shape */ +typedef enum eRigidBody_Shape { + /* simple box (i.e. bounding box) */ + RB_SHAPE_BOX = 0, + /* sphere */ + RB_SHAPE_SPHERE, + /* rounded "pill" shape (i.e. calcium tablets) */ + RB_SHAPE_CAPSULE, + /* cylinder (i.e. pringles can) */ + RB_SHAPE_CYLINDER, + /* cone (i.e. party hat) */ + RB_SHAPE_CONE, + + /* convex hull (minimal shrinkwrap encompassing all verts) */ + RB_SHAPE_CONVEXH, + /* triangulated mesh */ + RB_SHAPE_TRIMESH, + + /* concave mesh approximated using primitives */ + //RB_SHAPE_COMPOUND, +} eRigidBody_Shape; + +/* ******************************** */ +/* RigidBody Constraint */ + +/* RigidBodyConstraint (rbc) + * + * Represents an constraint connecting two rigid bodies. + */ +typedef struct RigidBodyCon { + struct Object *ob1; /* First object influenced by the constraint */ + struct Object *ob2; /* Second object influenced by the constraint */ + + /* General Settings for this RigidBodyCon */ + short type; /* (eRigidBodyCon_Type) role of RigidBody in sim */ + short num_solver_iterations;/* number of constraint solver iterations made per simulation step */ + + int flag; /* (eRigidBodyCon_Flag) */ + + float breaking_threshold; /* breaking impulse threshold */ + float pad; + + /* limits */ + float limit_lin_x_lower; /* lower limit for x axis translation */ + float limit_lin_x_upper; /* upper limit for x axis translation */ + float limit_lin_y_lower; /* lower limit for y axis translation */ + float limit_lin_y_upper; /* upper limit for y axis translation */ + float limit_lin_z_lower; /* lower limit for z axis translation */ + float limit_lin_z_upper; /* upper limit for z axis translation */ + float limit_ang_x_lower; /* lower limit for x axis rotation */ + float limit_ang_x_upper; /* upper limit for x axis rotation */ + float limit_ang_y_lower; /* lower limit for y axis rotation */ + float limit_ang_y_upper; /* upper limit for y axis rotation */ + float limit_ang_z_lower; /* lower limit for z axis rotation */ + float limit_ang_z_upper; /* upper limit for z axis rotation */ + + /* spring settings */ + /* RB_TODO document spring properties */ + float spring_stiffness_x; + float spring_stiffness_y; + float spring_stiffness_z; + float spring_damping_x; + float spring_damping_y; + float spring_damping_z; + + /* References to Physics Sim object. Exist at runtime only */ + void *physics_constraint; /* Physics object representation (i.e. btTypedConstraint) */ +} RigidBodyCon; + + +/* Participation types for RigidBodyOb */ +typedef enum eRigidBodyCon_Type { + /* lets bodies rotate around a specified point */ + RBC_TYPE_POINT = 0, + /* lets bodies rotate around a specified axis */ + RBC_TYPE_HINGE, + /* simulates wheel suspension */ + RBC_TYPE_HINGE2, + /* restricts movent to a specified axis */ + RBC_TYPE_SLIDER, + /* lets object rotate within a cpecified cone */ + RBC_TYPE_CONE_TWIST, + /* allows user to specify constraint axes */ + RBC_TYPE_6DOF, + /* like 6DOF but has springs */ + RBC_TYPE_6DOF_SPRING, + /* simulates a universal joint */ + RBC_TYPE_UNIVERSAL, + /* glues two bodies together */ + RBC_TYPE_FIXED, + /* similar to slider but also allows rotation around slider axis */ + RBC_TYPE_PISTON, + /* Simplified spring constraint with only once axis that's automatically placed between the connected bodies */ + RBC_TYPE_SPRING +} eRigidBodyCon_Type; + +/* Flags for RigidBodyCon */ +typedef enum eRigidBodyCon_Flag { + /* constraint influences rigid body motion */ + RBC_FLAG_ENABLED = (1 << 0), + /* constraint needs to be validated */ + RBC_FLAG_NEEDS_VALIDATE = (1 << 1), + /* allow constrained bodies to collide */ + RBC_FLAG_DISABLE_COLLISIONS = (1 << 2), + /* constraint can break */ + RBC_FLAG_USE_BREAKING = (1 << 3), + /* constraint use custom number of constraint solver iterations */ + RBC_FLAG_OVERRIDE_SOLVER_ITERATIONS = (1 << 4), + /* limits */ + RBC_FLAG_USE_LIMIT_LIN_X = (1 << 5), + RBC_FLAG_USE_LIMIT_LIN_Y = (1 << 6), + RBC_FLAG_USE_LIMIT_LIN_Z = (1 << 7), + RBC_FLAG_USE_LIMIT_ANG_X = (1 << 8), + RBC_FLAG_USE_LIMIT_ANG_Y = (1 << 9), + RBC_FLAG_USE_LIMIT_ANG_Z = (1 << 10), + /* springs */ + RBC_FLAG_USE_SPRING_X = (1 << 11), + RBC_FLAG_USE_SPRING_Y = (1 << 12), + RBC_FLAG_USE_SPRING_Z = (1 << 13) +} eRigidBodyCon_Flag; + +/* ******************************** */ + +#endif /* __DNA_RIGIDBODY_TYPES_H__ */ + diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 4194395ec43..dc36e88bc16 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -830,29 +830,11 @@ typedef struct Sculpt { //char tablet_size, tablet_strength; XXX not used? int radial_symm[3]; - // all this below is used to communicate with the cursor drawing routine - - /* record movement of mouse so that rake can start at an intuitive angle */ - float last_x, last_y; - float last_angle; - - int draw_anchored; - int anchored_size; - float anchored_location[3]; - float anchored_initial_mouse[2]; - - int draw_pressure; - float pressure_value; - - float special_rotation; - /* Maximum edge length for dynamic topology sculpting (in pixels) */ int detail_size; /* Direction used for SCULPT_OT_symmetrize operator */ int symmetrize_direction; - - int pad; } Sculpt; typedef struct UvSculpt { @@ -915,7 +897,24 @@ typedef struct UnifiedPaintSettings { /* user preferences for sculpt and paint */ int flag; - int pad; + + /* rake rotation */ + + /* record movement of mouse so that rake can start at an intuitive angle */ + float last_x, last_y; + float last_angle; + + float special_rotation; + + // all this below is used to communicate with the cursor drawing routine + int draw_anchored; + int anchored_size; + float anchored_location[3]; + float anchored_initial_mouse[2]; + + /* drawing pressure */ + int draw_pressure; + float pressure_value; } UnifiedPaintSettings; typedef enum { @@ -1187,6 +1186,9 @@ typedef struct Scene { ColorManagedViewSettings view_settings; ColorManagedDisplaySettings display_settings; ColorManagedColorspaceSettings sequencer_colorspace_settings; + + /* RigidBody simulation world+settings */ + struct RigidBodyWorld *rigidbody_world; } Scene; diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 1f665f2e0c0..4c1d2c638b9 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -435,7 +435,7 @@ typedef enum eScreen_Redraws_Flag { TIME_WITH_SEQ_AUDIO = (1 << 4), /* DEPRECATED */ TIME_SEQ = (1 << 5), TIME_ALL_IMAGE_WIN = (1 << 6), - TIME_CONTINUE_PHYSICS = (1 << 7), + TIME_CONTINUE_PHYSICS = (1 << 7), /* UNUSED */ TIME_NODES = (1 << 8), TIME_CLIPS = (1 << 9), } eScreen_Redraws_Flag; @@ -448,6 +448,7 @@ typedef enum eTimeline_Cache_Flag { TIME_CACHE_CLOTH = (1 << 3), TIME_CACHE_SMOKE = (1 << 4), TIME_CACHE_DYNAMICPAINT = (1 << 5), + TIME_CACHE_RIGIDBODY = (1 << 6), } eTimeline_Cache_Flag; @@ -917,6 +918,7 @@ typedef enum eSpaceNode_Flag { SNODE_AUTO_RENDER = (1 << 5), SNODE_SHOW_HIGHLIGHT = (1 << 6), SNODE_USE_HIDDEN_PREVIEW = (1 << 10), + SNODE_NEW_SHADERS = (1 << 11), } eSpaceNode_Flag; /* snode->texfrom */ diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 96bf4a10dda..c049c981be5 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -66,7 +66,7 @@ typedef struct uiFont { short blf_id; /* from blfont lib */ short uifont_id; /* own id */ short r_to_l; /* fonts that read from left to right */ - short pad; + short hinting; } uiFont; /* this state defines appearance of text */ diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index dbe54a4fcdf..d9d6db5ff91 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -46,6 +46,7 @@ struct RenderEngine; struct bGPdata; struct SmoothView3DStore; struct wmTimer; +struct Material; /* This is needed to not let VC choke on near and far... old * proprietary MS extensions... */ @@ -160,8 +161,8 @@ typedef struct View3D { float bundle_size; /* size of bundles in reconstructed data */ short bundle_drawtype; /* display style for bundle */ - - char pad[6]; + short pad; + int matcap_icon; /* icon id */ unsigned int lay_used; /* used while drawing */ @@ -209,11 +210,11 @@ typedef struct View3D { /* drawflags, denoting state */ short zbuf, transp, xray; - char pad3[2]; - void *properties_storage; /* Nkey panel stores stuff here (runtime only!) */ - + void *properties_storage; /* Nkey panel stores stuff here (runtime only!) */ + struct Material *defmaterial; /* used by matcap now */ + /* XXX deprecated? */ struct bGPdata *gpd DNA_DEPRECATED; /* Grease-Pencil Data (annotation layers) */ @@ -264,12 +265,14 @@ typedef struct View3D { #define V3D_SOLID_TEX 8 #define V3D_SHOW_GPENCIL 16 #define V3D_LOCK_CAMERA 32 -#define V3D_RENDER_SHADOW 64 /* This is a runtime only flag that's used to tell draw_mesh_object() that we're doing a shadow pass instead of a regular draw */ -#define V3D_SHOW_RECONSTRUCTION 128 +#define V3D_RENDER_SHADOW 64 /* This is a runtime only flag that's used to tell draw_mesh_object() that we're doing a shadow pass instead of a regular draw */ +#define V3D_SHOW_RECONSTRUCTION 128 #define V3D_SHOW_CAMERAPATH 256 #define V3D_SHOW_BUNDLENAME 512 #define V3D_BACKFACE_CULLING 1024 -#define V3D_RENDER_BORDER 2048 +#define V3D_RENDER_BORDER 2048 +#define V3D_SOLID_MATCAP 4096 /* user flag */ +#define V3D_SHOW_SOLID_MATCAP 8192 /* runtime flag */ /* View3D->around */ #define V3D_CENTER 0 diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c index b04052a98ef..dd65ce53b92 100644 --- a/source/blender/makesdna/intern/makesdna.c +++ b/source/blender/makesdna/intern/makesdna.c @@ -133,6 +133,7 @@ static const char *includefiles[] = { "DNA_tracking_types.h", "DNA_dynamicpaint_types.h", "DNA_mask_types.h", + "DNA_rigidbody_types.h", /* #ifdef WITH_FREESTYLE */ "DNA_freestyle_types.h", "DNA_linestyle_types.h", @@ -1266,6 +1267,7 @@ int main(int argc, char **argv) #include "DNA_tracking_types.h" #include "DNA_dynamicpaint_types.h" #include "DNA_mask_types.h" +#include "DNA_rigidbody_types.h" /* #ifdef WITH_FREESTYLE */ #include "DNA_freestyle_types.h" #include "DNA_linestyle_types.h" diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index af182c467be..821b429e75c 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -92,6 +92,7 @@ extern StructRNA RNA_BoolProperty; extern StructRNA RNA_Brush; extern StructRNA RNA_BrushTextureSlot; extern StructRNA RNA_BuildModifier; +extern StructRNA RNA_MeshCacheModifier; extern StructRNA RNA_Camera; extern StructRNA RNA_CastModifier; extern StructRNA RNA_ChildOfConstraint; @@ -466,6 +467,8 @@ extern StructRNA RNA_RenderLayer; extern StructRNA RNA_RenderPass; extern StructRNA RNA_RenderResult; extern StructRNA RNA_RenderSettings; +extern StructRNA RNA_RigidBodyWorld; +extern StructRNA RNA_RigidBodyObject; extern StructRNA RNA_RigidBodyJointConstraint; extern StructRNA RNA_SPHFluidSettings; extern StructRNA RNA_Scene; diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h index 463e0e04679..cd6d74c3488 100644 --- a/source/blender/makesrna/RNA_define.h +++ b/source/blender/makesrna/RNA_define.h @@ -87,7 +87,7 @@ PropertyRNA *RNA_def_string(StructOrFunctionRNA *cont, const char *identifier, c PropertyRNA *RNA_def_string_file_path(StructOrFunctionRNA *cont, const char *identifier, const char *default_value, int maxlen, const char *ui_name, const char *ui_description); PropertyRNA *RNA_def_string_dir_path(StructOrFunctionRNA *cont, const char *identifier, const char *default_value, int maxlen, const char *ui_name, const char *ui_description); PropertyRNA *RNA_def_string_file_name(StructOrFunctionRNA *cont, const char *identifier, const char *default_value, int maxlen, const char *ui_name, const char *ui_description); -PropertyRNA *RNA_def_string_translate(StructOrFunctionRNA *cont, const char *identifier, const char *default_value, int maxlen, const char *ui_name, const char *ui_description); +PropertyRNA *RNA_def_string_py_translate(StructOrFunctionRNA *cont, const char *identifier, const char *default_value, int maxlen, const char *ui_name, const char *ui_description); PropertyRNA *RNA_def_enum(StructOrFunctionRNA *cont, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description); PropertyRNA *RNA_def_enum_flag(StructOrFunctionRNA *cont, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description); diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h index a8df3b9dfdd..8038f97ec54 100644 --- a/source/blender/makesrna/RNA_enum_types.h +++ b/source/blender/makesrna/RNA_enum_types.h @@ -102,6 +102,12 @@ extern EnumPropertyItem object_type_items[]; extern EnumPropertyItem object_type_curve_items[]; +extern EnumPropertyItem rigidbody_ob_type_items[]; +extern EnumPropertyItem rigidbody_ob_shape_items[]; +extern EnumPropertyItem rigidbody_con_type_items[]; + +extern EnumPropertyItem object_axis_items[]; + extern EnumPropertyItem controller_type_items[]; extern EnumPropertyItem keymap_propvalue_items[]; diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h index c76f9824c73..5f34fad09c6 100644 --- a/source/blender/makesrna/RNA_types.h +++ b/source/blender/makesrna/RNA_types.h @@ -110,10 +110,9 @@ typedef enum PropertySubType { PROP_FILEPATH = 1, PROP_DIRPATH = 2, PROP_FILENAME = 3, - PROP_BYTESTRING = 4, /* a string which should be represented as bytes - * in python, still NULL terminated though. */ - PROP_TRANSLATE = 5, /* a string which should be translated */ - PROP_PASSWORD = 6, /* a string which should not be displayed in UI */ + PROP_BYTESTRING = 4, /* a string which should be represented as bytes in python, still NULL terminated though. */ + /* 5 was used by "PROP_TRANSLATE" sub-type, which is now a flag. */ + PROP_PASSWORD = 6, /* a string which should not be displayed in UI */ /* numbers */ PROP_UNSIGNED = 13, @@ -144,6 +143,7 @@ typedef enum PropertySubType { } PropertySubType; /* Make sure enums are updated with thses */ +/* HIGHEST FLAG IN USE: 1 << 29 */ typedef enum PropertyFlag { /* editable means the property is editable in the user * interface, properties are editable by default except @@ -200,6 +200,11 @@ typedef enum PropertyFlag { */ PROP_ENUM_FLAG = (1 << 21), + /* A string which should be translated when converting from py string to RNA prop. + * Should only be used in some functions' properties (currently only "text" one of funcs in UI API). + */ + PROP_STRING_PY_TRANSLATE = (1 << 28), + /* need context for update function */ PROP_CONTEXT_UPDATE = (1 << 22), PROP_CONTEXT_PROPERTY_UPDATE = (1 << 22) | (1 << 27), diff --git a/source/blender/makesrna/SConscript b/source/blender/makesrna/SConscript index 464939dc879..f3beee8bc14 100644 --- a/source/blender/makesrna/SConscript +++ b/source/blender/makesrna/SConscript @@ -38,6 +38,8 @@ incs += ' ../render/extern/include #/intern/cycles/blender' incs += ' ../nodes' incs += ' #/extern/glew/include' incs += ' #/intern/smoke/extern' +incs += ' ../rigidbody' + incs += ' ../bmesh' defs = [] @@ -45,6 +47,10 @@ defs = [] if env['WITH_BF_SMOKE']: defs.append('WITH_SMOKE') +if env['WITH_BF_BULLET']: + defs.append('WITH_BULLET') + incs += ' ../../rigidbody' + if env['WITH_BF_OPENEXR']: defs.append('WITH_OPENEXR') diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index a8b9b779ff8..2fb1f0bf6b4 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -70,6 +70,7 @@ set(DEFSRC rna_pose.c rna_property.c rna_render.c + rna_rigidbody.c rna_rna.c rna_scene.c rna_screen.c @@ -243,6 +244,13 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() +if(WITH_BULLET) + list(APPEND INC + ../../rigidbody + ) + add_definitions(-DWITH_BULLET) +endif() + # Build makesrna executable blender_include_dirs( . diff --git a/source/blender/makesrna/intern/SConscript b/source/blender/makesrna/intern/SConscript index 11562d729df..e159b9fd8eb 100644 --- a/source/blender/makesrna/intern/SConscript +++ b/source/blender/makesrna/intern/SConscript @@ -67,7 +67,11 @@ incs += ' #/intern/smoke/extern' if env['WITH_BF_SMOKE']: defs.append('WITH_SMOKE') - + +if env['WITH_BF_BULLET']: + defs.append('WITH_BULLET') + incs += ' ../../rigidbody' + if env['WITH_BF_OPENEXR']: defs.append('WITH_OPENEXR') diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 0992153560f..b4bf241815d 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -2444,7 +2444,6 @@ static const char *rna_property_subtypename(PropertySubType type) case PROP_FILENAME: return "PROP_FILENAME"; case PROP_DIRPATH: return "PROP_DIRPATH"; case PROP_BYTESTRING: return "PROP_BYTESTRING"; - case PROP_TRANSLATE: return "PROP_TRANSLATE"; case PROP_UNSIGNED: return "PROP_UNSIGNED"; case PROP_PERCENTAGE: return "PROP_PERCENTAGE"; case PROP_FACTOR: return "PROP_FACTOR"; @@ -2466,7 +2465,8 @@ static const char *rna_property_subtypename(PropertySubType type) case PROP_LAYER: return "PROP_LAYER"; case PROP_LAYER_MEMBER: return "PROP_LAYER_MEMBER"; case PROP_PASSWORD: return "PROP_PASSWORD"; - default: { + default: + { /* in case we don't have a type preset that includes the subtype */ if (RNA_SUBTYPE_UNIT(type)) { return rna_property_subtypename(type & ~RNA_SUBTYPE_UNIT(type)); @@ -3262,6 +3262,7 @@ static RNAProcessItem PROCESS_ITEMS[] = { {"rna_pose.c", "rna_pose_api.c", RNA_def_pose}, {"rna_property.c", NULL, RNA_def_gameproperty}, {"rna_render.c", NULL, RNA_def_render}, + {"rna_rigidbody.c", NULL, RNA_def_rigidbody}, {"rna_scene.c", "rna_scene_api.c", RNA_def_scene}, {"rna_screen.c", NULL, RNA_def_screen}, {"rna_sculpt_paint.c", NULL, RNA_def_sculpt_paint}, @@ -3547,8 +3548,27 @@ static const char *cpp_classes = "" "#define COLLECTION_PROPERTY_LOOKUP_STRING_FALSE(sname, identifier) \\\n" " inline static int sname##_##identifier##_lookup_string_wrap(PointerRNA *ptr, const char *key, PointerRNA *r_ptr) \\\n" " { \\\n" -" memset(r_ptr, 0, sizeof(*r_ptr)); \\\n" -" return 0; \\\n" +" CollectionPropertyIterator iter; \\\n" +" int found = 0; \\\n" +" PropertyRNA *item_name_prop = RNA_struct_name_property(ptr->type); \\\n" +" sname##_##identifier##_begin(&iter, ptr); \\\n" +" while (iter.valid && !found) { \\\n" +" char name_fixed[32]; \\\n" +" const char *name; \\\n" +" int name_length; \\\n" +" name = RNA_property_string_get_alloc(&iter.ptr, item_name_prop, name_fixed, sizeof(name_fixed), &name_length); \\\n" +" if (!strncmp(name, key, name_length)) { \\\n" +" *r_ptr = iter.ptr; \\\n" +" found = 1; \\\n" +" } \\\n" +" if (name_fixed != name) \\\n" +" MEM_freeN((void *) name); \\\n" +" sname##_##identifier##_next(&iter); \\\n" +" } \\\n" +" sname##_##identifier##_end(&iter); \\\n" +" if (!found) \\\n" +" memset(r_ptr, 0, sizeof(*r_ptr)); \\\n" +" return found; \\\n" " } \n" "#define COLLECTION_PROPERTY_LOOKUP_STRING_TRUE(sname, identifier) \\\n" " inline static int sname##_##identifier##_lookup_string_wrap(PointerRNA *ptr, const char *key, PointerRNA *r_ptr) \\\n" diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 59bcb1506af..aecc114f328 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -1505,7 +1505,7 @@ int RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop) static void rna_property_update(bContext *C, Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop) { - int is_rna = (prop->magic == RNA_MAGIC); + const bool is_rna = (prop->magic == RNA_MAGIC); prop = rna_ensure_property(prop); if (is_rna) { @@ -1585,19 +1585,19 @@ 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; - short is_rna = (prop->magic == RNA_MAGIC); /* sanity check */ - if (ELEM(NULL, ptr, prop)) + 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 == 0) || (prop->update == NULL) || (prop->flag & PROP_CONTEXT_UPDATE)) + if ((is_rna == false) || (prop->update == NULL) || (prop->flag & PROP_CONTEXT_UPDATE)) return; fn = prop->update; @@ -4210,11 +4210,11 @@ char *RNA_path_from_ID_to_struct(PointerRNA *ptr) char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop) { - int is_rna = (prop->magic == RNA_MAGIC); + const bool is_rna = (prop->magic == RNA_MAGIC); const char *propname; char *ptrpath, *path; - if (!ptr->id.data || !ptr->data || !prop) + if (!ptr->id.data || !ptr->data) return NULL; /* path from ID to the struct holding this property */ @@ -6097,7 +6097,8 @@ int RNA_property_equals(PointerRNA *a, PointerRNA *b, PropertyRNA *prop) /* get and set the default values as appropriate for the various types */ switch (RNA_property_type(prop)) { - case PROP_BOOLEAN: { + case PROP_BOOLEAN: + { if (len) { int fixed_a[16], fixed_b[16]; int *array_a, *array_b; @@ -6122,7 +6123,8 @@ int RNA_property_equals(PointerRNA *a, PointerRNA *b, PropertyRNA *prop) } } - case PROP_INT: { + case PROP_INT: + { if (len) { int fixed_a[16], fixed_b[16]; int *array_a, *array_b; @@ -6147,7 +6149,8 @@ int RNA_property_equals(PointerRNA *a, PointerRNA *b, PropertyRNA *prop) } } - case PROP_FLOAT: { + case PROP_FLOAT: + { if (len) { float fixed_a[16], fixed_b[16]; float *array_a, *array_b; @@ -6172,12 +6175,14 @@ int RNA_property_equals(PointerRNA *a, PointerRNA *b, PropertyRNA *prop) } } - case PROP_ENUM: { + case PROP_ENUM: + { int value = RNA_property_enum_get(a, prop); return value == RNA_property_enum_get(b, prop); } - case PROP_STRING: { + case PROP_STRING: + { char fixed_a[128], fixed_b[128]; int len_a, len_b; char *value_a = RNA_property_string_get_alloc(a, prop, fixed_a, sizeof(fixed_a), &len_a); diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index 06c01012e19..da8aa15cf2e 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -39,6 +39,8 @@ #include "MEM_guardedalloc.h" +#include "BLI_utildefines.h" + #include "BKE_action.h" #include "WM_types.h" diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 3d5106b0cef..4fb26f2b007 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -429,6 +429,13 @@ static void rna_def_brush_texture_slot(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; + static EnumPropertyItem prop_tex_paint_map_mode_items[] = { + {MTEX_MAP_MODE_VIEW, "VIEW_PLANE", 0, "View Plane", ""}, + {MTEX_MAP_MODE_TILED, "TILED", 0, "Tiled", ""}, + {MTEX_MAP_MODE_3D, "3D", 0, "3D", ""}, + {0, NULL, 0, NULL, NULL} + }; + srna = RNA_def_struct(brna, "BrushTextureSlot", "TextureSlot"); RNA_def_struct_sdna(srna, "MTex"); RNA_def_struct_ui_text(srna, "Brush Texture Slot", "Texture slot for textures in a Brush datablock"); @@ -444,6 +451,12 @@ static void rna_def_brush_texture_slot(BlenderRNA *brna) RNA_def_property_enum_items(prop, prop_map_mode_items); RNA_def_property_ui_text(prop, "Mode", ""); RNA_def_property_update(prop, 0, "rna_TextureSlot_update"); + + prop = RNA_def_property(srna, "tex_paint_map_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "brush_map_mode"); + RNA_def_property_enum_items(prop, prop_tex_paint_map_mode_items); + RNA_def_property_ui_text(prop, "Mode", ""); + RNA_def_property_update(prop, 0, "rna_TextureSlot_update"); } static void rna_def_sculpt_capabilities(BlenderRNA *brna) @@ -855,11 +868,6 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_RESTORE_MESH); RNA_def_property_ui_text(prop, "Restore Mesh", "Allow a single dot to be carefully positioned"); RNA_def_property_update(prop, 0, "rna_Brush_update"); - - prop = RNA_def_property(srna, "use_fixed_texture", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_FIXED_TEX); - RNA_def_property_ui_text(prop, "Fixed Texture", "Keep texture origin in fixed position"); - RNA_def_property_update(prop, 0, "rna_Brush_update"); /* only for projection paint, TODO, other paint modes */ prop = RNA_def_property(srna, "use_alpha", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index bc4194ebffb..f32f28e8143 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -886,7 +886,7 @@ static void rna_def_histogram(BlenderRNA *brna) prop = RNA_def_property(srna, "show_line", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", HISTO_FLAG_LINE); - RNA_def_property_ui_text(prop, "Show Line", "Display lines rather then filled shapes"); + RNA_def_property_ui_text(prop, "Show Line", "Display lines rather than filled shapes"); RNA_def_property_ui_icon(prop, ICON_IPO, 0); } diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index b94d7eb691f..4e6c3748230 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -1210,6 +1210,15 @@ void RNA_def_property_ui_icon(PropertyRNA *prop, int icon, int consecutive) prop->flag |= PROP_ICONS_CONSECUTIVE; } +/** + * The values hare are a little confusing: + * + * \param step For floats this is (step / 100), why /100? - nobody knows. + * for int's, whole values are used. + * + * \param precision The number of zeros to show + * (as a whole number - common range is 1 - 6), see PRECISION_FLOAT_MAX + */ void RNA_def_property_ui_range(PropertyRNA *prop, double min, double max, double step, int precision) { StructRNA *srna = DefRNA.laststruct; @@ -1230,6 +1239,21 @@ void RNA_def_property_ui_range(PropertyRNA *prop, double min, double max, double fprop->softmax = (float)max; fprop->step = (float)step; fprop->precision = (int)precision; +#if 0 /* handy but annoying */ + if (DefRNA.preprocess) { + /* check we're not over PRECISION_FLOAT_MAX */ + if (fprop->precision > 6) { + fprintf(stderr, "%s: \"%s.%s\", precision value over maximum.\n", + __func__, srna->identifier, prop->identifier); + DefRNA.error = 1; + } + else if (fprop->precision < 1) { + fprintf(stderr, "%s: \"%s.%s\", precision value under minimum.\n", + __func__, srna->identifier, prop->identifier); + DefRNA.error = 1; + } + } +#endif break; } default: @@ -2534,13 +2558,14 @@ PropertyRNA *RNA_def_string_file_name(StructOrFunctionRNA *cont_, const char *id return prop; } -PropertyRNA *RNA_def_string_translate(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, - int maxlen, const char *ui_name, const char *ui_description) +PropertyRNA *RNA_def_string_py_translate(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, + int maxlen, const char *ui_name, const char *ui_description) { ContainerRNA *cont = cont_; PropertyRNA *prop; - prop = RNA_def_property(cont, identifier, PROP_STRING, PROP_TRANSLATE); + prop = RNA_def_property(cont, identifier, PROP_STRING, PROP_NONE); + RNA_def_property_flag(prop, PROP_STRING_PY_TRANSLATE); if (maxlen != 0) RNA_def_property_string_maxlength(prop, maxlen); if (default_value) RNA_def_property_string_default(prop, default_value); RNA_def_property_ui_text(prop, ui_name, ui_description); diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index 5d37f67fa93..72e27ba9240 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -88,11 +88,15 @@ static int rna_Image_dirty_get(PointerRNA *ptr) return 0; } -static void rna_Image_source_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +static void rna_Image_source_set(PointerRNA *ptr, int value) { Image *ima = ptr->id.data; - BKE_image_signal(ima, NULL, IMA_SIGNAL_SRC_CHANGE); - DAG_id_tag_update(&ima->id, 0); + + if (value != ima->source) { + ima->source = value; + BKE_image_signal(ima, NULL, IMA_SIGNAL_SRC_CHANGE); + DAG_id_tag_update(&ima->id, 0); + } } static void rna_Image_fields_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) @@ -377,6 +381,38 @@ static void rna_Image_pixels_set(PointerRNA *ptr, const float *values) BKE_image_release_ibuf(ima, ibuf, lock); } +static int rna_Image_channels_get(PointerRNA *ptr) +{ + Image *im = (Image *)ptr->data; + ImBuf *ibuf; + void *lock; + int channels = 0; + + ibuf = BKE_image_acquire_ibuf(im, NULL, &lock); + if (ibuf) + channels = ibuf->channels; + + BKE_image_release_ibuf(im, ibuf, lock); + + return channels; +} + +static int rna_Image_is_float_get(PointerRNA *ptr) +{ + Image *im = (Image *)ptr->data; + ImBuf *ibuf; + void *lock; + int is_float = FALSE; + + ibuf = BKE_image_acquire_ibuf(im, NULL, &lock); + if (ibuf) + is_float = ibuf->rect_float != NULL; + + BKE_image_release_ibuf(im, ibuf, lock); + + return is_float; +} + #else static void rna_def_imageuser(BlenderRNA *brna) @@ -395,6 +431,11 @@ static void rna_def_imageuser(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_ImageUser_update"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + prop = RNA_def_property(srna, "frame_current", PROP_INT, PROP_TIME); + RNA_def_property_int_sdna(prop, NULL, "framenr"); + RNA_def_property_range(prop, MINAFRAME, MAXFRAME); + RNA_def_property_ui_text(prop, "Current Frame", "Current frame number in image sequence or movie"); + /* animation */ prop = RNA_def_property(srna, "use_cyclic", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "cycl", 0); @@ -490,9 +531,9 @@ static void rna_def_image(BlenderRNA *brna) prop = RNA_def_property(srna, "source", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, image_source_items); - RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Image_source_itemf"); + RNA_def_property_enum_funcs(prop, NULL, "rna_Image_source_set", "rna_Image_source_itemf"); RNA_def_property_ui_text(prop, "Source", "Where the image comes from"); - RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_source_update"); + RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL); prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, prop_type_items); @@ -664,6 +705,10 @@ static void rna_def_image(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Duration", "Duration (in frames) of the image (1 when not a video/sequence)"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); + /* NOTE about pixels/channels/is_floa: + * this properties describes how image is stored internally (inside of ImBuf), + * not how it was saved to disk or how it'll be saved on disk + */ prop = RNA_def_property(srna, "pixels", PROP_FLOAT, PROP_NONE); RNA_def_property_flag(prop, PROP_DYNAMIC); RNA_def_property_multi_array(prop, 1, NULL); @@ -671,6 +716,16 @@ static void rna_def_image(BlenderRNA *brna) RNA_def_property_dynamic_array_funcs(prop, "rna_Image_pixels_get_length"); RNA_def_property_float_funcs(prop, "rna_Image_pixels_get", "rna_Image_pixels_set", NULL); + prop = RNA_def_property(srna, "channels", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_funcs(prop, "rna_Image_channels_get", NULL, NULL); + RNA_def_property_ui_text(prop, "Channels", "Number of channels in pixels buffer"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + + prop = RNA_def_property(srna, "is_float", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, "rna_Image_is_float_get", NULL); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Is Float", "True if this image is stored in float buffer"); + prop = RNA_def_property(srna, "colorspace_settings", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "colorspace_settings"); RNA_def_property_struct_type(prop, "ColorManagedInputColorspaceSettings"); diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 636be933ced..99dd0a860d2 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -167,6 +167,7 @@ void RNA_def_packedfile(struct BlenderRNA *brna); void RNA_def_particle(struct BlenderRNA *brna); void RNA_def_pose(struct BlenderRNA *brna); 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_screen(struct BlenderRNA *brna); diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index 90cc8100718..6d182ed17f0 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -108,11 +108,11 @@ static Camera *rna_Main_cameras_new(Main *UNUSED(bmain), const char *name) id_us_min(id); return (Camera *)id; } -static void rna_Main_cameras_remove(Main *bmain, ReportList *reports, PointerRNA *camera_ptr) +static void rna_Main_cameras_remove(Main *UNUSED(bmain), ReportList *reports, PointerRNA *camera_ptr) { Camera *camera = camera_ptr->data; if (ID_REAL_USERS(camera) <= 0) { - BKE_libblock_free(&bmain->camera, camera); + BKE_libblock_free(&G.main->camera, camera); RNA_POINTER_INVALIDATE(camera_ptr); } else { @@ -201,12 +201,12 @@ static Object *rna_Main_objects_new(Main *UNUSED(bmain), ReportList *reports, co return ob; } -static void rna_Main_objects_remove(Main *bmain, ReportList *reports, PointerRNA *object_ptr) +static void rna_Main_objects_remove(Main *UNUSED(bmain), ReportList *reports, PointerRNA *object_ptr) { Object *object = object_ptr->data; if (ID_REAL_USERS(object) <= 0) { BKE_object_unlink(object); /* needed or ID pointers to this are not cleared */ - BKE_libblock_free(&bmain->object, object); + BKE_libblock_free(&G.main->object, object); RNA_POINTER_INVALIDATE(object_ptr); } else { @@ -221,11 +221,11 @@ static Material *rna_Main_materials_new(Main *UNUSED(bmain), const char *name) id_us_min(id); return (Material *)id; } -static void rna_Main_materials_remove(Main *bmain, ReportList *reports, PointerRNA *material_ptr) +static void rna_Main_materials_remove(Main *UNUSED(bmain), ReportList *reports, PointerRNA *material_ptr) { Material *material = material_ptr->data; if (ID_REAL_USERS(material) <= 0) { - BKE_libblock_free(&bmain->mat, material); + BKE_libblock_free(&G.main->mat, material); RNA_POINTER_INVALIDATE(material_ptr); } else { @@ -241,11 +241,11 @@ static bNodeTree *rna_Main_nodetree_new(Main *UNUSED(bmain), const char *name, i id_us_min(&tree->id); return tree; } -static void rna_Main_nodetree_remove(Main *bmain, ReportList *reports, PointerRNA *tree_ptr) +static void rna_Main_nodetree_remove(Main *UNUSED(bmain), ReportList *reports, PointerRNA *tree_ptr) { bNodeTree *tree = tree_ptr->data; if (ID_REAL_USERS(tree) <= 0) { - BKE_libblock_free(&bmain->nodetree, tree); + BKE_libblock_free(&G.main->nodetree, tree); RNA_POINTER_INVALIDATE(tree_ptr); } else { @@ -260,11 +260,12 @@ static Mesh *rna_Main_meshes_new(Main *UNUSED(bmain), const char *name) id_us_min(&me->id); return me; } -static void rna_Main_meshes_remove(Main *bmain, ReportList *reports, PointerRNA *mesh_ptr) +static void rna_Main_meshes_remove(Main *UNUSED(bmain), ReportList *reports, PointerRNA *mesh_ptr) { Mesh *mesh = mesh_ptr->data; + if (ID_REAL_USERS(mesh) <= 0) { - BKE_libblock_free(&bmain->mesh, mesh); + BKE_libblock_free(&G.main->mesh, mesh); RNA_POINTER_INVALIDATE(mesh_ptr); } else { @@ -280,11 +281,11 @@ static Lamp *rna_Main_lamps_new(Main *UNUSED(bmain), const char *name, int type) id_us_min(&lamp->id); return lamp; } -static void rna_Main_lamps_remove(Main *bmain, ReportList *reports, PointerRNA *lamp_ptr) +static void rna_Main_lamps_remove(Main *UNUSED(bmain), ReportList *reports, PointerRNA *lamp_ptr) { Lamp *lamp = lamp_ptr->data; if (ID_REAL_USERS(lamp) <= 0) { - BKE_libblock_free(&bmain->lamp, lamp); + BKE_libblock_free(&G.main->lamp, lamp); RNA_POINTER_INVALIDATE(lamp_ptr); } else { @@ -314,11 +315,11 @@ static Image *rna_Main_images_load(Main *UNUSED(bmain), ReportList *reports, con return ima; } -static void rna_Main_images_remove(Main *bmain, ReportList *reports, PointerRNA *image_ptr) +static void rna_Main_images_remove(Main *UNUSED(bmain), ReportList *reports, PointerRNA *image_ptr) { Image *image = image_ptr->data; if (ID_REAL_USERS(image) <= 0) { - BKE_libblock_free(&bmain->image, image); + BKE_libblock_free(&G.main->image, image); RNA_POINTER_INVALIDATE(image_ptr); } else { @@ -333,11 +334,11 @@ static Lattice *rna_Main_lattices_new(Main *UNUSED(bmain), const char *name) id_us_min(<->id); return lt; } -static void rna_Main_lattices_remove(Main *bmain, ReportList *reports, PointerRNA *lt_ptr) +static void rna_Main_lattices_remove(Main *UNUSED(bmain), ReportList *reports, PointerRNA *lt_ptr) { Lattice *lt = lt_ptr->data; if (ID_REAL_USERS(lt) <= 0) { - BKE_libblock_free(&bmain->latt, lt); + BKE_libblock_free(&G.main->latt, lt); RNA_POINTER_INVALIDATE(lt_ptr); } else { @@ -352,11 +353,11 @@ static Curve *rna_Main_curves_new(Main *UNUSED(bmain), const char *name, int typ id_us_min(&cu->id); return cu; } -static void rna_Main_curves_remove(Main *bmain, ReportList *reports, PointerRNA *cu_ptr) +static void rna_Main_curves_remove(Main *UNUSED(bmain), ReportList *reports, PointerRNA *cu_ptr) { Curve *cu = cu_ptr->data; if (ID_REAL_USERS(cu) <= 0) { - BKE_libblock_free(&bmain->curve, cu); + BKE_libblock_free(&G.main->curve, cu); RNA_POINTER_INVALIDATE(cu_ptr); } else { @@ -371,11 +372,11 @@ static MetaBall *rna_Main_metaballs_new(Main *UNUSED(bmain), const char *name) id_us_min(&mb->id); return mb; } -static void rna_Main_metaballs_remove(Main *bmain, ReportList *reports, PointerRNA *mb_ptr) +static void rna_Main_metaballs_remove(Main *UNUSED(bmain), ReportList *reports, PointerRNA *mb_ptr) { MetaBall *mb = mb_ptr->data; if (ID_REAL_USERS(mb) <= 0) { - BKE_libblock_free(&bmain->mball, mb); + BKE_libblock_free(&G.main->mball, mb); RNA_POINTER_INVALIDATE(mb_ptr); } else { @@ -418,11 +419,11 @@ static Tex *rna_Main_textures_new(Main *UNUSED(bmain), const char *name, int typ id_us_min(&tex->id); return tex; } -static void rna_Main_textures_remove(Main *bmain, ReportList *reports, PointerRNA *tex_ptr) +static void rna_Main_textures_remove(Main *UNUSED(bmain), ReportList *reports, PointerRNA *tex_ptr) { Tex *tex = tex_ptr->data; if (ID_REAL_USERS(tex) <= 0) { - BKE_libblock_free(&bmain->tex, tex); + BKE_libblock_free(&G.main->tex, tex); RNA_POINTER_INVALIDATE(tex_ptr); } else { @@ -437,11 +438,11 @@ static Brush *rna_Main_brushes_new(Main *UNUSED(bmain), const char *name) id_us_min(&brush->id); return brush; } -static void rna_Main_brushes_remove(Main *bmain, ReportList *reports, PointerRNA *brush_ptr) +static void rna_Main_brushes_remove(Main *UNUSED(bmain), ReportList *reports, PointerRNA *brush_ptr) { Brush *brush = brush_ptr->data; if (ID_REAL_USERS(brush) <= 0) { - BKE_libblock_free(&bmain->brush, brush); + BKE_libblock_free(&G.main->brush, brush); RNA_POINTER_INVALIDATE(brush_ptr); } else { @@ -456,11 +457,11 @@ static World *rna_Main_worlds_new(Main *UNUSED(bmain), const char *name) id_us_min(&world->id); return world; } -static void rna_Main_worlds_remove(Main *bmain, ReportList *reports, PointerRNA *world_ptr) +static void rna_Main_worlds_remove(Main *UNUSED(bmain), ReportList *reports, PointerRNA *world_ptr) { Group *world = world_ptr->data; if (ID_REAL_USERS(world) <= 0) { - BKE_libblock_free(&bmain->world, world); + BKE_libblock_free(&G.main->world, world); RNA_POINTER_INVALIDATE(world_ptr); } else { @@ -473,11 +474,11 @@ static Group *rna_Main_groups_new(Main *UNUSED(bmain), const char *name) { return add_group(name); } -static void rna_Main_groups_remove(Main *bmain, PointerRNA *group_ptr) +static void rna_Main_groups_remove(Main *UNUSED(bmain), PointerRNA *group_ptr) { Group *group = group_ptr->data; BKE_group_unlink(group); - BKE_libblock_free(&bmain->group, group); + BKE_libblock_free(&G.main->group, group); RNA_POINTER_INVALIDATE(group_ptr); } @@ -487,11 +488,11 @@ static Speaker *rna_Main_speakers_new(Main *UNUSED(bmain), const char *name) id_us_min(&speaker->id); return speaker; } -static void rna_Main_speakers_remove(Main *bmain, ReportList *reports, PointerRNA *speaker_ptr) +static void rna_Main_speakers_remove(Main *UNUSED(bmain), ReportList *reports, PointerRNA *speaker_ptr) { Speaker *speaker = speaker_ptr->data; if (ID_REAL_USERS(speaker) <= 0) { - BKE_libblock_free(&bmain->speaker, speaker); + BKE_libblock_free(&G.main->speaker, speaker); RNA_POINTER_INVALIDATE(speaker_ptr); } else { @@ -504,11 +505,11 @@ static Text *rna_Main_texts_new(Main *UNUSED(bmain), const char *name) { return BKE_text_add(name); } -static void rna_Main_texts_remove(Main *bmain, PointerRNA *text_ptr) +static void rna_Main_texts_remove(Main *UNUSED(bmain), PointerRNA *text_ptr) { Text *text = text_ptr->data; - BKE_text_unlink(bmain, text); - BKE_libblock_free(&bmain->text, text); + BKE_text_unlink(G.main, text); + BKE_libblock_free(&G.main->text, text); RNA_POINTER_INVALIDATE(text_ptr); } @@ -532,11 +533,11 @@ static bArmature *rna_Main_armatures_new(Main *UNUSED(bmain), const char *name) id_us_min(&arm->id); return arm; } -static void rna_Main_armatures_remove(Main *bmain, ReportList *reports, PointerRNA *arm_ptr) +static void rna_Main_armatures_remove(Main *UNUSED(bmain), ReportList *reports, PointerRNA *arm_ptr) { bArmature *arm = arm_ptr->data; if (ID_REAL_USERS(arm) <= 0) { - BKE_libblock_free(&bmain->armature, arm); + BKE_libblock_free(&G.main->armature, arm); RNA_POINTER_INVALIDATE(arm_ptr); } else { @@ -552,11 +553,11 @@ static bAction *rna_Main_actions_new(Main *UNUSED(bmain), const char *name) act->id.flag &= ~LIB_FAKEUSER; return act; } -static void rna_Main_actions_remove(Main *bmain, ReportList *reports, PointerRNA *act_ptr) +static void rna_Main_actions_remove(Main *UNUSED(bmain), ReportList *reports, PointerRNA *act_ptr) { bAction *act = act_ptr->data; if (ID_REAL_USERS(act) <= 0) { - BKE_libblock_free(&bmain->action, act); + BKE_libblock_free(&G.main->action, act); RNA_POINTER_INVALIDATE(act_ptr); } else { @@ -598,11 +599,11 @@ static MovieClip *rna_Main_movieclip_load(Main *UNUSED(bmain), ReportList *repor return clip; } -static void rna_Main_movieclips_remove(Main *bmain, PointerRNA *clip_ptr) +static void rna_Main_movieclips_remove(Main *UNUSED(bmain), PointerRNA *clip_ptr) { MovieClip *clip = clip_ptr->data; - BKE_movieclip_unlink(bmain, clip); - BKE_libblock_free(&bmain->movieclip, clip); + BKE_movieclip_unlink(G.main, clip); + BKE_libblock_free(&G.main->movieclip, clip); RNA_POINTER_INVALIDATE(clip_ptr); } @@ -615,11 +616,11 @@ static Mask *rna_Main_mask_new(Main *UNUSED(bmain), const char *name) return mask; } -static void rna_Main_masks_remove(Main *bmain, PointerRNA *mask_ptr) +static void rna_Main_masks_remove(Main *UNUSED(bmain), PointerRNA *mask_ptr) { Mask *mask = mask_ptr->data; - BKE_mask_free(bmain, mask); - BKE_libblock_free(&bmain->mask, mask); + BKE_mask_free(G.main, mask); + BKE_libblock_free(&G.main->mask, mask); RNA_POINTER_INVALIDATE(mask_ptr); } diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 8c8b7b4f637..60625cb0e0b 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -2921,11 +2921,6 @@ static void rna_def_mesh(BlenderRNA *brna) "Display selected edges using highlights in the 3D view and UV editor"); RNA_def_property_update(prop, 0, "rna_Mesh_update_draw"); - prop = RNA_def_property(srna, "show_all_edges", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_ALLEDGES); - RNA_def_property_ui_text(prop, "All Edges", "Display all edges for wireframe in all view modes in the 3D view"); - RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); - prop = RNA_def_property(srna, "show_faces", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "drawflag", ME_DRAWFACES); RNA_def_property_ui_text(prop, "Draw Faces", "Display all faces as shades in the 3D view and UV editor"); diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 7a576c88677..21ab11271c4 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -58,6 +58,7 @@ EnumPropertyItem modifier_type_items[] = { {0, "", 0, N_("Modify"), ""}, + {eModifierType_MeshCache, "MESH_CACHE", ICON_MOD_MESHDEFORM, "Mesh Cache", ""}, {eModifierType_UVProject, "UV_PROJECT", ICON_MOD_UVPROJECT, "UV Project", ""}, {eModifierType_UVWarp, "UV_WARP", ICON_MOD_UVPROJECT, "UV Warp", ""}, {eModifierType_WeightVGEdit, "VERTEX_WEIGHT_EDIT", ICON_MOD_VERTEX_WEIGHT, "Vertex Weight Edit", ""}, @@ -219,6 +220,8 @@ static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr) return &RNA_TriangulateModifier; case eModifierType_UVWarp: return &RNA_UVWarpModifier; + case eModifierType_MeshCache: + return &RNA_MeshCacheModifier; /* Default */ case eModifierType_None: case eModifierType_ShapeKey: @@ -1666,7 +1669,7 @@ static void rna_def_modifier_displace(BlenderRNA *brna) RNA_def_property_string_funcs(prop, NULL, NULL, "rna_DisplaceModifier_vgroup_set"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - prop = RNA_def_property(srna, "mid_level", PROP_FLOAT, PROP_DISTANCE); + prop = RNA_def_property(srna, "mid_level", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "midlevel"); RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); RNA_def_property_ui_range(prop, 0, 1, 10, 3); @@ -1840,18 +1843,23 @@ static void rna_def_modifier_laplaciansmooth(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME); RNA_def_property_ui_text(prop, "Preserve Volume", "Apply volume preservation after smooth"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "use_normalized", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_LAPLACIANSMOOTH_NORMALIZED); + RNA_def_property_ui_text(prop, "Normalized", "Improve and stabilize the enhanced shape"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); prop = RNA_def_property(srna, "lambda_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "lambda"); RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); - RNA_def_property_ui_range(prop, 0.0000001, 1000.0, 0.0000001, 8); + RNA_def_property_ui_range(prop, -1000.0, 1000.0, 5, 3); RNA_def_property_ui_text(prop, "Lambda Factor", "Smooth factor effect"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); prop = RNA_def_property(srna, "lambda_border", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "lambda_border"); RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); - RNA_def_property_ui_range(prop, 0.0000001, 1000.0, 0.0000001, 8); + RNA_def_property_ui_range(prop, -1000.0, 1000.0, 5, 3); RNA_def_property_ui_text(prop, "Lambda Border", "Lambda factor in border"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); @@ -3473,6 +3481,158 @@ static void rna_def_modifier_triangulate(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Modifier_update"); } +static void rna_def_modifier_meshcache(BlenderRNA *brna) +{ + static EnumPropertyItem prop_format_type_items[] = { + {MOD_MESHCACHE_TYPE_MDD, "MDD", 0, "MDD ", ""}, + {MOD_MESHCACHE_TYPE_PC2, "PC2", 0, "PC2", ""}, + {0, NULL, 0, NULL, NULL} + }; + + static EnumPropertyItem prop_deform_mode_items[] = { + {MOD_MESHCACHE_DEFORM_OVERWRITE, "OVERWRITE", 0, "Overwrite", + "Replace vertex coords with cached values"}, + {MOD_MESHCACHE_DEFORM_INTEGRATE, "INTEGRATE", 0, "Integrate", + "Integrate deformation from this modifiers input with the mesh-cache coords (useful for shape keys)"}, + {0, NULL, 0, NULL, NULL} + }; + + static EnumPropertyItem prop_interpolation_type_items[] = { + {MOD_MESHCACHE_INTERP_NONE, "NONE", 0, "None ", ""}, + {MOD_MESHCACHE_INTERP_LINEAR, "LINEAR", 0, "Linear", ""}, + /* for cardinal we'd need to read 4x cache's */ + // {MOD_MESHCACHE_INTERP_CARDINAL, "CARDINAL", 0, "Cardinal", ""}, + {0, NULL, 0, NULL, NULL} + }; + + static EnumPropertyItem prop_time_type_items[] = { + /* use 'eval_frame' */ + {MOD_MESHCACHE_TIME_FRAME, "FRAME", 0, "Frame", "Control playback using a frame-number " + "(ignoring time FPS and start frame from the file)"}, + /* use 'eval_time' */ + {MOD_MESHCACHE_TIME_SECONDS, "TIME", 0, "Time", "Control playback using time in seconds"}, + /* use 'eval_factor' */ + {MOD_MESHCACHE_TIME_FACTOR, "FACTOR", 0, "Factor", "Control playback using a value between [0, 1]"}, + {0, NULL, 0, NULL, NULL} + }; + + static EnumPropertyItem prop_time_play_items[] = { + {MOD_MESHCACHE_PLAY_CFEA, "SCENE", 0, "Scene", "Use the time from the scene"}, + {MOD_MESHCACHE_PLAY_EVAL, "CUSTOM", 0, "Custom", "Use the modifier's own time evaluation"}, + {0, NULL, 0, NULL, NULL} + }; + + static EnumPropertyItem prop_flip_axis_flag_items[] = { + {(1 << 0), "X", 0, "X", ""}, + {(1 << 1), "Y", 0, "Y", ""}, + {(1 << 2), "Z", 0, "Z", ""}, + {0, NULL, 0, NULL, NULL} + }; + + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "MeshCacheModifier", "Modifier"); + RNA_def_struct_ui_text(srna, "Cache Modifier", "Cache Mesh"); + RNA_def_struct_sdna(srna, "MeshCacheModifierData"); + RNA_def_struct_ui_icon(srna, ICON_MOD_MESHDEFORM); /* XXX, needs own icon */ + + prop = RNA_def_property(srna, "cache_format", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "type"); + RNA_def_property_enum_items(prop, prop_format_type_items); + RNA_def_property_ui_text(prop, "Format", ""); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "interpolation", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "interp"); + RNA_def_property_enum_items(prop, prop_interpolation_type_items); + RNA_def_property_ui_text(prop, "Interpolation", ""); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "time_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "time_mode"); + RNA_def_property_enum_items(prop, prop_time_type_items); + RNA_def_property_ui_text(prop, "Time Mode", "Method to control playback time"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "play_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "play_mode"); + RNA_def_property_enum_items(prop, prop_time_play_items); + RNA_def_property_ui_text(prop, "Time Mode", ""); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "deform_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "deform_mode"); + RNA_def_property_enum_items(prop, prop_deform_mode_items); + RNA_def_property_ui_text(prop, "Deform Mode", ""); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH); + RNA_def_property_ui_text(prop, "File Path", "Path to external displacements file"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "factor"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Influence", "Influence of the deformation"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + /* -------------------------------------------------------------------- */ + /* Axis Conversion */ + prop = RNA_def_property(srna, "forward_axis", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "forward_axis"); + RNA_def_property_enum_items(prop, object_axis_items); + RNA_def_property_ui_text(prop, "Forward", ""); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "up_axis", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "up_axis"); + RNA_def_property_enum_items(prop, object_axis_items); + RNA_def_property_ui_text(prop, "Up", ""); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "flip_axis", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "flip_axis"); + RNA_def_property_enum_items(prop, prop_flip_axis_flag_items); + RNA_def_property_flag(prop, PROP_ENUM_FLAG); + RNA_def_property_ui_text(prop, "Flip Axis", ""); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + /* -------------------------------------------------------------------- */ + /* For Scene time */ + prop = RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "frame_start"); + RNA_def_property_range(prop, -MAXFRAME, MAXFRAME); + RNA_def_property_ui_text(prop, "Frame Start", "Add this to the start frame"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "frame_scale", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "frame_scale"); + RNA_def_property_range(prop, 0.0f, 100.0f); + RNA_def_property_ui_text(prop, "Frame Scale", "Evaluation time in seconds"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + /* -------------------------------------------------------------------- */ + /* eval values depend on 'time_mode' */ + prop = RNA_def_property(srna, "eval_frame", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "eval_frame"); + RNA_def_property_range(prop, MINFRAME, MAXFRAME); + RNA_def_property_ui_text(prop, "Evaluation Frame", "The frame to evaluate (starting at 0)"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "eval_time", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "eval_time"); + RNA_def_property_range(prop, 0.0f, FLT_MAX); + RNA_def_property_ui_text(prop, "Evaluation Time", "Evaluation time in seconds"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "eval_factor", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "eval_factor"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Evaluation Factor", "Evaluation time in seconds"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); +} + void RNA_def_modifier(BlenderRNA *brna) { StructRNA *srna; @@ -3582,6 +3742,7 @@ void RNA_def_modifier(BlenderRNA *brna) rna_def_modifier_skin(brna); rna_def_modifier_laplaciansmooth(brna); rna_def_modifier_triangulate(brna); + rna_def_modifier_meshcache(brna); } #endif diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index 574f06e9107..2b7f6a182a0 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -115,7 +115,7 @@ static void rna_NlaStrip_start_frame_set(PointerRNA *ptr, float value) if (data->prev->type == NLASTRIP_TYPE_TRANSITION) { CLAMP(value, data->prev->start + NLASTRIP_MIN_LEN_THRESH, data->end - NLASTRIP_MIN_LEN_THRESH); - /* readjust the transition to stick to the endpoints of the action-clips */ + /* re-adjust the transition to stick to the endpoints of the action-clips */ data->prev->end = value; } else { diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index eecdf13813c..fe5b6e15f44 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -2537,7 +2537,8 @@ static void def_cmp_dilate_erode(StructRNA *srna) prop = RNA_def_property(srna, "distance", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "custom2"); - RNA_def_property_range(prop, -100, 100); + RNA_def_property_range(prop, -5000, 5000); + RNA_def_property_ui_range(prop, -100, 100, 0, 0); RNA_def_property_ui_text(prop, "Distance", "Distance to grow/shrink (number of iterations)"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index a617c78019f..47b775801f6 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -156,6 +156,15 @@ EnumPropertyItem object_type_curve_items[] = { {0, NULL, 0, NULL, NULL} }; +EnumPropertyItem object_axis_items[] = { + {OB_POSX, "POS_X", 0, "+X", ""}, + {OB_POSY, "POS_Y", 0, "+Y", ""}, + {OB_POSZ, "POS_Z", 0, "+Z", ""}, + {OB_NEGX, "NEG_X", 0, "-X", ""}, + {OB_NEGY, "NEG_Y", 0, "-Y", ""}, + {OB_NEGZ, "NEG_Z", 0, "-Z", ""}, + {0, NULL, 0, NULL, NULL} +}; #ifdef RNA_RUNTIME @@ -2002,16 +2011,6 @@ static void rna_def_object(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; - - static EnumPropertyItem track_items[] = { - {OB_POSX, "POS_X", 0, "+X", ""}, - {OB_POSY, "POS_Y", 0, "+Y", ""}, - {OB_POSZ, "POS_Z", 0, "+Z", ""}, - {OB_NEGX, "NEG_X", 0, "-X", ""}, - {OB_NEGY, "NEG_Y", 0, "-Y", ""}, - {OB_NEGZ, "NEG_Z", 0, "-Z", ""}, - {0, NULL, 0, NULL, NULL} - }; static EnumPropertyItem up_items[] = { {OB_POSX, "X", 0, "X", ""}, @@ -2142,7 +2141,7 @@ static void rna_def_object(BlenderRNA *brna) * since some other tools still refer to this */ prop = RNA_def_property(srna, "track_axis", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "trackflag"); - RNA_def_property_enum_items(prop, track_items); + RNA_def_property_enum_items(prop, object_axis_items); RNA_def_property_ui_text(prop, "Track Axis", "Axis that points in 'forward' direction (applies to DupliFrame when " "parent 'Follow' is enabled)"); @@ -2429,6 +2428,17 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Particle Systems", "Particle systems emitted from the object"); rna_def_object_particle_systems(brna, prop); + + prop = RNA_def_property(srna, "rigid_body", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "rigidbody_object"); + RNA_def_property_struct_type(prop, "RigidBodyObject"); + RNA_def_property_ui_text(prop, "Rigid Body Settings", "Settings for rigid body simulation"); + + prop = RNA_def_property(srna, "rigid_body_constraint", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "rigidbody_constraint"); + RNA_def_property_struct_type(prop, "RigidBodyConstraint"); + RNA_def_property_ui_text(prop, "Rigid Body Constraint", "Constraint constraining rigid bodies"); + /* restrict */ prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", OB_RESTRICT_VIEW); @@ -2557,7 +2567,7 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); prop = RNA_def_property(srna, "show_bounds", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "dtx", OB_BOUNDBOX); + RNA_def_property_boolean_sdna(prop, NULL, "dtx", OB_DRAWBOUNDOX); RNA_def_property_ui_text(prop, "Draw Bounds", "Display the object's bounds"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); @@ -2586,7 +2596,12 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "dtx", OB_DRAWWIRE); RNA_def_property_ui_text(prop, "Draw Wire", "Add the object's wireframe over solid drawing"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); - + + prop = RNA_def_property(srna, "show_all_edges", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "dtx", OB_DRAW_ALL_EDGES); + RNA_def_property_ui_text(prop, "Draw All Edges", "Display all edges for mesh objects"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + prop = RNA_def_property(srna, "show_transparent", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "dtx", OB_DRAWTRANSP); RNA_def_property_ui_text(prop, "Draw Transparent", diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index 0c2944b3966..873ea49824c 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -1182,7 +1182,7 @@ static void rna_def_field(BlenderRNA *brna) prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "f_strength"); - RNA_def_property_range(prop, -1000.0f, 1000.0f); + RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); RNA_def_property_ui_text(prop, "Strength", "Strength of force field"); RNA_def_property_update(prop, 0, "rna_FieldSettings_update"); diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 4a520cdc729..bd3e4e6862d 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -349,14 +349,17 @@ static void rna_ParticleSystem_co_hair(ParticleSystem *particlesystem, Object *o /*strands key loop data stored in cache + step->co*/ if (path_nbr) { if (step >= 0 && step <= path_nbr) { - if (step <= max_k) + if (step <= max_k) { copy_v3_v3(n_co, (cache + step)->co); + mul_m4_v3(particlesystem->imat, n_co); + mul_m4_v3(object->obmat, n_co); + } } } } -static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, ParticleSystemModifierData *modifier, ParticleData *particle, int particle_no, +static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, ParticleSystemModifierData *modifier, ParticleData *particle, int particle_no, int uv_no, float n_uv[2]) { ParticleSettings *part = 0; @@ -395,7 +398,7 @@ static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem, Par if (n_uv && ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME)) { if (num != DMCACHE_NOTFOUND) { MFace *mface = modifier->dm->getTessFaceData(modifier->dm, num, CD_MFACE); - MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, 0); + MTFace *mtface = (MTFace *)CustomData_get_layer_n(&modifier->dm->faceData, CD_MTFACE, uv_no); mtface += num; psys_interpolate_uvs(mtface, mface->v4, particle->fuv, n_uv); @@ -1246,10 +1249,10 @@ static void rna_def_particle_hair_key(BlenderRNA *brna) RNA_def_property_float_funcs(prop, "rna_ParticleHairKey_location_object_get", "rna_ParticleHairKey_location_object_set", NULL); - prop = RNA_def_property(srna, "co_hair_space", PROP_FLOAT, PROP_TRANSLATION); + prop = RNA_def_property(srna, "co_local", PROP_FLOAT, PROP_TRANSLATION); RNA_def_property_float_sdna(prop, NULL, "co"); RNA_def_property_ui_text(prop, "Location", - "Location of the hair key in its internal coordinate system, " + "Location of the hair key in its local coordinate system, " "relative to the emitting face"); /* Aided co func */ @@ -3362,6 +3365,7 @@ static void rna_def_particle_system(BlenderRNA *brna) prop = RNA_def_pointer(func, "modifier", "ParticleSystemModifier", "", "Particle modifier"); prop = RNA_def_pointer(func, "particle", "Particle", "", "Particle"); prop = RNA_def_int(func, "particle_no", 0, INT_MIN, INT_MAX, "Particle no", "", INT_MIN, INT_MAX); + prop = RNA_def_int(func, "uv_no", 0, INT_MIN, INT_MAX, "UV no", "", INT_MIN, INT_MAX); prop = RNA_def_property(func, "uv", PROP_FLOAT, PROP_COORDS); RNA_def_property_array(prop, 2); RNA_def_property_flag(prop, PROP_THICK_WRAP); diff --git a/source/blender/makesrna/intern/rna_rigidbody.c b/source/blender/makesrna/intern/rna_rigidbody.c new file mode 100644 index 00000000000..c1eb3b9b000 --- /dev/null +++ b/source/blender/makesrna/intern/rna_rigidbody.c @@ -0,0 +1,1008 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Foundation 2013, Joshua Leung, Sergej Reich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file rna_rigidbody.c + * \ingroup rna + * \brief RNA property definitions for Rigid Body datatypes + */ + +#include <stdlib.h> +#include <string.h> + +#include "RNA_define.h" + +#include "rna_internal.h" + +#include "DNA_group_types.h" +#include "DNA_object_types.h" +#include "DNA_rigidbody_types.h" +#include "DNA_scene_types.h" + +#include "BLI_utildefines.h" +#include "BLI_math.h" + +#include "WM_types.h" + +/* roles of objects in RigidBody Sims */ +EnumPropertyItem rigidbody_ob_type_items[] = { + {RBO_TYPE_ACTIVE, "ACTIVE", 0, "Active", "Object is directly controlled by simulation results"}, + {RBO_TYPE_PASSIVE, "PASSIVE", 0, "Passive", "Object is directly controlled by animation system"}, + {0, NULL, 0, NULL, NULL}}; + +/* collision shapes of objects in rigid body sim */ +EnumPropertyItem rigidbody_ob_shape_items[] = { + {RB_SHAPE_BOX, "BOX", ICON_MESH_CUBE, "Box", "Box-like shapes (i.e. cubes), including planes (i.e. ground planes)"}, + {RB_SHAPE_SPHERE, "SPHERE", ICON_MESH_UVSPHERE, "Sphere", ""}, + {RB_SHAPE_CAPSULE, "CAPSULE", ICON_OUTLINER_OB_META, "Capsule", ""}, + {RB_SHAPE_CYLINDER, "CYLINDER", ICON_MESH_CYLINDER, "Cylinder", ""}, + {RB_SHAPE_CONE, "CONE", ICON_MESH_CONE, "Cone", ""}, + {RB_SHAPE_CONVEXH, "CONVEX_HULL", ICON_MESH_ICOSPHERE, "Convex Hull", "A mesh-like surface encompassing (i.e. shrinkwrap over) all verts. Best results with fewer vertices"}, + {RB_SHAPE_TRIMESH, "MESH", ICON_MESH_MONKEY, "Mesh", "Mesh consisting of triangles only, allowing for more detailed interactions than convex hulls"}, + {0, NULL, 0, NULL, NULL}}; + +/* collision shapes of constraints in rigid body sim */ +EnumPropertyItem rigidbody_con_type_items[] = { + {RBC_TYPE_FIXED, "FIXED", ICON_FORCE_FORCE, "Fixed", "Glues rigid bodies together"}, + {RBC_TYPE_POINT, "POINT", ICON_FORCE_FORCE, "Point", "Constrains rigid bodies to move aound common pivot point"}, + {RBC_TYPE_HINGE, "HINGE", ICON_FORCE_FORCE, "Hinge", "Restricts rigid body rotation to one axis"}, + {RBC_TYPE_SLIDER, "SLIDER", ICON_FORCE_FORCE, "Slider", "Restricts rigid boddy translation to one axis"}, + {RBC_TYPE_PISTON, "PISTON", ICON_FORCE_FORCE, "Piston", "Restricts rigid boddy translation and rotation to one axis"}, + {RBC_TYPE_6DOF, "GENERIC", ICON_FORCE_FORCE, "Generic", "Restricts translation and rotation to specified axes"}, + {RBC_TYPE_6DOF_SPRING, "GENERIC_SPRING", ICON_FORCE_FORCE, "Generic Spring", "Restricts translation and rotation to specified axes with springs"}, + {0, NULL, 0, NULL, NULL}}; + + +#ifdef RNA_RUNTIME + +#ifdef WITH_BULLET +# include "RBI_api.h" +#endif + +#include "BKE_depsgraph.h" +#include "BKE_rigidbody.h" + +#define RB_FLAG_SET(dest, value, flag) { \ + if (value) \ + dest |= flag; \ + else \ + dest &= ~flag; \ +} + + +/* ******************************** */ + +static void rna_RigidBodyWorld_reset(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + RigidBodyWorld *rbw = (RigidBodyWorld *)ptr->data; + + BKE_rigidbody_cache_reset(rbw); +} + +static char *rna_RigidBodyWorld_path(PointerRNA *ptr) +{ + return BLI_sprintfN("rigidbody_world"); +} + +static void rna_RigidBodyWorld_num_solver_iterations_set(PointerRNA *ptr, int value) +{ + RigidBodyWorld *rbw = (RigidBodyWorld *)ptr->data; + + rbw->num_solver_iterations = value; + +#ifdef WITH_BULLET + if (rbw->physics_world) { + RB_dworld_set_solver_iterations(rbw->physics_world, value); + } +#endif +} + +static void rna_RigidBodyWorld_split_impulse_set(PointerRNA *ptr, int value) +{ + RigidBodyWorld *rbw = (RigidBodyWorld *)ptr->data; + + RB_FLAG_SET(rbw->flag, value, RBW_FLAG_USE_SPLIT_IMPULSE); + +#ifdef WITH_BULLET + if (rbw->physics_world) { + RB_dworld_set_split_impulse(rbw->physics_world, value); + } +#endif +} + +/* ******************************** */ + +static void rna_RigidBodyOb_reset(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + RigidBodyWorld *rbw = scene->rigidbody_world; + + BKE_rigidbody_cache_reset(rbw); +} + +static void rna_RigidBodyOb_shape_reset(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + RigidBodyWorld *rbw = scene->rigidbody_world; + RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; + + BKE_rigidbody_cache_reset(rbw); + if (rbo->physics_shape) + rbo->flag |= RBO_FLAG_NEEDS_RESHAPE; +} + +static char *rna_RigidBodyOb_path(PointerRNA *ptr) +{ + /* NOTE: this hardcoded path should work as long as only Objects have this */ + return BLI_sprintfN("rigid_body"); +} + +static void rna_RigidBodyOb_type_set(PointerRNA *ptr, int value) +{ + RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; + + rbo->type = value; + rbo->flag |= RBO_FLAG_NEEDS_VALIDATE; + +#ifdef WITH_BULLET + /* do physics sim updates */ + if (rbo->physics_object) { + RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo)); + } +#endif +} + +static void rna_RigidBodyOb_disabled_set(PointerRNA *ptr, int value) +{ + RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; + + RB_FLAG_SET(rbo->flag, !value, RBO_FLAG_DISABLED); + +#ifdef WITH_BULLET + /* update kinematic state if necessary - only needed for active bodies */ + if ((rbo->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) { + RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo)); + RB_body_set_kinematic_state(rbo->physics_object, !value); + rbo->flag |= RBO_FLAG_NEEDS_VALIDATE; + } +#endif +} + +static void rna_RigidBodyOb_shape_set(PointerRNA *ptr, int value) +{ + RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; + Object *ob = (Object *)ptr->id.data; + + rbo->shape = value; + + /* force creation of new collision shape reflecting this */ + BKE_rigidbody_validate_sim_shape(ob, TRUE); + +#ifdef WITH_BULLET + /* now tell RB sim about it */ + if (rbo->physics_object && rbo->physics_shape) { + RB_body_set_collision_shape(rbo->physics_object, rbo->physics_shape); + } +#endif +} + + +static void rna_RigidBodyOb_mass_set(PointerRNA *ptr, float value) +{ + RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; + + rbo->mass = value; + +#ifdef WITH_BULLET + /* only active bodies need mass update */ + if ((rbo->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) { + RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo)); + } +#endif +} + +static void rna_RigidBodyOb_friction_set(PointerRNA *ptr, float value) +{ + RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; + + rbo->friction = value; + +#ifdef WITH_BULLET + if (rbo->physics_object) { + RB_body_set_friction(rbo->physics_object, value); + } +#endif +} + +static void rna_RigidBodyOb_restitution_set(PointerRNA *ptr, float value) +{ + RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; + + rbo->restitution = value; +#ifdef WITH_BULLET + if (rbo->physics_object) { + RB_body_set_restitution(rbo->physics_object, value); + } +#endif +} + +static void rna_RigidBodyOb_collision_margin_set(PointerRNA *ptr, float value) +{ + RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; + + rbo->margin = value; + +#ifdef WITH_BULLET + if (rbo->physics_shape) { + RB_shape_set_margin(rbo->physics_shape, RBO_GET_MARGIN(rbo)); + } +#endif +} + +static void rna_RigidBodyOb_kinematic_state_set(PointerRNA *ptr, int value) +{ + RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; + + RB_FLAG_SET(rbo->flag, value, RBO_FLAG_KINEMATIC); + +#ifdef WITH_BULLET + /* update kinematic state if necessary */ + if (rbo->physics_object) { + RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo)); + RB_body_set_kinematic_state(rbo->physics_object, value); + rbo->flag |= RBO_FLAG_NEEDS_VALIDATE; + } +#endif +} + +static void rna_RigidBodyOb_activation_state_set(PointerRNA *ptr, int value) +{ + RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; + + RB_FLAG_SET(rbo->flag, value, RBO_FLAG_USE_DEACTIVATION); + +#ifdef WITH_BULLET + /* update activation state if necessary - only active bodies can be deactivated */ + if ((rbo->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) { + RB_body_set_activation_state(rbo->physics_object, value); + } +#endif +} + +static void rna_RigidBodyOb_linear_sleepThresh_set(PointerRNA *ptr, float value) +{ + RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; + + rbo->lin_sleep_thresh = value; + +#ifdef WITH_BULLET + /* only active bodies need sleep threshold update */ + if ((rbo->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) { + RB_body_set_linear_sleep_thresh(rbo->physics_object, value); + } +#endif +} + +static void rna_RigidBodyOb_angular_sleepThresh_set(PointerRNA *ptr, float value) +{ + RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; + + rbo->ang_sleep_thresh = value; + +#ifdef WITH_BULLET + /* only active bodies need sleep threshold update */ + if ((rbo->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) { + RB_body_set_angular_sleep_thresh(rbo->physics_object, value); + } +#endif +} + +static void rna_RigidBodyOb_linear_damping_set(PointerRNA *ptr, float value) +{ + RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; + + rbo->lin_damping = value; + +#ifdef WITH_BULLET + /* only active bodies need damping update */ + if ((rbo->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) { + RB_body_set_linear_damping(rbo->physics_object, value); + } +#endif +} + +static void rna_RigidBodyOb_angular_damping_set(PointerRNA *ptr, float value) +{ + RigidBodyOb *rbo = (RigidBodyOb *)ptr->data; + + rbo->ang_damping = value; + +#ifdef WITH_BULLET + /* only active bodies need damping update */ + if ((rbo->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) { + RB_body_set_angular_damping(rbo->physics_object, value); + } +#endif +} + +static char *rna_RigidBodyCon_path(PointerRNA *ptr) +{ + /* NOTE: this hardcoded path should work as long as only Objects have this */ + return BLI_sprintfN("rigid_body_constraint"); +} + +static void rna_RigidBodyCon_type_set(PointerRNA *ptr, int value) +{ + RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; + + rbc->type = value; + rbc->flag |= RBC_FLAG_NEEDS_VALIDATE; +} + +static void rna_RigidBodyCon_enabled_set(PointerRNA *ptr, int value) +{ + RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; + + RB_FLAG_SET(rbc->flag, value, RBC_FLAG_ENABLED); + +#ifdef WITH_BULLET + if (rbc->physics_constraint) { + RB_constraint_set_enabled(rbc->physics_constraint, value); + } +#endif +} + +static void rna_RigidBodyCon_disable_collisions_set(PointerRNA *ptr, int value) +{ + RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; + + RB_FLAG_SET(rbc->flag, value, RBC_FLAG_DISABLE_COLLISIONS); + + rbc->flag |= RBC_FLAG_NEEDS_VALIDATE; +} + +static void rna_RigidBodyCon_use_breaking_set(PointerRNA *ptr, int value) +{ + RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; + + if (value) { + rbc->flag |= RBC_FLAG_USE_BREAKING; +#ifdef WITH_BULLET + if (rbc->physics_constraint) { + RB_constraint_set_breaking_threshold(rbc->physics_constraint, rbc->breaking_threshold); + } +#endif + } + else { + rbc->flag &= ~RBC_FLAG_USE_BREAKING; +#ifdef WITH_BULLET + if (rbc->physics_constraint) { + RB_constraint_set_breaking_threshold(rbc->physics_constraint, FLT_MAX); + } +#endif + } +} + +static void rna_RigidBodyCon_breaking_threshold_set(PointerRNA *ptr, float value) +{ + RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; + + rbc->breaking_threshold = value; + +#ifdef WITH_BULLET + if (rbc->physics_constraint && (rbc->flag & RBC_FLAG_USE_BREAKING)) { + RB_constraint_set_breaking_threshold(rbc->physics_constraint, value); + } +#endif +} + +static void rna_RigidBodyCon_override_solver_iterations_set(PointerRNA *ptr, int value) +{ + RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; + + if (value) { + rbc->flag |= RBC_FLAG_OVERRIDE_SOLVER_ITERATIONS; +#ifdef WITH_BULLET + if (rbc->physics_constraint) { + RB_constraint_set_solver_iterations(rbc->physics_constraint, rbc->num_solver_iterations); + } +#endif + } + else { + rbc->flag &= ~RBC_FLAG_OVERRIDE_SOLVER_ITERATIONS; +#ifdef WITH_BULLET + if (rbc->physics_constraint) { + RB_constraint_set_solver_iterations(rbc->physics_constraint, -1); + } +#endif + } +} + +static void rna_RigidBodyCon_num_solver_iterations_set(PointerRNA *ptr, int value) +{ + RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; + + rbc->num_solver_iterations = value; + +#ifdef WITH_BULLET + if (rbc->physics_constraint && (rbc->flag & RBC_FLAG_OVERRIDE_SOLVER_ITERATIONS)) { + RB_constraint_set_solver_iterations(rbc->physics_constraint, value); + } +#endif +} + +static void rna_RigidBodyCon_spring_stiffness_x_set(PointerRNA *ptr, float value) +{ + RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; + + rbc->spring_stiffness_x = value; + +#ifdef WITH_BULLET + if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_X)) { + RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, value); + } +#endif +} + +static void rna_RigidBodyCon_spring_stiffness_y_set(PointerRNA *ptr, float value) +{ + RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; + + rbc->spring_stiffness_y = value; + +#ifdef WITH_BULLET + if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_Y)) { + RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, value); + } +#endif +} + +static void rna_RigidBodyCon_spring_stiffness_z_set(PointerRNA *ptr, float value) +{ + RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; + + rbc->spring_stiffness_z = value; + +#ifdef WITH_BULLET + if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_Z)) { + RB_constraint_set_stiffness_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, value); + } +#endif +} + +static void rna_RigidBodyCon_spring_damping_x_set(PointerRNA *ptr, float value) +{ + RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; + + rbc->spring_damping_x = value; + +#ifdef WITH_BULLET + if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_X)) { + RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_X, value); + } +#endif +} + +static void rna_RigidBodyCon_spring_damping_y_set(PointerRNA *ptr, float value) +{ + RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; + + rbc->spring_damping_y = value; +#ifdef WITH_BULLET + if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_Y)) { + RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Y, value); + } +#endif +} + +static void rna_RigidBodyCon_spring_damping_z_set(PointerRNA *ptr, float value) +{ + RigidBodyCon *rbc = (RigidBodyCon *)ptr->data; + + rbc->spring_damping_z = value; +#ifdef WITH_BULLET + if (rbc->physics_constraint && rbc->type == RBC_TYPE_6DOF_SPRING && (rbc->flag & RBC_FLAG_USE_SPRING_Z)) { + RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_LIN_Z, value); + } +#endif +} + +#else + +static void rna_def_rigidbody_world(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "RigidBodyWorld", NULL); + RNA_def_struct_sdna(srna, "RigidBodyWorld"); + RNA_def_struct_ui_text(srna, "Rigid Body World", "Self-contained rigid body simulation environment and settings"); + RNA_def_struct_path_func(srna, "rna_RigidBodyWorld_path"); + + /* groups */ + prop = RNA_def_property(srna, "group", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "Group"); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_ui_text(prop, "Group", "Group containing objects participating in this simulation"); + RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_reset"); + + prop = RNA_def_property(srna, "constraints", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "Group"); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_ui_text(prop, "Constraints", "Group containing rigid body constraint objects"); + RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_reset"); + + /* booleans */ + prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", RBW_FLAG_MUTED); + RNA_def_property_ui_text(prop, "Enabled", "Simulation will be evaluated"); + RNA_def_property_update(prop, NC_SCENE, NULL); + + /* time scale */ + prop = RNA_def_property(srna, "time_scale", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "time_scale"); + RNA_def_property_range(prop, 0.0f, 100.0f); + RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 3); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_ui_text(prop, "Time Scale", "Changes the speed of the simulation"); + RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_reset"); + + /* timestep */ + prop = RNA_def_property(srna, "steps_per_second", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "steps_per_second"); + RNA_def_property_range(prop, 1, SHRT_MAX); + RNA_def_property_ui_range(prop, 60, 1000, 1, 0); + RNA_def_property_int_default(prop, 60); + RNA_def_property_ui_text(prop, "Steps Per Second", "Number of simulation steps taken per second (higher values are more accurate but slower)"); + RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_reset"); + + /* constraint solver iterations */ + prop = RNA_def_property(srna, "num_solver_iterations", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "num_solver_iterations"); + RNA_def_property_range(prop, 1, 1000); + RNA_def_property_ui_range(prop, 10, 100, 1, 0); + RNA_def_property_int_default(prop, 10); + RNA_def_property_int_funcs(prop, NULL, "rna_RigidBodyWorld_num_solver_iterations_set", NULL); + RNA_def_property_ui_text(prop, "Solver Iterations", "Number of constraint solver iterations made per simulation step (higher values are more accurate but slower)"); + RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_reset"); + + /* split impulse */ + prop = RNA_def_property(srna, "use_split_impulse", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", RBW_FLAG_USE_SPLIT_IMPULSE); + RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyWorld_split_impulse_set"); + RNA_def_property_ui_text(prop, "Split Impulse", "Reduces extra velocity that can build up when objects collide (lowers simulation stabilty a litte so use only when necessary)"); + RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_reset"); + + /* cache */ + prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "pointcache"); + RNA_def_property_ui_text(prop, "Point Cache", ""); + + /* effector weights */ + prop = RNA_def_property(srna, "effector_weights", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "EffectorWeights"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Effector Weights", ""); +} + +static void rna_def_rigidbody_object(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + + srna = RNA_def_struct(brna, "RigidBodyObject", NULL); + RNA_def_struct_sdna(srna, "RigidBodyOb"); + RNA_def_struct_ui_text(srna, "Rigid Body Object", "Settings for object participating in Rigid Body Simulation"); + RNA_def_struct_path_func(srna, "rna_RigidBodyOb_path"); + + /* Enums */ + prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "type"); + RNA_def_property_enum_items(prop, rigidbody_ob_type_items); + RNA_def_property_enum_funcs(prop, NULL, "rna_RigidBodyOb_type_set", NULL); + RNA_def_property_ui_text(prop, "Type", "Role of object in Rigid Body Simulations"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + + /* booleans */ + prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", RBO_FLAG_DISABLED); + RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyOb_disabled_set"); + RNA_def_property_ui_text(prop, "Enabled", "Rigid Body actively participated in the simulation"); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "collision_shape", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "shape"); + RNA_def_property_enum_items(prop, rigidbody_ob_shape_items); + RNA_def_property_enum_funcs(prop, NULL, "rna_RigidBodyOb_shape_set", NULL); + RNA_def_property_ui_text(prop, "Collision Shape", "Collision Shape of object in Rigid Body Simulations"); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "kinematic", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", RBO_FLAG_KINEMATIC); + RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyOb_kinematic_state_set"); + RNA_def_property_ui_text(prop, "Kinematic", "Allows rigid body to be controlled by the animation system"); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + + /* Physics Parameters */ + prop = RNA_def_property(srna, "mass", PROP_FLOAT, PROP_UNIT_MASS); + RNA_def_property_float_sdna(prop, NULL, "mass"); + RNA_def_property_range(prop, 0.001f, FLT_MAX); // range must always be positive (and non-zero) + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_mass_set", NULL); + RNA_def_property_ui_text(prop, "Mass", "How much the object 'weighs' irrespective of gravity"); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + + /* Dynamics Parameters - Activation */ + // TODO: define and figure out how to implement these + + /* Dynamics Parameters - Deactivation */ + prop = RNA_def_property(srna, "use_deactivation", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", RBO_FLAG_USE_DEACTIVATION); + RNA_def_property_boolean_default(prop, TRUE); + RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyOb_activation_state_set"); + RNA_def_property_ui_text(prop, "Enable Deactivation", "Enables deactivation of resting rigid bodies (increases performance and stability but can cause glitches)"); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "start_deactivated", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", RBO_FLAG_START_DEACTIVATED); + RNA_def_property_ui_text(prop, "Start Deactivated", "Deactivates rigid body at the start of the simulation"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "deactivate_linear_velocity", PROP_FLOAT, PROP_UNIT_VELOCITY); + RNA_def_property_float_sdna(prop, NULL, "lin_sleep_thresh"); + RNA_def_property_range(prop, FLT_MIN, FLT_MAX); // range must always be positive (and non-zero) + RNA_def_property_float_default(prop, 0.4f); + RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_linear_sleepThresh_set", NULL); + RNA_def_property_ui_text(prop, "Linear Velocity Deactivation Threshold", "Linear Velocity below which simulation stops simulating object"); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "deactivate_angular_velocity", PROP_FLOAT, PROP_UNIT_VELOCITY); + RNA_def_property_float_sdna(prop, NULL, "ang_sleep_thresh"); + RNA_def_property_range(prop, FLT_MIN, FLT_MAX); // range must always be positive (and non-zero) + RNA_def_property_float_default(prop, 0.5f); + RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_angular_sleepThresh_set", NULL); + RNA_def_property_ui_text(prop, "Angular Velocity Deactivation Threshold", "Angular Velocity below which simulation stops simulating object"); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + + /* Dynamics Parameters - Damping Parameters */ + prop = RNA_def_property(srna, "linear_damping", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "lin_damping"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_float_default(prop, 0.04f); + RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_linear_damping_set", NULL); + RNA_def_property_ui_text(prop, "Linear Damping", "Amount of linear velocity that is lost over time"); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "angular_damping", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "ang_damping"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_float_default(prop, 0.1f); + RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_angular_damping_set", NULL); + RNA_def_property_ui_text(prop, "Angular Damping", "Amount of angular velocity that is lost over time"); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + + /* Collision Parameters - Surface Parameters */ + prop = RNA_def_property(srna, "friction", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "friction"); + RNA_def_property_range(prop, 0.0f, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 1, 3); + RNA_def_property_float_default(prop, 0.5f); + RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_friction_set", NULL); + RNA_def_property_ui_text(prop, "Friction", "Resistance of object to movement"); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "restitution", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "restitution"); + RNA_def_property_range(prop, 0.0f, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 1, 3); + RNA_def_property_float_default(prop, 0.0f); + RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_restitution_set", NULL); + RNA_def_property_ui_text(prop, "Restitution", "Tendency of object to bounce after colliding with another (0 = stays still, 1 = perfectly elastic)"); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + + /* Collision Parameters - Sensitivity */ + prop = RNA_def_property(srna, "use_margin", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", RBO_FLAG_USE_MARGIN); + RNA_def_property_boolean_default(prop, FALSE); + RNA_def_property_ui_text(prop, "Collision Margin", "Use custom collision margin (some shapes will have a visible gap around them)"); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_shape_reset"); + + prop = RNA_def_property(srna, "collision_margin", PROP_FLOAT, PROP_UNIT_LENGTH); + RNA_def_property_float_sdna(prop, NULL, "margin"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.01, 3); + RNA_def_property_float_default(prop, 0.04f); + RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_collision_margin_set", NULL); + RNA_def_property_ui_text(prop, "Collision Margin", "Threshold of distance near surface where collisions are still considered (best results when non-zero)"); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_shape_reset"); + + prop = RNA_def_property(srna, "collision_groups", PROP_BOOLEAN, PROP_LAYER_MEMBER); + RNA_def_property_boolean_sdna(prop, NULL, "col_groups", 1); + RNA_def_property_array(prop, 20); + RNA_def_property_ui_text(prop, "Collison Groups", "Collision Groups Rigid Body belongs to"); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + RNA_def_property_flag(prop, PROP_LIB_EXCEPTION); +} + +static void rna_def_rigidbody_constraint(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "RigidBodyConstraint", NULL); + RNA_def_struct_sdna(srna, "RigidBodyCon"); + RNA_def_struct_ui_text(srna, "Rigid Body Constraint", "Constraint influencing Objects inside Rigid Body Simulation"); + RNA_def_struct_path_func(srna, "rna_RigidBodyCon_path"); + + /* Enums */ + prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "type"); + RNA_def_property_enum_items(prop, rigidbody_con_type_items); + RNA_def_property_enum_funcs(prop, NULL, "rna_RigidBodyCon_type_set", NULL); + RNA_def_property_ui_text(prop, "Type", "Type of Rigid Body Constraint"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_ENABLED); + RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyCon_enabled_set"); + RNA_def_property_ui_text(prop, "Enabled", "Enable this constraint"); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "disable_collisions", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_DISABLE_COLLISIONS); + RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyCon_disable_collisions_set"); + RNA_def_property_ui_text(prop, "Disable Collisions", "Disables collisions between constrained ridid bodies"); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "object1", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "ob1"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Object 1", "First Rigid Body Object to be constrained"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "object2", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "ob2"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Object 2", "Second Rigid Body Object to be constrained"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + + /* Breaking Threshold */ + prop = RNA_def_property(srna, "use_breaking", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_BREAKING); + RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyCon_use_breaking_set"); + RNA_def_property_ui_text(prop, "Breakable", "Constraint can be broaken if it receives an impulse above the threshold"); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "breaking_threshold", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "breaking_threshold"); + RNA_def_property_range(prop, 0.0f, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0f, 1000.0f, 100.0, 2); + RNA_def_property_float_default(prop, 10.0f); + RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_breaking_threshold_set", NULL); + RNA_def_property_ui_text(prop, "Breaking Threshold", "Impulse threshold that must be reached for the constraint to break"); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + + /* Solver Iterations */ + prop = RNA_def_property(srna, "override_solver_iterations", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_OVERRIDE_SOLVER_ITERATIONS); + RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyCon_override_solver_iterations_set"); + RNA_def_property_ui_text(prop, "Override Solver Iterations", "Overrides the number of solver iterations for this constraint"); + RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "num_solver_iterations", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "num_solver_iterations"); + RNA_def_property_range(prop, 1, 1000); + RNA_def_property_ui_range(prop, 1, 100, 1, 0); + RNA_def_property_int_default(prop, 10); + RNA_def_property_int_funcs(prop, NULL, "rna_RigidBodyCon_num_solver_iterations_set", NULL); + RNA_def_property_ui_text(prop, "Solver Iterations", "Number of constraint solver iterations made per simulation step (higher values are more accurate but slower)"); + RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset"); + + /* Limits */ + prop = RNA_def_property(srna, "use_limit_lin_x", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_LIMIT_LIN_X); + RNA_def_property_ui_text(prop, "X Axis", "Limits translation on x axis"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "use_limit_lin_y", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_LIMIT_LIN_Y); + RNA_def_property_ui_text(prop, "Y Axis", "Limits translation on y axis"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "use_limit_lin_z", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_LIMIT_LIN_Z); + RNA_def_property_ui_text(prop, "Z Axis", "Limits translation on z axis"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "use_limit_ang_x", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_LIMIT_ANG_X); + RNA_def_property_ui_text(prop, "X Angle", "Limits rotation around x axis"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "use_limit_ang_y", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_LIMIT_ANG_Y); + RNA_def_property_ui_text(prop, "Y Angle", "Limits rotation around y axis"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "use_limit_ang_z", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_LIMIT_ANG_Z); + RNA_def_property_ui_text(prop, "Z Angle", "Limits rotation around z axis"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "use_spring_x", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_SPRING_X); + RNA_def_property_ui_text(prop, "X Spring", "Enables spring on X axis"); + RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "use_spring_y", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_SPRING_Y); + RNA_def_property_ui_text(prop, "Y Spring", "Enables spring on Y axis"); + RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "use_spring_z", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", RBC_FLAG_USE_SPRING_Z); + RNA_def_property_ui_text(prop, "Z Spring", "Enables spring on Z axis"); + RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "limit_lin_x_lower", PROP_FLOAT, PROP_UNIT_LENGTH); + RNA_def_property_float_sdna(prop, NULL, "limit_lin_x_lower"); + RNA_def_property_float_default(prop, -1.0f); + RNA_def_property_ui_text(prop, "Lower X Limit", "Lower limit of x axis translation"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "limit_lin_x_upper", PROP_FLOAT, PROP_UNIT_LENGTH); + RNA_def_property_float_sdna(prop, NULL, "limit_lin_x_upper"); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_ui_text(prop, "Upper X Limit", "Upper limit of x axis translation"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "limit_lin_y_lower", PROP_FLOAT, PROP_UNIT_LENGTH); + RNA_def_property_float_sdna(prop, NULL, "limit_lin_y_lower"); + RNA_def_property_float_default(prop, -1.0f); + RNA_def_property_ui_text(prop, "Lower Y Limit", "Lower limit of y axis translation"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "limit_lin_y_upper", PROP_FLOAT, PROP_UNIT_LENGTH); + RNA_def_property_float_sdna(prop, NULL, "limit_lin_y_upper"); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_ui_text(prop, "Upper Y Limit", "Upper limit of y axis translation"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "limit_lin_z_lower", PROP_FLOAT, PROP_UNIT_LENGTH); + RNA_def_property_float_sdna(prop, NULL, "limit_lin_z_lower"); + RNA_def_property_float_default(prop, -1.0f); + RNA_def_property_ui_text(prop, "Lower Z Limit", "Lower limit of z axis translation"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "limit_lin_z_upper", PROP_FLOAT, PROP_UNIT_LENGTH); + RNA_def_property_float_sdna(prop, NULL, "limit_lin_z_upper"); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_ui_text(prop, "Upper Z Limit", "Upper limit of z axis translation"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "limit_ang_x_lower", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "limit_ang_x_lower"); + RNA_def_property_range(prop, -M_PI * 2, M_PI * 2); + RNA_def_property_float_default(prop, -M_PI_4); + RNA_def_property_ui_text(prop, "Lower X Angle Limit", "Lower limit of x axis rotation"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "limit_ang_x_upper", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "limit_ang_x_upper"); + RNA_def_property_range(prop, -M_PI * 2, M_PI * 2); + RNA_def_property_float_default(prop, M_PI_4); + RNA_def_property_ui_text(prop, "Upper X Angle Limit", "Upper limit of x axis rotation"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "limit_ang_y_lower", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "limit_ang_y_lower"); + RNA_def_property_range(prop, -M_PI * 2, M_PI * 2); + RNA_def_property_float_default(prop, -M_PI_4); + RNA_def_property_ui_text(prop, "Lower Y Angle Limit", "Lower limit of y axis rotation"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "limit_ang_y_upper", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "limit_ang_y_upper"); + RNA_def_property_range(prop, -M_PI * 2, M_PI * 2); + RNA_def_property_float_default(prop, M_PI_4); + RNA_def_property_ui_text(prop, "Upper Y Angle Limit", "Upper limit of y axis rotation"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "limit_ang_z_lower", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "limit_ang_z_lower"); + RNA_def_property_range(prop, -M_PI * 2, M_PI * 2); + RNA_def_property_float_default(prop, -M_PI_4); + RNA_def_property_ui_text(prop, "Lower Z Angle Limit", "Lower limit of z axis rotation"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "limit_ang_z_upper", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "limit_ang_z_upper"); + RNA_def_property_range(prop, -M_PI * 2, M_PI * 2); + RNA_def_property_float_default(prop, M_PI_4); + RNA_def_property_ui_text(prop, "Upper Z Angle Limit", "Upper limit of z axis rotation"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "spring_stiffness_x", PROP_FLOAT, PROP_UNIT_LENGTH); + RNA_def_property_float_sdna(prop, NULL, "spring_stiffness_x"); + RNA_def_property_range(prop, 0.0f, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3); + RNA_def_property_float_default(prop, 10.0f); + RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_spring_stiffness_x_set", NULL); + RNA_def_property_ui_text(prop, "X Axis Stiffness", "Stiffness on the X axis"); + RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "spring_stiffness_y", PROP_FLOAT, PROP_UNIT_LENGTH); + RNA_def_property_float_sdna(prop, NULL, "spring_stiffness_y"); + RNA_def_property_range(prop, 0.0f, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3); + RNA_def_property_float_default(prop, 10.0f); + RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_spring_stiffness_y_set", NULL); + RNA_def_property_ui_text(prop, "Y Axis Stiffness", "Stiffness on the Y axis"); + RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "spring_stiffness_z", PROP_FLOAT, PROP_UNIT_LENGTH); + RNA_def_property_float_sdna(prop, NULL, "spring_stiffness_z"); + RNA_def_property_range(prop, 0.0f, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3); + RNA_def_property_float_default(prop, 10.0f); + RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_spring_stiffness_z_set", NULL); + RNA_def_property_ui_text(prop, "Z Axis Stiffness", "Stiffness on the Z axis"); + RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "spring_damping_x", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "spring_damping_x"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_float_default(prop, 0.5f); + RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_spring_damping_x_set", NULL); + RNA_def_property_ui_text(prop, "Damping X", "Damping on the X axis"); + RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "spring_damping_y", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "spring_damping_y"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_float_default(prop, 0.5f); + RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_spring_damping_y_set", NULL); + RNA_def_property_ui_text(prop, "Damping Y", "Damping on the Y axis"); + RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset"); + + prop = RNA_def_property(srna, "spring_damping_z", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "spring_damping_z"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_float_default(prop, 0.5f); + RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyCon_spring_damping_z_set", NULL); + RNA_def_property_ui_text(prop, "Damping Z", "Damping on the Z axis"); + RNA_def_property_update(prop, NC_OBJECT, "rna_RigidBodyOb_reset"); +} + +void RNA_def_rigidbody(BlenderRNA *brna) +{ + rna_def_rigidbody_world(brna); + rna_def_rigidbody_object(brna); + rna_def_rigidbody_constraint(brna); +} + + +#endif diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c index 3f03445635f..b5b3897ed46 100644 --- a/source/blender/makesrna/intern/rna_rna.c +++ b/source/blender/makesrna/intern/rna_rna.c @@ -31,6 +31,7 @@ #include "RNA_access.h" #include "RNA_define.h" +#include "RNA_enum_types.h" #include "rna_internal.h" @@ -45,6 +46,9 @@ EnumPropertyItem property_type_items[] = { {0, NULL, 0, NULL, NULL} }; +/* XXX Keep in sync with bpy_props.c's property_subtype_xxx_items ??? + * Currently it is not... + */ EnumPropertyItem property_subtype_items[] = { {PROP_NONE, "NONE", 0, "None", ""}, @@ -52,7 +56,7 @@ EnumPropertyItem property_subtype_items[] = { {PROP_FILEPATH, "FILEPATH", 0, "File Path", ""}, {PROP_DIRPATH, "DIRPATH", 0, "Directory Path", ""}, {PROP_FILENAME, "FILENAME", 0, "File Name", ""}, - {PROP_TRANSLATE, "TRANSLATE", 0, "Translate", ""}, + {PROP_PASSWORD, "PASSWORD", 0, "Password", "A string that is displayed hidden ('********')"}, /* numbers */ {PROP_UNSIGNED, "UNSIGNED", 0, "Unsigned", ""}, @@ -522,6 +526,13 @@ static int rna_Property_unit_get(PointerRNA *ptr) return RNA_SUBTYPE_UNIT(prop->subtype); } +static int rna_Property_icon_get(PointerRNA *ptr) +{ + PropertyRNA *prop = (PropertyRNA *)ptr->data; + rna_idproperty_check(&prop, ptr); + return prop->icon; +} + static int rna_Property_readonly_get(PointerRNA *ptr) { PropertyRNA *prop = (PropertyRNA *)ptr->data; @@ -880,6 +891,11 @@ static int rna_EnumPropertyItem_value_get(PointerRNA *ptr) return ((EnumPropertyItem *)ptr->data)->value; } +static int rna_EnumPropertyItem_icon_get(PointerRNA *ptr) +{ + return ((EnumPropertyItem *)ptr->data)->icon; +} + static PointerRNA rna_PointerProperty_fixed_type_get(PointerRNA *ptr) { PropertyRNA *prop = (PropertyRNA *)ptr->data; @@ -1131,6 +1147,12 @@ static void rna_def_property(BlenderRNA *brna) RNA_def_property_enum_funcs(prop, "rna_Property_unit_get", NULL, NULL); RNA_def_property_ui_text(prop, "Unit", "Type of units for this property"); + prop = RNA_def_property(srna, "icon", PROP_ENUM, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_enum_items(prop, icon_items); + RNA_def_property_enum_funcs(prop, "rna_Property_icon_get", NULL, NULL); + RNA_def_property_ui_text(prop, "Icon", "Icon of the item"); + prop = RNA_def_property(srna, "is_readonly", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_boolean_funcs(prop, "rna_Property_readonly_get", NULL); @@ -1408,6 +1430,12 @@ static void rna_def_enum_property(BlenderRNA *brna, StructRNA *srna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_int_funcs(prop, "rna_EnumPropertyItem_value_get", NULL, NULL); RNA_def_property_ui_text(prop, "Value", "Value of the item"); + + prop = RNA_def_property(srna, "icon", PROP_ENUM, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_enum_items(prop, icon_items); + RNA_def_property_enum_funcs(prop, "rna_EnumPropertyItem_icon_get", NULL, NULL); + RNA_def_property_ui_text(prop, "Icon", "Icon of the item"); } static void rna_def_pointer_property(StructRNA *srna, PropertyType type) diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index f4059bc5846..96bd0fb327e 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -35,6 +35,7 @@ #include "DNA_group_types.h" #include "DNA_modifier_types.h" #include "DNA_particle_types.h" +#include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" #include "DNA_userdef_types.h" #include "DNA_world_types.h" @@ -412,7 +413,7 @@ static void rna_Scene_object_unlink(Scene *scene, ReportList *reports, Object *o scene->basact = NULL; } - BLI_remlink(&scene->base, base); + BKE_scene_base_unlink(scene, base); MEM_freeN(base); ob->id.us--; @@ -1427,6 +1428,11 @@ static void rna_UnifiedPaintSettings_unprojected_radius_set(PointerRNA *ptr, flo ups->unprojected_radius = value; } +static char *rna_UnifiedPaintSettings_path(PointerRNA *ptr) +{ + return BLI_strdup("tool_settings.unified_paint_settings"); +} + /* note: without this, when Multi-Paint is activated/deactivated, the colors * will not change right away when multiple bones are selected, this function * is not for general use and only for the few cases where changing scene @@ -1456,6 +1462,11 @@ static void rna_SceneSequencer_update(Main *UNUSED(bmain), Scene *UNUSED(scene), BKE_sequencer_preprocessed_cache_cleanup(); } +static char *rna_ToolSettings_path(PointerRNA *ptr) +{ + return BLI_strdup("tool_settings"); +} + #ifdef WITH_FREESTYLE static PointerRNA rna_FreestyleLineSet_linestyle_get(PointerRNA *ptr) { @@ -1576,6 +1587,7 @@ static void rna_def_tool_settings(BlenderRNA *brna) }; srna = RNA_def_struct(brna, "ToolSettings", NULL); + RNA_def_struct_path_func(srna, "rna_ToolSettings_path"); RNA_def_struct_ui_text(srna, "Tool Settings", ""); prop = RNA_def_property(srna, "sculpt", PROP_POINTER, PROP_NONE); @@ -1892,6 +1904,7 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna) PropertyRNA *prop; srna = RNA_def_struct(brna, "UnifiedPaintSettings", NULL); + RNA_def_struct_path_func(srna, "rna_UnifiedPaintSettings_path"); RNA_def_struct_ui_text(srna, "Unified Paint Settings", "Overrides for some of the active brush's settings"); /* high-level flags to enable or disable unified paint settings */ @@ -4202,7 +4215,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop = RNA_def_property(srna, "motion_blur_shutter", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_float_sdna(prop, NULL, "blurfac"); - RNA_def_property_ui_range(prop, 0.01f, 2.0f, 1, 0); + RNA_def_property_ui_range(prop, 0.01f, 2.0f, 1, 1); RNA_def_property_ui_text(prop, "Shutter", "Time taken in frames between shutter open and close"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update"); @@ -5059,6 +5072,13 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET, NULL); rna_def_scene_keying_sets_all(brna, prop); + /* Rigid Body Simulation */ + prop = RNA_def_property(srna, "rigidbody_world", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "rigidbody_world"); + RNA_def_property_struct_type(prop, "RigidBodyWorld"); + RNA_def_property_ui_text(prop, "Rigid Body World", ""); + RNA_def_property_update(prop, NC_SCENE, NULL); + /* Tool Settings */ prop = RNA_def_property(srna, "tool_settings", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index 9b5a858a581..e877367790e 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -101,6 +101,7 @@ static void rna_Scene_collada_export( int selected, int include_children, int include_armatures, + int include_shapekeys, int deform_bones_only, int active_uv_only, @@ -113,7 +114,7 @@ static void rna_Scene_collada_export( int second_life) { collada_export(scene, filepath, apply_modifiers, export_mesh_type, selected, - include_children, include_armatures, deform_bones_only, + include_children, include_armatures, include_shapekeys, deform_bones_only, active_uv_only, include_uv_textures, include_material_textures, use_texture_copies, use_object_instantiation, sort_by_name, second_life); } @@ -149,6 +150,7 @@ void RNA_api_scene(StructRNA *srna) parm = RNA_def_boolean(func, "selected", 0, "Selection Only", "Export only selected elements"); parm = RNA_def_boolean(func, "include_children", 0, "Include Children", "Export all children of selected objects (even if not selected)"); parm = RNA_def_boolean(func, "include_armatures", 0, "Include Armatures", "Export related armatures (even if not selected)"); + parm = RNA_def_boolean(func, "include_shapekeys", 0, "Include Shape Keys", "Export all Shape Keys from Mesh Objects"); parm = RNA_def_boolean(func, "deform_bones_only", 0, "Deform Bones only", "Only export deforming bones with armatures"); parm = RNA_def_boolean(func, "active_uv_only", 0, "Active UV Layer only", "Export only the active UV Layer"); diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c index cc1895541df..08bac1da7a7 100644 --- a/source/blender/makesrna/intern/rna_sculpt_paint.c +++ b/source/blender/makesrna/intern/rna_sculpt_paint.c @@ -190,6 +190,11 @@ static int rna_ParticleEdit_hair_get(PointerRNA *ptr) return 0; } +static char *rna_ParticleEdit_path(PointerRNA *ptr) +{ + return BLI_strdup("tool_settings.particle_edit"); +} + static int rna_Brush_mode_poll(PointerRNA *ptr, PointerRNA value) { Scene *scene = (Scene *)ptr->id.data; @@ -242,6 +247,38 @@ static void rna_Sculpt_ShowDiffuseColor_update(Main *UNUSED(bmain), Scene *scene } } +static char *rna_Sculpt_path(PointerRNA *ptr) +{ + return BLI_strdup("tool_settings.sculpt"); +} + +static char *rna_VertexPaint_path(PointerRNA *ptr) +{ + Scene *scene = (Scene *)ptr->id.data; + ToolSettings *ts = scene->toolsettings; + if (ptr->data == ts->vpaint) { + return BLI_strdup("tool_settings.vertex_paint"); + } + else { + return BLI_strdup("tool_settings.weight_paint"); + } +} + +static char *rna_ImagePaintSettings_path(PointerRNA *ptr) +{ + return BLI_strdup("tool_settings.image_paint"); +} + +static char *rna_UvSculpt_path(PointerRNA *ptr) +{ + return BLI_strdup("tool_settings.uv_sculpt"); +} + +static char *rna_ParticleBrush_path(PointerRNA *ptr) +{ + return BLI_strdup("tool_settings.particle_edit.brush"); +} + #else static void rna_def_paint(BlenderRNA *brna) @@ -283,6 +320,7 @@ static void rna_def_sculpt(BlenderRNA *brna) PropertyRNA *prop; srna = RNA_def_struct(brna, "Sculpt", "Paint"); + RNA_def_struct_path_func(srna, "rna_Sculpt_path"); RNA_def_struct_ui_text(srna, "Sculpt", ""); prop = RNA_def_property(srna, "radial_symmetry", PROP_INT, PROP_XYZ); @@ -368,6 +406,7 @@ static void rna_def_uv_sculpt(BlenderRNA *brna) StructRNA *srna; srna = RNA_def_struct(brna, "UvSculpt", "Paint"); + RNA_def_struct_path_func(srna, "rna_UvSculpt_path"); RNA_def_struct_ui_text(srna, "UV Sculpting", ""); } @@ -380,6 +419,7 @@ static void rna_def_vertex_paint(BlenderRNA *brna) srna = RNA_def_struct(brna, "VertexPaint", "Paint"); RNA_def_struct_sdna(srna, "VPaint"); + RNA_def_struct_path_func(srna, "rna_VertexPaint_path"); RNA_def_struct_ui_text(srna, "Vertex Paint", "Properties of vertex and weight paint mode"); /* vertex paint only */ @@ -408,6 +448,7 @@ static void rna_def_image_paint(BlenderRNA *brna) srna = RNA_def_struct(brna, "ImagePaint", "Paint"); RNA_def_struct_sdna(srna, "ImagePaintSettings"); + RNA_def_struct_path_func(srna, "rna_ImagePaintSettings_path"); RNA_def_struct_ui_text(srna, "Image Paint", "Properties of image and texture painting mode"); /* booleans */ @@ -492,6 +533,7 @@ static void rna_def_particle_edit(BlenderRNA *brna) srna = RNA_def_struct(brna, "ParticleEdit", NULL); RNA_def_struct_sdna(srna, "ParticleEditSettings"); + RNA_def_struct_path_func(srna, "rna_ParticleEdit_path"); RNA_def_struct_ui_text(srna, "Particle Edit", "Properties of particle editing mode"); prop = RNA_def_property(srna, "tool", PROP_ENUM, PROP_NONE); @@ -587,6 +629,7 @@ static void rna_def_particle_edit(BlenderRNA *brna) srna = RNA_def_struct(brna, "ParticleBrush", NULL); RNA_def_struct_sdna(srna, "ParticleBrushData"); + RNA_def_struct_path_func(srna, "rna_ParticleBrush_path"); RNA_def_struct_ui_text(srna, "Particle Brush", "Particle editing brush"); prop = RNA_def_property(srna, "size", PROP_INT, PROP_DISTANCE); diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index a41551fc8da..f7daf6a3b06 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -40,6 +40,8 @@ #include "DNA_sequence_types.h" #include "DNA_movieclip_types.h" +#include "BLI_math.h" + #include "BKE_animsys.h" #include "BKE_global.h" #include "BKE_sequencer.h" @@ -48,7 +50,6 @@ #include "MEM_guardedalloc.h" #include "WM_types.h" -#include "BLI_math.h" #include "BLF_translation.h" @@ -2058,13 +2059,13 @@ static void rna_def_transform(StructRNA *srna) prop = RNA_def_property(srna, "scale_start_x", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_float_sdna(prop, NULL, "ScalexIni"); RNA_def_property_ui_text(prop, "Scale X", ""); - RNA_def_property_ui_range(prop, 0, 10, 3, 10); + RNA_def_property_ui_range(prop, 0, 10, 3, 6); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "scale_start_y", PROP_FLOAT, PROP_UNSIGNED); RNA_def_property_float_sdna(prop, NULL, "ScaleyIni"); RNA_def_property_ui_text(prop, "Scale Y", ""); - RNA_def_property_ui_range(prop, 0, 10, 3, 10); + RNA_def_property_ui_range(prop, 0, 10, 3, 6); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "use_uniform_scale", PROP_BOOLEAN, PROP_NONE); @@ -2075,13 +2076,13 @@ static void rna_def_transform(StructRNA *srna) prop = RNA_def_property(srna, "translate_start_x", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "xIni"); RNA_def_property_ui_text(prop, "Translate X", ""); - RNA_def_property_ui_range(prop, -500.0f, 500.0f, 3, 10); + RNA_def_property_ui_range(prop, -500.0f, 500.0f, 3, 6); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "translate_start_y", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "yIni"); RNA_def_property_ui_text(prop, "Translate Y", ""); - RNA_def_property_ui_range(prop, -500.0f, 500.0f, 3, 10); + RNA_def_property_ui_range(prop, -500.0f, 500.0f, 3, 6); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); prop = RNA_def_property(srna, "rotation_start", PROP_FLOAT, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 7fa3aae8ede..cccdf3258d2 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -41,6 +41,7 @@ #include "DNA_action_types.h" #include "DNA_key_types.h" +#include "DNA_material_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_space_types.h" @@ -144,6 +145,7 @@ EnumPropertyItem clip_editor_mode_items[] = { #include "BKE_paint.h" #include "BKE_scene.h" #include "BKE_screen.h" +#include "BKE_icons.h" #include "ED_image.h" #include "ED_node.h" @@ -152,6 +154,8 @@ EnumPropertyItem clip_editor_mode_items[] = { #include "ED_sequencer.h" #include "ED_clip.h" +#include "GPU_material.h" + #include "IMB_imbuf_types.h" static StructRNA *rna_Space_refine(struct PointerRNA *ptr) @@ -376,6 +380,31 @@ static void rna_SpaceView3D_viewport_shade_update(Main *UNUSED(bmain), Scene *UN } } +static void rna_SpaceView3D_matcap_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + View3D *v3d = (View3D *)(ptr->data); + + if (v3d->defmaterial) { + Material *ma = v3d->defmaterial; + + if (ma->preview) + BKE_previewimg_free(&ma->preview); + + if (ma->gpumaterial.first) + GPU_material_free(ma); + + WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, ma); + } +} + +static void rna_SpaceView3D_matcap_enable(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + View3D *v3d = (View3D *)(ptr->data); + + if (v3d->matcap_icon == 0) + v3d->matcap_icon = ICON_MATCAP_01; +} + static void rna_SpaceView3D_pivot_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) { if (U.uiflag & USER_LOCKAROUND) { @@ -482,8 +511,9 @@ static void rna_RegionView3D_view_rotation_set(PointerRNA *ptr, const float *val static void rna_RegionView3D_view_matrix_set(PointerRNA *ptr, const float *values) { RegionView3D *rv3d = (RegionView3D *)(ptr->data); - negate_v3_v3(rv3d->ofs, values); - ED_view3d_from_m4((float (*)[4])values, rv3d->ofs, rv3d->viewquat, &rv3d->dist); + float mat[4][4]; + invert_m4_m4(mat, (float (*)[4])values); + ED_view3d_from_m4(mat, rv3d->ofs, rv3d->viewquat, &rv3d->dist); } /* api call */ @@ -1463,6 +1493,7 @@ static void rna_def_backgroundImages(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "Remove all background images"); } + static void rna_def_space_view3d(BlenderRNA *brna) { StructRNA *srna; @@ -1499,6 +1530,27 @@ static void rna_def_space_view3d(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; + static EnumPropertyItem view3d_matcap_items[] = { + {ICON_MATCAP_01, "01", ICON_MATCAP_01, "", ""}, + {ICON_MATCAP_02, "02", ICON_MATCAP_02, "", ""}, + {ICON_MATCAP_03, "03", ICON_MATCAP_03, "", ""}, + {ICON_MATCAP_04, "04", ICON_MATCAP_04, "", ""}, + {ICON_MATCAP_05, "05", ICON_MATCAP_05, "", ""}, + {ICON_MATCAP_06, "06", ICON_MATCAP_06, "", ""}, + {ICON_MATCAP_07, "07", ICON_MATCAP_07, "", ""}, + {ICON_MATCAP_08, "08", ICON_MATCAP_08, "", ""}, + {ICON_MATCAP_09, "09", ICON_MATCAP_09, "", ""}, + {ICON_MATCAP_10, "10", ICON_MATCAP_10, "", ""}, + {ICON_MATCAP_11, "11", ICON_MATCAP_11, "", ""}, + {ICON_MATCAP_12, "12", ICON_MATCAP_12, "", ""}, + {ICON_MATCAP_13, "13", ICON_MATCAP_13, "", ""}, + {ICON_MATCAP_14, "14", ICON_MATCAP_14, "", ""}, + {ICON_MATCAP_15, "15", ICON_MATCAP_15, "", ""}, + {ICON_MATCAP_16, "16", ICON_MATCAP_16, "", ""}, + {0, NULL, 0, NULL, NULL} + }; + + srna = RNA_def_struct(brna, "SpaceView3D", "Space"); RNA_def_struct_sdna(srna, "View3D"); RNA_def_struct_ui_text(srna, "3D View Space", "3D View space data"); @@ -1819,6 +1871,17 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Show 3D Marker Names", "Show names for reconstructed tracks objects"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + prop = RNA_def_property(srna, "use_matcap", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", V3D_SOLID_MATCAP); + RNA_def_property_ui_text(prop, "Matcap", "Active Objects draw images mapped on normals, enhancing Solid Draw Mode"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_SpaceView3D_matcap_enable"); + + prop = RNA_def_property(srna, "matcap_icon", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "matcap_icon"); + RNA_def_property_enum_items(prop, view3d_matcap_items); + RNA_def_property_ui_text(prop, "Matcap", "Image to use for Material Capture, active objects only"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_SpaceView3D_matcap_update"); + /* region */ srna = RNA_def_struct(brna, "RegionView3D", NULL); @@ -2699,6 +2762,11 @@ static void rna_def_space_time(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_DYNAMICPAINT); RNA_def_property_ui_text(prop, "Dynamic Paint", "Show the active object's Dynamic Paint cache"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, NULL); + + prop = RNA_def_property(srna, "cache_rigidbody", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_RIGIDBODY); + RNA_def_property_ui_text(prop, "Rigid Body", "Show the active object's Rigid Body cache"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, NULL); } static void rna_def_console_line(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c index 2ab448c9188..fc67ae27387 100644 --- a/source/blender/makesrna/intern/rna_texture.c +++ b/source/blender/makesrna/intern/rna_texture.c @@ -44,6 +44,8 @@ #include "DNA_particle_types.h" #include "DNA_scene_types.h" /* MAXFRAME only */ +#include "BLI_utildefines.h" + #include "BKE_node.h" #include "WM_api.h" @@ -563,7 +565,7 @@ static void rna_def_colormapping(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Color_mapping_update"); prop = RNA_def_property(srna, "contrast", PROP_FLOAT, PROP_NONE); - RNA_def_property_range(prop, 0.01, 5); + RNA_def_property_range(prop, 0.0, 5); RNA_def_property_ui_text(prop, "Contrast", "Adjust the contrast of the texture"); RNA_def_property_update(prop, 0, "rna_Color_mapping_update"); @@ -1978,7 +1980,7 @@ static void rna_def_texture(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Texture_update"); prop = RNA_def_property(srna, "contrast", PROP_FLOAT, PROP_NONE); - RNA_def_property_range(prop, 0.01, 5); + RNA_def_property_range(prop, 0.0, 5); RNA_def_property_ui_text(prop, "Contrast", "Adjust the contrast of the texture"); RNA_def_property_update(prop, 0, "rna_Texture_update"); diff --git a/source/blender/makesrna/intern/rna_texture_api.c b/source/blender/makesrna/intern/rna_texture_api.c index 5be9d3a0dec..218fda361fa 100644 --- a/source/blender/makesrna/intern/rna_texture_api.c +++ b/source/blender/makesrna/intern/rna_texture_api.c @@ -71,7 +71,7 @@ static void clear_envmap(struct EnvMap *env, bContext *C) static void texture_evaluate(struct Tex *tex, float value[3], float color_r[4]) { TexResult texres = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL}; - multitex_ext(tex, value, NULL, NULL, 1, &texres); + multitex_ext(tex, value, NULL, NULL, 1, &texres, NULL); color_r[0] = texres.tr; color_r[1] = texres.tg; diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c index 00124a82dd1..fad93ea9054 100644 --- a/source/blender/makesrna/intern/rna_ui.c +++ b/source/blender/makesrna/intern/rna_ui.c @@ -813,9 +813,6 @@ static void rna_def_panel(BlenderRNA *brna) "class name is \"OBJECT_PT_hello\", and bl_idname is not set by the " "script, then bl_idname = \"OBJECT_PT_hello\""); - /* panel's label indeed doesn't need PROP_TRANSLATE flag: translation of label happens in runtime - * when drawing panel and having this flag set will make runtime switching of language much more tricky - * because label will be stored translated */ prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "type->label"); RNA_def_property_flag(prop, PROP_REGISTER); @@ -992,9 +989,6 @@ static void rna_def_menu(BlenderRNA *brna) "class name is \"OBJECT_MT_hello\", and bl_idname is not set by the " "script, then bl_idname = \"OBJECT_MT_hello\")"); - /* menu's label indeed doesn't need PROP_TRANSLATE flag: translation of label happens in runtime - * when drawing panel and having this flag set will make runtime switching of language much more tricky - * because label will be stored translated */ prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "type->label"); RNA_def_property_flag(prop, PROP_REGISTER); diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index 366d0dc1fd9..787a5d6487e 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -42,6 +42,17 @@ #include "rna_internal.h" +#define DEF_ICON_BLANK_SKIP +#define DEF_ICON(name) {ICON_##name, (#name), 0, (#name), ""}, +#define DEF_VICO(name) {VICO_##name, (#name), 0, (#name), ""}, +EnumPropertyItem icon_items[] = { +#include "UI_icons.h" + {0, NULL, 0, NULL, NULL} +}; +#undef DEF_ICON_BLANK_SKIP +#undef DEF_ICON +#undef DEF_VICO + #ifdef RNA_RUNTIME static void rna_uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *name, int icon, @@ -181,22 +192,11 @@ static int rna_ui_get_enum_icon(bContext *C, PointerRNA *ptr, const char *propna #else -#define DEF_ICON_BLANK_SKIP -#define DEF_ICON(name) {ICON_##name, (#name), 0, (#name), ""}, -#define DEF_VICO(name) {VICO_##name, (#name), 0, (#name), ""}, -EnumPropertyItem icon_items[] = { -#include "UI_icons.h" - {0, NULL, 0, NULL, NULL} -}; -#undef DEF_ICON_BLANK_SKIP -#undef DEF_ICON -#undef DEF_VICO - static void api_ui_item_common(FunctionRNA *func) { PropertyRNA *prop; - RNA_def_string_translate(func, "text", "", 0, "", "Override automatic text of the item"); + RNA_def_string_py_translate(func, "text", "", 0, "", "Override automatic text of the item"); prop = RNA_def_property(func, "icon", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, icon_items); @@ -466,7 +466,7 @@ void RNA_api_ui_layout(StructRNA *srna) parm = RNA_def_string(func, "type_property", "", 0, "", "Identifier of property in data giving the type of the ID-blocks to use"); RNA_def_property_flag(parm, PROP_REQUIRED); - RNA_def_string_translate(func, "text", "", 0, "", "Custom label to display in UI"); + RNA_def_string_py_translate(func, "text", "", 0, "", "Custom label to display in UI"); func = RNA_def_function(srna, "template_path_builder", "uiTemplatePathBuilder"); parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take property"); @@ -475,7 +475,7 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_property_flag(parm, PROP_REQUIRED); parm = RNA_def_pointer(func, "root", "ID", "", "ID-block from which path is evaluated from"); RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR); - RNA_def_string_translate(func, "text", "", 0, "", "Custom label to display in UI"); + RNA_def_string_py_translate(func, "text", "", 0, "", "Custom label to display in UI"); func = RNA_def_function(srna, "template_modifier", "uiTemplateModifier"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); @@ -512,6 +512,10 @@ void RNA_api_ui_layout(StructRNA *srna) api_ui_item_rna_common(func); RNA_def_boolean(func, "expand", 0, "", "Expand button to show more detail"); + func = RNA_def_function(srna, "template_icon_view", "uiTemplateIconView"); + RNA_def_function_ui_description(func, "Enum. Large widget showing Icon previews"); + api_ui_item_rna_common(func); + func = RNA_def_function(srna, "template_histogram", "uiTemplateHistogram"); RNA_def_function_ui_description(func, "Item. A histogramm widget to analyze imaga data"); api_ui_item_rna_common(func); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index f53b67c0e92..8ebf83532de 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -325,6 +325,11 @@ static void rna_userdef_addon_remove(ReportList *reports, PointerRNA *bext_ptr) return; } + if (bext->prop) { + IDP_FreeProperty(bext->prop); + MEM_freeN(bext->prop); + } + BLI_freelinkN(&U.addons, bext); RNA_POINTER_INVALIDATE(bext_ptr); } @@ -603,22 +608,14 @@ static void rna_def_userdef_theme_ui_style(BlenderRNA *brna) RNA_def_struct_clear_flag(srna, STRUCT_UNDO); RNA_def_struct_ui_text(srna, "Style", "Theme settings for style sets"); - /* (not used yet) */ -#if 0 - prop = RNA_def_property(srna, "panelzoom", PROP_FLOAT, PROP_NONE); - RNA_def_property_range(prop, 0.5, 2.0); - RNA_def_property_ui_text(prop, "Panel Zoom", "Default zoom level for panel areas"); -#endif - /* (not used yet) */ -#if 0 - prop = RNA_def_property(srna, "group_label", PROP_POINTER, PROP_NONE); + prop = RNA_def_property(srna, "panel_title", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); - RNA_def_property_pointer_sdna(prop, NULL, "grouplabel"); + RNA_def_property_pointer_sdna(prop, NULL, "paneltitle"); RNA_def_property_struct_type(prop, "ThemeFontStyle"); - RNA_def_property_ui_text(prop, "Group Label Font", ""); + RNA_def_property_ui_text(prop, "Panel Title Font", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); -#endif + prop = RNA_def_property(srna, "widget_label", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "widgetlabel"); @@ -1893,6 +1890,18 @@ static void rna_def_userdef_theme_space_node(BlenderRNA *brna) RNA_def_property_array(prop, 4); RNA_def_property_ui_text(prop, "Frame Node", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "matte_node", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "syntaxs"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Matte Node", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "distor_node", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "syntaxd"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Distort Node", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); prop = RNA_def_property(srna, "noodle_curving", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "noodle_curving"); @@ -3325,7 +3334,7 @@ static void rna_def_userdef_system(BlenderRNA *brna) prop = RNA_def_property(srna, "dpi", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "dpi"); - RNA_def_property_range(prop, 48, 128); + RNA_def_property_range(prop, 48, 144); RNA_def_property_ui_text(prop, "DPI", "Font size and resolution for display"); RNA_def_property_update(prop, 0, "rna_userdef_dpi_update"); diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index f416d3403ad..0c1c5d8f64a 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -853,8 +853,11 @@ static void rna_Operator_unregister(struct Main *bmain, StructRNA *type) /* update while blender is running */ wm = bmain->wm.first; - if (wm) + if (wm) { WM_operator_stack_clear(wm); + + WM_operator_handlers_clear(wm, ot); + } WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); RNA_struct_free_extension(type, &ot->ext); @@ -1330,9 +1333,6 @@ static void rna_def_operator(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP); RNA_def_struct_name_property(srna, prop); - /* operator's label indeed doesn't need PROP_TRANSLATE flag: translation of label happens in runtime - * when drawing panel and having this flag set will make runtime switching of language much more tricky - * because label will be stored translated */ prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "type->name"); RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */ @@ -1397,9 +1397,6 @@ static void rna_def_macro_operator(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP); RNA_def_struct_name_property(srna, prop); - /* menu's label indeed doesn't need PROP_TRANSLATE flag: translation of label happens in runtime - * when drawing panel and having this flag set will make runtime switching of language much more tricky - * because label will be stored translated */ prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "type->name"); RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */ diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index 33209095164..9f1361b4909 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -28,7 +28,6 @@ set(INC . intern ../blenkernel - ../blenkernel/intern ../blenlib ../blenfont ../blenloader @@ -67,6 +66,10 @@ set(SRC intern/MOD_laplaciansmooth.c intern/MOD_lattice.c intern/MOD_mask.c + intern/MOD_meshcache.c + intern/MOD_meshcache_mdd.c + intern/MOD_meshcache_pc2.c + intern/MOD_meshcache_util.c intern/MOD_meshdeform.c intern/MOD_mirror.c intern/MOD_multires.c @@ -100,6 +103,7 @@ set(SRC MOD_modifiertypes.h intern/MOD_boolean_util.h intern/MOD_fluidsim_util.h + intern/MOD_meshcache_util.h intern/MOD_util.h intern/MOD_weightvg_util.h ) diff --git a/source/blender/modifiers/MOD_modifiertypes.h b/source/blender/modifiers/MOD_modifiertypes.h index 17e903e9ebb..bac75b3f30f 100644 --- a/source/blender/modifiers/MOD_modifiertypes.h +++ b/source/blender/modifiers/MOD_modifiertypes.h @@ -78,6 +78,7 @@ extern ModifierTypeInfo modifierType_Skin; extern ModifierTypeInfo modifierType_LaplacianSmooth; extern ModifierTypeInfo modifierType_Triangulate; extern ModifierTypeInfo modifierType_UVWarp; +extern ModifierTypeInfo modifierType_MeshCache; /* MOD_util.c */ void modifier_type_init(ModifierTypeInfo *types[]); diff --git a/source/blender/modifiers/SConscript b/source/blender/modifiers/SConscript index d3430c6a4d5..679109079c2 100644 --- a/source/blender/modifiers/SConscript +++ b/source/blender/modifiers/SConscript @@ -25,17 +25,30 @@ # # ***** END GPL LICENSE BLOCK ***** -Import ('env') +Import('env') sources = env.Glob('intern/*.c') -incs = '. ./intern' -incs += ' #/intern/guardedalloc #/intern/bsp/extern #/intern/elbeem/extern #/extern/glew/include #/intern/opennl/extern' -incs += ' ../render/extern/include ../blenloader ../bmesh' -incs += ' ../include ../blenlib ../blenfont ../makesdna ../makesrna ../blenkernel ../blenkernel/intern' -incs += ' ../gpu' - -incs += ' ' + env['BF_ZLIB_INC'] +incs = [ + '.', + './intern', + '#/intern/guardedalloc', + '#/intern/bsp/extern', + '#/intern/elbeem/extern', + '#/extern/glew/include', + '#/intern/opennl/extern', + '../render/extern/include', + '../blenloader', + '../bmesh', + '../include', + '../blenlib', + '../blenfont', + '../makesdna', + '../makesrna', + '../blenkernel', + '../gpu', + env['BF_ZLIB_INC'], + ] defs = [] @@ -43,7 +56,7 @@ if env ['WITH_BF_BOOLEAN']: defs.append('WITH_MOD_BOOLEAN') if env['WITH_BF_REMESH']: - incs += ' #/intern/dualcon' + incs.append('#/intern/dualcon') defs.append('WITH_MOD_REMESH') if env['WITH_BF_FLUID']: @@ -53,12 +66,12 @@ if env['WITH_BF_OCEANSIM']: defs.append('WITH_OCEANSIM') if env['WITH_BF_GAMEENGINE']: - incs += ' #/extern/recastnavigation' + incs.append('#/extern/recastnavigation') defs.append('WITH_GAMEENGINE') if env['WITH_BF_INTERNATIONAL']: defs.append('WITH_INTERNATIONAL') -env.BlenderLib ( libname = 'bf_modifiers', sources = sources, - includes = Split(incs), defines=defs, - libtype=['core','player'], priority = [80, 40] ) +env.BlenderLib(libname='bf_modifiers', sources=sources, + includes=incs, defines=defs, + libtype=['core', 'player'], priority=[80, 40]) diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c index 0a48003fc81..04198d9feb9 100644 --- a/source/blender/modifiers/intern/MOD_boolean.c +++ b/source/blender/modifiers/intern/MOD_boolean.c @@ -135,7 +135,13 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, * in some cases the depsgraph fails us - especially for objects * in other scenes when compositing */ if (bmd->object != ob) { - dm = mesh_get_derived_final(md->scene, bmd->object, CD_MASK_MESH); + /* weak! - but we can too easy end up with circular dep crash otherwise */ + if (modifiers_findByType(bmd->object, eModifierType_Boolean) == NULL) { + dm = mesh_get_derived_final(md->scene, bmd->object, CD_MASK_MESH); + } + else { + dm = bmd->object->derivedFinal; + } } else { dm = NULL; diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c index 2105a6efd21..c5a756733f5 100644 --- a/source/blender/modifiers/intern/MOD_build.c +++ b/source/blender/modifiers/intern/MOD_build.c @@ -37,6 +37,7 @@ #include "BLI_utildefines.h" #include "BLI_rand.h" +#include "BLI_math_vector.h" #include "BLI_ghash.h" #include "DNA_scene_types.h" @@ -104,12 +105,19 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob), MVert *mvert_src = dm->getVertArray(dm); - vertMap = MEM_callocN(sizeof(*vertMap) * numVert_src, "build modifier vertMap"); - for (i = 0; i < numVert_src; i++) vertMap[i] = i; - edgeMap = MEM_callocN(sizeof(*edgeMap) * numEdge_src, "build modifier edgeMap"); - for (i = 0; i < numEdge_src; i++) edgeMap[i] = i; - faceMap = MEM_callocN(sizeof(*faceMap) * numPoly_src, "build modifier faceMap"); - for (i = 0; i < numPoly_src; i++) faceMap[i] = i; + vertMap = MEM_mallocN(sizeof(*vertMap) * numVert_src, "build modifier vertMap"); + edgeMap = MEM_mallocN(sizeof(*edgeMap) * numEdge_src, "build modifier edgeMap"); + faceMap = MEM_mallocN(sizeof(*faceMap) * numPoly_src, "build modifier faceMap"); + +#pragma omp parallel sections if (numVert_src + numEdge_src + numPoly_src >= DM_OMP_LIMIT) + { +#pragma omp section + { range_vn_i(vertMap, numVert_src, 0); } +#pragma omp section + { range_vn_i(edgeMap, numEdge_src, 0); } +#pragma omp section + { range_vn_i(faceMap, numPoly_src, 0); } + } frac = (BKE_scene_frame_get(md->scene) - bmd->start) / bmd->length; CLAMP(frac, 0.0f, 1.0f); diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c index b9384e6208e..ab141312932 100644 --- a/source/blender/modifiers/intern/MOD_collision.c +++ b/source/blender/modifiers/intern/MOD_collision.c @@ -137,7 +137,7 @@ static void deformVerts(ModifierData *md, Object *ob, numverts = dm->getNumVerts(dm); - if ((current_time > collmd->time_xnew) || (BKE_ptcache_get_continue_physics())) { + if (current_time > collmd->time_xnew) { unsigned int i; /* check if mesh has changed */ diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c index 266226040a3..62da82a2af1 100644 --- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c +++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c @@ -82,6 +82,7 @@ typedef struct BLaplacianSystem LaplacianSystem; static CustomDataMask required_data_mask(Object *UNUSED(ob), ModifierData *md); static int is_disabled(ModifierData *md, int UNUSED(useRenderParams)); +static float average_area_quad_v3(float *v1, float *v2, float *v3, float *v4); static float compute_volume(float (*vertexCos)[3], MFace *mfaces, int numFaces); static float cotan_weight(float *v1, float *v2, float *v3); static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, int a_numVerts); @@ -93,7 +94,7 @@ static void init_data(ModifierData *md); static void init_laplacian_matrix(LaplacianSystem *sys); static void memset_laplacian_system(LaplacianSystem *sys, int val); static void volume_preservation(LaplacianSystem *sys, float vini, float vend, short flag); -static void validate_solution(LaplacianSystem *sys, short flag); +static void validate_solution(LaplacianSystem *sys, short flag, float lambda, float lambda_border); static void delete_void_pointer(void *data) { @@ -196,10 +197,10 @@ static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, in static void init_data(ModifierData *md) { LaplacianSmoothModifierData *smd = (LaplacianSmoothModifierData *) md; - smd->lambda = 0.00001f; - smd->lambda_border = 0.00005f; + smd->lambda = 0.01f; + smd->lambda_border = 0.01f; smd->repeat = 1; - smd->flag = MOD_LAPLACIANSMOOTH_X | MOD_LAPLACIANSMOOTH_Y | MOD_LAPLACIANSMOOTH_Z | MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME; + smd->flag = MOD_LAPLACIANSMOOTH_X | MOD_LAPLACIANSMOOTH_Y | MOD_LAPLACIANSMOOTH_Z | MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME | MOD_LAPLACIANSMOOTH_NORMALIZED; smd->defgrp_name[0] = '\0'; } @@ -239,6 +240,13 @@ static CustomDataMask required_data_mask(Object *UNUSED(ob), ModifierData *md) return dataMask; } +static float average_area_quad_v3(float *v1, float *v2, float *v3, float *v4) +{ + float areaq = 0.0f; + areaq = area_tri_v3(v1, v2, v3) + area_tri_v3(v1, v2, v4) + area_tri_v3(v1, v3, v4); + return areaq / 2.0f; +} + static float cotan_weight(float *v1, float *v2, float *v3) { float a[3], b[3], c[3], clen; @@ -372,10 +380,17 @@ static void init_laplacian_matrix(LaplacianSystem *sys) if (has_4_vert) sys->zerola[idv4] = 1; } - sys->ring_areas[idv1] += areaf; - sys->ring_areas[idv2] += areaf; - sys->ring_areas[idv3] += areaf; - if (has_4_vert) sys->ring_areas[idv4] += areaf; + if (has_4_vert) { + sys->ring_areas[idv1] += average_area_quad_v3(v1, v2, v3, v4); + sys->ring_areas[idv2] += average_area_quad_v3(v2, v3, v4, v1); + sys->ring_areas[idv3] += average_area_quad_v3(v3, v4, v1, v2); + sys->ring_areas[idv4] += average_area_quad_v3(v4, v1, v2, v3); + } + else { + sys->ring_areas[idv1] += areaf; + sys->ring_areas[idv2] += areaf; + sys->ring_areas[idv3] += areaf; + } if (has_4_vert) { @@ -403,9 +418,9 @@ static void init_laplacian_matrix(LaplacianSystem *sys) } } else { - w1 = cotan_weight(v1, v2, v3); - w2 = cotan_weight(v2, v3, v1); - w3 = cotan_weight(v3, v1, v2); + w1 = cotan_weight(v1, v2, v3) / 2.0f; + w2 = cotan_weight(v2, v3, v1) / 2.0f; + w3 = cotan_weight(v3, v1, v2) / 2.0f; sys->fweights[i][0] = sys->fweights[i][0] + w1; sys->fweights[i][1] = sys->fweights[i][1] + w2; @@ -505,43 +520,26 @@ static void fill_laplacian_matrix(LaplacianSystem *sys) } } -static void validate_solution(LaplacianSystem *sys, short flag) +static void validate_solution(LaplacianSystem * sys, short flag, float lambda, float lambda_border) { - int i, idv1, idv2; - float leni, lene; + int i; + float lam; float vini, vend; - float *vi1, *vi2, ve1[3], ve2[3]; + if (flag & MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME) { vini = compute_volume(sys->vertexCos, sys->mfaces, sys->numFaces); } - for (i = 0; i < sys->numEdges; i++) { - idv1 = sys->medges[i].v1; - idv2 = sys->medges[i].v2; - vi1 = sys->vertexCos[idv1]; - vi2 = sys->vertexCos[idv2]; - ve1[0] = nlGetVariable(0, idv1); - ve1[1] = nlGetVariable(1, idv1); - ve1[2] = nlGetVariable(2, idv1); - ve2[0] = nlGetVariable(0, idv2); - ve2[1] = nlGetVariable(1, idv2); - ve2[2] = nlGetVariable(2, idv2); - leni = len_v3v3(vi1, vi2); - lene = len_v3v3(ve1, ve2); - if (lene > leni * MOD_LAPLACIANSMOOTH_MAX_EDGE_PERCENTAGE || lene < leni * MOD_LAPLACIANSMOOTH_MIN_EDGE_PERCENTAGE) { - sys->zerola[idv1] = 1; - sys->zerola[idv2] = 1; - } - } for (i = 0; i < sys->numVerts; i++) { if (sys->zerola[i] == 0) { + lam = sys->numNeEd[i] == sys->numNeFa[i] ? (lambda >= 0.0f ? 1.0f : -1.0f) : (lambda_border >= 0.0f ? 1.0f : -1.0f); if (flag & MOD_LAPLACIANSMOOTH_X) { - sys->vertexCos[i][0] = nlGetVariable(0, i); + sys->vertexCos[i][0] += lam * (nlGetVariable(0, i) - sys->vertexCos[i][0]); } if (flag & MOD_LAPLACIANSMOOTH_Y) { - sys->vertexCos[i][1] = nlGetVariable(1, i); + sys->vertexCos[i][1] += lam * (nlGetVariable(1, i) - sys->vertexCos[i][1]); } if (flag & MOD_LAPLACIANSMOOTH_Z) { - sys->vertexCos[i][2] = nlGetVariable(2, i); + sys->vertexCos[i][2] += lam * (nlGetVariable(2, i) - sys->vertexCos[i][2]); } } } @@ -578,17 +576,17 @@ static void laplaciansmoothModifier_do( sys->vert_centroid[0] = 0.0f; sys->vert_centroid[1] = 0.0f; sys->vert_centroid[2] = 0.0f; - for (iter = 0; iter < smd->repeat; iter++) { - memset_laplacian_system(sys, 0); - nlNewContext(); - sys->context = nlGetCurrent(); - nlSolverParameteri(NL_NB_VARIABLES, numVerts); - nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE); - nlSolverParameteri(NL_NB_ROWS, numVerts); - nlSolverParameteri(NL_NB_RIGHT_HAND_SIDES, 3); + memset_laplacian_system(sys, 0); + nlNewContext(); + sys->context = nlGetCurrent(); + nlSolverParameteri(NL_NB_VARIABLES, numVerts); + nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE); + nlSolverParameteri(NL_NB_ROWS, numVerts); + nlSolverParameteri(NL_NB_RIGHT_HAND_SIDES, 3); - init_laplacian_matrix(sys); + init_laplacian_matrix(sys); + for (iter = 0; iter < smd->repeat; iter++) { nlBegin(NL_SYSTEM); for (i = 0; i < numVerts; i++) { nlSetVariable(0, i, vertexCos[i][0]); @@ -605,46 +603,64 @@ static void laplaciansmoothModifier_do( nlBegin(NL_MATRIX); dv = dvert; for (i = 0; i < numVerts; i++) { - nlRightHandSideAdd(0, i, vertexCos[i][0]); - nlRightHandSideAdd(1, i, vertexCos[i][1]); - nlRightHandSideAdd(2, i, vertexCos[i][2]); - if (dv) { - wpaint = defvert_find_weight(dv, defgrp_index); - dv++; - } - else { - wpaint = 1.0f; - } - - if (sys->zerola[i] == 0) { - w = sys->vweights[i] * sys->ring_areas[i]; - sys->vweights[i] = (w == 0.0f) ? 0.0f : -smd->lambda * wpaint / (4.0f * w); - w = sys->vlengths[i]; - sys->vlengths[i] = (w == 0.0f) ? 0.0f : -smd->lambda_border * wpaint * 2.0f / w; + nlRightHandSideSet(0, i, vertexCos[i][0]); + nlRightHandSideSet(1, i, vertexCos[i][1]); + nlRightHandSideSet(2, i, vertexCos[i][2]); + if (iter == 0) { + if (dv) { + wpaint = defvert_find_weight(dv, defgrp_index); + dv++; + } + else { + wpaint = 1.0f; + } - if (sys->numNeEd[i] == sys->numNeFa[i]) { - nlMatrixAdd(i, i, 1.0f + smd->lambda * wpaint / (4.0f * sys->ring_areas[i])); + if (sys->zerola[i] == 0) { + if (smd->flag & MOD_LAPLACIANSMOOTH_NORMALIZED) { + w = sys->vweights[i]; + sys->vweights[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda) * wpaint / w; + w = sys->vlengths[i]; + sys->vlengths[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda_border) * wpaint * 2.0f / w; + if (sys->numNeEd[i] == sys->numNeFa[i]) { + nlMatrixAdd(i, i, 1.0f + fabsf(smd->lambda) * wpaint); + } + else { + nlMatrixAdd(i, i, 1.0f + fabsf(smd->lambda_border) * wpaint * 2.0f); + } + } + else { + w = sys->vweights[i] * sys->ring_areas[i]; + sys->vweights[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda) * wpaint / (4.0f * w); + w = sys->vlengths[i]; + sys->vlengths[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda_border) * wpaint * 2.0f / w; + + if (sys->numNeEd[i] == sys->numNeFa[i]) { + nlMatrixAdd(i, i, 1.0f + fabsf(smd->lambda) * wpaint / (4.0f * sys->ring_areas[i])); + } + else { + nlMatrixAdd(i, i, 1.0f + fabsf(smd->lambda_border) * wpaint * 2.0f); + } + } } else { - nlMatrixAdd(i, i, 1.0f + smd->lambda_border * wpaint * 2.0f); + nlMatrixAdd(i, i, 1.0f); } } - else { - nlMatrixAdd(i, i, 1.0f); - } } - fill_laplacian_matrix(sys); + if (iter == 0) { + fill_laplacian_matrix(sys); + } nlEnd(NL_MATRIX); nlEnd(NL_SYSTEM); if (nlSolveAdvanced(NULL, NL_TRUE)) { - validate_solution(sys, smd->flag); + validate_solution(sys, smd->flag, smd->lambda, smd->lambda_border); } - nlDeleteContext(sys->context); - sys->context = NULL; } + nlDeleteContext(sys->context); + sys->context = NULL; delete_laplacian_system(sys); } diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c new file mode 100644 index 00000000000..5e702a4eabc --- /dev/null +++ b/source/blender/modifiers/intern/MOD_meshcache.c @@ -0,0 +1,344 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/modifiers/intern/MOD_meshcache.c + * \ingroup modifiers + */ + +#include <stdio.h> + +#include "DNA_scene_types.h" +#include "DNA_object_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "BLI_utildefines.h" +#include "BLI_string.h" +#include "BLI_path_util.h" +#include "BLI_math.h" + +#include "BKE_DerivedMesh.h" +#include "BKE_scene.h" +#include "BKE_global.h" +#include "BKE_mesh.h" +#include "BKE_main.h" + +#include "MEM_guardedalloc.h" + +#include "MOD_meshcache_util.h" /* utility functions */ + +#include "MOD_modifiertypes.h" + +#include "MOD_util.h" + +static void initData(ModifierData *md) +{ + MeshCacheModifierData *mcmd = (MeshCacheModifierData *)md; + + mcmd->flag = 0; + mcmd->type = MOD_MESHCACHE_TYPE_MDD; + mcmd->interp = MOD_MESHCACHE_INTERP_LINEAR; + mcmd->frame_scale = 1.0f; + + mcmd->factor = 1.0f; + + /* (Y, Z). Blender default */ + mcmd->forward_axis = 1; + mcmd->up_axis = 2; +} + +static void copyData(ModifierData *md, ModifierData *target) +{ + MeshCacheModifierData *mcmd = (MeshCacheModifierData *)md; + MeshCacheModifierData *tmcmd = (MeshCacheModifierData *)target; + + tmcmd->flag = mcmd->flag; + tmcmd->type = mcmd->type; + + tmcmd->time_mode = mcmd->time_mode; + tmcmd->play_mode = mcmd->play_mode; + + tmcmd->forward_axis = mcmd->forward_axis; + tmcmd->up_axis = mcmd->up_axis; + tmcmd->flip_axis = mcmd->flip_axis; + + tmcmd->interp = mcmd->interp; + + tmcmd->frame_start = mcmd->frame_start; + tmcmd->frame_scale = mcmd->frame_scale; + + tmcmd->factor = mcmd->factor; + tmcmd->deform_mode = mcmd->deform_mode; + + tmcmd->eval_frame = mcmd->eval_frame; + tmcmd->eval_time = mcmd->eval_time; + tmcmd->eval_factor = mcmd->eval_factor; + + BLI_strncpy(tmcmd->filepath, mcmd->filepath, sizeof(tmcmd->filepath)); +} + +static int dependsOnTime(ModifierData *md) +{ + MeshCacheModifierData *mcmd = (MeshCacheModifierData *)md; + return (mcmd->play_mode == MOD_MESHCACHE_PLAY_CFEA); +} + +static int isDisabled(ModifierData *md, int UNUSED(useRenderParams)) +{ + MeshCacheModifierData *mcmd = (MeshCacheModifierData *) md; + + /* leave it up to the modifier to check the file is valid on calculation */ + return (mcmd->factor <= 0.0f) || (mcmd->filepath[0] == '\0'); +} + + +static void meshcache_do( + MeshCacheModifierData *mcmd, Object *ob, DerivedMesh *UNUSED(dm), + float (*vertexCos_Real)[3], int numVerts) +{ + const bool use_factor = mcmd->factor < 1.0f; + float (*vertexCos_Store)[3] = (use_factor || (mcmd->deform_mode == MOD_MESHCACHE_DEFORM_INTEGRATE)) ? + MEM_mallocN(sizeof(*vertexCos_Store) * numVerts, __func__) : NULL; + float (*vertexCos)[3] = vertexCos_Store ? vertexCos_Store : vertexCos_Real; + + Scene *scene = mcmd->modifier.scene; + const float fps = FPS; + + char filepath[FILE_MAX]; + const char *err_str = NULL; + bool ok; + + float time; + + + /* -------------------------------------------------------------------- */ + /* Interpret Time (the reading functions also do some of this ) */ + if (mcmd->play_mode == MOD_MESHCACHE_PLAY_CFEA) { + const float cfra = BKE_scene_frame_get(scene); + + switch (mcmd->time_mode) { + case MOD_MESHCACHE_TIME_FRAME: + { + time = cfra; + break; + } + case MOD_MESHCACHE_TIME_SECONDS: + { + time = cfra / fps; + break; + } + case MOD_MESHCACHE_TIME_FACTOR: + default: + { + time = cfra / fps; + break; + } + } + + /* apply offset and scale */ + time = (mcmd->frame_scale * time) - mcmd->frame_start; + } + else { /* if (mcmd->play_mode == MOD_MESHCACHE_PLAY_EVAL) { */ + switch (mcmd->time_mode) { + case MOD_MESHCACHE_TIME_FRAME: + { + time = mcmd->eval_frame; + break; + } + case MOD_MESHCACHE_TIME_SECONDS: + { + time = mcmd->eval_time; + break; + } + case MOD_MESHCACHE_TIME_FACTOR: + default: + { + time = mcmd->eval_factor; + break; + } + } + } + + + /* -------------------------------------------------------------------- */ + /* Read the File (or error out when the file is bad) */ + + /* would be nice if we could avoid doing this _every_ frame */ + BLI_strncpy(filepath, mcmd->filepath, sizeof(filepath)); + BLI_path_abs(filepath, ID_BLEND_PATH(G.main, (ID *)ob)); + + switch (mcmd->type) { + case MOD_MESHCACHE_TYPE_MDD: + ok = MOD_meshcache_read_mdd_times(filepath, vertexCos, numVerts, + mcmd->interp, time, fps, mcmd->time_mode, &err_str); + break; + case MOD_MESHCACHE_TYPE_PC2: + ok = MOD_meshcache_read_pc2_times(filepath, vertexCos, numVerts, + mcmd->interp, time, fps, mcmd->time_mode, &err_str); + break; + default: + ok = false; + break; + } + + + /* -------------------------------------------------------------------- */ + /* tricky shape key integration (slow!) */ + if (mcmd->deform_mode == MOD_MESHCACHE_DEFORM_INTEGRATE) { + Mesh *me = ob->data; + + /* we could support any object type */ + if (UNLIKELY(ob->type != OB_MESH)) { + modifier_setError(&mcmd->modifier, "'Integrate' only valid for Mesh objects"); + } + else if (UNLIKELY(me->totvert != numVerts)) { + modifier_setError(&mcmd->modifier, "'Integrate' original mesh vertex mismatch"); + } + else if (UNLIKELY(me->totpoly == 0)) { + modifier_setError(&mcmd->modifier, "'Integrate' requires faces"); + } + else { + /* the moons align! */ + int i; + + float (*vertexCos_Source)[3] = MEM_mallocN(sizeof(*vertexCos_Source) * numVerts, __func__); + float (*vertexCos_New)[3] = MEM_mallocN(sizeof(*vertexCos_New) * numVerts, __func__); + MVert *mv = me->mvert; + + for (i = 0; i < numVerts; i++, mv++) { + copy_v3_v3(vertexCos_Source[i], mv->co); + } + + BKE_mesh_calc_relative_deform( + me->mpoly, me->totpoly, + me->mloop, me->totvert, + + (const float (*)[3])vertexCos_Source, /* from the original Mesh*/ + (const float (*)[3])vertexCos_Real, /* the input we've been given (shape keys!) */ + + (const float (*)[3])vertexCos, /* the result of this modifier */ + vertexCos_New /* the result of this function */ + ); + + /* write the corrected locations back into the result */ + memcpy(vertexCos, vertexCos_New, sizeof(*vertexCos) * numVerts); + + MEM_freeN(vertexCos_Source); + MEM_freeN(vertexCos_New); + } + } + + + /* -------------------------------------------------------------------- */ + /* Apply the transformation matrix (if needed) */ + if (UNLIKELY(err_str)) { + modifier_setError(&mcmd->modifier, err_str); + } + else if (ok) { + bool use_matrix = false; + float mat[3][3]; + unit_m3(mat); + + if (mat3_from_axis_conversion(mcmd->forward_axis, mcmd->up_axis, 1, 2, mat)) { + use_matrix = true; + } + + if (mcmd->flip_axis) { + float tmat[3][3]; + unit_m3(tmat); + if (mcmd->flip_axis & (1 << 0)) tmat[0][0] = -1.0f; + if (mcmd->flip_axis & (1 << 1)) tmat[1][1] = -1.0f; + if (mcmd->flip_axis & (1 << 2)) tmat[2][2] = -1.0f; + mul_m3_m3m3(mat, tmat, mat); + + use_matrix = true; + } + + if (use_matrix) { + int i; + for (i = 0; i < numVerts; i++) { + mul_m3_v3(mat, vertexCos[i]); + } + } + } + + if (vertexCos_Store) { + if (ok) { + if (use_factor) { + interp_vn_vn(*vertexCos_Real, *vertexCos_Store, mcmd->factor, numVerts * 3); + } + else { + memcpy(vertexCos_Real, vertexCos_Store, sizeof(*vertexCos_Store) * numVerts); + } + } + + MEM_freeN(vertexCos_Store); + } +} + +static void deformVerts(ModifierData *md, Object *ob, + DerivedMesh *derivedData, + float (*vertexCos)[3], + int numVerts, + ModifierApplyFlag UNUSED(flag)) +{ + MeshCacheModifierData *mcmd = (MeshCacheModifierData *)md; + + meshcache_do(mcmd, ob, derivedData, vertexCos, numVerts); +} + +static void deformVertsEM( + ModifierData *md, Object *ob, struct BMEditMesh *UNUSED(editData), + DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) +{ + MeshCacheModifierData *mcmd = (MeshCacheModifierData *)md; + + meshcache_do(mcmd, ob, derivedData, vertexCos, numVerts); +} + + +ModifierTypeInfo modifierType_MeshCache = { + /* name */ "Mesh Cache", + /* structName */ "MeshCacheModifierData", + /* structSize */ sizeof(MeshCacheModifierData), + /* type */ eModifierTypeType_OnlyDeform, + /* flags */ eModifierTypeFlag_AcceptsCVs | + eModifierTypeFlag_SupportsEditmode, + + /* copyData */ copyData, + /* deformVerts */ deformVerts, + /* deformMatrices */ NULL, + /* deformVertsEM */ deformVertsEM, + /* deformMatricesEM */ NULL, + /* applyModifier */ NULL, + /* applyModifierEM */ NULL, + /* initData */ initData, + /* requiredDataMask */ NULL, + /* freeData */ NULL, + /* isDisabled */ isDisabled, + /* updateDepgraph */ NULL, + /* dependsOnTime */ dependsOnTime, + /* dependsOnNormals */ NULL, + /* foreachObjectLink */ NULL, + /* foreachIDLink */ NULL, + /* foreachTexLink */ NULL, +}; diff --git a/source/blender/modifiers/intern/MOD_meshcache_mdd.c b/source/blender/modifiers/intern/MOD_meshcache_mdd.c new file mode 100644 index 00000000000..e001855ba0b --- /dev/null +++ b/source/blender/modifiers/intern/MOD_meshcache_mdd.c @@ -0,0 +1,301 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Campbell Barton, pkowal + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/modifiers/intern/MOD_meshcache_mdd.c + * \ingroup modifiers + */ + +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include "BLO_sys_types.h" +#include "BLI_utildefines.h" +#include "BLI_endian_switch.h" +#include "BLI_fileops.h" +#include "BLI_math.h" + +#include "MOD_meshcache_util.h" /* own include */ + +#include "DNA_modifier_types.h" + +typedef struct MDDHead { + int frame_tot; + int verts_tot; +} MDDHead; /* frames, verts */ + +static bool meshcache_read_mdd_head(FILE *fp, const int verts_tot, + MDDHead *mdd_head, + const char **err_str) +{ + if (!fread(mdd_head, sizeof(*mdd_head), 1, fp)) { + *err_str = "Missing header"; + return false; + } + +#ifdef __LITTLE_ENDIAN__ + BLI_endian_switch_int32_array((int *)mdd_head, 2); +#endif + + if (mdd_head->verts_tot != verts_tot) { + *err_str = "Vertex count mismatch"; + return false; + } + + if (mdd_head->frame_tot <= 0) { + *err_str = "Invalid frame total"; + return false; + } + /* intentionally dont seek back */ + + return true; +} + +/** + * Gets the index frange and factor + */ +static bool meshcache_read_mdd_range(FILE *fp, + const int verts_tot, + const float frame, const char interp, + int r_index_range[2], float *r_factor, + const char **err_str) +{ + MDDHead mdd_head; + + /* first check interpolation and get the vert locations */ + + if (meshcache_read_mdd_head(fp, verts_tot, &mdd_head, err_str) == false) { + return false; + } + + MOD_meshcache_calc_range(frame, interp, mdd_head.frame_tot, r_index_range, r_factor); + + return true; +} + +static bool meshcache_read_mdd_range_from_time(FILE *fp, + const int verts_tot, + const float time, const float UNUSED(fps), + float *r_frame, + const char **err_str) +{ + MDDHead mdd_head; + int i; + float f_time, f_time_prev = FLT_MAX; + float frame; + + if (meshcache_read_mdd_head(fp, verts_tot, &mdd_head, err_str) == false) { + return false; + } + + for (i = 0; i < mdd_head.frame_tot; i++) { + fread(&f_time, sizeof(float), 1, fp); +#ifdef __LITTLE_ENDIAN__ + BLI_endian_switch_float(&f_time); +#endif + if (f_time >= time) { + break; + } + f_time_prev = f_time; + } + + if (i == mdd_head.frame_tot) { + frame = (float)(mdd_head.frame_tot - 1); + } + if (UNLIKELY(f_time_prev == FLT_MAX)) { + frame = 0.0f; + } + else { + const float range = f_time - f_time_prev; + + if (range <= FRAME_SNAP_EPS) { + frame = (float)i; + } + else { + frame = (float)(i - 1) + ((time - f_time_prev) / range); + } + } + + *r_frame = frame; + return true; +} + +bool MOD_meshcache_read_mdd_index(FILE *fp, + float (*vertexCos)[3], const int verts_tot, + const int index, const float factor, + const char **err_str) +{ + MDDHead mdd_head; + + if (meshcache_read_mdd_head(fp, verts_tot, &mdd_head, err_str) == false) { + return false; + } + + if (fseek(fp, mdd_head.frame_tot * sizeof(int), SEEK_CUR) != 0) { + *err_str = "Header seek failed"; + return false; + } + + if (fseek(fp, index * mdd_head.verts_tot * sizeof(float) * 3, SEEK_CUR) != 0) { + *err_str = "Failed to seek frame"; + return false; + } + + if (factor >= 1.0f) { +#if 1 + float *vco = *vertexCos; + unsigned int i; + for (i = mdd_head.verts_tot; i != 0 ; i--, vco += 3) { + fread(vco, sizeof(float) * 3, 1, fp); + +# ifdef __LITTLE_ENDIAN__ + BLI_endian_switch_float(vco + 0); + BLI_endian_switch_float(vco + 1); + BLI_endian_switch_float(vco + 2); +# endif /* __LITTLE_ENDIAN__ */ + } +#else + /* no blending */ + if (!fread(vertexCos, sizeof(float) * 3, mdd_head.verts_tot, f)) { + *err_str = errno ? strerror(errno) : "Failed to read frame"; + return false; + } +# ifdef __LITTLE_ENDIAN__ + BLI_endian_switch_float_array(vertexCos[0], mdd_head.verts_tot * 3); +# endif +#endif + } + else { + const float ifactor = 1.0f - factor; + float *vco = *vertexCos; + unsigned int i; + for (i = mdd_head.verts_tot; i != 0 ; i--, vco += 3) { + float tvec[3]; + fread(tvec, sizeof(float) * 3, 1, fp); + +#ifdef __LITTLE_ENDIAN__ + BLI_endian_switch_float(tvec + 0); + BLI_endian_switch_float(tvec + 1); + BLI_endian_switch_float(tvec + 2); +#endif + + vco[0] = (vco[0] * ifactor) + (tvec[0] * factor); + vco[1] = (vco[1] * ifactor) + (tvec[1] * factor); + vco[2] = (vco[2] * ifactor) + (tvec[2] * factor); + } + } + + return true; +} + +bool MOD_meshcache_read_mdd_frame(FILE *fp, + float (*vertexCos)[3], const int verts_tot, const char interp, + const float frame, + const char **err_str) +{ + int index_range[2]; + float factor; + + if (meshcache_read_mdd_range(fp, verts_tot, frame, interp, + index_range, &factor, /* read into these values */ + err_str) == false) + { + return false; + } + + if (index_range[0] == index_range[1]) { + /* read single */ + if ((fseek(fp, 0, SEEK_SET) == 0) && + MOD_meshcache_read_mdd_index(fp, vertexCos, verts_tot, index_range[0], 1.0f, err_str)) + { + return true; + } + else { + return false; + } + } + else { + /* read both and interpolate */ + if ((fseek(fp, 0, SEEK_SET) == 0) && + MOD_meshcache_read_mdd_index(fp, vertexCos, verts_tot, index_range[0], 1.0f, err_str) && + (fseek(fp, 0, SEEK_SET) == 0) && + MOD_meshcache_read_mdd_index(fp, vertexCos, verts_tot, index_range[1], factor, err_str)) + { + return true; + } + else { + return false; + } + } +} + +bool MOD_meshcache_read_mdd_times(const char *filepath, + float (*vertexCos)[3], const int verts_tot, const char interp, + const float time, const float fps, const char time_mode, + const char **err_str) +{ + float frame; + + FILE *fp = BLI_fopen(filepath, "rb"); + bool ok; + + if (fp == NULL) { + *err_str = errno ? strerror(errno) : "Unknown error opening file"; + return false; + } + + switch (time_mode) { + case MOD_MESHCACHE_TIME_FRAME: + { + frame = time; + break; + } + case MOD_MESHCACHE_TIME_SECONDS: + { + /* we need to find the closest time */ + if (meshcache_read_mdd_range_from_time(fp, verts_tot, time, fps, &frame, err_str) == false) { + fclose(fp); + return false; + } + rewind(fp); + break; + } + case MOD_MESHCACHE_TIME_FACTOR: + default: + { + MDDHead mdd_head; + if (meshcache_read_mdd_head(fp, verts_tot, &mdd_head, err_str) == false) { + fclose(fp); + return false; + } + + frame = CLAMPIS(time, 0.0f, 1.0f) * (float)mdd_head.frame_tot; + rewind(fp); + break; + } + } + + ok = MOD_meshcache_read_mdd_frame(fp, vertexCos, verts_tot, interp, frame, err_str); + + fclose(fp); + return ok; +} diff --git a/source/blender/modifiers/intern/MOD_meshcache_pc2.c b/source/blender/modifiers/intern/MOD_meshcache_pc2.c new file mode 100644 index 00000000000..1ecb347d174 --- /dev/null +++ b/source/blender/modifiers/intern/MOD_meshcache_pc2.c @@ -0,0 +1,277 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/modifiers/intern/MOD_meshcache_pc2.c + * \ingroup modifiers + */ + +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include "BLO_sys_types.h" +#include "BLI_utildefines.h" +#include "BLI_endian_switch.h" +#include "BLI_fileops.h" +#include "BLI_math.h" + +#include "MOD_meshcache_util.h" /* own include */ + +#include "DNA_modifier_types.h" + +typedef struct PC2Head { + char header[12]; /* 'POINTCACHE2\0' */ + int file_version; /* unused - should be 1 */ + int verts_tot; + float start; + float sampling; + int frame_tot; +} PC2Head; /* frames, verts */ + +static bool meshcache_read_pc2_head(FILE *fp, const int verts_tot, + PC2Head *pc2_head, + const char **err_str) +{ + if (!fread(pc2_head, sizeof(*pc2_head), 1, fp)) { + *err_str = "Missing header"; + return false; + } + + if (strcmp(pc2_head->header, "POINTCACHE2") != 0) { + *err_str = "Invalid header"; + return false; + } + +#ifdef __BIG_ENDIAN__ + BLI_endian_switch_int32_array(&pc2_head->huh, (sizeof(*pc2_head) - sizeof(pc2_head->header)) / sizeof(int)); +#endif + + if (pc2_head->verts_tot != verts_tot) { + *err_str = "Vertex count mismatch"; + return false; + } + + if (pc2_head->frame_tot <= 0) { + *err_str = "Invalid frame total"; + return false; + } + /* intentionally dont seek back */ + + return true; +} + + +/** + * Gets the index frange and factor + * + * currently same as for MDD + */ +static bool meshcache_read_pc2_range(FILE *fp, + const int verts_tot, + const float frame, const char interp, + int r_index_range[2], float *r_factor, + const char **err_str) +{ + PC2Head pc2_head; + + /* first check interpolation and get the vert locations */ + + if (meshcache_read_pc2_head(fp, verts_tot, &pc2_head, err_str) == false) { + return false; + } + + MOD_meshcache_calc_range(frame, interp, pc2_head.frame_tot, r_index_range, r_factor); + + return true; +} + +static bool meshcache_read_pc2_range_from_time(FILE *fp, + const int verts_tot, + const float time, const float fps, + float *r_frame, + const char **err_str) +{ + PC2Head pc2_head; + float frame; + + if (meshcache_read_pc2_head(fp, verts_tot, &pc2_head, err_str) == false) { + return false; + } + + frame = ((time / fps) - pc2_head.start) / pc2_head.sampling; + + if (frame >= pc2_head.frame_tot) { + frame = (float)(pc2_head.frame_tot - 1); + } + else if (frame < 0.0f) { + frame = 0.0f; + } + + *r_frame = frame; + return true; +} + +bool MOD_meshcache_read_pc2_index(FILE *fp, + float (*vertexCos)[3], const int verts_tot, + const int index, const float factor, + const char **err_str) +{ + PC2Head pc2_head; + + if (meshcache_read_pc2_head(fp, verts_tot, &pc2_head, err_str) == false) { + return false; + } + + if (fseek(fp, index * pc2_head.verts_tot * sizeof(float) * 3, SEEK_CUR) != 0) { + *err_str = "Failed to seek frame"; + return false; + } + + if (factor >= 1.0f) { + float *vco = *vertexCos; + unsigned int i; + for (i = pc2_head.verts_tot; i != 0 ; i--, vco += 3) { + fread(vco, sizeof(float) * 3, 1, fp); + +# ifdef __BIG_ENDIAN__ + BLI_endian_switch_float(vco + 0); + BLI_endian_switch_float(vco + 1); + BLI_endian_switch_float(vco + 2); +# endif /* __BIG_ENDIAN__ */ + } + } + else { + const float ifactor = 1.0f - factor; + float *vco = *vertexCos; + unsigned int i; + for (i = pc2_head.verts_tot; i != 0 ; i--, vco += 3) { + float tvec[3]; + fread(tvec, sizeof(float) * 3, 1, fp); + +#ifdef __BIG_ENDIAN__ + BLI_endian_switch_float(tvec + 0); + BLI_endian_switch_float(tvec + 1); + BLI_endian_switch_float(tvec + 2); +#endif /* __BIG_ENDIAN__ */ + + vco[0] = (vco[0] * ifactor) + (tvec[0] * factor); + vco[1] = (vco[1] * ifactor) + (tvec[1] * factor); + vco[2] = (vco[2] * ifactor) + (tvec[2] * factor); + } + } + + return true; +} + + +bool MOD_meshcache_read_pc2_frame(FILE *fp, + float (*vertexCos)[3], const int verts_tot, const char interp, + const float frame, + const char **err_str) +{ + int index_range[2]; + float factor; + + if (meshcache_read_pc2_range(fp, verts_tot, frame, interp, + index_range, &factor, /* read into these values */ + err_str) == false) + { + return false; + } + + if (index_range[0] == index_range[1]) { + /* read single */ + if ((fseek(fp, 0, SEEK_SET) == 0) && + MOD_meshcache_read_pc2_index(fp, vertexCos, verts_tot, index_range[0], 1.0f, err_str)) + { + return true; + } + else { + return false; + } + } + else { + /* read both and interpolate */ + if ((fseek(fp, 0, SEEK_SET) == 0) && + MOD_meshcache_read_pc2_index(fp, vertexCos, verts_tot, index_range[0], 1.0f, err_str) && + (fseek(fp, 0, SEEK_SET) == 0) && + MOD_meshcache_read_pc2_index(fp, vertexCos, verts_tot, index_range[1], factor, err_str)) + { + return true; + } + else { + return false; + } + } +} + +bool MOD_meshcache_read_pc2_times(const char *filepath, + float (*vertexCos)[3], const int verts_tot, const char interp, + const float time, const float fps, const char time_mode, + const char **err_str) +{ + float frame; + + FILE *fp = BLI_fopen(filepath, "rb"); + bool ok; + + if (fp == NULL) { + *err_str = errno ? strerror(errno) : "Unknown error opening file"; + return false; + } + + switch (time_mode) { + case MOD_MESHCACHE_TIME_FRAME: + { + frame = time; + break; + } + case MOD_MESHCACHE_TIME_SECONDS: + { + /* we need to find the closest time */ + if (meshcache_read_pc2_range_from_time(fp, verts_tot, time, fps, &frame, err_str) == false) { + fclose(fp); + return false; + } + rewind(fp); + break; + } + case MOD_MESHCACHE_TIME_FACTOR: + default: + { + PC2Head pc2_head; + if (meshcache_read_pc2_head(fp, verts_tot, &pc2_head, err_str) == false) { + fclose(fp); + return false; + } + + frame = CLAMPIS(time, 0.0f, 1.0f) * (float)pc2_head.frame_tot; + rewind(fp); + break; + } + } + + ok = MOD_meshcache_read_pc2_frame(fp, vertexCos, verts_tot, interp, frame, err_str); + + fclose(fp); + return ok; +} diff --git a/source/blender/modifiers/intern/MOD_meshcache_util.c b/source/blender/modifiers/intern/MOD_meshcache_util.c new file mode 100644 index 00000000000..679a79322c3 --- /dev/null +++ b/source/blender/modifiers/intern/MOD_meshcache_util.c @@ -0,0 +1,71 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "BLI_utildefines.h" +#include "BLI_math.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" + +#include "MEM_guardedalloc.h" + +#include "MOD_meshcache_util.h" + +void MOD_meshcache_calc_range(const float frame, const char interp, + const int frame_tot, + int r_index_range[2], float *r_factor) +{ + if (interp == MOD_MESHCACHE_INTERP_NONE) { + r_index_range[0] = r_index_range[1] = max_ii(0, min_ii(frame_tot - 1, (int)(floorf(frame) + 0.5f))); + *r_factor = 1.0f; /* dummy */ + } + else { + const float tframe = floorf(frame); + const float range = frame - tframe; + r_index_range[0] = (int)tframe; + if (range <= FRAME_SNAP_EPS) { + /* we're close enough not to need blending */ + r_index_range[1] = r_index_range[0]; + *r_factor = 1.0f; /* dummy */ + } + else { + /* blend between 2 frames */ + r_index_range[1] = r_index_range[0] + 1; + *r_factor = range; + } + + /* clamp */ + if ((r_index_range[0] >= frame_tot) || + (r_index_range[1] >= frame_tot)) + { + r_index_range[0] = r_index_range[1] = frame_tot - 1; + *r_factor = 1.0f; /* dummy */ + } + else if ((r_index_range[0] < 0) || + (r_index_range[1] < 0)) + { + r_index_range[0] = r_index_range[1] = 0; + *r_factor = 1.0f; /* dummy */ + } + } +} diff --git a/source/blender/modifiers/intern/MOD_meshcache_util.h b/source/blender/modifiers/intern/MOD_meshcache_util.h new file mode 100644 index 00000000000..d7e71518f77 --- /dev/null +++ b/source/blender/modifiers/intern/MOD_meshcache_util.h @@ -0,0 +1,67 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/modifiers/intern/MOD_meshcache_util.h + * \ingroup modifiers + */ + +#ifndef __MOD_MESHCACHE_UTIL_H__ + +struct MPoly; +struct MLoop; + +/* MOD_meshcache_mdd.c */ +bool MOD_meshcache_read_mdd_index(FILE *fp, + float (*vertexCos)[3], const int vertex_tot, + const int index, const float factor, + const char **err_str); +bool MOD_meshcache_read_mdd_frame(FILE *fp, + float (*vertexCos)[3], const int verts_tot, const char interp, + const float frame, + const char **err_str); +bool MOD_meshcache_read_mdd_times(const char *filepath, + float (*vertexCos)[3], const int verts_tot, const char interp, + const float time, const float fps, const char time_mode, + const char **err_str); + +/* MOD_meshcache_pc2.c */ +bool MOD_meshcache_read_pc2_index(FILE *fp, + float (*vertexCos)[3], const int verts_tot, + const int index, const float factor, + const char **err_str); +bool MOD_meshcache_read_pc2_frame(FILE *fp, + float (*vertexCos)[3], const int verts_tot, const char interp, + const float frame, + const char **err_str); +bool MOD_meshcache_read_pc2_times(const char *filepath, + float (*vertexCos)[3], const int verts_tot, const char interp, + const float time, const float fps, const char time_mode, + const char **err_str); + +/* MOD_meshcache_util.c */ +void MOD_meshcache_calc_range(const float frame, const char interp, + const int frame_tot, + int r_index_range[2], float *r_factor); + +#define FRAME_SNAP_EPS 0.0001f + +#endif /* __MOD_MESHCACHE_UTIL_H__ */ diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c index 1021620e04f..e7d62452590 100644 --- a/source/blender/modifiers/intern/MOD_screw.c +++ b/source/blender/modifiers/intern/MOD_screw.c @@ -314,11 +314,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, CustomData_add_layer(&result->polyData, CD_ORIGINDEX, CD_CALLOC, NULL, maxPolys); } -#if 0 // trunk - origindex = result->getPolyDataArray(result, CD_ORIGINDEX); -#else // bmesh origindex = CustomData_get_layer(&result->polyData, CD_ORIGINDEX); -#endif DM_copy_vert_data(dm, result, 0, 0, totvert); /* copy first otherwise this overwrites our own vertex normals */ diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index a73d52a0a63..81c53185825 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -1278,7 +1278,8 @@ static void skin_fix_hole_no_good_verts(BMesh *bm, Frame *frame, BMFace *split_f return; /* Get split face's verts */ - BM_iter_as_array(bm, BM_VERTS_OF_FACE, split_face, (void **)verts, 4); + // BM_iter_as_array(bm, BM_VERTS_OF_FACE, split_face, (void **)verts, 4); + BM_face_as_array_vert_quad(split_face, verts); skin_choose_quad_bridge_order(verts, frame->verts, best_order); /* Delete split face and merge */ @@ -1314,16 +1315,21 @@ static void skin_hole_detach_partially_attached_frame(BMesh *bm, Frame *frame) } -static void quad_from_tris(BMesh *bm, BMEdge *e, BMFace *adj[2], BMVert *ndx[4]) +static void quad_from_tris(BMEdge *e, BMFace *adj[2], BMVert *ndx[4]) { BMVert *tri[2][3]; BMVert *opp = NULL; int i, j; BLI_assert(adj[0]->len == 3 && adj[1]->len == 3); - + +#if 0 BM_iter_as_array(bm, BM_VERTS_OF_FACE, adj[0], (void **)tri[0], 3); BM_iter_as_array(bm, BM_VERTS_OF_FACE, adj[1], (void **)tri[1], 3); +#else + BM_face_as_array_vert_tri(adj[0], tri[0]); + BM_face_as_array_vert_tri(adj[1], tri[1]); +#endif /* Find what the second tri has that the first doesn't */ for (i = 0; i < 3; i++) { @@ -1354,7 +1360,7 @@ static void add_quad_from_tris(SkinOutput *so, BMEdge *e, BMFace *adj[2]) { BMVert *quad[4]; - quad_from_tris(so->bm, e, adj, quad); + quad_from_tris(e, adj, quad); add_poly(so, quad[0], quad[1], quad[2], quad[3]); } @@ -1381,7 +1387,7 @@ static void hull_merge_triangles(SkinOutput *so, const SkinModifierData *smd) /* Construct quad using the two triangles adjacent to * the edge */ - quad_from_tris(so->bm, e, adj, quad); + quad_from_tris(e, adj, quad); /* Calculate a score for the quad, higher score for * triangles being closer to coplanar */ diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c index e97f4191e6f..c0d46b14aa8 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.c +++ b/source/blender/modifiers/intern/MOD_subsurf.c @@ -47,7 +47,7 @@ #include "MOD_modifiertypes.h" -#include "CCGSubSurf.h" +#include "intern/CCGSubSurf.h" static void initData(ModifierData *md) { @@ -103,7 +103,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, subsurf_flags |= SUBSURF_USE_RENDER_PARAMS; if (isFinalCalc) subsurf_flags |= SUBSURF_IS_FINAL_CALC; - if (ob->flag & OB_MODE_EDIT) + if (ob->mode & OB_MODE_EDIT) subsurf_flags |= SUBSURF_IN_EDIT_MODE; result = subsurf_make_derived_from_derived(derivedData, smd, NULL, subsurf_flags); diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c index 6c2f68891af..1084023fcf0 100644 --- a/source/blender/modifiers/intern/MOD_util.c +++ b/source/blender/modifiers/intern/MOD_util.c @@ -74,7 +74,7 @@ void get_texture_value(Tex *texture, float *tex_co, TexResult *texres) int result_type; /* no node textures for now */ - result_type = multitex_ext_safe(texture, tex_co, texres); + result_type = multitex_ext_safe(texture, tex_co, texres, NULL); /* if the texture gave an RGB value, we assume it didn't give a valid * intensity, since this is in the context of modifiers don't use perceptual color conversion. @@ -280,5 +280,6 @@ void modifier_type_init(ModifierTypeInfo *types[]) INIT_TYPE(LaplacianSmooth); INIT_TYPE(Triangulate); INIT_TYPE(UVWarp); + INIT_TYPE(MeshCache); #undef INIT_TYPE } diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index a7b491cf42b..12842085189 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -123,6 +123,7 @@ set(SRC composite/nodes/node_composite_pixelate.c composite/node_composite_tree.c + composite/node_composite_util.h shader/nodes/node_shader_camera.c shader/nodes/node_shader_common.c @@ -235,13 +236,6 @@ set(SRC intern/node_common.h ) -if(WITH_COMPOSITOR_LEGACY) - list(APPEND SRC - composite/node_composite_util.h - composite/node_composite_util.c - ) -endif() - if(WITH_PYTHON) list(APPEND INC ../python @@ -267,8 +261,4 @@ if(WITH_COMPOSITOR) add_definitions(-DWITH_COMPOSITOR) endif() -if(WITH_COMPOSITOR_LEGACY) - add_definitions(-DWITH_COMPOSITOR_LEGACY) -endif() - blender_add_lib(bf_nodes "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/nodes/SConscript b/source/blender/nodes/SConscript index cc735902934..9f56689bf43 100644 --- a/source/blender/nodes/SConscript +++ b/source/blender/nodes/SConscript @@ -66,9 +66,6 @@ if env['WITH_BF_COMPOSITOR']: incs += ' ../compositor ' defs.append("WITH_COMPOSITOR") -if env['WITH_BF_COMPOSITOR_LEGACY']: - defs.append("WITH_COMPOSITOR_LEGACY") - env.BlenderLib ( libname = 'bf_nodes', sources = sources, includes = Split(incs), defines = defs, libtype=['core','player'], priority = [190,105] ) env.BlenderLib ( libname = 'bf_cmpnodes', sources = cmpsources, includes = Split(incs), defines = defs, libtype=['core','player'], priority = [175,101] ) env.BlenderLib ( libname = 'bf_shdnodes', sources = shdsources, includes = Split(incs), defines = defs, libtype=['core','player'], priority = [175,101] ) diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c index 03462738d58..a6592b47e87 100644 --- a/source/blender/nodes/composite/node_composite_tree.c +++ b/source/blender/nodes/composite/node_composite_tree.c @@ -51,7 +51,6 @@ #include "BKE_tracking.h" #include "node_common.h" -#include "node_exec.h" #include "node_util.h" #include "PIL_time.h" @@ -95,9 +94,6 @@ static void free_node_cache(bNodeTree *UNUSED(ntree), bNode *node) for (sock= node->outputs.first; sock; sock= sock->next) { if (sock->cache) { -#ifdef WITH_COMPOSITOR_LEGACY - free_compbuf(sock->cache); -#endif sock->cache= NULL; } } @@ -161,9 +157,6 @@ static void localize(bNodeTree *localtree, bNodeTree *ntree) for (sock= node->outputs.first; sock; sock= sock->next) { sock->new_sock->cache= sock->cache; -#ifdef WITH_COMPOSITOR_LEGACY - compbuf_set_node(sock->new_sock->cache, node->new_node); -#endif sock->cache= NULL; sock->new_sock->new_sock= sock; } @@ -239,9 +232,6 @@ static void local_merge(bNodeTree *localtree, bNodeTree *ntree) for (lsock= lnode->outputs.first; lsock; lsock= lsock->next) { if (ntreeOutputExists(lnode->new_node, lsock->new_sock)) { lsock->new_sock->cache= lsock->cache; -#ifdef WITH_COMPOSITOR_LEGACY - compbuf_set_node(lsock->new_sock->cache, lnode->new_node); -#endif lsock->cache= NULL; lsock->new_sock= NULL; } @@ -277,421 +267,6 @@ bNodeTreeType ntreeType_Composite = { }; -/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes. - * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees. - */ -struct bNodeTreeExec *ntreeCompositBeginExecTree(bNodeTree *ntree, int use_tree_data) -{ - bNodeTreeExec *exec; - bNode *node; - bNodeSocket *sock; - - if (use_tree_data) { - /* XXX hack: prevent exec data from being generated twice. - * this should be handled by the renderer! - */ - if (ntree->execdata) - return ntree->execdata; - } - - /* ensures only a single output node is enabled */ - ntreeSetOutput(ntree); - - exec = ntree_exec_begin(ntree); - - for (node= exec->nodetree->nodes.first; node; node= node->next) { - /* initialize needed for groups */ - node->exec= 0; - - for (sock= node->outputs.first; sock; sock= sock->next) { - bNodeStack *ns= node_get_socket_stack(exec->stack, sock); - if (ns && sock->cache) { - ns->data= sock->cache; - sock->cache= NULL; - } - } - /* cannot initialize them while using in threads */ - if (ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT)) { - curvemapping_initialize(node->storage); - if (node->type==CMP_NODE_CURVE_RGB) - curvemapping_premultiply(node->storage, 0); - } - } - - if (use_tree_data) { - /* XXX this should not be necessary, but is still used for cmp/sha/tex nodes, - * which only store the ntree pointer. Should be fixed at some point! - */ - ntree->execdata = exec; - } - - return exec; -} - -/* XXX Group nodes must set use_tree_data to false, since their trees can be shared by multiple nodes. - * If use_tree_data is true, the ntree->execdata pointer is checked to avoid multiple execution of top-level trees. - */ -void ntreeCompositEndExecTree(bNodeTreeExec *exec, int use_tree_data) -{ - if (exec) { - bNodeTree *ntree= exec->nodetree; - bNode *node; - bNodeStack *ns; - - for (node= exec->nodetree->nodes.first; node; node= node->next) { - bNodeSocket *sock; - - for (sock= node->outputs.first; sock; sock= sock->next) { - ns = node_get_socket_stack(exec->stack, sock); - if (ns && ns->data) { - sock->cache= ns->data; - ns->data= NULL; - } - } - if (node->type==CMP_NODE_CURVE_RGB) - curvemapping_premultiply(node->storage, 1); - - node->need_exec= 0; - } - - ntree_exec_end(exec); - - if (use_tree_data) { - /* XXX clear nodetree backpointer to exec data, same problem as noted in ntreeBeginExecTree */ - ntree->execdata = NULL; - } - } -} - -#ifdef WITH_COMPOSITOR -#ifdef WITH_COMPOSITOR_LEGACY - -/* ***************************** threaded version for execute composite nodes ************* */ -/* these are nodes without input, only giving values */ -/* or nodes with only value inputs */ -static int node_only_value(bNode *node) -{ - bNodeSocket *sock; - - if (ELEM3(node->type, CMP_NODE_TIME, CMP_NODE_VALUE, CMP_NODE_RGB)) - return 1; - - /* doing this for all node types goes wrong. memory free errors */ - if (node->inputs.first && node->type==CMP_NODE_MAP_VALUE) { - int retval= 1; - for (sock= node->inputs.first; sock; sock= sock->next) { - if (sock->link) - retval &= node_only_value(sock->link->fromnode); - } - return retval; - } - return 0; -} - -/* not changing info, for thread callback */ -typedef struct ThreadData { - bNodeStack *stack; - RenderData *rd; -} ThreadData; - -static void *exec_composite_node(void *nodeexec_v) -{ - bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */ - bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */ - bNodeExec *nodeexec= nodeexec_v; - bNode *node= nodeexec->node; - ThreadData *thd= (ThreadData *)node->threaddata; - - node_get_stack(node, thd->stack, nsin, nsout); - - if (node->typeinfo->execfunc) - node->typeinfo->execfunc(thd->rd, node, nsin, nsout); - else if (node->typeinfo->newexecfunc) - node->typeinfo->newexecfunc(thd->rd, 0, node, nodeexec->data, nsin, nsout); - - node->exec |= NODE_READY; - return NULL; -} - -/* return total of executable nodes, for timecursor */ -static int setExecutableNodes(bNodeTreeExec *exec, ThreadData *thd) -{ - bNodeTree *ntree = exec->nodetree; - bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */ - bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */ - bNodeExec *nodeexec; - bNode *node; - bNodeSocket *sock; - int n, totnode= 0, group_edit= 0; - - /* if we are in group edit, viewer nodes get skipped when group has viewer */ - for (node= ntree->nodes.first; node; node= node->next) - if (node->type==NODE_GROUP && (node->flag & NODE_GROUP_EDIT)) - if (ntreeHasType((bNodeTree *)node->id, CMP_NODE_VIEWER)) - group_edit= 1; - - /* NB: using the exec data list here to have valid dependency sort */ - for (n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) { - int a; - node = nodeexec->node; - - node_get_stack(node, exec->stack, nsin, nsout); - - /* test the outputs */ - /* skip value-only nodes (should be in type!) */ - if (!node_only_value(node)) { - for (a=0, sock= node->outputs.first; sock; sock= sock->next, a++) { - if (nsout[a]->data==NULL && nsout[a]->hasoutput) { - node->need_exec= 1; - break; - } - } - } - - /* test the inputs */ - for (a=0, sock= node->inputs.first; sock; sock= sock->next, a++) { - /* skip viewer nodes in bg render or group edit */ - if ( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER) && (G.background || group_edit)) - node->need_exec= 0; - /* is sock in use? */ - else if (sock->link) { - bNodeLink *link= sock->link; - - /* this is the test for a cyclic case */ - if (link->fromnode==NULL || link->tonode==NULL); - else if (link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF) { - if (link->fromnode->need_exec) { - node->need_exec= 1; - break; - } - } - else { - node->need_exec= 0; - printf("Node %s skipped, cyclic dependency\n", node->name); - } - } - } - - if (node->need_exec) { - - /* free output buffers */ - for (a=0, sock= node->outputs.first; sock; sock= sock->next, a++) { - if (nsout[a]->data) { - free_compbuf(nsout[a]->data); - nsout[a]->data= NULL; - } - } - totnode++; - /* printf("node needs exec %s\n", node->name); */ - - /* tag for getExecutableNode() */ - node->exec= 0; - } - else { - /* tag for getExecutableNode() */ - node->exec= NODE_READY|NODE_FINISHED|NODE_SKIPPED; - - } - } - - /* last step: set the stack values for only-value nodes */ - /* just does all now, compared to a full buffer exec this is nothing */ - if (totnode) { - for (n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) { - node = nodeexec->node; - if (node->need_exec==0 && node_only_value(node)) { - if (node->typeinfo->execfunc) { - node_get_stack(node, exec->stack, nsin, nsout); - node->typeinfo->execfunc(thd->rd, node, nsin, nsout); - } - } - } - } - - return totnode; -} - -/* while executing tree, free buffers from nodes that are not needed anymore */ -static void freeExecutableNode(bNodeTreeExec *exec) -{ - /* node outputs can be freed when: - * - not a render result or image node - * - when node outputs go to nodes all being set NODE_FINISHED - */ - bNodeTree *ntree = exec->nodetree; - bNodeExec *nodeexec; - bNode *node; - bNodeSocket *sock; - int n; - - /* set exec flag for finished nodes that might need freed */ - for (node= ntree->nodes.first; node; node= node->next) { - if (node->type!=CMP_NODE_R_LAYERS) - if (node->exec & NODE_FINISHED) - node->exec |= NODE_FREEBUFS; - } - /* clear this flag for input links that are not done yet. - * Using the exec data for valid dependency sort. - */ - for (n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) { - node = nodeexec->node; - if ((node->exec & NODE_FINISHED)==0) { - for (sock= node->inputs.first; sock; sock= sock->next) - if (sock->link) - sock->link->fromnode->exec &= ~NODE_FREEBUFS; - } - } - /* now we can free buffers */ - for (node= ntree->nodes.first; node; node= node->next) { - if (node->exec & NODE_FREEBUFS) { - for (sock= node->outputs.first; sock; sock= sock->next) { - bNodeStack *ns= node_get_socket_stack(exec->stack, sock); - if (ns && ns->data) { - free_compbuf(ns->data); - ns->data= NULL; - // printf("freed buf node %s\n", node->name); - } - } - } - } -} - -static bNodeExec *getExecutableNode(bNodeTreeExec *exec) -{ - bNodeExec *nodeexec; - bNodeSocket *sock; - int n; - - for (n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) { - if (nodeexec->node->exec==0) { - /* input sockets should be ready */ - for (sock= nodeexec->node->inputs.first; sock; sock= sock->next) { - if (sock->link && sock->link->fromnode) - if ((sock->link->fromnode->exec & NODE_READY)==0) - break; - } - if (sock==NULL) - return nodeexec; - } - } - return NULL; -} - -/* check if texture nodes need exec or end */ -static void ntree_composite_texnode(bNodeTree *ntree, int init) -{ - bNode *node; - - for (node= ntree->nodes.first; node; node= node->next) { - if (node->type==CMP_NODE_TEXTURE && node->id) { - Tex *tex= (Tex *)node->id; - if (tex->nodetree && tex->use_nodes) { - /* has internal flag to detect it only does it once */ - if (init) { - if (!tex->nodetree->execdata) - tex->nodetree->execdata = ntreeTexBeginExecTree(tex->nodetree, 1); - } - else - ntreeTexEndExecTree(tex->nodetree->execdata, 1); - tex->nodetree->execdata = NULL; - } - } - } - -} - -/* optimized tree execute test for compositing */ -static void ntreeCompositExecTreeOld(bNodeTree *ntree, RenderData *rd, int do_preview) -{ - bNodeExec *nodeexec; - bNode *node; - ListBase threads; - ThreadData thdata; - int totnode, curnode, rendering = TRUE, n; - bNodeTreeExec *exec = ntree->execdata; - - if (do_preview) - ntreeInitPreview(ntree, 0, 0); - - if (!ntree->execdata) { - /* XXX this is the top-level tree, so we use the ntree->execdata pointer. */ - exec = ntreeCompositBeginExecTree(ntree, 1); - } - ntree_composite_texnode(ntree, 1); - - /* prevent unlucky accidents */ - if (G.background) - rd->scemode &= ~R_COMP_CROP; - - /* setup callerdata for thread callback */ - thdata.rd= rd; - thdata.stack= exec->stack; - - /* fixed seed, for example noise texture */ - BLI_srandom(rd->cfra); - - /* sets need_exec tags in nodes */ - curnode = totnode= setExecutableNodes(exec, &thdata); - - BLI_init_threads(&threads, exec_composite_node, rd->threads); - - while (rendering) { - - if (BLI_available_threads(&threads)) { - nodeexec= getExecutableNode(exec); - if (nodeexec) { - node = nodeexec->node; - if (ntree->progress && totnode) - ntree->progress(ntree->prh, (1.0f - curnode/(float)totnode)); - if (ntree->stats_draw) { - char str[128]; - BLI_snprintf(str, sizeof(str), "Compositing %d %s", curnode, node->name); - ntree->stats_draw(ntree->sdh, str); - } - curnode--; - - node->threaddata = &thdata; - node->exec= NODE_PROCESSING; - BLI_insert_thread(&threads, nodeexec); - } - else - PIL_sleep_ms(50); - } - else - PIL_sleep_ms(50); - - rendering= 0; - /* test for ESC */ - if (ntree->test_break && ntree->test_break(ntree->tbh)) { - for (node= ntree->nodes.first; node; node= node->next) - node->exec |= NODE_READY; - } - - /* check for ready ones, and if we need to continue */ - for (n=0, nodeexec=exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) { - node = nodeexec->node; - if (node->exec & NODE_READY) { - if ((node->exec & NODE_FINISHED)==0) { - BLI_remove_thread(&threads, nodeexec); /* this waits for running thread to finish btw */ - node->exec |= NODE_FINISHED; - - /* freeing unused buffers */ - if (rd->scemode & R_COMP_FREE) - freeExecutableNode(exec); - } - } - else rendering= 1; - } - } - - BLI_end_threads(&threads); - - /* XXX top-level tree uses the ntree->execdata pointer */ - ntreeCompositEndExecTree(exec, 1); -} -#endif /* WITH_COMPOSITOR_LEGACY */ -#endif /* WITH_COMPOSITOR */ - void *COM_linker_hack = NULL; void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int rendering, int do_preview, @@ -699,16 +274,7 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int rendering, int const ColorManagedDisplaySettings *display_settings) { #ifdef WITH_COMPOSITOR -#ifdef WITH_COMPOSITOR_LEGACY - if (G.debug_value == 200) - { - ntreeCompositExecTreeOld(ntree, rd, do_preview); - } - else -#endif - { - COM_execute(rd, ntree, rendering, view_settings, display_settings); - } + COM_execute(rd, ntree, rendering, view_settings, display_settings); #else (void)ntree, (void)rd, (void)rendering, (void)do_preview; (void)view_settings, (void)display_settings; diff --git a/source/blender/nodes/composite/node_composite_util.c b/source/blender/nodes/composite/node_composite_util.c deleted file mode 100644 index c4b48b83b16..00000000000 --- a/source/blender/nodes/composite/node_composite_util.c +++ /dev/null @@ -1,1412 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2006 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/nodes/composite/node_composite_util.c - * \ingroup nodes - */ - -#include "node_composite_util.h" - -#ifdef WITH_COMPOSITOR_LEGACY - -#include <limits.h> - -CompBuf *alloc_compbuf(int sizex, int sizey, int type, int alloc) -{ - CompBuf *cbuf= MEM_callocN(sizeof(CompBuf), "compbuf"); - - cbuf->x= sizex; - cbuf->y= sizey; - cbuf->xrad= sizex/2; - cbuf->yrad= sizey/2; - - cbuf->type= type; - if (alloc) { - if (cbuf->type==CB_RGBA) - cbuf->rect= MEM_mapallocN(4*sizeof(float)*sizex*sizey, "compbuf RGBA rect"); - else if (cbuf->type==CB_VEC3) - cbuf->rect= MEM_mapallocN(3*sizeof(float)*sizex*sizey, "compbuf Vector3 rect"); - else if (cbuf->type==CB_VEC2) - cbuf->rect= MEM_mapallocN(2*sizeof(float)*sizex*sizey, "compbuf Vector2 rect"); - else - cbuf->rect= MEM_mapallocN(sizeof(float)*sizex*sizey, "compbuf Fac rect"); - cbuf->malloc= 1; - } - cbuf->disprect.xmin = 0; - cbuf->disprect.ymin = 0; - cbuf->disprect.xmax = sizex; - cbuf->disprect.ymax = sizey; - - return cbuf; -} - -CompBuf *dupalloc_compbuf(CompBuf *cbuf) -{ - CompBuf *dupbuf= alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 1); - if (dupbuf) { - memcpy(dupbuf->rect, cbuf->rect, cbuf->type*sizeof(float)*cbuf->x*cbuf->y); - - dupbuf->xof= cbuf->xof; - dupbuf->yof= cbuf->yof; - } - return dupbuf; -} - -/* instead of reference counting, we create a list */ -CompBuf *pass_on_compbuf(CompBuf *cbuf) -{ - CompBuf *dupbuf= (cbuf)? alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 0): NULL; - CompBuf *lastbuf; - - if (dupbuf) { - dupbuf->rect= cbuf->rect; - dupbuf->xof= cbuf->xof; - dupbuf->yof= cbuf->yof; - dupbuf->malloc= 0; - - /* get last buffer in list, and append dupbuf */ - for (lastbuf= cbuf; lastbuf; lastbuf= lastbuf->next) - if (lastbuf->next==NULL) - break; - lastbuf->next= dupbuf; - dupbuf->prev= lastbuf; - } - return dupbuf; -} - - -void free_compbuf(CompBuf *cbuf) -{ - /* check referencing, then remove from list and set malloc tag */ - if (cbuf->prev || cbuf->next) { - if (cbuf->prev) - cbuf->prev->next= cbuf->next; - if (cbuf->next) - cbuf->next->prev= cbuf->prev; - if (cbuf->malloc) { - if (cbuf->prev) - cbuf->prev->malloc= 1; - else - cbuf->next->malloc= 1; - cbuf->malloc= 0; - } - } - - if (cbuf->malloc && cbuf->rect) - MEM_freeN(cbuf->rect); - - MEM_freeN(cbuf); -} - -void print_compbuf(char *str, CompBuf *cbuf) -{ - printf("Compbuf %s %d %d %p\n", str, cbuf->x, cbuf->y, (void *)cbuf->rect); - -} - -void compbuf_set_node(CompBuf *cbuf, bNode *node) -{ - if (cbuf) cbuf->node = node; -} - - -CompBuf *get_cropped_compbuf(rcti *drect, float *rectf, int rectx, int recty, int type) -{ - CompBuf *cbuf; - rcti disprect= *drect; - float *outfp; - int dx, y; - - if (disprect.xmax>rectx) disprect.xmax = rectx; - if (disprect.ymax>recty) disprect.ymax = recty; - if (disprect.xmin>= disprect.xmax) return NULL; - if (disprect.ymin>= disprect.ymax) return NULL; - - cbuf= alloc_compbuf(BLI_rcti_size_x(&disprect), BLI_rcti_size_y(&disprect), type, 1); - outfp= cbuf->rect; - rectf += type*(disprect.ymin*rectx + disprect.xmin); - dx= type*cbuf->x; - for (y=cbuf->y; y>0; y--, outfp+=dx, rectf+=type*rectx) - memcpy(outfp, rectf, sizeof(float)*dx); - - return cbuf; -} - -CompBuf *scalefast_compbuf(CompBuf *inbuf, int newx, int newy) -{ - CompBuf *outbuf; - float *rectf, *newrectf, *rf; - int x, y, c, pixsize= inbuf->type; - int ofsx, ofsy, stepx, stepy; - - if (inbuf->x==newx && inbuf->y==newy) - return dupalloc_compbuf(inbuf); - - outbuf= alloc_compbuf(newx, newy, inbuf->type, 1); - newrectf= outbuf->rect; - - stepx = (65536.0 * (inbuf->x - 1.0) / (newx - 1.0)) + 0.5; - stepy = (65536.0 * (inbuf->y - 1.0) / (newy - 1.0)) + 0.5; - ofsy = 32768; - - for (y = newy; y > 0 ; y--) { - rectf = inbuf->rect; - rectf += pixsize * (ofsy >> 16) * inbuf->x; - - ofsy += stepy; - ofsx = 32768; - - for (x = newx ; x>0 ; x--) { - - rf= rectf + pixsize*(ofsx >> 16); - for (c=0; c<pixsize; c++) - newrectf[c] = rf[c]; - - newrectf+= pixsize; - - ofsx += stepx; - } - } - - return outbuf; -} - -void typecheck_compbuf_color(float *out, float *in, int outtype, int intype) -{ - if (intype == outtype) { - memcpy(out, in, sizeof(float)*outtype); - } - else if (outtype==CB_VAL) { - if (intype==CB_VEC2) { - *out= 0.5f*(in[0]+in[1]); - } - else if (intype==CB_VEC3) { - *out= 0.333333f*(in[0]+in[1]+in[2]); - } - else if (intype==CB_RGBA) { - *out = rgb_to_bw(in); - } - } - else if (outtype==CB_VEC2) { - if (intype==CB_VAL) { - out[0] = in[0]; - out[1] = in[0]; - } - else if (intype==CB_VEC3) { - out[0] = in[0]; - out[1] = in[1]; - } - else if (intype==CB_RGBA) { - out[0] = in[0]; - out[1] = in[1]; - } - } - else if (outtype==CB_VEC3) { - if (intype==CB_VAL) { - out[0] = in[0]; - out[1] = in[0]; - out[2] = in[0]; - } - else if (intype==CB_VEC2) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = 0.0f; - } - else if (intype==CB_RGBA) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - } - } - else if (outtype==CB_RGBA) { - if (intype==CB_VAL) { - out[0] = in[0]; - out[1] = in[0]; - out[2] = in[0]; - out[3] = 1.0f; - } - else if (intype==CB_VEC2) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = 0.0f; - out[3] = 1.0f; - } - else if (intype==CB_VEC3) { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = 1.0f; - } - } -} - -CompBuf *typecheck_compbuf(CompBuf *inbuf, int type) -{ - if (inbuf && inbuf->type!=type) { - CompBuf *outbuf; - float *inrf, *outrf; - int x; - - outbuf= alloc_compbuf(inbuf->x, inbuf->y, type, 1); - - /* warning note: xof and yof are applied in pixelprocessor, but should be copied otherwise? */ - outbuf->xof= inbuf->xof; - outbuf->yof= inbuf->yof; - - if (inbuf->rect_procedural) { - outbuf->rect_procedural= inbuf->rect_procedural; - copy_v3_v3(outbuf->procedural_size, inbuf->procedural_size); - copy_v3_v3(outbuf->procedural_offset, inbuf->procedural_offset); - outbuf->procedural_type= inbuf->procedural_type; - outbuf->node= inbuf->node; - return outbuf; - } - - inrf= inbuf->rect; - outrf= outbuf->rect; - x= inbuf->x*inbuf->y; - - if (type==CB_VAL) { - if (inbuf->type==CB_VEC2) { - for (; x>0; x--, outrf+= 1, inrf+= 2) - *outrf= 0.5f*(inrf[0]+inrf[1]); - } - else if (inbuf->type==CB_VEC3) { - for (; x>0; x--, outrf+= 1, inrf+= 3) - *outrf= 0.333333f*(inrf[0]+inrf[1]+inrf[2]); - } - else if (inbuf->type==CB_RGBA) { - for (; x>0; x--, outrf+= 1, inrf+= 4) - *outrf = rgb_to_bw(inrf); - } - } - else if (type==CB_VEC2) { - if (inbuf->type==CB_VAL) { - for (; x>0; x--, outrf+= 2, inrf+= 1) { - outrf[0] = inrf[0]; - outrf[1] = inrf[0]; - } - } - else if (inbuf->type==CB_VEC3) { - for (; x>0; x--, outrf+= 2, inrf+= 3) { - outrf[0] = inrf[0]; - outrf[1] = inrf[1]; - } - } - else if (inbuf->type==CB_RGBA) { - for (; x>0; x--, outrf+= 2, inrf+= 4) { - outrf[0] = inrf[0]; - outrf[1] = inrf[1]; - } - } - } - else if (type==CB_VEC3) { - if (inbuf->type==CB_VAL) { - for (; x>0; x--, outrf+= 3, inrf+= 1) { - outrf[0] = inrf[0]; - outrf[1] = inrf[0]; - outrf[2] = inrf[0]; - } - } - else if (inbuf->type==CB_VEC2) { - for (; x>0; x--, outrf+= 3, inrf+= 2) { - outrf[0] = inrf[0]; - outrf[1] = inrf[1]; - outrf[2] = 0.0f; - } - } - else if (inbuf->type==CB_RGBA) { - for (; x>0; x--, outrf+= 3, inrf+= 4) { - outrf[0] = inrf[0]; - outrf[1] = inrf[1]; - outrf[2] = inrf[2]; - } - } - } - else if (type==CB_RGBA) { - if (inbuf->type==CB_VAL) { - for (; x>0; x--, outrf+= 4, inrf+= 1) { - outrf[0] = inrf[0]; - outrf[1] = inrf[0]; - outrf[2] = inrf[0]; - outrf[3] = 1.0f; - } - } - else if (inbuf->type==CB_VEC2) { - for (; x>0; x--, outrf+= 4, inrf+= 2) { - outrf[0] = inrf[0]; - outrf[1] = inrf[1]; - outrf[2] = 0.0f; - outrf[3] = 1.0f; - } - } - else if (inbuf->type==CB_VEC3) { - for (; x>0; x--, outrf+= 4, inrf+= 3) { - outrf[0] = inrf[0]; - outrf[1] = inrf[1]; - outrf[2] = inrf[2]; - outrf[3] = 1.0f; - } - } - } - - return outbuf; - } - return inbuf; -} - -float *compbuf_get_pixel(CompBuf *cbuf, float *defcol, float *use, int x, int y, int xrad, int yrad) -{ - if (cbuf) { - if (cbuf->rect_procedural) { - cbuf->rect_procedural(cbuf, use, (float)x/(float)xrad, (float)y/(float)yrad); - return use; - } - else { - static float col[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - - /* map coords */ - x-= cbuf->xof; - y-= cbuf->yof; - - if (y<-cbuf->yrad || y>= -cbuf->yrad+cbuf->y) return col; - if (x<-cbuf->xrad || x>= -cbuf->xrad+cbuf->x) return col; - - return cbuf->rect + cbuf->type*( (cbuf->yrad+y)*cbuf->x + (cbuf->xrad+x) ); - } - } - else return defcol; -} - -/* **************************************************** */ - -static CompBuf *composit_check_compbuf(CompBuf *cbuf, int type, CompBuf *outbuf) -{ - /* check type */ - CompBuf *dbuf= typecheck_compbuf(cbuf, type); - - /* if same as output and translated, duplicate so pixels don't interfere */ - if (dbuf == outbuf && !dbuf->rect_procedural && (dbuf->xof || dbuf->yof)) - dbuf= dupalloc_compbuf(dbuf); - - return dbuf; -} - -/* Pixel-to-Pixel operation, 1 Image in, 1 out */ -void composit1_pixel_processor(bNode *node, CompBuf *out, CompBuf *src_buf, float *src_col, - void (*func)(bNode *, float *, float *), - int src_type) -{ - CompBuf *src_use; - float *outfp=out->rect, *srcfp; - float color[4]; /* local color if compbuf is procedural */ - int xrad, yrad, x, y; - - src_use= composit_check_compbuf(src_buf, src_type, out); - - xrad= out->xrad; - yrad= out->yrad; - - for (y= -yrad; y<-yrad+out->y; y++) { - for (x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) { - srcfp= compbuf_get_pixel(src_use, src_col, color, x, y, xrad, yrad); - func(node, outfp, srcfp); - } - } - - if (src_use!=src_buf) - free_compbuf(src_use); -} - -/* Pixel-to-Pixel operation, 2 Images in, 1 out */ -void composit2_pixel_processor(bNode *node, CompBuf *out, CompBuf *src_buf, float *src_col, - CompBuf *fac_buf, float *fac, void (*func)(bNode *, float *, float *, float *), - int src_type, int fac_type) -{ - CompBuf *src_use, *fac_use; - float *outfp=out->rect, *srcfp, *facfp; - float color[4]; /* local color if compbuf is procedural */ - int xrad, yrad, x, y; - - src_use= composit_check_compbuf(src_buf, src_type, out); - fac_use= composit_check_compbuf(fac_buf, fac_type, out); - - xrad= out->xrad; - yrad= out->yrad; - - for (y= -yrad; y<-yrad+out->y; y++) { - for (x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) { - srcfp= compbuf_get_pixel(src_use, src_col, color, x, y, xrad, yrad); - facfp= compbuf_get_pixel(fac_use, fac, color, x, y, xrad, yrad); - - func(node, outfp, srcfp, facfp); - } - } - if (src_use!=src_buf) - free_compbuf(src_use); - if (fac_use!=fac_buf) - free_compbuf(fac_use); -} - -/* Pixel-to-Pixel operation, 3 Images in, 1 out */ -void composit3_pixel_processor(bNode *node, CompBuf *out, CompBuf *src1_buf, float *src1_col, CompBuf *src2_buf, float *src2_col, - CompBuf *fac_buf, float *fac, void (*func)(bNode *, float *, float *, float *, float *), - int src1_type, int src2_type, int fac_type) -{ - CompBuf *src1_use, *src2_use, *fac_use; - float *outfp=out->rect, *src1fp, *src2fp, *facfp; - float color[4]; /* local color if compbuf is procedural */ - int xrad, yrad, x, y; - - src1_use= composit_check_compbuf(src1_buf, src1_type, out); - src2_use= composit_check_compbuf(src2_buf, src2_type, out); - fac_use= composit_check_compbuf(fac_buf, fac_type, out); - - xrad= out->xrad; - yrad= out->yrad; - - for (y= -yrad; y<-yrad+out->y; y++) { - for (x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) { - src1fp= compbuf_get_pixel(src1_use, src1_col, color, x, y, xrad, yrad); - src2fp= compbuf_get_pixel(src2_use, src2_col, color, x, y, xrad, yrad); - facfp= compbuf_get_pixel(fac_use, fac, color, x, y, xrad, yrad); - - func(node, outfp, src1fp, src2fp, facfp); - } - } - - if (src1_use!=src1_buf) - free_compbuf(src1_use); - if (src2_use!=src2_buf) - free_compbuf(src2_use); - if (fac_use!=fac_buf) - free_compbuf(fac_use); -} - -/* Pixel-to-Pixel operation, 4 Images in, 1 out */ -void composit4_pixel_processor(bNode *node, CompBuf *out, CompBuf *src1_buf, float *src1_col, CompBuf *fac1_buf, float *fac1, - CompBuf *src2_buf, float *src2_col, CompBuf *fac2_buf, float *fac2, - void (*func)(bNode *, float *, float *, float *, float *, float *), - int src1_type, int fac1_type, int src2_type, int fac2_type) -{ - CompBuf *src1_use, *src2_use, *fac1_use, *fac2_use; - float *outfp=out->rect, *src1fp, *src2fp, *fac1fp, *fac2fp; - float color[4]; /* local color if compbuf is procedural */ - int xrad, yrad, x, y; - - src1_use= composit_check_compbuf(src1_buf, src1_type, out); - src2_use= composit_check_compbuf(src2_buf, src2_type, out); - fac1_use= composit_check_compbuf(fac1_buf, fac1_type, out); - fac2_use= composit_check_compbuf(fac2_buf, fac2_type, out); - - xrad= out->xrad; - yrad= out->yrad; - - for (y= -yrad; y<-yrad+out->y; y++) { - for (x= -xrad; x<-xrad+out->x; x++, outfp+=out->type) { - src1fp= compbuf_get_pixel(src1_use, src1_col, color, x, y, xrad, yrad); - src2fp= compbuf_get_pixel(src2_use, src2_col, color, x, y, xrad, yrad); - fac1fp= compbuf_get_pixel(fac1_use, fac1, color, x, y, xrad, yrad); - fac2fp= compbuf_get_pixel(fac2_use, fac2, color, x, y, xrad, yrad); - - func(node, outfp, src1fp, fac1fp, src2fp, fac2fp); - } - } - - if (src1_use!=src1_buf) - free_compbuf(src1_use); - if (src2_use!=src2_buf) - free_compbuf(src2_use); - if (fac1_use!=fac1_buf) - free_compbuf(fac1_use); - if (fac2_use!=fac2_buf) - free_compbuf(fac2_use); -} - - -CompBuf *valbuf_from_rgbabuf(CompBuf *cbuf, int channel) -{ - CompBuf *valbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); - float *valf, *rectf; - int tot; - - /* warning note: xof and yof are applied in pixelprocessor, but should be copied otherwise? */ - valbuf->xof= cbuf->xof; - valbuf->yof= cbuf->yof; - - valf= valbuf->rect; - - /* defaults to returning alpha channel */ - if ((channel < CHAN_R) || (channel > CHAN_A)) channel = CHAN_A; - - rectf= cbuf->rect + channel; - - for (tot= cbuf->x*cbuf->y; tot>0; tot--, valf++, rectf+=4) - *valf= *rectf; - - return valbuf; -} - -void valbuf_to_rgbabuf(CompBuf *valbuf, CompBuf *cbuf, int channel) -{ - float *valf, *rectf; - int tot; - - valf= valbuf->rect; - - /* defaults to returning alpha channel */ - if ((channel < CHAN_R) || (channel > CHAN_A)) channel = CHAN_A; - - rectf = cbuf->rect + channel; - - for (tot= cbuf->x*cbuf->y; tot>0; tot--, valf++, rectf+=4) - *rectf = *valf; -} - -static CompBuf *generate_procedural_preview(CompBuf *cbuf, int newx, int newy) -{ - CompBuf *outbuf; - float *outfp; - int xrad, yrad, x, y; - - outbuf= alloc_compbuf(newx, newy, CB_RGBA, 1); - - outfp= outbuf->rect; - xrad= outbuf->xrad; - yrad= outbuf->yrad; - - for (y= -yrad; y<-yrad+outbuf->y; y++) - for (x= -xrad; x<-xrad+outbuf->x; x++, outfp+=outbuf->type) - cbuf->rect_procedural(cbuf, outfp, (float)x/(float)xrad, (float)y/(float)yrad); - - return outbuf; -} - -/* OCIO_TODO: this function is only used by legacy compositor system only, which would likely be removed soon, - * keep check for old color management flag for now - */ -void generate_preview(void *data, bNode *node, CompBuf *stackbuf) -{ - RenderData *rd= data; - bNodePreview *preview= node->preview; - int xsize, ysize; - int profile_from= (rd->color_mgt_flag & R_COLOR_MANAGEMENT)? IB_PROFILE_LINEAR_RGB: IB_PROFILE_SRGB; - int predivide= TRUE; - int dither= 0; - unsigned char *rect; - - if (preview && stackbuf) { - CompBuf *cbuf, *stackbuf_use; - - if (stackbuf->rect==NULL && stackbuf->rect_procedural==NULL) return; - - stackbuf_use= typecheck_compbuf(stackbuf, CB_RGBA); - - if (stackbuf->x > stackbuf->y) { - xsize= 140; - ysize= (140*stackbuf->y)/stackbuf->x; - } - else { - ysize= 140; - xsize= (140*stackbuf->x)/stackbuf->y; - } - - if (stackbuf_use->rect_procedural) - cbuf= generate_procedural_preview(stackbuf_use, xsize, ysize); - else - cbuf= scalefast_compbuf(stackbuf_use, xsize, ysize); - - /* convert to byte for preview */ - rect= MEM_callocN(sizeof(unsigned char)*4*xsize*ysize, "bNodePreview.rect"); - - IMB_buffer_byte_from_float(rect, cbuf->rect, - 4, dither, IB_PROFILE_SRGB, profile_from, predivide, - xsize, ysize, xsize, xsize); - - free_compbuf(cbuf); - if (stackbuf_use!=stackbuf) - free_compbuf(stackbuf_use); - - // BLI_lock_thread(LOCK_PREVIEW); - - if (preview->rect) - MEM_freeN(preview->rect); - preview->xsize= xsize; - preview->ysize= ysize; - preview->rect= rect; - - // BLI_unlock_thread(LOCK_PREVIEW); - } -} - -void do_rgba_to_yuva(bNode *UNUSED(node), float *out, float *in) -{ - rgb_to_yuv(in[0], in[1], in[2], &out[0], &out[1], &out[2]); - out[3]=in[3]; -} - -void do_rgba_to_hsva(bNode *UNUSED(node), float *out, float *in) -{ - rgb_to_hsv(in[0], in[1], in[2], &out[0], &out[1], &out[2]); - out[3]=in[3]; -} - -void do_rgba_to_ycca(bNode *UNUSED(node), float *out, float *in) -{ - rgb_to_ycc(in[0], in[1], in[2], &out[0], &out[1], &out[2], BLI_YCC_ITU_BT601); - out[3]=in[3]; -} - -void do_yuva_to_rgba(bNode *UNUSED(node), float *out, float *in) -{ - yuv_to_rgb(in[0], in[1], in[2], &out[0], &out[1], &out[2]); - out[3]=in[3]; -} - -void do_hsva_to_rgba(bNode *UNUSED(node), float *out, float *in) -{ - hsv_to_rgb(in[0], in[1], in[2], &out[0], &out[1], &out[2]); - out[3]=in[3]; -} - -void do_ycca_to_rgba(bNode *UNUSED(node), float *out, float *in) -{ - ycc_to_rgb(in[0], in[1], in[2], &out[0], &out[1], &out[2], BLI_YCC_ITU_BT601); - out[3]=in[3]; -} - -void do_copy_rgba(bNode *UNUSED(node), float *out, float *in) -{ - copy_v4_v4(out, in); -} - -void do_copy_rgb(bNode *UNUSED(node), float *out, float *in) -{ - copy_v3_v3(out, in); - out[3] = 1.0f; -} - -void do_copy_value(bNode *UNUSED(node), float *out, float *in) -{ - out[0] = in[0]; -} - -void do_copy_a_rgba(bNode *UNUSED(node), float *out, float *in, float *fac) -{ - copy_v3_v3(out, in); - out[3] = *fac; -} - -/* only accepts RGBA buffers */ -void gamma_correct_compbuf(CompBuf *img, int inversed) -{ - float *drect; - int x; - - if (img->type!=CB_RGBA) return; - - drect= img->rect; - if (inversed) { - for (x=img->x*img->y; x>0; x--, drect+=4) { - if (drect[0]>0.0f) drect[0] = sqrt(drect[0]); else drect[0] = 0.0f; - if (drect[1]>0.0f) drect[1] = sqrt(drect[1]); else drect[1] = 0.0f; - if (drect[2]>0.0f) drect[2] = sqrt(drect[2]); else drect[2] = 0.0f; - } - } - else { - for (x=img->x*img->y; x>0; x--, drect+=4) { - if (drect[0]>0.0f) drect[0]*= drect[0]; else drect[0] = 0.0f; - if (drect[1]>0.0f) drect[1]*= drect[1]; else drect[1] = 0.0f; - if (drect[2]>0.0f) drect[2]*= drect[2]; else drect[2] = 0.0f; - } - } -} - -void premul_compbuf(CompBuf *img, int inversed) -{ - float *drect; - int x; - - if (img->type!=CB_RGBA) return; - - drect= img->rect; - if (inversed) { - for (x=img->x*img->y; x>0; x--, drect+=4) { - if (fabsf(drect[3]) < 1e-5f) { - drect[0] = 0.0f; - drect[1] = 0.0f; - drect[2] = 0.0f; - } - else { - drect[0] /= drect[3]; - drect[1] /= drect[3]; - drect[2] /= drect[3]; - } - } - } - else { - for (x=img->x*img->y; x>0; x--, drect+=4) { - drect[0] *= drect[3]; - drect[1] *= drect[3]; - drect[2] *= drect[3]; - } - } -} - - - -/* - * 2D Fast Hartley Transform, used for convolution - */ - -typedef float fREAL; - -// returns next highest power of 2 of x, as well it's log2 in L2 -static unsigned int nextPow2(unsigned int x, unsigned int* L2) -{ - unsigned int pw, x_notpow2 = x & (x-1); - *L2 = 0; - while (x>>=1) ++(*L2); - pw = 1 << (*L2); - if (x_notpow2) { (*L2)++; pw<<=1; } - return pw; -} - -//------------------------------------------------------------------------------ - -// from FXT library by Joerg Arndt, faster in order bitreversal -// use: r = revbin_upd(r, h) where h = N>>1 -static unsigned int revbin_upd(unsigned int r, unsigned int h) -{ - while (!((r^=h)&h)) h >>= 1; - return r; -} -//------------------------------------------------------------------------------ -static void FHT(fREAL* data, unsigned int M, unsigned int inverse) -{ - double tt, fc, dc, fs, ds, a = M_PI; - fREAL t1, t2; - int n2, bd, bl, istep, k, len = 1 << M, n = 1; - - int i, j = 0; - unsigned int Nh = len >> 1; - for (i=1;i<(len-1);++i) { - j = revbin_upd(j, Nh); - if (j>i) { - t1 = data[i]; - data[i] = data[j]; - data[j] = t1; - } - } - - do { - fREAL* data_n = &data[n]; - - istep = n << 1; - for (k=0; k<len; k+=istep) { - t1 = data_n[k]; - data_n[k] = data[k] - t1; - data[k] += t1; - } - - n2 = n >> 1; - if (n>2) { - fc = dc = cos(a); - fs = ds = sqrt(1.0 - fc*fc); //sin(a); - bd = n-2; - for (bl=1; bl<n2; bl++) { - fREAL* data_nbd = &data_n[bd]; - fREAL* data_bd = &data[bd]; - for (k=bl; k<len; k+=istep) { - t1 = fc*data_n[k] + fs*data_nbd[k]; - t2 = fs*data_n[k] - fc*data_nbd[k]; - data_n[k] = data[k] - t1; - data_nbd[k] = data_bd[k] - t2; - data[k] += t1; - data_bd[k] += t2; - } - tt = fc*dc - fs*ds; - fs = fs*dc + fc*ds; - fc = tt; - bd -= 2; - } - } - - if (n>1) { - for (k=n2; k<len; k+=istep) { - t1 = data_n[k]; - data_n[k] = data[k] - t1; - data[k] += t1; - } - } - - n = istep; - a *= 0.5; - } while (n<len); - - if (inverse) { - fREAL sc = (fREAL)1 / (fREAL)len; - for (k=0; k<len; ++k) - data[k] *= sc; - } -} -//------------------------------------------------------------------------------ -/* 2D Fast Hartley Transform, Mx/My -> log2 of width/height, - * nzp -> the row where zero pad data starts, - * inverse -> see above */ -static void FHT2D(fREAL *data, unsigned int Mx, unsigned int My, - unsigned int nzp, unsigned int inverse) -{ - unsigned int i, j, Nx, Ny, maxy; - fREAL t; - - Nx = 1 << Mx; - Ny = 1 << My; - - // rows (forward transform skips 0 pad data) - maxy = inverse ? Ny : nzp; - for (j=0; j<maxy; ++j) - FHT(&data[Nx*j], Mx, inverse); - - // transpose data - if (Nx==Ny) { // square - for (j=0; j<Ny; ++j) - for (i=j+1; i<Nx; ++i) { - unsigned int op = i + (j << Mx), np = j + (i << My); - t=data[op], data[op]=data[np], data[np]=t; - } - } - else { // rectangular - unsigned int k, Nym = Ny-1, stm = 1 << (Mx + My); - for (i=0; stm>0; i++) { - #define PRED(k) (((k & Nym) << Mx) + (k >> My)) - for (j=PRED(i); j>i; j=PRED(j)); - if (j < i) continue; - for (k=i, j=PRED(i); j!=i; k=j, j=PRED(j), stm--) { - t=data[j], data[j]=data[k], data[k]=t; - } - #undef PRED - stm--; - } - } - // swap Mx/My & Nx/Ny - i = Nx, Nx = Ny, Ny = i; - i = Mx, Mx = My, My = i; - - // now columns == transposed rows - for (j=0; j<Ny; ++j) - FHT(&data[Nx*j], Mx, inverse); - - // finalize - for (j=0; j<=(Ny >> 1); j++) { - unsigned int jm = (Ny - j) & (Ny-1); - unsigned int ji = j << Mx; - unsigned int jmi = jm << Mx; - for (i=0; i<=(Nx >> 1); i++) { - unsigned int im = (Nx - i) & (Nx-1); - fREAL A = data[ji + i]; - fREAL B = data[jmi + i]; - fREAL C = data[ji + im]; - fREAL D = data[jmi + im]; - fREAL E = (fREAL)0.5*((A + D) - (B + C)); - data[ji + i] = A - E; - data[jmi + i] = B + E; - data[ji + im] = C + E; - data[jmi + im] = D - E; - } - } - -} - -//------------------------------------------------------------------------------ - -/* 2D convolution calc, d1 *= d2, M/N - > log2 of width/height */ -static void fht_convolve(fREAL* d1, fREAL* d2, unsigned int M, unsigned int N) -{ - fREAL a, b; - unsigned int i, j, k, L, mj, mL; - unsigned int m = 1 << M, n = 1 << N; - unsigned int m2 = 1 << (M-1), n2 = 1 << (N-1); - unsigned int mn2 = m << (N-1); - - d1[0] *= d2[0]; - d1[mn2] *= d2[mn2]; - d1[m2] *= d2[m2]; - d1[m2 + mn2] *= d2[m2 + mn2]; - for (i=1; i<m2; i++) { - k = m - i; - a = d1[i]*d2[i] - d1[k]*d2[k]; - b = d1[k]*d2[i] + d1[i]*d2[k]; - d1[i] = (b + a)*(fREAL)0.5; - d1[k] = (b - a)*(fREAL)0.5; - a = d1[i + mn2]*d2[i + mn2] - d1[k + mn2]*d2[k + mn2]; - b = d1[k + mn2]*d2[i + mn2] + d1[i + mn2]*d2[k + mn2]; - d1[i + mn2] = (b + a)*(fREAL)0.5; - d1[k + mn2] = (b - a)*(fREAL)0.5; - } - for (j=1; j<n2; j++) { - L = n - j; - mj = j << M; - mL = L << M; - a = d1[mj]*d2[mj] - d1[mL]*d2[mL]; - b = d1[mL]*d2[mj] + d1[mj]*d2[mL]; - d1[mj] = (b + a)*(fREAL)0.5; - d1[mL] = (b - a)*(fREAL)0.5; - a = d1[m2 + mj]*d2[m2 + mj] - d1[m2 + mL]*d2[m2 + mL]; - b = d1[m2 + mL]*d2[m2 + mj] + d1[m2 + mj]*d2[m2 + mL]; - d1[m2 + mj] = (b + a)*(fREAL)0.5; - d1[m2 + mL] = (b - a)*(fREAL)0.5; - } - for (i=1; i<m2; i++) { - k = m - i; - for (j=1; j<n2; j++) { - L = n - j; - mj = j << M; - mL = L << M; - a = d1[i + mj]*d2[i + mj] - d1[k + mL]*d2[k + mL]; - b = d1[k + mL]*d2[i + mj] + d1[i + mj]*d2[k + mL]; - d1[i + mj] = (b + a)*(fREAL)0.5; - d1[k + mL] = (b - a)*(fREAL)0.5; - a = d1[i + mL]*d2[i + mL] - d1[k + mj]*d2[k + mj]; - b = d1[k + mj]*d2[i + mL] + d1[i + mL]*d2[k + mj]; - d1[i + mL] = (b + a)*(fREAL)0.5; - d1[k + mj] = (b - a)*(fREAL)0.5; - } - } -} - -//------------------------------------------------------------------------------ - -void convolve(CompBuf* dst, CompBuf* in1, CompBuf* in2) -{ - fREAL *data1, *data2, *fp; - unsigned int w2, h2, hw, hh, log2_w, log2_h; - fRGB wt, *colp; - int x, y, ch; - int xbl, ybl, nxb, nyb, xbsz, ybsz; - int in2done = FALSE; - - CompBuf* rdst = alloc_compbuf(in1->x, in1->y, in1->type, 1); - - // convolution result width & height - w2 = 2*in2->x - 1; - h2 = 2*in2->y - 1; - // FFT pow2 required size & log2 - w2 = nextPow2(w2, &log2_w); - h2 = nextPow2(h2, &log2_h); - - // alloc space - data1 = (fREAL*)MEM_callocN(3*w2*h2*sizeof(fREAL), "convolve_fast FHT data1"); - data2 = (fREAL*)MEM_callocN(w2*h2*sizeof(fREAL), "convolve_fast FHT data2"); - - // normalize convolutor - wt[0] = wt[1] = wt[2] = 0.f; - for (y=0; y<in2->y; y++) { - colp = (fRGB*)&in2->rect[y*in2->x*in2->type]; - for (x=0; x<in2->x; x++) - add_v3_v3(wt, colp[x]); - } - if (wt[0] != 0.f) wt[0] = 1.f/wt[0]; - if (wt[1] != 0.f) wt[1] = 1.f/wt[1]; - if (wt[2] != 0.f) wt[2] = 1.f/wt[2]; - for (y=0; y<in2->y; y++) { - colp = (fRGB*)&in2->rect[y*in2->x*in2->type]; - for (x=0; x<in2->x; x++) - mul_v3_v3(colp[x], wt); - } - - // copy image data, unpacking interleaved RGBA into separate channels - // only need to calc data1 once - - // block add-overlap - hw = in2->x >> 1; - hh = in2->y >> 1; - xbsz = (w2 + 1) - in2->x; - ybsz = (h2 + 1) - in2->y; - nxb = in1->x / xbsz; - if (in1->x % xbsz) nxb++; - nyb = in1->y / ybsz; - if (in1->y % ybsz) nyb++; - for (ybl=0; ybl<nyb; ybl++) { - for (xbl=0; xbl<nxb; xbl++) { - - // each channel one by one - for (ch=0; ch<3; ch++) { - fREAL* data1ch = &data1[ch*w2*h2]; - - // only need to calc fht data from in2 once, can re-use for every block - if (!in2done) { - // in2, channel ch -> data1 - for (y=0; y<in2->y; y++) { - fp = &data1ch[y*w2]; - colp = (fRGB*)&in2->rect[y*in2->x*in2->type]; - for (x=0; x<in2->x; x++) - fp[x] = colp[x][ch]; - } - } - - // in1, channel ch -> data2 - memset(data2, 0, w2*h2*sizeof(fREAL)); - for (y=0; y<ybsz; y++) { - int yy = ybl*ybsz + y; - if (yy >= in1->y) continue; - fp = &data2[y*w2]; - colp = (fRGB*)&in1->rect[yy*in1->x*in1->type]; - for (x=0; x<xbsz; x++) { - int xx = xbl*xbsz + x; - if (xx >= in1->x) continue; - fp[x] = colp[xx][ch]; - } - } - - // forward FHT - // zero pad data start is different for each == height+1 - if (!in2done) FHT2D(data1ch, log2_w, log2_h, in2->y+1, 0); - FHT2D(data2, log2_w, log2_h, in2->y+1, 0); - - // FHT2D transposed data, row/col now swapped - // convolve & inverse FHT - fht_convolve(data2, data1ch, log2_h, log2_w); - FHT2D(data2, log2_h, log2_w, 0, 1); - // data again transposed, so in order again - - // overlap-add result - for (y=0; y<(int)h2; y++) { - const int yy = ybl*ybsz + y - hh; - if ((yy < 0) || (yy >= in1->y)) continue; - fp = &data2[y*w2]; - colp = (fRGB*)&rdst->rect[yy*in1->x*in1->type]; - for (x=0; x<(int)w2; x++) { - const int xx = xbl*xbsz + x - hw; - if ((xx < 0) || (xx >= in1->x)) continue; - colp[xx][ch] += fp[x]; - } - } - - } - in2done = TRUE; - } - } - - MEM_freeN(data2); - MEM_freeN(data1); - memcpy(dst->rect, rdst->rect, sizeof(float)*dst->x*dst->y*dst->type); - free_compbuf(rdst); -} - - -/* - * - * Utility functions qd_* should probably be integrated better with other functions here. - * - */ -// sets fcol to pixelcolor at (x, y) -void qd_getPixel(CompBuf* src, int x, int y, float* col) -{ - if (src->rect_procedural) { - float bc[4]; - src->rect_procedural(src, bc, (float)x/(float)src->xrad, (float)y/(float)src->yrad); - - switch (src->type) { - /* these fallthrough to get all the channels */ - case CB_RGBA: col[3]=bc[3]; - case CB_VEC3: col[2]=bc[2]; - case CB_VEC2: col[1]=bc[1]; - case CB_VAL: col[0]=bc[0]; - } - } - else if ((x >= 0) && (x < src->x) && (y >= 0) && (y < src->y)) { - float* bc = &src->rect[(x + y*src->x)*src->type]; - switch (src->type) { - /* these fallthrough to get all the channels */ - case CB_RGBA: col[3]=bc[3]; - case CB_VEC3: col[2]=bc[2]; - case CB_VEC2: col[1]=bc[1]; - case CB_VAL: col[0]=bc[0]; - } - } - else { - switch (src->type) { - /* these fallthrough to get all the channels */ - case CB_RGBA: col[3]=0.0; - case CB_VEC3: col[2]=0.0; - case CB_VEC2: col[1]=0.0; - case CB_VAL: col[0]=0.0; - } - } -} - -// sets pixel (x, y) to color col -void qd_setPixel(CompBuf* src, int x, int y, float* col) -{ - if ((x >= 0) && (x < src->x) && (y >= 0) && (y < src->y)) { - float* bc = &src->rect[(x + y*src->x)*src->type]; - switch (src->type) { - /* these fallthrough to get all the channels */ - case CB_RGBA: bc[3]=col[3]; - case CB_VEC3: bc[2]=col[2]; - case CB_VEC2: bc[1]=col[1]; - case CB_VAL: bc[0]=col[0]; - } - } -} - -// adds fcol to pixelcolor (x, y) -void qd_addPixel(CompBuf* src, int x, int y, float* col) -{ - if ((x >= 0) && (x < src->x) && (y >= 0) && (y < src->y)) { - float* bc = &src->rect[(x + y*src->x)*src->type]; - bc[0] += col[0], bc[1] += col[1], bc[2] += col[2]; - } -} - -// multiplies pixel by factor value f -void qd_multPixel(CompBuf* src, int x, int y, float f) -{ - if ((x >= 0) && (x < src->x) && (y >= 0) && (y < src->y)) { - float* bc = &src->rect[(x + y*src->x)*src->type]; - bc[0] *= f, bc[1] *= f, bc[2] *= f; - } -} - -// bilinear interpolation with wraparound -void qd_getPixelLerpWrap(CompBuf* src, float u, float v, float* col) -{ - const float ufl = floor(u), vfl = floor(v); - const int nx = (int)ufl % src->x, ny = (int)vfl % src->y; - const int x1 = (nx < 0) ? (nx + src->x) : nx; - const int y1 = (ny < 0) ? (ny + src->y) : ny; - const int x2 = (x1 + 1) % src->x, y2 = (y1 + 1) % src->y; - const float* c00 = &src->rect[(x1 + y1*src->x)*src->type]; - const float* c10 = &src->rect[(x2 + y1*src->x)*src->type]; - const float* c01 = &src->rect[(x1 + y2*src->x)*src->type]; - const float* c11 = &src->rect[(x2 + y2*src->x)*src->type]; - const float uf = u - ufl, vf = v - vfl; - const float w00=(1.f-uf)*(1.f-vf), w10=uf*(1.f-vf), w01=(1.f-uf)*vf, w11=uf*vf; - col[0] = w00*c00[0] + w10*c10[0] + w01*c01[0] + w11*c11[0]; - if (src->type != CB_VAL) { - col[1] = w00*c00[1] + w10*c10[1] + w01*c01[1] + w11*c11[1]; - col[2] = w00*c00[2] + w10*c10[2] + w01*c01[2] + w11*c11[2]; - col[3] = w00*c00[3] + w10*c10[3] + w01*c01[3] + w11*c11[3]; - } -} - -// as above, without wrap around -void qd_getPixelLerp(CompBuf* src, float u, float v, float* col) -{ - const float ufl = floor(u), vfl = floor(v); - const int x1 = (int)ufl, y1 = (int)vfl; - const int x2 = (int)ceil(u), y2 = (int)ceil(v); - if ((x2 >= 0) && (y2 >= 0) && (x1 < src->x) && (y1 < src->y)) { - const float B[4] = {0, 0, 0, 0}; - const int ox1 = (x1 < 0), oy1 = (y1 < 0), ox2 = (x2 >= src->x), oy2 = (y2 >= src->y); - const float* c00 = (ox1 || oy1) ? B : &src->rect[(x1 + y1*src->x)*src->type]; - const float* c10 = (ox2 || oy1) ? B : &src->rect[(x2 + y1*src->x)*src->type]; - const float* c01 = (ox1 || oy2) ? B : &src->rect[(x1 + y2*src->x)*src->type]; - const float* c11 = (ox2 || oy2) ? B : &src->rect[(x2 + y2*src->x)*src->type]; - const float uf = u - ufl, vf = v - vfl; - const float w00=(1.f-uf)*(1.f-vf), w10=uf*(1.f-vf), w01=(1.f-uf)*vf, w11=uf*vf; - col[0] = w00*c00[0] + w10*c10[0] + w01*c01[0] + w11*c11[0]; - if (src->type != CB_VAL) { - col[1] = w00*c00[1] + w10*c10[1] + w01*c01[1] + w11*c11[1]; - col[2] = w00*c00[2] + w10*c10[2] + w01*c01[2] + w11*c11[2]; - col[3] = w00*c00[3] + w10*c10[3] + w01*c01[3] + w11*c11[3]; - } - } - else col[0] = col[1] = col[2] = col[3] = 0.f; -} - -// as above, sampling only one channel -void qd_getPixelLerpChan(CompBuf* src, float u, float v, int chan, float* out) -{ - const float ufl = floor(u), vfl = floor(v); - const int x1 = (int)ufl, y1 = (int)vfl; - const int x2 = (int)ceil(u), y2 = (int)ceil(v); - if (chan >= src->type) chan = 0; - if ((x2 >= 0) && (y2 >= 0) && (x1 < src->x) && (y1 < src->y)) { - const float B[4] = {0, 0, 0, 0}; - const int ox1 = (x1 < 0), oy1 = (y1 < 0), ox2 = (x2 >= src->x), oy2 = (y2 >= src->y); - const float* c00 = (ox1 || oy1) ? B : &src->rect[(x1 + y1*src->x)*src->type + chan]; - const float* c10 = (ox2 || oy1) ? B : &src->rect[(x2 + y1*src->x)*src->type + chan]; - const float* c01 = (ox1 || oy2) ? B : &src->rect[(x1 + y2*src->x)*src->type + chan]; - const float* c11 = (ox2 || oy2) ? B : &src->rect[(x2 + y2*src->x)*src->type + chan]; - const float uf = u - ufl, vf = v - vfl; - const float w00=(1.f-uf)*(1.f-vf), w10=uf*(1.f-vf), w01=(1.f-uf)*vf, w11=uf*vf; - out[0] = w00*c00[0] + w10*c10[0] + w01*c01[0] + w11*c11[0]; - } - else *out = 0.f; -} - - -CompBuf* qd_downScaledCopy(CompBuf* src, int scale) -{ - CompBuf* fbuf; - if (scale <= 1) - fbuf = dupalloc_compbuf(src); - else { - int nw = src->x/scale, nh = src->y/scale; - if ((2*(src->x % scale)) > scale) nw++; - if ((2*(src->y % scale)) > scale) nh++; - fbuf = alloc_compbuf(nw, nh, src->type, 1); - { - int x, y, xx, yy, sx, sy, mx, my; - float colsum[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - float fscale = 1.f/(float)(scale*scale); - for (y=0; y<nh; y++) { - fRGB* fcolp = (fRGB*)&fbuf->rect[y*fbuf->x*fbuf->type]; - yy = y*scale; - my = yy + scale; - if (my > src->y) my = src->y; - for (x=0; x<nw; x++) { - xx = x*scale; - mx = xx + scale; - if (mx > src->x) mx = src->x; - zero_v3(colsum); - for (sy=yy; sy<my; sy++) { - fRGB* scolp = (fRGB*)&src->rect[sy*src->x*src->type]; - for (sx=xx; sx<mx; sx++) - add_v3_v3(colsum, scolp[sx]); - } - mul_v3_fl(colsum, fscale); - copy_v3_v3(fcolp[x], colsum); - } - } - } - } - return fbuf; -} - -// fast g.blur, per channel -// xy var. bits 1 & 2 ca be used to blur in x or y direction separately -void IIR_gauss(CompBuf* src, float sigma, int chan, int xy) -{ - double q, q2, sc, cf[4], tsM[9], tsu[3], tsv[3]; - double *X, *Y, *W; - const unsigned int src_width = src->x; - const unsigned int src_height = src->y; - unsigned int i, x, y, sz; - - // <0.5 not valid, though can have a possibly useful sort of sharpening effect - if (sigma < 0.5f) return; - - if ((xy < 1) || (xy > 3)) xy = 3; - - // XXX The YVV macro defined below explicitly expects sources of at least 3x3 pixels, - // so just skiping blur along faulty direction if src's def is below that limit! - if (src_width < 3) xy &= ~(int) 1; - if (src_height < 3) xy &= ~(int) 2; - if (xy < 1) return; - - // see "Recursive Gabor Filtering" by Young/VanVliet - // all factors here in double.prec. Required, because for single.prec it seems to blow up if sigma > ~200 - if (sigma >= 3.556f) - q = 0.9804f * (sigma - 3.556f) + 2.5091f; - else // sigma >= 0.5 - q = (0.0561f * sigma + 0.5784f) * sigma - 0.2568f; - q2 = q * q; - sc = (1.1668 + q) * (3.203729649 + (2.21566 + q) * q); - // no gabor filtering here, so no complex multiplies, just the regular coefs. - // all negated here, so as not to have to recalc Triggs/Sdika matrix - cf[1] = q * (5.788961737 + (6.76492 + 3.0 * q) * q) / sc; - cf[2] = -q2 * (3.38246 + 3.0 * q) / sc; - // 0 & 3 unchanged - cf[3] = q2 * q / sc; - cf[0] = 1.0 - cf[1] - cf[2] - cf[3]; - - // Triggs/Sdika border corrections, - // it seems to work, not entirely sure if it is actually totally correct, - // Besides J.M.Geusebroek's anigauss.c (see http://www.science.uva.nl/~mark), - // found one other implementation by Cristoph Lampert, - // but neither seem to be quite the same, result seems to be ok so far anyway. - // Extra scale factor here to not have to do it in filter, - // though maybe this had something to with the precision errors - sc = cf[0] / ((1.0 + cf[1] - cf[2] + cf[3]) * (1.0 - cf[1] - cf[2] - cf[3]) * (1.0 + cf[2] + (cf[1] - cf[3]) * cf[3])); - tsM[0] = sc * (-cf[3] * cf[1] + 1.0 - cf[3] * cf[3] - cf[2]); - tsM[1] = sc * ((cf[3] + cf[1]) * (cf[2] + cf[3] * cf[1])); - tsM[2] = sc * (cf[3] * (cf[1] + cf[3] * cf[2])); - tsM[3] = sc * (cf[1] + cf[3] * cf[2]); - tsM[4] = sc * (-(cf[2] - 1.0) * (cf[2] + cf[3] * cf[1])); - tsM[5] = sc * (-(cf[3] * cf[1] + cf[3] * cf[3] + cf[2] - 1.0) * cf[3]); - tsM[6] = sc * (cf[3] * cf[1] + cf[2] + cf[1] * cf[1] - cf[2] * cf[2]); - tsM[7] = sc * (cf[1] * cf[2] + cf[3] * cf[2] * cf[2] - cf[1] * cf[3] * cf[3] - cf[3] * cf[3] * cf[3] - cf[3] * cf[2] + cf[3]); - tsM[8] = sc * (cf[3] * (cf[1] + cf[3] * cf[2])); - -#define YVV(L) \ -{ \ - W[0] = cf[0] * X[0] + cf[1] * X[0] + cf[2] * X[0] + cf[3] * X[0]; \ - W[1] = cf[0] * X[1] + cf[1] * W[0] + cf[2] * X[0] + cf[3] * X[0]; \ - W[2] = cf[0] * X[2] + cf[1] * W[1] + cf[2] * W[0] + cf[3] * X[0]; \ - for (i = 3; i < L; i++) { \ - W[i] = cf[0] * X[i] + cf[1] * W[i - 1] + cf[2] * W[i - 2] + cf[3] * W[i - 3]; \ - } \ - tsu[0] = W[L - 1] - X[L - 1]; \ - tsu[1] = W[L - 2] - X[L - 1]; \ - tsu[2] = W[L - 3] - X[L - 1]; \ - tsv[0] = tsM[0] * tsu[0] + tsM[1] * tsu[1] + tsM[2] * tsu[2] + X[L - 1]; \ - tsv[1] = tsM[3] * tsu[0] + tsM[4] * tsu[1] + tsM[5] * tsu[2] + X[L - 1]; \ - tsv[2] = tsM[6] * tsu[0] + tsM[7] * tsu[1] + tsM[8] * tsu[2] + X[L - 1]; \ - Y[L - 1] = cf[0] * W[L - 1] + cf[1] * tsv[0] + cf[2] * tsv[1] + cf[3] * tsv[2]; \ - Y[L - 2] = cf[0] * W[L - 2] + cf[1] * Y[L - 1] + cf[2] * tsv[0] + cf[3] * tsv[1]; \ - Y[L - 3] = cf[0] * W[L - 3] + cf[1] * Y[L - 2] + cf[2] * Y[L - 1] + cf[3] * tsv[0]; \ - /* 'i != UINT_MAX' is really 'i >= 0', but necessary for unsigned int wrapping */ \ - for (i = L - 4; i != UINT_MAX; i--) { \ - Y[i] = cf[0] * W[i] + cf[1] * Y[i + 1] + cf[2] * Y[i + 2] + cf[3] * Y[i + 3]; \ - } \ -} (void)0 - - // intermediate buffers - sz = MAX2(src_width, src_height); - X = MEM_callocN(sz * sizeof(double), "IIR_gauss X buf"); - Y = MEM_callocN(sz * sizeof(double), "IIR_gauss Y buf"); - W = MEM_callocN(sz * sizeof(double), "IIR_gauss W buf"); - if (xy & 1) { // H - for (y = 0; y < src_height; ++y) { - const int yx = y * src_width; - for (x = 0; x < src_width; ++x) - X[x] = src->rect[(x + yx) * src->type + chan]; - YVV(src_width); - for (x = 0; x < src_width; ++x) - src->rect[(x + yx) * src->type + chan] = Y[x]; - } - } - if (xy & 2) { // V - for (x = 0; x < src_width; ++x) { - for (y = 0; y < src_height; ++y) - X[y] = src->rect[(x + y * src_width) * src->type + chan]; - YVV(src_height); - for (y = 0; y < src_height; ++y) - src->rect[(x + y * src_width) * src->type + chan] = Y[y]; - } - } - - MEM_freeN(X); - MEM_freeN(W); - MEM_freeN(Y); -#undef YVV -} - -#endif /* WITH_COMPOSITOR_LEGACY */ diff --git a/source/blender/nodes/composite/node_composite_util.h b/source/blender/nodes/composite/node_composite_util.h index f2719ee0779..a3c4bffe018 100644 --- a/source/blender/nodes/composite/node_composite_util.h +++ b/source/blender/nodes/composite/node_composite_util.h @@ -33,177 +33,30 @@ #ifndef __NODE_COMPOSITE_UTIL_H__ #define __NODE_COMPOSITE_UTIL_H__ -#include <stdlib.h> -#include <string.h> -#include <math.h> - -#include "MEM_guardedalloc.h" - -#include "DNA_camera_types.h" /* qdn: defocus node, need camera info */ -#include "DNA_color_types.h" #include "DNA_ID.h" -#include "DNA_image_types.h" -#include "DNA_material_types.h" #include "DNA_movieclip_types.h" #include "DNA_node_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_texture_types.h" #include "BLI_math.h" #include "BLI_blenlib.h" -#include "BLI_rand.h" -#include "BLI_threads.h" -#include "BLI_utildefines.h" -#include "BLI_utildefines.h" #include "BLF_translation.h" -#include "BKE_blender.h" -#include "BKE_camera.h" #include "BKE_colortools.h" -#include "BKE_global.h" #include "BKE_image.h" -#include "BKE_main.h" -#include "BKE_material.h" -#include "BKE_movieclip.h" -#include "BKE_node.h" #include "BKE_texture.h" #include "BKE_tracking.h" -#include "BKE_library.h" -#include "BKE_object.h" - #include "node_util.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" #include "RE_pipeline.h" -#include "RE_shader_ext.h" -#include "RE_render_ext.h" /* only for forward declarations */ #include "NOD_composite.h" #define CMP_SCALE_MAX 12000 -#ifdef WITH_COMPOSITOR_LEGACY - -/* *************************** operations support *************************** */ - -/* general signal that's in output sockets, and goes over the wires */ -typedef struct CompBuf { - float *rect; - int x, y, xrad, yrad; - short type, malloc; - rcti disprect; /* cropped part of image */ - int xof, yof; /* relative to center of target image */ - - void (*rect_procedural)(struct CompBuf *, float *, float, float); - float procedural_size[3], procedural_offset[3]; - int procedural_type; - bNode *node; /* only in use for procedural bufs */ - - struct CompBuf *next, *prev; /* for pass-on, works nicer than reference counting */ -} CompBuf; - -/* defines also used for pixel size */ -#define CB_RGBA 4 -#define CB_VEC4 4 -#define CB_VEC3 3 -#define CB_VEC2 2 -#define CB_VAL 1 - -/* defines for RGBA channels */ -#define CHAN_R 0 -#define CHAN_G 1 -#define CHAN_B 2 -#define CHAN_A 3 - - - -CompBuf *alloc_compbuf(int sizex, int sizey, int type, int alloc); -CompBuf *dupalloc_compbuf(CompBuf *cbuf); -CompBuf *pass_on_compbuf(CompBuf *cbuf); -void free_compbuf(CompBuf *cbuf); -void print_compbuf(char *str, CompBuf *cbuf); -void compbuf_set_node(struct CompBuf *cbuf, struct bNode *node); - -CompBuf *get_cropped_compbuf(rcti *drect, float *rectf, int rectx, int recty, int type); -CompBuf *scalefast_compbuf(CompBuf *inbuf, int newx, int newy); -CompBuf *typecheck_compbuf(CompBuf *inbuf, int type); -void typecheck_compbuf_color(float *out, float *in, int outtype, int intype); - -/* **************************************************** */ - -float *compbuf_get_pixel(CompBuf *cbuf, float *defcol, float *use, int x, int y, int xrad, int yrad); - -/* Pixel-to-Pixel operation, 1 Image in, 1 out */ -void composit1_pixel_processor(bNode *node, CompBuf *out, CompBuf *src_buf, float *src_col, - void (*func)(bNode *, float *, float *), - int src_type); -/* Pixel-to-Pixel operation, 2 Images in, 1 out */ -void composit2_pixel_processor(bNode *node, CompBuf *out, CompBuf *src_buf, float *src_col, - CompBuf *fac_buf, float *fac, void (*func)(bNode *, float *, float *, float *), - int src_type, int fac_type); - -/* Pixel-to-Pixel operation, 3 Images in, 1 out */ -void composit3_pixel_processor(bNode *node, CompBuf *out, CompBuf *src1_buf, float *src1_col, CompBuf *src2_buf, float *src2_col, - CompBuf *fac_buf, float *fac, void (*func)(bNode *, float *, float *, float *, float *), - int src1_type, int src2_type, int fac_type); - -/* Pixel-to-Pixel operation, 4 Images in, 1 out */ -void composit4_pixel_processor(bNode *node, CompBuf *out, CompBuf *src1_buf, float *src1_col, CompBuf *fac1_buf, float *fac1, - CompBuf *src2_buf, float *src2_col, CompBuf *fac2_buf, float *fac2, - void (*func)(bNode *, float *, float *, float *, float *, float *), - int src1_type, int fac1_type, int src2_type, int fac2_type); - -CompBuf *valbuf_from_rgbabuf(CompBuf *cbuf, int channel); -void valbuf_to_rgbabuf(CompBuf *valbuf, CompBuf *cbuf, int channel); -void generate_preview(void *data, bNode *node, CompBuf *stackbuf); - -void do_copy_rgba(bNode *node, float *out, float *in); -void do_copy_rgb(bNode *node, float *out, float *in); -void do_copy_value(bNode *node, float *out, float *in); -void do_copy_a_rgba(bNode *node, float *out, float *in, float *fac); - -void do_rgba_to_yuva(bNode *node, float *out, float *in); -void do_rgba_to_hsva(bNode *node, float *out, float *in); -void do_rgba_to_ycca(bNode *node, float *out, float *in); -void do_yuva_to_rgba(bNode *node, float *out, float *in); -void do_hsva_to_rgba(bNode *node, float *out, float *in); -void do_ycca_to_rgba(bNode *node, float *out, float *in); - -void gamma_correct_compbuf(CompBuf *img, int inversed); -void premul_compbuf(CompBuf *img, int inversed); -void convolve(CompBuf* dst, CompBuf* in1, CompBuf* in2); - -extern void node_ID_title_cb(void *node_v, void *unused_v); - - -/* utility functions used by glare, tonemap and lens distortion */ -/* soms macros for color handling */ -typedef float fRGB[4]; -/* multiply c2 by color rgb, rgb as separate arguments */ -#define fRGB_rgbmult(c, r, g, b) { c[0]*=(r); c[1]*=(g); c[2]*=(b); } (void)0 - -void qd_getPixel(CompBuf* src, int x, int y, float* col); -void qd_setPixel(CompBuf* src, int x, int y, float* col); -void qd_addPixel(CompBuf* src, int x, int y, float* col); -void qd_multPixel(CompBuf* src, int x, int y, float f); -void qd_getPixelLerpWrap(CompBuf* src, float u, float v, float* col); -void qd_getPixelLerp(CompBuf* src, float u, float v, float* col); -void qd_getPixelLerpChan(CompBuf* src, float u, float v, int chan, float* out); -CompBuf* qd_downScaledCopy(CompBuf* src, int scale); -void IIR_gauss(CompBuf* src, float sigma, int chan, int xy); -/* end utility funcs */ - -/* transformations */ - -CompBuf* node_composit_transform(CompBuf *cbuf, float x, float y, float angle, float scale, int filter_type); -float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc); - -#endif - -#endif /* WITH_COMPOSITOR_LEGACY */ +#endif /* __NODE_COMPOSITE_UTIL_H__ */ diff --git a/source/blender/nodes/composite/nodes/node_composite_alphaOver.c b/source/blender/nodes/composite/nodes/node_composite_alphaOver.c index 71b71c9dd4a..2654aa94be0 100644 --- a/source/blender/nodes/composite/nodes/node_composite_alphaOver.c +++ b/source/blender/nodes/composite/nodes/node_composite_alphaOver.c @@ -43,103 +43,6 @@ static bNodeSocketTemplate cmp_node_alphaover_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_alphaover_premul(bNode *UNUSED(node), float *out, float *src, float *over, float *fac) -{ - - /* Zero alpha values should still permit an add of RGB data */ - if (over[3]<0.0f) { - copy_v4_v4(out, src); - } - else if (fac[0]==1.0f && over[3]>=1.0f) { - copy_v4_v4(out, over); - } - else { - float mul= 1.0f - fac[0]*over[3]; - - out[0] = (mul*src[0]) + fac[0]*over[0]; - out[1] = (mul*src[1]) + fac[0]*over[1]; - out[2] = (mul*src[2]) + fac[0]*over[2]; - out[3] = (mul*src[3]) + fac[0]*over[3]; - } -} - -/* result will be still premul, but the over part is premulled */ -static void do_alphaover_key(bNode *UNUSED(node), float *out, float *src, float *over, float *fac) -{ - - if (over[3]<=0.0f) { - copy_v4_v4(out, src); - } - else if (fac[0]==1.0f && over[3]>=1.0f) { - copy_v4_v4(out, over); - } - else { - float premul= fac[0]*over[3]; - float mul= 1.0f - premul; - - out[0] = (mul*src[0]) + premul*over[0]; - out[1] = (mul*src[1]) + premul*over[1]; - out[2] = (mul*src[2]) + premul*over[2]; - out[3] = (mul*src[3]) + fac[0]*over[3]; - } -} - -/* result will be still premul, but the over part is premulled */ -static void do_alphaover_mixed(bNode *node, float *out, float *src, float *over, float *fac) -{ - - if (over[3]<=0.0f) { - copy_v4_v4(out, src); - } - else if (fac[0]==1.0f && over[3]>=1.0f) { - copy_v4_v4(out, over); - } - else { - NodeTwoFloats *ntf= node->storage; - float addfac= 1.0f - ntf->x + over[3]*ntf->x; - float premul= fac[0]*addfac; - float mul= 1.0f - fac[0]*over[3]; - - out[0] = (mul*src[0]) + premul*over[0]; - out[1] = (mul*src[1]) + premul*over[1]; - out[2] = (mul*src[2]) + premul*over[2]; - out[3] = (mul*src[3]) + fac[0]*over[3]; - } -} - - -static void node_composit_exec_alphaover(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - /* stack order in: col col */ - /* stack order out: col */ - if (out[0]->hasoutput==0) - return; - - /* input no image? then only color operation */ - if (in[1]->data==NULL && in[2]->data==NULL) { - do_alphaover_premul(node, out[0]->vec, in[1]->vec, in[2]->vec, in[0]->vec); - } - else { - /* make output size of input image */ - CompBuf *cbuf= in[1]->data?in[1]->data:in[2]->data; - CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */ - NodeTwoFloats *ntf= node->storage; - - if (ntf->x != 0.0f) - composit3_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[2]->data, in[2]->vec, in[0]->data, in[0]->vec, do_alphaover_mixed, CB_RGBA, CB_RGBA, CB_VAL); - else if (node->custom1) - composit3_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[2]->data, in[2]->vec, in[0]->data, in[0]->vec, do_alphaover_key, CB_RGBA, CB_RGBA, CB_VAL); - else - composit3_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[2]->data, in[2]->vec, in[0]->data, in[0]->vec, do_alphaover_premul, CB_RGBA, CB_RGBA, CB_VAL); - - out[0]->data= stackbuf; - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_alphaover_init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { node->storage= MEM_callocN(sizeof(NodeTwoFloats), "NodeTwoFloats"); @@ -154,9 +57,6 @@ void register_node_type_cmp_alphaover(bNodeTreeType *ttype) node_type_size(&ntype, 80, 40, 120); node_type_init(&ntype, node_alphaover_init); node_type_storage(&ntype, "NodeTwoFloats", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_alphaover); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c b/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c index 7674ace42a3..34cc9a90615 100644 --- a/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c +++ b/source/blender/nodes/composite/nodes/node_composite_bilateralblur.c @@ -43,221 +43,6 @@ static bNodeSocketTemplate cmp_node_bilateralblur_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -#define INIT_C3 \ - mean0 = 1; \ - mean1[0] = src[0]; \ - mean1[1] = src[1]; \ - mean1[2] = src[2]; \ - mean1[3] = src[3]; \ - (void)0 - -/* finds color distances */ -#define COLOR_DISTANCE_C3(c1, c2) \ - ((c1[0] - c2[0]) * (c1[0] - c2[0]) + \ - (c1[1] - c2[1]) * (c1[1] - c2[1]) + \ - (c1[2] - c2[2]) * (c1[2] - c2[2]) + \ - (c1[3] - c2[3]) * (c1[3] - c2[3])) - -/* this is the main kernel function for comparing color distances - * and adding them weighted to the final color */ -#define KERNEL_ELEMENT_C3(k) \ - temp_color = src + deltas[k]; \ - ref_color = ref + deltas[k]; \ - w = weight_tab[k] + \ - (double)COLOR_DISTANCE_C3(ref, ref_color) * i2sigma_color; \ - w = 1.0 / (w * w + 1); \ - mean0 += w; \ - mean1[0] += (double)temp_color[0] * w; \ - mean1[1] += (double)temp_color[1] * w; \ - mean1[2] += (double)temp_color[2] * w; \ - mean1[3] += (double)temp_color[3] * w; \ - (void)0 - -/* write blurred values to image */ -#define UPDATE_OUTPUT_C3 \ - mean0 = 1.0 / mean0; \ - dest[x * pix + 0] = mean1[0] * mean0; \ - dest[x * pix + 1] = mean1[1] * mean0; \ - dest[x * pix + 2] = mean1[2] * mean0; \ - dest[x * pix + 3] = mean1[3] * mean0; \ - (void)0 - -/* initializes deltas for fast access to neighbor pixels */ -#define INIT_3X3_DELTAS(deltas, step, nch) \ - ((deltas)[0] = (nch), (deltas)[1] = -(step) + (nch), \ - (deltas)[2] = -(step), (deltas)[3] = -(step) - (nch), \ - (deltas)[4] = -(nch), (deltas)[5] = (step) - (nch), \ - (deltas)[6] = (step), (deltas)[7] = (step) + (nch)); \ - (void)0 - - -/* code of this node was heavily inspired by the smooth function of opencv library. - * The main change is an optional image input */ -static void node_composit_exec_bilateralblur(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - NodeBilateralBlurData *nbbd = node->storage; - CompBuf *new, *source, *img = in[0]->data, *refimg = in[1]->data; - double mean0, w, i2sigma_color, i2sigma_space; - double mean1[4]; - double weight_tab[8]; - float *src, *dest, *ref, *temp_color, *ref_color; - float sigma_color, sigma_space; - int imgx, imgy, x, y, pix, i, step; - int deltas[8]; - short found_determinator = 0; - - if (img == NULL || out[0]->hasoutput == 0) - return; - - if (img->type != CB_RGBA) { - img = typecheck_compbuf(in[0]->data, CB_RGBA); - } - - imgx = img->x; - imgy = img->y; - pix = img->type; - step = pix * imgx; - - if (refimg) { - if (refimg->x == imgx && refimg->y == imgy) { - if (ELEM3(refimg->type, CB_VAL, CB_VEC2, CB_VEC3)) { - refimg = typecheck_compbuf(in[1]->data, CB_RGBA); - found_determinator = 1; - } - } - } - else { - refimg = img; - } - - /* allocs */ - source = dupalloc_compbuf(img); - new = alloc_compbuf(imgx, imgy, pix, 1); - - /* accept image offsets from other nodes */ - new->xof = img->xof; - new->yof = img->yof; - - /* bilateral code properties */ - sigma_color = nbbd->sigma_color; - sigma_space = nbbd->sigma_space; - - i2sigma_color = 1.0f / (sigma_color * sigma_color); - i2sigma_space = 1.0f / (sigma_space * sigma_space); - - INIT_3X3_DELTAS(deltas, step, pix); - - weight_tab[0] = weight_tab[2] = weight_tab[4] = weight_tab[6] = i2sigma_space; - weight_tab[1] = weight_tab[3] = weight_tab[5] = weight_tab[7] = i2sigma_space * 2; - - /* iterations */ - for (i = 0; i < nbbd->iter; i++) { - src = source->rect; - ref = refimg->rect; - dest = new->rect; - /*goes through image, there are more loops for 1st/last line and all other lines*/ - /*kernel element accumulates surrounding colors, which are then written with the update_output function*/ - for (x = 0; x < imgx; x++, src += pix, ref += pix) { - INIT_C3; - - KERNEL_ELEMENT_C3(6); - - if (x > 0) { - KERNEL_ELEMENT_C3(5); - KERNEL_ELEMENT_C3(4); - } - - if (x < imgx - 1) { - KERNEL_ELEMENT_C3(7); - KERNEL_ELEMENT_C3(0); - } - - UPDATE_OUTPUT_C3; - } - - dest += step; - - for (y = 1; y < imgy - 1; y++, dest += step, src += pix, ref += pix) { - x = 0; - - INIT_C3; - - KERNEL_ELEMENT_C3(0); - KERNEL_ELEMENT_C3(1); - KERNEL_ELEMENT_C3(2); - KERNEL_ELEMENT_C3(6); - KERNEL_ELEMENT_C3(7); - - UPDATE_OUTPUT_C3; - - src += pix; - ref += pix; - - for (x = 1; x < imgx - 1; x++, src += pix, ref += pix) { - INIT_C3; - - KERNEL_ELEMENT_C3(0); - KERNEL_ELEMENT_C3(1); - KERNEL_ELEMENT_C3(2); - KERNEL_ELEMENT_C3(3); - KERNEL_ELEMENT_C3(4); - KERNEL_ELEMENT_C3(5); - KERNEL_ELEMENT_C3(6); - KERNEL_ELEMENT_C3(7); - - UPDATE_OUTPUT_C3; - } - - INIT_C3; - - KERNEL_ELEMENT_C3(2); - KERNEL_ELEMENT_C3(3); - KERNEL_ELEMENT_C3(4); - KERNEL_ELEMENT_C3(5); - KERNEL_ELEMENT_C3(6); - - UPDATE_OUTPUT_C3; - } - - for (x = 0; x < imgx; x++, src += pix, ref += pix) { - INIT_C3; - - KERNEL_ELEMENT_C3(2); - - if (x > 0) { - KERNEL_ELEMENT_C3(3); - KERNEL_ELEMENT_C3(4); - } - if (x < imgx - 1) { - KERNEL_ELEMENT_C3(1); - KERNEL_ELEMENT_C3(0); - } - - UPDATE_OUTPUT_C3; - } - - if (node->exec & NODE_BREAK) break; - - SWAP(CompBuf, *source, *new); - } - - if (img != in[0]->data) - free_compbuf(img); - - if (found_determinator == 1) { - if (refimg != in[1]->data) - free_compbuf(refimg); - } - - out[0]->data = source; - - free_compbuf(new); -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_bilateralblur(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { NodeBilateralBlurData *nbbd = MEM_callocN(sizeof(NodeBilateralBlurData), "node bilateral blur data"); @@ -275,9 +60,6 @@ void register_node_type_cmp_bilateralblur(bNodeTreeType *ttype) node_type_size(&ntype, 150, 120, 200); node_type_init(&ntype, node_composit_init_bilateralblur); node_type_storage(&ntype, "NodeBilateralBlurData", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_bilateralblur); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_blur.c b/source/blender/nodes/composite/nodes/node_composite_blur.c index eb7f7763afb..9d19f9667bc 100644 --- a/source/blender/nodes/composite/nodes/node_composite_blur.c +++ b/source/blender/nodes/composite/nodes/node_composite_blur.c @@ -44,686 +44,6 @@ static bNodeSocketTemplate cmp_node_blur_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static float *make_gausstab(int filtertype, int rad) -{ - float *gausstab, sum, val; - int i, n; - - n = 2 * rad + 1; - - gausstab = (float *) MEM_mallocN(n * sizeof(float), "gauss"); - - sum = 0.0f; - for (i = -rad; i <= rad; i++) { - val = RE_filter_value(filtertype, (float)i / (float)rad); - sum += val; - gausstab[i + rad] = val; - } - - sum = 1.0f / sum; - for (i = 0; i < n; i++) - gausstab[i] *= sum; - - return gausstab; -} - -static float *make_bloomtab(int rad) -{ - float *bloomtab, val; - int i, n; - - n = 2 * rad + 1; - - bloomtab = (float *) MEM_mallocN(n * sizeof(float), "bloom"); - - for (i = -rad; i <= rad; i++) { - val = powf(1.0f - fabsf((float)i) / ((float)rad), 4.0f); - bloomtab[i + rad] = val; - } - - return bloomtab; -} - -/* both input images of same type, either 4 or 1 channel */ -static void blur_single_image(bNode *node, CompBuf *new, CompBuf *img, float scale) -{ - NodeBlurData *nbd = node->storage; - CompBuf *work; - register float sum, val; - float rval, gval, bval, aval; - float *gausstab, *gausstabcent; - int rad, imgx = img->x, imgy = img->y; - int x, y, pix = img->type; - int i, bigstep; - float *src, *dest; - - /* helper image */ - work = alloc_compbuf(imgx, imgy, img->type, 1); /* allocs */ - - /* horizontal */ - if (nbd->sizex == 0) { - memcpy(work->rect, img->rect, sizeof(float) * img->type * imgx * imgy); - } - else { - rad = scale * (float)nbd->sizex; - if (rad > imgx / 2) - rad = imgx / 2; - else if (rad < 1) - rad = 1; - - gausstab = make_gausstab(nbd->filtertype, rad); - gausstabcent = gausstab + rad; - - for (y = 0; y < imgy; y++) { - float *srcd = img->rect + pix * (y * img->x); - - dest = work->rect + pix * (y * img->x); - - for (x = 0; x < imgx; x++) { - int minr = x - rad < 0 ? -x : -rad; - int maxr = x + rad > imgx ? imgx - x : rad; - - src = srcd + pix * (x + minr); - - sum = gval = rval = bval = aval = 0.0f; - for (i = minr; i < maxr; i++) { - val = gausstabcent[i]; - sum += val; - rval += val * (*src++); - if (pix == 4) { - gval += val * (*src++); - bval += val * (*src++); - aval += val * (*src++); - } - } - sum = 1.0f / sum; - *dest++ = rval * sum; - if (pix == 4) { - *dest++ = gval * sum; - *dest++ = bval * sum; - *dest++ = aval * sum; - } - } - if (node->exec & NODE_BREAK) - break; - } - - /* vertical */ - MEM_freeN(gausstab); - } - - if (nbd->sizey == 0) { - memcpy(new->rect, work->rect, sizeof(float) * img->type * imgx * imgy); - } - else { - rad = scale * (float)nbd->sizey; - if (rad > imgy / 2) - rad = imgy / 2; - else if (rad < 1) - rad = 1; - - gausstab = make_gausstab(nbd->filtertype, rad); - gausstabcent = gausstab + rad; - - bigstep = pix * imgx; - for (x = 0; x < imgx; x++) { - float *srcd = work->rect + pix * x; - - dest = new->rect + pix * x; - - for (y = 0; y < imgy; y++) { - int minr = y - rad < 0 ? -y : -rad; - int maxr = y + rad > imgy ? imgy - y : rad; - - src = srcd + bigstep * (y + minr); - - sum = gval = rval = bval = aval = 0.0f; - for (i = minr; i < maxr; i++) { - val = gausstabcent[i]; - sum += val; - rval += val * src[0]; - if (pix == 4) { - gval += val * src[1]; - bval += val * src[2]; - aval += val * src[3]; - } - src += bigstep; - } - sum = 1.0f / sum; - dest[0] = rval * sum; - if (pix == 4) { - dest[1] = gval * sum; - dest[2] = bval * sum; - dest[3] = aval * sum; - } - dest += bigstep; - } - if (node->exec & NODE_BREAK) - break; - } - MEM_freeN(gausstab); - } - - free_compbuf(work); -} - -/* reference has to be mapped 0-1, and equal in size */ -static void bloom_with_reference(CompBuf *new, CompBuf *img, CompBuf *UNUSED(ref), float UNUSED(fac), NodeBlurData *nbd) -{ - CompBuf *wbuf; - register float val; - float radxf, radyf; - float **maintabs; - float *gausstabx, *gausstabcenty; - float *gausstaby, *gausstabcentx; - int radx, rady, imgx = img->x, imgy = img->y; - int x, y; - int i, j; - float *src, *dest, *wb; - - wbuf = alloc_compbuf(imgx, imgy, CB_VAL, 1); - - /* horizontal */ - radx = (float)nbd->sizex; - if (radx > imgx / 2) - radx = imgx / 2; - else if (radx < 1) - radx = 1; - - /* vertical */ - rady = (float)nbd->sizey; - if (rady > imgy / 2) - rady = imgy / 2; - else if (rady < 1) - rady = 1; - - x = MAX2(radx, rady); - maintabs = MEM_mallocN(x * sizeof(void *), "gauss array"); - for (i = 0; i < x; i++) - maintabs[i] = make_bloomtab(i + 1); - - /* vars to store before we go */ -// refd= ref->rect; - src = img->rect; - - radxf = (float)radx; - radyf = (float)rady; - - for (y = 0; y < imgy; y++) { - for (x = 0; x < imgx; x++, src += 4) { //, refd++) { - -// int refradx= (int)(refd[0]*radxf); -// int refrady= (int)(refd[0]*radyf); - - int refradx = (int)(radxf * 0.3f * src[3] * (src[0] + src[1] + src[2])); - int refrady = (int)(radyf * 0.3f * src[3] * (src[0] + src[1] + src[2])); - - if (refradx > radx) refradx = radx; - else if (refradx < 1) refradx = 1; - if (refrady > rady) refrady = rady; - else if (refrady < 1) refrady = 1; - - if (refradx == 1 && refrady == 1) { - wb = wbuf->rect + (y * imgx + x); - dest = new->rect + 4 * (y * imgx + x); - wb[0] += 1.0f; - dest[0] += src[0]; - dest[1] += src[1]; - dest[2] += src[2]; - dest[3] += src[3]; - } - else { - int minxr = x - refradx < 0 ? -x : -refradx; - int maxxr = x + refradx > imgx ? imgx - x : refradx; - int minyr = y - refrady < 0 ? -y : -refrady; - int maxyr = y + refrady > imgy ? imgy - y : refrady; - - float *destd = new->rect + 4 * ( (y + minyr) * imgx + x + minxr); - float *wbufd = wbuf->rect + ( (y + minyr) * imgx + x + minxr); - - gausstabx = maintabs[refradx - 1]; - gausstabcentx = gausstabx + refradx; - gausstaby = maintabs[refrady - 1]; - gausstabcenty = gausstaby + refrady; - - for (i = minyr; i < maxyr; i++, destd += 4 * imgx, wbufd += imgx) { - dest = destd; - wb = wbufd; - for (j = minxr; j < maxxr; j++, dest += 4, wb++) { - - val = gausstabcenty[i] * gausstabcentx[j]; - wb[0] += val; - dest[0] += val * src[0]; - dest[1] += val * src[1]; - dest[2] += val * src[2]; - dest[3] += val * src[3]; - } - } - } - } - } - - x = imgx * imgy; - dest = new->rect; - wb = wbuf->rect; - while (x--) { - val = 1.0f / wb[0]; - dest[0] *= val; - dest[1] *= val; - dest[2] *= val; - dest[3] *= val; - wb++; - dest += 4; - } - - free_compbuf(wbuf); - - x = MAX2(radx, rady); - for (i = 0; i < x; i++) - MEM_freeN(maintabs[i]); - MEM_freeN(maintabs); - -} - -#if 0 -static float hexagon_filter(float fi, float fj) -{ - fi = fabs(fi); - fj = fabs(fj); - - if (fj > 0.33f) { - fj = (fj - 0.33f) / 0.66f; - if (fi + fj > 1.0f) - return 0.0f; - else - return 1.0f; - } - else return 1.0f; -} -#endif - -/* uses full filter, no horizontal/vertical optimize possible */ -/* both images same type, either 1 or 4 channels */ -static void bokeh_single_image(bNode *node, CompBuf *new, CompBuf *img, float fac) -{ - NodeBlurData *nbd = node->storage; - register float val; - float radxf, radyf; - float *gausstab, *dgauss; - int radx, rady, imgx = img->x, imgy = img->y; - int x, y, pix = img->type; - int i, j, n; - float *src = NULL, *dest, *srcd = NULL; - - /* horizontal */ - radxf = fac * (float)nbd->sizex; - if (radxf > imgx / 2.0f) - radxf = imgx / 2.0f; - else if (radxf < 1.0f) - radxf = 1.0f; - - /* vertical */ - radyf = fac * (float)nbd->sizey; - if (radyf > imgy / 2.0f) - radyf = imgy / 2.0f; - else if (radyf < 1.0f) - radyf = 1.0f; - - radx = ceil(radxf); - rady = ceil(radyf); - - n = (2 * radx + 1) * (2 * rady + 1); - - /* create a full filter image */ - gausstab = MEM_mallocN(sizeof(float) * n, "filter tab"); - dgauss = gausstab; - val = 0.0f; - for (j = -rady; j <= rady; j++) { - for (i = -radx; i <= radx; i++, dgauss++) { - float fj = (float)j / radyf; - float fi = (float)i / radxf; - float dist = sqrt(fj * fj + fi * fi); - - // *dgauss= hexagon_filter(fi, fj); - *dgauss = RE_filter_value(nbd->filtertype, dist); - - val += *dgauss; - } - } - - if (val != 0.0f) { - val = 1.0f / val; - for (j = n - 1; j >= 0; j--) - gausstab[j] *= val; - } - else gausstab[4] = 1.0f; - - for (y = -rady + 1; y < imgy + rady - 1; y++) { - - if (y <= 0) srcd = img->rect; - else if (y < imgy) srcd += pix * imgx; - else srcd = img->rect + pix * (imgy - 1) * imgx; - - for (x = -radx + 1; x < imgx + radx - 1; x++) { - int minxr = x - radx < 0 ? -x : -radx; - int maxxr = x + radx >= imgx ? imgx - x - 1 : radx; - int minyr = y - rady < 0 ? -y : -rady; - int maxyr = y + rady > imgy - 1 ? imgy - y - 1 : rady; - - float *destd = new->rect + pix * ( (y + minyr) * imgx + x + minxr); - float *dgausd = gausstab + (minyr + rady) * (2 * radx + 1) + minxr + radx; - - if (x <= 0) src = srcd; - else if (x < imgx) src += pix; - else src = srcd + pix * (imgx - 1); - - for (i = minyr; i <= maxyr; i++, destd += pix * imgx, dgausd += 2 * radx + 1) { - dest = destd; - dgauss = dgausd; - for (j = minxr; j <= maxxr; j++, dest += pix, dgauss++) { - val = *dgauss; - if (val != 0.0f) { - dest[0] += val * src[0]; - if (pix > 1) { - dest[1] += val * src[1]; - dest[2] += val * src[2]; - dest[3] += val * src[3]; - } - } - } - } - } - if (node->exec & NODE_BREAK) - break; - } - - MEM_freeN(gausstab); -} - - -/* reference has to be mapped 0-1, and equal in size */ -static void blur_with_reference(bNode *node, CompBuf *new, CompBuf *img, CompBuf *ref) -{ - NodeBlurData *nbd = node->storage; - CompBuf *blurbuf, *ref_use; - register float sum, val; - float rval, gval, bval, aval, radxf, radyf; - float **maintabs; - float *gausstabx, *gausstabcenty; - float *gausstaby, *gausstabcentx; - int radx, rady, imgx = img->x, imgy = img->y; - int x, y, pix = img->type; - int i, j; - float *src, *dest, *refd, *blurd; - float defcol[4] = {1.0f, 1.0f, 1.0f, 1.0f}; /* default color for compbuf_get_pixel */ - float proccol[4]; /* local color if compbuf is procedural */ - int refradx, refrady; - - if (ref->x != img->x || ref->y != img->y) - return; - - ref_use = typecheck_compbuf(ref, CB_VAL); - - /* trick is; we blur the reference image... but only works with clipped values*/ - blurbuf = alloc_compbuf(imgx, imgy, CB_VAL, 1); - blurbuf->xof = ref_use->xof; - blurbuf->yof = ref_use->yof; - blurd = blurbuf->rect; - refd = ref_use->rect; - for (x = imgx * imgy; x > 0; x--, refd++, blurd++) { - if (refd[0] < 0.0f) blurd[0] = 0.0f; - else if (refd[0] > 1.0f) blurd[0] = 1.0f; - else blurd[0] = refd[0]; - } - - blur_single_image(node, blurbuf, blurbuf, 1.0f); - - /* horizontal */ - radx = (float)nbd->sizex; - if (radx > imgx / 2) - radx = imgx / 2; - else if (radx < 1) - radx = 1; - - /* vertical */ - rady = (float)nbd->sizey; - if (rady > imgy / 2) - rady = imgy / 2; - else if (rady < 1) - rady = 1; - - x = MAX2(radx, rady); - maintabs = MEM_mallocN(x * sizeof(void *), "gauss array"); - for (i = 0; i < x; i++) - maintabs[i] = make_gausstab(nbd->filtertype, i + 1); - - dest = new->rect; - radxf = (float)radx; - radyf = (float)rady; - - for (y = 0; y < imgy; y++) { - for (x = 0; x < imgx; x++, dest += pix) { - refd = compbuf_get_pixel(blurbuf, defcol, proccol, x - blurbuf->xrad, y - blurbuf->yrad, blurbuf->xrad, blurbuf->yrad); - refradx = (int)(refd[0] * radxf); - refrady = (int)(refd[0] * radyf); - - if (refradx > radx) refradx = radx; - else if (refradx < 1) refradx = 1; - if (refrady > rady) refrady = rady; - else if (refrady < 1) refrady = 1; - - if (refradx == 1 && refrady == 1) { - src = img->rect + pix * (y * imgx + x); - if (pix == 1) - dest[0] = src[0]; - else - copy_v4_v4(dest, src); - } - else { - int minxr = x - refradx < 0 ? -x : -refradx; - int maxxr = x + refradx > imgx ? imgx - x : refradx; - int minyr = y - refrady < 0 ? -y : -refrady; - int maxyr = y + refrady > imgy ? imgy - y : refrady; - - float *srcd = img->rect + pix * ( (y + minyr) * imgx + x + minxr); - - gausstabx = maintabs[refradx - 1]; - gausstabcentx = gausstabx + refradx; - gausstaby = maintabs[refrady - 1]; - gausstabcenty = gausstaby + refrady; - - sum = gval = rval = bval = aval = 0.0f; - - for (i = minyr; i < maxyr; i++, srcd += pix * imgx) { - src = srcd; - for (j = minxr; j < maxxr; j++, src += pix) { - - val = gausstabcenty[i] * gausstabcentx[j]; - sum += val; - rval += val * src[0]; - if (pix > 1) { - gval += val * src[1]; - bval += val * src[2]; - aval += val * src[3]; - } - } - } - sum = 1.0f / sum; - dest[0] = rval * sum; - if (pix > 1) { - dest[1] = gval * sum; - dest[2] = bval * sum; - dest[3] = aval * sum; - } - } - } - if (node->exec & NODE_BREAK) - break; - } - - free_compbuf(blurbuf); - - x = MAX2(radx, rady); - for (i = 0; i < x; i++) - MEM_freeN(maintabs[i]); - MEM_freeN(maintabs); - - if (ref_use != ref) - free_compbuf(ref_use); -} - -static void node_composit_exec_blur(void *data, bNode *node, bNodeStack **in, bNodeStack **out) -{ - CompBuf *new, *img = in[0]->data; - NodeBlurData *nbd = node->storage; - - if (img == NULL) return; - - /* store image in size that is needed for absolute/relative conversions on ui level */ - nbd->image_in_width = img->x; - nbd->image_in_height = img->y; - - if (out[0]->hasoutput == 0) return; - - if (nbd->relative) { - if (nbd->aspect == CMP_NODE_BLUR_ASPECT_NONE) { - nbd->sizex = (int)(nbd->percentx * 0.01f * nbd->image_in_width); - nbd->sizey = (int)(nbd->percenty * 0.01f * nbd->image_in_height); - } - else if (nbd->aspect == CMP_NODE_BLUR_ASPECT_Y) { - nbd->sizex = (int)(nbd->percentx * 0.01f * nbd->image_in_width); - nbd->sizey = (int)(nbd->percenty * 0.01f * nbd->image_in_width); - } - else if (nbd->aspect == CMP_NODE_BLUR_ASPECT_X) { - nbd->sizex = (int)(nbd->percentx * 0.01f * nbd->image_in_height); - nbd->sizey = (int)(nbd->percenty * 0.01f * nbd->image_in_height); - } - } - - if (nbd->sizex == 0 && nbd->sizey == 0) { - new = pass_on_compbuf(img); - out[0]->data = new; - } - else if (nbd->filtertype == R_FILTER_FAST_GAUSS) { - if (in[1]->vec[0] < 0.001f) { /* time node inputs can be a tiny value */ - new = pass_on_compbuf(img); - } - else { - // TODO: can this be mapped with reference, too? - const float sx = ((float)nbd->sizex * in[1]->vec[0]) / 2.0f, sy = ((float)nbd->sizey * in[1]->vec[0]) / 2.0f; - int c; - - if ((img == NULL) || (out[0]->hasoutput == 0)) return; - - if (img->type == CB_VEC2) - new = typecheck_compbuf(img, CB_VAL); - else if (img->type == CB_VEC3) - new = typecheck_compbuf(img, CB_RGBA); - else - new = dupalloc_compbuf(img); - - if ((sx == sy) && (sx > 0.f)) { - for (c = 0; c < new->type; ++c) - IIR_gauss(new, sx, c, 3); - } - else { - if (sx > 0.f) { - for (c = 0; c < new->type; ++c) - IIR_gauss(new, sx, c, 1); - } - if (sy > 0.f) { - for (c = 0; c < new->type; ++c) - IIR_gauss(new, sy, c, 2); - } - } - } - out[0]->data = new; - } - else { - /* All non fast gauss blur methods */ - if (img->type == CB_VEC2 || img->type == CB_VEC3) { - img = typecheck_compbuf(in[0]->data, CB_RGBA); - } - - /* if fac input, we do it different */ - if (in[1]->data) { - CompBuf *gammabuf; - - /* make output size of input image */ - new = alloc_compbuf(img->x, img->y, img->type, 1); /* allocs */ - - /* accept image offsets from other nodes */ - new->xof = img->xof; - new->yof = img->yof; - - if (nbd->gamma) { - gammabuf = dupalloc_compbuf(img); - gamma_correct_compbuf(gammabuf, 0); - } - else gammabuf = img; - - blur_with_reference(node, new, gammabuf, in[1]->data); - - if (nbd->gamma) { - gamma_correct_compbuf(new, 1); - free_compbuf(gammabuf); - } - if (node->exec & NODE_BREAK) { - free_compbuf(new); - new = NULL; - } - out[0]->data = new; - } - else { - - if (in[1]->vec[0] <= 0.001f) { /* time node inputs can be a tiny value */ - new = pass_on_compbuf(img); - } - else { - CompBuf *gammabuf; - - /* make output size of input image */ - new = alloc_compbuf(img->x, img->y, img->type, 1); /* allocs */ - - /* accept image offsets from other nodes */ - new->xof = img->xof; - new->yof = img->yof; - - if (nbd->gamma) { - gammabuf = dupalloc_compbuf(img); - gamma_correct_compbuf(gammabuf, 0); - } - else gammabuf = img; - - if (nbd->bokeh) - bokeh_single_image(node, new, gammabuf, in[1]->vec[0]); - else if (1) - blur_single_image(node, new, gammabuf, in[1]->vec[0]); - else /* bloom experimental... */ - bloom_with_reference(new, gammabuf, NULL, in[1]->vec[0], nbd); - - if (nbd->gamma) { - gamma_correct_compbuf(new, 1); - free_compbuf(gammabuf); - } - if (node->exec & NODE_BREAK) { - free_compbuf(new); - new = NULL; - } - } - out[0]->data = new; - } - if (img != in[0]->data) - free_compbuf(img); - } - - generate_preview(data, node, out[0]->data); -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_blur(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { NodeBlurData *data = MEM_callocN(sizeof(NodeBlurData), "node blur data"); @@ -740,9 +60,6 @@ void register_node_type_cmp_blur(bNodeTreeType *ttype) node_type_size(&ntype, 120, 80, 200); node_type_init(&ntype, node_composit_init_blur); node_type_storage(&ntype, "NodeBlurData", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_blur); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_brightness.c b/source/blender/nodes/composite/nodes/node_composite_brightness.c index ecf572f59c7..719423edcf8 100644 --- a/source/blender/nodes/composite/nodes/node_composite_brightness.c +++ b/source/blender/nodes/composite/nodes/node_composite_brightness.c @@ -47,54 +47,6 @@ static bNodeSocketTemplate cmp_node_brightcontrast_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_brightnesscontrast(bNode *UNUSED(node), float *out, float *in, float *in_brightness, float *in_contrast) -{ - float i; - int c; - float a, b, v; - float brightness = (*in_brightness) / 100.0f; - float contrast = *in_contrast; - float delta = contrast / 200.0f; - a = 1.0f - delta * 2.0f; - /* - * The algorithm is by Werner D. Streidt - * (http://visca.com/ffactory/archives/5-99/msg00021.html) - * Extracted of OpenCV demhist.c - */ - if (contrast > 0) { - a = 1.0f / a; - b = a * (brightness - delta); - } - else { - delta *= -1; - b = a * (brightness + delta); - } - - for (c=0; c<3; c++) { - i = in[c]; - v = a*i + b; - out[c] = v; - } -} - -static void node_composit_exec_brightcontrast(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - if (out[0]->hasoutput==0) - return; - - if (in[0]->data) { - CompBuf *stackbuf, *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA); - stackbuf= dupalloc_compbuf(cbuf); - composit3_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, in[2]->data, in[2]->vec, do_brightnesscontrast, CB_RGBA, CB_VAL, CB_VAL); - out[0]->data = stackbuf; - if (cbuf != in[0]->data) - free_compbuf(cbuf); - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ void register_node_type_cmp_brightcontrast(bNodeTreeType *ttype) { @@ -103,9 +55,6 @@ void register_node_type_cmp_brightcontrast(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_BRIGHTCONTRAST, "Bright/Contrast", NODE_CLASS_OP_COLOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_brightcontrast_in, cmp_node_brightcontrast_out); node_type_size(&ntype, 140, 100, 320); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_brightcontrast); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_channelMatte.c b/source/blender/nodes/composite/nodes/node_composite_channelMatte.c index 40dbbbb8dca..a54a8507882 100644 --- a/source/blender/nodes/composite/nodes/node_composite_channelMatte.c +++ b/source/blender/nodes/composite/nodes/node_composite_channelMatte.c @@ -45,153 +45,6 @@ static bNodeSocketTemplate cmp_node_channel_matte_out[] ={ {-1, 0, ""} }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_normalized_rgba_to_ycca2(bNode *UNUSED(node), float *out, float *in) -{ - /*normalize to the range 0.0 to 1.0) */ - rgb_to_ycc(in[0], in[1], in[2], &out[0], &out[1], &out[2], BLI_YCC_ITU_BT601); - out[0]=(out[0])/255.0f; - out[1]=(out[1])/255.0f; - out[2]=(out[2])/255.0f; - out[3]=in[3]; -} - -static void do_normalized_ycca_to_rgba2(bNode *UNUSED(node), float *out, float *in) -{ - /*un-normalize the normalize from above */ - in[0]=in[0]*255.0f; - in[1]=in[1]*255.0f; - in[2]=in[2]*255.0f; - ycc_to_rgb(in[0], in[1], in[2], &out[0], &out[1], &out[2], BLI_YCC_ITU_BT601); - out[3]=in[3]; -} - - -static void do_channel_matte(bNode *node, float *out, float *in) -{ - NodeChroma *c=(NodeChroma *)node->storage; - float alpha=0.0; - - switch (c->algorithm) { - case 0: { /* Alpha=key_channel-limit channel */ - int key_channel=node->custom2-1; - int limit_channel=c->channel-1; - alpha=in[key_channel]-in[limit_channel]; - break; - } - case 1: { /* Alpha=G-MAX(R, B) */ - switch (node->custom2) { - case 1: - { - alpha=in[0]-MAX2(in[1], in[2]); - break; - } - case 2: - { - alpha=in[1]-MAX2(in[0], in[2]); - break; - } - case 3: - { - alpha=in[2]-MAX2(in[0], in[1]); - break; - } - default: - break; - } - break; - } - default: - break; - } - - /*flip because 0.0 is transparent, not 1.0*/ - alpha=1-alpha; - - /* test range*/ - if (alpha>c->t1) { - alpha=in[3]; /*whatever it was prior */ - } - else if (alpha<c->t2) { - alpha=0.0; - } - else {/*blend */ - alpha=(alpha-c->t2)/(c->t1-c->t2); - } - - - /* don't make something that was more transparent less transparent */ - if (alpha<in[3]) { - out[3]=alpha; - } - else { - out[3]=in[3]; - } -} - -static void node_composit_exec_channel_matte(void *data, bNode *node, bNodeStack **in, bNodeStack **out) -{ - CompBuf *cbuf; - CompBuf *outbuf; - - if (in[0]->hasinput==0) return; - if (in[0]->data==NULL) return; - if (out[0]->hasoutput==0 && out[1]->hasoutput==0) return; - - cbuf=typecheck_compbuf(in[0]->data, CB_RGBA); - - outbuf=dupalloc_compbuf(cbuf); - - /*convert to colorspace*/ - switch (node->custom1) { - case CMP_NODE_CHANNEL_MATTE_CS_RGB: - break; - case CMP_NODE_CHANNEL_MATTE_CS_HSV: /*HSV*/ - composit1_pixel_processor(node, outbuf, cbuf, in[1]->vec, do_rgba_to_hsva, CB_RGBA); - break; - case CMP_NODE_CHANNEL_MATTE_CS_YUV: /*YUV*/ - composit1_pixel_processor(node, outbuf, cbuf, in[1]->vec, do_rgba_to_yuva, CB_RGBA); - break; - case CMP_NODE_CHANNEL_MATTE_CS_YCC: /*YCC*/ - composit1_pixel_processor(node, outbuf, cbuf, in[1]->vec, do_normalized_rgba_to_ycca2, CB_RGBA); - break; - default: - break; - } - - /*use the selected channel information to do the key */ - composit1_pixel_processor(node, outbuf, outbuf, in[1]->vec, do_channel_matte, CB_RGBA); - - /*convert back to RGB colorspace in place*/ - switch (node->custom1) { - case CMP_NODE_CHANNEL_MATTE_CS_RGB: /*RGB*/ - break; - case CMP_NODE_CHANNEL_MATTE_CS_HSV: /*HSV*/ - composit1_pixel_processor(node, outbuf, outbuf, in[1]->vec, do_hsva_to_rgba, CB_RGBA); - break; - case CMP_NODE_CHANNEL_MATTE_CS_YUV: /*YUV*/ - composit1_pixel_processor(node, outbuf, outbuf, in[1]->vec, do_yuva_to_rgba, CB_RGBA); - break; - case CMP_NODE_CHANNEL_MATTE_CS_YCC: /*YCC*/ - composit1_pixel_processor(node, outbuf, outbuf, in[1]->vec, do_normalized_ycca_to_rgba2, CB_RGBA); - break; - default: - break; - } - - generate_preview(data, node, outbuf); - out[0]->data=outbuf; - if (out[1]->hasoutput) - out[1]->data=valbuf_from_rgbabuf(outbuf, CHAN_A); - - if (cbuf!=in[0]->data) - free_compbuf(cbuf); - -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_channel_matte(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma"); @@ -216,9 +69,6 @@ void register_node_type_cmp_channel_matte(bNodeTreeType *ttype) node_type_size(&ntype, 200, 80, 250); node_type_init(&ntype, node_composit_init_channel_matte); node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_channel_matte); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_chromaMatte.c b/source/blender/nodes/composite/nodes/node_composite_chromaMatte.c index f343f806d57..83c8bbc9a1e 100644 --- a/source/blender/nodes/composite/nodes/node_composite_chromaMatte.c +++ b/source/blender/nodes/composite/nodes/node_composite_chromaMatte.c @@ -45,136 +45,6 @@ static bNodeSocketTemplate cmp_node_chroma_out[] = { {-1, 0, ""} }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_rgba_to_ycca_normalized(bNode *UNUSED(node), float *out, float *in) -{ - rgb_to_ycc(in[0], in[1], in[2], &out[0], &out[1], &out[2], BLI_YCC_ITU_BT601); - - //normalize to 0..1.0 - out[0]=out[0]/255.0f; - out[1]=out[1]/255.0f; - out[2]=out[2]/255.0f; - - //rescale to -1.0..1.0 - out[0]=(out[0]*2.0f)-1.0f; - out[1]=(out[1]*2.0f)-1.0f; - out[2]=(out[2]*2.0f)-1.0f; - - // out[0]=((out[0])-16)/255.0; - // out[1]=((out[1])-128)/255.0; - // out[2]=((out[2])-128)/255.0; - out[3]=in[3]; -} - -static void do_ycca_to_rgba_normalized(bNode *UNUSED(node), float *out, float *in) -{ - /*un-normalize the normalize from above */ - in[0]=(in[0]+1.0f)/2.0f; - in[1]=(in[1]+1.0f)/2.0f; - in[2]=(in[2]+1.0f)/2.0f; - - in[0]=(in[0]*255.0f); - in[1]=(in[1]*255.0f); - in[2]=(in[2]*255.0f); - - // in[0]=(in[0]*255.0)+16; - // in[1]=(in[1]*255.0)+128; - // in[2]=(in[2]*255.0)+128; - ycc_to_rgb(in[0], in[1], in[2], &out[0], &out[1], &out[2], BLI_YCC_ITU_BT601); - out[3]=in[3]; -} - -static void do_chroma_key(bNode *node, float *out, float *in) -{ - NodeChroma *c; - float x, z, alpha; - float theta, beta, angle, angle2; - float kfg; - - c=node->storage; - - /* Algorithm from book "Video Demistified," does not include the spill reduction part */ - - /* find theta, the angle that the color space should be rotated based on key chroma values*/ - theta=atan2(c->key[2], c->key[1]); - - /*rotate the cb and cr into x/z space */ - x=in[1]*cosf(theta)+in[2]*sinf(theta); - z=in[2]*cosf(theta)-in[1]*sinf(theta); - - /*if within the acceptance angle */ - angle=c->t1; /* t1 is radians. */ - - /* if kfg is <0 then the pixel is outside of the key color */ - kfg= x-(fabsf(z)/tanf(angle/2.0f)); - - copy_v3_v3(out, in); - - if (kfg>0.0f) { /* found a pixel that is within key color */ - beta=atan2(z, x); - angle2=c->t2; /* t2 is radians. */ - - /* if beta is within the cutoff angle */ - if (fabsf(beta) < (angle2/2.0f)) { - alpha=0.0; - } - else { - alpha=1.0f-(kfg/c->fstrength); - } - - /* don't make something that was more transparent less transparent */ - if (alpha<in[3]) { - out[3]=alpha; - } - else { - out[3]=in[3]; - } - } - else { /* make pixel just as transparent as it was before */ - out[3]=in[3]; - } -} - -static void node_composit_exec_chroma_matte(void *data, bNode *node, bNodeStack **in, bNodeStack **out) -{ - CompBuf *cbuf; - CompBuf *chromabuf; - NodeChroma *c; - - if (in[0]->hasinput==0) return; - if (in[0]->data==NULL) return; - if (out[0]->hasoutput==0 && out[1]->hasoutput==0) return; - - cbuf= typecheck_compbuf(in[0]->data, CB_RGBA); - - chromabuf= dupalloc_compbuf(cbuf); - - c=node->storage; - - /*convert rgbbuf to normalized chroma space*/ - composit1_pixel_processor(node, chromabuf, cbuf, in[0]->vec, do_rgba_to_ycca_normalized, CB_RGBA); - /*convert key to normalized chroma color space */ - do_rgba_to_ycca_normalized(node, c->key, in[1]->vec); - - /*per pixel chroma key*/ - composit1_pixel_processor(node, chromabuf, chromabuf, in[0]->vec, do_chroma_key, CB_RGBA); - - /*convert back*/ - composit1_pixel_processor(node, chromabuf, chromabuf, in[0]->vec, do_ycca_to_rgba_normalized, CB_RGBA); - - out[0]->data= chromabuf; - if (out[1]->hasoutput) - out[1]->data= valbuf_from_rgbabuf(chromabuf, CHAN_A); - - generate_preview(data, node, chromabuf); - - if (cbuf!=in[0]->data) - free_compbuf(cbuf); -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_chroma_matte(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma"); @@ -195,9 +65,6 @@ void register_node_type_cmp_chroma_matte(bNodeTreeType *ttype) node_type_size(&ntype, 200, 80, 300); node_type_init(&ntype, node_composit_init_chroma_matte); node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_chroma_matte); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_colorMatte.c b/source/blender/nodes/composite/nodes/node_composite_colorMatte.c index 07a6647d976..1642d9283c3 100644 --- a/source/blender/nodes/composite/nodes/node_composite_colorMatte.c +++ b/source/blender/nodes/composite/nodes/node_composite_colorMatte.c @@ -45,77 +45,6 @@ static bNodeSocketTemplate cmp_node_color_out[] = { {-1, 0, ""} }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_color_key(bNode *node, float *out, float *in) -{ - float h_wrap; - NodeChroma *c; - c=node->storage; - - - copy_v3_v3(out, in); - - if ( - /* do hue last because it needs to wrap, and does some more checks */ - - /* sat */ (fabsf(in[1]-c->key[1]) < c->t2) && - /* val */ (fabsf(in[2]-c->key[2]) < c->t3) && - - /* multiply by 2 because it wraps on both sides of the hue, - * otherwise 0.5 would key all hue's */ - - /* hue */ ((h_wrap= 2.0f * fabsf(in[0]-c->key[0])) < c->t1 || (2.0f - h_wrap) < c->t1) - ) { - out[3]=0.0; /*make transparent*/ - } - - else { /*pixel is outside key color */ - out[3]=in[3]; /* make pixel just as transparent as it was before */ - } -} - -static void node_composit_exec_color_matte(void *data, bNode *node, bNodeStack **in, bNodeStack **out) -{ - CompBuf *cbuf; - CompBuf *colorbuf; - NodeChroma *c; - - if (in[0]->hasinput==0) return; - if (in[0]->data==NULL) return; - if (out[0]->hasoutput==0 && out[1]->hasoutput==0) return; - - cbuf= typecheck_compbuf(in[0]->data, CB_RGBA); - - colorbuf= dupalloc_compbuf(cbuf); - - c=node->storage; - - /*convert rgbbuf to hsv*/ - composit1_pixel_processor(node, colorbuf, cbuf, in[0]->vec, do_rgba_to_hsva, CB_RGBA); - - /*convert key to hsv*/ - do_rgba_to_hsva(node, c->key, in[1]->vec); - - - /*per pixel color key*/ - composit1_pixel_processor(node, colorbuf, colorbuf, in[0]->vec, do_color_key, CB_RGBA); - - /*convert back*/ - composit1_pixel_processor(node, colorbuf, colorbuf, in[0]->vec, do_hsva_to_rgba, CB_RGBA); - - out[0]->data= colorbuf; - if (out[1]->hasoutput) - out[1]->data= valbuf_from_rgbabuf(colorbuf, CHAN_A); - - generate_preview(data, node, colorbuf); - - if (cbuf!=in[0]->data) - free_compbuf(cbuf); -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_color_matte(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node color"); @@ -136,9 +65,6 @@ void register_node_type_cmp_color_matte(bNodeTreeType *ttype) node_type_size(&ntype, 200, 80, 300); node_type_init(&ntype, node_composit_init_color_matte); node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_color_matte); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_colorSpill.c b/source/blender/nodes/composite/nodes/node_composite_colorSpill.c index 44a5ac9e968..3679a65b238 100644 --- a/source/blender/nodes/composite/nodes/node_composite_colorSpill.c +++ b/source/blender/nodes/composite/nodes/node_composite_colorSpill.c @@ -43,281 +43,6 @@ static bNodeSocketTemplate cmp_node_color_spill_out[] = { {-1, 0, ""} }; -#ifdef WITH_COMPOSITOR_LEGACY - -#define AVG(a, b) ((a + b) / 2) - - -static void do_simple_spillmap_red(bNode *node, float* out, float *in) -{ - NodeColorspill *ncs; - ncs=node->storage; - out[0]=in[0]-( ncs->limscale * in[ncs->limchan] ); -} - -static void do_simple_spillmap_red_fac(bNode *node, float* out, float *in, float *fac) -{ - NodeColorspill *ncs; - ncs=node->storage; - - out[0] = *fac * (in[0]-( ncs->limscale * in[ncs->limchan])); -} - -static void do_simple_spillmap_green(bNode *node, float* out, float *in) -{ - NodeColorspill *ncs; - ncs=node->storage; - out[0]=in[1]-( ncs->limscale * in[ncs->limchan] ); -} - -static void do_simple_spillmap_green_fac(bNode *node, float* out, float *in, float *fac) -{ - NodeColorspill *ncs; - ncs=node->storage; - - out[0] = *fac * (in[1]-( ncs->limscale * in[ncs->limchan])); -} - -static void do_simple_spillmap_blue(bNode *node, float* out, float *in) -{ - NodeColorspill *ncs; - ncs=node->storage; - out[0]=in[2]-( ncs->limscale * in[ncs->limchan] ); -} - -static void do_simple_spillmap_blue_fac(bNode *node, float* out, float *in, float *fac) -{ - NodeColorspill *ncs; - ncs=node->storage; - - out[0] = *fac * (in[2]-( ncs->limscale * in[ncs->limchan])); -} - -static void do_average_spillmap_red(bNode *node, float* out, float *in) -{ - NodeColorspill *ncs; - ncs=node->storage; - out[0]=in[0]-(ncs->limscale * AVG(in[1], in[2]) ); -} - -static void do_average_spillmap_red_fac(bNode *node, float* out, float *in, float *fac) -{ - NodeColorspill *ncs; - ncs=node->storage; - - out[0] = *fac * (in[0]-(ncs->limscale * AVG(in[1], in[2]) )); -} - -static void do_average_spillmap_green(bNode *node, float* out, float *in) -{ - NodeColorspill *ncs; - ncs=node->storage; - out[0]=in[1]-(ncs->limscale * AVG(in[0], in[2]) ); -} - -static void do_average_spillmap_green_fac(bNode *node, float* out, float *in, float *fac) -{ - NodeColorspill *ncs; - ncs=node->storage; - - out[0] = *fac * (in[0]-(ncs->limscale * AVG(in[0], in[2]) )); -} - -static void do_average_spillmap_blue(bNode *node, float* out, float *in) -{ - NodeColorspill *ncs; - ncs=node->storage; - out[0]=in[2]-(ncs->limscale * AVG(in[0], in[1]) ); -} - -static void do_average_spillmap_blue_fac(bNode *node, float* out, float *in, float *fac) -{ - NodeColorspill *ncs; - ncs=node->storage; - - out[0] = *fac * (in[0]-(ncs->limscale * AVG(in[0], in[1]) )); -} - -static void do_apply_spillmap_red(bNode *node, float* out, float *in, float *map) -{ - NodeColorspill *ncs; - ncs=node->storage; - if (map[0]>0) { - out[0]=in[0]-(ncs->uspillr*map[0]); - out[1]=in[1]+(ncs->uspillg*map[0]); - out[2]=in[2]+(ncs->uspillb*map[0]); - } - else { - out[0]=in[0]; - out[1]=in[1]; - out[2]=in[2]; - } -} - -static void do_apply_spillmap_green(bNode *node, float* out, float *in, float *map) -{ - NodeColorspill *ncs; - ncs=node->storage; - if (map[0]>0) { - out[0]=in[0]+(ncs->uspillr*map[0]); - out[1]=in[1]-(ncs->uspillg*map[0]); - out[2]=in[2]+(ncs->uspillb*map[0]); - } - else { - out[0]=in[0]; - out[1]=in[1]; - out[2]=in[2]; - } -} - -static void do_apply_spillmap_blue(bNode *node, float* out, float *in, float *map) -{ - NodeColorspill *ncs; - ncs=node->storage; - if (map[0]>0) { - out[0]=in[0]+(ncs->uspillr*map[0]); - out[1]=in[1]+(ncs->uspillg*map[0]); - out[2]=in[2]-(ncs->uspillb*map[0]); - } - else { - out[0]=in[0]; - out[1]=in[1]; - out[2]=in[2]; - } -} - -static void node_composit_exec_color_spill(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - /* Originally based on the information from the book "The Art and Science of Digital Composition" and - * discussions from vfxtalk.com .*/ - CompBuf *cbuf; - /* CompBuf *mask; */ /* UNUSED */ - CompBuf *rgbbuf; - CompBuf *spillmap; - NodeColorspill *ncs; - ncs=node->storage; - - /* early out for missing connections */ - if (out[0]->hasoutput==0 ) return; - if (in[0]->hasinput==0) return; - if (in[0]->data==NULL) return; - - cbuf=typecheck_compbuf(in[0]->data, CB_RGBA); - /* mask= */ /* UNUSED */ typecheck_compbuf(in[1]->data, CB_VAL); - spillmap=alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); - rgbbuf=dupalloc_compbuf(cbuf); - - switch (node->custom1) { - case 1: /*red spill*/ - { - switch (node->custom2) { - case 0: /* simple limit */ - { - if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) { - composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_simple_spillmap_red, CB_RGBA); - } - else { - composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_simple_spillmap_red_fac, CB_RGBA, CB_VAL); - } - break; - } - case 1: /* average limit */ - { - if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) { - composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_average_spillmap_red, CB_RGBA); - } - else { - composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_average_spillmap_red_fac, CB_RGBA, CB_VAL); - } - break; - } - } - if (ncs->unspill==0) { - ncs->uspillr=1.0f; - ncs->uspillg=0.0f; - ncs->uspillb=0.0f; - } - composit2_pixel_processor(node, rgbbuf, cbuf, in[0]->vec, spillmap, NULL, do_apply_spillmap_red, CB_RGBA, CB_VAL); - break; - } - case 2: /*green spill*/ - { - switch (node->custom2) { - case 0: /* simple limit */ - { - if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) { - composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_simple_spillmap_green, CB_RGBA); - } - else { - composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_simple_spillmap_green_fac, CB_RGBA, CB_VAL); - } - break; - } - case 1: /* average limit */ - { - if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) { - composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_average_spillmap_green, CB_RGBA); - } - else { - composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_average_spillmap_green_fac, CB_RGBA, CB_VAL); - } - break; - } - } - if (ncs->unspill==0) { - ncs->uspillr=0.0f; - ncs->uspillg=1.0f; - ncs->uspillb=0.0f; - } - composit2_pixel_processor(node, rgbbuf, cbuf, in[0]->vec, spillmap, NULL, do_apply_spillmap_green, CB_RGBA, CB_VAL); - break; - } - case 3: /*blue spill*/ - { - switch (node->custom2) { - case 0: /* simple limit */ - { - if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) { - composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_simple_spillmap_blue, CB_RGBA); - } - else { - composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_simple_spillmap_blue_fac, CB_RGBA, CB_VAL); - } - break; - } - case 1: /* average limit */ - { - if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) { - composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_average_spillmap_blue, CB_RGBA); - } - else { - composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_average_spillmap_blue_fac, CB_RGBA, CB_VAL); - } - break; - } - } - if (ncs->unspill==0) { - ncs->uspillr=0.0f; - ncs->uspillg=0.0f; - ncs->uspillb=1.0f; - } - composit2_pixel_processor(node, rgbbuf, cbuf, in[0]->vec, spillmap, NULL, do_apply_spillmap_blue, CB_RGBA, CB_VAL); - break; - } - default: - break; - } - - out[0]->data=rgbbuf; - - if (cbuf!=in[0]->data) - free_compbuf(cbuf); - - free_compbuf(spillmap); -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_color_spill(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { NodeColorspill *ncs= MEM_callocN(sizeof(NodeColorspill), "node colorspill"); @@ -338,9 +63,6 @@ void register_node_type_cmp_color_spill(bNodeTreeType *ttype) node_type_size(&ntype, 140, 80, 200); node_type_init(&ntype, node_composit_init_color_spill); node_type_storage(&ntype, "NodeColorspill", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_color_spill); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_colorbalance.c b/source/blender/nodes/composite/nodes/node_composite_colorbalance.c index df49e537788..da9ce64d994 100644 --- a/source/blender/nodes/composite/nodes/node_composite_colorbalance.c +++ b/source/blender/nodes/composite/nodes/node_composite_colorbalance.c @@ -46,138 +46,6 @@ static bNodeSocketTemplate cmp_node_colorbalance_out[] = { {-1, 0, ""} }; -#ifdef WITH_COMPOSITOR_LEGACY - -/* this function implements ASC-CDL according to the spec at http://www.asctech.org/ - * Slope - * S = in * slope - * Offset - * O = S + offset - * = (in * slope) + offset - * Power - * out = Clamp(O) ^ power - * = Clamp((in * slope) + offset) ^ power - */ -DO_INLINE float colorbalance_cdl(float in, float offset, float power, float slope) -{ - float x = in * slope + offset; - - /* prevent NaN */ - CLAMP(x, 0.0f, 1.0f); - - return powf(x, power); -} - -/* note: lift_lgg is just 2-lift, gamma_inv is 1.0/gamma */ -DO_INLINE float colorbalance_lgg(float in, float lift_lgg, float gamma_inv, float gain) -{ - /* 1:1 match with the sequencer with linear/srgb conversions, the conversion isn't pretty - * but best keep it this way, since testing for durian shows a similar calculation - * without lin/srgb conversions gives bad results (over-saturated shadows) with colors - * slightly below 1.0. some correction can be done but it ends up looking bad for shadows or lighter tones - campbell */ - float x= (((linearrgb_to_srgb(in) - 1.0f) * lift_lgg) + 1.0f) * gain; - - /* prevent NaN */ - if (x < 0.f) x = 0.f; - - return powf(srgb_to_linearrgb(x), gamma_inv); -} - -static void do_colorbalance_cdl(bNode *node, float* out, float *in) -{ - NodeColorBalance *n= (NodeColorBalance *)node->storage; - - out[0] = colorbalance_cdl(in[0], n->lift[0], n->gamma[0], n->gain[0]); - out[1] = colorbalance_cdl(in[1], n->lift[1], n->gamma[1], n->gain[1]); - out[2] = colorbalance_cdl(in[2], n->lift[2], n->gamma[2], n->gain[2]); - out[3] = in[3]; -} - -static void do_colorbalance_cdl_fac(bNode *node, float* out, float *in, float *fac) -{ - NodeColorBalance *n= (NodeColorBalance *)node->storage; - const float mfac= 1.0f - *fac; - - out[0] = mfac*in[0] + *fac * colorbalance_cdl(in[0], n->lift[0], n->gamma[0], n->gain[0]); - out[1] = mfac*in[1] + *fac * colorbalance_cdl(in[1], n->lift[1], n->gamma[1], n->gain[1]); - out[2] = mfac*in[2] + *fac * colorbalance_cdl(in[2], n->lift[2], n->gamma[2], n->gain[2]); - out[3] = in[3]; -} - -static void do_colorbalance_lgg(bNode *node, float* out, float *in) -{ - NodeColorBalance *n= (NodeColorBalance *)node->storage; - - out[0] = colorbalance_lgg(in[0], n->lift_lgg[0], n->gamma_inv[0], n->gain[0]); - out[1] = colorbalance_lgg(in[1], n->lift_lgg[1], n->gamma_inv[1], n->gain[1]); - out[2] = colorbalance_lgg(in[2], n->lift_lgg[2], n->gamma_inv[2], n->gain[2]); - out[3] = in[3]; -} - -static void do_colorbalance_lgg_fac(bNode *node, float* out, float *in, float *fac) -{ - NodeColorBalance *n= (NodeColorBalance *)node->storage; - const float mfac= 1.0f - *fac; - - out[0] = mfac*in[0] + *fac * colorbalance_lgg(in[0], n->lift_lgg[0], n->gamma_inv[0], n->gain[0]); - out[1] = mfac*in[1] + *fac * colorbalance_lgg(in[1], n->lift_lgg[1], n->gamma_inv[1], n->gain[1]); - out[2] = mfac*in[2] + *fac * colorbalance_lgg(in[2], n->lift_lgg[2], n->gamma_inv[2], n->gain[2]); - out[3] = in[3]; -} - -static void node_composit_exec_colorbalance(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - CompBuf *cbuf= in[1]->data; - CompBuf *stackbuf; - - /* stack order input: fac, image */ - /* stack order output: image */ - if (out[0]->hasoutput==0) return; - - if (in[0]->vec[0] == 0.f && in[0]->data == NULL) { - out[0]->data = pass_on_compbuf(cbuf); - return; - } - - { - NodeColorBalance *n= (NodeColorBalance *)node->storage; - int c; - - for (c = 0; c < 3; c++) { - n->lift_lgg[c] = 2.0f - n->lift[c]; - n->gamma_inv[c] = (n->gamma[c] != 0.0f) ? 1.0f/n->gamma[c] : 1000000.0f; - } - } - - if (cbuf) { - stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* create output based on image input */ - - if (node->custom1 == 0) { - /* lift gamma gain */ - if ((in[0]->data==NULL) && (in[0]->vec[0] >= 1.f)) { - composit1_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, do_colorbalance_lgg, CB_RGBA); - } - else { - composit2_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[0]->data, in[0]->vec, do_colorbalance_lgg_fac, CB_RGBA, CB_VAL); - } - } - else { - /* offset/power/slope : ASC-CDL */ - if ((in[0]->data==NULL) && (in[0]->vec[0] >= 1.f)) { - composit1_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, do_colorbalance_cdl, CB_RGBA); - } - else { - composit2_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[0]->data, in[0]->vec, do_colorbalance_cdl_fac, CB_RGBA, CB_VAL); - } - - } - - out[0]->data=stackbuf; - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_colorbalance(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { NodeColorBalance *n= node->storage= MEM_callocN(sizeof(NodeColorBalance), "node colorbalance"); @@ -196,9 +64,6 @@ void register_node_type_cmp_colorbalance(bNodeTreeType *ttype) node_type_size(&ntype, 400, 200, 400); node_type_init(&ntype, node_composit_init_colorbalance); node_type_storage(&ntype, "NodeColorBalance", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_colorbalance); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_common.c b/source/blender/nodes/composite/nodes/node_composite_common.c index 10b81cdaaa0..7198798a152 100644 --- a/source/blender/nodes/composite/nodes/node_composite_common.c +++ b/source/blender/nodes/composite/nodes/node_composite_common.c @@ -32,187 +32,11 @@ #include "DNA_node_types.h" -#include "BKE_node.h" - #include "node_composite_util.h" #include "node_common.h" #include "node_exec.h" -#if 0 -static void PRINT_BUFFERS(bNodeTreeExec *exec) -{ - bNodeTree *ntree= exec->nodetree; - bNode *node; - bNodeSocket *sock; - bNodeStack *ns; - int i; - - printf("-------------- DEBUG --------------\n"); - for (sock=ntree->inputs.first, i=0; sock; sock=sock->next, ++i) { - ns = node_get_socket_stack(exec->stack, sock); - printf("%d. Tree Input %s", i, sock->name); - if (ns->external) - printf(" (external)"); - printf(": data=%p\n", ns->data); - } - for (sock=ntree->outputs.first, i=0; sock; sock=sock->next, ++i) { - ns = node_get_socket_stack(exec->stack, sock); - printf("%d. Tree Output %s", i, sock->name); - if (ns->external) - printf(" (external)"); - printf(": data=%p\n", ns->data); - } - for (node=ntree->nodes.first; node; node=node->next) { - printf("Node %s:\n", node->name); - for (sock=node->inputs.first, i=0; sock; sock=sock->next, ++i) { - ns = node_get_socket_stack(exec->stack, sock); - printf("\t%d. Input %s", i, sock->name); - if (ns->external) - printf(" (external)"); - printf(": data=%p\n", ns->data); - } - for (sock=node->outputs.first, i=0; sock; sock=sock->next, ++i) { - ns = node_get_socket_stack(exec->stack, sock); - printf("\t%d. Output %s", i, sock->name); - if (ns->external) - printf(" (external)"); - printf(": data=%p\n", ns->data); - } - } -} -#endif - -static void copy_stack(bNodeStack *to, bNodeStack *from) -{ - if (to != from) { - copy_v4_v4(to->vec, from->vec); - to->data = from->data; - to->datatype = from->datatype; - - /* tag as copy to prevent freeing */ - to->is_copy = 1; - } -} - -static void move_stack(bNodeStack *to, bNodeStack *from) -{ - if (to != from) { - copy_v4_v4(to->vec, from->vec); - to->data = from->data; - to->datatype = from->datatype; - to->is_copy = from->is_copy; - - zero_v4(from->vec); - from->data = NULL; - from->datatype = 0; - from->is_copy = 0; - } -} - -/**** GROUP ****/ - -static void *group_initexec(bNode *node) -{ - bNodeTree *ngroup = (bNodeTree *)node->id; - bNodeTreeExec *exec; - bNodeSocket *sock; - bNodeStack *ns; - - if (!ngroup) - return NULL; - - /* initialize the internal node tree execution */ - exec = ntreeCompositBeginExecTree(ngroup, 0); - - /* tag group outputs as external to prevent freeing */ - for (sock = ngroup->outputs.first; sock; sock = sock->next) { - if (!(sock->flag & SOCK_INTERNAL)) { - ns = node_get_socket_stack(exec->stack, sock); - ns->external = 1; - } - } - - return exec; -} - -static void group_freeexec(bNode *UNUSED(node), void *nodedata) -{ - bNodeTreeExec *gexec = (bNodeTreeExec *)nodedata; - - if (gexec) - ntreeCompositEndExecTree(gexec, 0); -} - -/* Copy inputs to the internal stack. - * This is a shallow copy, no buffers are duplicated here! - */ -static void group_copy_inputs(bNode *node, bNodeStack **in, bNodeStack *gstack) -{ - bNodeSocket *sock; - bNodeStack *ns; - int a; - for (sock=node->inputs.first, a=0; sock; sock=sock->next, ++a) { - if (sock->groupsock) { - ns = node_get_socket_stack(gstack, sock->groupsock); - copy_stack(ns, in[a]); - } - } -} - -/* Copy internal results to the external outputs. - */ -static void group_move_outputs(bNode *node, bNodeStack **out, bNodeStack *gstack) -{ - bNodeSocket *sock; - bNodeStack *ns; - int a; - for (sock = node->outputs.first, a = 0; sock; sock = sock->next, ++a) { - if (sock->groupsock) { - ns = node_get_socket_stack(gstack, sock->groupsock); - move_stack(out[a], ns); - } - } -} - -/* Free internal buffers */ -static void group_free_internal(bNodeTreeExec *gexec) -{ - bNodeStack *ns; - int i; - - for (i = 0, ns = gexec->stack; i < gexec->stacksize; ++i, ++ns) { - if (!ns->external && !ns->is_copy) { - if (ns->data) { -#ifdef WITH_COMPOSITOR_LEGACY - free_compbuf(ns->data); -#endif - ns->data = NULL; - } - } - } -} - -static void group_execute(void *data, int thread, struct bNode *node, void *nodedata, struct bNodeStack **in, struct bNodeStack **out) -{ - bNodeTreeExec *exec= (bNodeTreeExec *)nodedata; - - if (!exec) - return; - - /* XXX same behavior as trunk: all nodes inside group are executed. - * it's stupid, but just makes it work. compo redesign will do this better. - */ - { - bNode *inode; - for (inode=exec->nodetree->nodes.first; inode; inode=inode->next) - inode->need_exec = 1; - } - - group_copy_inputs(node, in, exec->stack); - ntreeExecNodes(exec, data, thread); - group_free_internal(exec); - group_move_outputs(node, out, exec->stack); -} +#include "BKE_node.h" void register_node_type_cmp_group(bNodeTreeType *ttype) { @@ -227,7 +51,7 @@ void register_node_type_cmp_group(bNodeTreeType *ttype) node_type_template(&ntype, node_group_template); node_type_update(&ntype, NULL, node_group_verify); node_type_group_edit(&ntype, node_group_edit_get, node_group_edit_set, node_group_edit_clear); - node_type_exec_new(&ntype, group_initexec, group_freeexec, group_execute); nodeRegisterType(ttype, &ntype); } + diff --git a/source/blender/nodes/composite/nodes/node_composite_composite.c b/source/blender/nodes/composite/nodes/node_composite_composite.c index cb932b6a8de..ca12b500e5b 100644 --- a/source/blender/nodes/composite/nodes/node_composite_composite.c +++ b/source/blender/nodes/composite/nodes/node_composite_composite.c @@ -39,65 +39,6 @@ static bNodeSocketTemplate cmp_node_composite_in[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -/* applies to render pipeline */ -static void node_composit_exec_composite(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out)) -{ - /* image assigned to output */ - /* stack order input sockets: col, alpha, z */ - - if (node->flag & NODE_DO_OUTPUT) { /* only one works on out */ - Scene *scene= (Scene *)node->id; - RenderData *rd= data; - - if (scene && (rd->scemode & R_DOCOMP)) { - Render *re= RE_GetRender(scene->id.name); - RenderResult *rr= RE_AcquireResultWrite(re); - if (rr) { - CompBuf *outbuf, *zbuf=NULL; - - if (rr->rectf) - MEM_freeN(rr->rectf); - outbuf= alloc_compbuf(rr->rectx, rr->recty, CB_RGBA, 1); - - if (in[1]->data==NULL) - composit1_pixel_processor(node, outbuf, in[0]->data, in[0]->vec, do_copy_rgba, CB_RGBA); - else - composit2_pixel_processor(node, outbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_copy_a_rgba, CB_RGBA, CB_VAL); - - if (in[2]->data) { - if (rr->rectz) - MEM_freeN(rr->rectz); - zbuf= alloc_compbuf(rr->rectx, rr->recty, CB_VAL, 1); - composit1_pixel_processor(node, zbuf, in[2]->data, in[2]->vec, do_copy_value, CB_VAL); - rr->rectz= zbuf->rect; - zbuf->malloc= 0; - free_compbuf(zbuf); - } - generate_preview(data, node, outbuf); - - /* we give outbuf to rr... */ - rr->rectf= outbuf->rect; - outbuf->malloc= 0; - free_compbuf(outbuf); - - /* signal for imageviewer to refresh (it converts to byte rects...) */ - BKE_image_signal(BKE_image_verify_viewer(IMA_TYPE_R_RESULT, "Render Result"), NULL, IMA_SIGNAL_FREE); - - RE_ReleaseResult(re); - return; - } - else - RE_ReleaseResult(re); - } - } - if (in[0]->data) - generate_preview(data, node, in[0]->data); -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_composite(bNodeTreeType *ttype) { static bNodeType ntype; @@ -105,9 +46,6 @@ void register_node_type_cmp_composite(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_COMPOSITE, "Composite", NODE_CLASS_OUTPUT, NODE_PREVIEW); node_type_socket_templates(&ntype, cmp_node_composite_in, NULL); node_type_size(&ntype, 80, 60, 200); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_composite); -#endif /* Do not allow muting for this node. */ node_type_internal_links(&ntype, NULL); diff --git a/source/blender/nodes/composite/nodes/node_composite_crop.c b/source/blender/nodes/composite/nodes/node_composite_crop.c index ad51fae1998..90d48a543ad 100644 --- a/source/blender/nodes/composite/nodes/node_composite_crop.c +++ b/source/blender/nodes/composite/nodes/node_composite_crop.c @@ -43,68 +43,6 @@ static bNodeSocketTemplate cmp_node_crop_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void node_composit_exec_crop(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - if (in[0]->data) { - NodeTwoXYs *ntxy= node->storage; - CompBuf *cbuf= in[0]->data; - CompBuf *stackbuf; - int x, y; - float *srcfp, *outfp; - rcti outputrect; - - if (node->custom2) { - ntxy->x1= cbuf->x* ntxy->fac_x1; - ntxy->x2= cbuf->x* ntxy->fac_x2; - ntxy->y1= cbuf->y* ntxy->fac_y1; - ntxy->y2= cbuf->y* ntxy->fac_y2; - } - - /* check input image size */ - if (cbuf->x <= ntxy->x1 + 1) - ntxy->x1= cbuf->x - 1; - - if (cbuf->y <= ntxy->y1 + 1) - ntxy->y1= cbuf->y - 1; - - if (cbuf->x <= ntxy->x2 + 1) - ntxy->x2= cbuf->x - 1; - - if (cbuf->y <= ntxy->y2 + 1) - ntxy->y2= cbuf->y - 1; - - /* figure out the minimums and maximums */ - outputrect.xmax=MAX2(ntxy->x1, ntxy->x2) + 1; - outputrect.xmin=MIN2(ntxy->x1, ntxy->x2); - outputrect.ymax=MAX2(ntxy->y1, ntxy->y2) + 1; - outputrect.ymin=MIN2(ntxy->y1, ntxy->y2); - - if (node->custom1) { - /* this option crops the image size too */ - stackbuf= get_cropped_compbuf(&outputrect, cbuf->rect, cbuf->x, cbuf->y, cbuf->type); - } - else { - /* this option won't crop the size of the image as well */ - /* allocate memory for the output image */ - stackbuf = alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 1); - - /* select the cropped part of the image and set it to the output */ - for (y=outputrect.ymin; y<outputrect.ymax; y++) { - srcfp= cbuf->rect + (y * cbuf->x + outputrect.xmin) * cbuf->type; - outfp= stackbuf->rect + (y * stackbuf->x + outputrect.xmin) * stackbuf->type; - for (x=outputrect.xmin; x<outputrect.xmax; x++, outfp+= stackbuf->type, srcfp+= cbuf->type) - memcpy(outfp, srcfp, sizeof(float)*stackbuf->type); - } - } - - out[0]->data= stackbuf; - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_crop(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { NodeTwoXYs *nxy= MEM_callocN(sizeof(NodeTwoXYs), "node xy data"); @@ -124,9 +62,6 @@ void register_node_type_cmp_crop(bNodeTreeType *ttype) node_type_size(&ntype, 140, 100, 320); node_type_init(&ntype, node_composit_init_crop); node_type_storage(&ntype, "NodeTwoXYs", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_crop); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_curves.c b/source/blender/nodes/composite/nodes/node_composite_curves.c index a1999ec8887..9f40159baf3 100644 --- a/source/blender/nodes/composite/nodes/node_composite_curves.c +++ b/source/blender/nodes/composite/nodes/node_composite_curves.c @@ -41,25 +41,6 @@ static bNodeSocketTemplate cmp_node_time_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void node_composit_exec_curves_time(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out) -{ - RenderData *rd= data; - /* stack order output: fac */ - float fac= 0.0f; - - if (node->custom1 < node->custom2) - fac= (rd->cfra - node->custom1)/(float)(node->custom2-node->custom1); - - curvemapping_initialize(node->storage); - fac = curvemapping_evaluateF(node->storage, 0, fac); - - out[0]->vec[0] = CLAMPIS(fac, 0.0f, 1.0f); -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_curves_time(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { node->custom1= 1; @@ -76,9 +57,6 @@ void register_node_type_cmp_curve_time(bNodeTreeType *ttype) node_type_size(&ntype, 140, 100, 320); node_type_init(&ntype, node_composit_init_curves_time); node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_curves_time); -#endif nodeRegisterType(ttype, &ntype); } @@ -96,19 +74,6 @@ static bNodeSocketTemplate cmp_node_curve_vec_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void node_composit_exec_curve_vec(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - /* stack order input: vec */ - /* stack order output: vec */ - - curvemapping_initialize(node->storage); - curvemapping_evaluate_premulRGBF(node->storage, out[0]->vec, in[0]->vec); -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_curve_vec(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { node->storage= curvemapping_add(3, -1.0f, -1.0f, 1.0f, 1.0f); @@ -123,9 +88,6 @@ void register_node_type_cmp_curve_vec(bNodeTreeType *ttype) node_type_size(&ntype, 200, 140, 320); node_type_init(&ntype, node_composit_init_curve_vec); node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_curve_vec); -#endif nodeRegisterType(ttype, &ntype); } @@ -145,67 +107,6 @@ static bNodeSocketTemplate cmp_node_curve_rgb_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_curves(bNode *node, float *out, float *in) -{ - curvemapping_initialize(node->storage); - curvemapping_evaluate_premulRGBF(node->storage, out, in); - out[3] = in[3]; -} - -static void do_curves_fac(bNode *node, float *out, float *in, float *fac) -{ - curvemapping_initialize(node->storage); - - if (*fac >= 1.0f) - curvemapping_evaluate_premulRGBF(node->storage, out, in); - else if (*fac <= 0.0f) { - copy_v3_v3(out, in); - } - else { - float col[4], mfac= 1.0f-*fac; - curvemapping_evaluate_premulRGBF(node->storage, col, in); - out[0] = mfac*in[0] + *fac*col[0]; - out[1] = mfac*in[1] + *fac*col[1]; - out[2] = mfac*in[2] + *fac*col[2]; - } - out[3] = in[3]; -} - -static void node_composit_exec_curve_rgb(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - /* stack order input: fac, image, black level, white level */ - /* stack order output: image */ - - if (out[0]->hasoutput==0) - return; - - curvemapping_initialize(node->storage); - - /* input no image? then only color operation */ - if (in[1]->data==NULL) { - curvemapping_evaluateRGBF(node->storage, out[0]->vec, in[1]->vec); - } - else { - /* make output size of input image */ - CompBuf *cbuf= in[1]->data; - CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */ - - curvemapping_set_black_white(node->storage, in[2]->vec, in[3]->vec); - - if (in[0]->data==NULL && in[0]->vec[0] == 1.0f) - composit1_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, do_curves, CB_RGBA); - else - composit2_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[0]->data, in[0]->vec, do_curves_fac, CB_RGBA, CB_VAL); - - out[0]->data= stackbuf; - } - -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_curve_rgb(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f); @@ -220,9 +121,6 @@ void register_node_type_cmp_curve_rgb(bNodeTreeType *ttype) node_type_size(&ntype, 200, 140, 320); node_type_init(&ntype, node_composit_init_curve_rgb); node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_curve_rgb); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_defocus.c b/source/blender/nodes/composite/nodes/node_composite_defocus.c index 27ce0f7c4a7..88787cc869e 100644 --- a/source/blender/nodes/composite/nodes/node_composite_defocus.c +++ b/source/blender/nodes/composite/nodes/node_composite_defocus.c @@ -44,830 +44,6 @@ static bNodeSocketTemplate cmp_node_defocus_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -// line coefs for point sampling & scancon. data. -typedef struct BokehCoeffs { - float x0, y0, dx, dy; - float ls_x, ls_y; - float min_x, min_y, max_x, max_y; -} BokehCoeffs; - -// returns array of BokehCoeffs -// returns length of array in 'len_bkh', -// radius squared of inscribed disk in 'inradsq', needed in getWeight() test, -// BKH[8] is the data returned for the bokeh shape & bkh_b[4] is it's 2d bound -static void makeBokeh(char bktype, char ro, int* len_bkh, float* inradsq, BokehCoeffs BKH[8], float bkh_b[4]) -{ - float x0, x1, y0, y1, dx, dy, iDxy; - /* ro now is in radians. */ - float w = MAX2(1e-6f, ro); // never reported stangely enough, but a zero offset causes missing center line... - float wi = DEG2RADF(360.f/bktype); - int i, ov, nv; - - // bktype must be at least 3 & <= 8 - bktype = (bktype<3) ? 3 : ((bktype>8) ? 8 : bktype); - *len_bkh = bktype; - *inradsq = -1.f; - - for (i=0; i<(*len_bkh); i++) { - x0 = cos(w); - y0 = sin(w); - w += wi; - x1 = cos(w); - y1 = sin(w); - if ((*inradsq)<0.f) { - // radius squared of inscribed disk - float idx=(x0+x1)*0.5f, idy=(y0+y1)*0.5f; - *inradsq = idx*idx + idy*idy; - } - BKH[i].x0 = x0; - BKH[i].y0 = y0; - dx = x1-x0, dy = y1-y0; - iDxy = 1.f / sqrtf(dx*dx + dy*dy); - dx *= iDxy; - dy *= iDxy; - BKH[i].dx = dx; - BKH[i].dy = dy; - } - - // precalc scanconversion data - // bokeh bound, not transformed, for scanconvert - bkh_b[0] = bkh_b[2] = 1e10f; // xmin/ymin - bkh_b[1] = bkh_b[3] = -1e10f; // xmax/ymax - ov = (*len_bkh) - 1; - for (nv=0; nv<(*len_bkh); nv++) { - bkh_b[0] = MIN2(bkh_b[0], BKH[nv].x0); // xmin - bkh_b[1] = MAX2(bkh_b[1], BKH[nv].x0); // xmax - bkh_b[2] = MIN2(bkh_b[2], BKH[nv].y0); // ymin - bkh_b[3] = MAX2(bkh_b[3], BKH[nv].y0); // ymax - BKH[nv].min_x = MIN2(BKH[ov].x0, BKH[nv].x0); - BKH[nv].max_x = MAX2(BKH[ov].x0, BKH[nv].x0); - BKH[nv].min_y = MIN2(BKH[ov].y0, BKH[nv].y0); - BKH[nv].max_y = MAX2(BKH[ov].y0, BKH[nv].y0); - dy = BKH[nv].y0 - BKH[ov].y0; - BKH[nv].ls_x = (BKH[nv].x0 - BKH[ov].x0) / ((dy==0.f) ? 1.f : dy); - BKH[nv].ls_y = (BKH[nv].ls_x==0.f) ? 1.f : (1.f/BKH[nv].ls_x); - ov = nv; - } -} - -// test if u/v inside shape & returns weight value -static float getWeight(BokehCoeffs* BKH, int len_bkh, float u, float v, float rad, float inradsq) -{ - BokehCoeffs* bc = BKH; - float cdist, irad = (rad==0.f) ? 1.f : (1.f/rad); - u *= irad; - v *= irad; - - // early out test1: if point outside outer unit disk, it cannot be inside shape - cdist = u*u + v*v; - if (cdist>1.f) return 0.f; - - // early out test2: if point inside or on inner disk, point must be inside shape - if (cdist<=inradsq) return 1.f; - - while (len_bkh--) { - if ((bc->dy*(u - bc->x0) - bc->dx*(v - bc->y0)) > 0.f) return 0.f; - bc++; - } - return 1.f; -} - -// QMC.seq. for sampling, A.Keller, EMS -static float RI_vdC(unsigned int bits, unsigned int r) -{ - bits = ( bits << 16) | ( bits >> 16); - bits = ((bits & 0x00ff00ff) << 8) | ((bits & 0xff00ff00) >> 8); - bits = ((bits & 0x0f0f0f0f) << 4) | ((bits & 0xf0f0f0f0) >> 4); - bits = ((bits & 0x33333333) << 2) | ((bits & 0xcccccccc) >> 2); - bits = ((bits & 0x55555555) << 1) | ((bits & 0xaaaaaaaa) >> 1); - bits ^= r; - return (float)((double)bits / 4294967296.0); -} - -// single channel IIR gaussian filtering -// much faster than anything else, constant time independent of width -// should extend to multichannel and make this a node, could be useful -// note: this is an almost exact copy of 'IIR_gauss' -static void IIR_gauss_single(CompBuf *buf, float sigma) -{ - double q, q2, sc, cf[4], tsM[9], tsu[3], tsv[3]; - float *X, *Y, *W; - const unsigned int src_width = buf->x; - const unsigned int src_height = buf->y; - unsigned int i, x, y, sz; - - // single channel only for now - if (buf->type != CB_VAL) return; - - // <0.5 not valid, though can have a possibly useful sort of sharpening effect - if (sigma < 0.5f) return; - - // see "Recursive Gabor Filtering" by Young/VanVliet - // all factors here in double.prec. Required, because for single.prec it seems to blow up if sigma > ~200 - if (sigma >= 3.556f) - q = 0.9804f * (sigma - 3.556f) + 2.5091f; - else // sigma >= 0.5 - q = (0.0561f * sigma + 0.5784f) * sigma - 0.2568f; - q2 = q * q; - sc = (1.1668 + q) * (3.203729649 + (2.21566 + q) * q); - // no gabor filtering here, so no complex multiplies, just the regular coefs. - // all negated here, so as not to have to recalc Triggs/Sdika matrix - cf[1] = q * (5.788961737 + (6.76492 + 3.0 * q) * q) / sc; - cf[2] = -q2 * (3.38246 + 3.0 * q) / sc; - // 0 & 3 unchanged - cf[3] = q2 * q / sc; - cf[0] = 1.0 - cf[1] - cf[2] - cf[3]; - - // Triggs/Sdika border corrections, - // it seems to work, not entirely sure if it is actually totally correct, - // Besides J.M.Geusebroek's anigauss.c (see http://www.science.uva.nl/~mark), - // found one other implementation by Cristoph Lampert, - // but neither seem to be quite the same, result seems to be ok so far anyway. - // Extra scale factor here to not have to do it in filter, - // though maybe this had something to with the precision errors - sc = cf[0] / ((1.0 + cf[1] - cf[2] + cf[3]) * (1.0 - cf[1] - cf[2] - cf[3]) * (1.0 + cf[2] + (cf[1] - cf[3]) * cf[3])); - tsM[0] = sc * (-cf[3] * cf[1] + 1.0 - cf[3] * cf[3] - cf[2]); - tsM[1] = sc * ((cf[3] + cf[1]) * (cf[2] + cf[3] * cf[1])); - tsM[2] = sc * (cf[3] * (cf[1] + cf[3] * cf[2])); - tsM[3] = sc * (cf[1] + cf[3] * cf[2]); - tsM[4] = sc * (-(cf[2] - 1.0) * (cf[2] + cf[3] * cf[1])); - tsM[5] = sc * (-(cf[3] * cf[1] + cf[3] * cf[3] + cf[2] - 1.0) * cf[3]); - tsM[6] = sc * (cf[3] * cf[1] + cf[2] + cf[1] * cf[1] - cf[2] * cf[2]); - tsM[7] = sc * (cf[1] * cf[2] + cf[3] * cf[2] * cf[2] - cf[1] * cf[3] * cf[3] - cf[3] * cf[3] * cf[3] - cf[3] * cf[2] + cf[3]); - tsM[8] = sc * (cf[3] * (cf[1] + cf[3] * cf[2])); - -#define YVV(L) \ -{ \ - W[0] = cf[0] * X[0] + cf[1] * X[0] + cf[2] * X[0] + cf[3] * X[0]; \ - W[1] = cf[0] * X[1] + cf[1] * W[0] + cf[2] * X[0] + cf[3] * X[0]; \ - W[2] = cf[0] * X[2] + cf[1] * W[1] + cf[2] * W[0] + cf[3] * X[0]; \ - for (i = 3; i < L; i++) { \ - W[i] = cf[0] * X[i] + cf[1] * W[i - 1] + cf[2] * W[i - 2] + cf[3] * W[i - 3]; \ - } \ - tsu[0] = W[L - 1] - X[L - 1]; \ - tsu[1] = W[L - 2] - X[L - 1]; \ - tsu[2] = W[L - 3] - X[L - 1]; \ - tsv[0] = tsM[0] * tsu[0] + tsM[1] * tsu[1] + tsM[2] * tsu[2] + X[L - 1]; \ - tsv[1] = tsM[3] * tsu[0] + tsM[4] * tsu[1] + tsM[5] * tsu[2] + X[L - 1]; \ - tsv[2] = tsM[6] * tsu[0] + tsM[7] * tsu[1] + tsM[8] * tsu[2] + X[L - 1]; \ - Y[L - 1] = cf[0] * W[L - 1] + cf[1] * tsv[0] + cf[2] * tsv[1] + cf[3] * tsv[2]; \ - Y[L - 2] = cf[0] * W[L - 2] + cf[1] * Y[L - 1] + cf[2] * tsv[0] + cf[3] * tsv[1]; \ - Y[L - 3] = cf[0] * W[L - 3] + cf[1] * Y[L - 2] + cf[2] * Y[L - 1] + cf[3] * tsv[0]; \ - /* 'i != UINT_MAX' is really 'i >= 0', but necessary for unsigned int wrapping */ \ - for (i = L - 4; i != UINT_MAX; i--) { \ - Y[i] = cf[0] * W[i] + cf[1] * Y[i + 1] + cf[2] * Y[i + 2] + cf[3] * Y[i + 3]; \ - } \ -} (void)0 - - // intermediate buffers - sz = MAX2(src_width, src_height); - Y = MEM_callocN(sz * sizeof(float), "IIR_gauss Y buf"); - W = MEM_callocN(sz * sizeof(float), "IIR_gauss W buf"); - // H - for (y = 0; y < src_height; y++) { - X = &buf->rect[y * src_width]; - YVV(src_width); - memcpy(X, Y, sizeof(float) * src_width); - } - // V - X = MEM_callocN(src_height * sizeof(float), "IIR_gauss X buf"); - for (x = 0; x < src_width; x++) { - for (y = 0; y < src_height; y++) - X[y] = buf->rect[x + y * src_width]; - YVV(src_height); - for (y = 0; y < src_height; y++) - buf->rect[x + y * src_width] = Y[y]; - } - MEM_freeN(X); - - MEM_freeN(W); - MEM_freeN(Y); -#undef YVV -} - -static void defocus_blur(bNode *node, CompBuf *new, CompBuf *img, CompBuf *zbuf, float inpval, int no_zbuf) -{ - NodeDefocus *nqd = node->storage; - CompBuf *wts; // weights buffer - CompBuf *crad; // CoC radius buffer - BokehCoeffs BKH[8]; // bokeh shape data, here never > 8 pts. - float bkh_b[4] = {0}; // shape 2D bound - float cam_fdist=1, cam_invfdist=1, cam_lens=35; - float cam_sensor = DEFAULT_SENSOR_WIDTH; - float dof_sp, maxfgc, bk_hn_theta=0, inradsq=0; - int y, len_bkh=0, ydone = FALSE; - float aspect, aperture; - int minsz; - //float bcrad, nmaxc, scf; - - // get some required params from the current scene camera - // (ton) this is wrong, needs fixed - Scene *scene= (Scene*)node->id; - Object* camob = (scene)? scene->camera: NULL; - if (camob && camob->type==OB_CAMERA) { - Camera* cam = (Camera*)camob->data; - cam_lens = cam->lens; - cam_fdist = BKE_camera_object_dof_distance(camob); - cam_sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y); - if (cam_fdist == 0.0f) cam_fdist = 1e10f; /* if the dof is 0.0 then set it be be far away */ - cam_invfdist = 1.f / cam_fdist; - } - // guess work here.. best match with raytraced result - minsz = MIN2(img->x, img->y); - dof_sp = (float)minsz / ((cam_sensor / 2.0f) / cam_lens); // <- == aspect * MIN2(img->x, img->y) / tan(0.5f * fov); - - // aperture - aspect = (img->x > img->y) ? (img->y / (float)img->x) : (img->x / (float)img->y); - aperture = 0.5f * (cam_lens / (aspect * cam_sensor)) / nqd->fstop; - - // if not disk, make bokeh coefficients and other needed data - if (nqd->bktype!=0) { - makeBokeh(nqd->bktype, nqd->rotation, &len_bkh, &inradsq, BKH, bkh_b); - bk_hn_theta = 0.5 * nqd->bktype * sin(2.0 * M_PI / nqd->bktype); // weight factor - } - - // accumulated weights - wts = alloc_compbuf(img->x, img->y, CB_VAL, 1); - // CoC radius buffer - crad = alloc_compbuf(img->x, img->y, CB_VAL, 1); - - // if 'no_zbuf' flag set (which is always set if input is not an image), - // values are instead interpreted directly as blur radius values - if (no_zbuf) { - // to prevent *reaaallly* big radius values and impossible calculation times, - // limit the maximum to half the image width or height, whichever is smaller - float maxr = 0.5f*(float)MIN2(img->x, img->y); - unsigned int p; - - for (p=0; p<(unsigned int)(img->x*img->y); p++) { - crad->rect[p] = zbuf ? (zbuf->rect[p]*nqd->scale) : inpval; - // bug #5921, limit minimum - crad->rect[p] = MAX2(1e-5f, crad->rect[p]); - crad->rect[p] = MIN2(crad->rect[p], maxr); - // if maxblur!=0, limit maximum - if (nqd->maxblur != 0.f) crad->rect[p] = MIN2(crad->rect[p], nqd->maxblur); - } - } - else { - float wt; - - // actual zbuffer. - // separate foreground from background CoC's - // then blur background and blend in again with foreground, - // improves the 'blurred foreground overlapping in-focus midground' sharp boundary problem. - // wts buffer here used for blendmask - maxfgc = 0.f; // maximum foreground CoC radius - for (y=0; y<img->y; y++) { - unsigned int p = y * img->x; - int x; - for (x=0; x<img->x; x++) { - unsigned int px = p + x; - float iZ = (zbuf->rect[px]==0.f) ? 0.f : (1.f/zbuf->rect[px]); - crad->rect[px] = 0.5f*(aperture*(dof_sp*(cam_invfdist - iZ) - 1.f)); - if (crad->rect[px] <= 0.f) { - wts->rect[px] = 1.f; - crad->rect[px] = -crad->rect[px]; - if (crad->rect[px] > maxfgc) maxfgc = crad->rect[px]; - } - else crad->rect[px] = wts->rect[px] = 0; - } - } - - // fast blur... - // bug #6656 part 1, probably when previous node_composite.c was split into separate files, it was not properly updated - // to include recent cvs commits (well, at least not defocus node), so this part was missing... - wt = min_ff(nqd->maxblur, aperture * 128.0f); - IIR_gauss_single(crad, wt); - IIR_gauss_single(wts, wt); - - // bug #6656 part 2a, although foreground blur is not based anymore on closest object, - // the rescaling op below was still based on that anyway, and unlike the comment in below code, - // the difference is therefore not always that small at all... - // so for now commented out, not sure if this is going to cause other future problems, lets just wait and see... - /* - // find new maximum to scale it back to original - // (could skip this, not strictly necessary, in general, difference is quite small, but just in case...) - nmaxc = 0; - for (p=0; p<(img->x*img->y); p++) - if (crad->rect[p] > nmaxc) nmaxc = crad->rect[p]; - // rescale factor - scf = (nmaxc==0.f) ? 1.f: (maxfgc / nmaxc); - */ - - // and blend... - for (y=0; y<img->y; y++) { - unsigned int p = y*img->x; - int x; - - for (x=0; x<img->x; x++) { - unsigned px = p + x; - if (zbuf->rect[px]!=0.f) { - float iZ = (zbuf->rect[px]==0.f) ? 0.f : (1.f/zbuf->rect[px]); - - // bug #6656 part 2b, do not rescale - /* - bcrad = 0.5f*fabs(aperture*(dof_sp*(cam_invfdist - iZ) - 1.f)); - // scale crad back to original maximum and blend - crad->rect[px] = bcrad + wts->rect[px]*(scf*crad->rect[px] - bcrad); - */ - crad->rect[px] = 0.5f*fabsf(aperture*(dof_sp*(cam_invfdist - iZ) - 1.f)); - - // 'bug' #6615, limit minimum radius to 1 pixel, not really a solution, but somewhat mitigates the problem - crad->rect[px] = MAX2(crad->rect[px], 0.5f); - // if maxblur!=0, limit maximum - if (nqd->maxblur != 0.f) crad->rect[px] = MIN2(crad->rect[px], nqd->maxblur); - } - else crad->rect[px] = 0.f; - // clear weights for next part - wts->rect[px] = 0.f; - } - // esc set by main calling process - if (node->exec & NODE_BREAK) - break; - } - } - - //------------------------------------------------------------------ - // main loop -#ifndef __APPLE__ /* can crash on Mac, see bug #22856, disabled for now */ -#ifdef __INTEL_COMPILER /* icc doesn't like the compound statement -- internal error: 0_1506 */ - #pragma omp parallel for private(y) if (!nqd->preview) schedule(guided) -#else - #pragma omp parallel for private(y) if (!nqd->preview && img->y*img->x > 16384) schedule(guided) -#endif -#endif - for (y=0; y<img->y; y++) { - unsigned int p, p4, zp, cp, cp4; - float *ctcol, u, v, ct_crad, cR2=0; - int x, sx, sy; - - // some sort of visual feedback would be nice, or at least this text in the renderwin header - // but for now just print some info in the console every 8 scanlines. - #pragma omp critical - { - if (((ydone & 7)==0) || (ydone==(img->y-1))) { - if (G.background==0) { - printf("\rdefocus: Processing Line %d of %d ... ", ydone+1, img->y); - fflush(stdout); - } - } - - ydone++; - } - - // esc set by main calling process. don't break because openmp doesn't - // allow it, just continue and do nothing - if (node->exec & NODE_BREAK) - continue; - - zp = y * img->x; - for (x=0; x<img->x; x++) { - cp = zp + x; - cp4 = cp * img->type; - - // Circle of Confusion radius for current pixel - cR2 = ct_crad = crad->rect[cp]; - // skip if zero (border render) - if (ct_crad==0.f) { - // related to bug #5921, forgot output image when skipping 0 radius values - new->rect[cp4] = img->rect[cp4]; - if (new->type != CB_VAL) { - new->rect[cp4+1] = img->rect[cp4+1]; - new->rect[cp4+2] = img->rect[cp4+2]; - new->rect[cp4+3] = img->rect[cp4+3]; - } - continue; - } - cR2 *= cR2; - - // pixel color - ctcol = &img->rect[cp4]; - - if (!nqd->preview) { - int xs, xe, ys, ye; - float lwt, wtcol[4] = {0}, aacol[4] = {0}; - float wt; - - // shape weight - if (nqd->bktype==0) // disk - wt = 1.f/((float)M_PI*cR2); - else - wt = 1.f/(cR2*bk_hn_theta); - - // weighted color - wtcol[0] = wt*ctcol[0]; - if (new->type != CB_VAL) { - wtcol[1] = wt*ctcol[1]; - wtcol[2] = wt*ctcol[2]; - wtcol[3] = wt*ctcol[3]; - } - - // macro for background blur overlap test - // unfortunately, since this is done per pixel, - // it has a very significant negative impact on processing time... - // (eg. aa disk blur without test: 112 sec, vs with test: 176 sec...) - // iff center blur radius > threshold - // and if overlap pixel in focus, do nothing, else add color/weigbt - // (threshold constant is dependent on amount of blur) - #define TESTBG1(c, w) {\ - if (ct_crad > nqd->bthresh) {\ - if (crad->rect[p] > nqd->bthresh) {\ - new->rect[p] += c[0];\ - wts->rect[p] += w;\ - }\ - }\ - else {\ - new->rect[p] += c[0];\ - wts->rect[p] += w;\ - }\ - } - #define TESTBG4(c, w) {\ - if (ct_crad > nqd->bthresh) {\ - if (crad->rect[p] > nqd->bthresh) {\ - new->rect[p4] += c[0];\ - new->rect[p4+1] += c[1];\ - new->rect[p4+2] += c[2];\ - new->rect[p4+3] += c[3];\ - wts->rect[p] += w;\ - }\ - }\ - else {\ - new->rect[p4] += c[0];\ - new->rect[p4+1] += c[1];\ - new->rect[p4+2] += c[2];\ - new->rect[p4+3] += c[3];\ - wts->rect[p] += w;\ - }\ - } - if (nqd->bktype == 0) { - // Disk - int _x, i, j, di; - float Dj, T; - // AA pixel - #define AAPIX(a, b) {\ - int _ny = b;\ - if ((_ny >= 0) && (_ny < new->y)) {\ - int _nx = a;\ - if ((_nx >=0) && (_nx < new->x)) {\ - p = _ny*new->x + _nx;\ - if (new->type==CB_VAL) {\ - TESTBG1(aacol, lwt);\ - }\ - else {\ - p4 = p * new->type;\ - TESTBG4(aacol, lwt);\ - }\ - }\ - }\ - } - // circle scanline - #define CSCAN(a, b) {\ - int _ny = y + b;\ - if ((_ny >= 0) && (_ny < new->y)) {\ - xs = x - a + 1;\ - if (xs < 0) xs = 0;\ - xe = x + a;\ - if (xe > new->x) xe = new->x;\ - p = _ny*new->x + xs;\ - if (new->type==CB_VAL) {\ - for (_x=xs; _x<xe; _x++, p++) TESTBG1(wtcol, wt);\ - }\ - else {\ - p4 = p * new->type;\ - for (_x=xs; _x<xe; _x++, p++, p4+=new->type) TESTBG4(wtcol, wt);\ - }\ - }\ - } - - i = ceil(ct_crad); - j = 0; - T = 0; - while (i > j) { - Dj = sqrt(cR2 - j*j); - Dj -= floorf(Dj); - di = 0; - if (Dj > T) { i--; di = 1; } - T = Dj; - aacol[0] = wtcol[0]*Dj; - if (new->type != CB_VAL) { - aacol[1] = wtcol[1]*Dj; - aacol[2] = wtcol[2]*Dj; - aacol[3] = wtcol[3]*Dj; - } - lwt = wt*Dj; - if (i!=j) { - // outer pixels - AAPIX(x+j, y+i) - AAPIX(x+j, y-i) - if (j) { - AAPIX(x-j, y+i) // BL - AAPIX(x-j, y-i) // TL - } - if (di) { // only when i changed, interior of outer section - CSCAN(j, i) // bottom - CSCAN(j, -i) // top - } - } - // lower mid section - AAPIX(x+i, y+j) - if (i) AAPIX(x-i, y+j) - CSCAN(i, j) - // upper mid section - if (j) { - AAPIX(x+i, y-j) - if (i) AAPIX(x-i, y-j) - CSCAN(i, -j) - } - j++; - } - #undef CSCAN - #undef AAPIX - } - else { - // n-agonal - int ov, nv; - float mind, maxd, lwt; - ys = max_ii((int)floor(bkh_b[2] * ct_crad + y), 0); - ye = min_ii((int)ceil(bkh_b[3] * ct_crad + y), new->y - 1); - for (sy=ys; sy<=ye; sy++) { - float fxs = 1e10f, fxe = -1e10f; - float yf = (sy - y)/ct_crad; - int found = 0; - ov = len_bkh - 1; - mind = maxd = 0; - for (nv=0; nv<len_bkh; nv++) { - if ((BKH[nv].max_y >= yf) && (BKH[nv].min_y <= yf)) { - float tx = BKH[ov].x0 + BKH[nv].ls_x*(yf - BKH[ov].y0); - if (tx < fxs) { fxs = tx; mind = BKH[nv].ls_x; } - if (tx > fxe) { fxe = tx; maxd = BKH[nv].ls_x; } - if (++found == 2) break; - } - ov = nv; - } - if (found) { - fxs = fxs*ct_crad + x; - fxe = fxe*ct_crad + x; - xs = (int)floor(fxs), xe = (int)ceil(fxe); - // AA hack for first and last x pixel, near vertical edges only - if (fabsf(mind) <= 1.f) { - if ((xs >= 0) && (xs < new->x)) { - lwt = 1.f-(fxs - xs); - aacol[0] = wtcol[0]*lwt; - p = xs + sy*new->x; - if (new->type==CB_VAL) { - lwt *= wt; - TESTBG1(aacol, lwt); - } - else { - p4 = p * new->type; - aacol[1] = wtcol[1]*lwt; - aacol[2] = wtcol[2]*lwt; - aacol[3] = wtcol[3]*lwt; - lwt *= wt; - TESTBG4(aacol, lwt); - } - } - } - if (fabsf(maxd) <= 1.f) { - if ((xe >= 0) && (xe < new->x)) { - lwt = 1.f-(xe - fxe); - aacol[0] = wtcol[0]*lwt; - p = xe + sy*new->x; - if (new->type==CB_VAL) { - lwt *= wt; - TESTBG1(aacol, lwt); - } - else { - p4 = p * new->type; - aacol[1] = wtcol[1]*lwt; - aacol[2] = wtcol[2]*lwt; - aacol[3] = wtcol[3]*lwt; - lwt *= wt; - TESTBG4(aacol, lwt); - } - } - } - xs = MAX2(xs+1, 0); - xe = MIN2(xe, new->x); - // remaining interior scanline - p = sy*new->x + xs; - if (new->type==CB_VAL) { - for (sx=xs; sx<xe; sx++, p++) TESTBG1(wtcol, wt); - } - else { - p4 = p * new->type; - for (sx=xs; sx<xe; sx++, p++, p4+=new->type) TESTBG4(wtcol, wt); - } - } - } - - // now traverse in opposite direction, y scanlines, - // but this time only draw the near horizontal edges, - // applying same AA hack as above - xs = MAX2((int)floor(bkh_b[0]*ct_crad + x), 0); - xe = MIN2((int)ceil(bkh_b[1]*ct_crad + x), img->x - 1); - for (sx=xs; sx<=xe; sx++) { - float xf = (sx - x)/ct_crad; - float fys = 1e10f, fye = -1e10f; - int found = 0; - ov = len_bkh - 1; - mind = maxd = 0; - for (nv=0; nv<len_bkh; nv++) { - if ((BKH[nv].max_x >= xf) && (BKH[nv].min_x <= xf)) { - float ty = BKH[ov].y0 + BKH[nv].ls_y*(xf - BKH[ov].x0); - if (ty < fys) { fys = ty; mind = BKH[nv].ls_y; } - if (ty > fye) { fye = ty; maxd = BKH[nv].ls_y; } - if (++found == 2) break; - } - ov = nv; - } - if (found) { - fys = fys*ct_crad + y; - fye = fye*ct_crad + y; - // near horizontal edges only, line slope <= 1 - if (fabsf(mind) <= 1.f) { - int iys = (int)floor(fys); - if ((iys >= 0) && (iys < new->y)) { - lwt = 1.f - (fys - iys); - aacol[0] = wtcol[0]*lwt; - p = sx + iys*new->x; - if (new->type==CB_VAL) { - lwt *= wt; - TESTBG1(aacol, lwt); - } - else { - p4 = p * new->type; - aacol[1] = wtcol[1]*lwt; - aacol[2] = wtcol[2]*lwt; - aacol[3] = wtcol[3]*lwt; - lwt *= wt; - TESTBG4(aacol, lwt); - } - } - } - if (fabsf(maxd) <= 1.f) { - int iye = ceil(fye); - if ((iye >= 0) && (iye < new->y)) { - lwt = 1.f - (iye - fye); - aacol[0] = wtcol[0]*lwt; - p = sx + iye*new->x; - if (new->type==CB_VAL) { - lwt *= wt; - TESTBG1(aacol, lwt); - } - else { - p4 = p * new->type; - aacol[1] = wtcol[1]*lwt; - aacol[2] = wtcol[2]*lwt; - aacol[3] = wtcol[3]*lwt; - lwt *= wt; - TESTBG4(aacol, lwt); - } - } - } - } - } - - } - #undef TESTBG4 - #undef TESTBG1 - - } - else { - // sampled, simple rejection sampling here, good enough - unsigned int maxsam, s, ui = BLI_rand()*BLI_rand(); - float wcor, cpr = BLI_frand(), lwt; - if (no_zbuf) - maxsam = nqd->samples; // no zbuffer input, use sample value directly - else { - // depth adaptive sampling hack, the more out of focus, the more samples taken, 16 minimum. - maxsam = (int)(0.5f + nqd->samples*(1.f-(float)exp(-fabs(zbuf->rect[cp] - cam_fdist)))); - if (maxsam < 16) maxsam = 16; - } - wcor = 1.f/(float)maxsam; - for (s=0; s<maxsam; ++s) { - u = ct_crad*(2.f*RI_vdC(s, ui) - 1.f); - v = ct_crad*(2.f*(s + cpr)/(float)maxsam - 1.f); - sx = (int)(x + u + 0.5f), sy = (int)(y + v + 0.5f); - if ((sx<0) || (sx >= new->x) || (sy<0) || (sy >= new->y)) continue; - p = sx + sy*new->x; - p4 = p * new->type; - if (nqd->bktype==0) // Disk - lwt = ((u*u + v*v)<=cR2) ? wcor : 0.f; - else /* AA not needed here */ - lwt = wcor * getWeight(BKH, len_bkh, u, v, ct_crad, inradsq); - // prevent background bleeding onto in-focus pixels, user-option - if (ct_crad > nqd->bthresh) { // if center blur > threshold - if (crad->rect[p] > nqd->bthresh) { // if overlap pixel in focus, do nothing, else add color/weigbt - new->rect[p4] += ctcol[0] * lwt; - if (new->type != CB_VAL) { - new->rect[p4+1] += ctcol[1] * lwt; - new->rect[p4+2] += ctcol[2] * lwt; - new->rect[p4+3] += ctcol[3] * lwt; - } - wts->rect[p] += lwt; - } - } - else { - new->rect[p4] += ctcol[0] * lwt; - if (new->type != CB_VAL) { - new->rect[p4+1] += ctcol[1] * lwt; - new->rect[p4+2] += ctcol[2] * lwt; - new->rect[p4+3] += ctcol[3] * lwt; - } - wts->rect[p] += lwt; - } - } - } - - } - } - - // finally, normalize - for (y=0; y<new->y; y++) { - unsigned int p = y * new->x; - unsigned int p4 = p * new->type; - int x; - - for (x=0; x<new->x; x++) { - float dv = (wts->rect[p]==0.f) ? 1.f : (1.f/wts->rect[p]); - new->rect[p4] *= dv; - if (new->type!=CB_VAL) { - new->rect[p4+1] *= dv; - new->rect[p4+2] *= dv; - new->rect[p4+3] *= dv; - } - p++; - p4 += new->type; - } - } - - free_compbuf(crad); - free_compbuf(wts); - - printf("Done\n"); -} - - -static void node_composit_exec_defocus(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - CompBuf *new, *old, *zbuf_use = NULL, *img = in[0]->data, *zbuf = in[1]->data; - NodeDefocus *nqd = node->storage; - int no_zbuf = nqd->no_zbuf; - - if ((img==NULL) || (out[0]->hasoutput==0)) return; - - // if image not valid type or fstop==infinite (128), nothing to do, pass in to out - if (((img->type!=CB_RGBA) && (img->type!=CB_VAL)) || ((no_zbuf==0) && (nqd->fstop==128.f))) { - out[0]->data = pass_on_compbuf(img); - return; - } - - if (zbuf!=NULL) { - // Zbuf input, check to make sure, single channel, same size - // doesn't have to be actual zbuffer, but must be value type - if ((zbuf->x != img->x) || (zbuf->y != img->y)) { - // could do a scale here instead... - printf("Z input must be same size as image !\n"); - return; - } - zbuf_use = typecheck_compbuf(zbuf, CB_VAL); - } - else no_zbuf = 1; // no zbuffer input - - // ok, process - old = img; - if (nqd->gamco) { - // gamma correct, blender func is simplified, fixed value & RGBA only, - // should make user param. also depremul and premul afterwards, gamma - // correction can't work with premul alpha - old = dupalloc_compbuf(img); - premul_compbuf(old, 1); - gamma_correct_compbuf(old, 0); - premul_compbuf(old, 0); - } - - new = alloc_compbuf(old->x, old->y, old->type, 1); - defocus_blur(node, new, old, zbuf_use, in[1]->vec[0]*nqd->scale, no_zbuf); - - if (nqd->gamco) { - premul_compbuf(new, 1); - gamma_correct_compbuf(new, 1); - premul_compbuf(new, 0); - free_compbuf(old); - } - if (node->exec & NODE_BREAK) { - free_compbuf(new); - new= NULL; - } - out[0]->data = new; - if (zbuf_use && (zbuf_use != zbuf)) free_compbuf(zbuf_use); -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_defocus(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { /* qdn: defocus node */ @@ -894,9 +70,6 @@ void register_node_type_cmp_defocus(bNodeTreeType *ttype) node_type_size(&ntype, 150, 120, 200); node_type_init(&ntype, node_composit_init_defocus); node_type_storage(&ntype, "NodeDefocus", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_defocus); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_despeckle.c b/source/blender/nodes/composite/nodes/node_composite_despeckle.c index 9d47e4bc276..8fc97ef6a86 100644 --- a/source/blender/nodes/composite/nodes/node_composite_despeckle.c +++ b/source/blender/nodes/composite/nodes/node_composite_despeckle.c @@ -42,15 +42,6 @@ static bNodeSocketTemplate cmp_node_despeckle_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void node_composit_exec_despeckle(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **UNUSED(in), bNodeStack **UNUSED(out)) -{ - /* pass */ -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_despeckle(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { node->custom3 = 0.5f; @@ -65,9 +56,6 @@ void register_node_type_cmp_despeckle(bNodeTreeType *ttype) node_type_socket_templates(&ntype, cmp_node_despeckle_in, cmp_node_despeckle_out); node_type_size(&ntype, 80, 40, 120); node_type_init(&ntype, node_composit_init_despeckle); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_despeckle); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_diffMatte.c b/source/blender/nodes/composite/nodes/node_composite_diffMatte.c index 014b72d3c60..bcfd9dd768b 100644 --- a/source/blender/nodes/composite/nodes/node_composite_diffMatte.c +++ b/source/blender/nodes/composite/nodes/node_composite_diffMatte.c @@ -45,91 +45,6 @@ static bNodeSocketTemplate cmp_node_diff_matte_out[] = { {-1, 0, ""} }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_diff_matte(bNode *node, float *outColor, float *inColor1, float *inColor2) -{ - NodeChroma *c= (NodeChroma *)node->storage; - float tolerance=c->t1; - float fper=c->t2; - /* get falloff amount over tolerance size */ - float falloff=(1.0f-fper) * tolerance; - float difference; - float alpha; - float maxInputAlpha; - - /* average together the distances */ - difference= fabs(inColor2[0]-inColor1[0]) + - fabs(inColor2[1]-inColor1[1]) + - fabs(inColor2[2]-inColor1[2]); - difference=difference/3.0f; - - copy_v3_v3(outColor, inColor1); - - if (difference <= tolerance) { - if (difference <= falloff) { - alpha = 0.0f; - } - else { - /* alpha as percent (distance / tolerance), each modified by falloff amount (in pixels)*/ - alpha=(difference-falloff)/(tolerance-falloff); - } - - /*only change if more transparent than either image */ - maxInputAlpha=max_ff(inColor1[3], inColor2[3]); - if (alpha < maxInputAlpha) { - /*clamp*/ - if (alpha < 0.0f) alpha = 0.0f; - if (alpha > 1.0f) alpha = 1.0f; - outColor[3] = alpha; - } - else { /* leave as before */ - outColor[3]=maxInputAlpha; - } - } -} - -static void node_composit_exec_diff_matte(void *data, bNode *node, bNodeStack **in, bNodeStack **out) -{ - CompBuf *outbuf= NULL; - CompBuf *imbuf1= NULL; - CompBuf *imbuf2= NULL; - /* NodeChroma *c; */ /* UNUSED */ - - /*is anything connected?*/ - if (out[0]->hasoutput==0 && out[1]->hasoutput==0) return; - - /*must have an image imput*/ - if (in[0]->data==NULL) return; - - - imbuf1=typecheck_compbuf(in[0]->data, CB_RGBA); - - /* if there's an image, use that, if not use the color */ - if (in[1]->data) { - imbuf2=typecheck_compbuf(in[1]->data, CB_RGBA); - } - - /* c=node->storage; */ /* UNUSED */ - outbuf=dupalloc_compbuf(imbuf1); - - /* note, processor gets a keyvals array passed on as buffer constant */ - composit2_pixel_processor(node, outbuf, imbuf1, in[0]->vec, imbuf2, in[1]->vec, do_diff_matte, CB_RGBA, CB_RGBA); - - out[0]->data=outbuf; - if (out[1]->hasoutput) - out[1]->data=valbuf_from_rgbabuf(outbuf, CHAN_A); - generate_preview(data, node, outbuf); - - if (imbuf1!=in[0]->data) - free_compbuf(imbuf1); - - if (imbuf2!=in[1]->data) - free_compbuf(imbuf2); -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_diff_matte(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma"); @@ -147,9 +62,6 @@ void register_node_type_cmp_diff_matte(bNodeTreeType *ttype) node_type_size(&ntype, 200, 80, 250); node_type_init(&ntype, node_composit_init_diff_matte); node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_diff_matte); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_dilate.c b/source/blender/nodes/composite/nodes/node_composite_dilate.c index 9787c9f7145..0238914a9d1 100644 --- a/source/blender/nodes/composite/nodes/node_composite_dilate.c +++ b/source/blender/nodes/composite/nodes/node_composite_dilate.c @@ -44,112 +44,6 @@ static bNodeSocketTemplate cmp_node_dilateerode_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void morpho_dilate(CompBuf *cbuf) -{ - int x, y; - float *p, *rectf = cbuf->rect; - - for (y = 0; y < cbuf->y; y++) { - for (x = 0; x < cbuf->x - 1; x++) { - p = rectf + cbuf->x * y + x; - *p = max_ff(*p, *(p + 1)); - } - } - - for (y = 0; y < cbuf->y; y++) { - for (x = cbuf->x - 1; x >= 1; x--) { - p = rectf + cbuf->x * y + x; - *p = max_ff(*p, *(p - 1)); - } - } - - for (x = 0; x < cbuf->x; x++) { - for (y = 0; y < cbuf->y - 1; y++) { - p = rectf + cbuf->x * y + x; - *p = max_ff(*p, *(p + cbuf->x)); - } - } - - for (x = 0; x < cbuf->x; x++) { - for (y = cbuf->y - 1; y >= 1; y--) { - p = rectf + cbuf->x * y + x; - *p = max_ff(*p, *(p - cbuf->x)); - } - } -} - -static void morpho_erode(CompBuf *cbuf) -{ - int x, y; - float *p, *rectf = cbuf->rect; - - for (y = 0; y < cbuf->y; y++) { - for (x = 0; x < cbuf->x - 1; x++) { - p = rectf + cbuf->x * y + x; - *p = min_ff(*p, *(p + 1)); - } - } - - for (y = 0; y < cbuf->y; y++) { - for (x = cbuf->x - 1; x >= 1; x--) { - p = rectf + cbuf->x * y + x; - *p = min_ff(*p, *(p - 1)); - } - } - - for (x = 0; x < cbuf->x; x++) { - for (y = 0; y < cbuf->y - 1; y++) { - p = rectf + cbuf->x * y + x; - *p = min_ff(*p, *(p + cbuf->x)); - } - } - - for (x = 0; x < cbuf->x; x++) { - for (y = cbuf->y - 1; y >= 1; y--) { - p = rectf + cbuf->x * y + x; - *p = min_ff(*p, *(p - cbuf->x)); - } - } - -} - -static void node_composit_exec_dilateerode(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - /* stack order in: mask */ - /* stack order out: mask */ - if (out[0]->hasoutput == 0) - return; - - /* input no image? then only color operation */ - if (in[0]->data == NULL) { - zero_v4(out[0]->vec); - } - else { - /* make output size of input image */ - CompBuf *cbuf = typecheck_compbuf(in[0]->data, CB_VAL); - CompBuf *stackbuf = dupalloc_compbuf(cbuf); - short i; - - if (node->custom2 > 0) { // positive, dilate - for (i = 0; i < node->custom2; i++) - morpho_dilate(stackbuf); - } - else if (node->custom2 < 0) { // negative, erode - for (i = 0; i > node->custom2; i--) - morpho_erode(stackbuf); - } - - if (cbuf != in[0]->data) - free_compbuf(cbuf); - - out[0]->data = stackbuf; - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_dilateerode(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { NodeDilateErode *data = MEM_callocN(sizeof(NodeDilateErode), "NodeDilateErode"); @@ -165,9 +59,6 @@ void register_node_type_cmp_dilateerode(bNodeTreeType *ttype) node_type_socket_templates(&ntype, cmp_node_dilateerode_in, cmp_node_dilateerode_out); node_type_size(&ntype, 130, 100, 320); node_type_init(&ntype, node_composit_init_dilateerode); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_dilateerode); -#endif node_type_storage(&ntype, "NodeDilateErode", node_free_standard_storage, node_copy_standard_storage); diff --git a/source/blender/nodes/composite/nodes/node_composite_directionalblur.c b/source/blender/nodes/composite/nodes/node_composite_directionalblur.c index a343315264d..ca32f37a32e 100644 --- a/source/blender/nodes/composite/nodes/node_composite_directionalblur.c +++ b/source/blender/nodes/composite/nodes/node_composite_directionalblur.c @@ -42,90 +42,6 @@ static bNodeSocketTemplate cmp_node_dblur_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static CompBuf *dblur(bNode *node, CompBuf *img, int iterations, int wrap, - float center_x, float center_y, float dist, float angle, float spin, float zoom) -{ - if ((dist != 0.f) || (spin != 0.f) || (zoom != 0.f)) { - void (*getpix)(CompBuf *, float, float, float *) = wrap ? qd_getPixelLerpWrap : qd_getPixelLerp; - const float a = angle; - const float itsc = 1.f / powf(2.f, (float)iterations); - float D; - float center_x_pix, center_y_pix; - float tx, ty; - float sc, rot; - CompBuf *tmp; - int i, j; - - tmp = dupalloc_compbuf(img); - - D = dist * sqrtf(img->x * img->x + img->y * img->y); - center_x_pix = center_x * img->x; - center_y_pix = center_y * img->y; - - tx = itsc * D * cosf(a); - ty = -itsc * D * sinf(a); - sc = itsc * zoom; - rot = itsc * spin; - - /* blur the image */ - for (i = 0; i < iterations; ++i) { - const float cs = cosf(rot), ss = sinf(rot); - const float isc = 1.f / (1.f + sc); - unsigned int x, y; - float col[4] = {0, 0, 0, 0}; - - for (y = 0; y < img->y; ++y) { - const float v = isc * (y - center_y_pix) + ty; - - for (x = 0; x < img->x; ++x) { - const float u = isc * (x - center_x_pix) + tx; - unsigned int p = (x + y * img->x) * img->type; - - getpix(tmp, cs * u + ss * v + center_x_pix, cs * v - ss * u + center_y_pix, col); - - /* mix img and transformed tmp */ - for (j = 0; j < 4; ++j) { - img->rect[p + j] = 0.5f * (img->rect[p + j] + col[j]); - } - } - } - - /* copy img to tmp */ - if (i != (iterations - 1)) - memcpy(tmp->rect, img->rect, sizeof(float) * img->x * img->y * img->type); - - /* double transformations */ - tx *= 2.f, ty *= 2.f; - sc *= 2.f, rot *= 2.f; - - if (node->exec & NODE_BREAK) break; - } - - free_compbuf(tmp); - } - - return img; -} - -static void node_composit_exec_dblur(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - NodeDBlurData *ndbd = node->storage; - CompBuf *new, *img = in[0]->data; - - if ((img == NULL) || (out[0]->hasoutput == 0)) return; - - if (img->type != CB_RGBA) - new = typecheck_compbuf(img, CB_RGBA); - else - new = dupalloc_compbuf(img); - - out[0]->data = dblur(node, new, ndbd->iter, ndbd->wrap, ndbd->center_x, ndbd->center_y, ndbd->distance, ndbd->angle, ndbd->spin, ndbd->zoom); -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_dblur(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { NodeDBlurData *ndbd = MEM_callocN(sizeof(NodeDBlurData), "node dblur data"); @@ -143,9 +59,6 @@ void register_node_type_cmp_dblur(bNodeTreeType *ttype) node_type_size(&ntype, 150, 120, 200); node_type_init(&ntype, node_composit_init_dblur); node_type_storage(&ntype, "NodeDBlurData", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_dblur); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_displace.c b/source/blender/nodes/composite/nodes/node_composite_displace.c index c07ad0a0c97..595596765a9 100644 --- a/source/blender/nodes/composite/nodes/node_composite_displace.c +++ b/source/blender/nodes/composite/nodes/node_composite_displace.c @@ -47,145 +47,6 @@ static bNodeSocketTemplate cmp_node_displace_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -/* minimum distance (in pixels) a pixel has to be displaced - * in order to take effect */ -#define DISPLACE_EPSILON 0.01f - -static void do_displace(bNode *node, CompBuf *stackbuf, CompBuf *cbuf, CompBuf *vecbuf, float *UNUSED(veccol), CompBuf *xbuf, CompBuf *ybuf, float *xscale, float *yscale) -{ - ImBuf *ibuf; - int x, y; - float p_dx, p_dy; /* main displacement in pixel space */ - float d_dx, d_dy; - float dxt, dyt; - float u, v; - float xs, ys; - float vec[3], vecdx[3], vecdy[3]; - float col[3]; - - ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0); - ibuf->rect_float= cbuf->rect; - - for (y=0; y < stackbuf->y; y++) { - for (x=0; x < stackbuf->x; x++) { - /* calc pixel coordinates */ - qd_getPixel(vecbuf, x-vecbuf->xof, y-vecbuf->yof, vec); - - if (xbuf) - qd_getPixel(xbuf, x-xbuf->xof, y-xbuf->yof, &xs); - else - xs = xscale[0]; - - if (ybuf) - qd_getPixel(ybuf, x-ybuf->xof, y-ybuf->yof, &ys); - else - ys = yscale[0]; - - /* clamp x and y displacement to triple image resolution - - * to prevent hangs from huge values mistakenly plugged in eg. z buffers */ - CLAMP(xs, -stackbuf->x*4, stackbuf->x*4); - CLAMP(ys, -stackbuf->y*4, stackbuf->y*4); - - p_dx = vec[0] * xs; - p_dy = vec[1] * ys; - - /* if no displacement, then just copy this pixel */ - if (fabsf(p_dx) < DISPLACE_EPSILON && fabsf(p_dy) < DISPLACE_EPSILON) { - qd_getPixel(cbuf, x-cbuf->xof, y-cbuf->yof, col); - qd_setPixel(stackbuf, x, y, col); - continue; - } - - /* displaced pixel in uv coords, for image sampling */ - u = (x - cbuf->xof - p_dx + 0.5f) / (float)stackbuf->x; - v = (y - cbuf->yof - p_dy + 0.5f) / (float)stackbuf->y; - - - /* calc derivatives */ - qd_getPixel(vecbuf, x-vecbuf->xof+1, y-vecbuf->yof, vecdx); - qd_getPixel(vecbuf, x-vecbuf->xof, y-vecbuf->yof+1, vecdy); - d_dx = vecdx[0] * xs; - d_dy = vecdy[1] * ys; - - /* clamp derivatives to minimum displacement distance in UV space */ - dxt = p_dx - d_dx; - dyt = p_dy - d_dy; - - dxt = signf(dxt)*max_ff(fabsf(dxt), DISPLACE_EPSILON)/(float)stackbuf->x; - dyt = signf(dyt)*max_ff(fabsf(dyt), DISPLACE_EPSILON)/(float)stackbuf->y; - - ibuf_sample(ibuf, u, v, dxt, dyt, col); - qd_setPixel(stackbuf, x, y, col); - - if (node->exec & NODE_BREAK) break; - } - - if (node->exec & NODE_BREAK) break; - } - IMB_freeImBuf(ibuf); - - -/* simple method for reference, linear interpolation */ -#if 0 - int x, y; - float dx, dy; - float u, v; - float vec[3]; - float col[3]; - - for (y=0; y < stackbuf->y; y++) { - for (x=0; x < stackbuf->x; x++) { - qd_getPixel(vecbuf, x, y, vec); - - dx = vec[0] * (xscale[0]); - dy = vec[1] * (yscale[0]); - - u = (x - dx + 0.5f) / (float)stackbuf->x; - v = (y - dy + 0.5f) / (float)stackbuf->y; - - qd_getPixelLerp(cbuf, u*cbuf->x - 0.5f, v*cbuf->y - 0.5f, col); - qd_setPixel(stackbuf, x, y, col); - } - } -#endif -} - - -static void node_composit_exec_displace(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - if (out[0]->hasoutput==0) - return; - - if (in[0]->data && in[1]->data) { - CompBuf *cbuf= in[0]->data; - CompBuf *vecbuf= in[1]->data; - CompBuf *xbuf= in[2]->data; - CompBuf *ybuf= in[3]->data; - CompBuf *stackbuf; - - cbuf= typecheck_compbuf(cbuf, CB_RGBA); - vecbuf= typecheck_compbuf(vecbuf, CB_VEC3); - xbuf= typecheck_compbuf(xbuf, CB_VAL); - ybuf= typecheck_compbuf(ybuf, CB_VAL); - - stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */ - - do_displace(node, stackbuf, cbuf, vecbuf, in[1]->vec, xbuf, ybuf, in[2]->vec, in[3]->vec); - - out[0]->data= stackbuf; - - - if (cbuf!=in[0]->data) - free_compbuf(cbuf); - if (vecbuf!=in[1]->data) - free_compbuf(vecbuf); - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_displace(bNodeTreeType *ttype) { static bNodeType ntype; @@ -193,9 +54,6 @@ void register_node_type_cmp_displace(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_DISPLACE, "Displace", NODE_CLASS_DISTORT, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_displace_in, cmp_node_displace_out); node_type_size(&ntype, 140, 100, 320); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_displace); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_distanceMatte.c b/source/blender/nodes/composite/nodes/node_composite_distanceMatte.c index 7e605865cd2..fffb85cca8e 100644 --- a/source/blender/nodes/composite/nodes/node_composite_distanceMatte.c +++ b/source/blender/nodes/composite/nodes/node_composite_distanceMatte.c @@ -45,147 +45,6 @@ static bNodeSocketTemplate cmp_node_distance_matte_out[] = { {-1, 0, ""} }; -#ifdef WITH_COMPOSITOR_LEGACY - -/* note, keyvals is passed on from caller as stack array */ -/* might have been nicer as temp struct though... */ -static void do_distance_matte(bNode *node, float *out, float *in) -{ - NodeChroma *c= (NodeChroma *)node->storage; - float tolerance=c->t1; - float fper=c->t2; - /* get falloff amount over tolerance size */ - float falloff=(1.0f-fper) * tolerance; - float distance; - float alpha; - - distance=sqrt((c->key[0]-in[0])*(c->key[0]-in[0]) + - (c->key[1]-in[1])*(c->key[1]-in[1]) + - (c->key[2]-in[2])*(c->key[2]-in[2])); - - copy_v3_v3(out, in); - - if (distance <= tolerance) { - if (distance <= falloff) { - alpha = 0.0f; - } - else { - /* alpha as percent (distance / tolerance), each modified by falloff amount (in pixels)*/ - alpha=(distance-falloff)/(tolerance-falloff); - } - - /*only change if more transparent than before */ - if (alpha < in[3]) { - /*clamp*/ - if (alpha < 0.0f) alpha = 0.0f; - if (alpha > 1.0f) alpha = 1.0f; - out[3]=alpha; - } - else { /* leave as before */ - out[3]=in[3]; - } - } -} - -static void do_chroma_distance_matte(bNode *node, float *out, float *in) -{ - NodeChroma *c= (NodeChroma *)node->storage; - float tolerance=c->t1; - float fper=c->t2; - /* get falloff amount over tolerance size */ - float falloff=(1.0f-fper) * tolerance; - float y_key, cb_key, cr_key; - float y_pix, cb_pix, cr_pix; - float distance; - float alpha; - - /*convert key to chroma colorspace */ - rgb_to_ycc(c->key[0], c->key[1], c->key[2], &y_key, &cb_key, &cr_key, BLI_YCC_JFIF_0_255); - /* normalize the values */ - cb_key=cb_key/255.0f; - cr_key=cr_key/255.0f; - - /*convert pixel to chroma colorspace */ - rgb_to_ycc(in[0], in[1], in[2], &y_pix, &cb_pix, &cr_pix, BLI_YCC_JFIF_0_255); - /*normalize the values */ - cb_pix=cb_pix/255.0f; - cr_pix=cr_pix/255.0f; - - distance=sqrt((cb_key-cb_pix)*(cb_key-cb_pix) + - (cr_key-cr_pix)*(cr_key-cr_pix)); - - copy_v3_v3(out, in); - - if (distance <= tolerance) { - if (distance <= falloff) { - alpha = 0.0f; - } - else { - /* alpha as percent (distance / tolerance), each modified by falloff amount (in pixels)*/ - alpha=(distance-falloff)/(tolerance-falloff); - } - - /*only change if more transparent than before */ - if (alpha < in[3]) { - /*clamp*/ - if (alpha < 0.0f) alpha = 0.0f; - if (alpha > 1.0f) alpha = 1.0f; - out[3]=alpha; - } - else { /* leave as before */ - out[3]=in[3]; - } - } -} - -static void node_composit_exec_distance_matte(void *data, bNode *node, bNodeStack **in, bNodeStack **out) -{ - /* - * Loosely based on the Sequencer chroma key plug-in, but enhanced to work in other color spaces and - * uses a different difference function (suggested in forums of vfxtalk.com). - */ - CompBuf *workbuf; - CompBuf *inbuf; - NodeChroma *c; - - /*is anything connected?*/ - if (out[0]->hasoutput==0 && out[1]->hasoutput==0) return; - /*must have an image imput*/ - if (in[0]->data==NULL) return; - - inbuf=typecheck_compbuf(in[0]->data, CB_RGBA); - - c=node->storage; - workbuf=dupalloc_compbuf(inbuf); - - /*use the input color*/ - c->key[0] = in[1]->vec[0]; - c->key[1] = in[1]->vec[1]; - c->key[2] = in[1]->vec[2]; - - /* work in RGB color space */ - if (c->channel == 1) { - /* note, processor gets a keyvals array passed on as buffer constant */ - composit1_pixel_processor(node, workbuf, workbuf, in[0]->vec, do_distance_matte, CB_RGBA); - } - /* work in YCbCr color space */ - else { - composit1_pixel_processor(node, workbuf, workbuf, in[0]->vec, do_chroma_distance_matte, CB_RGBA); - } - - - - out[0]->data=workbuf; - if (out[1]->hasoutput) - out[1]->data=valbuf_from_rgbabuf(workbuf, CHAN_A); - generate_preview(data, node, workbuf); - - if (inbuf!=in[0]->data) - free_compbuf(inbuf); -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_distance_matte(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma"); @@ -204,9 +63,6 @@ void register_node_type_cmp_distance_matte(bNodeTreeType *ttype) node_type_size(&ntype, 200, 80, 250); node_type_init(&ntype, node_composit_init_distance_matte); node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_distance_matte); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_doubleEdgeMask.c b/source/blender/nodes/composite/nodes/node_composite_doubleEdgeMask.c index 3c1e3ee443e..4f42c40ee13 100644 --- a/source/blender/nodes/composite/nodes/node_composite_doubleEdgeMask.c +++ b/source/blender/nodes/composite/nodes/node_composite_doubleEdgeMask.c @@ -42,1239 +42,6 @@ static bNodeSocketTemplate cmp_node_doubleedgemask_out[] = { { -1, 0, "" } // output socket array terminator }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_adjacentKeepBorders(unsigned int t, unsigned int rw, unsigned int *limask, unsigned int *lomask, unsigned int *lres, float *res, unsigned int *rsize) -{ - int x; - unsigned int isz=0; // inner edge size - unsigned int osz=0; // outer edge size - unsigned int gsz=0; // gradient fill area size - /* Test the four corners */ - /* upper left corner */ - x=t-rw+1; - // test if inner mask is filled - if (limask[x]) { - // test if pixel underneath, or to the right, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x-rw] && lomask[x-rw]) || (!limask[x+1] && lomask[x+1])) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - /* upper right corner */ - x=t; - // test if inner mask is filled - if (limask[x]) { - // test if pixel underneath, or to the left, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x-rw] && lomask[x-rw]) || (!limask[x-1] && lomask[x-1])) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - /* lower left corner */ - x=0; - // test if inner mask is filled - if (limask[x]) { - // test if pixel above, or to the right, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x+rw] && lomask[x+rw]) || (!limask[x+1] && lomask[x+1])) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - /* lower right corner */ - x=rw-1; - // test if inner mask is filled - if (limask[x]) { - // test if pixel above, or to the left, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x+rw] && lomask[x+rw]) || (!limask[x-1] && lomask[x-1])) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - - /* Test the TOP row of pixels in buffer, except corners */ - for (x= t-1; x>=(t-rw)+2; x--) { - // test if inner mask is filled - if (limask[x]) { - // test if pixel to the right, or to the left, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x-1] && lomask[x-1]) || (!limask[x+1] && lomask[x+1])) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - } - - /* Test the BOTTOM row of pixels in buffer, except corners */ - for (x= rw-2; x; x--) { - // test if inner mask is filled - if (limask[x]) { - // test if pixel to the right, or to the left, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x-1] && lomask[x-1]) || (!limask[x+1] && lomask[x+1])) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - } - /* Test the LEFT edge of pixels in buffer, except corners */ - for (x= t-(rw<<1)+1; x>=rw; x-=rw) { - // test if inner mask is filled - if (limask[x]) { - // test if pixel underneath, or above, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x-rw] && lomask[x-rw]) || (!limask[x+rw] && lomask[x+rw])) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - } - - /* Test the RIGHT edge of pixels in buffer, except corners */ - for (x= t-rw; x>rw; x-=rw) { - // test if inner mask is filled - if (limask[x]) { - // test if pixel underneath, or above, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x-rw] && lomask[x-rw]) || (!limask[x+rw] && lomask[x+rw])) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - } - - rsize[0]=isz; // fill in our return sizes for edges + fill - rsize[1]=osz; - rsize[2]=gsz; -} - -static void do_adjacentBleedBorders(unsigned int t, unsigned int rw, unsigned int *limask, unsigned int *lomask, unsigned int *lres, float *res, unsigned int *rsize) -{ - int x; - unsigned int isz=0; // inner edge size - unsigned int osz=0; // outer edge size - unsigned int gsz=0; // gradient fill area size - /* Test the four corners */ - /* upper left corner */ - x=t-rw+1; - // test if inner mask is filled - if (limask[x]) { - // test if pixel underneath, or to the right, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x-rw] && lomask[x-rw]) || (!limask[x+1] && lomask[x+1])) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x-rw] || !lomask[x+1]) { // test if outer mask is empty underneath or to the right - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x]=2; // flag pixel as gradient - } - } - /* upper right corner */ - x=t; - // test if inner mask is filled - if (limask[x]) { - // test if pixel underneath, or to the left, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x-rw] && lomask[x-rw]) || (!limask[x-1] && lomask[x-1])) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x-rw] || !lomask[x-1]) { // test if outer mask is empty underneath or to the left - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x]=2; // flag pixel as gradient - } - } - /* lower left corner */ - x=0; - // test if inner mask is filled - if (limask[x]) { - // test if pixel above, or to the right, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x+rw] && lomask[x+rw]) || (!limask[x+1] && lomask[x+1])) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x+rw] || !lomask[x+1]) { // test if outer mask is empty above or to the right - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x]=2; // flag pixel as gradient - } - } - /* lower right corner */ - x=rw-1; - // test if inner mask is filled - if (limask[x]) { - // test if pixel above, or to the left, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x+rw] && lomask[x+rw]) || (!limask[x-1] && lomask[x-1])) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x+rw] || !lomask[x-1]) { // test if outer mask is empty above or to the left - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x]=2; // flag pixel as gradient - } - } - /* Test the TOP row of pixels in buffer, except corners */ - for (x= t-1; x>=(t-rw)+2; x--) { - // test if inner mask is filled - if (limask[x]) { - // test if pixel to the left, or to the right, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x-1] && lomask[x-1]) || (!limask[x+1] && lomask[x+1])) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x-1] || !lomask[x+1]) { // test if outer mask is empty to the left or to the right - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x]=2; // flag pixel as gradient - } - } - } - - /* Test the BOTTOM row of pixels in buffer, except corners */ - for (x= rw-2; x; x--) { - // test if inner mask is filled - if (limask[x]) { - // test if pixel to the left, or to the right, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x-1] && lomask[x-1]) || (!limask[x+1] && lomask[x+1])) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x-1] || !lomask[x+1]) { // test if outer mask is empty to the left or to the right - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x]=2; // flag pixel as gradient - } - } - } - /* Test the LEFT edge of pixels in buffer, except corners */ - for (x= t-(rw<<1)+1; x>=rw; x-=rw) { - // test if inner mask is filled - if (limask[x]) { - // test if pixel underneath, or above, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x-rw] && lomask[x-rw]) || (!limask[x+rw] && lomask[x+rw])) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x-rw] || !lomask[x+rw]) { // test if outer mask is empty underneath or above - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x]=2; // flag pixel as gradient - } - } - } - - /* Test the RIGHT edge of pixels in buffer, except corners */ - for (x= t-rw; x>rw; x-=rw) { - // test if inner mask is filled - if (limask[x]) { - // test if pixel underneath, or above, are empty in the inner mask, - // but filled in the outer mask - if ((!limask[x-rw] && lomask[x-rw]) || (!limask[x+rw] && lomask[x+rw])) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x-rw] || !lomask[x+rw]) { // test if outer mask is empty underneath or above - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x]=2; // flag pixel as gradient - } - } - } - - rsize[0]=isz; // fill in our return sizes for edges + fill - rsize[1]=osz; - rsize[2]=gsz; -} - -static void do_allKeepBorders(unsigned int t, unsigned int rw, unsigned int *limask, unsigned int *lomask, unsigned int *lres, float *res, unsigned int *rsize) -{ - int x; - unsigned int isz=0; // inner edge size - unsigned int osz=0; // outer edge size - unsigned int gsz=0; // gradient fill area size - /* Test the four corners */ - /* upper left corner */ - x=t-rw+1; - // test if inner mask is filled - if (limask[x]) { - // test if the inner mask is empty underneath or to the right - if (!limask[x-rw] || !limask[x+1]) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - /* upper right corner */ - x=t; - // test if inner mask is filled - if (limask[x]) { - // test if the inner mask is empty underneath or to the left - if (!limask[x-rw] || !limask[x-1]) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - /* lower left corner */ - x=0; - // test if inner mask is filled - if (limask[x]) { - // test if inner mask is empty above or to the right - if (!limask[x+rw] || !limask[x+1]) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - /* lower right corner */ - x=rw-1; - // test if inner mask is filled - if (limask[x]) { - // test if inner mask is empty above or to the left - if (!limask[x+rw] || !limask[x-1]) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - - /* Test the TOP row of pixels in buffer, except corners */ - for (x= t-1; x>=(t-rw)+2; x--) { - // test if inner mask is filled - if (limask[x]) { - // test if inner mask is empty to the left or to the right - if (!limask[x-1] || !limask[x+1]) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - } - - /* Test the BOTTOM row of pixels in buffer, except corners */ - for (x= rw-2; x; x--) { - // test if inner mask is filled - if (limask[x]) { - // test if inner mask is empty to the left or to the right - if (!limask[x-1] || !limask[x+1]) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - } - /* Test the LEFT edge of pixels in buffer, except corners */ - for (x= t-(rw<<1)+1; x>=rw; x-=rw) { - // test if inner mask is filled - if (limask[x]) { - // test if inner mask is empty underneath or above - if (!limask[x-rw] || !limask[x+rw]) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - } - - /* Test the RIGHT edge of pixels in buffer, except corners */ - for (x= t-rw; x>rw; x-=rw) { - // test if inner mask is filled - if (limask[x]) { - // test if inner mask is empty underneath or above - if (!limask[x-rw] || !limask[x+rw]) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - } - - rsize[0]=isz; // fill in our return sizes for edges + fill - rsize[1]=osz; - rsize[2]=gsz; -} - -static void do_allBleedBorders(unsigned int t, unsigned int rw, unsigned int *limask, unsigned int *lomask, unsigned int *lres, float *res, unsigned int *rsize) -{ - int x; - unsigned int isz=0; // inner edge size - unsigned int osz=0; // outer edge size - unsigned int gsz=0; // gradient fill area size - /* Test the four corners */ - /* upper left corner */ - x=t-rw+1; - // test if inner mask is filled - if (limask[x]) { - // test if the inner mask is empty underneath or to the right - if (!limask[x-rw] || !limask[x+1]) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x-rw] || !lomask[x+1]) { // test if outer mask is empty underneath or to the right - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x]=2; // flag pixel as gradient - } - } - /* upper right corner */ - x=t; - // test if inner mask is filled - if (limask[x]) { - // test if the inner mask is empty underneath or to the left - if (!limask[x-rw] || !limask[x-1]) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x-rw] || !lomask[x-1]) { // test if outer mask is empty above or to the left - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x]=2; // flag pixel as gradient - } - } - /* lower left corner */ - x=0; - // test if inner mask is filled - if (limask[x]) { - // test if inner mask is empty above or to the right - if (!limask[x+rw] || !limask[x+1]) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x+rw] || !lomask[x+1]) { // test if outer mask is empty underneath or to the right - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x]=2; // flag pixel as gradient - } - } - /* lower right corner */ - x=rw-1; - // test if inner mask is filled - if (limask[x]) { - // test if inner mask is empty above or to the left - if (!limask[x+rw] || !limask[x-1]) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x+rw] || !lomask[x-1]) { // test if outer mask is empty underneath or to the left - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x]=2; // flag pixel as gradient - } - } - /* Test the TOP row of pixels in buffer, except corners */ - for (x= t-1; x>=(t-rw)+2; x--) { - // test if inner mask is filled - if (limask[x]) { - // test if inner mask is empty to the left or to the right - if (!limask[x-1] || !limask[x+1]) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x-1] || !lomask[x+1]) { // test if outer mask is empty to the left or to the right - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x]=2; // flag pixel as gradient - } - } - } - - /* Test the BOTTOM row of pixels in buffer, except corners */ - for (x= rw-2; x; x--) { - // test if inner mask is filled - if (limask[x]) { - // test if inner mask is empty to the left or to the right - if (!limask[x-1] || !limask[x+1]) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x-1] || !lomask[x+1]) { // test if outer mask is empty to the left or to the right - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x]=2; // flag pixel as gradient - } - } - } - /* Test the LEFT edge of pixels in buffer, except corners */ - for (x= t-(rw<<1)+1; x>=rw; x-=rw) { - // test if inner mask is filled - if (limask[x]) { - // test if inner mask is empty underneath or above - if (!limask[x-rw] || !limask[x+rw]) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x-rw] || !lomask[x+rw]) { // test if outer mask is empty underneath or above - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x]=2; // flag pixel as gradient - } - } - } - - /* Test the RIGHT edge of pixels in buffer, except corners */ - for (x= t-rw; x>rw; x-=rw) { - // test if inner mask is filled - if (limask[x]) { - // test if inner mask is empty underneath or above - if (!limask[x-rw] || !limask[x+rw]) { - isz++; // increment inner edge size - lres[x]=4; // flag pixel as inner edge - } - else { - res[x]=1.0f; // pixel is just part of inner mask, and it's not an edge - } - } - else if (lomask[x]) { // inner mask was empty, test if outer mask is filled - if (!lomask[x-rw] || !lomask[x+rw]) { // test if outer mask is empty underneath or above - osz++; // increment outer edge size - lres[x]=3; // flag pixel as outer edge - } - else { - gsz++; // increment the gradient pixel count - lres[x]=2; // flag pixel as gradient - } - } - } - - rsize[0]=isz; // fill in our return sizes for edges + fill - rsize[1]=osz; - rsize[2]=gsz; -} - -static void do_allEdgeDetection(unsigned int t, unsigned int rw, unsigned int *limask, unsigned int *lomask, unsigned int *lres, float *res, unsigned int *rsize, unsigned int in_isz, unsigned int in_osz, unsigned int in_gsz) -{ - int x; // x = pixel loop counter - int a; // a = pixel loop counter - int dx; // dx = delta x - int pix_prevRow; // pix_prevRow = pixel one row behind the one we are testing in a loop - int pix_nextRow; // pix_nextRow = pixel one row in front of the one we are testing in a loop - int pix_prevCol; // pix_prevCol = pixel one column behind the one we are testing in a loop - int pix_nextCol; // pix_nextCol = pixel one column in front of the one we are testing in a loop - /* Test all rows between the FIRST and LAST rows, excluding left and right edges */ - for (x= (t-rw)+1, dx=x-(rw-2); dx>rw; x-=rw, dx-=rw) { - a=x-2; - pix_prevRow=a+rw; - pix_nextRow=a-rw; - pix_prevCol=a+1; - pix_nextCol=a-1; - while (a>dx-2) { - if (!limask[a]) { // if the inner mask is empty - if (lomask[a]) { // if the outer mask is full - /* - * Next we test all 4 directions around the current pixel: next/prev/up/down - * The test ensures that the outer mask is empty and that the inner mask - * is also empty. If both conditions are true for any one of the 4 adjacent pixels - * then the current pixel is counted as being a true outer edge pixel. - */ - if ((!lomask[pix_nextCol] && !limask[pix_nextCol]) || - (!lomask[pix_prevCol] && !limask[pix_prevCol]) || - (!lomask[pix_nextRow] && !limask[pix_nextRow]) || - (!lomask[pix_prevRow] && !limask[pix_prevRow])) - { - in_osz++; // increment the outer boundary pixel count - lres[a]=3; // flag pixel as part of outer edge - } - else { // it's not a boundary pixel, but it is a gradient pixel - in_gsz++; // increment the gradient pixel count - lres[a]=2; // flag pixel as gradient - } - } - - } - else { - if (!limask[pix_nextCol] || !limask[pix_prevCol] || !limask[pix_nextRow] || !limask[pix_prevRow]) { - in_isz++; // increment the inner boundary pixel count - lres[a]=4; // flag pixel as part of inner edge - } - else { - res[a]=1.0f; // pixel is part of inner mask, but not at an edge - } - } - a--; - pix_prevRow--; - pix_nextRow--; - pix_prevCol--; - pix_nextCol--; - } - } - - rsize[0]=in_isz; // fill in our return sizes for edges + fill - rsize[1]=in_osz; - rsize[2]=in_gsz; -} - -static void do_adjacentEdgeDetection(unsigned int t, unsigned int rw, unsigned int *limask, unsigned int *lomask, unsigned int *lres, float *res, unsigned int *rsize, unsigned int in_isz, unsigned int in_osz, unsigned int in_gsz) -{ - int x; // x = pixel loop counter - int a; // a = pixel loop counter - int dx; // dx = delta x - int pix_prevRow; // pix_prevRow = pixel one row behind the one we are testing in a loop - int pix_nextRow; // pix_nextRow = pixel one row in front of the one we are testing in a loop - int pix_prevCol; // pix_prevCol = pixel one column behind the one we are testing in a loop - int pix_nextCol; // pix_nextCol = pixel one column in front of the one we are testing in a loop - /* Test all rows between the FIRST and LAST rows, excluding left and right edges */ - for (x= (t-rw)+1, dx=x-(rw-2); dx>rw; x-=rw, dx-=rw) { - a=x-2; - pix_prevRow=a+rw; - pix_nextRow=a-rw; - pix_prevCol=a+1; - pix_nextCol=a-1; - while (a>dx-2) { - if (!limask[a]) { // if the inner mask is empty - if (lomask[a]) { // if the outer mask is full - /* - * Next we test all 4 directions around the current pixel: next/prev/up/down - * The test ensures that the outer mask is empty and that the inner mask - * is also empty. If both conditions are true for any one of the 4 adjacent pixels - * then the current pixel is counted as being a true outer edge pixel. - */ - if ((!lomask[pix_nextCol] && !limask[pix_nextCol]) || - (!lomask[pix_prevCol] && !limask[pix_prevCol]) || - (!lomask[pix_nextRow] && !limask[pix_nextRow]) || - (!lomask[pix_prevRow] && !limask[pix_prevRow])) - { - in_osz++; // increment the outer boundary pixel count - lres[a]=3; // flag pixel as part of outer edge - } - else { // it's not a boundary pixel, but it is a gradient pixel - in_gsz++; // increment the gradient pixel count - lres[a]=2; // flag pixel as gradient - } - } - - } - else { - if ((!limask[pix_nextCol] && lomask[pix_nextCol]) || - (!limask[pix_prevCol] && lomask[pix_prevCol]) || - (!limask[pix_nextRow] && lomask[pix_nextRow]) || - (!limask[pix_prevRow] && lomask[pix_prevRow])) - { - in_isz++; // increment the inner boundary pixel count - lres[a]=4; // flag pixel as part of inner edge - } - else { - res[a]=1.0f; // pixel is part of inner mask, but not at an edge - } - } - a--; - pix_prevRow--; // advance all four "surrounding" pixel pointers - pix_nextRow--; - pix_prevCol--; - pix_nextCol--; - } - } - - rsize[0]=in_isz; // fill in our return sizes for edges + fill - rsize[1]=in_osz; - rsize[2]=in_gsz; -} - -static void do_createEdgeLocationBuffer(unsigned int t, unsigned int rw, unsigned int *lres, float *res, unsigned short *gbuf, unsigned int *innerEdgeOffset, unsigned int *outerEdgeOffset, unsigned int isz, unsigned int gsz) -{ - int x; // x = pixel loop counter - int a; // a = temporary pixel index buffer loop counter - unsigned int ud; // ud = unscaled edge distance - unsigned int dmin; // dmin = minimum edge distance - - unsigned int rsl; // long used for finding fast 1.0/sqrt - unsigned int gradientFillOffset; - unsigned int innerAccum=0; // for looping inner edge pixel indexes, represents current position from offset - unsigned int outerAccum=0; // for looping outer edge pixel indexes, represents current position from offset - unsigned int gradientAccum=0; // for looping gradient pixel indexes, represents current position from offset - /* - * Here we compute the size of buffer needed to hold (row, col) coordinates - * for each pixel previously determined to be either gradient, inner edge, - * or outer edge. - * - * Allocation is done by requesting 4 bytes "sizeof(int)" per pixel, even - * though gbuf[] is declared as unsigned short* (2 bytes) because we don't - * store the pixel indexes, we only store x, y location of pixel in buffer. - * - * This does make the assumption that x and y can fit in 16 unsigned bits - * so if Blender starts doing renders greater than 65536 in either direction - * this will need to allocate gbuf[] as unsigned int* and allocate 8 bytes - * per flagged pixel. - * - * In general, the buffer on-screen: - * - * Example: 9 by 9 pixel block - * - * . = pixel non-white in both outer and inner mask - * o = pixel white in outer, but not inner mask, adjacent to "." pixel - * g = pixel white in outer, but not inner mask, not adjacent to "." pixel - * i = pixel white in inner mask, adjacent to "g" or "." pixel - * F = pixel white in inner mask, only adjacent to other pixels white in the inner mask - * - * - * ......... <----- pixel #80 - * ..oooo... - * .oggggo.. - * .oggiggo. - * .ogiFigo. - * .oggiggo. - * .oggggo.. - * ..oooo... - * pixel #00 -----> ......... - * - * gsz = 18 (18 "g" pixels above) - * isz = 4 (4 "i" pixels above) - * osz = 18 (18 "o" pixels above) - * - * - * The memory in gbuf[] after filling will look like this: - * - * gradientFillOffset (0 pixels) innerEdgeOffset (18 pixels) outerEdgeOffset (22 pixels) - * / / / - * / / / - * |X Y X Y X Y X Y > <X Y X Y > <X Y X Y X Y > <X Y X Y | <- (x, y) - * +--------------------------------> <----------------> <------------------------> <----------------+ - * |0 2 4 6 8 10 12 14 > ... <68 70 72 74 > ... <80 82 84 86 88 90 > ... <152 154 156 158 | <- bytes - * +--------------------------------> <----------------> <------------------------> <----------------+ - * |g0 g0 g1 g1 g2 g2 g3 g3 > <g17 g17 i0 i0 > <i2 i2 i3 i3 o0 o0 > <o16 o16 o17 o17 | <- pixel - * / / / - * / / / - * / / / - * +---------- gradientAccum (18) ---------+ +--- innerAccum (22) ---+ +--- outerAccum (40) ---+ - * - * - * Ultimately we do need the pixel's memory buffer index to set the output - * pixel color, but it's faster to reconstruct the memory buffer location - * each iteration of the final gradient calculation than it is to deconstruct - * a memory location into x, y pairs each round. - */ - - - gradientFillOffset=0; // since there are likely "more" of these, put it first. :) - *innerEdgeOffset=gradientFillOffset+gsz; // set start of inner edge indexes - *outerEdgeOffset=(*innerEdgeOffset)+isz; // set start of outer edge indexes - /* set the accumulators to correct positions */ // set up some accumulator variables for loops - gradientAccum = gradientFillOffset; // each accumulator variable starts at its respective - innerAccum = *innerEdgeOffset; // section's offset so when we start filling, each - outerAccum = *outerEdgeOffset; // section fills up it's allocated space in gbuf - //uses dmin=row, rsl=col - for (x=0, dmin=0; x<t; x+=rw, dmin++) { - for (rsl=0; rsl<rw; rsl++) { - a=x+rsl; - if (lres[a]==2) { // it is a gradient pixel flagged by 2 - ud=gradientAccum<<1; // double the index to reach correct unsigned short location - gbuf[ud]=dmin; // insert pixel's row into gradient pixel location buffer - gbuf[ud+1]=rsl; // insert pixel's column into gradient pixel location buffer - gradientAccum++; // increment gradient index buffer pointer - } - else if (lres[a]==3) { // it is an outer edge pixel flagged by 3 - ud=outerAccum<<1; // double the index to reach correct unsigned short location - gbuf[ud]=dmin; // insert pixel's row into outer edge pixel location buffer - gbuf[ud+1]=rsl; // insert pixel's column into outer edge pixel location buffer - outerAccum++; // increment outer edge index buffer pointer - res[a]=0.0f; // set output pixel intensity now since it won't change later - } - else if (lres[a]==4) { // it is an inner edge pixel flagged by 4 - ud=innerAccum<<1; // double int index to reach correct unsigned short location - gbuf[ud]=dmin; // insert pixel's row into inner edge pixel location buffer - gbuf[ud+1]=rsl; // insert pixel's column into inner edge pixel location buffer - innerAccum++; // increment inner edge index buffer pointer - res[a]=1.0f; // set output pixel intensity now since it won't change later - } - } - } - -} - -static void do_fillGradientBuffer(unsigned int rw, float *res, unsigned short *gbuf, unsigned int isz, unsigned int osz, unsigned int gsz, unsigned int innerEdgeOffset, unsigned int outerEdgeOffset) -{ - int x; // x = pixel loop counter - int a; // a = temporary pixel index buffer loop counter - int fsz; // size of the frame - unsigned int rsl; // long used for finding fast 1.0/sqrt - float rsf; // float used for finding fast 1.0/sqrt - const float rsopf = 1.5f; // constant float used for finding fast 1.0/sqrt - - unsigned int gradientFillOffset; - unsigned int t; - unsigned int ud; // ud = unscaled edge distance - unsigned int dmin; // dmin = minimum edge distance - float odist; // odist = current outer edge distance - float idist; // idist = current inner edge distance - int dx; // dx = X-delta (used for distance proportion calculation) - int dy; // dy = Y-delta (used for distance proportion calculation) - /* - * The general algorithm used to color each gradient pixel is: - * - * 1.) Loop through all gradient pixels. - * A.) For each gradient pixel: - * a.) Loop though all outside edge pixels, looking for closest one - * to the gradient pixel we are in. - * b.) Loop through all inside edge pixels, looking for closest one - * to the gradient pixel we are in. - * c.) Find proportion of distance from gradient pixel to inside edge - * pixel compared to sum of distance to inside edge and distance to - * outside edge. - * - * In an image where: - * . = blank (black) pixels, not covered by inner mask or outer mask - * + = desired gradient pixels, covered only by outer mask - * * = white full mask pixels, covered by at least inner mask - * - * ............................... - * ...............+++++++++++..... - * ...+O++++++..++++++++++++++.... - * ..+++\++++++++++++++++++++..... - * .+++++G+++++++++*******+++..... - * .+++++|+++++++*********+++..... - * .++***I****************+++..... - * .++*******************+++...... - * .+++*****************+++....... - * ..+++***************+++........ - * ....+++**********+++........... - * ......++++++++++++............. - * ............................... - * - * O = outside edge pixel - * \ - * G = gradient pixel - * | - * I = inside edge pixel - * - * __ - * *note that IO does not need to be a straight line, in fact - * many cases can arise where straight lines do not work - * correctly. - * - * __ __ __ - * d.) Pixel color is assigned as |GO| / ( |GI| + |GO| ) - * - * The implementation does not compute distance, but the reciprocal of the - * distance. This is done to avoid having to compute a square root, as a - * reciprocal square root can be computed faster. Therefore, the code computes - * pixel color as |GI| / (|GI| + |GO|). Since these are reciprocals, GI serves the - * purpose of GO for the proportion calculation. - * - * For the purposes of the minimum distance comparisons, we only check - * the sums-of-squares against each other, since they are in the same - * mathematical sort-order as if we did go ahead and take square roots - * - * Loop through all gradient pixels. - */ - - for (x= gsz-1; x>=0; x--) { - gradientFillOffset=x<<1; - t=gbuf[gradientFillOffset]; // calculate column of pixel indexed by gbuf[x] - fsz=gbuf[gradientFillOffset+1]; // calculate row of pixel indexed by gbuf[x] - dmin=0xffffffff; // reset min distance to edge pixel - for (a=outerEdgeOffset+osz-1; a>=outerEdgeOffset; a--) { // loop through all outer edge buffer pixels - ud=a<<1; - dy=t-gbuf[ud]; // set dx to gradient pixel column - outer edge pixel row - dx=fsz-gbuf[ud+1]; // set dy to gradient pixel row - outer edge pixel column - ud=dx*dx+dy*dy; // compute sum of squares - if (ud<dmin) { // if our new sum of squares is less than the current minimum - dmin=ud; // set a new minimum equal to the new lower value - } - } - odist=(float)(dmin); // cast outer min to a float - rsf=odist*0.5f; // - rsl=*(unsigned int*)&odist; // use some peculiar properties of the way bits are stored - rsl=0x5f3759df-(rsl>>1); // in floats vs. unsigned ints to compute an approximate - odist=*(float*)&rsl; // reciprocal square root - odist=odist*(rsopf-(rsf*odist*odist)); // -- ** this line can be iterated for more accuracy ** -- - dmin=0xffffffff; // reset min distance to edge pixel - for (a= innerEdgeOffset+isz-1; a>=innerEdgeOffset; a--) { // loop through all inside edge pixels - ud=a<<1; - dy=t-gbuf[ud]; // compute delta in Y from gradient pixel to inside edge pixel - dx=fsz-gbuf[ud+1]; // compute delta in X from gradient pixel to inside edge pixel - ud=dx*dx+dy*dy; // compute sum of squares - if (ud<dmin) { // if our new sum of squares is less than the current minimum we've found - dmin=ud; // set a new minimum equal to the new lower value - } - } - idist=(float)(dmin); // cast inner min to a float - rsf=idist*0.5f; // - rsl=*(unsigned int*)&idist; // - rsl=0x5f3759df-(rsl>>1); // see notes above - idist=*(float*)&rsl; // - idist=idist*(rsopf-(rsf*idist*idist)); // - /* - * Note once again that since we are using reciprocals of distance values our - * proportion is already the correct intensity, and does not need to be - * subtracted from 1.0 like it would have if we used real distances. - */ - - /* - * Here we reconstruct the pixel's memory location in the CompBuf by - * Pixel Index = Pixel Column + ( Pixel Row * Row Width ) - */ - res[gbuf[gradientFillOffset+1]+(gbuf[gradientFillOffset]*rw)]=(idist/(idist+odist)); //set intensity - } - -} - - -static void node_composit_exec_doubleedgemask(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - - float *imask; // imask = pointer to inner mask pixel buffer - float *omask; // omask = pointer to outer mask pixel buffer - float *res; // res = pointer to output mask - - unsigned int *lres; // lres = unsigned int pointer to output pixel buffer (for bit operations) - unsigned int *limask; // limask = unsigned int pointer to inner mask (for bit operations) - unsigned int *lomask; // lomask = unsigned int pointer to outer mask (for bit operations) - - int rw; // rw = pixel row width - int t; // t = total number of pixels in buffer - 1 (used for loop starts) - int fsz; // size of the frame - - unsigned int isz=0; // size (in pixels) of inside edge pixel index buffer - unsigned int osz=0; // size (in pixels) of outside edge pixel index buffer - unsigned int gsz=0; // size (in pixels) of gradient pixel index buffer - unsigned int rsize[3]; // size storage to pass to helper functions - unsigned int innerEdgeOffset=0; // offset into final buffer where inner edge pixel indexes start - unsigned int outerEdgeOffset=0; // offset into final buffer where outer edge pixel indexes start - - unsigned short *gbuf; // gradient/inner/outer pixel location index buffer - - CompBuf *cbuf; // pointer, will be set to inner mask data - CompBuf *dbuf; // pointer, will be set to outer mask data - CompBuf *stackbuf; // pointer, will get allocated as output buffer - - if (out[0]->hasoutput==0) { // if the node's output socket is not connected to anything... - return; // do not execute any further, just exit the node immediately - } - - if (in[0]->data && in[1]->data) { // if both input sockets have some data coming in... - cbuf= in[0]->data; // get a pointer to the inner mask data - dbuf= in[1]->data; // get a pointer to the outer mask data - if (cbuf->type!=CB_VAL || dbuf->type!=CB_VAL) { // if either input socket has an incorrect data type coming in - return; // exit the node immediately - } - - t=(cbuf->x*cbuf->y)-1; // determine size of the frame - - stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); // allocate the output buffer - - imask= cbuf->rect; // set the inner mask - omask= dbuf->rect; // set the outer mask - res= stackbuf->rect; // set output pointer - lres= (unsigned int*)res; // unsigned int pointer to output buffer (for bit level ops) - limask=(unsigned int*)imask; // unsigned int pointer to input mask (for bit level ops) - lomask=(unsigned int*)omask; // unsigned int pointer to output mask (for bit level ops) - rw= cbuf->x; // width of a row of pixels - - - /* - * The whole buffer is broken up into 4 parts. The four CORNERS, the FIRST and LAST rows, the - * LEFT and RIGHT edges (excluding the corner pixels), and all OTHER rows. - * This allows for quick computation of outer edge pixels where - * a screen edge pixel is marked to be gradient. - * - * The pixel type (gradient vs inner-edge vs outer-edge) tests change - * depending on the user selected "Inner Edge Mode" and the user selected - * "Buffer Edge Mode" on the node's GUI. There are 4 sets of basically the - * same algorithm: - * - * 1.) Inner Edge -> Adjacent Only - * Buffer Edge -> Keep Inside - * - * 2.) Inner Edge -> Adjacent Only - * Buffer Edge -> Bleed Out - * - * 3.) Inner Edge -> All - * Buffer Edge -> Keep Inside - * - * 4.) Inner Edge -> All - * Buffer Edge -> Bleed Out - * - * Each version has slightly different criteria for detecting an edge pixel. - */ - if (node->custom2) { // if "adjacent only" inner edge mode is turned on - if (node->custom1) { // if "keep inside" buffer edge mode is turned on - do_adjacentKeepBorders(t, rw, limask, lomask, lres, res, rsize); - } - else { // "bleed out" buffer edge mode is turned on - do_adjacentBleedBorders(t, rw, limask, lomask, lres, res, rsize); - } - isz=rsize[0]; // set up inner edge, outer edge, and gradient buffer sizes after border pass - osz=rsize[1]; - gsz=rsize[2]; - // detect edges in all non-border pixels in the buffer - do_adjacentEdgeDetection(t, rw, limask, lomask, lres, res, rsize, isz, osz, gsz); - } - else { // "all" inner edge mode is turned on - if (node->custom1) { // if "keep inside" buffer edge mode is turned on - do_allKeepBorders(t, rw, limask, lomask, lres, res, rsize); - } - else { // "bleed out" buffer edge mode is turned on - do_allBleedBorders(t, rw, limask, lomask, lres, res, rsize); - } - isz=rsize[0]; // set up inner edge, outer edge, and gradient buffer sizes after border pass - osz=rsize[1]; - gsz=rsize[2]; - // detect edges in all non-border pixels in the buffer - do_allEdgeDetection(t, rw, limask, lomask, lres, res, rsize, isz, osz, gsz); - } - - isz=rsize[0]; // set edge and gradient buffer sizes once again... - osz=rsize[1]; // the sizes in rsize[] may have been modified - gsz=rsize[2]; // by the do_*EdgeDetection() function. - - // quick check for existance of edges in the buffer... - // if we don't have any one of the three sizes, the other two make no difference visually, - // so we can just pass the inner input buffer back as output. - if (!gsz || !isz || !osz) { - out[0]->data= stackbuf; // point the node output buffer to our filled buffer - return; - } - - - fsz=gsz+isz+osz; // calculate size of pixel index buffer needed - gbuf= MEM_mallocN(fsz*sizeof(int), "grd buf"); // allocate edge/gradient pixel index buffer - - do_createEdgeLocationBuffer(t, rw, lres, res, gbuf, &innerEdgeOffset, &outerEdgeOffset, isz, gsz); - do_fillGradientBuffer(rw, res, gbuf, isz, osz, gsz, innerEdgeOffset, outerEdgeOffset); - - MEM_freeN(gbuf); // free the gradient index buffer - out[0]->data= stackbuf; // point the node output buffer to our filled buffer - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_doubleedgemask(bNodeTreeType *ttype) { static bNodeType ntype; // allocate a node type data structure @@ -1282,9 +49,6 @@ void register_node_type_cmp_doubleedgemask(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_DOUBLEEDGEMASK, "Double Edge Mask", NODE_CLASS_MATTE, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_doubleedgemask_in, cmp_node_doubleedgemask_out); node_type_size(&ntype, 210, 210, 210); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_doubleedgemask); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_filter.c b/source/blender/nodes/composite/nodes/node_composite_filter.c index a27116ab077..338bfc0326d 100644 --- a/source/blender/nodes/composite/nodes/node_composite_filter.c +++ b/source/blender/nodes/composite/nodes/node_composite_filter.c @@ -43,186 +43,6 @@ static bNodeSocketTemplate cmp_node_filter_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_filter_edge(CompBuf *out, CompBuf *in, float *filter, float fac) -{ - float *row1, *row2, *row3; - float *fp, f1, f2, mfac= 1.0f-fac; - int rowlen, x, y, c, pix= in->type; - - rowlen= in->x; - - for (y=0; y<in->y; y++) { - /* setup rows */ - if (y==0) row1= in->rect; - else row1= in->rect + pix*(y-1)*rowlen; - - row2= in->rect + y*pix*rowlen; - - if (y==in->y-1) row3= row2; - else row3= row2 + pix*rowlen; - - fp= out->rect + pix*y*rowlen; - - if (pix==CB_RGBA) { - copy_v4_v4(fp, row2); - fp+= pix; - - for (x=2; x<rowlen; x++) { - for (c=0; c<3; c++) { - f1= filter[0]*row1[0] + filter[1]*row1[4] + filter[2]*row1[8] + filter[3]*row2[0] + filter[4]*row2[4] + filter[5]*row2[8] + filter[6]*row3[0] + filter[7]*row3[4] + filter[8]*row3[8]; - f2= filter[0]*row1[0] + filter[3]*row1[4] + filter[6]*row1[8] + filter[1]*row2[0] + filter[4]*row2[4] + filter[7]*row2[8] + filter[2]*row3[0] + filter[5]*row3[4] + filter[8]*row3[8]; - fp[0] = mfac*row2[4] + fac*sqrt(f1*f1 + f2*f2); - fp++; row1++; row2++; row3++; - } - fp[0] = row2[4]; - /* no alpha... will clear it completely */ - fp++; row1++; row2++; row3++; - } - copy_v4_v4(fp, row2+4); - } - else if (pix==CB_VAL) { - fp+= pix; - for (x=2; x<rowlen; x++) { - f1= filter[0]*row1[0] + filter[1]*row1[1] + filter[2]*row1[2] + filter[3]*row2[0] + filter[4]*row2[1] + filter[5]*row2[2] + filter[6]*row3[0] + filter[7]*row3[1] + filter[8]*row3[2]; - f2= filter[0]*row1[0] + filter[3]*row1[1] + filter[6]*row1[2] + filter[1]*row2[0] + filter[4]*row2[1] + filter[7]*row2[2] + filter[2]*row3[0] + filter[5]*row3[1] + filter[8]*row3[2]; - fp[0] = mfac*row2[1] + fac*sqrt(f1*f1 + f2*f2); - fp++; row1++; row2++; row3++; - } - } - } -} - -static void do_filter3(CompBuf *out, CompBuf *in, float *filter, float fac) -{ - float *row1, *row2, *row3; - float *fp, mfac= 1.0f-fac; - int rowlen, x, y, c; - int pixlen= in->type; - - rowlen= in->x; - - for (y=0; y<in->y; y++) { - /* setup rows */ - if (y==0) row1= in->rect; - else row1= in->rect + pixlen*(y-1)*rowlen; - - row2= in->rect + y*pixlen*rowlen; - - if (y==in->y-1) row3= row2; - else row3= row2 + pixlen*rowlen; - - fp= out->rect + pixlen*(y)*rowlen; - - if (pixlen==1) { - fp[0] = row2[0]; - fp+= 1; - - for (x=2; x<rowlen; x++) { - fp[0] = mfac*row2[1] + fac*(filter[0]*row1[0] + filter[1]*row1[1] + filter[2]*row1[2] + filter[3]*row2[0] + filter[4]*row2[1] + filter[5]*row2[2] + filter[6]*row3[0] + filter[7]*row3[1] + filter[8]*row3[2]); - fp++; row1++; row2++; row3++; - } - fp[0] = row2[1]; - } - else if (pixlen==2) { - fp[0] = row2[0]; - fp[1] = row2[1]; - fp+= 2; - - for (x=2; x<rowlen; x++) { - for (c=0; c<2; c++) { - fp[0] = mfac*row2[2] + fac*(filter[0]*row1[0] + filter[1]*row1[2] + filter[2]*row1[4] + filter[3]*row2[0] + filter[4]*row2[2] + filter[5]*row2[4] + filter[6]*row3[0] + filter[7]*row3[2] + filter[8]*row3[4]); - fp++; row1++; row2++; row3++; - } - } - fp[0] = row2[2]; - fp[1] = row2[3]; - } - else if (pixlen==3) { - copy_v3_v3(fp, row2); - fp+= 3; - - for (x=2; x<rowlen; x++) { - for (c=0; c<3; c++) { - fp[0] = mfac*row2[3] + fac*(filter[0]*row1[0] + filter[1]*row1[3] + filter[2]*row1[6] + filter[3]*row2[0] + filter[4]*row2[3] + filter[5]*row2[6] + filter[6]*row3[0] + filter[7]*row3[3] + filter[8]*row3[6]); - fp++; row1++; row2++; row3++; - } - } - copy_v3_v3(fp, row2+3); - } - else { - copy_v4_v4(fp, row2); - fp+= 4; - - for (x=2; x<rowlen; x++) { - for (c=0; c<4; c++) { - fp[0] = mfac*row2[4] + fac*(filter[0]*row1[0] + filter[1]*row1[4] + filter[2]*row1[8] + filter[3]*row2[0] + filter[4]*row2[4] + filter[5]*row2[8] + filter[6]*row3[0] + filter[7]*row3[4] + filter[8]*row3[8]); - fp++; row1++; row2++; row3++; - } - } - copy_v4_v4(fp, row2+4); - } - } -} - - -static void node_composit_exec_filter(void *data, bNode *node, bNodeStack **in, bNodeStack **out) -{ - static float soft[9] = {1/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 4/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 1/16.0f}; - float sharp[9] = {-1, -1, -1, -1, 9, -1, -1, -1, -1}; - float laplace[9] = {-1/8.0f, -1/8.0f, -1/8.0f, -1/8.0f, 1.0f, -1/8.0f, -1/8.0f, -1/8.0f, -1/8.0f}; - float sobel[9] = {1, 2, 1, 0, 0, 0, -1, -2, -1}; - float prewitt[9] = {1, 1, 1, 0, 0, 0, -1, -1, -1}; - float kirsch[9] = {5, 5, 5, -3, -3, -3, -2, -2, -2}; - float shadow[9] = {1, 2, 1, 0, 1, 0, -1, -2, -1}; - - if (out[0]->hasoutput==0) return; - - /* stack order in: Image */ - /* stack order out: Image */ - - if (in[1]->data) { - /* make output size of first available input image */ - CompBuf *cbuf= in[1]->data; - CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 1); /* allocs */ - - /* warning note: xof and yof are applied in pixelprocessor, but should be copied otherwise? */ - stackbuf->xof= cbuf->xof; - stackbuf->yof= cbuf->yof; - - switch (node->custom1) { - case CMP_FILT_SOFT: - do_filter3(stackbuf, cbuf, soft, in[0]->vec[0]); - break; - case CMP_FILT_SHARP: - do_filter3(stackbuf, cbuf, sharp, in[0]->vec[0]); - break; - case CMP_FILT_LAPLACE: - do_filter3(stackbuf, cbuf, laplace, in[0]->vec[0]); - break; - case CMP_FILT_SOBEL: - do_filter_edge(stackbuf, cbuf, sobel, in[0]->vec[0]); - break; - case CMP_FILT_PREWITT: - do_filter_edge(stackbuf, cbuf, prewitt, in[0]->vec[0]); - break; - case CMP_FILT_KIRSCH: - do_filter_edge(stackbuf, cbuf, kirsch, in[0]->vec[0]); - break; - case CMP_FILT_SHADOW: - do_filter3(stackbuf, cbuf, shadow, in[0]->vec[0]); - break; - } - - out[0]->data= stackbuf; - - generate_preview(data, node, out[0]->data); - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_filter(bNodeTreeType *ttype) { static bNodeType ntype; @@ -231,9 +51,6 @@ void register_node_type_cmp_filter(bNodeTreeType *ttype) node_type_socket_templates(&ntype, cmp_node_filter_in, cmp_node_filter_out); node_type_size(&ntype, 80, 40, 120); node_type_label(&ntype, node_filter_label); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_filter); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_flip.c b/source/blender/nodes/composite/nodes/node_composite_flip.c index 4aa98d173e7..de41c7274fe 100644 --- a/source/blender/nodes/composite/nodes/node_composite_flip.c +++ b/source/blender/nodes/composite/nodes/node_composite_flip.c @@ -43,55 +43,6 @@ static bNodeSocketTemplate cmp_node_flip_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void node_composit_exec_flip(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - if (in[0]->data) { - CompBuf *cbuf= in[0]->data; - CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 1); /* note, this returns zero'd image */ - int i, src_pix, src_width, src_height, srcydelt, outydelt, x, y; - float *srcfp, *outfp; - - src_pix= cbuf->type; - src_width= cbuf->x; - src_height= cbuf->y; - srcfp= cbuf->rect; - outfp= stackbuf->rect; - srcydelt= src_width*src_pix; - outydelt= srcydelt; - - if (node->custom1) { /*set up output pointer for y flip*/ - outfp+= (src_height-1)*outydelt; - outydelt= -outydelt; - } - - for (y=0; y<src_height; y++) { - if (node->custom1 == 1) { /* no x flip so just copy line*/ - memcpy(outfp, srcfp, sizeof(float) * src_pix * src_width); - srcfp+=srcydelt; - } - else { - outfp += (src_width-1)*src_pix; - for (x=0; x<src_width; x++) { - for (i=0; i<src_pix; i++) { - outfp[i] = srcfp[i]; - } - outfp -= src_pix; - srcfp += src_pix; - } - outfp += src_pix; - } - outfp += outydelt; - } - - out[0]->data= stackbuf; - - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_flip(bNodeTreeType *ttype) { static bNodeType ntype; @@ -99,9 +50,6 @@ void register_node_type_cmp_flip(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_FLIP, "Flip", NODE_CLASS_DISTORT, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_flip_in, cmp_node_flip_out); node_type_size(&ntype, 140, 100, 320); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_flip); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_gamma.c b/source/blender/nodes/composite/nodes/node_composite_gamma.c index b8c99894301..e7fbdeaedd7 100644 --- a/source/blender/nodes/composite/nodes/node_composite_gamma.c +++ b/source/blender/nodes/composite/nodes/node_composite_gamma.c @@ -45,40 +45,6 @@ static bNodeSocketTemplate cmp_node_gamma_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_gamma(bNode *UNUSED(node), float *out, float *in, float *fac) -{ - int i=0; - for (i=0; i<3; i++) { - /* check for negative to avoid nan's */ - out[i] = (in[i] > 0.0f)? powf(in[i], fac[0]): in[i]; - } - out[3] = in[3]; -} -static void node_composit_exec_gamma(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - /* stack order in: Fac, Image */ - /* stack order out: Image */ - if (out[0]->hasoutput==0) return; - - /* input no image? then only color operation */ - if (in[0]->data==NULL) { - do_gamma(node, out[0]->vec, in[0]->vec, in[1]->vec); - } - else { - /* make output size of input image */ - CompBuf *cbuf= in[0]->data; - CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs - - composit2_pixel_processor(node, stackbuf, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_gamma, CB_RGBA, CB_VAL); - - out[0]->data= stackbuf; - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_gamma(bNodeTreeType *ttype) { static bNodeType ntype; @@ -86,9 +52,6 @@ void register_node_type_cmp_gamma(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_gamma_in, cmp_node_gamma_out); node_type_size(&ntype, 140, 100, 320); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_gamma); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_glare.c b/source/blender/nodes/composite/nodes/node_composite_glare.c index 950d8a56f58..5fdb262de97 100644 --- a/source/blender/nodes/composite/nodes/node_composite_glare.c +++ b/source/blender/nodes/composite/nodes/node_composite_glare.c @@ -41,442 +41,6 @@ static bNodeSocketTemplate cmp_node_glare_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -// mix two images, src buffer does not have to be same size, -static void mixImages(CompBuf *dst, CompBuf *src, float mix) -{ - int x, y; - fRGB c1, c2, *dcolp, *scolp; - const float mf = 2.f - 2.f*fabsf(mix - 0.5f); - if ((dst->x == src->x) && (dst->y == src->y)) { - for (y=0; y<dst->y; y++) { - dcolp = (fRGB*)&dst->rect[y*dst->x*dst->type]; - scolp = (fRGB*)&src->rect[y*dst->x*dst->type]; - for (x=0; x<dst->x; x++) { - copy_v3_v3(c1, dcolp[x]); - copy_v3_v3(c2, scolp[x]); - c1[0] += mix*(c2[0] - c1[0]); - c1[1] += mix*(c2[1] - c1[1]); - c1[2] += mix*(c2[2] - c1[2]); - if (c1[0] < 0.f) c1[0] = 0.f; - if (c1[1] < 0.f) c1[1] = 0.f; - if (c1[2] < 0.f) c1[2] = 0.f; - mul_v3_fl(c1, mf); - copy_v3_v3(dcolp[x], c1); - } - } - } - else { - float xr = src->x / (float)dst->x; - float yr = src->y / (float)dst->y; - for (y=0; y<dst->y; y++) { - dcolp = (fRGB*)&dst->rect[y*dst->x*dst->type]; - for (x=0; x<dst->x; x++) { - copy_v3_v3(c1, dcolp[x]); - qd_getPixelLerp(src, (x + 0.5f)*xr - 0.5f, (y + 0.5f)*yr - 0.5f, c2); - c1[0] += mix*(c2[0] - c1[0]); - c1[1] += mix*(c2[1] - c1[1]); - c1[2] += mix*(c2[2] - c1[2]); - if (c1[0] < 0.f) c1[0] = 0.f; - if (c1[1] < 0.f) c1[1] = 0.f; - if (c1[2] < 0.f) c1[2] = 0.f; - mul_v3_fl(c1, mf); - copy_v3_v3(dcolp[x], c1); - } - } - } -} - - -// adds src to dst image, must be of same size -static void addImage(CompBuf* dst, CompBuf* src, float scale) -{ - if ((dst->x == src->x) && (dst->y == src->y)) { - int p = dst->x*dst->y*dst->type; - float *dcol = dst->rect, *scol = src->rect; - while (p--) *dcol++ += *scol++ * scale; - } -} - - -// returns possibly downscaled copy of all pixels above threshold -static CompBuf* BTP(CompBuf* src, float threshold, int scaledown) -{ - int x, y; - CompBuf* bsrc = qd_downScaledCopy(src, scaledown); - float* cr = bsrc->rect; - for (y=0; y<bsrc->y; ++y) - for (x=0; x<bsrc->x; ++x, cr+=4) { - if (rgb_to_luma_y(cr) >= threshold) { - cr[0] -= threshold, cr[1] -= threshold, cr[2] -= threshold; - cr[0] = MAX2(cr[0], 0.f); - cr[1] = MAX2(cr[1], 0.f); - cr[2] = MAX2(cr[2], 0.f); - } - else cr[0] = cr[1] = cr[2] = 0.f; - } - return bsrc; -} - -//-------------------------------------------------------------------------------------------- -// simple 4-point star filter - -static void star4(NodeGlare* ndg, CompBuf* dst, CompBuf* src) -{ - int x, y, i, xm, xp, ym, yp; - float c[4] = {0, 0, 0, 0}, tc[4] = {0, 0, 0, 0}; - CompBuf *tbuf1, *tbuf2, *tsrc; - const float f1 = 1.f - ndg->fade, f2 = (1.f - f1)*0.5f; - //const float t3 = ndg->threshold*3.f; - const float sc = (float)(1 << ndg->quality); - const float isc = 1.f/sc; - - tsrc = BTP(src, ndg->threshold, (int)sc); - - tbuf1 = dupalloc_compbuf(tsrc); - tbuf2 = dupalloc_compbuf(tsrc); - - for (i=0; i<ndg->iter; i++) { - // (x || x-1, y-1) to (x || x+1, y+1) - // F - for (y=0; y<tbuf1->y; y++) { - ym = y - i; - yp = y + i; - for (x=0; x<tbuf1->x; x++) { - xm = x - i; - xp = x + i; - qd_getPixel(tbuf1, x, y, c); - mul_v3_fl(c, f1); - qd_getPixel(tbuf1, (ndg->angle ? xm : x), ym, tc); - madd_v3_v3fl(c, tc, f2); - qd_getPixel(tbuf1, (ndg->angle ? xp : x), yp, tc); - madd_v3_v3fl(c, tc, f2); - qd_setPixel(tbuf1, x, y, c); - } - } - // B - for (y=tbuf1->y-1; y>=0; y--) { - ym = y - i; - yp = y + i; - for (x=tbuf1->x-1; x>=0; x--) { - xm = x - i; - xp = x + i; - qd_getPixel(tbuf1, x, y, c); - mul_v3_fl(c, f1); - qd_getPixel(tbuf1, (ndg->angle ? xm : x), ym, tc); - madd_v3_v3fl(c, tc, f2); - qd_getPixel(tbuf1, (ndg->angle ? xp : x), yp, tc); - madd_v3_v3fl(c, tc, f2); - qd_setPixel(tbuf1, x, y, c); - } - } - // (x-1, y || y+1) to (x+1, y || y-1) - // F - for (y=0; y<tbuf2->y; y++) { - ym = y - i; - yp = y + i; - for (x=0; x<tbuf2->x; x++) { - xm = x - i; - xp = x + i; - qd_getPixel(tbuf2, x, y, c); - mul_v3_fl(c, f1); - qd_getPixel(tbuf2, xm, (ndg->angle ? yp : y), tc); - madd_v3_v3fl(c, tc, f2); - qd_getPixel(tbuf2, xp, (ndg->angle ? ym : y), tc); - madd_v3_v3fl(c, tc, f2); - qd_setPixel(tbuf2, x, y, c); - } - } - // B - for (y=tbuf2->y-1; y>=0; y--) { - ym = y - i; - yp = y + i; - for (x=tbuf2->x-1; x>=0; x--) { - xm = x - i; - xp = x + i; - qd_getPixel(tbuf2, x, y, c); - mul_v3_fl(c, f1); - qd_getPixel(tbuf2, xm, (ndg->angle ? yp : y), tc); - madd_v3_v3fl(c, tc, f2); - qd_getPixel(tbuf2, xp, (ndg->angle ? ym : y), tc); - madd_v3_v3fl(c, tc, f2); - qd_setPixel(tbuf2, x, y, c); - } - } - } - - for (y=0; y<tbuf1->y; ++y) - for (x=0; x<tbuf1->x; ++x) { - unsigned int p = (x + y*tbuf1->x)*tbuf1->type; - tbuf1->rect[p] += tbuf2->rect[p]; - tbuf1->rect[p+1] += tbuf2->rect[p+1]; - tbuf1->rect[p+2] += tbuf2->rect[p+2]; - } - - for (y=0; y<dst->y; ++y) { - const float m = 0.5f + 0.5f*ndg->mix; - for (x=0; x<dst->x; ++x) { - unsigned int p = (x + y*dst->x)*dst->type; - qd_getPixelLerp(tbuf1, x*isc, y*isc, tc); - dst->rect[p] = src->rect[p] + m*(tc[0] - src->rect[p]); - dst->rect[p+1] = src->rect[p+1] + m*(tc[1] - src->rect[p+1]); - dst->rect[p+2] = src->rect[p+2] + m*(tc[2] - src->rect[p+2]); - } - } - - free_compbuf(tbuf1); - free_compbuf(tbuf2); - free_compbuf(tsrc); -} - -//-------------------------------------------------------------------------------------------- -// streak filter - -static void streaks(NodeGlare* ndg, CompBuf* dst, CompBuf* src) -{ - CompBuf *bsrc, *tsrc, *tdst, *sbuf; - int x, y, n; - unsigned int nump=0; - fRGB c1, c2, c3, c4; - float a, ang = DEG2RADF(360.0f)/(float)ndg->angle; - - bsrc = BTP(src, ndg->threshold, 1 << ndg->quality); - tsrc = dupalloc_compbuf(bsrc); // sample from buffer - tdst = alloc_compbuf(tsrc->x, tsrc->y, tsrc->type, 1); // sample to buffer - sbuf = alloc_compbuf(tsrc->x, tsrc->y, tsrc->type, 1); // streak sum buffer - - - for (a=0.f; a<DEG2RADF(360.0f); a+=ang) { - const float an = a + ndg->angle_ofs; - const float vx = cos((double)an), vy = sin((double)an); - for (n=0; n<ndg->iter; ++n) { - const float p4 = pow(4.0, (double)n); - const float vxp = vx*p4, vyp = vy*p4; - const float wt = pow((double)ndg->fade, (double)p4); - const float cmo = 1.f - (float)pow((double)ndg->colmod, (double)n+1); // colormodulation amount relative to current pass - float* tdstcol = tdst->rect; - for (y=0; y<tsrc->y; ++y) { - for (x=0; x<tsrc->x; ++x, tdstcol+=4) { - // first pass no offset, always same for every pass, exact copy, - // otherwise results in uneven brightness, only need once - if (n==0) qd_getPixel(tsrc, x, y, c1); else c1[0]=c1[1]=c1[2]=0; - qd_getPixelLerp(tsrc, x + vxp, y + vyp, c2); - qd_getPixelLerp(tsrc, x + vxp*2.f, y + vyp*2.f, c3); - qd_getPixelLerp(tsrc, x + vxp*3.f, y + vyp*3.f, c4); - // modulate color to look vaguely similar to a color spectrum - fRGB_rgbmult(c2, 1.f, cmo, cmo); - fRGB_rgbmult(c3, cmo, cmo, 1.f); - fRGB_rgbmult(c4, cmo, 1.f, cmo); - tdstcol[0] = 0.5f*(tdstcol[0] + c1[0] + wt*(c2[0] + wt*(c3[0] + wt*c4[0]))); - tdstcol[1] = 0.5f*(tdstcol[1] + c1[1] + wt*(c2[1] + wt*(c3[1] + wt*c4[1]))); - tdstcol[2] = 0.5f*(tdstcol[2] + c1[2] + wt*(c2[2] + wt*(c3[2] + wt*c4[2]))); - } - } - memcpy(tsrc->rect, tdst->rect, sizeof(float)*tdst->x*tdst->y*tdst->type); - } - - addImage(sbuf, tsrc, 1.f/(float)(6 - ndg->iter)); - memset(tdst->rect, 0, tdst->x*tdst->y*tdst->type*sizeof(float)); - memcpy(tsrc->rect, bsrc->rect, bsrc->x*bsrc->y*bsrc->type*sizeof(float)); - nump++; - } - - mixImages(dst, sbuf, 0.5f + 0.5f*ndg->mix); - - free_compbuf(tsrc); - free_compbuf(tdst); - free_compbuf(sbuf); - free_compbuf(bsrc); -} - - -//-------------------------------------------------------------------------------------------- -// Ghosts (lensflare) - -static float smoothMask(float x, float y) -{ - float t; - x = 2.f*x - 1.f, y = 2.f*y - 1.f; - if ((t = 1.f - sqrtf(x*x + y*y)) <= 0.f) return 0.f; - return t; -} - -static void ghosts(NodeGlare* ndg, CompBuf* dst, CompBuf* src) -{ - // colormodulation and scale factors (cm & scalef) for 16 passes max: 64 - int x, y, n, p, np; - fRGB c, tc, cm[64]; - float sc, isc, u, v, sm, s, t, ofs, scalef[64]; - CompBuf *tbuf1, *tbuf2, *gbuf; - const float cmo = 1.f - ndg->colmod; - const int qt = 1 << ndg->quality; - const float s1 = 4.f/(float)qt, s2 = 2.f*s1; - - gbuf = BTP(src, ndg->threshold, qt); - tbuf1 = dupalloc_compbuf(gbuf); - IIR_gauss(tbuf1, s1, 0, 3); - IIR_gauss(tbuf1, s1, 1, 3); - IIR_gauss(tbuf1, s1, 2, 3); - tbuf2 = dupalloc_compbuf(tbuf1); - IIR_gauss(tbuf2, s2, 0, 3); - IIR_gauss(tbuf2, s2, 1, 3); - IIR_gauss(tbuf2, s2, 2, 3); - - if (ndg->iter & 1) ofs = 0.5f; else ofs = 0.f; - for (x=0; x<(ndg->iter*4); x++) { - y = x & 3; - cm[x][0] = cm[x][1] = cm[x][2] = 1; - if (y==1) fRGB_rgbmult(cm[x], 1.f, cmo, cmo); - if (y==2) fRGB_rgbmult(cm[x], cmo, cmo, 1.f); - if (y==3) fRGB_rgbmult(cm[x], cmo, 1.f, cmo); - scalef[x] = 2.1f*(1.f-(x+ofs)/(float)(ndg->iter*4)); - if (x & 1) scalef[x] = -0.99f/scalef[x]; - } - - sc = 2.13; - isc = -0.97; - for (y=0; y<gbuf->y; y++) { - v = (float)(y+0.5f) / (float)gbuf->y; - for (x=0; x<gbuf->x; x++) { - u = (float)(x+0.5f) / (float)gbuf->x; - s = (u-0.5f)*sc + 0.5f, t = (v-0.5f)*sc + 0.5f; - qd_getPixelLerp(tbuf1, s*gbuf->x, t*gbuf->y, c); - sm = smoothMask(s, t); - mul_v3_fl(c, sm); - s = (u-0.5f)*isc + 0.5f, t = (v-0.5f)*isc + 0.5f; - qd_getPixelLerp(tbuf2, s*gbuf->x - 0.5f, t*gbuf->y - 0.5f, tc); - sm = smoothMask(s, t); - madd_v3_v3fl(c, tc, sm); - qd_setPixel(gbuf, x, y, c); - } - } - - memset(tbuf1->rect, 0, tbuf1->x*tbuf1->y*tbuf1->type*sizeof(float)); - for (n=1; n<ndg->iter; n++) { - for (y=0; y<gbuf->y; y++) { - v = (float)(y+0.5f) / (float)gbuf->y; - for (x=0; x<gbuf->x; x++) { - u = (float)(x+0.5f) / (float)gbuf->x; - tc[0] = tc[1] = tc[2] = 0.f; - for (p=0;p<4;p++) { - np = (n<<2) + p; - s = (u-0.5f)*scalef[np] + 0.5f; - t = (v-0.5f)*scalef[np] + 0.5f; - qd_getPixelLerp(gbuf, s*gbuf->x - 0.5f, t*gbuf->y - 0.5f, c); - mul_v3_v3(c, cm[np]); - sm = smoothMask(s, t)*0.25f; - madd_v3_v3fl(tc, c, sm); - } - p = (x + y*tbuf1->x)*tbuf1->type; - tbuf1->rect[p] += tc[0]; - tbuf1->rect[p+1] += tc[1]; - tbuf1->rect[p+2] += tc[2]; - } - } - memcpy(gbuf->rect, tbuf1->rect, tbuf1->x*tbuf1->y*tbuf1->type*sizeof(float)); - } - - free_compbuf(tbuf1); - free_compbuf(tbuf2); - - mixImages(dst, gbuf, 0.5f + 0.5f*ndg->mix); - free_compbuf(gbuf); -} - -//-------------------------------------------------------------------------------------------- -// Fog glow (convolution with kernel of exponential falloff) - -static void fglow(NodeGlare* ndg, CompBuf* dst, CompBuf* src) -{ - int x, y; - float scale, u, v, r, w, d; - fRGB fcol; - CompBuf *tsrc, *ckrn; - unsigned int sz = 1 << ndg->size; - const float cs_r = 1.f, cs_g = 1.f, cs_b = 1.f; - - // temp. src image - tsrc = BTP(src, ndg->threshold, 1 << ndg->quality); - // make the convolution kernel - ckrn = alloc_compbuf(sz, sz, CB_RGBA, 1); - - scale = 0.25f*sqrtf(sz*sz); - - for (y=0; y<sz; ++y) { - v = 2.f*(y / (float)sz) - 1.f; - for (x=0; x<sz; ++x) { - u = 2.f*(x / (float)sz) - 1.f; - r = (u*u + v*v)*scale; - d = -sqrtf(sqrtf(sqrtf(r)))*9.f; - fcol[0] = expf(d*cs_r), fcol[1] = expf(d*cs_g), fcol[2] = expf(d*cs_b); - // linear window good enough here, visual result counts, not scientific analysis - //w = (1.f-fabs(u))*(1.f-fabs(v)); - // actually, Hanning window is ok, cos^2 for some reason is slower - w = (0.5f + 0.5f*cos((double)u*M_PI))*(0.5f + 0.5f*cos((double)v*M_PI)); - mul_v3_fl(fcol, w); - qd_setPixel(ckrn, x, y, fcol); - } - } - - convolve(tsrc, tsrc, ckrn); - free_compbuf(ckrn); - mixImages(dst, tsrc, 0.5f + 0.5f*ndg->mix); - free_compbuf(tsrc); -} - -//-------------------------------------------------------------------------------------------- - -static void node_composit_exec_glare(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - CompBuf *new, *src, *img = in[0]->data; - NodeGlare* ndg = node->storage; - - if ((img == NULL) || (out[0]->hasoutput == 0)) return; - - if (img->type != CB_RGBA) { - new = typecheck_compbuf(img, CB_RGBA); - src = typecheck_compbuf(img, CB_RGBA); - } - else { - new = dupalloc_compbuf(img); - src = dupalloc_compbuf(img); - } - - { - int x, y; - for (y=0; y<new->y; ++y) { - fRGB* col = (fRGB*)&new->rect[y*new->x*new->type]; - for (x=0; x<new->x; ++x) { - col[x][0] = MAX2(col[x][0], 0.f); - col[x][1] = MAX2(col[x][1], 0.f); - col[x][2] = MAX2(col[x][2], 0.f); - } - } - } - - switch (ndg->type) { - case 0: - star4(ndg, new, src); - break; - case 1: - fglow(ndg, new, src); - break; - case 3: - ghosts(ndg, new, src); - break; - case 2: - default: - streaks(ndg, new, src); - break; - } - - free_compbuf(src); - out[0]->data = new; -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_glare(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { NodeGlare *ndg = MEM_callocN(sizeof(NodeGlare), "node glare data"); @@ -502,9 +66,6 @@ void register_node_type_cmp_glare(bNodeTreeType *ttype) node_type_size(&ntype, 150, 120, 200); node_type_init(&ntype, node_composit_init_glare); node_type_storage(&ntype, "NodeGlare", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_glare); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_hueSatVal.c b/source/blender/nodes/composite/nodes/node_composite_hueSatVal.c index d52e3d01a32..be748199bc5 100644 --- a/source/blender/nodes/composite/nodes/node_composite_hueSatVal.c +++ b/source/blender/nodes/composite/nodes/node_composite_hueSatVal.c @@ -44,59 +44,6 @@ static bNodeSocketTemplate cmp_node_hue_sat_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_hue_sat_fac(bNode *node, float *out, float *in, float *fac) -{ - NodeHueSat *nhs= node->storage; - - if (*fac!=0.0f && (nhs->hue!=0.5f || nhs->sat!=1.0f || nhs->val!=1.0f)) { - float col[3], hsv[3], mfac= 1.0f - *fac; - - rgb_to_hsv(in[0], in[1], in[2], hsv, hsv+1, hsv+2); - hsv[0]+= (nhs->hue - 0.5f); - if (hsv[0]>1.0f) hsv[0]-=1.0f; else if (hsv[0]<0.0f) hsv[0]+= 1.0f; - hsv[1]*= nhs->sat; - hsv[2]*= nhs->val; - hsv_to_rgb(hsv[0], hsv[1], hsv[2], col, col+1, col+2); - - out[0] = mfac*in[0] + *fac*col[0]; - out[1] = mfac*in[1] + *fac*col[1]; - out[2] = mfac*in[2] + *fac*col[2]; - out[3] = in[3]; - } - else { - copy_v4_v4(out, in); - } -} - -static void node_composit_exec_hue_sat(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - /* stack order in: Fac, Image */ - /* stack order out: Image */ - if (out[0]->hasoutput==0) return; - - /* input no image? then only color operation */ - if (in[1]->data==NULL) { - do_hue_sat_fac(node, out[0]->vec, in[1]->vec, in[0]->vec); - } - else { - /* make output size of input image */ - CompBuf *cbuf= dupalloc_compbuf(in[1]->data); - CompBuf *stackbuf=typecheck_compbuf(cbuf, CB_RGBA); - - composit2_pixel_processor(node, stackbuf, stackbuf, in[1]->vec, in[0]->data, in[0]->vec, do_hue_sat_fac, CB_RGBA, CB_VAL); - - out[0]->data= stackbuf; - - /* get rid of intermediary cbuf if it's extra */ - if (stackbuf!=cbuf) - free_compbuf(cbuf); - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_hue_sat(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { NodeHueSat *nhs= MEM_callocN(sizeof(NodeHueSat), "node hue sat"); @@ -115,9 +62,6 @@ void register_node_type_cmp_hue_sat(bNodeTreeType *ttype) node_type_size(&ntype, 150, 80, 250); node_type_init(&ntype, node_composit_init_hue_sat); node_type_storage(&ntype, "NodeHueSat", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_hue_sat); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_huecorrect.c b/source/blender/nodes/composite/nodes/node_composite_huecorrect.c index f751dbea8d2..45002b0aa0b 100644 --- a/source/blender/nodes/composite/nodes/node_composite_huecorrect.c +++ b/source/blender/nodes/composite/nodes/node_composite_huecorrect.c @@ -43,106 +43,6 @@ static bNodeSocketTemplate cmp_node_huecorrect_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_huecorrect(bNode *node, float *out, float *in) -{ - float hsv[3], f; - - rgb_to_hsv(in[0], in[1], in[2], hsv, hsv+1, hsv+2); - - curvemapping_initialize(node->storage); - - /* adjust hue, scaling returned default 0.5 up to 1 */ - f = curvemapping_evaluateF(node->storage, 0, hsv[0]); - hsv[0] += f-0.5f; - - /* adjust saturation, scaling returned default 0.5 up to 1 */ - f = curvemapping_evaluateF(node->storage, 1, hsv[0]); - hsv[1] *= (f * 2.f); - - /* adjust value, scaling returned default 0.5 up to 1 */ - f = curvemapping_evaluateF(node->storage, 2, hsv[0]); - hsv[2] *= (f * 2.f); - - hsv[0] = hsv[0] - floorf(hsv[0]); /* mod 1.0 */ - CLAMP(hsv[1], 0.f, 1.f); - - /* convert back to rgb */ - hsv_to_rgb(hsv[0], hsv[1], hsv[2], out, out+1, out+2); - - out[3] = in[3]; -} - -static void do_huecorrect_fac(bNode *node, float *out, float *in, float *fac) -{ - float hsv[3], rgb[3], f; - const float mfac = 1.f-*fac; - - rgb_to_hsv(in[0], in[1], in[2], hsv, hsv+1, hsv+2); - - curvemapping_initialize(node->storage); - - /* adjust hue, scaling returned default 0.5 up to 1 */ - f = curvemapping_evaluateF(node->storage, 0, hsv[0]); - hsv[0] += f-0.5f; - - /* adjust saturation, scaling returned default 0.5 up to 1 */ - f = curvemapping_evaluateF(node->storage, 1, hsv[0]); - hsv[1] *= (f * 2.f); - - /* adjust value, scaling returned default 0.5 up to 1 */ - f = curvemapping_evaluateF(node->storage, 2, hsv[0]); - hsv[2] *= (f * 2.f); - - hsv[0] = hsv[0] - floorf(hsv[0]); /* mod 1.0 */ - CLAMP(hsv[1], 0.f, 1.f); - - /* convert back to rgb */ - hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2); - - out[0] = mfac*in[0] + *fac*rgb[0]; - out[1] = mfac*in[1] + *fac*rgb[1]; - out[2] = mfac*in[2] + *fac*rgb[2]; - out[3] = in[3]; -} - -static void node_composit_exec_huecorrect(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - CompBuf *cbuf= in[1]->data; - CompBuf *stackbuf; - - /* stack order input: fac, image, black level, white level */ - /* stack order output: image */ - - if (out[0]->hasoutput==0) - return; - - if (in[0]->vec[0] == 0.f && in[0]->data == NULL) { - out[0]->data = pass_on_compbuf(cbuf); - return; - } - - /* input no image? then only color operation */ - if (in[1]->data==NULL) { - do_huecorrect_fac(node, out[0]->vec, in[1]->vec, in[0]->vec); - } - - if (cbuf) { - stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* make output size of input image */ - - if ((in[0]->data==NULL) && (in[0]->vec[0] >= 1.f)) - composit1_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, do_huecorrect, CB_RGBA); - else - composit2_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[0]->data, in[0]->vec, do_huecorrect_fac, CB_RGBA, CB_VAL); - - out[0]->data= stackbuf; - } - -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_huecorrect(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { CurveMapping *cumapping = node->storage= curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); @@ -168,9 +68,6 @@ void register_node_type_cmp_huecorrect(bNodeTreeType *ttype) node_type_size(&ntype, 320, 140, 400); node_type_init(&ntype, node_composit_init_huecorrect); node_type_storage(&ntype, "CurveMapping", node_free_curves, node_copy_curves); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_huecorrect); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_idMask.c b/source/blender/nodes/composite/nodes/node_composite_idMask.c index ef0c5021192..8aa08386ae9 100644 --- a/source/blender/nodes/composite/nodes/node_composite_idMask.c +++ b/source/blender/nodes/composite/nodes/node_composite_idMask.c @@ -44,72 +44,6 @@ static bNodeSocketTemplate cmp_node_idmask_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -/* stackbuf should be zeroed */ -static void do_idmask(CompBuf *stackbuf, CompBuf *cbuf, float idnr) -{ - float *rect; - int x; - char *abuf= MEM_mapallocN(cbuf->x*cbuf->y, "anti ali buf"); - - rect= cbuf->rect; - for (x= cbuf->x*cbuf->y - 1; x>=0; x--) - if (rect[x]==idnr) - abuf[x] = 255; - - antialias_tagbuf(cbuf->x, cbuf->y, abuf); - - rect= stackbuf->rect; - for (x= cbuf->x*cbuf->y - 1; x>=0; x--) - if (abuf[x]>1) - rect[x] = (1.0f/255.0f)*(float)abuf[x]; - - MEM_freeN(abuf); -} - -/* full sample version */ -static void do_idmask_fsa(CompBuf *stackbuf, CompBuf *cbuf, float idnr) -{ - float *rect, *rs; - int x; - - rect= cbuf->rect; - rs= stackbuf->rect; - for (x= cbuf->x*cbuf->y - 1; x>=0; x--) - if (rect[x]==idnr) - rs[x] = 1.0f; - -} - - -static void node_composit_exec_idmask(void *data, bNode *node, bNodeStack **in, bNodeStack **out) -{ - RenderData *rd= data; - - if (out[0]->hasoutput==0) - return; - - if (in[0]->data) { - CompBuf *cbuf= in[0]->data; - CompBuf *stackbuf; - - if (cbuf->type!=CB_VAL) - return; - - stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); /* allocs */; - - if ((rd->scemode & R_FULL_SAMPLE) || node->custom2 == 0) - do_idmask_fsa(stackbuf, cbuf, (float)node->custom1); - else - do_idmask(stackbuf, cbuf, (float)node->custom1); - - out[0]->data= stackbuf; - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_idmask(bNodeTreeType *ttype) { static bNodeType ntype; @@ -117,9 +51,6 @@ void register_node_type_cmp_idmask(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_ID_MASK, "ID Mask", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_idmask_in, cmp_node_idmask_out); node_type_size(&ntype, 140, 100, 320); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_idmask); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index 7e44210928c..66a141b8b6e 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -29,7 +29,6 @@ * \ingroup cmpnodes */ - #include "node_composite_util.h" /* **************** IMAGE (and RenderResult, multilayer image) ******************** */ @@ -285,242 +284,6 @@ static void cmp_node_image_update(bNodeTree *ntree, bNode *node) cmp_node_image_verify_outputs(ntree, node); } -#ifdef WITH_COMPOSITOR_LEGACY - -/* float buffer from the image with matching color management */ -float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc) -{ - float *rect; - - *alloc= FALSE; - - /* OCIO_TODO: this is a part of legacy compositor system, don't bother with porting this code - * to new color management system since this code would likely be simply removed soon - */ - if (rd->color_mgt_flag & R_COLOR_MANAGEMENT) { - rect= ibuf->rect_float; - } - else { - rect= MEM_mapallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, "node_composit_get_image"); - - IMB_buffer_float_from_float(rect, ibuf->rect_float, - 4, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, TRUE, - ibuf->x, ibuf->y, ibuf->x, ibuf->x); - - *alloc= TRUE; - } - - return rect; -} - -/* note: this function is used for multilayer too, to ensure uniform - * handling with BKE_image_acquire_ibuf() */ -static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *iuser) -{ - ImBuf *ibuf; - CompBuf *stackbuf; - int type; - - float *rect; - int alloc= FALSE; - - ibuf= BKE_image_acquire_ibuf(ima, iuser, NULL); - if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) { - return NULL; - } - - if (ibuf->rect_float == NULL) { - IMB_float_from_rect(ibuf); - } - - /* now we need a float buffer from the image with matching color management */ - /* XXX weak code, multilayer is excluded from this */ - if (ibuf->channels == 4 && ima->rr==NULL) { - rect= node_composit_get_float_buffer(rd, ibuf, &alloc); - } - else { - /* non-rgba passes can't use color profiles */ - rect= ibuf->rect_float; - } - /* done coercing into the correct color management */ - - - type= ibuf->channels; - - if (rd->scemode & R_COMP_CROP) { - stackbuf= get_cropped_compbuf(&rd->disprect, rect, ibuf->x, ibuf->y, type); - if (alloc) - MEM_freeN(rect); - } - else { - /* we put imbuf copy on stack, cbuf knows rect is from other ibuf when freed! */ - stackbuf= alloc_compbuf(ibuf->x, ibuf->y, type, FALSE); - stackbuf->rect= rect; - stackbuf->malloc= alloc; - } - - /* code to respect the premul flag of images; I'm - * not sure if this is a good idea for multilayer images, - * since it never worked before for them. - */ -#if 0 - if (type==CB_RGBA && ima->flag & IMA_DO_PREMUL) { - //premul the image - int i; - float *pixel = stackbuf->rect; - - for (i=0; i<stackbuf->x*stackbuf->y; i++, pixel += 4) { - pixel[0] *= pixel[3]; - pixel[1] *= pixel[3]; - pixel[2] *= pixel[3]; - } - } -#endif - - BKE_image_release_ibuf(ima, ibuf, NULL); - - return stackbuf; -} - -static CompBuf *node_composit_get_zimage(bNode *node, RenderData *rd) -{ - ImBuf *ibuf= BKE_image_acquire_ibuf((Image *)node->id, node->storage, NULL); - CompBuf *zbuf= NULL; - - if (ibuf && ibuf->zbuf_float) { - if (rd->scemode & R_COMP_CROP) { - zbuf= get_cropped_compbuf(&rd->disprect, ibuf->zbuf_float, ibuf->x, ibuf->y, CB_VAL); - } - else { - zbuf= alloc_compbuf(ibuf->x, ibuf->y, CB_VAL, 0); - zbuf->rect= ibuf->zbuf_float; - } - } - - BKE_image_release_ibuf((Image *)node->id, ibuf, NULL); - - return zbuf; -} - -/* check if layer is available, returns pass buffer */ -static CompBuf *compbuf_multilayer_get(RenderData *rd, RenderLayer *rl, Image *ima, ImageUser *iuser, int passindex) -{ - RenderPass *rpass = BLI_findlink(&rl->passes, passindex); - if (rpass) { - CompBuf *cbuf; - - iuser->pass = passindex; - BKE_image_multilayer_index(ima->rr, iuser); - cbuf = node_composit_get_image(rd, ima, iuser); - - return cbuf; - } - return NULL; -} - -static void node_composit_exec_image(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out) -{ - /* image assigned to output */ - /* stack order input sockets: col, alpha */ - if (node->id) { - RenderData *rd= data; - Image *ima= (Image *)node->id; - ImageUser *iuser= (ImageUser *)node->storage; - ImBuf *ibuf = NULL; - - /* first set the right frame number in iuser */ - BKE_image_user_frame_calc(iuser, rd->cfra, 0); - - /* force a load, we assume iuser index will be set OK anyway */ - if (ima->type==IMA_TYPE_MULTILAYER) - ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); - - if (ima->type==IMA_TYPE_MULTILAYER && ima->rr) { - RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer); - - if (rl) { - bNodeSocket *sock; - NodeImageLayer *sockdata; - int out_index; - CompBuf *combinedbuf= NULL, *firstbuf= NULL; - - for (sock=node->outputs.first, out_index=0; sock; sock=sock->next, ++out_index) { - sockdata = sock->storage; - if (out[out_index]->hasoutput) { - CompBuf *stackbuf = out[out_index]->data = compbuf_multilayer_get(rd, rl, ima, iuser, sockdata->pass_index); - if (stackbuf) { - /* preview policy: take first 'Combined' pass if available, - * otherwise just use the first layer. - */ - if (!firstbuf) { - firstbuf = stackbuf; - } - if (!combinedbuf && - (strcmp(sock->name, "Combined") == 0 || strcmp(sock->name, "Image") == 0)) - { - combinedbuf = stackbuf; - } - } - } - } - - /* preview */ - if (combinedbuf) - generate_preview(data, node, combinedbuf); - else if (firstbuf) - generate_preview(data, node, firstbuf); - } - } - else { - CompBuf *stackbuf = node_composit_get_image(rd, ima, iuser); - if (stackbuf) { - int num_outputs = BLI_countlist(&node->outputs); - - /*respect image premul option*/ - if (stackbuf->type==CB_RGBA && ima->flag & IMA_DO_PREMUL) { - int i; - float *pixel; - - /* first duplicate stackbuf->rect, since it's just a pointer - * to the source imbuf, and we don't want to change that.*/ - stackbuf->rect = MEM_dupallocN(stackbuf->rect); - - /* since stackbuf now has allocated memory, rather than just a pointer, - * mark it as allocated so it can be freed properly */ - stackbuf->malloc=1; - - /*premul the image*/ - pixel = stackbuf->rect; - for (i=0; i<stackbuf->x*stackbuf->y; i++, pixel += 4) { - pixel[0] *= pixel[3]; - pixel[1] *= pixel[3]; - pixel[2] *= pixel[3]; - } - } - - /* put image on stack */ - if (num_outputs > 0) - out[0]->data= stackbuf; - - /* alpha output */ - if (num_outputs > 1 && out[1]->hasoutput) - out[1]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A); - - /* Z output */ - if (num_outputs > 2 && out[2]->hasoutput) - out[2]->data= node_composit_get_zimage(node, rd); - - /* preview */ - generate_preview(data, node, stackbuf); - } - } - - BKE_image_release_ibuf(ima, ibuf, NULL); - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_image(bNodeTree *ntree, bNode *node, bNodeTemplate *UNUSED(ntemp)) { ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user"); @@ -565,9 +328,6 @@ void register_node_type_cmp_image(bNodeTreeType *ttype) node_type_init(&ntype, node_composit_init_image); node_type_storage(&ntype, "ImageUser", node_composit_free_image, node_composit_copy_image); node_type_update(&ntype, cmp_node_image_update, NULL); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_image); -#endif nodeRegisterType(ttype, &ntype); } @@ -575,141 +335,6 @@ void register_node_type_cmp_image(bNodeTreeType *ttype) /* **************** RENDER RESULT ******************** */ -#ifdef WITH_COMPOSITOR_LEGACY - -static CompBuf *compbuf_from_pass(RenderData *rd, RenderLayer *rl, int rectx, int recty, int passcode) -{ - float *fp= RE_RenderLayerGetPass(rl, passcode); - if (fp) { - CompBuf *buf; - int buftype= CB_VEC3; - - if (ELEM4(passcode, SCE_PASS_Z, SCE_PASS_INDEXOB, SCE_PASS_MIST, SCE_PASS_INDEXMA)) - buftype= CB_VAL; - else if (passcode==SCE_PASS_VECTOR) - buftype= CB_VEC4; - else if (ELEM(passcode, SCE_PASS_COMBINED, SCE_PASS_RGBA)) - buftype= CB_RGBA; - - if (rd->scemode & R_COMP_CROP) - buf= get_cropped_compbuf(&rd->disprect, fp, rectx, recty, buftype); - else { - buf= alloc_compbuf(rectx, recty, buftype, 0); - buf->rect= fp; - } - return buf; - } - return NULL; -} - -static void node_composit_rlayers_out(RenderData *rd, RenderLayer *rl, bNodeStack **out, int rectx, int recty) -{ - if (out[RRES_OUT_Z]->hasoutput) - out[RRES_OUT_Z]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_Z); - if (out[RRES_OUT_VEC]->hasoutput) - out[RRES_OUT_VEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_VECTOR); - if (out[RRES_OUT_NORMAL]->hasoutput) - out[RRES_OUT_NORMAL]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_NORMAL); - if (out[RRES_OUT_UV]->hasoutput) - out[RRES_OUT_UV]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_UV); - - if (out[RRES_OUT_RGBA]->hasoutput) - out[RRES_OUT_RGBA]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RGBA); - if (out[RRES_OUT_DIFF]->hasoutput) - out[RRES_OUT_DIFF]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE); - if (out[RRES_OUT_SPEC]->hasoutput) - out[RRES_OUT_SPEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SPEC); - if (out[RRES_OUT_SHADOW]->hasoutput) - out[RRES_OUT_SHADOW]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SHADOW); - if (out[RRES_OUT_AO]->hasoutput) - out[RRES_OUT_AO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_AO); - if (out[RRES_OUT_REFLECT]->hasoutput) - out[RRES_OUT_REFLECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFLECT); - if (out[RRES_OUT_REFRACT]->hasoutput) - out[RRES_OUT_REFRACT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFRACT); - if (out[RRES_OUT_INDIRECT]->hasoutput) - out[RRES_OUT_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDIRECT); - if (out[RRES_OUT_INDEXOB]->hasoutput) - out[RRES_OUT_INDEXOB]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXOB); - if (out[RRES_OUT_INDEXMA]->hasoutput) - out[RRES_OUT_INDEXMA]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXMA); - if (out[RRES_OUT_MIST]->hasoutput) - out[RRES_OUT_MIST]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_MIST); - if (out[RRES_OUT_EMIT]->hasoutput) - out[RRES_OUT_EMIT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_EMIT); - if (out[RRES_OUT_ENV]->hasoutput) - out[RRES_OUT_ENV]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_ENVIRONMENT); - if (out[RRES_OUT_DIFF_DIRECT]->hasoutput) - out[RRES_OUT_DIFF_DIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE_DIRECT); - if (out[RRES_OUT_DIFF_INDIRECT]->hasoutput) - out[RRES_OUT_DIFF_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE_INDIRECT); - if (out[RRES_OUT_DIFF_COLOR]->hasoutput) - out[RRES_OUT_DIFF_COLOR]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE_COLOR); - if (out[RRES_OUT_GLOSSY_DIRECT]->hasoutput) - out[RRES_OUT_GLOSSY_DIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_GLOSSY_DIRECT); - if (out[RRES_OUT_GLOSSY_INDIRECT]->hasoutput) - out[RRES_OUT_GLOSSY_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_GLOSSY_INDIRECT); - if (out[RRES_OUT_GLOSSY_COLOR]->hasoutput) - out[RRES_OUT_GLOSSY_COLOR]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_GLOSSY_COLOR); - if (out[RRES_OUT_TRANSM_DIRECT]->hasoutput) - out[RRES_OUT_TRANSM_DIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_TRANSM_DIRECT); - if (out[RRES_OUT_TRANSM_INDIRECT]->hasoutput) - out[RRES_OUT_TRANSM_INDIRECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_TRANSM_INDIRECT); - if (out[RRES_OUT_TRANSM_COLOR]->hasoutput) - out[RRES_OUT_TRANSM_COLOR]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_TRANSM_COLOR); -} - -static void node_composit_exec_rlayers(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out) -{ - Scene *sce= (Scene *)node->id; - Render *re= (sce)? RE_GetRender(sce->id.name): NULL; - RenderData *rd= data; - RenderResult *rr= NULL; - - if (re) - rr= RE_AcquireResultRead(re); - - if (rr) { - SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1); - if (srl) { - RenderLayer *rl= RE_GetRenderLayer(rr, srl->name); - if (rl && rl->rectf) { - CompBuf *stackbuf; - - /* we put render rect on stack, cbuf knows rect is from other ibuf when freed! */ - if (rd->scemode & R_COMP_CROP) - stackbuf= get_cropped_compbuf(&rd->disprect, rl->rectf, rr->rectx, rr->recty, CB_RGBA); - else { - stackbuf= alloc_compbuf(rr->rectx, rr->recty, CB_RGBA, 0); - stackbuf->rect= rl->rectf; - } - if (stackbuf==NULL) { - printf("Error; Preview Panel in UV Window returns zero sized image\n"); - } - else { - stackbuf->xof= rr->xof; - stackbuf->yof= rr->yof; - - /* put on stack */ - out[RRES_OUT_IMAGE]->data= stackbuf; - - if (out[RRES_OUT_ALPHA]->hasoutput) - out[RRES_OUT_ALPHA]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A); - - node_composit_rlayers_out(rd, rl, out, rr->rectx, rr->recty); - - generate_preview(data, node, stackbuf); - } - } - } - } - - if (re) - RE_ReleaseResult(re); -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_rlayers(bNodeTreeType *ttype) { static bNodeType ntype; @@ -717,9 +342,6 @@ void register_node_type_cmp_rlayers(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_R_LAYERS, "Render Layers", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS); node_type_socket_templates(&ntype, NULL, cmp_node_rlayers_out); node_type_size(&ntype, 150, 100, 300); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_rlayers); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_inpaint.c b/source/blender/nodes/composite/nodes/node_composite_inpaint.c index 25ecf428b4a..95e5834456c 100644 --- a/source/blender/nodes/composite/nodes/node_composite_inpaint.c +++ b/source/blender/nodes/composite/nodes/node_composite_inpaint.c @@ -44,15 +44,6 @@ static bNodeSocketTemplate cmp_node_inpaint_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void node_composit_exec_inpaint(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **UNUSED(in), bNodeStack **UNUSED(out)) -{ - /* pass */ -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_inpaint(bNodeTreeType *ttype) { static bNodeType ntype; @@ -60,9 +51,6 @@ void register_node_type_cmp_inpaint(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_INPAINT, "Inpaint", NODE_CLASS_OP_FILTER, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_inpaint_in, cmp_node_inpaint_out); node_type_size(&ntype, 130, 100, 320); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_inpaint); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_invert.c b/source/blender/nodes/composite/nodes/node_composite_invert.c index 2db6e42f603..05bccf84d58 100644 --- a/source/blender/nodes/composite/nodes/node_composite_invert.c +++ b/source/blender/nodes/composite/nodes/node_composite_invert.c @@ -43,82 +43,6 @@ static bNodeSocketTemplate cmp_node_invert_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_invert(bNode *node, float *out, float *in) -{ - if (node->custom1 & CMP_CHAN_RGB) { - out[0] = 1.0f - in[0]; - out[1] = 1.0f - in[1]; - out[2] = 1.0f - in[2]; - } - else { - copy_v3_v3(out, in); - } - - if (node->custom1 & CMP_CHAN_A) - out[3] = 1.0f - in[3]; - else - out[3] = in[3]; -} - -static void do_invert_fac(bNode *node, float *out, float *in, float *fac) -{ - float col[4], facm; - - do_invert(node, col, in); - - /* blend inverted result against original input with fac */ - facm = 1.0f - fac[0]; - - if (node->custom1 & CMP_CHAN_RGB) { - col[0] = fac[0]*col[0] + (facm*in[0]); - col[1] = fac[0]*col[1] + (facm*in[1]); - col[2] = fac[0]*col[2] + (facm*in[2]); - } - if (node->custom1 & CMP_CHAN_A) - col[3] = fac[0]*col[3] + (facm*in[3]); - - copy_v4_v4(out, col); -} - -static void node_composit_exec_invert(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - /* stack order in: fac, Image, Image */ - /* stack order out: Image */ - float *fac= in[0]->vec; - - if (out[0]->hasoutput==0) return; - - /* input no image? then only color operation */ - if (in[1]->data==NULL && in[0]->data==NULL) { - do_invert_fac(node, out[0]->vec, in[1]->vec, fac); - } - else { - /* make output size of first available input image, or then size of fac */ - CompBuf *cbuf= in[1]->data?in[1]->data:in[0]->data; - - /* if neither RGB or A toggled on, pass through */ - if (node->custom1 != 0) { - CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */ - - if (fac[0] < 1.0f || in[0]->data!=NULL) - composit2_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[0]->data, fac, do_invert_fac, CB_RGBA, CB_VAL); - else - composit1_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, do_invert, CB_RGBA); - out[0]->data= stackbuf; - return; - - } - else { - out[0]->data = pass_on_compbuf(cbuf); - return; - } - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_invert(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { node->custom1 |= CMP_CHAN_RGB; @@ -133,9 +57,6 @@ void register_node_type_cmp_invert(bNodeTreeType *ttype) node_type_socket_templates(&ntype, cmp_node_invert_in, cmp_node_invert_out); node_type_size(&ntype, 120, 120, 140); node_type_init(&ntype, node_composit_init_invert); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_invert); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_keying.c b/source/blender/nodes/composite/nodes/node_composite_keying.c index 6553df350ff..5e285095a4e 100644 --- a/source/blender/nodes/composite/nodes/node_composite_keying.c +++ b/source/blender/nodes/composite/nodes/node_composite_keying.c @@ -60,13 +60,6 @@ static bNodeSocketTemplate cmp_node_keying_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY -static void node_composit_exec_keying(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **UNUSED(in), bNodeStack **UNUSED(out)) -{ - /* pass */ -} -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_keying(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { NodeKeyingData *data; @@ -94,9 +87,6 @@ void register_node_type_cmp_keying(bNodeTreeType *ttype) node_type_size(&ntype, 140, 100, 320); node_type_init(&ntype, node_composit_init_keying); node_type_storage(&ntype, "NodeKeyingData", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_keying); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c index 96e905827cb..5db7f8fc991 100644 --- a/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c +++ b/source/blender/nodes/composite/nodes/node_composite_keyingscreen.c @@ -50,140 +50,6 @@ static bNodeSocketTemplate cmp_node_keyingscreen_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void compute_gradient_screen(RenderData *rd, NodeKeyingScreenData *keyingscreen_data, MovieClip *clip, CompBuf *screenbuf) -{ - MovieClipUser user = {0}; - MovieTracking *tracking = &clip->tracking; - MovieTrackingTrack *track; - VoronoiTriangulationPoint *triangulated_points; - VoronoiSite *sites; - ImBuf *ibuf; - ListBase *tracksbase; - ListBase edges = {NULL, NULL}; - int sites_total, triangulated_points_total, triangles_total; - int (*triangles)[3]; - int i, x, y; - float *rect = screenbuf->rect; - - if (keyingscreen_data->tracking_object[0]) { - MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, keyingscreen_data->tracking_object); - - if (!object) - return; - - tracksbase = BKE_tracking_object_get_tracks(tracking, object); - } - else - tracksbase = BKE_tracking_get_active_tracks(tracking); - - sites_total = BLI_countlist(tracksbase); - - if (!sites_total) - return; - - BKE_movieclip_user_set_frame(&user, rd->cfra); - ibuf = BKE_movieclip_get_ibuf(clip, &user); - - sites = MEM_callocN(sizeof(VoronoiSite) * sites_total, "keyingscreen voronoi sites"); - track = tracksbase->first; - i = 0; - while (track) { - VoronoiSite *site = &sites[i]; - MovieTrackingMarker *marker = BKE_tracking_marker_get(track, rd->cfra); - ImBuf *pattern_ibuf = BKE_tracking_get_pattern_imbuf(ibuf, track, marker, TRUE, FALSE); - int j; - - zero_v3(site->color); - - if (pattern_ibuf) { - for (j = 0; j < pattern_ibuf->x * pattern_ibuf->y; j++) { - if (pattern_ibuf->rect_float) { - add_v3_v3(site->color, &pattern_ibuf->rect_float[4 * j]); - } - else { - unsigned char *rrgb = (unsigned char *)pattern_ibuf->rect; - - site->color[0] += srgb_to_linearrgb((float)rrgb[4 * j + 0] / 255.0f); - site->color[1] += srgb_to_linearrgb((float)rrgb[4 * j + 1] / 255.0f); - site->color[2] += srgb_to_linearrgb((float)rrgb[4 * j + 2] / 255.0f); - } - } - - mul_v3_fl(site->color, 1.0f / (pattern_ibuf->x * pattern_ibuf->y)); - IMB_freeImBuf(pattern_ibuf); - } - - site->co[0] = marker->pos[0] * screenbuf->x; - site->co[1] = marker->pos[1] * screenbuf->y; - - track = track->next; - i++; - } - - IMB_freeImBuf(ibuf); - - BLI_voronoi_compute(sites, sites_total, screenbuf->x, screenbuf->y, &edges); - - BLI_voronoi_triangulate(sites, sites_total, &edges, screenbuf->x, screenbuf->y, - &triangulated_points, &triangulated_points_total, - &triangles, &triangles_total); - - for (y = 0; y < screenbuf->y; y++) { - for (x = 0; x < screenbuf->x; x++) { - int index = 4 * (y * screenbuf->x + x); - - rect[index + 0] = rect[index + 1] = rect[index + 2] = 0.0f; - rect[index + 3] = 1.0f; - - for (i = 0; i < triangles_total; i++) { - int *triangle = triangles[i]; - VoronoiTriangulationPoint *a = &triangulated_points[triangle[0]], - *b = &triangulated_points[triangle[1]], - *c = &triangulated_points[triangle[2]]; - float co[2] = {x, y}, w[3]; - - if (barycentric_coords_v2(a->co, b->co, c->co, co, w)) { - if (barycentric_inside_triangle_v2(w)) { - rect[index + 0] += a->color[0] * w[0] + b->color[0] * w[1] + c->color[0] * w[2]; - rect[index + 1] += a->color[1] * w[0] + b->color[1] * w[1] + c->color[1] * w[2]; - rect[index + 2] += a->color[2] * w[0] + b->color[2] * w[1] + c->color[2] * w[2]; - } - } - } - } - } - - MEM_freeN(triangulated_points); - MEM_freeN(triangles); - MEM_freeN(sites); - BLI_freelistN(&edges); -} - -static void node_composit_exec_keyingscreen(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out) -{ - NodeKeyingScreenData *keyingscreen_data = node->storage; - RenderData *rd = data; - CompBuf *screenbuf = NULL; - - if (node->id) { - MovieClip *clip = (MovieClip *) node->id; - MovieClipUser user = {0}; - int width, height; - - BKE_movieclip_user_set_frame(&user, rd->cfra); - BKE_movieclip_get_size(clip, &user, &width, &height); - - screenbuf = alloc_compbuf(width, height, CB_RGBA, TRUE); - compute_gradient_screen(rd, keyingscreen_data, clip, screenbuf); - } - - out[0]->data = screenbuf; -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_keyingscreen(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { NodeKeyingScreenData *data; @@ -202,9 +68,6 @@ void register_node_type_cmp_keyingscreen(bNodeTreeType *ttype) node_type_size(&ntype, 140, 100, 320); node_type_init(&ntype, node_composit_init_keyingscreen); node_type_storage(&ntype, "NodeKeyingScreenData", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_keyingscreen); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_lensdist.c b/source/blender/nodes/composite/nodes/node_composite_lensdist.c index 1ac8c457d45..e454022de3d 100644 --- a/source/blender/nodes/composite/nodes/node_composite_lensdist.c +++ b/source/blender/nodes/composite/nodes/node_composite_lensdist.c @@ -43,149 +43,6 @@ static bNodeSocketTemplate cmp_node_lensdist_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -/* assumes *dst is type RGBA */ -static void lensDistort(CompBuf *dst, CompBuf *src, float kr, float kg, float kb, int jit, int proj, int fit) -{ - int x, y, z; - const float cx = 0.5f*(float)dst->x, cy = 0.5f*(float)dst->y; - - if (proj) { - // shift - CompBuf *tsrc = dupalloc_compbuf(src); - - for (z=0; z<tsrc->type; ++z) - IIR_gauss(tsrc, (kr+0.5f)*(kr+0.5f), z, 1); - kr *= 20.f; - - for (y=0; y<dst->y; y++) { - fRGB *colp = (fRGB*)&dst->rect[y*dst->x*dst->type]; - const float v = (y + 0.5f)/(float)dst->y; - - for (x=0; x<dst->x; x++) { - const float u = (x + 0.5f)/(float)dst->x; - - qd_getPixelLerpChan(tsrc, (u*dst->x + kr) - 0.5f, v*dst->y - 0.5f, 0, colp[x]); - if (tsrc->type == CB_VAL) - colp[x][1] = tsrc->rect[x + y*tsrc->x]; - else - colp[x][1] = tsrc->rect[(x + y*tsrc->x)*tsrc->type + 1]; - qd_getPixelLerpChan(tsrc, (u*dst->x - kr) - 0.5f, v*dst->y - 0.5f, 2, colp[x]+2); - - /* set alpha */ - colp[x][3] = 1.0f; - } - } - free_compbuf(tsrc); - } - else { - // Spherical - // Scale factor to make bottom/top & right/left sides fit in window after deform - // so in the case of pincushion (kn < 0), corners will be outside window. - // Now also optionally scales image such that black areas are not visible when distort factor is positive - // (makes distorted corners match window corners, but really only valid if mk<=0.5) - const float mk = max_fff(kr, kg, kb); - const float sc = (fit && (mk > 0.f)) ? (1.f/(1.f + 2.f*mk)) : (1.f/(1.f + mk)); - const float drg = 4.f*(kg - kr), dgb = 4.f*(kb - kg); - - kr *= 4.f, kg *= 4.f, kb *= 4.f; - - for (y=0; y<dst->y; y++) { - fRGB *colp = (fRGB*)&dst->rect[y*dst->x*dst->type]; - const float v = sc*((y + 0.5f) - cy)/cy; - - for (x=0; x<dst->x; x++) { - int dr = 0, dg = 0, db = 0; - float d, t, ln[6] = {0, 0, 0, 0, 0, 0}; - fRGB c1, tc = {0, 0, 0, 0}; - const float u = sc*((x + 0.5f) - cx)/cx; - const float uv_dot = u * u + v * v; - int sta = 0, mid = 0, end = 0; - - if ((t = 1.f - kr*uv_dot) >= 0.f) { - d = 1.f/(1.f + sqrtf(t)); - ln[0] = (u*d + 0.5f)*dst->x - 0.5f, ln[1] = (v*d + 0.5f)*dst->y - 0.5f; - sta = 1; - } - if ((t = 1.f - kg*uv_dot) >= 0.f) { - d = 1.f/(1.f + sqrtf(t)); - ln[2] = (u*d + 0.5f)*dst->x - 0.5f, ln[3] = (v*d + 0.5f)*dst->y - 0.5f; - mid = 1; - } - if ((t = 1.f - kb*uv_dot) >= 0.f) { - d = 1.f/(1.f + sqrtf(t)); - ln[4] = (u*d + 0.5f)*dst->x - 0.5f, ln[5] = (v*d + 0.5f)*dst->y - 0.5f; - end = 1; - } - - if (sta && mid && end) { - // RG - const int dx = ln[2] - ln[0], dy = ln[3] - ln[1]; - const float dsf = sqrtf(dx*dx + dy*dy) + 1.f; - const int ds = (int)(jit ? ((dsf < 4.f) ? 2.f : sqrtf(dsf)) : dsf); - const float sd = 1.f/(float)ds; - - for (z=0; z<ds; ++z) { - const float tz = ((float)z + (jit ? BLI_frand() : 0.5f))*sd; - t = 1.f - (kr + tz*drg)*uv_dot; - d = 1.f / (1.f + sqrtf(t)); - qd_getPixelLerp(src, (u*d + 0.5f)*dst->x - 0.5f, (v*d + 0.5f)*dst->y - 0.5f, c1); - if (src->type == CB_VAL) c1[1] = c1[2] = c1[0]; - tc[0] += (1.f-tz)*c1[0], tc[1] += tz*c1[1]; - dr++, dg++; - } - // GB - { - const int dx = ln[4] - ln[2], dy = ln[5] - ln[3]; - const float dsf = sqrtf(dx*dx + dy*dy) + 1.f; - const int ds = (int)(jit ? ((dsf < 4.f) ? 2.f : sqrtf(dsf)) : dsf); - const float sd = 1.f/(float)ds; - - for (z=0; z<ds; ++z) { - const float tz = ((float)z + (jit ? BLI_frand() : 0.5f))*sd; - t = 1.f - (kg + tz*dgb)*uv_dot; - d = 1.f / (1.f + sqrtf(t)); - qd_getPixelLerp(src, (u*d + 0.5f)*dst->x - 0.5f, (v*d + 0.5f)*dst->y - 0.5f, c1); - if (src->type == CB_VAL) c1[1] = c1[2] = c1[0]; - tc[1] += (1.f-tz)*c1[1], tc[2] += tz*c1[2]; - dg++, db++; - } - } - } - - if (dr) colp[x][0] = 2.f*tc[0] / (float)dr; - if (dg) colp[x][1] = 2.f*tc[1] / (float)dg; - if (db) colp[x][2] = 2.f*tc[2] / (float)db; - - /* set alpha */ - colp[x][3] = 1.0f; - } - } - } -} - - -static void node_composit_exec_lensdist(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - CompBuf *new, *img = in[0]->data; - NodeLensDist *nld = node->storage; - const float k = MAX2(MIN2(in[1]->vec[0], 1.f), -0.999f); - // smaller dispersion range for somewhat more control - const float d = 0.25f*MAX2(MIN2(in[2]->vec[0], 1.f), 0.f); - const float kr = MAX2(MIN2((k+d), 1.f), -0.999f), kb = MAX2(MIN2((k-d), 1.f), -0.999f); - - if ((img==NULL) || (out[0]->hasoutput==0)) return; - - new = alloc_compbuf(img->x, img->y, CB_RGBA, 1); - - lensDistort(new, img, (nld->proj ? d : kr), k, kb, nld->jit, nld->proj, nld->fit); - - out[0]->data = new; -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_lensdist(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { NodeLensDist *nld = MEM_callocN(sizeof(NodeLensDist), "node lensdist data"); @@ -203,9 +60,6 @@ void register_node_type_cmp_lensdist(bNodeTreeType *ttype) node_type_size(&ntype, 150, 120, 200); node_type_init(&ntype, node_composit_init_lensdist); node_type_storage(&ntype, "NodeLensDist", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_lensdist); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_levels.c b/source/blender/nodes/composite/nodes/node_composite_levels.c index 57d94d6cb4d..5f9797d9123 100644 --- a/source/blender/nodes/composite/nodes/node_composite_levels.c +++ b/source/blender/nodes/composite/nodes/node_composite_levels.c @@ -45,274 +45,6 @@ static bNodeSocketTemplate cmp_node_view_levels_out[] = { {-1, 0, ""} }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void fill_bins(bNode *node, CompBuf* in, int* bins) -{ - float value[4]; - int ivalue=0; - int x, y; - - /*fill bins */ - for (y=0; y<in->y; y++) { - for (x=0; x<in->x; x++) { - - /* get the pixel */ - qd_getPixel(in, x, y, value); - - if (value[3] > 0.0f) { /* don't count transparent pixels */ - switch (node->custom1) { - case 1: { /* all colors */ - value[0] = rgb_to_bw(value); - value[0]=value[0]*255; /* scale to 0-255 range */ - ivalue=(int)value[0]; - break; - } - case 2: { /* red channel */ - value[0]=value[0]*255; /* scale to 0-255 range */ - ivalue=(int)value[0]; - break; - } - case 3: { /* green channel */ - value[1]=value[1]*255; /* scale to 0-255 range */ - ivalue=(int)value[1]; - break; - } - case 4: /*blue channel */ - { - value[2]=value[2]*255; /* scale to 0-255 range */ - ivalue=(int)value[2]; - break; - } - case 5: /* luminence */ - { - rgb_to_yuv(value[0], value[1], value[2], &value[0], &value[1], &value[2]); - value[0]=value[0]*255; /* scale to 0-255 range */ - ivalue=(int)value[0]; - break; - } - } /*end switch */ - - /*clip*/ - if (ivalue<0) ivalue=0; - if (ivalue>255) ivalue=255; - - /*put in the correct bin*/ - bins[ivalue]+=1; - } /*end if alpha */ - } - } -} - -static float brightness_mean(bNode *node, CompBuf* in) -{ - float sum=0.0; - int numPixels=0.0; - int x, y; - float value[4]; - - for (x=0; x< in->x; x++) { - for (y=0; y < in->y; y++) { - - /* get the pixel */ - qd_getPixel(in, x, y, value); - - if (value[3] > 0.0f) { /* don't count transparent pixels */ - numPixels++; - switch (node->custom1) { - case 1: - { - value[0] = rgb_to_bw(value); - sum+=value[0]; - break; - } - case 2: - { - sum+=value[0]; - break; - } - case 3: - { - sum+=value[1]; - break; - } - case 4: - { - sum+=value[2]; - break; - } - case 5: - { - rgb_to_yuv(value[0], value[1], value[2], &value[0], &value[1], &value[2]); - sum+=value[0]; - break; - } - } - } - } - } - - return sum/numPixels; -} - -static float brightness_standard_deviation(bNode *node, CompBuf* in, float mean) -{ - float sum=0.0; - int numPixels=0.0; - int x, y; - float value[4]; - - for (x=0; x< in->x; x++) { - for (y=0; y < in->y; y++) { - - /* get the pixel */ - qd_getPixel(in, x, y, value); - - if (value[3] > 0.0f) { /* don't count transparent pixels */ - numPixels++; - switch (node->custom1) { - case 1: - { - value[0] = rgb_to_bw(value); - sum+=(value[0]-mean)*(value[0]-mean); - break; - } - case 2: - { - sum+=value[0]; - sum+=(value[0]-mean)*(value[0]-mean); - break; - } - case 3: - { - sum+=value[1]; - sum+=(value[1]-mean)*(value[1]-mean); - break; - } - case 4: - { - sum+=value[2]; - sum+=(value[2]-mean)*(value[2]-mean); - break; - } - case 5: - { - rgb_to_yuv(value[0], value[1], value[2], &value[0], &value[1], &value[2]); - sum+=(value[0]-mean)*(value[0]-mean); - break; - } - } - } - } - } - - - return sqrt(sum/(float)(numPixels-1)); -} - -static void draw_histogram(bNode *node, CompBuf *out, int* bins) -{ - int x, y; - float color[4]; - float value; - int max; - - /* find max value */ - max=0; - for (x=0; x<256; x++) { - if (bins[x]>max) max=bins[x]; - } - - /*draw histogram in buffer */ - for (x=0; x<out->x; x++) { - for (y=0;y<out->y; y++) { - - /* get normalized value (0..255) */ - value=((float)bins[x]/(float)max)*255.0f; - - if (y < (int)value) { /*if the y value is below the height of the bar for this line then draw with the color */ - switch (node->custom1) { - case 1: { /* draw in black */ - color[0]=0.0; color[1]=0.0; color[2]=0.0; color[3]=1.0; - break; - } - case 2: { /* draw in red */ - color[0]=1.0; color[1]=0.0; color[2]=0.0; color[3]=1.0; - break; - } - case 3: { /* draw in green */ - color[0]=0.0; color[1]=1.0; color[2]=0.0; color[3]=1.0; - break; - } - case 4: { /* draw in blue */ - color[0]=0.0; color[1]=0.0; color[2]=1.0; color[3]=1.0; - break; - } - case 5: { /* draw in white */ - color[0]=1.0; color[1]=1.0; color[2]=1.0; color[3]=1.0; - break; - } - } - } - else { - color[0]=0.8; color[1]=0.8; color[2]=0.8; color[3]=1.0; - } - - /* set the color */ - qd_setPixel(out, x, y, color); - } - } -} - -static void node_composit_exec_view_levels(void *data, bNode *node, bNodeStack **in, bNodeStack **out) -{ - CompBuf* cbuf; - CompBuf* histogram; - float mean, std_dev; - int bins[256]; - int x; - - if (in[0]->hasinput==0) return; - if (in[0]->data==NULL) return; - - histogram=alloc_compbuf(256, 256, CB_RGBA, 1); - cbuf=typecheck_compbuf(in[0]->data, CB_RGBA); - - /*initalize bins*/ - for (x=0; x<256; x++) { - bins[x]=0; - } - - /*fill bins */ - fill_bins(node, in[0]->data, bins); - - /* draw the histogram chart */ - draw_histogram(node, histogram, bins); - - /* calculate the average brightness and contrast */ - mean=brightness_mean(node, in[0]->data); - std_dev=brightness_standard_deviation(node, in[0]->data, mean); - - /* Printf debuging ;) */ -#if 0 - printf("Mean: %f\n", mean); - printf("Std Dev: %f\n", std_dev); -#endif - - if (out[0]->hasoutput) - out[0]->vec[0] = mean; - if (out[1]->hasoutput) - out[1]->vec[0] = std_dev; - - generate_preview(data, node, histogram); - - if (cbuf!=in[0]->data) - free_compbuf(cbuf); - free_compbuf(histogram); -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_view_levels(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { node->custom1=1; /*All channels*/ @@ -327,9 +59,6 @@ void register_node_type_cmp_view_levels(bNodeTreeType *ttype) node_type_size(&ntype, 140, 100, 320); node_type_init(&ntype, node_composit_init_view_levels); node_type_storage(&ntype, "ImageUser", NULL, NULL); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_view_levels); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_lummaMatte.c b/source/blender/nodes/composite/nodes/node_composite_lummaMatte.c index ed232933139..6e0c877fe1c 100644 --- a/source/blender/nodes/composite/nodes/node_composite_lummaMatte.c +++ b/source/blender/nodes/composite/nodes/node_composite_lummaMatte.c @@ -45,61 +45,6 @@ static bNodeSocketTemplate cmp_node_luma_matte_out[] = { {-1, 0, ""} }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_luma_matte(bNode *node, float *out, float *in) -{ - NodeChroma *c=(NodeChroma *)node->storage; - float alpha; - - /* test range*/ - if (in[0]>c->t1) { - alpha=1.0; - } - else if (in[0]<c->t2) { - alpha=0.0; - } - else {/*blend */ - alpha=(in[0]-c->t2)/(c->t1-c->t2); - } - - /* don't make something that was more transparent less transparent */ - if (alpha<in[3]) { - out[3]=alpha; - } - else { - out[3]=in[3]; - } - -} - -static void node_composit_exec_luma_matte(void *data, bNode *node, bNodeStack **in, bNodeStack **out) -{ - CompBuf *cbuf; - CompBuf *outbuf; - - if (in[0]->hasinput==0) return; - if (in[0]->data==NULL) return; - if (out[0]->hasoutput==0 && out[1]->hasoutput==0) return; - - cbuf=typecheck_compbuf(in[0]->data, CB_RGBA); - - outbuf=dupalloc_compbuf(cbuf); - - composit1_pixel_processor(node, outbuf, cbuf, in[1]->vec, do_rgba_to_yuva, CB_RGBA); - composit1_pixel_processor(node, outbuf, outbuf, in[1]->vec, do_luma_matte, CB_RGBA); - composit1_pixel_processor(node, outbuf, outbuf, in[1]->vec, do_yuva_to_rgba, CB_RGBA); - - generate_preview(data, node, outbuf); - out[0]->data=outbuf; - if (out[1]->hasoutput) - out[1]->data=valbuf_from_rgbabuf(outbuf, CHAN_A); - if (cbuf!=in[0]->data) - free_compbuf(cbuf); -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_luma_matte(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma"); @@ -117,9 +62,6 @@ void register_node_type_cmp_luma_matte(bNodeTreeType *ttype) node_type_size(&ntype, 200, 80, 250); node_type_init(&ntype, node_composit_init_luma_matte); node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_luma_matte); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_mapUV.c b/source/blender/nodes/composite/nodes/node_composite_mapUV.c index 40092a84367..8fd49cd206b 100644 --- a/source/blender/nodes/composite/nodes/node_composite_mapUV.c +++ b/source/blender/nodes/composite/nodes/node_composite_mapUV.c @@ -44,128 +44,6 @@ static bNodeSocketTemplate cmp_node_mapuv_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -/* foreach UV, use these values to read in cbuf and write to stackbuf */ -/* stackbuf should be zeroed */ -static void do_mapuv(CompBuf *stackbuf, CompBuf *cbuf, CompBuf *uvbuf, float threshold) -{ - ImBuf *ibuf; - float *out= stackbuf->rect, *uv, *uvnext, *uvprev; - float dx, dy, alpha; - int x, y, sx, sy, row= 3*stackbuf->x; - - /* ibuf needed for sampling */ - ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0); - ibuf->rect_float= cbuf->rect; - - /* vars for efficient looping */ - uv= uvbuf->rect; - uvnext= uv+row; - uvprev= uv-row; - sx= stackbuf->x; - sy= stackbuf->y; - - for (y=0; y<sy; y++) { - for (x=0; x<sx; x++, out+=4, uv+=3, uvnext+=3, uvprev+=3) { - if (x>0 && x<sx-1 && y>0 && y<sy-1) { - if (uv[2]!=0.0f) { - float uv_l, uv_r; - - /* adaptive sampling, red (U) channel */ - - /* prevent alpha zero UVs to be used */ - uv_l= uv[-1]!=0.0f? fabsf(uv[0]-uv[-3]) : 0.0f; - uv_r= uv[ 5]!=0.0f? fabsf(uv[0]-uv[ 3]) : 0.0f; - - //dx= 0.5f*(fabs(uv[0]-uv[-3]) + fabs(uv[0]-uv[3])); - dx= 0.5f*(uv_l + uv_r); - - uv_l= uvprev[-1]!=0.0f? fabsf(uv[0]-uvprev[-3]) : 0.0f; - uv_r= uvnext[-1]!=0.0f? fabsf(uv[0]-uvnext[-3]) : 0.0f; - - //dx+= 0.25f*(fabs(uv[0]-uvprev[-3]) + fabs(uv[0]-uvnext[-3])); - dx+= 0.25f*(uv_l + uv_r); - - uv_l= uvprev[ 5]!=0.0f? fabsf(uv[0]-uvprev[+3]) : 0.0f; - uv_r= uvnext[ 5]!=0.0f? fabsf(uv[0]-uvnext[+3]) : 0.0f; - - //dx+= 0.25f*(fabs(uv[0]-uvprev[+3]) + fabs(uv[0]-uvnext[+3])); - dx+= 0.25f*(uv_l + uv_r); - - /* adaptive sampling, green (V) channel */ - - uv_l= uv[-row+2]!=0.0f? fabsf(uv[1]-uv[-row+1]) : 0.0f; - uv_r= uv[ row+2]!=0.0f? fabsf(uv[1]-uv[ row+1]) : 0.0f; - - //dy= 0.5f*(fabs(uv[1]-uv[-row+1]) + fabs(uv[1]-uv[row+1])); - dy= 0.5f*(uv_l + uv_r); - - uv_l= uvprev[-1]!=0.0f? fabsf(uv[1]-uvprev[+1-3]) : 0.0f; - uv_r= uvnext[-1]!=0.0f? fabsf(uv[1]-uvnext[+1-3]) : 0.0f; - - //dy+= 0.25f*(fabs(uv[1]-uvprev[+1-3]) + fabs(uv[1]-uvnext[+1-3])); - dy+= 0.25f*(uv_l + uv_r); - - uv_l= uvprev[ 5]!=0.0f? fabsf(uv[1]-uvprev[+1+3]) : 0.0f; - uv_r= uvnext[ 5]!=0.0f? fabsf(uv[1]-uvnext[+1+3]) : 0.0f; - - //dy+= 0.25f*(fabs(uv[1]-uvprev[+1+3]) + fabs(uv[1]-uvnext[+1+3])); - dy+= 0.25f*(uv_l + uv_r); - - /* UV to alpha threshold */ - alpha= 1.0f - threshold*(dx+dy); - if (alpha<0.0f) alpha= 0.0f; - else alpha*= uv[2]; - - /* should use mipmap */ - if (dx > 0.20f) dx= 0.20f; - if (dy > 0.20f) dy= 0.20f; - - ibuf_sample(ibuf, uv[0], uv[1], dx, dy, out); - /* premul */ - if (alpha<1.0f) { - out[0]*= alpha; - out[1]*= alpha; - out[2]*= alpha; - out[3]*= alpha; - } - } - } - } - } - - IMB_freeImBuf(ibuf); -} - - -static void node_composit_exec_mapuv(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - if (out[0]->hasoutput==0) - return; - - if (in[0]->data && in[1]->data) { - CompBuf *cbuf= in[0]->data; - CompBuf *uvbuf= in[1]->data; - CompBuf *stackbuf; - - cbuf= typecheck_compbuf(cbuf, CB_RGBA); - uvbuf= typecheck_compbuf(uvbuf, CB_VEC3); - stackbuf= alloc_compbuf(uvbuf->x, uvbuf->y, CB_RGBA, 1); /* allocs */; - - do_mapuv(stackbuf, cbuf, uvbuf, 0.05f*(float)node->custom1); - - out[0]->data= stackbuf; - - if (cbuf!=in[0]->data) - free_compbuf(cbuf); - if (uvbuf!=in[1]->data) - free_compbuf(uvbuf); - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_mapuv(bNodeTreeType *ttype) { static bNodeType ntype; @@ -173,9 +51,6 @@ void register_node_type_cmp_mapuv(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_MAP_UV, "Map UV", NODE_CLASS_DISTORT, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_mapuv_in, cmp_node_mapuv_out); node_type_size(&ntype, 140, 100, 320); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_mapuv); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_mapValue.c b/source/blender/nodes/composite/nodes/node_composite_mapValue.c index 677d5bd5013..62db0be5411 100644 --- a/source/blender/nodes/composite/nodes/node_composite_mapValue.c +++ b/source/blender/nodes/composite/nodes/node_composite_mapValue.c @@ -42,44 +42,6 @@ static bNodeSocketTemplate cmp_node_map_value_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_map_value(bNode *node, float *out, float *src) -{ - TexMapping *texmap= node->storage; - - out[0] = (src[0] + texmap->loc[0])*texmap->size[0]; - if (texmap->flag & TEXMAP_CLIP_MIN) - if (out[0]<texmap->min[0]) - out[0] = texmap->min[0]; - if (texmap->flag & TEXMAP_CLIP_MAX) - if (out[0]>texmap->max[0]) - out[0] = texmap->max[0]; -} - -static void node_composit_exec_map_value(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - /* stack order in: valbuf */ - /* stack order out: valbuf */ - if (out[0]->hasoutput==0) return; - - /* input no image? then only value operation */ - if (in[0]->data==NULL) { - do_map_value(node, out[0]->vec, in[0]->vec); - } - else { - /* make output size of input image */ - CompBuf *cbuf= in[0]->data; - CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); /* allocs */ - - composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_map_value, CB_VAL); - - out[0]->data= stackbuf; - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_map_value(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { node->storage= add_tex_mapping(); @@ -94,9 +56,6 @@ void register_node_type_cmp_map_value(bNodeTreeType *ttype) node_type_size(&ntype, 100, 60, 150); node_type_init(&ntype, node_composit_init_map_value); node_type_storage(&ntype, "TexMapping", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_map_value); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_mask.c b/source/blender/nodes/composite/nodes/node_composite_mask.c index 3463c1a8413..0bac68ab1ac 100644 --- a/source/blender/nodes/composite/nodes/node_composite_mask.c +++ b/source/blender/nodes/composite/nodes/node_composite_mask.c @@ -45,48 +45,6 @@ static bNodeSocketTemplate cmp_node_mask_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY -static void node_composit_exec_mask(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out) -{ - if (node->id) { - Mask *mask = (Mask *)node->id; - MaskRasterHandle *mr_handle; - CompBuf *stackbuf; - RenderData *rd = data; - float *res; - int sx, sy; - - if (!out[0]->hasoutput) { - /* the node's output socket is not connected to anything... - * do not execute any further, just exit the node immediately - */ - return; - } - - sx = (rd->size * rd->xsch) / 100; - sy = (rd->size * rd->ysch) / 100; - - /* allocate the output buffer */ - stackbuf = alloc_compbuf(sx, sy, CB_VAL, TRUE); - res = stackbuf->rect; - - /* mask raster begin */ - mr_handle = BKE_maskrasterize_handle_new(); - BKE_maskrasterize_handle_init(mr_handle, mask, - sx, sy, - TRUE, - (node->custom1 & CMP_NODEFLAG_MASK_AA) != 0, - (node->custom1 & CMP_NODEFLAG_MASK_NO_FEATHER) == 0); - BKE_maskrasterize_buffer(mr_handle, sx, sy, res); - BKE_maskrasterize_handle_free(mr_handle); - /* mask raster end */ - - /* pass on output and free */ - out[0]->data = stackbuf; - } -} -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_mask(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { NodeMask *data = MEM_callocN(sizeof(NodeMask), STRINGIFY(NodeMask)); @@ -105,9 +63,6 @@ void register_node_type_cmp_mask(bNodeTreeType *ttype) node_type_socket_templates(&ntype, NULL, cmp_node_mask_out); node_type_size(&ntype, 140, 100, 320); node_type_init(&ntype, node_composit_init_mask); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_mask); -#endif node_type_storage(&ntype, "NodeMask", node_free_standard_storage, node_copy_standard_storage); diff --git a/source/blender/nodes/composite/nodes/node_composite_math.c b/source/blender/nodes/composite/nodes/node_composite_math.c index 5bc67adf5fb..5bf555cd605 100644 --- a/source/blender/nodes/composite/nodes/node_composite_math.c +++ b/source/blender/nodes/composite/nodes/node_composite_math.c @@ -44,161 +44,6 @@ static bNodeSocketTemplate cmp_node_math_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_math(bNode *node, float *out, float *in, float *in2) -{ - switch (node->custom1) { - case 0: /* Add */ - out[0] = in[0] + in2[0]; - break; - case 1: /* Subtract */ - out[0] = in[0] - in2[0]; - break; - case 2: /* Multiply */ - out[0] = in[0] * in2[0]; - break; - case 3: /* Divide */ - { - if (in2[0]==0) /* We don't want to divide by zero. */ - out[0] = 0.0; - else - out[0] = in[0] / in2[0]; - } - break; - case 4: /* Sine */ - out[0] = sin(in[0]); - break; - case 5: /* Cosine */ - out[0] = cos(in[0]); - break; - case 6: /* Tangent */ - out[0] = tan(in[0]); - break; - case 7: /* Arc-Sine */ - { - /* Can't do the impossible... */ - if (in[0] <= 1 && in[0] >= -1 ) - out[0] = asin(in[0]); - else - out[0] = 0.0; - } - break; - case 8: /* Arc-Cosine */ - { - /* Can't do the impossible... */ - if ( in[0] <= 1 && in[0] >= -1 ) - out[0] = acos(in[0]); - else - out[0] = 0.0; - } - break; - case 9: /* Arc-Tangent */ - out[0] = atan(in[0]); - break; - case 10: /* Power */ - { - /* Only raise negative numbers by full integers */ - if ( in[0] >= 0 ) { - out[0] = pow(in[0], in2[0]); - } - else { - float y_mod_1 = fabsf(fmodf(in2[0], 1.0f)); - - /* if input value is not nearly an integer, fall back to zero, nicer than straight rounding */ - if (y_mod_1 > 0.999f || y_mod_1 < 0.001f) { - out[0] = powf(in[0], floorf(in2[0] + 0.5f)); - } - else { - out[0] = 0.0f; - } - } - } - break; - case 11: /* Logarithm */ - { - /* Don't want any imaginary numbers... */ - if ( in[0] > 0 && in2[0] > 0 ) - out[0] = log(in[0]) / log(in2[0]); - else - out[0] = 0.0; - } - break; - case 12: /* Minimum */ - { - if ( in[0] < in2[0] ) - out[0] = in[0]; - else - out[0] = in2[0]; - } - break; - case 13: /* Maximum */ - { - if ( in[0] > in2[0] ) - out[0] = in[0]; - else - out[0] = in2[0]; - } - break; - case 14: /* Round */ - { - /* round by the second value */ - if ( in2[0] != 0.0f ) - out[0] = floorf(in[0] / in2[0] + 0.5f) * in2[0]; - else - out[0] = floorf(in[0] + 0.5f); - } - break; - case 15: /* Less Than */ - { - if ( in[0] < in2[0] ) - out[0] = 1.0f; - else - out[0] = 0.0f; - } - break; - case 16: /* Greater Than */ - { - if ( in[0] > in2[0] ) - out[0] = 1.0f; - else - out[0] = 0.0f; - } - break; - } -} - -static void node_composit_exec_math(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - CompBuf *cbuf=in[0]->data; - CompBuf *cbuf2=in[1]->data; - CompBuf *stackbuf; - - /* check for inputs and outputs for early out*/ - if (out[0]->hasoutput==0) return; - - /* no image-color operation */ - if (in[0]->data==NULL && in[1]->data==NULL) { - do_math(node, out[0]->vec, in[0]->vec, in[1]->vec); - return; - } - - /* create output based on first input */ - if (cbuf) { - stackbuf=alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); - } - /* and if it doesn't exist use the second input since we - * know that one of them must exist at this point*/ - else { - stackbuf=alloc_compbuf(cbuf2->x, cbuf2->y, CB_VAL, 1); - } - - /* operate in case there's valid size */ - composit2_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_math, CB_VAL, CB_VAL); - out[0]->data= stackbuf; -} - -#endif /* WITH_COMPOSITOR_LEGACY */ void register_node_type_cmp_math(bNodeTreeType *ttype) { @@ -208,9 +53,6 @@ void register_node_type_cmp_math(bNodeTreeType *ttype) node_type_socket_templates(&ntype, cmp_node_math_in, cmp_node_math_out); node_type_size(&ntype, 120, 110, 160); node_type_label(&ntype, node_math_label); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_math); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_mixrgb.c b/source/blender/nodes/composite/nodes/node_composite_mixrgb.c index 5d3ee480612..fed73e13c92 100644 --- a/source/blender/nodes/composite/nodes/node_composite_mixrgb.c +++ b/source/blender/nodes/composite/nodes/node_composite_mixrgb.c @@ -43,48 +43,6 @@ static bNodeSocketTemplate cmp_node_mix_rgb_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_mix_rgb(bNode *node, float *out, float *in1, float *in2, float *fac) -{ - float col[3]; - - copy_v3_v3(col, in1); - if (node->custom2) - ramp_blend(node->custom1, col, in2[3]*fac[0], in2); - else - ramp_blend(node->custom1, col, fac[0], in2); - copy_v3_v3(out, col); - out[3] = in1[3]; -} - -static void node_composit_exec_mix_rgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out) -{ - /* stack order in: fac, Image, Image */ - /* stack order out: Image */ - float *fac= in[0]->vec; - - if (out[0]->hasoutput==0) return; - - /* input no image? then only color operation */ - if (in[1]->data==NULL && in[2]->data==NULL) { - do_mix_rgb(node, out[0]->vec, in[1]->vec, in[2]->vec, fac); - } - else { - /* make output size of first available input image */ - CompBuf *cbuf= in[1]->data?in[1]->data:in[2]->data; - CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */ - - composit3_pixel_processor(node, stackbuf, in[1]->data, in[1]->vec, in[2]->data, in[2]->vec, in[0]->data, fac, do_mix_rgb, CB_RGBA, CB_RGBA, CB_VAL); - - out[0]->data= stackbuf; - - generate_preview(data, node, out[0]->data); - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - /* custom1 = mix type */ void register_node_type_cmp_mix_rgb(bNodeTreeType *ttype) { @@ -94,9 +52,6 @@ void register_node_type_cmp_mix_rgb(bNodeTreeType *ttype) node_type_socket_templates(&ntype, cmp_node_mix_rgb_in, cmp_node_mix_rgb_out); node_type_size(&ntype, 110, 60, 120); node_type_label(&ntype, node_blend_label); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_mix_rgb); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_movieclip.c b/source/blender/nodes/composite/nodes/node_composite_movieclip.c index 370cff5e0d7..85745d2ff40 100644 --- a/source/blender/nodes/composite/nodes/node_composite_movieclip.c +++ b/source/blender/nodes/composite/nodes/node_composite_movieclip.c @@ -42,106 +42,6 @@ static bNodeSocketTemplate cmp_node_movieclip_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static CompBuf *node_composit_get_movieclip(RenderData *rd, MovieClip *clip, MovieClipUser *user) -{ - ImBuf *orig_ibuf, *ibuf; - CompBuf *stackbuf; - int type; - - float *rect; - int alloc = FALSE; - - orig_ibuf = BKE_movieclip_get_ibuf(clip, user); - - if (orig_ibuf == NULL || (orig_ibuf->rect == NULL && orig_ibuf->rect_float == NULL)) { - IMB_freeImBuf(orig_ibuf); - return NULL; - } - - ibuf = IMB_dupImBuf(orig_ibuf); - IMB_freeImBuf(orig_ibuf); - - if (ibuf->rect_float == NULL || (ibuf->userflags & IB_RECT_INVALID)) { - IMB_float_from_rect(ibuf); - ibuf->userflags &= ~IB_RECT_INVALID; - } - - /* now we need a float buffer from the image with matching color management */ - if (ibuf->channels == 4) { - rect = node_composit_get_float_buffer(rd, ibuf, &alloc); - } - else { - /* non-rgba passes can't use color profiles */ - rect = ibuf->rect_float; - } - /* done coercing into the correct color management */ - - if (!alloc) { - rect = MEM_dupallocN(rect); - alloc = TRUE; - } - - type = ibuf->channels; - - if (rd->scemode & R_COMP_CROP) { - stackbuf = get_cropped_compbuf(&rd->disprect, rect, ibuf->x, ibuf->y, type); - if (alloc) - MEM_freeN(rect); - } - else { - /* we put imbuf copy on stack, cbuf knows rect is from other ibuf when freed! */ - stackbuf = alloc_compbuf(ibuf->x, ibuf->y, type, FALSE); - stackbuf->rect = rect; - stackbuf->malloc = alloc; - } - - IMB_freeImBuf(ibuf); - - return stackbuf; -} - -static void node_composit_exec_movieclip(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out) -{ - if (node->id) { - RenderData *rd = data; - MovieClip *clip = (MovieClip *)node->id; - MovieClipUser *user = (MovieClipUser *)node->storage; - CompBuf *stackbuf = NULL; - - BKE_movieclip_user_set_frame(user, rd->cfra); - - stackbuf = node_composit_get_movieclip(rd, clip, user); - - if (stackbuf) { - MovieTrackingStabilization *stab = &clip->tracking.stabilization; - - /* put image on stack */ - out[0]->data = stackbuf; - - if (stab->flag & TRACKING_2D_STABILIZATION) { - float loc[2], scale, angle; - int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, rd->cfra); - - BKE_tracking_stabilization_data_get(&clip->tracking, clip_framenr, stackbuf->x, stackbuf->y, - loc, &scale, &angle); - - out[1]->vec[0] = loc[0]; - out[2]->vec[0] = loc[1]; - - out[3]->vec[0] = scale; - out[4]->vec[0] = angle; - } - - /* generate preview */ - generate_preview(data, node, stackbuf); - } - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { MovieClipUser *user = MEM_callocN(sizeof(MovieClipUser), "node movie clip user"); @@ -159,9 +59,6 @@ void register_node_type_cmp_movieclip(bNodeTreeType *ttype) node_type_size(&ntype, 120, 80, 300); node_type_init(&ntype, init); node_type_storage(&ntype, "MovieClipUser", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_movieclip); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c b/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c index 9f4cd467c94..4817c59bbbd 100644 --- a/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c +++ b/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c @@ -30,9 +30,6 @@ * \ingroup cmpnodes */ -#include "BLF_translation.h" - - #include "node_composite_util.h" /* **************** Translate ******************** */ @@ -47,66 +44,6 @@ static bNodeSocketTemplate cmp_node_moviedistortion_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY -static void node_composit_exec_moviedistortion(void *data, bNode *node, bNodeStack **in, bNodeStack **out) -{ - if (in[0]->data) { - if (node->id) { - MovieClip *clip = (MovieClip *)node->id; - CompBuf *cbuf = typecheck_compbuf(in[0]->data, CB_RGBA); - CompBuf *stackbuf = alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 0); - ImBuf *ibuf; - - ibuf = IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0); - - if (ibuf) { - RenderData *rd = data; - ImBuf *obuf; - MovieTracking *tracking = &clip->tracking; - int width, height; - float overscan = 0.0f; - MovieClipUser user = {0}; - - BKE_movieclip_user_set_frame(&user, rd->cfra); - - ibuf->rect_float = cbuf->rect; - - BKE_movieclip_get_size(clip, &user, &width, &height); - - if (!node->storage) - node->storage = BKE_tracking_distortion_new(); - - if (node->custom1 == 0) - obuf = BKE_tracking_distortion_exec(node->storage, tracking, ibuf, width, height, overscan, 1); - else - obuf = BKE_tracking_distortion_exec(node->storage, tracking, ibuf, width, height, overscan, 0); - - stackbuf->rect = obuf->rect_float; - stackbuf->malloc = TRUE; - - obuf->mall &= ~IB_rectfloat; - obuf->rect_float = NULL; - - IMB_freeImBuf(ibuf); - IMB_freeImBuf(obuf); - } - - /* pass on output and free */ - out[0]->data = stackbuf; - - if (cbuf != in[0]->data) - free_compbuf(cbuf); - } - else { - CompBuf *cbuf = in[0]->data; - CompBuf *stackbuf = pass_on_compbuf(cbuf); - - out[0]->data = stackbuf; - } - } -} -#endif /* WITH_COMPOSITOR_LEGACY */ - static const char *label(bNode *node) { if (node->custom1 == 0) @@ -137,9 +74,6 @@ void register_node_type_cmp_moviedistortion(bNodeTreeType *ttype) node_type_socket_templates(&ntype, cmp_node_moviedistortion_in, cmp_node_moviedistortion_out); node_type_size(&ntype, 140, 100, 320); node_type_label(&ntype, label); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_moviedistortion); -#endif node_type_storage(&ntype, NULL, storage_free, storage_copy); diff --git a/source/blender/nodes/composite/nodes/node_composite_normal.c b/source/blender/nodes/composite/nodes/node_composite_normal.c index d104e8f03e6..1497757bbf4 100644 --- a/source/blender/nodes/composite/nodes/node_composite_normal.c +++ b/source/blender/nodes/composite/nodes/node_composite_normal.c @@ -45,44 +45,6 @@ static bNodeSocketTemplate cmp_node_normal_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_normal(bNode *node, float *out, float *in) -{ - bNodeSocket *sock= node->outputs.first; - float *nor= ((bNodeSocketValueVector*)sock->default_value)->value; - - /* render normals point inside... the widget points outside */ - out[0] = -dot_v3v3(nor, in); -} - -/* generates normal, does dot product */ -static void node_composit_exec_normal(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - bNodeSocket *sock= node->outputs.first; - float *nor= ((bNodeSocketValueVector*)sock->default_value)->value; - /* stack order input: normal */ - /* stack order output: normal, value */ - - /* input no image? then only vector op */ - if (in[0]->data==NULL) { - copy_v3_v3(out[0]->vec, nor); - /* render normals point inside... the widget points outside */ - out[1]->vec[0] = -dot_v3v3(out[0]->vec, in[0]->vec); - } - else if (out[1]->hasoutput) { - /* make output size of input image */ - CompBuf *cbuf= in[0]->data; - CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); /* allocs */ - - composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_normal, CB_VEC3); - - out[1]->data= stackbuf; - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { bNodeSocket *sock= node->outputs.first; @@ -101,9 +63,6 @@ void register_node_type_cmp_normal(bNodeTreeType *ttype) node_type_socket_templates(&ntype, cmp_node_normal_in, cmp_node_normal_out); node_type_init(&ntype, init); node_type_size(&ntype, 100, 60, 200); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_normal); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_normalize.c b/source/blender/nodes/composite/nodes/node_composite_normalize.c index 19b543dce5d..f90a5cdba74 100644 --- a/source/blender/nodes/composite/nodes/node_composite_normalize.c +++ b/source/blender/nodes/composite/nodes/node_composite_normalize.c @@ -43,69 +43,6 @@ static bNodeSocketTemplate cmp_node_normalize_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_normalize(bNode *UNUSED(node), float *out, float *src, float *min, float *mult) -{ - float res; - res = (src[0] - min[0]) * mult[0]; - if (res > 1.0f) { - out[0] = 1.0f; - } - else if (res < 0.0f) { - out[0] = 0.0f; - } - else { - out[0] = res; - } -} - -/* The code below assumes all data is inside range +- this, and that input buffer is single channel */ -#define BLENDER_ZMAX 10000.0f - -static void node_composit_exec_normalize(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - /* stack order in: valbuf */ - /* stack order out: valbuf */ - if (out[0]->hasoutput==0) return; - - /* Input has no image buffer? Then pass the value */ - if (in[0]->data==NULL) { - copy_v4_v4(out[0]->vec, in[0]->vec); - } - else { - float min = 1.0f+BLENDER_ZMAX; - float max = -1.0f-BLENDER_ZMAX; - float mult = 1.0f; - float *val; - /* make output size of input image */ - CompBuf *cbuf= in[0]->data; - int tot= cbuf->x*cbuf->y; - CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); /* allocs */ - - for (val = cbuf->rect; tot; tot--, val++) { - if ((*val > max) && (*val <= BLENDER_ZMAX)) { - max = *val; - } - if ((*val < min) && (*val >= -BLENDER_ZMAX)) { - min = *val; - } - } - /* In the rare case of flat buffer, which would cause a divide by 0, just pass the input to the output */ - if ((max-min) != 0.0f) { - mult = 1.0f/(max-min); - composit3_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, NULL, &min, NULL, &mult, do_normalize, CB_VAL, CB_VAL, CB_VAL); - } - else { - memcpy(stackbuf->rect, cbuf->rect, sizeof(float) * cbuf->x * cbuf->y); - } - - out[0]->data= stackbuf; - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_normalize(bNodeTreeType *ttype) { static bNodeType ntype; @@ -113,9 +50,6 @@ void register_node_type_cmp_normalize(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_NORMALIZE, "Normalize", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_normalize_in, cmp_node_normalize_out); node_type_size(&ntype, 100, 60, 150); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_normalize); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_outputFile.c b/source/blender/nodes/composite/nodes/node_composite_outputFile.c index fe23f7373fb..e8a650682c2 100644 --- a/source/blender/nodes/composite/nodes/node_composite_outputFile.c +++ b/source/blender/nodes/composite/nodes/node_composite_outputFile.c @@ -225,183 +225,6 @@ static void update_output_file(bNodeTree *UNUSED(ntree), bNode *node) } } -#ifdef WITH_COMPOSITOR_LEGACY - -/* write input data into individual files */ -static void exec_output_file_singlelayer(RenderData *rd, bNode *node, bNodeStack **in) -{ - Main *bmain= G.main; /* TODO, have this passed along */ - NodeImageMultiFile *nimf= node->storage; - bNodeSocket *sock; - int i; - int has_preview = 0; - - for (sock=node->inputs.first, i=0; sock; sock=sock->next, ++i) { - if (in[i]->data) { - NodeImageMultiFileSocket *sockdata = sock->storage; - ImageFormatData *format = (sockdata->use_node_format ? &nimf->format : &sockdata->format); - char path[FILE_MAX]; - char filename[FILE_MAX]; - CompBuf *cbuf = NULL; - ImBuf *ibuf; - - switch (format->planes) { - case R_IMF_PLANES_BW: - cbuf = typecheck_compbuf(in[i]->data, CB_VAL); - break; - case R_IMF_PLANES_RGB: - cbuf = typecheck_compbuf(in[i]->data, CB_VEC3); - break; - case R_IMF_PLANES_RGBA: - cbuf = typecheck_compbuf(in[i]->data, CB_RGBA); - break; - } - - ibuf = IMB_allocImBuf(cbuf->x, cbuf->y, format->planes, 0); - /* XXX have to set this explicitly it seems */ - switch (format->planes) { - case R_IMF_PLANES_BW: ibuf->channels = 1; break; - case R_IMF_PLANES_RGB: ibuf->channels = 3; break; - case R_IMF_PLANES_RGBA: ibuf->channels = 4; break; - } - ibuf->rect_float = cbuf->rect; - ibuf->dither = rd->dither_intensity; - - /* get full path */ - BLI_join_dirfile(path, FILE_MAX, nimf->base_path, sockdata->path); - BKE_makepicstring(filename, path, bmain->name, rd->cfra, format, (rd->scemode & R_EXTENSION), TRUE); - - if (0 == BKE_imbuf_write(ibuf, filename, format)) - printf("Cannot save Node File Output to %s\n", filename); - else - printf("Saved: %s\n", filename); - - IMB_freeImBuf(ibuf); - - /* simply pick the first valid input for preview */ - if (!has_preview) { - generate_preview(rd, node, cbuf); - has_preview = 1; - } - - if (in[i]->data != cbuf) - free_compbuf(cbuf); - } - } -} - -/* write input data into layers */ -static void exec_output_file_multilayer(RenderData *rd, bNode *node, bNodeStack **in) -{ - Main *bmain= G.main; /* TODO, have this passed along */ - NodeImageMultiFile *nimf= node->storage; - void *exrhandle= IMB_exr_get_handle(); - char filename[FILE_MAX]; - bNodeSocket *sock; - int i; - /* Must have consistent pixel size for exr file, simply take the first valid input size. */ - int rectx = -1; - int recty = -1; - int has_preview = 0; - - BKE_makepicstring_from_type(filename, nimf->base_path, bmain->name, rd->cfra, R_IMF_IMTYPE_MULTILAYER, (rd->scemode & R_EXTENSION), TRUE); - BLI_make_existing_file(filename); - - for (sock=node->inputs.first, i=0; sock; sock=sock->next, ++i) { - if (in[i]->data) { - NodeImageMultiFileSocket *sockdata = sock->storage; - CompBuf *cbuf = in[i]->data; - char channelname[EXR_TOT_MAXNAME]; /* '.' and single character channel name is appended */ - char *channelname_ext; - - if (cbuf->rect_procedural) { - printf("Error writing multilayer EXR: Procedural buffer not supported\n"); - continue; - } - if (rectx < 0) { - rectx = cbuf->x; - recty = cbuf->y; - } - else if (cbuf->x != rectx || cbuf->y != recty) { - printf("Error: Multilayer EXR output node %s expects same resolution for all input buffers. Layer %s skipped.\n", node->name, sock->name); - continue; - } - - BLI_strncpy(channelname, sockdata->layer, sizeof(channelname)-2); - channelname_ext = channelname + strlen(channelname); - - /* create channels */ - switch (cbuf->type) { - case CB_VAL: - strcpy(channelname_ext, ".V"); - IMB_exr_add_channel(exrhandle, NULL, channelname, 1, rectx, cbuf->rect); - break; - case CB_VEC2: - strcpy(channelname_ext, ".X"); - IMB_exr_add_channel(exrhandle, NULL, channelname, 2, 2*rectx, cbuf->rect); - strcpy(channelname_ext, ".Y"); - IMB_exr_add_channel(exrhandle, NULL, channelname, 2, 2*rectx, cbuf->rect+1); - break; - case CB_VEC3: - strcpy(channelname_ext, ".X"); - IMB_exr_add_channel(exrhandle, NULL, channelname, 3, 3*rectx, cbuf->rect); - strcpy(channelname_ext, ".Y"); - IMB_exr_add_channel(exrhandle, NULL, channelname, 3, 3*rectx, cbuf->rect+1); - strcpy(channelname_ext, ".Z"); - IMB_exr_add_channel(exrhandle, NULL, channelname, 3, 3*rectx, cbuf->rect+2); - break; - case CB_RGBA: - strcpy(channelname_ext, ".R"); - IMB_exr_add_channel(exrhandle, NULL, channelname, 4, 4*rectx, cbuf->rect); - strcpy(channelname_ext, ".G"); - IMB_exr_add_channel(exrhandle, NULL, channelname, 4, 4*rectx, cbuf->rect+1); - strcpy(channelname_ext, ".B"); - IMB_exr_add_channel(exrhandle, NULL, channelname, 4, 4*rectx, cbuf->rect+2); - strcpy(channelname_ext, ".A"); - IMB_exr_add_channel(exrhandle, NULL, channelname, 4, 4*rectx, cbuf->rect+3); - break; - } - - /* simply pick the first valid input for preview */ - if (!has_preview) { - generate_preview(rd, node, cbuf); - has_preview = 1; - } - } - } - - /* when the filename has no permissions, this can fail */ - if (IMB_exr_begin_write(exrhandle, filename, rectx, recty, nimf->format.exr_codec)) { - IMB_exr_write_channels(exrhandle); - } - else { - /* TODO, get the error from openexr's exception */ - /* XXX nice way to do report? */ - printf("Error Writing Render Result, see console\n"); - } - - IMB_exr_close(exrhandle); -} - -static void node_composit_exec_outputfile(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out)) -{ - RenderData *rd= data; - NodeImageMultiFile *nimf= node->storage; - - if (G.is_rendering == FALSE) { - /* only output files when rendering a sequence - - * otherwise, it overwrites the output files just - * scrubbing through the timeline when the compositor updates */ - return; - } - - if (nimf->format.imtype==R_IMF_IMTYPE_MULTILAYER) - exec_output_file_multilayer(rd, node, in); - else - exec_output_file_singlelayer(rd, node, in); -} -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_output_file(bNodeTreeType *ttype) { static bNodeType ntype; @@ -412,9 +235,6 @@ void register_node_type_cmp_output_file(bNodeTreeType *ttype) node_type_init(&ntype, init_output_file); node_type_storage(&ntype, "NodeImageMultiFile", free_output_file, copy_output_file); node_type_update(&ntype, update_output_file, NULL); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_outputfile); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_premulkey.c b/source/blender/nodes/composite/nodes/node_composite_premulkey.c index 7f7b7692b02..88f583b402e 100644 --- a/source/blender/nodes/composite/nodes/node_composite_premulkey.c +++ b/source/blender/nodes/composite/nodes/node_composite_premulkey.c @@ -44,27 +44,6 @@ static bNodeSocketTemplate cmp_node_premulkey_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void node_composit_exec_premulkey(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - if (out[0]->hasoutput==0) - return; - - if (in[0]->data) { - CompBuf *stackbuf, *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA); - - stackbuf= dupalloc_compbuf(cbuf); - premul_compbuf(stackbuf, node->custom1 == 1); - - out[0]->data = stackbuf; - if (cbuf != in[0]->data) - free_compbuf(cbuf); - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_premulkey(bNodeTreeType *ttype) { static bNodeType ntype; @@ -72,9 +51,6 @@ void register_node_type_cmp_premulkey(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_PREMULKEY, "Alpha Convert", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_premulkey_in, cmp_node_premulkey_out); node_type_size(&ntype, 140, 100, 320); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_premulkey); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_rgb.c b/source/blender/nodes/composite/nodes/node_composite_rgb.c index 54fba650783..ad06d7a9a7e 100644 --- a/source/blender/nodes/composite/nodes/node_composite_rgb.c +++ b/source/blender/nodes/composite/nodes/node_composite_rgb.c @@ -39,18 +39,6 @@ static bNodeSocketTemplate cmp_node_rgb_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void node_composit_exec_rgb(void *UNUSED(data), bNode *node, bNodeStack **UNUSED(in), bNodeStack **out) -{ - bNodeSocket *sock= node->outputs.first; - float *col= ((bNodeSocketValueRGBA*)sock->default_value)->value; - - copy_v4_v4(out[0]->vec, col); -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_rgb(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { bNodeSocket *sock= node->outputs.first; @@ -70,9 +58,6 @@ void register_node_type_cmp_rgb(bNodeTreeType *ttype) node_type_socket_templates(&ntype, NULL, cmp_node_rgb_out); node_type_init(&ntype, node_composit_init_rgb); node_type_size(&ntype, 140, 80, 140); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_rgb); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_rotate.c b/source/blender/nodes/composite/nodes/node_composite_rotate.c index 50c8b2a78c1..4eb869e5444 100644 --- a/source/blender/nodes/composite/nodes/node_composite_rotate.c +++ b/source/blender/nodes/composite/nodes/node_composite_rotate.c @@ -44,87 +44,6 @@ static bNodeSocketTemplate cmp_node_rotate_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -/* only supports RGBA nodes now */ -static void node_composit_exec_rotate(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - - if (out[0]->hasoutput==0) - return; - - if (in[0]->data) { - CompBuf *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA); - CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* note, this returns zero'd image */ - float rad, u, v, s, c, centx, centy, miny, maxy, minx, maxx; - int x, y, yo, xo; - ImBuf *ibuf, *obuf; - - rad= in[1]->vec[0]; - - - s= sin(rad); - c= cos(rad); - centx= cbuf->x/2; - centy= cbuf->y/2; - - minx= -centx; - maxx= -centx + (float)cbuf->x; - miny= -centy; - maxy= -centy + (float)cbuf->y; - - - ibuf=IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0); - obuf=IMB_allocImBuf(stackbuf->x, stackbuf->y, 32, 0); - - if (ibuf && obuf) { - ibuf->rect_float=cbuf->rect; - obuf->rect_float=stackbuf->rect; - - for (y=miny; y<maxy; y++) { - yo= y+(int)centy; - - for (x=minx; x<maxx;x++) { - u=c*x + y*s + centx; - v=-s*x + c*y + centy; - xo= x+(int)centx; - - switch (node->custom1) { - case 0: - nearest_interpolation(ibuf, obuf, u, v, xo, yo); - break; - case 1: - bilinear_interpolation(ibuf, obuf, u, v, xo, yo); - break; - case 2: - bicubic_interpolation(ibuf, obuf, u, v, xo, yo); - break; - } - - } - } - - /* rotate offset vector too, but why negative rad, ehh?? Has to be replaced with [3][3] matrix once (ton) */ - s= sin(-rad); - c= cos(-rad); - centx= (float)cbuf->xof; centy= (float)cbuf->yof; - stackbuf->xof= (int)( c*centx + s*centy); - stackbuf->yof= (int)(-s*centx + c*centy); - - IMB_freeImBuf(ibuf); - IMB_freeImBuf(obuf); - } - - /* pass on output and free */ - out[0]->data= stackbuf; - if (cbuf!=in[0]->data) { - free_compbuf(cbuf); - } - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_rotate(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { node->custom1= 1; /* Bilinear Filter*/ @@ -138,9 +57,6 @@ void register_node_type_cmp_rotate(bNodeTreeType *ttype) node_type_socket_templates(&ntype, cmp_node_rotate_in, cmp_node_rotate_out); node_type_size(&ntype, 140, 100, 320); node_type_init(&ntype, node_composit_init_rotate); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_rotate); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_scale.c b/source/blender/nodes/composite/nodes/node_composite_scale.c index 2224d653c37..5136aec112d 100644 --- a/source/blender/nodes/composite/nodes/node_composite_scale.c +++ b/source/blender/nodes/composite/nodes/node_composite_scale.c @@ -45,147 +45,6 @@ static bNodeSocketTemplate cmp_node_scale_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -/* only supports RGBA nodes now */ -/* node->custom1 stores if input values are absolute or relative scale */ -static void node_composit_exec_scale(void *data, bNode *node, bNodeStack **in, bNodeStack **out) -{ - if (out[0]->hasoutput == 0) - return; - - if (in[0]->data) { - RenderData *rd = data; - CompBuf *stackbuf, *cbuf = typecheck_compbuf(in[0]->data, CB_RGBA); - ImBuf *ibuf; - int newx, newy; - float ofsx = 0.0f, ofsy = 0.0f; - - if (node->custom1 == CMP_SCALE_RELATIVE) { - newx = MAX2((int)(in[1]->vec[0] * cbuf->x), 1); - newy = MAX2((int)(in[2]->vec[0] * cbuf->y), 1); - } - else if (node->custom1 == CMP_SCALE_SCENEPERCENT) { - newx = cbuf->x * (rd->size / 100.0f); - newy = cbuf->y * (rd->size / 100.0f); - } - else if (node->custom1 == CMP_SCALE_RENDERPERCENT) { - - if (node->custom3 != 0.0f || node->custom4 != 0.0f) { - const float w_dst = (rd->xsch * rd->size) / 100; - const float h_dst = (rd->ysch * rd->size) / 100; - - if (w_dst > h_dst) { - ofsx = node->custom3 * w_dst; - ofsy = node->custom4 * w_dst; - } - else { - ofsx = node->custom3 * h_dst; - ofsy = node->custom4 * h_dst; - } - } - - /* supports framing options */ - if (node->custom2 & CMP_SCALE_RENDERSIZE_FRAME_ASPECT) { - /* apply aspect from clip */ - const float w_src = cbuf->x; - const float h_src = cbuf->y; - - /* destination aspect is already applied from the camera frame */ - const float w_dst = (rd->xsch * rd->size) / 100; - const float h_dst = (rd->ysch * rd->size) / 100; - - const float asp_src = w_src / h_src; - const float asp_dst = w_dst / h_dst; - - if (fabsf(asp_src - asp_dst) >= FLT_EPSILON) { - if ((asp_src > asp_dst) == ((node->custom2 & CMP_SCALE_RENDERSIZE_FRAME_CROP) != 0)) { - /* fit X */ - const float div = asp_src / asp_dst; - newx = w_dst * div; - newy = h_dst; - } - else { - /* fit Y */ - const float div = asp_dst / asp_src; - newx = w_dst; - newy = h_dst * div; - } - } - else { - /* same as below - no aspect correction needed */ - newx = w_dst; - newy = h_dst; - } - } - else { - /* stretch */ - newx = (rd->xsch * rd->size) / 100; - newy = (rd->ysch * rd->size) / 100; - } - } - else { /* CMP_SCALE_ABSOLUTE */ - newx = MAX2((int)in[1]->vec[0], 1); - newy = MAX2((int)in[2]->vec[0], 1); - } - newx = MIN2(newx, CMP_SCALE_MAX); - newy = MIN2(newy, CMP_SCALE_MAX); - - ibuf = IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0); - if (ibuf) { - ibuf->rect_float = cbuf->rect; - IMB_scaleImBuf(ibuf, newx, newy); - - if (ibuf->rect_float == cbuf->rect) { - /* no scaling happened. */ - stackbuf = pass_on_compbuf(in[0]->data); - } - else { - stackbuf = alloc_compbuf(newx, newy, CB_RGBA, 0); - stackbuf->rect = ibuf->rect_float; - stackbuf->malloc = 1; - } - - ibuf->rect_float = NULL; - ibuf->mall &= ~IB_rectfloat; - IMB_freeImBuf(ibuf); - - /* also do the translation vector */ - stackbuf->xof = (int)(ofsx + (((float)newx / (float)cbuf->x) * (float)cbuf->xof)); - stackbuf->yof = (int)(ofsy + (((float)newy / (float)cbuf->y) * (float)cbuf->yof)); - } - else { - stackbuf = dupalloc_compbuf(cbuf); - printf("Scaling to %dx%d failed\n", newx, newy); - } - - out[0]->data = stackbuf; - if (cbuf != in[0]->data) - free_compbuf(cbuf); - } - else if (node->custom1 == CMP_SCALE_ABSOLUTE) { - CompBuf *stackbuf; - int a, x, y; - float *fp; - - x = MAX2((int)in[1]->vec[0], 1); - y = MAX2((int)in[2]->vec[0], 1); - - stackbuf = alloc_compbuf(x, y, CB_RGBA, 1); - fp = stackbuf->rect; - - a = stackbuf->x * stackbuf->y; - while (a--) { - copy_v4_v4(fp, in[0]->vec); - fp += 4; - } - - out[0]->data = stackbuf; - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_scale(bNodeTreeType *ttype) { static bNodeType ntype; @@ -193,9 +52,6 @@ void register_node_type_cmp_scale(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_SCALE, "Scale", NODE_CLASS_DISTORT, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_scale_in, cmp_node_scale_out); node_type_size(&ntype, 140, 100, 320); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_scale); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c b/source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c index f1a75493718..83b9d5d3fcd 100644 --- a/source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c +++ b/source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c @@ -46,63 +46,6 @@ static bNodeSocketTemplate cmp_node_sephsva_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_sephsva(bNode *UNUSED(node), float *out, float *in) -{ - float h, s, v; - - rgb_to_hsv(in[0], in[1], in[2], &h, &s, &v); - - out[0] = h; - out[1] = s; - out[2] = v; - out[3] = in[3]; -} - -static void node_composit_exec_sephsva(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - /* stack order out: bw channels */ - /* stack order in: col */ - - /* input no image? then only color operation */ - if (in[0]->data==NULL) { - float h, s, v; - - rgb_to_hsv(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2], &h, &s, &v); - - out[0]->vec[0] = h; - out[1]->vec[0] = s; - out[2]->vec[0] = v; - out[3]->vec[0] = in[0]->vec[3]; - } - else if ((out[0]->hasoutput) || (out[1]->hasoutput) || (out[2]->hasoutput) || (out[3]->hasoutput)) { - /* create new buffer so input buffer doesn't get corrupted */ - CompBuf *cbuf= dupalloc_compbuf(in[0]->data); - CompBuf *cbuf2= typecheck_compbuf(cbuf, CB_RGBA); - - /* convert the RGB stackbuf to an HSV representation */ - composit1_pixel_processor(node, cbuf2, cbuf2, in[0]->vec, do_sephsva, CB_RGBA); - - /* separate each of those channels */ - if (out[0]->hasoutput) - out[0]->data= valbuf_from_rgbabuf(cbuf2, CHAN_R); - if (out[1]->hasoutput) - out[1]->data= valbuf_from_rgbabuf(cbuf2, CHAN_G); - if (out[2]->hasoutput) - out[2]->data= valbuf_from_rgbabuf(cbuf2, CHAN_B); - if (out[3]->hasoutput) - out[3]->data= valbuf_from_rgbabuf(cbuf2, CHAN_A); - - /*not used anymore */ - if (cbuf2!=cbuf) - free_compbuf(cbuf2); - free_compbuf(cbuf); - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_sephsva(bNodeTreeType *ttype) { static bNodeType ntype; @@ -110,9 +53,6 @@ void register_node_type_cmp_sephsva(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_SEPHSVA, "Separate HSVA", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, cmp_node_sephsva_in, cmp_node_sephsva_out); node_type_size(&ntype, 80, 40, 140); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_sephsva); -#endif nodeRegisterType(ttype, &ntype); } @@ -131,53 +71,6 @@ static bNodeSocketTemplate cmp_node_combhsva_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_comb_hsva(bNode *UNUSED(node), float *out, float *in1, float *in2, float *in3, float *in4) -{ - float r, g, b; - hsv_to_rgb(in1[0], in2[0], in3[0], &r, &g, &b); - - out[0] = r; - out[1] = g; - out[2] = b; - out[3] = in4[0]; -} - -static void node_composit_exec_combhsva(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - /* stack order out: 1 rgba channels */ - /* stack order in: 4 value channels */ - - /* input no image? then only color operation in HSV */ - if ((in[0]->data==NULL) && (in[1]->data==NULL) && (in[2]->data==NULL) && (in[3]->data==NULL)) { - hsv_to_rgb(in[0]->vec[0], in[1]->vec[0], in[2]->vec[0], - &out[0]->vec[0], &out[0]->vec[1], &out[0]->vec[2]); - out[0]->vec[3] = in[3]->vec[0]; - } - else { - /* make output size of first available input image */ - CompBuf *cbuf; - CompBuf *stackbuf; - - /* allocate a CompBuf the size of the first available input */ - if (in[0]->data) cbuf = in[0]->data; - else if (in[1]->data) cbuf = in[1]->data; - else if (in[2]->data) cbuf = in[2]->data; - else cbuf = in[3]->data; - - stackbuf = alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */ - - composit4_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, - in[2]->data, in[2]->vec, in[3]->data, in[3]->vec, - do_comb_hsva, CB_VAL, CB_VAL, CB_VAL, CB_VAL); - - out[0]->data= stackbuf; - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_combhsva(bNodeTreeType *ttype) { static bNodeType ntype; @@ -185,9 +78,6 @@ void register_node_type_cmp_combhsva(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_COMBHSVA, "Combine HSVA", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_combhsva_in, cmp_node_combhsva_out); node_type_size(&ntype, 80, 40, 140); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_combhsva); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c b/source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c index 83b2c731020..8508087da0f 100644 --- a/source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c +++ b/source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c @@ -45,42 +45,6 @@ static bNodeSocketTemplate cmp_node_seprgba_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void node_composit_exec_seprgba(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, bNodeStack **out) -{ - /* stack order out: bw channels */ - /* stack order in: col */ - - /* input no image? then only color operation */ - if (in[0]->data==NULL) { - out[0]->vec[0] = in[0]->vec[0]; - out[1]->vec[0] = in[0]->vec[1]; - out[2]->vec[0] = in[0]->vec[2]; - out[3]->vec[0] = in[0]->vec[3]; - } - else { - /* make sure we get right rgba buffer */ - CompBuf *cbuf= typecheck_compbuf(in[0]->data, CB_RGBA); - - /* don't do any pixel processing, just copy the stack directly (faster, I presume) */ - if (out[0]->hasoutput) - out[0]->data= valbuf_from_rgbabuf(cbuf, CHAN_R); - if (out[1]->hasoutput) - out[1]->data= valbuf_from_rgbabuf(cbuf, CHAN_G); - if (out[2]->hasoutput) - out[2]->data= valbuf_from_rgbabuf(cbuf, CHAN_B); - if (out[3]->hasoutput) - out[3]->data= valbuf_from_rgbabuf(cbuf, CHAN_A); - - if (cbuf!=in[0]->data) - free_compbuf(cbuf); - - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_seprgba(bNodeTreeType *ttype) { static bNodeType ntype; @@ -88,9 +52,6 @@ void register_node_type_cmp_seprgba(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_SEPRGBA, "Separate RGBA", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, cmp_node_seprgba_in, cmp_node_seprgba_out); node_type_size(&ntype, 80, 40, 140); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_seprgba); -#endif nodeRegisterType(ttype, &ntype); } @@ -110,51 +71,6 @@ static bNodeSocketTemplate cmp_node_combrgba_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_combrgba(bNode *UNUSED(node), float *out, float *in1, float *in2, float *in3, float *in4) -{ - out[0] = in1[0]; - out[1] = in2[0]; - out[2] = in3[0]; - out[3] = in4[0]; -} - -static void node_composit_exec_combrgba(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - /* stack order out: 1 rgba channels */ - /* stack order in: 4 value channels */ - - /* input no image? then only color operation */ - if ((in[0]->data==NULL) && (in[1]->data==NULL) && (in[2]->data==NULL) && (in[3]->data==NULL)) { - out[0]->vec[0] = in[0]->vec[0]; - out[0]->vec[1] = in[1]->vec[0]; - out[0]->vec[2] = in[2]->vec[0]; - out[0]->vec[3] = in[3]->vec[0]; - } - else { - /* make output size of first available input image */ - CompBuf *cbuf; - CompBuf *stackbuf; - - /* allocate a CompBuf the size of the first available input */ - if (in[0]->data) cbuf = in[0]->data; - else if (in[1]->data) cbuf = in[1]->data; - else if (in[2]->data) cbuf = in[2]->data; - else cbuf = in[3]->data; - - stackbuf = alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */ - - composit4_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, - in[2]->data, in[2]->vec, in[3]->data, in[3]->vec, - do_combrgba, CB_VAL, CB_VAL, CB_VAL, CB_VAL); - - out[0]->data= stackbuf; - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_combrgba(bNodeTreeType *ttype) { static bNodeType ntype; @@ -162,9 +78,6 @@ void register_node_type_cmp_combrgba(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_COMBRGBA, "Combine RGBA", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_combrgba_in, cmp_node_combrgba_out); node_type_size(&ntype, 80, 40, 140); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_combrgba); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c b/source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c index 982d674708c..a7cc7367c67 100644 --- a/source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c +++ b/source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c @@ -46,109 +46,6 @@ static bNodeSocketTemplate cmp_node_sepycca_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_sepycca_601(bNode *UNUSED(node), float *out, float *in) -{ - float y, cb, cr; - - rgb_to_ycc(in[0], in[1], in[2], &y, &cb, &cr, BLI_YCC_ITU_BT601); - - /*divided by 255 to normalize for viewing in */ - out[0] = y/255.0f; - out[1] = cb/255.0f; - out[2] = cr/255.0f; - out[3] = in[3]; -} - -static void do_sepycca_709(bNode *UNUSED(node), float *out, float *in) -{ - float y, cb, cr; - - rgb_to_ycc(in[0], in[1], in[2], &y, &cb, &cr, BLI_YCC_ITU_BT709); - - /*divided by 255 to normalize for viewing in */ - out[0] = y/255.0f; - out[1] = cb/255.0f; - out[2] = cr/255.0f; - out[3] = in[3]; -} - -static void do_sepycca_jfif(bNode *UNUSED(node), float *out, float *in) -{ - float y, cb, cr; - - rgb_to_ycc(in[0], in[1], in[2], &y, &cb, &cr, BLI_YCC_JFIF_0_255); - - /*divided by 255 to normalize for viewing in */ - out[0] = y/255.0f; - out[1] = cb/255.0f; - out[2] = cr/255.0f; - out[3] = in[3]; -} - -static void node_composit_exec_sepycca(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - /* input no image? then only color operation */ - if (in[0]->data==NULL) { - float y, cb, cr; - - switch (node->custom1) { - case 1: - rgb_to_ycc(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2], &y, &cb, &cr, BLI_YCC_ITU_BT709); - break; - case 2: - rgb_to_ycc(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2], &y, &cb, &cr, BLI_YCC_JFIF_0_255); - break; - case 0: - default: - rgb_to_ycc(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2], &y, &cb, &cr, BLI_YCC_ITU_BT601); - break; - } - - /*divided by 255 to normalize for viewing in */ - out[0]->vec[0] = y/255.0f; - out[1]->vec[0] = cb/255.0f; - out[2]->vec[0] = cr/255.0f; - out[3]->vec[0] = in[0]->vec[3]; - } - else if ((out[0]->hasoutput) || (out[1]->hasoutput) || (out[2]->hasoutput) || (out[3]->hasoutput)) { - /* make copy of buffer so input buffer doesn't get corrupted */ - CompBuf *cbuf= dupalloc_compbuf(in[0]->data); - CompBuf *cbuf2=typecheck_compbuf(cbuf, CB_RGBA); - - /* convert the RGB stackbuf to an HSV representation */ - switch (node->custom1) { - case 1: - composit1_pixel_processor(node, cbuf2, cbuf2, in[0]->vec, do_sepycca_709, CB_RGBA); - break; - case 2: - composit1_pixel_processor(node, cbuf2, cbuf2, in[0]->vec, do_sepycca_jfif, CB_RGBA); - break; - case 0: - default: - composit1_pixel_processor(node, cbuf2, cbuf2, in[0]->vec, do_sepycca_601, CB_RGBA); - break; - } - - /* separate each of those channels */ - if (out[0]->hasoutput) - out[0]->data= valbuf_from_rgbabuf(cbuf2, CHAN_R); - if (out[1]->hasoutput) - out[1]->data= valbuf_from_rgbabuf(cbuf2, CHAN_G); - if (out[2]->hasoutput) - out[2]->data= valbuf_from_rgbabuf(cbuf2, CHAN_B); - if (out[3]->hasoutput) - out[3]->data= valbuf_from_rgbabuf(cbuf2, CHAN_A); - - /*not used anymore */ - if (cbuf2!=cbuf) - free_compbuf(cbuf2); - free_compbuf(cbuf); - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ void register_node_type_cmp_sepycca(bNodeTreeType *ttype) { @@ -157,9 +54,6 @@ void register_node_type_cmp_sepycca(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_SEPYCCA, "Separate YCbCrA", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_sepycca_in, cmp_node_sepycca_out); node_type_size(&ntype, 80, 40, 140); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_sepycca); -#endif nodeRegisterType(ttype, &ntype); } @@ -179,128 +73,6 @@ static bNodeSocketTemplate cmp_node_combycca_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_comb_ycca_601(bNode *UNUSED(node), float *out, float *in1, float *in2, float *in3, float *in4) -{ - float r, g, b; - float y, cb, cr; - - /*need to un-normalize the data*/ - y=in1[0]*255; - cb=in2[0]*255; - cr=in3[0]*255; - - ycc_to_rgb(y, cb, cr, &r, &g, &b, BLI_YCC_ITU_BT601); - - out[0] = r; - out[1] = g; - out[2] = b; - out[3] = in4[0]; -} - -static void do_comb_ycca_709(bNode *UNUSED(node), float *out, float *in1, float *in2, float *in3, float *in4) -{ - float r, g, b; - float y, cb, cr; - - /*need to un-normalize the data*/ - y=in1[0]*255; - cb=in2[0]*255; - cr=in3[0]*255; - - ycc_to_rgb(y, cb, cr, &r, &g, &b, BLI_YCC_ITU_BT709); - - out[0] = r; - out[1] = g; - out[2] = b; - out[3] = in4[0]; -} - -static void do_comb_ycca_jfif(bNode *UNUSED(node), float *out, float *in1, float *in2, float *in3, float *in4) -{ - float r, g, b; - float y, cb, cr; - - /*need to un-normalize the data*/ - y=in1[0]*255; - cb=in2[0]*255; - cr=in3[0]*255; - - ycc_to_rgb(y, cb, cr, &r, &g, &b, BLI_YCC_JFIF_0_255); - - out[0] = r; - out[1] = g; - out[2] = b; - out[3] = in4[0]; -} - -static void node_composit_exec_combycca(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - /* stack order out: 1 ycca channels */ - /* stack order in: 4 value channels */ - - /* input no image? then only color operation */ - if ((in[0]->data==NULL) && (in[1]->data==NULL) && (in[2]->data==NULL) && (in[3]->data==NULL)) { - float y = in[0]->vec[0] * 255; - float cb = in[1]->vec[0] * 255; - float cr = in[2]->vec[0] * 255; - - switch (node->custom1) { - case 1: - ycc_to_rgb(y, cb, cr, &out[0]->vec[0], &out[0]->vec[1], &out[0]->vec[2], BLI_YCC_ITU_BT709); - break; - case 2: - ycc_to_rgb(y, cb, cr, &out[0]->vec[0], &out[0]->vec[1], &out[0]->vec[2], BLI_YCC_JFIF_0_255); - break; - case 0: - default: - ycc_to_rgb(y, cb, cr, &out[0]->vec[0], &out[0]->vec[1], &out[0]->vec[2], BLI_YCC_ITU_BT601); - break; - } - - out[0]->vec[3] = in[3]->vec[0]; - } - else { - /* make output size of first available input image */ - CompBuf *cbuf; - CompBuf *stackbuf; - - /* allocate a CompBuf the size of the first available input */ - if (in[0]->data) cbuf = in[0]->data; - else if (in[1]->data) cbuf = in[1]->data; - else if (in[2]->data) cbuf = in[2]->data; - else cbuf = in[3]->data; - - stackbuf = alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */ - - - switch (node->custom1) { - case 1: - composit4_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, - in[2]->data, in[2]->vec, in[3]->data, in[3]->vec, - do_comb_ycca_709, CB_VAL, CB_VAL, CB_VAL, CB_VAL); - break; - - case 2: - composit4_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, - in[2]->data, in[2]->vec, in[3]->data, in[3]->vec, - do_comb_ycca_jfif, CB_VAL, CB_VAL, CB_VAL, CB_VAL); - break; - case 0: - default: - composit4_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, - in[2]->data, in[2]->vec, in[3]->data, in[3]->vec, - do_comb_ycca_601, CB_VAL, CB_VAL, CB_VAL, CB_VAL); - break; - } - - out[0]->data= stackbuf; - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_combycca(bNodeTreeType *ttype) { static bNodeType ntype; @@ -308,9 +80,6 @@ void register_node_type_cmp_combycca(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_COMBYCCA, "Combine YCbCrA", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_combycca_in, cmp_node_combycca_out); node_type_size(&ntype, 80, 40, 140); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_combycca); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c b/source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c index 0a9575971b4..88edf7ec6b0 100644 --- a/source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c +++ b/source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c @@ -46,63 +46,6 @@ static bNodeSocketTemplate cmp_node_sepyuva_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_sepyuva(bNode *UNUSED(node), float *out, float *in) -{ - float y, u, v; - - rgb_to_yuv(in[0], in[1], in[2], &y, &u, &v); - - out[0] = y; - out[1] = u; - out[2] = v; - out[3] = in[3]; -} - -static void node_composit_exec_sepyuva(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - /* stack order out: bw channels */ - /* stack order in: col */ - - /* input no image? then only color operation */ - if (in[0]->data==NULL) { - float y, u, v; - - rgb_to_yuv(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2], &y, &u, &v); - - out[0]->vec[0] = y; - out[1]->vec[0] = u; - out[2]->vec[0] = v; - out[3]->vec[0] = in[0]->vec[3]; - } - else if ((out[0]->hasoutput) || (out[1]->hasoutput) || (out[2]->hasoutput) || (out[3]->hasoutput)) { - /* make copy of buffer so input image doesn't get corrupted */ - CompBuf *cbuf= dupalloc_compbuf(in[0]->data); - CompBuf *cbuf2=typecheck_compbuf(cbuf, CB_RGBA); - - /* convert the RGB stackbuf to an YUV representation */ - composit1_pixel_processor(node, cbuf2, cbuf2, in[0]->vec, do_sepyuva, CB_RGBA); - - /* separate each of those channels */ - if (out[0]->hasoutput) - out[0]->data= valbuf_from_rgbabuf(cbuf2, CHAN_R); - if (out[1]->hasoutput) - out[1]->data= valbuf_from_rgbabuf(cbuf2, CHAN_G); - if (out[2]->hasoutput) - out[2]->data= valbuf_from_rgbabuf(cbuf2, CHAN_B); - if (out[3]->hasoutput) - out[3]->data= valbuf_from_rgbabuf(cbuf2, CHAN_A); - - /*not used anymore */ - if (cbuf2!=cbuf) - free_compbuf(cbuf2); - free_compbuf(cbuf); - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_sepyuva(bNodeTreeType *ttype) { @@ -111,9 +54,6 @@ void register_node_type_cmp_sepyuva(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_SEPYUVA, "Separate YUVA", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, cmp_node_sepyuva_in, cmp_node_sepyuva_out); node_type_size(&ntype, 80, 40, 140); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_sepyuva); -#endif nodeRegisterType(ttype, &ntype); } @@ -133,54 +73,6 @@ static bNodeSocketTemplate cmp_node_combyuva_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_comb_yuva(bNode *UNUSED(node), float *out, float *in1, float *in2, float *in3, float *in4) -{ - float r, g, b; - yuv_to_rgb(in1[0], in2[0], in3[0], &r, &g, &b); - - out[0] = r; - out[1] = g; - out[2] = b; - out[3] = in4[0]; -} - -static void node_composit_exec_combyuva(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - /* stack order out: 1 rgba channels */ - /* stack order in: 4 value channels */ - - /* input no image? then only color operation */ - if ((in[0]->data==NULL) && (in[1]->data==NULL) && (in[2]->data==NULL) && (in[3]->data==NULL)) { - out[0]->vec[0] = in[0]->vec[0]; - out[0]->vec[1] = in[1]->vec[0]; - out[0]->vec[2] = in[2]->vec[0]; - out[0]->vec[3] = in[3]->vec[0]; - } - else { - /* make output size of first available input image */ - CompBuf *cbuf; - CompBuf *stackbuf; - - /* allocate a CompBuf the size of the first available input */ - if (in[0]->data) cbuf = in[0]->data; - else if (in[1]->data) cbuf = in[1]->data; - else if (in[2]->data) cbuf = in[2]->data; - else cbuf = in[3]->data; - - stackbuf = alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */ - - composit4_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, - in[2]->data, in[2]->vec, in[3]->data, in[3]->vec, - do_comb_yuva, CB_VAL, CB_VAL, CB_VAL, CB_VAL); - - out[0]->data= stackbuf; - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_combyuva(bNodeTreeType *ttype) { static bNodeType ntype; @@ -188,9 +80,6 @@ void register_node_type_cmp_combyuva(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_COMBYUVA, "Combine YUVA", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_combyuva_in, cmp_node_combyuva_out); node_type_size(&ntype, 80, 40, 140); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_combyuva); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_setalpha.c b/source/blender/nodes/composite/nodes/node_composite_setalpha.c index 59c104869fe..0cec19b15af 100644 --- a/source/blender/nodes/composite/nodes/node_composite_setalpha.c +++ b/source/blender/nodes/composite/nodes/node_composite_setalpha.c @@ -43,41 +43,6 @@ static bNodeSocketTemplate cmp_node_setalpha_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void node_composit_exec_setalpha(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - /* stack order out: RGBA image */ - /* stack order in: col, alpha */ - - /* input no image? then only color operation */ - if (in[0]->data==NULL && in[1]->data==NULL) { - out[0]->vec[0] = in[0]->vec[0]; - out[0]->vec[1] = in[0]->vec[1]; - out[0]->vec[2] = in[0]->vec[2]; - out[0]->vec[3] = in[1]->vec[0]; - } - else { - /* make output size of input image */ - CompBuf *cbuf= in[0]->data?in[0]->data:in[1]->data; - CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */ - - if (in[1]->data==NULL && in[1]->vec[0]==1.0f) { - /* pass on image */ - composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_copy_rgb, CB_RGBA); - } - else { - /* send an compbuf or a value to set as alpha - composit2_pixel_processor handles choosing the right one */ - composit2_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_copy_a_rgba, CB_RGBA, CB_VAL); - } - - out[0]->data= stackbuf; - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - - void register_node_type_cmp_setalpha(bNodeTreeType *ttype) { static bNodeType ntype; @@ -85,9 +50,6 @@ void register_node_type_cmp_setalpha(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_SETALPHA, "Set Alpha", NODE_CLASS_CONVERTOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_setalpha_in, cmp_node_setalpha_out); node_type_size(&ntype, 120, 40, 140); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_setalpha); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_splitViewer.c b/source/blender/nodes/composite/nodes/node_composite_splitViewer.c index 523f1dee406..3f4c3d67e2c 100644 --- a/source/blender/nodes/composite/nodes/node_composite_splitViewer.c +++ b/source/blender/nodes/composite/nodes/node_composite_splitViewer.c @@ -39,110 +39,6 @@ static bNodeSocketTemplate cmp_node_splitviewer_in[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_copy_split_rgba(bNode *UNUSED(node), float *out, float *in1, float *in2, float *fac) -{ - if (*fac==0.0f) { - copy_v4_v4(out, in1); - } - else { - copy_v4_v4(out, in2); - } -} - -static void node_composit_exec_splitviewer(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out)) -{ - /* image assigned to output */ - /* stack order input sockets: image image */ - - if (in[0]->data==NULL || in[1]->data==NULL) - return; - - if (node->id && (node->flag & NODE_DO_OUTPUT)) { /* only one works on out */ - Image *ima= (Image *)node->id; - RenderData *rd= data; - ImBuf *ibuf; - CompBuf *cbuf, *buf1, *buf2, *mask; - int x, y; - float offset; - void *lock; - - buf1= typecheck_compbuf(in[0]->data, CB_RGBA); - buf2= typecheck_compbuf(in[1]->data, CB_RGBA); - - BKE_image_user_frame_calc(node->storage, rd->cfra, 0); - - /* always returns for viewer image, but we check nevertheless */ - ibuf= BKE_image_acquire_ibuf(ima, node->storage, &lock); - if (ibuf==NULL) { - printf("node_composit_exec_viewer error\n"); - BKE_image_release_ibuf(ima, ibuf, lock); - return; - } - - /* free all in ibuf */ - imb_freerectImBuf(ibuf); - imb_freerectfloatImBuf(ibuf); - IMB_freezbuffloatImBuf(ibuf); - - /* make ibuf, and connect to ima */ - ibuf->x= buf1->x; - ibuf->y= buf1->y; - imb_addrectfloatImBuf(ibuf); - - ima->ok= IMA_OK_LOADED; - - /* output buf */ - cbuf= alloc_compbuf(buf1->x, buf1->y, CB_RGBA, 0); /* no alloc*/ - cbuf->rect= ibuf->rect_float; - - /* mask buf */ - mask= alloc_compbuf(buf1->x, buf1->y, CB_VAL, 1); - - - /* Check which offset mode is selected and limit offset if needed */ - if (node->custom2 == 0) { - offset = buf1->x / 100.0f * node->custom1; - CLAMP(offset, 0, buf1->x); - } - else { - offset = buf1->y / 100.0f * node->custom1; - CLAMP(offset, 0, buf1->y); - } - - if (node->custom2 == 0) { - for (y=0; y<buf1->y; y++) { - float *fac= mask->rect + y*buf1->x; - for (x=offset; x>0; x--, fac++) - *fac= 1.0f; - } - } - else { - for (y=0; y<offset; y++) { - float *fac= mask->rect + y*buf1->x; - for (x=buf1->x; x>0; x--, fac++) - *fac= 1.0f; - } - } - - composit3_pixel_processor(node, cbuf, buf1, in[0]->vec, buf2, in[1]->vec, mask, NULL, do_copy_split_rgba, CB_RGBA, CB_RGBA, CB_VAL); - - BKE_image_release_ibuf(ima, ibuf, lock); - - generate_preview(data, node, cbuf); - free_compbuf(cbuf); - free_compbuf(mask); - - if (in[0]->data != buf1) - free_compbuf(buf1); - if (in[1]->data != buf2) - free_compbuf(buf2); - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_splitviewer(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user"); @@ -162,9 +58,6 @@ void register_node_type_cmp_splitviewer(bNodeTreeType *ttype) node_type_size(&ntype, 140, 100, 320); node_type_init(&ntype, node_composit_init_splitviewer); node_type_storage(&ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_splitviewer); -#endif /* Do not allow muting for this node. */ node_type_internal_links(&ntype, NULL); diff --git a/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c b/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c index 1787e075a14..964e54eb862 100644 --- a/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c +++ b/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c @@ -45,32 +45,6 @@ static bNodeSocketTemplate cmp_node_stabilize2d_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void node_composit_exec_stabilize2d(void *data, bNode *node, bNodeStack **in, bNodeStack **out) -{ - if (in[0]->data && node->id) { - RenderData *rd = data; - MovieClip *clip = (MovieClip *)node->id; - CompBuf *cbuf = typecheck_compbuf(in[0]->data, CB_RGBA); - CompBuf *stackbuf; - float loc[2], scale, angle; - int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, rd->cfra); - - BKE_tracking_stabilization_data_get(&clip->tracking, clip_framenr, cbuf->x, cbuf->y, loc, &scale, &angle); - - stackbuf = node_composit_transform(cbuf, loc[0], loc[1], angle, scale, node->custom1); - - /* pass on output and free */ - out[0]->data = stackbuf; - - if (cbuf != in[0]->data) - free_compbuf(cbuf); - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_stabilize2d(bNodeTreeType *ttype) { static bNodeType ntype; @@ -78,9 +52,6 @@ void register_node_type_cmp_stabilize2d(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_STABILIZE2D, "Stabilize 2D", NODE_CLASS_DISTORT, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_stabilize2d_in, cmp_node_stabilize2d_out); node_type_size(&ntype, 140, 100, 320); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_stabilize2d); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_texture.c b/source/blender/nodes/composite/nodes/node_composite_texture.c index b6518c48638..17b5720c7ad 100644 --- a/source/blender/nodes/composite/nodes/node_composite_texture.c +++ b/source/blender/nodes/composite/nodes/node_composite_texture.c @@ -44,108 +44,6 @@ static bNodeSocketTemplate cmp_node_texture_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -/* called without rect allocated */ -static void texture_procedural(CompBuf *cbuf, float *out, float xco, float yco) -{ - bNode *node= cbuf->node; - TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL}; - float vec[3], *size, nor[3] = {0.0f, 0.0f, 0.0f}, col[4]; - int retval, type= cbuf->procedural_type; - - size= cbuf->procedural_size; - - vec[0] = size[0]*(xco + cbuf->procedural_offset[0]); - vec[1] = size[1]*(yco + cbuf->procedural_offset[1]); - vec[2] = size[2]*cbuf->procedural_offset[2]; - - retval= multitex_ext((Tex *)node->id, vec, NULL, NULL, 0, &texres); - - if (type==CB_VAL) { - if (texres.talpha) - col[0] = texres.ta; - else - col[0] = texres.tin; - } - else if (type==CB_RGBA) { - if (texres.talpha) - col[3] = texres.ta; - else - col[3] = texres.tin; - - if ((retval & TEX_RGB)) { - copy_v3_v3(col, &texres.tr); - } - else { - copy_v3_fl(col, col[3]); - } - } - else { - copy_v3_v3(col, nor); - } - - typecheck_compbuf_color(out, col, cbuf->type, cbuf->procedural_type); -} - -/* texture node outputs get a small rect, to make sure all other nodes accept it */ -/* only the pixel-processor nodes do something with it though */ -static void node_composit_exec_texture(void *data, bNode *node, bNodeStack **in, bNodeStack **out) -{ - /* outputs: value, color, normal */ - - if (node->id) { - RenderData *rd= data; - short sizex, sizey; - - /* first make the preview image */ - CompBuf *prevbuf= alloc_compbuf(140, 140, CB_RGBA, 1); /* alloc */ - - prevbuf->rect_procedural= texture_procedural; - prevbuf->node= node; - copy_v3_v3(prevbuf->procedural_offset, in[0]->vec); - copy_v3_v3(prevbuf->procedural_size, in[1]->vec); - prevbuf->procedural_type= CB_RGBA; - composit1_pixel_processor(node, prevbuf, prevbuf, out[0]->vec, do_copy_rgba, CB_RGBA); - - generate_preview(data, node, prevbuf); - free_compbuf(prevbuf); - - /* texture procedural buffer type doesnt work well, we now render a buffer in scene size */ - sizex = (rd->size*rd->xsch)/100; - sizey = (rd->size*rd->ysch)/100; - - if (out[0]->hasoutput) { - CompBuf *stackbuf= alloc_compbuf(sizex, sizey, CB_VAL, 1); /* alloc */ - - stackbuf->rect_procedural= texture_procedural; - stackbuf->node= node; - copy_v3_v3(stackbuf->procedural_offset, in[0]->vec); - copy_v3_v3(stackbuf->procedural_size, in[1]->vec); - stackbuf->procedural_type= CB_VAL; - composit1_pixel_processor(node, stackbuf, stackbuf, out[0]->vec, do_copy_value, CB_VAL); - stackbuf->rect_procedural= NULL; - - out[0]->data= stackbuf; - } - if (out[1]->hasoutput) { - CompBuf *stackbuf= alloc_compbuf(sizex, sizey, CB_RGBA, 1); /* alloc */ - - stackbuf->rect_procedural= texture_procedural; - stackbuf->node= node; - copy_v3_v3(stackbuf->procedural_offset, in[0]->vec); - copy_v3_v3(stackbuf->procedural_size, in[1]->vec); - stackbuf->procedural_type= CB_RGBA; - composit1_pixel_processor(node, stackbuf, stackbuf, out[0]->vec, do_copy_rgba, CB_RGBA); - stackbuf->rect_procedural= NULL; - - out[1]->data= stackbuf; - } - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_texture(bNodeTreeType *ttype) { static bNodeType ntype; @@ -153,9 +51,6 @@ void register_node_type_cmp_texture(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_TEXTURE, "Texture", NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW); node_type_socket_templates(&ntype, cmp_node_texture_in, cmp_node_texture_out); node_type_size(&ntype, 120, 80, 240); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_texture); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_tonemap.c b/source/blender/nodes/composite/nodes/node_composite_tonemap.c index 00b1a5514dc..94492431c9f 100644 --- a/source/blender/nodes/composite/nodes/node_composite_tonemap.c +++ b/source/blender/nodes/composite/nodes/node_composite_tonemap.c @@ -41,114 +41,6 @@ static bNodeSocketTemplate cmp_node_tonemap_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static float avgLogLum(CompBuf *src, float* auto_key, float* Lav, float* Cav) -{ - float lsum = 0; - int p = src->x*src->y; - fRGB* bc = (fRGB*)src->rect; - float avl, maxl = -1e10f, minl = 1e10f; - const float sc = 1.f/(src->x*src->y); - *Lav = 0.f; - while (p--) { - float L = rgb_to_luma_y(bc[0]); - *Lav += L; - add_v3_v3(Cav, bc[0]); - lsum += (float)log((double)MAX2(L, 0.0) + 1e-5); - maxl = (L > maxl) ? L : maxl; - minl = (L < minl) ? L : minl; - bc++; - } - *Lav *= sc; - mul_v3_fl(Cav, sc); - maxl = log((double)maxl + 1e-5); minl = log((double)minl + 1e-5f); avl = lsum*sc; - *auto_key = (maxl > minl) ? ((maxl - avl) / (maxl - minl)) : 1.f; - return exp((double)avl); -} - - -static void tonemap(NodeTonemap* ntm, CompBuf* dst, CompBuf* src) -{ - int x, y; - float dr, dg, db, al, igm = (ntm->gamma==0.f) ? 1 : (1.f / ntm->gamma); - float auto_key, Lav, Cav[3] = {0, 0, 0}; - - al = avgLogLum(src, &auto_key, &Lav, Cav); - al = (al == 0.f) ? 0.f : (ntm->key / al); - - if (ntm->type == 1) { - // Reinhard/Devlin photoreceptor - const float f = exp((double)-ntm->f); - const float m = (ntm->m > 0.f) ? ntm->m : (0.3f + 0.7f*pow((double)auto_key, 1.4)); - const float ic = 1.f - ntm->c, ia = 1.f - ntm->a; - if (ntm->m == 0.f) printf("tonemap node, M: %g\n", m); - for (y=0; y<src->y; ++y) { - fRGB* sp = (fRGB*)&src->rect[y*src->x*src->type]; - fRGB* dp = (fRGB*)&dst->rect[y*src->x*src->type]; - for (x=0; x<src->x; ++x) { - const float L = rgb_to_luma_y(sp[x]); - float I_l = sp[x][0] + ic*(L - sp[x][0]); - float I_g = Cav[0] + ic*(Lav - Cav[0]); - float I_a = I_l + ia*(I_g - I_l); - dp[x][0] /= (dp[x][0] + pow((double)f*I_a, (double)m)); - I_l = sp[x][1] + ic*(L - sp[x][1]); - I_g = Cav[1] + ic*(Lav - Cav[1]); - I_a = I_l + ia*(I_g - I_l); - dp[x][1] /= (dp[x][1] + pow((double)f*I_a, (double)m)); - I_l = sp[x][2] + ic*(L - sp[x][2]); - I_g = Cav[2] + ic*(Lav - Cav[2]); - I_a = I_l + ia*(I_g - I_l); - dp[x][2] /= (dp[x][2] + pow((double)f*I_a, (double)m)); - } - } - return; - } - - // Reinhard simple photographic tm (simplest, not using whitepoint var) - for (y=0; y<src->y; y++) { - fRGB* sp = (fRGB*)&src->rect[y*src->x*src->type]; - fRGB* dp = (fRGB*)&dst->rect[y*src->x*src->type]; - for (x=0; x<src->x; x++) { - copy_v4_v4(dp[x], sp[x]); - mul_v3_fl(dp[x], al); - dr = dp[x][0] + ntm->offset; - dg = dp[x][1] + ntm->offset; - db = dp[x][2] + ntm->offset; - dp[x][0] /= ((dr == 0.f) ? 1.f : dr); - dp[x][1] /= ((dg == 0.f) ? 1.f : dg); - dp[x][2] /= ((db == 0.f) ? 1.f : db); - if (igm != 0.f) { - dp[x][0] = pow((double)MAX2(dp[x][0], 0.0), igm); - dp[x][1] = pow((double)MAX2(dp[x][1], 0.0), igm); - dp[x][2] = pow((double)MAX2(dp[x][2], 0.0), igm); - } - } - } -} - - -static void node_composit_exec_tonemap(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - CompBuf *new, *img = in[0]->data; - - if ((img==NULL) || (out[0]->hasoutput==0)) return; - - if (img->type != CB_RGBA) - img = typecheck_compbuf(img, CB_RGBA); - - new = dupalloc_compbuf(img); - - tonemap(node->storage, new, img); - - out[0]->data = new; - - if (img!=in[0]->data) - free_compbuf(img); -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_tonemap(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { NodeTonemap *ntm = MEM_callocN(sizeof(NodeTonemap), "node tonemap data"); @@ -174,9 +66,6 @@ void register_node_type_cmp_tonemap(bNodeTreeType *ttype) node_type_size(&ntype, 150, 120, 200); node_type_init(&ntype, node_composit_init_tonemap); node_type_storage(&ntype, "NodeTonemap", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_tonemap); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_trackpos.c b/source/blender/nodes/composite/nodes/node_composite_trackpos.c index 4364ca61ba1..41dc5633ee5 100644 --- a/source/blender/nodes/composite/nodes/node_composite_trackpos.c +++ b/source/blender/nodes/composite/nodes/node_composite_trackpos.c @@ -39,15 +39,6 @@ static bNodeSocketTemplate cmp_node_trackpos_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void node_composit_exec_trackpos(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **UNUSED(in), bNodeStack **UNUSED(out)) -{ - /* pass */ -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void init(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { NodeTrackPosData *data = MEM_callocN(sizeof(NodeTrackPosData), "node track position data"); @@ -64,9 +55,6 @@ void register_node_type_cmp_trackpos(bNodeTreeType *ttype) node_type_size(&ntype, 120, 80, 300); node_type_init(&ntype, init); node_type_storage(&ntype, "NodeTrackPosData", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_trackpos); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_transform.c b/source/blender/nodes/composite/nodes/node_composite_transform.c index d6bb545cd5c..f51e49328ab 100644 --- a/source/blender/nodes/composite/nodes/node_composite_transform.c +++ b/source/blender/nodes/composite/nodes/node_composite_transform.c @@ -48,89 +48,6 @@ static bNodeSocketTemplate cmp_node_transform_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -CompBuf* node_composit_transform(CompBuf *cbuf, float x, float y, float angle, float scale, int filter_type) -{ - CompBuf *stackbuf = alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, TRUE); - ImBuf *ibuf, *obuf; - float mat[4][4], lmat[4][4], rmat[4][4], smat[4][4], cmat[4][4], icmat[4][4]; - float svec[3] = {scale, scale, scale}, loc[2] = {x, y}; - - unit_m4(rmat); - unit_m4(lmat); - unit_m4(smat); - unit_m4(cmat); - - /* image center as rotation center */ - cmat[3][0] = (float)cbuf->x/2.0f; - cmat[3][1] = (float)cbuf->y/2.0f; - invert_m4_m4(icmat, cmat); - - size_to_mat4(smat, svec); /* scale matrix */ - add_v2_v2(lmat[3], loc); /* tranlation matrix */ - rotate_m4(rmat, 'Z', angle); /* rotation matrix */ - - /* compose transformation matrix */ - mul_serie_m4(mat, lmat, cmat, rmat, smat, icmat, NULL, NULL, NULL); - - invert_m4(mat); - - ibuf = IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0); - obuf = IMB_allocImBuf(stackbuf->x, stackbuf->y, 32, 0); - - if (ibuf && obuf) { - int i, j; - - ibuf->rect_float = cbuf->rect; - obuf->rect_float = stackbuf->rect; - - for (j = 0; j < cbuf->y; j++) { - for (i = 0; i < cbuf->x; i++) { - float vec[3] = {i, j, 0}; - - mul_v3_m4v3(vec, mat, vec); - - switch (filter_type) { - case 0: - nearest_interpolation(ibuf, obuf, vec[0], vec[1], i, j); - break; - case 1: - bilinear_interpolation(ibuf, obuf, vec[0], vec[1], i, j); - break; - case 2: - bicubic_interpolation(ibuf, obuf, vec[0], vec[1], i, j); - break; - } - } - } - - IMB_freeImBuf(ibuf); - IMB_freeImBuf(obuf); - } - - /* pass on output and free */ - return stackbuf; -} - -static void node_composit_exec_transform(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - if (in[0]->data) { - CompBuf *cbuf = typecheck_compbuf(in[0]->data, CB_RGBA); - CompBuf *stackbuf; - - stackbuf = node_composit_transform(cbuf, in[1]->vec[0], in[2]->vec[0], in[3]->vec[0], in[4]->vec[0], node->custom1); - - /* pass on output and free */ - out[0]->data = stackbuf; - - if (cbuf != in[0]->data) - free_compbuf(cbuf); - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_transform(bNodeTreeType *ttype) { static bNodeType ntype; @@ -138,9 +55,6 @@ void register_node_type_cmp_transform(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_TRANSFORM, "Transform", NODE_CLASS_DISTORT, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_transform_in, cmp_node_transform_out); node_type_size(&ntype, 140, 100, 320); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_transform); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_translate.c b/source/blender/nodes/composite/nodes/node_composite_translate.c index 1c2963a2f08..7c7c6304d27 100644 --- a/source/blender/nodes/composite/nodes/node_composite_translate.c +++ b/source/blender/nodes/composite/nodes/node_composite_translate.c @@ -46,23 +46,6 @@ static bNodeSocketTemplate cmp_node_translate_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void node_composit_exec_translate(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, bNodeStack **out) -{ - if (in[0]->data) { - CompBuf *cbuf= in[0]->data; - CompBuf *stackbuf= pass_on_compbuf(cbuf); - - stackbuf->xof+= (int)floor(in[1]->vec[0]); - stackbuf->yof+= (int)floor(in[2]->vec[0]); - - out[0]->data= stackbuf; - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_translate(bNodeTreeType *ttype) { static bNodeType ntype; @@ -70,9 +53,6 @@ void register_node_type_cmp_translate(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_TRANSLATE, "Translate", NODE_CLASS_DISTORT, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_translate_in, cmp_node_translate_out); node_type_size(&ntype, 140, 100, 320); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_translate); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_valToRgb.c b/source/blender/nodes/composite/nodes/node_composite_valToRgb.c index 5c111998b18..c40880cc421 100644 --- a/source/blender/nodes/composite/nodes/node_composite_valToRgb.c +++ b/source/blender/nodes/composite/nodes/node_composite_valToRgb.c @@ -44,44 +44,6 @@ static bNodeSocketTemplate cmp_node_valtorgb_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_colorband_composit(bNode *node, float *out, float *in) -{ - do_colorband(node->storage, in[0], out); -} - -static void node_composit_exec_valtorgb(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - /* stack order in: fac */ - /* stack order out: col, alpha */ - - if (out[0]->hasoutput==0 && out[1]->hasoutput==0) - return; - - if (node->storage) { - /* input no image? then only color operation */ - if (in[0]->data==NULL) { - do_colorband(node->storage, in[0]->vec[0], out[0]->vec); - } - else { - /* make output size of input image */ - CompBuf *cbuf= in[0]->data; - CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */ - - composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_colorband_composit, CB_VAL); - - out[0]->data= stackbuf; - - if (out[1]->hasoutput) - out[1]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A); - - } - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_valtorgb(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { node->storage= add_colorband(1); @@ -96,9 +58,6 @@ void register_node_type_cmp_valtorgb(bNodeTreeType *ttype) node_type_size(&ntype, 240, 200, 300); node_type_init(&ntype, node_composit_init_valtorgb); node_type_storage(&ntype, "ColorBand", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_valtorgb); -#endif nodeRegisterType(ttype, &ntype); } @@ -115,38 +74,6 @@ static bNodeSocketTemplate cmp_node_rgbtobw_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_rgbtobw(bNode *UNUSED(node), float *out, float *in) -{ - out[0] = rgb_to_bw(in); -} - -static void node_composit_exec_rgbtobw(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - /* stack order out: bw */ - /* stack order in: col */ - - if (out[0]->hasoutput==0) - return; - - /* input no image? then only color operation */ - if (in[0]->data==NULL) { - do_rgbtobw(node, out[0]->vec, in[0]->vec); - } - else { - /* make output size of input image */ - CompBuf *cbuf= in[0]->data; - CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); /* allocs */ - - composit1_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, do_rgbtobw, CB_RGBA); - - out[0]->data= stackbuf; - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_rgbtobw(bNodeTreeType *ttype) { static bNodeType ntype; @@ -154,9 +81,6 @@ void register_node_type_cmp_rgbtobw(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_RGBTOBW, "RGB to BW", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, cmp_node_rgbtobw_in, cmp_node_rgbtobw_out); node_type_size(&ntype, 80, 40, 120); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_rgbtobw); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_value.c b/source/blender/nodes/composite/nodes/node_composite_value.c index 2c65fe6be19..05e79efa196 100644 --- a/source/blender/nodes/composite/nodes/node_composite_value.c +++ b/source/blender/nodes/composite/nodes/node_composite_value.c @@ -49,18 +49,6 @@ static void node_composit_init_value(bNodeTree *UNUSED(ntree), bNode *node, bNod dval->max = FLT_MAX; } -#ifdef WITH_COMPOSITOR_LEGACY - -static void node_composit_exec_value(void *UNUSED(data), bNode *node, bNodeStack **UNUSED(in), bNodeStack **out) -{ - bNodeSocket *sock= node->outputs.first; - float val= ((bNodeSocketValueFloat*)sock->default_value)->value; - - out[0]->vec[0] = val; -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_value(bNodeTreeType *ttype) { static bNodeType ntype; @@ -69,9 +57,6 @@ void register_node_type_cmp_value(bNodeTreeType *ttype) node_type_socket_templates(&ntype, NULL, cmp_node_value_out); node_type_init(&ntype, node_composit_init_value); node_type_size(&ntype, 80, 40, 120); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_value); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_vecBlur.c b/source/blender/nodes/composite/nodes/node_composite_vecBlur.c index 62c2c02836a..ff4fe8d8da5 100644 --- a/source/blender/nodes/composite/nodes/node_composite_vecBlur.c +++ b/source/blender/nodes/composite/nodes/node_composite_vecBlur.c @@ -45,48 +45,6 @@ static bNodeSocketTemplate cmp_node_vecblur_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void node_composit_exec_vecblur(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) -{ - NodeBlurData *nbd = node->storage; - CompBuf *new, *img = in[0]->data, *vecbuf = in[2]->data, *zbuf = in[1]->data; - - if (img == NULL || vecbuf == NULL || zbuf == NULL || out[0]->hasoutput == 0) - return; - if (vecbuf->x != img->x || vecbuf->y != img->y) { - printf("ERROR: cannot do different sized vecbuf yet\n"); - return; - } - if (vecbuf->type != CB_VEC4) { - printf("ERROR: input should be vecbuf\n"); - return; - } - if (zbuf->type != CB_VAL) { - printf("ERROR: input should be zbuf\n"); - return; - } - if (zbuf->x != img->x || zbuf->y != img->y) { - printf("ERROR: cannot do different sized zbuf yet\n"); - return; - } - - /* allow the input image to be of another type */ - img = typecheck_compbuf(in[0]->data, CB_RGBA); - - new = dupalloc_compbuf(img); - - /* call special zbuffer version */ - RE_zbuf_accumulate_vecblur(nbd, img->x, img->y, new->rect, img->rect, vecbuf->rect, zbuf->rect); - - out[0]->data = new; - - if (img != in[0]->data) - free_compbuf(img); -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_vecblur(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { NodeBlurData *nbd = MEM_callocN(sizeof(NodeBlurData), "node blur data"); @@ -105,9 +63,6 @@ void register_node_type_cmp_vecblur(bNodeTreeType *ttype) node_type_size(&ntype, 120, 80, 200); node_type_init(&ntype, node_composit_init_vecblur); node_type_storage(&ntype, "NodeBlurData", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_vecblur); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/composite/nodes/node_composite_viewer.c b/source/blender/nodes/composite/nodes/node_composite_viewer.c index 1c27cc21b06..24affc8f374 100644 --- a/source/blender/nodes/composite/nodes/node_composite_viewer.c +++ b/source/blender/nodes/composite/nodes/node_composite_viewer.c @@ -41,90 +41,6 @@ static bNodeSocketTemplate cmp_node_viewer_in[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void node_composit_exec_viewer(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out)) -{ - /* image assigned to output */ - /* stack order input sockets: col, alpha, z */ - - if (node->id && (node->flag & NODE_DO_OUTPUT)) { /* only one works on out */ - RenderData *rd = data; - Image *ima = (Image *)node->id; - ImBuf *ibuf; - CompBuf *cbuf, *tbuf; - int rectx, recty; - void *lock; - - BKE_image_user_frame_calc(node->storage, rd->cfra, 0); - - /* always returns for viewer image, but we check nevertheless */ - ibuf = BKE_image_acquire_ibuf(ima, node->storage, &lock); - if (ibuf == NULL) { - printf("node_composit_exec_viewer error\n"); - BKE_image_release_ibuf(ima, ibuf, lock); - return; - } - - /* free all in ibuf */ - imb_freerectImBuf(ibuf); - imb_freerectfloatImBuf(ibuf); - IMB_freezbuffloatImBuf(ibuf); - - /* get size */ - tbuf = in[0]->data ? in[0]->data : (in[1]->data ? in[1]->data : in[2]->data); - if (tbuf == NULL) { - rectx = 320; recty = 256; - } - else { - rectx = tbuf->x; - recty = tbuf->y; - } - - /* make ibuf, and connect to ima */ - ibuf->x = rectx; - ibuf->y = recty; - imb_addrectfloatImBuf(ibuf); - - ima->ok = IMA_OK_LOADED; - - /* now we combine the input with ibuf */ - cbuf = alloc_compbuf(rectx, recty, CB_RGBA, 0); /* no alloc*/ - cbuf->rect = ibuf->rect_float; - - /* when no alpha, we can simply copy */ - if (in[1]->data == NULL) { - composit1_pixel_processor(node, cbuf, in[0]->data, in[0]->vec, do_copy_rgba, CB_RGBA); - } - else - composit2_pixel_processor(node, cbuf, in[0]->data, in[0]->vec, in[1]->data, in[1]->vec, do_copy_a_rgba, CB_RGBA, CB_VAL); - - /* zbuf option */ - if (in[2]->data) { - CompBuf *zbuf = alloc_compbuf(rectx, recty, CB_VAL, 1); - ibuf->zbuf_float = zbuf->rect; - ibuf->mall |= IB_zbuffloat; - - composit1_pixel_processor(node, zbuf, in[2]->data, in[2]->vec, do_copy_value, CB_VAL); - - /* free compbuf, but not the rect */ - zbuf->malloc = 0; - free_compbuf(zbuf); - } - - BKE_image_release_ibuf(ima, ibuf, lock); - - generate_preview(data, node, cbuf); - free_compbuf(cbuf); - - } - else if (in[0]->data) { - generate_preview(data, node, in[0]->data); - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - static void node_composit_init_viewer(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp)) { ImageUser *iuser = MEM_callocN(sizeof(ImageUser), "node image user"); @@ -145,9 +61,6 @@ void register_node_type_cmp_viewer(bNodeTreeType *ttype) node_type_size(&ntype, 80, 60, 200); node_type_init(&ntype, node_composit_init_viewer); node_type_storage(&ntype, "ImageUser", node_free_standard_storage, node_copy_standard_storage); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_viewer); -#endif node_type_internal_links(&ntype, NULL); diff --git a/source/blender/nodes/composite/nodes/node_composite_zcombine.c b/source/blender/nodes/composite/nodes/node_composite_zcombine.c index 8e639aaa357..89d0cccd183 100644 --- a/source/blender/nodes/composite/nodes/node_composite_zcombine.c +++ b/source/blender/nodes/composite/nodes/node_composite_zcombine.c @@ -48,183 +48,6 @@ static bNodeSocketTemplate cmp_node_zcombine_out[] = { { -1, 0, "" } }; -#ifdef WITH_COMPOSITOR_LEGACY - -static void do_zcombine(bNode *node, float *out, float *src1, float *z1, float *src2, float *z2) -{ - float alpha; - float malpha; - - if (*z1 <= *z2) { - if (node->custom1) { - // use alpha in combine operation - alpha= src1[3]; - malpha= 1.0f - alpha; - out[0] = malpha*src2[0] + alpha*src1[0]; - out[1] = malpha*src2[1] + alpha*src1[1]; - out[2] = malpha*src2[2] + alpha*src1[2]; - out[3] = malpha*src2[3] + alpha*src1[3]; - } - else { - // do combination based solely on z value - copy_v4_v4(out, src1); - } - } - else { - if (node->custom1) { - // use alpha in combine operation - alpha= src2[3]; - malpha= 1.0f - alpha; - out[0] = malpha*src1[0] + alpha*src2[0]; - out[1] = malpha*src1[1] + alpha*src2[1]; - out[2] = malpha*src1[2] + alpha*src2[2]; - out[3] = malpha*src1[3] + alpha*src2[3]; - } - else { - // do combination based solely on z value - copy_v4_v4(out, src1); - } - - if (node->custom2) - *z1= *z2; - } -} - -static void do_zcombine_mask(bNode *node, float *out, float *z1, float *z2) -{ - if (*z1 > *z2) { - *out= 1.0f; - if (node->custom2) - *z1= *z2; - } -} - -static void do_zcombine_add(bNode *node, float *out, float *col1, float *col2, float *acol) -{ - float alpha; - float malpha; - - if (node->custom1) { - // use alpha in combine operation, antialiased mask in used here just as hint for the z value - if (*acol>0.0f) { - alpha= col2[3]; - malpha= 1.0f - alpha; - - - out[0] = malpha*col1[0] + alpha*col2[0]; - out[1] = malpha*col1[1] + alpha*col2[1]; - out[2] = malpha*col1[2] + alpha*col2[2]; - out[3] = malpha*col1[3] + alpha*col2[3]; - } - else { - alpha= col1[3]; - malpha= 1.0f - alpha; - - - out[0] = malpha*col2[0] + alpha*col1[0]; - out[1] = malpha*col2[1] + alpha*col1[1]; - out[2] = malpha*col2[2] + alpha*col1[2]; - out[3] = malpha*col2[3] + alpha*col1[3]; - } - } - else { - // do combination based solely on z value but with antialiased mask - alpha = *acol; - malpha= 1.0f - alpha; - - out[0] = malpha*col1[0] + alpha*col2[0]; - out[1] = malpha*col1[1] + alpha*col2[1]; - out[2] = malpha*col1[2] + alpha*col2[2]; - out[3] = malpha*col1[3] + alpha*col2[3]; - } -} - -static void node_composit_exec_zcombine(void *data, bNode *node, bNodeStack **in, bNodeStack **out) -{ - RenderData *rd= data; - CompBuf *cbuf= in[0]->data; - CompBuf *zbuf; - - /* stack order in: col z col z */ - /* stack order out: col z */ - if (out[0]->hasoutput==0 && out[1]->hasoutput==0) - return; - - /* no input image; do nothing now */ - if (in[0]->data==NULL) { - return; - } - - if (out[1]->hasoutput) { - /* copy or make a buffer for for the first z value, here we write result in */ - if (in[1]->data) - zbuf= dupalloc_compbuf(in[1]->data); - else { - float *zval; - int tot= cbuf->x*cbuf->y; - - zbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); - for (zval= zbuf->rect; tot; tot--, zval++) - *zval= in[1]->vec[0]; - } - /* lazy coder hack */ - node->custom2= 1; - out[1]->data= zbuf; - } - else { - node->custom2= 0; - zbuf= in[1]->data; - } - - if (rd->scemode & R_FULL_SAMPLE) { - /* make output size of first input image */ - CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); // allocs - - composit4_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, zbuf, in[1]->vec, in[2]->data, in[2]->vec, - in[3]->data, in[3]->vec, do_zcombine, CB_RGBA, CB_VAL, CB_RGBA, CB_VAL); - - out[0]->data= stackbuf; - } - else { - /* make output size of first input image */ - CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */ - CompBuf *mbuf; - float *fp; - int x; - char *aabuf; - - - /* make a mask based on comparison, optionally write zvalue */ - mbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1); - composit2_pixel_processor(node, mbuf, zbuf, in[1]->vec, in[3]->data, in[3]->vec, do_zcombine_mask, CB_VAL, CB_VAL); - - /* convert to char */ - aabuf= MEM_mallocN(cbuf->x*cbuf->y, "aa buf"); - fp= mbuf->rect; - for (x= cbuf->x*cbuf->y-1; x>=0; x--) - if (fp[x]==0.0f) aabuf[x] = 0; - else aabuf[x] = 255; - - antialias_tagbuf(cbuf->x, cbuf->y, aabuf); - - /* convert to float */ - fp= mbuf->rect; - for (x= cbuf->x*cbuf->y-1; x>=0; x--) - if (aabuf[x]>1) - fp[x] = (1.0f/255.0f)*(float)aabuf[x]; - - composit3_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, in[2]->data, in[2]->vec, mbuf, NULL, - do_zcombine_add, CB_RGBA, CB_RGBA, CB_VAL); - /* free */ - free_compbuf(mbuf); - MEM_freeN(aabuf); - - out[0]->data= stackbuf; - } -} - -#endif /* WITH_COMPOSITOR_LEGACY */ - void register_node_type_cmp_zcombine(bNodeTreeType *ttype) { static bNodeType ntype; @@ -232,9 +55,6 @@ void register_node_type_cmp_zcombine(bNodeTreeType *ttype) node_type_base(ttype, &ntype, CMP_NODE_ZCOMBINE, "Z Combine", NODE_CLASS_OP_COLOR, NODE_OPTIONS); node_type_socket_templates(&ntype, cmp_node_zcombine_in, cmp_node_zcombine_out); node_type_size(&ntype, 80, 40, 120); -#ifdef WITH_COMPOSITOR_LEGACY - node_type_exec(&ntype, node_composit_exec_zcombine); -#endif nodeRegisterType(ttype, &ntype); } diff --git a/source/blender/nodes/intern/node_exec.c b/source/blender/nodes/intern/node_exec.c index 86f8f4dfbbf..7a8b8c940c9 100644 --- a/source/blender/nodes/intern/node_exec.c +++ b/source/blender/nodes/intern/node_exec.c @@ -258,7 +258,7 @@ void ntree_exec_end(bNodeTreeExec *exec) MEM_freeN(exec); } -/**** Compositor/Material/Texture trees ****/ +/**** Material/Texture trees ****/ bNodeThreadStack *ntreeGetThreadStack(bNodeTreeExec *exec, int thread) { @@ -287,33 +287,7 @@ void ntreeReleaseThreadStack(bNodeThreadStack *nts) nts->used = 0; } -void ntreeExecNodes(bNodeTreeExec *exec, void *callerdata, int thread) -{ - bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */ - bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */ - bNodeExec *nodeexec; - bNode *node; - int n; - - /* nodes are presorted, so exec is in order of list */ - - for (n=0, nodeexec= exec->nodeexec; n < exec->totnodes; ++n, ++nodeexec) { - node = nodeexec->node; - if (node->need_exec) { - node_get_stack(node, exec->stack, nsin, nsout); - /* Handle muted nodes... - * If the mute func is not set, assume the node should never be muted, - * and hence execute it! - */ - if (node->typeinfo->execfunc) - node->typeinfo->execfunc(callerdata, node, nsin, nsout); - else if (node->typeinfo->newexecfunc) - node->typeinfo->newexecfunc(callerdata, thread, node, nodeexec->data, nsin, nsout); - } - } -} - -void ntreeExecThreadNodes(bNodeTreeExec *exec, bNodeThreadStack *nts, void *callerdata, int thread) +bool ntreeExecThreadNodes(bNodeTreeExec *exec, bNodeThreadStack *nts, void *callerdata, int thread) { bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */ bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */ @@ -331,10 +305,15 @@ void ntreeExecThreadNodes(bNodeTreeExec *exec, bNodeThreadStack *nts, void *call * If the mute func is not set, assume the node should never be muted, * and hence execute it! */ +// if (node->typeinfo->compatibility == NODE_NEW_SHADING) +// return false; if (node->typeinfo->execfunc) node->typeinfo->execfunc(callerdata, node, nsin, nsout); else if (node->typeinfo->newexecfunc) node->typeinfo->newexecfunc(callerdata, thread, node, nodeexec->data, nsin, nsout); } } + + /* signal to that all went OK, for render */ + return true; } diff --git a/source/blender/nodes/intern/node_exec.h b/source/blender/nodes/intern/node_exec.h index e985795de71..5febda036e0 100644 --- a/source/blender/nodes/intern/node_exec.h +++ b/source/blender/nodes/intern/node_exec.h @@ -77,10 +77,8 @@ void node_get_stack(struct bNode *node, struct bNodeStack *stack, struct bNodeSt struct bNodeTreeExec *ntree_exec_begin(struct bNodeTree *ntree); void ntree_exec_end(struct bNodeTreeExec *exec); -void ntreeExecNodes(struct bNodeTreeExec *exec, void *callerdata, int thread); - struct bNodeThreadStack *ntreeGetThreadStack(struct bNodeTreeExec *exec, int thread); void ntreeReleaseThreadStack(struct bNodeThreadStack *nts); -void ntreeExecThreadNodes(struct bNodeTreeExec *exec, struct bNodeThreadStack *nts, void *callerdata, int thread); +bool ntreeExecThreadNodes(struct bNodeTreeExec *exec, struct bNodeThreadStack *nts, void *callerdata, int thread); #endif diff --git a/source/blender/nodes/intern/node_util.h b/source/blender/nodes/intern/node_util.h index 3134baa283c..6b783915816 100644 --- a/source/blender/nodes/intern/node_util.h +++ b/source/blender/nodes/intern/node_util.h @@ -65,13 +65,3 @@ const char *node_filter_label(struct bNode *node); void node_update_internal_links_default(struct bNodeTree *ntree, struct bNode *node); #endif - -// this is needed for inlining behavior -#if defined _MSC_VER -# define DO_INLINE __inline -#elif defined (__sun) || defined (__sun__) -# define DO_INLINE -#else -# define DO_INLINE static inline -#endif - diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c index b7dc83d7d79..8fde0b9c342 100644 --- a/source/blender/nodes/shader/node_shader_tree.c +++ b/source/blender/nodes/shader/node_shader_tree.c @@ -248,7 +248,8 @@ void ntreeShaderEndExecTree(bNodeTreeExec *exec, int use_tree_data) } } -void ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr) +/* only for Blender internal */ +bool ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr) { ShaderCallData scd; /** @@ -258,6 +259,7 @@ void ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr) Material *mat = shi->mat; bNodeThreadStack *nts = NULL; bNodeTreeExec *exec = ntree->execdata; + int compat; /* convert caller data to struct */ scd.shi = shi; @@ -277,13 +279,17 @@ void ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr) } nts = ntreeGetThreadStack(exec, shi->thread); - ntreeExecThreadNodes(exec, nts, &scd, shi->thread); + compat = ntreeExecThreadNodes(exec, nts, &scd, shi->thread); ntreeReleaseThreadStack(nts); // \note: set material back to preserved material shi->mat = mat; + /* better not allow negative for now */ if (shr->combined[0] < 0.0f) shr->combined[0] = 0.0f; if (shr->combined[1] < 0.0f) shr->combined[1] = 0.0f; if (shr->combined[2] < 0.0f) shr->combined[2] = 0.0f; + + /* if compat is zero, it has been using non-compatible nodes */ + return compat; } diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c index 544ccb8fda6..f567e36cc19 100644 --- a/source/blender/nodes/shader/node_shader_util.c +++ b/source/blender/nodes/shader/node_shader_util.c @@ -221,6 +221,7 @@ void node_gpu_stack_from_data(struct GPUNodeStack *gs, int type, bNodeStack *ns) void node_data_from_gpu_stack(bNodeStack *ns, GPUNodeStack *gs) { + copy_v4_v4(ns->vec, gs->vec); ns->data= gs->link; ns->sockettype= gs->sockettype; } diff --git a/source/blender/nodes/shader/node_shader_util.h b/source/blender/nodes/shader/node_shader_util.h index e4dc74e8d40..9c911501435 100644 --- a/source/blender/nodes/shader/node_shader_util.h +++ b/source/blender/nodes/shader/node_shader_util.h @@ -49,6 +49,12 @@ #include "DNA_scene_types.h" #include "DNA_texture_types.h" +#include "BLI_math.h" +#include "BLI_blenlib.h" +#include "BLI_rand.h" +#include "BLI_threads.h" +#include "BLI_utildefines.h" + #include "BKE_blender.h" #include "BKE_colortools.h" #include "BKE_global.h" @@ -63,12 +69,6 @@ #include "NOD_shader.h" #include "node_util.h" -#include "BLI_math.h" -#include "BLI_blenlib.h" -#include "BLI_rand.h" -#include "BLI_threads.h" -#include "BLI_utildefines.h" - #include "BLF_translation.h" #include "IMB_imbuf_types.h" diff --git a/source/blender/nodes/shader/nodes/node_shader_common.c b/source/blender/nodes/shader/nodes/node_shader_common.c index cf6f778bbf5..9c784709de3 100644 --- a/source/blender/nodes/shader/nodes/node_shader_common.c +++ b/source/blender/nodes/shader/nodes/node_shader_common.c @@ -33,6 +33,8 @@ #include "DNA_node_types.h" +#include "BLI_utildefines.h" + #include "BKE_node.h" #include "node_shader_util.h" diff --git a/source/blender/nodes/shader/nodes/node_shader_texture.c b/source/blender/nodes/shader/nodes/node_shader_texture.c index b77c7d07407..ec238b62408 100644 --- a/source/blender/nodes/shader/nodes/node_shader_texture.c +++ b/source/blender/nodes/shader/nodes/node_shader_texture.c @@ -72,7 +72,7 @@ static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, b if (in[0]->datatype==NS_OSA_VECTORS) { float *fp= in[0]->data; - retval= multitex_nodes((Tex *)node->id, vec, fp, fp+3, shi->osatex, &texres, thread, which_output, NULL, NULL); + retval = multitex_nodes((Tex *)node->id, vec, fp, fp+3, shi->osatex, &texres, thread, which_output, NULL, NULL, NULL); } else if (in[0]->datatype==NS_OSA_VALUES) { float *fp= in[0]->data; @@ -80,14 +80,14 @@ static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, b dxt[0] = fp[0]; dxt[1] = dxt[2] = 0.0f; dyt[0] = fp[1]; dyt[1] = dyt[2] = 0.0f; - retval= multitex_nodes((Tex *)node->id, vec, dxt, dyt, shi->osatex, &texres, thread, which_output, NULL, NULL); + retval = multitex_nodes((Tex *)node->id, vec, dxt, dyt, shi->osatex, &texres, thread, which_output, NULL, NULL, NULL); } else - retval= multitex_nodes((Tex *)node->id, vec, NULL, NULL, 0, &texres, thread, which_output, NULL, NULL); + retval = multitex_nodes((Tex *)node->id, vec, NULL, NULL, 0, &texres, thread, which_output, NULL, NULL, NULL); } else { copy_v3_v3(vec, shi->lo); - retval= multitex_nodes((Tex *)node->id, vec, NULL, NULL, 0, &texres, thread, which_output, NULL, NULL); + retval = multitex_nodes((Tex *)node->id, vec, NULL, NULL, 0, &texres, thread, which_output, NULL, NULL, NULL); } /* stupid exception */ diff --git a/source/blender/nodes/texture/node_texture_util.h b/source/blender/nodes/texture/node_texture_util.h index 16dbc2f7bfb..3b2a7e14f69 100644 --- a/source/blender/nodes/texture/node_texture_util.h +++ b/source/blender/nodes/texture/node_texture_util.h @@ -48,6 +48,12 @@ #include "DNA_scene_types.h" #include "DNA_texture_types.h" +#include "BLI_math.h" +#include "BLI_blenlib.h" +#include "BLI_rand.h" +#include "BLI_threads.h" +#include "BLI_utildefines.h" + #include "BKE_blender.h" #include "BKE_colortools.h" #include "BKE_global.h" @@ -56,19 +62,12 @@ #include "BKE_material.h" #include "BKE_node.h" #include "BKE_texture.h" - #include "BKE_library.h" #include "node_util.h" #include "NOD_texture.h" -#include "BLI_math.h" -#include "BLI_blenlib.h" -#include "BLI_rand.h" -#include "BLI_threads.h" -#include "BLI_utildefines.h" - #include "BLF_translation.h" #include "IMB_imbuf_types.h" diff --git a/source/blender/nodes/texture/nodes/node_texture_common.c b/source/blender/nodes/texture/nodes/node_texture_common.c index 41bfd0ae00a..aa427ff3587 100644 --- a/source/blender/nodes/texture/nodes/node_texture_common.c +++ b/source/blender/nodes/texture/nodes/node_texture_common.c @@ -33,6 +33,8 @@ #include "DNA_node_types.h" +#include "BLI_utildefines.h" + #include "BKE_node.h" #include "node_texture_util.h" diff --git a/source/blender/nodes/texture/nodes/node_texture_proc.c b/source/blender/nodes/texture/nodes/node_texture_proc.c index 8876d98b9b2..de2dac22d81 100644 --- a/source/blender/nodes/texture/nodes/node_texture_proc.c +++ b/source/blender/nodes/texture/nodes/node_texture_proc.c @@ -69,7 +69,7 @@ static void do_proc(float *result, TexParams *p, const float col1[4], const floa texres.nor = NULL; textype = multitex_nodes(tex, p->co, p->dxt, p->dyt, p->osatex, - &texres, thread, 0, p->shi, p->mtex); + &texres, thread, 0, p->shi, p->mtex, NULL); if (is_normal) return; diff --git a/source/blender/nodes/texture/nodes/node_texture_texture.c b/source/blender/nodes/texture/nodes/node_texture_texture.c index cc7367a7632..f839f485976 100644 --- a/source/blender/nodes/texture/nodes/node_texture_texture.c +++ b/source/blender/nodes/texture/nodes/node_texture_texture.c @@ -78,7 +78,7 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor texres.nor = nor; textype = multitex_nodes(nodetex, co, dxt, dyt, p->osatex, - &texres, thread, 0, p->shi, p->mtex); + &texres, thread, 0, p->shi, p->mtex, NULL); if (textype & TEX_RGB) { copy_v4_v4(out, &texres.tr); diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index 13cb11d1301..0f5be095e0f 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -87,6 +87,11 @@ void BPY_context_update(struct bContext *C); void BPY_id_release(struct ID *id); +/* I18n for addons */ +#ifdef WITH_INTERNATIONAL +const char *BPY_app_translations_py_pgettext(const char *msgctxt, const char *msgid); +#endif + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/source/blender/python/bmesh/bmesh_py_api.c b/source/blender/python/bmesh/bmesh_py_api.c index ce8153fb994..47e6baf8e93 100644 --- a/source/blender/python/bmesh/bmesh_py_api.c +++ b/source/blender/python/bmesh/bmesh_py_api.c @@ -115,8 +115,8 @@ static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args, static const char *kwlist[] = {"mesh", "tessface", "destructive", NULL}; PyObject *py_me; Mesh *me; - int do_tessface = TRUE; - int is_destructive = TRUE; + int do_tessface = true; + int is_destructive = true; if (!PyArg_ParseTupleAndKeywords(args, kw, "O|ii:update_edit_mesh", (char **)kwlist, &py_me, &do_tessface, &is_destructive)) @@ -137,7 +137,7 @@ static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args, } { - extern void EDBM_update_generic(BMEditMesh *em, const short do_tessface, const short is_destructive); + extern void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_destructive); EDBM_update_generic(me->edit_btmesh, do_tessface, is_destructive); } diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.c b/source/blender/python/bmesh/bmesh_py_ops_call.c index 32315195072..d4c8033589a 100644 --- a/source/blender/python/bmesh/bmesh_py_ops_call.c +++ b/source/blender/python/bmesh/bmesh_py_ops_call.c @@ -214,7 +214,7 @@ static int bpy_slot_from_py(BMesh *bm, BMOperator *bmop, BMOpSlot *slot, PyObjec return -1; } else if (((size = ((MatrixObject *)value)->num_col) != ((MatrixObject *)value)->num_row) || - (ELEM(size, 3, 4) == FALSE)) + (ELEM(size, 3, 4) == false)) { PyErr_Format(PyExc_TypeError, "%.200s: keyword \"%.200s\" expected a 3x3 or 4x4 matrix Matrix", @@ -319,7 +319,7 @@ static int bpy_slot_from_py(BMesh *bm, BMOperator *bmop, BMOpSlot *slot, PyObjec elem_array = BPy_BMElem_PySeq_As_Array(&bm, value, 0, PY_SSIZE_T_MAX, &elem_array_len, (slot->slot_subtype.elem & BM_ALL_NOLOOP), - TRUE, TRUE, slot_name); + true, true, slot_name); /* error is set above */ if (elem_array == NULL) { diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index 37376cc7610..cde977288d1 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -127,11 +127,11 @@ static int bpy_bm_elem_hflag_set(BPy_BMElem *self, PyObject *value, void *flag) param = PyLong_AsLong(value); - if (param == TRUE) { + if (param == true) { BM_elem_flag_enable(self->ele, hflag); return 0; } - else if (param == FALSE) { + else if (param == false) { BM_elem_flag_disable(self->ele, hflag); return 0; } @@ -869,7 +869,7 @@ static PyObject *bpy_bmesh_to_mesh(BPy_BMesh *self, PyObject *args) bm = self->bm; - BM_mesh_bm_to_me(bm, me, FALSE); + BM_mesh_bm_to_me(bm, me, false); /* we could have the user do this but if they forget blender can easy crash * since the references arrays for the objects derived meshes are now invalid */ @@ -899,9 +899,9 @@ static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args) Object *ob; struct Scene *scene; BMesh *bm; - int use_deform = TRUE; - int use_render = FALSE; - int use_cage = FALSE; + int use_deform = true; + int use_render = false; + int use_cage = false; DerivedMesh *dm; const int mask = CD_MASK_BMESH; @@ -999,7 +999,7 @@ static PyObject *bpy_bmesh_from_mesh(BPy_BMesh *self, PyObject *args, PyObject * BMesh *bm; PyObject *py_mesh; Mesh *me; - int use_shape_key = FALSE; + int use_shape_key = false; int shape_key_index = 0; if (!PyArg_ParseTupleAndKeywords(args, kw, "O|ii:from_mesh", (char **)kwlist, @@ -1047,7 +1047,7 @@ static PyObject *bpy_bmesh_select_flush(BPy_BMesh *self, PyObject *value) BPY_BM_CHECK_OBJ(self); param = PyLong_AsLong(value); - if (param != FALSE && param != TRUE) { + if (param != false && param != true) { PyErr_SetString(PyExc_TypeError, "expected a boolean type 0/1"); return NULL; @@ -1071,7 +1071,7 @@ PyDoc_STRVAR(bpy_bmesh_normal_update_doc, static PyObject *bpy_bmesh_normal_update(BPy_BMesh *self, PyObject *args) { - int skip_hidden = FALSE; + int skip_hidden = false; BPY_BM_CHECK_OBJ(self); @@ -1178,7 +1178,7 @@ static PyObject *bpy_bm_elem_select_set(BPy_BMElem *self, PyObject *value) BPY_BM_CHECK_OBJ(self); param = PyLong_AsLong(value); - if (param != FALSE && param != TRUE) { + if (param != false && param != true) { PyErr_SetString(PyExc_TypeError, "expected a boolean type 0/1"); return NULL; @@ -1206,7 +1206,7 @@ static PyObject *bpy_bm_elem_hide_set(BPy_BMElem *self, PyObject *value) BPY_BM_CHECK_OBJ(self); param = PyLong_AsLong(value); - if (param != FALSE && param != TRUE) { + if (param != false && param != true) { PyErr_SetString(PyExc_TypeError, "expected a boolean type 0/1"); return NULL; @@ -1273,7 +1273,7 @@ static PyObject *bpy_bmvert_copy_from_vert_interp(BPy_BMVert *self, PyObject *ar vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 2, 2, &vert_seq_len, BM_VERT, - TRUE, TRUE, "BMVert.copy_from_vert_interp(...)"); + true, true, "BMVert.copy_from_vert_interp(...)"); if (vert_array == NULL) { return NULL; @@ -1523,8 +1523,8 @@ static PyObject *bpy_bmface_copy(BPy_BMFace *self, PyObject *args, PyObject *kw) static const char *kwlist[] = {"verts", "edges", NULL}; BMesh *bm = self->bm; - int do_verts = TRUE; - int do_edges = TRUE; + int do_verts = true; + int do_edges = true; BMFace *f_cpy; BPY_BM_CHECK_OBJ(self); @@ -1664,8 +1664,8 @@ PyDoc_STRVAR(bpy_bmloop_copy_from_face_interp_doc, static PyObject *bpy_bmloop_copy_from_face_interp(BPy_BMLoop *self, PyObject *args) { BPy_BMFace *py_face = NULL; - int do_vertex = TRUE; - int do_multires = TRUE; + int do_vertex = true; + int do_multires = true; BPY_BM_CHECK_OBJ(self); @@ -1833,7 +1833,7 @@ static PyObject *bpy_bmedgeseq_new(BPy_BMElemSeq *self, PyObject *args) vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 2, 2, &vert_seq_len, BM_VERT, - TRUE, TRUE, "edges.new(...)"); + true, true, "edges.new(...)"); if (vert_array == NULL) { return NULL; @@ -1911,7 +1911,7 @@ static PyObject *bpy_bmfaceseq_new(BPy_BMElemSeq *self, PyObject *args) vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 3, PY_SSIZE_T_MAX, &vert_seq_len, BM_VERT, - TRUE, TRUE, "faces.new(...)"); + true, true, "faces.new(...)"); if (vert_array == NULL) { return NULL; @@ -2064,7 +2064,7 @@ static PyObject *bpy_bmedgeseq_get__method(BPy_BMElemSeq *self, PyObject *args) vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 2, 2, &vert_seq_len, BM_VERT, - TRUE, TRUE, "edges.get(...)"); + true, true, "edges.get(...)"); if (vert_array == NULL) { return NULL; @@ -2116,7 +2116,7 @@ static PyObject *bpy_bmfaceseq_get__method(BPy_BMElemSeq *self, PyObject *args) vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 1, PY_SSIZE_T_MAX, &vert_seq_len, BM_VERT, - TRUE, TRUE, "faces.get(...)"); + true, true, "faces.get(...)"); if (vert_array == NULL) { return NULL; @@ -2243,7 +2243,7 @@ static PyObject *bpy_bmelemseq_sort(BPy_BMElemSeq *self, PyObject *args, PyObjec { static const char *kwlist[] = {"key", "reverse", NULL}; PyObject *keyfunc = NULL; /* optional */ - int reverse = FALSE; /* optional */ + int do_reverse = false; /* optional */ const char htype = bm_iter_itype_htype_map[self->itype]; int n_elem; @@ -2268,7 +2268,7 @@ static PyObject *bpy_bmelemseq_sort(BPy_BMElemSeq *self, PyObject *args, PyObjec if (!PyArg_ParseTupleAndKeywords(args, kw, "|Oi:BMElemSeq.sort", (char **)kwlist, - &keyfunc, &reverse)) + &keyfunc, &do_reverse)) { return NULL; } @@ -2338,7 +2338,7 @@ static PyObject *bpy_bmelemseq_sort(BPy_BMElemSeq *self, PyObject *args, PyObjec range_vn_i(elem_idx, n_elem, 0); /* Sort the index array according to the order of the 'keys' array */ - if (reverse) + if (do_reverse) elem_idx_compare_by_keys = bpy_bmelemseq_sort_cmp_by_keys_descending; else elem_idx_compare_by_keys = bpy_bmelemseq_sort_cmp_by_keys_ascending; @@ -2616,7 +2616,7 @@ static PyObject *bpy_bmelemseq_subscript_slice(BPy_BMElemSeq *self, Py_ssize_t s { BMIter iter; int count = 0; - int ok; + bool ok; PyObject *list; PyObject *item; @@ -2628,14 +2628,14 @@ static PyObject *bpy_bmelemseq_subscript_slice(BPy_BMElemSeq *self, Py_ssize_t s ok = BM_iter_init(&iter, self->bm, self->itype, self->py_ele ? self->py_ele->ele : NULL); - BLI_assert(ok == TRUE); + BLI_assert(ok == true); - if (UNLIKELY(ok == FALSE)) { + if (UNLIKELY(ok == false)) { return list; } /* first loop up-until the start */ - for (ok = TRUE; ok; ok = (BM_iter_step(&iter) != NULL)) { + for (ok = true; ok; ok = (BM_iter_step(&iter) != NULL)) { if (count == start) { break; } @@ -3434,7 +3434,7 @@ int bpy_bm_generic_valid_check(BPy_BMGeneric *self) * function where the actual error will be caused by * the previous action. */ #if 0 - if (BM_mesh_validate(self->bm) == FALSE) { + if (BM_mesh_validate(self->bm) == false) { PyErr_Format(PyExc_ReferenceError, "BMesh used by %.200s has become invalid", Py_TYPE(self)->tp_name); @@ -3479,7 +3479,7 @@ void bpy_bm_generic_invalidate(BPy_BMGeneric *self) */ void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size, const char htype, - const char do_unique_check, const char do_bm_check, + const bool do_unique_check, const bool do_bm_check, const char *error_prefix) { BMesh *bm = (r_bm && *r_bm) ? *r_bm : NULL; @@ -3546,17 +3546,17 @@ void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ if (do_unique_check) { /* check for double verts! */ - int ok = TRUE; + bool ok = true; for (i = 0; i < seq_len; i++) { - if (UNLIKELY(BM_elem_flag_test(alloc[i], BM_ELEM_INTERNAL_TAG) == FALSE)) { - ok = FALSE; + if (UNLIKELY(BM_elem_flag_test(alloc[i], BM_ELEM_INTERNAL_TAG) == false)) { + ok = false; } /* ensure we don't leave this enabled */ BM_elem_flag_disable(alloc[i], BM_ELEM_INTERNAL_TAG); } - if (ok == FALSE) { + if (ok == false) { PyErr_Format(PyExc_ValueError, "%s: found the same %.200s used multiple times", error_prefix, BPy_BMElem_StringFromHType(htype)); diff --git a/source/blender/python/bmesh/bmesh_py_types.h b/source/blender/python/bmesh/bmesh_py_types.h index d15918a3c11..8e6d04ec9ba 100644 --- a/source/blender/python/bmesh/bmesh_py_types.h +++ b/source/blender/python/bmesh/bmesh_py_types.h @@ -160,7 +160,7 @@ PyObject *BPy_BMElem_CreatePyObject(BMesh *bm, BMHeader *ele); /* just checks ty void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size, const char htype, - const char do_unique_check, const char do_bm_check, + const bool do_unique_check, const bool do_bm_check, const char *error_prefix); PyObject *BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_len); diff --git a/source/blender/python/bmesh/bmesh_py_types_meshdata.c b/source/blender/python/bmesh/bmesh_py_types_meshdata.c index b0870578f5a..f59676252d4 100644 --- a/source/blender/python/bmesh/bmesh_py_types_meshdata.c +++ b/source/blender/python/bmesh/bmesh_py_types_meshdata.c @@ -187,10 +187,10 @@ static int bpy_bmloopuv_flag_set(BPy_BMLoopUV *self, PyObject *value, void *flag const int flag = GET_INT_FROM_POINTER(flag_p); switch (PyLong_AsLong(value)) { - case TRUE: + case true: self->data->flag |= flag; return 0; - case FALSE: + case false: self->data->flag &= ~flag; return 0; default: diff --git a/source/blender/python/bmesh/bmesh_py_types_select.c b/source/blender/python/bmesh/bmesh_py_types_select.c index dfcfbeb0ab5..33cb1f5d0fb 100644 --- a/source/blender/python/bmesh/bmesh_py_types_select.c +++ b/source/blender/python/bmesh/bmesh_py_types_select.c @@ -107,7 +107,7 @@ static PyObject *bpy_bmeditselseq_add(BPy_BMEditSelSeq *self, BPy_BMElem *value) if ((BPy_BMVert_Check(value) || BPy_BMEdge_Check(value) || - BPy_BMFace_Check(value)) == FALSE) + BPy_BMFace_Check(value)) == false) { PyErr_Format(PyExc_TypeError, "Expected a BMVert/BMedge/BMFace not a %.200s", Py_TYPE(value)->tp_name); @@ -132,7 +132,7 @@ static PyObject *bpy_bmeditselseq_remove(BPy_BMEditSelSeq *self, BPy_BMElem *val if ((BPy_BMVert_Check(value) || BPy_BMEdge_Check(value) || - BPy_BMFace_Check(value)) == FALSE) + BPy_BMFace_Check(value)) == false) { PyErr_Format(PyExc_TypeError, "Expected a BMVert/BMedge/BMFace not a %.200s", Py_TYPE(value)->tp_name); @@ -141,7 +141,7 @@ static PyObject *bpy_bmeditselseq_remove(BPy_BMEditSelSeq *self, BPy_BMElem *val BPY_BM_CHECK_SOURCE_OBJ(value, self->bm, "select_history.remove()"); - if (BM_select_history_remove(self->bm, value->ele) == FALSE) { + if (BM_select_history_remove(self->bm, value->ele) == false) { PyErr_SetString(PyExc_ValueError, "Element not found in selection history"); return NULL; @@ -196,7 +196,7 @@ static PyObject *bpy_bmeditselseq_subscript_int(BPy_BMEditSelSeq *self, int keyn static PyObject *bpy_bmeditselseq_subscript_slice(BPy_BMEditSelSeq *self, Py_ssize_t start, Py_ssize_t stop) { int count = 0; - int ok; + bool ok; PyObject *list; PyObject *item; @@ -210,12 +210,12 @@ static PyObject *bpy_bmeditselseq_subscript_slice(BPy_BMEditSelSeq *self, Py_ssi ok = (ese != NULL); - if (UNLIKELY(ok == FALSE)) { + if (UNLIKELY(ok == false)) { return list; } /* first loop up-until the start */ - for (ok = TRUE; ok; ok = ((ese = ese->next) != NULL)) { + for (ok = true; ok; ok = ((ese = ese->next) != NULL)) { if (count == start) { break; } @@ -429,7 +429,7 @@ int BPy_BMEditSel_Assign(BPy_BMesh *self, PyObject *value) value_array = BPy_BMElem_PySeq_As_Array(&bm, value, 0, PY_SSIZE_T_MAX, &value_len, BM_VERT | BM_EDGE | BM_FACE, - TRUE, TRUE, "BMesh.select_history = value"); + true, true, "BMesh.select_history = value"); if (value_array == NULL) { return -1; diff --git a/source/blender/python/bmesh/bmesh_py_utils.c b/source/blender/python/bmesh/bmesh_py_utils.c index a43c5c18126..7c0adcfc997 100644 --- a/source/blender/python/bmesh/bmesh_py_utils.c +++ b/source/blender/python/bmesh/bmesh_py_utils.c @@ -90,7 +90,7 @@ static PyObject *bpy_bm_utils_vert_collapse_edge(PyObject *UNUSED(self), PyObjec bm = py_edge->bm; - e_new = BM_vert_collapse_edge(bm, py_edge->e, py_vert->v, TRUE); + e_new = BM_vert_collapse_edge(bm, py_edge->e, py_vert->v, true); if (e_new) { return BPy_BMEdge_CreatePyObject(bm, e_new); @@ -156,7 +156,7 @@ static PyObject *bpy_bm_utils_vert_collapse_faces(PyObject *UNUSED(self), PyObje bm = py_edge->bm; - e_new = BM_vert_collapse_faces(bm, py_edge->e, py_vert->v, CLAMPIS(fac, 0.0f, 1.0f), do_join_faces, TRUE); + e_new = BM_vert_collapse_faces(bm, py_edge->e, py_vert->v, CLAMPIS(fac, 0.0f, 1.0f), do_join_faces, true); if (e_new) { return BPy_BMEdge_CreatePyObject(bm, e_new); @@ -239,7 +239,7 @@ static PyObject *bpy_bm_utils_vert_separate(PyObject *UNUSED(self), PyObject *ar edge_array = BPy_BMElem_PySeq_As_Array(&bm, edge_seq, 0, PY_SSIZE_T_MAX, &edge_array_len, BM_EDGE, - TRUE, TRUE, "vert_separate(...)"); + true, true, "vert_separate(...)"); if (edge_array == NULL) { return NULL; @@ -338,7 +338,7 @@ PyDoc_STRVAR(bpy_bm_utils_edge_rotate_doc, static PyObject *bpy_bm_utils_edge_rotate(PyObject *UNUSED(self), PyObject *args) { BPy_BMEdge *py_edge; - int do_ccw = FALSE; + int do_ccw = false; BMesh *bm; BMEdge *e_new = NULL; @@ -396,7 +396,7 @@ static PyObject *bpy_bm_utils_face_split(PyObject *UNUSED(self), PyObject *args, /* optional */ PyObject *py_coords = NULL; - int edge_exists = TRUE; + int edge_exists = true; BPy_BMEdge *py_edge_example = NULL; float *coords; @@ -426,8 +426,8 @@ static PyObject *bpy_bm_utils_face_split(PyObject *UNUSED(self), PyObject *args, } /* this doubles for checking that the verts are in the same mesh */ - if (BM_vert_in_face(py_face->f, py_vert_a->v) == FALSE || - BM_vert_in_face(py_face->f, py_vert_b->v) == FALSE) + if (BM_vert_in_face(py_face->f, py_vert_a->v) == false || + BM_vert_in_face(py_face->f, py_vert_b->v) == false) { PyErr_SetString(PyExc_ValueError, "face_split(...): one of the verts passed is not found in the face"); @@ -496,7 +496,7 @@ static PyObject *bpy_bm_utils_face_join(PyObject *UNUSED(self), PyObject *args) BMFace **face_array; Py_ssize_t face_seq_len = 0; BMFace *f_new; - int do_remove = TRUE; + int do_remove = true; if (!PyArg_ParseTuple(args, "O|i:face_join", &py_face_array, &do_remove)) { return NULL; @@ -504,7 +504,7 @@ static PyObject *bpy_bm_utils_face_join(PyObject *UNUSED(self), PyObject *args) face_array = BPy_BMElem_PySeq_As_Array(&bm, py_face_array, 2, PY_SSIZE_T_MAX, &face_seq_len, BM_FACE, - TRUE, TRUE, "face_join(...)"); + true, true, "face_join(...)"); if (face_array == NULL) { return NULL; /* error will be set */ diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt index 823c7c709d7..30ab4bd4b0e 100644 --- a/source/blender/python/intern/CMakeLists.txt +++ b/source/blender/python/intern/CMakeLists.txt @@ -49,6 +49,7 @@ set(SRC bpy_app_ffmpeg.c bpy_app_build_options.c bpy_app_handlers.c + bpy_app_translations.c bpy_driver.c bpy_interface.c bpy_interface_atexit.c @@ -72,6 +73,7 @@ set(SRC bpy_app_ffmpeg.h bpy_app_build_options.h bpy_app_handlers.h + bpy_app_translations.h bpy_driver.h bpy_intern_string.h bpy_library.h diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index 65568e9a0c1..7889b9a7f0b 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -36,6 +36,8 @@ #include "bpy_app_ffmpeg.h" #include "bpy_app_build_options.h" +#include "bpy_app_translations.h" + #include "bpy_app_handlers.h" #include "bpy_driver.h" @@ -86,7 +88,8 @@ static PyStructSequence_Field app_info_fields[] = { {(char *)"ffmpeg", (char *)"FFmpeg library information backend"}, {(char *)"build_options", (char *)"A set containing most important enabled optional build features"}, {(char *)"handlers", (char *)"Application handler callbacks"}, - {NULL} + {(char *)"translations", (char *)"Application and addons internationalization API"}, + {NULL}, }; static PyStructSequence_Desc app_info_desc = { @@ -152,6 +155,7 @@ static PyObject *make_app_info(void) SetObjItem(BPY_app_ffmpeg_struct()); SetObjItem(BPY_app_build_options_struct()); SetObjItem(BPY_app_handlers_struct()); + SetObjItem(BPY_app_translations_struct()); #undef SetIntItem #undef SetStrItem diff --git a/source/blender/python/intern/bpy_app_build_options.c b/source/blender/python/intern/bpy_app_build_options.c index 8815348c22d..60105f73f37 100644 --- a/source/blender/python/intern/bpy_app_build_options.c +++ b/source/blender/python/intern/bpy_app_build_options.c @@ -32,7 +32,7 @@ static PyTypeObject BlenderAppBuildOptionsType; static PyStructSequence_Field app_builtopts_info_fields[] = { - /* names mostly follow CMake options, lowecases, after WITH_ */ + /* names mostly follow CMake options, lowercase, after WITH_ */ {(char *)"bullet", NULL}, {(char *)"codec_avi", NULL}, {(char *)"codec_ffmpeg", NULL}, @@ -72,7 +72,7 @@ static PyStructSequence_Field app_builtopts_info_fields[] = { static PyStructSequence_Desc app_builtopts_info_desc = { (char *)"bpy.app.build_options", /* name */ - (char *)"This module contains information about FFmpeg blender is linked against", /* doc */ + (char *)"This module contains information about options blender is built with", /* doc */ app_builtopts_info_fields, /* fields */ (sizeof(app_builtopts_info_fields) / sizeof(PyStructSequence_Field)) - 1 }; diff --git a/source/blender/python/intern/bpy_app_translations.c b/source/blender/python/intern/bpy_app_translations.c new file mode 100644 index 00000000000..b6d2f624229 --- /dev/null +++ b/source/blender/python/intern/bpy_app_translations.c @@ -0,0 +1,753 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Bastien Montagne + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/python/intern/bpy_app_translations.c + * \ingroup pythonintern + * + * This file defines a singleton py object accessed via 'bpy.app.translations', + * which exposes various data and functions useful in i18n work. + * Most notably, it allows to extend main translations with py dicts. + */ + +#include <Python.h> +/* XXX Why bloody hell isn't that included in Python.h???? */ +#include <structmember.h> + +#include "BLI_string.h" +#include "BLI_ghash.h" +#include "BLI_utildefines.h" + +#include "BPY_extern.h" +#include "bpy_app_translations.h" + +#include "MEM_guardedalloc.h" + +#include "BLF_translation.h" + +#include "RNA_types.h" +#include "RNA_access.h" + + +typedef struct +{ + PyObject_HEAD + /* The string used to separate context from actual message in PY_TRANSLATE RNA props. */ + const char *context_separator; + /* A "named tuple" (StructSequence actually...) containing all C-defined contexts. */ + PyObject *contexts; + /* A readonly mapping {C context id: python id} (actually, a MappingProxy). */ + PyObject *contexts_C_to_py; + /* A py dict containing all registered py dicts (order is more or less random, first match wins!). */ + PyObject *py_messages; +} BlenderAppTranslations; + +/* Our singleton instance pointer */ +static BlenderAppTranslations *_translations = NULL; + +#ifdef WITH_INTERNATIONAL + +/***** Helpers for ghash *****/ +typedef struct GHashKey { + const char *msgctxt; + const char *msgid; +} GHashKey; + +static GHashKey *_ghashutil_keyalloc(const void *msgctxt, const void *msgid) +{ + GHashKey *key = MEM_mallocN(sizeof(GHashKey), "Py i18n GHashKey"); + key->msgctxt = BLI_strdup(msgctxt ? msgctxt : BLF_I18NCONTEXT_DEFAULT_BPY_INTERN); + key->msgid = BLI_strdup(msgid); + return key; +} + +static unsigned int _ghashutil_keyhash(const void *ptr) +{ + const GHashKey *key = ptr; + unsigned int hash = BLI_ghashutil_strhash(key->msgctxt); + return hash ^ BLI_ghashutil_strhash(key->msgid); +} + +static int _ghashutil_keycmp(const void *a, const void *b) +{ + const GHashKey *A = a; + const GHashKey *B = b; + + /* Note: comparing msgid first, most of the time it will be enough! */ + int cmp = BLI_ghashutil_strcmp(A->msgid, B->msgid); + if (cmp == 0) + return BLI_ghashutil_strcmp(A->msgctxt, B->msgctxt); + return cmp; +} + +static void _ghashutil_keyfree(void *ptr) +{ + const GHashKey *key = ptr; + + /* We assume both msgctxt and msgid were BLI_strdup'ed! */ + MEM_freeN((void *)key->msgctxt); + MEM_freeN((void *)key->msgid); + MEM_freeN((void *)key); +} + +static void _ghashutil_valfree(void *ptr) +{ + MEM_freeN(ptr); +} + +/***** Python's messages cache *****/ + +/* We cache all messages available for a given locale from all py dicts into a single ghash. + * Changing of locale is not so common, while looking for a message translation is, so let's try to optimize + * the later as much as we can! + * Note changing of locale, as well as (un)registering a message dict, invalidate that cache. + */ +static GHash *_translations_cache = NULL; + +static void _clear_translations_cache(void) +{ + if (_translations_cache) { + BLI_ghash_free(_translations_cache, _ghashutil_keyfree, _ghashutil_valfree); + } + _translations_cache = NULL; +} + +static void _build_translations_cache(PyObject *py_messages, const char *locale) +{ + PyObject *uuid, *uuid_dict; + Py_ssize_t pos = 0; + char *language = NULL, *language_country = NULL, *language_variant = NULL; + + /* For each py dict, we'll search for full locale, then language+country, then language+variant, + * then only language keys... */ + BLF_locale_explode(locale, &language, NULL, NULL, &language_country, &language_variant); + + /* Clear the cached ghash if needed, and create a new one. */ + _clear_translations_cache(); + _translations_cache = BLI_ghash_new(_ghashutil_keyhash, _ghashutil_keycmp, __func__); + + /* Iterate over all py dicts. */ + while (PyDict_Next(py_messages, &pos, &uuid, &uuid_dict)) { + PyObject *lang_dict; + +#if 0 + PyObject_Print(uuid_dict, stdout, 0); + printf("\n"); +#endif + + /* Try to get first complete locale, then language+country, then language+variant, then only language */ + lang_dict = PyDict_GetItemString(uuid_dict, locale); + if (!lang_dict && language_country) { + lang_dict = PyDict_GetItemString(uuid_dict, language_country); + locale = language_country; + } + if (!lang_dict && language_variant) { + lang_dict = PyDict_GetItemString(uuid_dict, language_variant); + locale = language_variant; + } + if (!lang_dict && language) { + lang_dict = PyDict_GetItemString(uuid_dict, language); + locale = language; + } + + if (lang_dict) { + PyObject *pykey, *trans; + Py_ssize_t ppos = 0; + + if (!PyDict_Check(lang_dict)) { + printf("WARNING! In translations' dict of \""); + PyObject_Print(uuid, stdout, Py_PRINT_RAW); + printf("\":\n"); + printf(" Each language key must have a dictionary as value, \"%s\" is not valid, skipping: ", + locale); + PyObject_Print(lang_dict, stdout, Py_PRINT_RAW); + printf("\n"); + continue; + } + + /* Iterate over all translations of the found language dict, and populate our ghash cache. */ + while (PyDict_Next(lang_dict, &ppos, &pykey, &trans)) { + GHashKey *key; + const char *msgctxt = NULL, *msgid = NULL; + bool invalid_key = false; + + if ((PyTuple_CheckExact(pykey) == false) || (PyTuple_GET_SIZE(pykey) != 2)) { + invalid_key = true; + } + else { + PyObject *tmp = PyTuple_GET_ITEM(pykey, 0); + if (tmp == Py_None) { + msgctxt = BLF_I18NCONTEXT_DEFAULT; + } + else if (PyUnicode_Check(tmp)) { + msgctxt = _PyUnicode_AsString(tmp); + } + else { + invalid_key = true; + } + + tmp = PyTuple_GET_ITEM(pykey, 1); + if (PyUnicode_Check(tmp)) { + msgid = _PyUnicode_AsString(tmp); + } + else { + invalid_key = true; + } + } + + if (invalid_key) { + printf("WARNING! In translations' dict of \""); + PyObject_Print(uuid, stdout, Py_PRINT_RAW); + printf("\", %s language:\n", locale); + printf(" Keys must be tuples of (msgctxt [string or None], msgid [string]), " + "this one is not valid, skipping: "); + PyObject_Print(pykey, stdout, Py_PRINT_RAW); + printf("\n"); + continue; + } + if (PyUnicode_Check(trans) == false) { + printf("WARNING! In translations' dict of \""); + PyObject_Print(uuid, stdout, Py_PRINT_RAW); + printf("\":\n"); + printf(" Values must be strings, this one is not valid, skipping: "); + PyObject_Print(trans, stdout, Py_PRINT_RAW); + printf("\n"); + continue; + } + + key = _ghashutil_keyalloc(msgctxt, msgid); + + /* Do not overwrite existing keys! */ + if (BLI_ghash_lookup(_translations_cache, (void *)key)) { + continue; + } + + BLI_ghash_insert(_translations_cache, key, BLI_strdup(_PyUnicode_AsString(trans))); + } + } + } + + /* Clean up! */ + if (language) + MEM_freeN(language); + if (language_country) + MEM_freeN(language_country); + if (language_variant) + MEM_freeN(language_variant); +} + +const char *BPY_app_translations_py_pgettext(const char *msgctxt, const char *msgid) +{ +#define STATIC_LOCALE_SIZE 32 /* Should be more than enough! */ + + GHashKey *key; + static char locale[STATIC_LOCALE_SIZE] = ""; + const char *tmp; + + /* Just in case, should never happen! */ + if (!_translations) + return msgid; + + tmp = BLF_lang_get(); + if (strcmp(tmp, locale) || !_translations_cache) { + PyGILState_STATE _py_state; + + BLI_strncpy(locale, tmp, STATIC_LOCALE_SIZE); + + /* Locale changed or cache does not exist, refresh the whole cache! */ + /* This func may be called from C (i.e. outside of python interpreter 'context'). */ + _py_state = PyGILState_Ensure(); + + _build_translations_cache(_translations->py_messages, locale); + + PyGILState_Release(_py_state); + } + + /* And now, simply create the key (context, messageid) and find it in the cached dict! */ + key = _ghashutil_keyalloc(msgctxt, msgid); + + tmp = BLI_ghash_lookup(_translations_cache, key); + + _ghashutil_keyfree((void *)key); + + if (tmp) + return tmp; + return msgid; + +#undef STATIC_LOCALE_SIZE +} + +#endif /* WITH_INTERNATIONAL */ + +PyDoc_STRVAR(app_translations_py_messages_register_doc, +".. method:: register(module_name, translations_dict)\n" +"\n" +" Registers an addon's UI translations.\n" +"\n" +" Note: Does nothing when Blender is built without internationalization support.\n" +"\n" +" :arg module_name: The name identifying the addon.\n" +" :type module_name: string\n" +" :arg translations_dict: A dictionary built like that:\n" +" {locale: {msg_key: msg_translation, ...}, ...}\n" +" :type translations_dict: dict\n" +"\n" +); +static PyObject *app_translations_py_messages_register(BlenderAppTranslations *self, PyObject *args, PyObject *kw) +{ +#ifdef WITH_INTERNATIONAL + static const char *kwlist[] = {"module_name", "translations_dict", NULL}; + PyObject *module_name, *uuid_dict; + + if (!PyArg_ParseTupleAndKeywords(args, kw, "O!O!:bpy.app.translations.register", (char **)kwlist, &PyUnicode_Type, + &module_name, &PyDict_Type, &uuid_dict)) + { + return NULL; + } + + if (PyDict_Contains(self->py_messages, module_name)) { + PyErr_Format(PyExc_ValueError, + "bpy.app.translations.register: translations message cache already contains some data for " + "addon '%s'", (const char *)_PyUnicode_AsString(module_name)); + return NULL; + } + + PyDict_SetItem(self->py_messages, module_name, uuid_dict); + + /* Clear cached messages dict! */ + _clear_translations_cache(); +#else + (void)self; + (void)args; + (void)kw; +#endif + + /* And we are done! */ + Py_RETURN_NONE; +} + +PyDoc_STRVAR(app_translations_py_messages_unregister_doc, +".. method:: unregister(module_name)\n" +"\n" +" Unregisters an addon's UI translations.\n" +"\n" +" Note: Does nothing when Blender is built without internationalization support.\n" +"\n" +" :arg module_name: The name identifying the addon.\n" +" :type module_name: string\n" +"\n" +); +static PyObject *app_translations_py_messages_unregister(BlenderAppTranslations *self, PyObject *args, PyObject *kw) +{ +#ifdef WITH_INTERNATIONAL + static const char *kwlist[] = {"module_name", NULL}; + PyObject *module_name; + + if (!PyArg_ParseTupleAndKeywords(args, kw, "O!:bpy.app.translations.unregister", (char **)kwlist, &PyUnicode_Type, + &module_name)) + { + return NULL; + } + + if (PyDict_Contains(self->py_messages, module_name)) { + PyDict_DelItem(self->py_messages, module_name); + /* Clear cached messages ghash! */ + _clear_translations_cache(); + } +#else + (void)self; + (void)args; + (void)kw; +#endif + + /* And we are done! */ + Py_RETURN_NONE; +} + +/***** C-defined contexts *****/ +/* This is always available (even when WITH_INTERNATIONAL is not defined). */ + +static PyTypeObject BlenderAppTranslationsContextsType; + +static BLF_i18n_contexts_descriptor _contexts[] = BLF_I18NCONTEXTS_DESC; + +/* These fields are just empty placeholders, actual values get set in app_translations_struct(). + * This allows us to avoid many handwriting, and above all, to keep all context definition stuff in BLF_translation.h! + */ +static PyStructSequence_Field +app_translations_contexts_fields[sizeof(_contexts) / sizeof(BLF_i18n_contexts_descriptor)] = {{NULL}}; + +static PyStructSequence_Desc app_translations_contexts_desc = { + (char *)"bpy.app.translations.contexts", /* name */ + (char *)"This named tuple contains all pre-defined translation contexts", /* doc */ + app_translations_contexts_fields, /* fields */ + (sizeof(app_translations_contexts_fields) / sizeof(PyStructSequence_Field)) - 1 +}; + +static PyObject *app_translations_contexts_make(void) +{ + PyObject *translations_contexts; + BLF_i18n_contexts_descriptor *ctxt; + int pos = 0; + + translations_contexts = PyStructSequence_New(&BlenderAppTranslationsContextsType); + if (translations_contexts == NULL) { + return NULL; + } + +#define SetObjString(item) PyStructSequence_SET_ITEM(translations_contexts, pos++, PyUnicode_FromString((item))) +#define SetObjNone() Py_INCREF(Py_None); PyStructSequence_SET_ITEM(translations_contexts, pos++, Py_None) + + for (ctxt = _contexts; ctxt->c_id; ctxt++) { + if (ctxt->value) { + SetObjString(ctxt->value); + } + else { + SetObjNone(); + } + } + +#undef SetObjString +#undef SetObjNone + + return translations_contexts; +} + +/***** Main BlenderAppTranslations Py object definition *****/ + +PyDoc_STRVAR(app_translations_contexts_doc, + "A named tuple containing all pre-defined translation contexts.\n" + "WARNING: do not use the \"" BLF_I18NCONTEXT_DEFAULT_BPY_INTERN "\" context, it is internally assimilated as the " + "default one!\n" +); + +PyDoc_STRVAR(app_translations_contexts_C_to_py_doc, + "A readonly dict mapping contexts' C-identifiers to their py-identifiers." +); + +PyMemberDef app_translations_members[] = { + {(char *)"contexts", T_OBJECT_EX, offsetof(BlenderAppTranslations, contexts), READONLY, + app_translations_contexts_doc}, + {(char *)"contexts_C_to_py", T_OBJECT_EX, offsetof(BlenderAppTranslations, contexts_C_to_py), READONLY, + app_translations_contexts_C_to_py_doc}, + {NULL} +}; + +PyDoc_STRVAR(app_translations_locale_doc, + "The actual locale currently in use (will always return a void string when Blender is built without " + "internationalization support)." +); +static PyObject *app_translations_locale_get(PyObject *UNUSED(self), void *UNUSED(userdata)) +{ + return PyUnicode_FromString(BLF_lang_get()); +} + +/* Note: defining as getter, as (even if quite unlikely), this *may* change during runtime... */ +PyDoc_STRVAR(app_translations_locales_doc, "All locales currently known by Blender (i.e. available as translations)."); +static PyObject *app_translations_locales_get(PyObject *UNUSED(self), void *UNUSED(userdata)) +{ + PyObject *ret; + EnumPropertyItem *it, *items = BLF_RNA_lang_enum_properties(); + int num_locales = 0, pos = 0; + + if (items) { + /* This is not elegant, but simple! */ + for (it = items; it->identifier; it++) { + if (it->value) + num_locales++; + } + } + + ret = PyTuple_New(num_locales); + + if (items) { + for (it = items; it->identifier; it++) { + if (it->value) + PyTuple_SET_ITEM(ret, pos++, PyUnicode_FromString(it->description)); + } + } + + return ret; +} + +PyGetSetDef app_translations_getseters[] = { + /* {name, getter, setter, doc, userdata} */ + {(char *)"locale", (getter)app_translations_locale_get, NULL, app_translations_locale_doc, NULL}, + {(char *)"locales", (getter)app_translations_locales_get, NULL, app_translations_locales_doc, NULL}, + {NULL} +}; + +PyDoc_STRVAR(app_translations_pgettext_doc, +".. method:: pgettext(msgid, msgctxt)\n" +"\n" +" Try to translate the given msgid (with optional msgctxt).\n" +" NOTE: The (msgid, msgctxt) parameter orders has been switched compared to gettext function, to allow\n" +" single-parameter calls (context then defaults to BLF_I18NCONTEXT_DEFAULT).\n" +" NOTE: You should really rarely need to use this function in regular addon code, as all translation should be\n" +" handled by Blender internal code.\n" +" Note: Does nothing when Blender is built without internationalization support (hence always returns msgid).\n" +"\n" +" :arg msgid: The string to translate.\n" +" :type msgid: string\n" +" :arg msgctxt: The translation context.\n" +" :type msgctxt: string or None\n" +" :default msgctxt: BLF_I18NCONTEXT_DEFAULT value.\n" +" :return: The translated string (or msgid if no translation was found).\n" +"\n" +); +static PyObject *app_translations_pgettext(BlenderAppTranslations *UNUSED(self), PyObject *args, PyObject *kw) +{ + /* Note we could optimize this a bit when WITH_INTERNATIONAL is not defined, but don't think "code complexity" would + * be worth it, as this func should not often be used! + */ + /* XXX This code fails with scons when WITH_INTERNATIONAL is not defined, at link time, stating that BLF_pgettext + * is undefined... So using #ifdef after all, rather than removing scons from blender trunk! + */ + static const char *kwlist[] = {"msgid", "msgctxt", NULL}; + char *msgid, *msgctxt = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kw, "s|z:bpy.app.translations.pgettext", (char **)kwlist, + &msgid, &msgctxt)) + { + return NULL; + } + +#ifdef WITH_INTERNATIONAL + return PyUnicode_FromString(BLF_pgettext(msgctxt ? msgctxt : BLF_I18NCONTEXT_DEFAULT, msgid)); +#else + return PyUnicode_FromString(msgid); +#endif +} + +PyDoc_STRVAR(app_translations_locale_explode_doc, +".. method:: locale_explode(locale)\n" +"\n" +" Return all components and their combinations of the given ISO locale string.\n" +"\n" +" >>> bpy.app.translations.locale_explode(\"sr_RS@latin\")\n" +" (\"sr\", \"RS\", \"latin\", \"sr_RS\", \"sr@latin\")\n" +"\n" +" For non-complete locales, missing elements will be None.\n" +"\n" +" :arg locale: The ISO locale string to explode.\n" +" :type msgid: string\n" +" :return: A tuple (language, country, variant, language_country, language@variant).\n" +"\n" +); +static PyObject *app_translations_locale_explode(BlenderAppTranslations *UNUSED(self), PyObject *args, PyObject *kw) +{ + static const char *kwlist[] = {"locale", NULL}; + const char *locale; + char *language, *country, *variant, *language_country, *language_variant; + + if (!PyArg_ParseTupleAndKeywords(args, kw, "s:bpy.app.translations.locale_explode", (char **)kwlist, &locale)) { + return NULL; + } + + BLF_locale_explode(locale, &language, &country, &variant, &language_country, &language_variant); + + return Py_BuildValue("sssss", language, country, variant, language_country, language_variant); +} + +PyMethodDef app_translations_methods[] = { + /* Can't use METH_KEYWORDS alone, see http://bugs.python.org/issue11587 */ + {(char *)"register", (PyCFunction)app_translations_py_messages_register, METH_VARARGS | METH_KEYWORDS, + app_translations_py_messages_register_doc}, + {(char *)"unregister", (PyCFunction)app_translations_py_messages_unregister, METH_VARARGS | METH_KEYWORDS, + app_translations_py_messages_unregister_doc}, + {(char *)"pgettext", (PyCFunction)app_translations_pgettext, METH_VARARGS | METH_KEYWORDS | METH_STATIC, + app_translations_pgettext_doc}, + {(char *)"locale_explode", (PyCFunction)app_translations_locale_explode, METH_VARARGS | METH_KEYWORDS | METH_STATIC, + app_translations_locale_explode_doc}, + {NULL} +}; + +static PyObject *app_translations_new(PyTypeObject *type, PyObject *UNUSED(args), PyObject *UNUSED(kw)) +{ +/* printf("%s (%p)\n", __func__, _translations); */ + + if (!_translations) { + _translations = (BlenderAppTranslations *)type->tp_alloc(type, 0); + if (_translations) { + PyObject *py_ctxts; + BLF_i18n_contexts_descriptor *ctxt; + + _translations->contexts = app_translations_contexts_make(); + + py_ctxts = PyDict_New(); + for (ctxt = _contexts; ctxt->c_id; ctxt++) { + PyObject *val = PyUnicode_FromString(ctxt->py_id); + PyDict_SetItemString(py_ctxts, ctxt->c_id, val); + Py_DECREF(val); + } + _translations->contexts_C_to_py = PyDictProxy_New(py_ctxts); + Py_DECREF(py_ctxts); /* The actual dict is only owned by its proxy */ + + _translations->py_messages = PyDict_New(); + } + } + + return (PyObject *)_translations; +} + +static void app_translations_free(void *obj) +{ + PyObject_Del(obj); +#ifdef WITH_INTERNATIONAL + _clear_translations_cache(); +#endif +} + +PyDoc_STRVAR(app_translations_doc, +" This object contains some data/methods regarding internationalization in Blender, and allows every py script\n" +" to feature translations for its own UI messages.\n" +"\n" +" WARNING: Most of this object should only be useful if you actually manipulate i18n stuff from Python.\n" +" If you are a regular addon, you should only bother about :contexts: and :context_sep: members, and the \n" +" :register:/:unregister: functions!" +"\n" +" To add translations to your python script, you must define a dictionary formatted like that:\n" +" {locale: {msg_key: msg_translation, ...}, ...}\n" +" where:\n" +" locale is either a lang iso code (e.g. 'fr'), a lang+country code (e.g. 'pt_BR'),\n" +" a lang+variant code (e.g. 'sr@latin'), or a full code (e.g. 'uz_UZ@cyrilic').\n" +" msg_key is a tuple (context, org message) - use, as much as possible, the predefined :contexts:.\n" +" msg_translation is the translated message in given language!" +" Then, call bpy.app.translations.register(__name__, your_dict) in your register() function, and \n" +" bpy.app.translations.unregister(__name__) in your unregister() one.\n" +"\n" +" bl_i18n_utils module has several functions to help you collect strings to translate, and generate the needed\n" +" python code (the translation dictionary), as well as optional intermediary po files if you want some...\n" +" See its documentation for more details.\n" +"\n" +); +static PyTypeObject BlenderAppTranslationsType = { + PyVarObject_HEAD_INIT(NULL, 0) + /* tp_name */ + (char *)"bpy.app._translations_type", + /* tp_basicsize */ + sizeof(BlenderAppTranslations), + 0, /* tp_itemsize */ + /* methods */ + /* No destructor, this is a singleton! */ + NULL, /* tp_dealloc */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ + NULL, /* tp_repr */ + + /* Method suites for standard classes */ + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + NULL, /* PyMappingMethods *tp_as_mapping; */ + + /* More standard operations (here for binary compatibility) */ + NULL, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ + NULL, /* getattrofunc tp_getattro; */ + NULL, /* setattrofunc tp_setattro; */ + + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ + + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT, /* long tp_flags; */ + + app_translations_doc, /* char *tp_doc; Documentation string */ + + /*** Assigned meaning in release 2.0 ***/ + /* call function for all accessible objects */ + NULL, /* traverseproc tp_traverse; */ + + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ + + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons ***/ + NULL, /* richcmpfunc tp_richcompare; */ + + /*** weak reference enabler ***/ + 0, /* long tp_weaklistoffset */ + + /*** Added in release 2.2 ***/ + /* Iterators */ + NULL, /* getiterfunc tp_iter; */ + NULL, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + app_translations_methods, /* struct PyMethodDef *tp_methods; */ + app_translations_members, /* struct PyMemberDef *tp_members; */ + app_translations_getseters, /* struct PyGetSetDef *tp_getset; */ + NULL, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + /* newfunc tp_new; */ + (newfunc)app_translations_new, + /* Low-level free-memory routine */ + app_translations_free, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL +}; + +PyObject *BPY_app_translations_struct(void) +{ + PyObject *ret; + + /* Let's finalize our contexts structseq definition! */ + { + BLF_i18n_contexts_descriptor *ctxt; + PyStructSequence_Field *desc; + + /* We really populate the contexts' fields here! */ + for (ctxt = _contexts, desc = app_translations_contexts_desc.fields; ctxt->c_id; ctxt++, desc++) { + desc->name = (char *)ctxt->py_id; + desc->doc = NULL; + } + desc->name = desc->doc = NULL; /* End sentinel! */ + + PyStructSequence_InitType(&BlenderAppTranslationsContextsType, &app_translations_contexts_desc); + } + + if (PyType_Ready(&BlenderAppTranslationsType) < 0) + return NULL; + + ret = PyObject_CallObject((PyObject *)&BlenderAppTranslationsType, NULL); + + /* prevent user from creating new instances */ + BlenderAppTranslationsType.tp_new = NULL; + /* without this we can't do set(sys.modules) [#29635] */ + BlenderAppTranslationsType.tp_hash = (hashfunc)_Py_HashPointer; + + return ret; +} diff --git a/source/blender/python/intern/bpy_app_translations.h b/source/blender/python/intern/bpy_app_translations.h new file mode 100644 index 00000000000..704307574d0 --- /dev/null +++ b/source/blender/python/intern/bpy_app_translations.h @@ -0,0 +1,32 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Bastien Montagne + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/python/intern/bpy_app_translations.h + * \ingroup pythonintern + */ + +#ifndef __BPY_APP_TRANSLATIONS_H__ +#define __BPY_APP_TRANSLATIONS_H__ + +PyObject *BPY_app_translations_struct(void); + +#endif /* __BPY_APP_TRANSLATIONS_H__ */ diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index f3fa0c9a0a9..b42fdbd0ca4 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -74,13 +74,15 @@ static EnumPropertyItem property_flag_enum_items[] = { {0, NULL, 0, NULL, NULL}}; /* subtypes */ +/* XXX Keep in sync with rna_rna.c's property_subtype_items ??? + * Currently it is not... + */ static EnumPropertyItem property_subtype_string_items[] = { {PROP_FILEPATH, "FILE_PATH", 0, "File Path", ""}, {PROP_DIRPATH, "DIR_PATH", 0, "Directory Path", ""}, {PROP_FILENAME, "FILE_NAME", 0, "Filename", ""}, {PROP_BYTESTRING, "BYTE_STRING", 0, "Byte String", ""}, - {PROP_TRANSLATE, "TRANSLATE", 0, "Translate", ""}, - {PROP_PASSWORD, "PASSWORD", 0, "Password", 0}, + {PROP_PASSWORD, "PASSWORD", 0, "Password", "A string that is displayed hidden ('********')"}, {PROP_NONE, "NONE", 0, "None", ""}, {0, NULL, 0, NULL, NULL}}; @@ -1257,6 +1259,20 @@ static size_t strswapbufcpy(char *buf, const char **orig) } #endif +static int icon_id_from_name(const char *name) +{ + EnumPropertyItem *item; + int id; + + if (name[0]) { + for (item = icon_items, id = 0; item->identifier; item++, id++) + if (strcmp(item->name, name) == 0) + return item->value; + } + + return 0; +} + static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, int *defvalue, const short is_enum_flag) { EnumPropertyItem *items; @@ -1303,6 +1319,7 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i for (i = 0; i < seq_len; i++) { EnumPropertyItem tmp = {0, "", 0, "", ""}; + const char *tmp_icon = NULL; Py_ssize_t item_size; Py_ssize_t id_str_size; Py_ssize_t name_str_size; @@ -1312,12 +1329,14 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i if ((PyTuple_CheckExact(item)) && (item_size = PyTuple_GET_SIZE(item)) && - (item_size == 3 || item_size == 4) && + (item_size >= 3 && item_size <= 5) && (tmp.identifier = _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 0), &id_str_size)) && (tmp.name = _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 1), &name_str_size)) && (tmp.description = _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 2), &desc_str_size)) && /* TODO, number isn't ensured to be unique from the script author */ - (item_size < 4 || py_long_as_int(PyTuple_GET_ITEM(item, 3), &tmp.value) != -1)) + (item_size != 4 || py_long_as_int(PyTuple_GET_ITEM(item, 3), &tmp.value) != -1) && + (item_size != 5 || ((tmp_icon = _PyUnicode_AsString(PyTuple_GET_ITEM(item, 3))) && + py_long_as_int(PyTuple_GET_ITEM(item, 4), &tmp.value) != -1))) { if (is_enum_flag) { if (item_size < 4) { @@ -1340,6 +1359,9 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i } } + if (tmp_icon) + tmp.icon = icon_id_from_name(tmp_icon); + items[i] = tmp; /* calculate combine string length */ @@ -1349,8 +1371,8 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i MEM_freeN(items); PyErr_SetString(PyExc_TypeError, "EnumProperty(...): expected a tuple containing " - "(identifier, name, description) and optionally a " - "unique number"); + "(identifier, name, description) and optionally an " + "icon name and unique number"); return NULL; } @@ -2501,7 +2523,7 @@ BPY_PROPDEF_DESC_DOC " :arg options: Enumerator in ['HIDDEN', 'SKIP_SAVE', 'ANIMATABLE', 'ENUM_FLAG', 'LIBRARY_EDITABLE'].\n" " :type options: set\n" " :arg items: sequence of enum items formatted:\n" -" [(identifier, name, description, number), ...] where the identifier is used\n" +" [(identifier, name, description, icon, number), ...] where the identifier is used\n" " for python access and other values are used for the interface.\n" " Note the item is optional.\n" " For dynamic values a callback can be passed which returns a list in\n" @@ -2509,7 +2531,7 @@ BPY_PROPDEF_DESC_DOC " This function must take 2 arguments (self, context)\n" " WARNING: Do not use generators here (they will work the first time, but will lead to empty values\n" " in some unload/reload scenarii)!\n" -" :type items: sequence of string triplets or a function\n" +" :type items: sequence of string triples or a function\n" BPY_PROPDEF_UPDATE_DOC ); static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw) diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 94f262f57f5..85a6db00703 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -1623,8 +1623,10 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb } } else { - /* Unicode String */ +#ifdef WITH_INTERNATIONAL + bool do_translate = RNA_property_flag(prop) & PROP_STRING_PY_TRANSLATE; +#endif /* WITH_INTERNATIONAL */ #ifdef USE_STRING_COERCE PyObject *value_coerce = NULL; @@ -1634,17 +1636,18 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb } else { param = _PyUnicode_AsString(value); -#ifdef WITH_INTERNATIONAL - if (subtype == PROP_TRANSLATE) { - param = IFACE_(param); - } -#endif /* WITH_INTERNATIONAL */ - } #else /* USE_STRING_COERCE */ param = _PyUnicode_AsString(value); #endif /* USE_STRING_COERCE */ + /* Any half-brained compiler should be able to optimize this out when WITH_INTERNATIONAL is off */ +#ifdef WITH_INTERNATIONAL + if (do_translate) { + param = IFACE_(param); + } +#endif + if (param == NULL) { if (PyUnicode_Check(value)) { /* there was an error assigning a string type, diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt index 16cba944e01..effc564fdc9 100644 --- a/source/blender/render/CMakeLists.txt +++ b/source/blender/render/CMakeLists.txt @@ -54,6 +54,7 @@ set(SRC intern/raytrace/rayobject_qbvh.cpp intern/raytrace/rayobject_rtbuild.cpp intern/raytrace/rayobject_vbvh.cpp + intern/source/bake.c intern/source/convertblender.c intern/source/envmap.c intern/source/external_engine.c diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index 64135a16f5d..b687acae1f7 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -62,6 +62,7 @@ struct Scene; #define RE_ENGINE_DO_UPDATE 8 #define RE_ENGINE_RENDERING 16 #define RE_ENGINE_HIGHLIGHT_TILES 32 +#define RE_ENGINE_USED_FOR_VIEWPORT 64 extern ListBase R_engines; @@ -105,6 +106,7 @@ typedef struct RenderEngine { } RenderEngine; RenderEngine *RE_engine_create(RenderEngineType *type); +RenderEngine *RE_engine_create_ex(RenderEngineType *type, int use_for_viewport); void RE_engine_free(RenderEngine *engine); void RE_layer_load_from_file(struct RenderLayer *layer, struct ReportList *reports, const char *filename, int x, int y); diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h index 2a9a1becc42..2dfbdd0d6f5 100644 --- a/source/blender/render/extern/include/RE_render_ext.h +++ b/source/blender/render/extern/include/RE_render_ext.h @@ -49,10 +49,11 @@ struct RNode; struct Render; struct MTex; struct ImBuf; +struct ImagePool; struct DerivedMesh; /* particle.c, effect.c, editmesh_modes.c and brush.c, returns 1 if rgb, 0 otherwise */ -int externtex(struct MTex *mtex, const float vec[3], float *tin, float *tr, float *tg, float *tb, float *ta, const int thread); +int externtex(struct MTex *mtex, const float vec[3], float *tin, float *tr, float *tg, float *tb, float *ta, const int thread, struct ImagePool *pool); /* particle.c */ void texture_rgb_blend(float in[3], const float tex[3], const float out[3], 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 10045a8f7e1..d686de21517 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -184,19 +184,24 @@ typedef struct ShadeInput { } ShadeInput; +typedef struct BakeImBufuserData { + float *displacement_buffer; + char *mask_buffer; +} BakeImBufuserData; /* node shaders... */ struct Tex; struct MTex; struct ImBuf; +struct ImagePool; /* this one uses nodes */ -int multitex_ext(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres); +int multitex_ext(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, struct ImagePool *pool); /* nodes disabled */ -int multitex_ext_safe(struct Tex *tex, float texvec[3], struct TexResult *texres); +int multitex_ext_safe(struct Tex *tex, float texvec[3], struct TexResult *texres, struct ImagePool *pool); /* only for internal node usage */ int multitex_nodes(struct Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, - const short thread, short which_output, struct ShadeInput *shi, struct MTex *mtex); + const short thread, short which_output, struct ShadeInput *shi, struct MTex *mtex, struct ImagePool *pool); /* shaded view and bake */ struct Render; @@ -206,6 +211,7 @@ struct Object; int RE_bake_shade_all_selected(struct Render *re, int type, struct Object *actob, short *do_update, float *progress); struct Image *RE_bake_shade_get_image(void); void RE_bake_ibuf_filter(struct ImBuf *ibuf, char *mask, const int filter); +void RE_bake_ibuf_normalize_displacement(struct ImBuf *ibuf, float *displacement, char *mask, float displacement_min, float displacement_max); #define BAKE_RESULT_OK 0 #define BAKE_RESULT_NO_OBJECTS 1 diff --git a/source/blender/render/intern/include/envmap.h b/source/blender/render/intern/include/envmap.h index d0f346f7402..a6c6d46e2e9 100644 --- a/source/blender/render/intern/include/envmap.h +++ b/source/blender/render/intern/include/envmap.h @@ -44,9 +44,10 @@ struct Render; struct TexResult; +struct ImagePool; void make_envmaps(struct Render *re); -int envmaptex(struct Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres); +int envmaptex(struct Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, struct TexResult *texres, struct ImagePool *pool); #endif /* __ENVMAP_H__ */ diff --git a/source/blender/render/intern/include/pixelshading.h b/source/blender/render/intern/include/pixelshading.h index 30d574694b2..faf8c5f54f5 100644 --- a/source/blender/render/intern/include/pixelshading.h +++ b/source/blender/render/intern/include/pixelshading.h @@ -32,6 +32,8 @@ #ifndef __PIXELSHADING_H__ #define __PIXELSHADING_H__ +struct ImagePool; + /** * Render the pixel at (x,y) for object ap. Apply the jitter mask. * Output is given in float collector[4]. The type vector: diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 3b8cd3c6aa5..deba6d165f2 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -62,6 +62,7 @@ struct RayFace; struct RenderEngine; struct ReportList; struct Main; +struct ImagePool; #define TABLEINITSIZE 1024 @@ -264,6 +265,8 @@ struct Render RenderStats i; struct ReportList *reports; + + struct ImagePool *pool; }; /* ------------------------------------------------------------------------- */ @@ -377,6 +380,7 @@ struct halosort { /* ------------------------------------------------------------------------- */ struct Material; struct MTFace; +struct ImagePool; typedef struct RadFace { float unshot[3], totrad[3]; @@ -409,6 +413,7 @@ typedef struct HaloRen { int pixels; unsigned int lay; struct Material *mat; + struct ImagePool *pool; } HaloRen; /* ------------------------------------------------------------------------- */ diff --git a/source/blender/render/intern/include/texture.h b/source/blender/render/intern/include/texture.h index 4b9fa2d2042..2dc12f39db7 100644 --- a/source/blender/render/intern/include/texture.h +++ b/source/blender/render/intern/include/texture.h @@ -60,6 +60,7 @@ struct TexResult; struct Tex; struct Image; struct ImBuf; +struct ImagePool; /* texture.h */ @@ -76,9 +77,9 @@ void render_realtime_texture(struct ShadeInput *shi, struct Image *ima); /* imagetexture.h */ -int imagewraposa(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, const float texvec[3], const float dxt[2], const float dyt[2], struct TexResult *texres); -int imagewrap(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, const float texvec[3], struct TexResult *texres); -void image_sample(struct Image *ima, float fx, float fy, float dx, float dy, float result[4]); +int imagewraposa(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, const float texvec[3], const float dxt[2], const float dyt[2], struct TexResult *texres, struct ImagePool *pool); +int imagewrap(struct Tex *tex, struct Image *ima, struct ImBuf *ibuf, const float texvec[3], struct TexResult *texres, struct ImagePool *pool); +void image_sample(struct Image *ima, float fx, float fy, float dx, float dy, float result[4], struct ImagePool *pool); #endif /* __TEXTURE_H__ */ diff --git a/source/blender/render/intern/raytrace/rayobject_octree.cpp b/source/blender/render/intern/raytrace/rayobject_octree.cpp index 658ab9dc091..e4fd5a6d41e 100644 --- a/source/blender/render/intern/raytrace/rayobject_octree.cpp +++ b/source/blender/render/intern/raytrace/rayobject_octree.cpp @@ -667,10 +667,12 @@ static void RE_rayobject_octree_done(RayObject *tree) oc->ocface = NULL; MEM_freeN(oc->ro_nodes); oc->ro_nodes = NULL; - + +#if 0 printf("%f %f - %f\n", oc->min[0], oc->max[0], oc->ocfacx); printf("%f %f - %f\n", oc->min[1], oc->max[1], oc->ocfacy); printf("%f %f - %f\n", oc->min[2], oc->max[2], oc->ocfacz); +#endif } static void RE_rayobject_octree_bb(RayObject *tree, float *min, float *max) diff --git a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp index d03bdb74407..3e80deefecd 100644 --- a/source/blender/render/intern/raytrace/rayobject_vbvh.cpp +++ b/source/blender/render/intern/raytrace/rayobject_vbvh.cpp @@ -38,12 +38,12 @@ int tot_hints = 0; #include "MEM_guardedalloc.h" -#include "BKE_global.h" - #include "BLI_math.h" #include "BLI_memarena.h" #include "BLI_utildefines.h" +#include "BKE_global.h" + #include "rayintersection.h" #include "rayobject.h" #include "rayobject_rtbuild.h" diff --git a/source/blender/render/intern/source/bake.c b/source/blender/render/intern/source/bake.c new file mode 100644 index 00000000000..d4451d570a4 --- /dev/null +++ b/source/blender/render/intern/source/bake.c @@ -0,0 +1,1107 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * Contributors: 2004/2005/2006 Blender Foundation, full recode + * Contributors: Vertex color baking, Copyright 2011 AutoCRC + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/render/intern/source/bake.c + * \ingroup render + */ + + +/* system includes */ +#include <stdio.h> +#include <string.h> + +/* External modules: */ +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" +#include "BLI_blenlib.h" +#include "BLI_threads.h" +#include "BLI_utildefines.h" + +#include "DNA_image_types.h" +#include "DNA_material_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "BKE_customdata.h" +#include "BKE_depsgraph.h" +#include "BKE_global.h" +#include "BKE_image.h" +#include "BKE_main.h" +#include "BKE_node.h" +#include "BKE_scene.h" + +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" +#include "IMB_colormanagement.h" + +/* local include */ +#include "rayintersection.h" +#include "rayobject.h" +#include "render_types.h" +#include "renderdatabase.h" +#include "shading.h" +#include "zbuf.h" + +#include "PIL_time.h" + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ +/* only to be used here in this file, it's for speed */ +extern struct Render R; +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + + +/* ************************* bake ************************ */ + + +typedef struct BakeShade { + ShadeSample ssamp; + ObjectInstanceRen *obi; + VlakRen *vlr; + + ZSpan *zspan; + Image *ima; + ImBuf *ibuf; + + int rectx, recty, quad, type, vdone; + bool ready; + + float dir[3]; + Object *actob; + + /* Output: vertex color or image data. If vcol is not NULL, rect and + * rect_float should be NULL. */ + MPoly *mpoly; + MLoop *mloop; + MLoopCol *vcol; + + unsigned int *rect; + float *rect_float; + + /* displacement buffer used for normalization with unknown maximal distance */ + bool use_displacement_buffer; + float *displacement_buffer; + float displacement_min, displacement_max; + + bool use_mask; + char *rect_mask; /* bake pixel mask */ + + float dxco[3], dyco[3]; + + short *do_update; + + struct ColorSpace *rect_colorspace; +} BakeShade; + +static void bake_set_shade_input(ObjectInstanceRen *obi, VlakRen *vlr, ShadeInput *shi, int quad, int UNUSED(isect), int x, int y, float u, float v) +{ + if (quad) + shade_input_set_triangle_i(shi, obi, vlr, 0, 2, 3); + else + shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2); + + /* cache for shadow */ + shi->samplenr = R.shadowsamplenr[shi->thread]++; + + shi->mask = 0xFFFF; /* all samples */ + + shi->u = -u; + shi->v = -v; + shi->xs = x; + shi->ys = y; + + shade_input_set_uv(shi); + shade_input_set_normals(shi); + + /* no normal flip */ + if (shi->flippednor) + shade_input_flip_normals(shi); + + /* set up view vector to look right at the surface (note that the normal + * is negated in the renderer so it does not need to be done here) */ + shi->view[0] = shi->vn[0]; + shi->view[1] = shi->vn[1]; + shi->view[2] = shi->vn[2]; +} + +static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(quad), int x, int y, float UNUSED(u), float UNUSED(v), float *tvn, float *ttang) +{ + BakeShade *bs = handle; + ShadeSample *ssamp = &bs->ssamp; + ShadeResult shr; + VlakRen *vlr = shi->vlr; + + shade_input_init_material(shi); + + if (bs->type == RE_BAKE_AO) { + ambient_occlusion(shi); + + if (R.r.bake_flag & R_BAKE_NORMALIZE) { + copy_v3_v3(shr.combined, shi->ao); + } + else { + zero_v3(shr.combined); + environment_lighting_apply(shi, &shr); + } + } + else { + if (bs->type == RE_BAKE_SHADOW) /* Why do shadows set the color anyhow?, ignore material color for baking */ + shi->r = shi->g = shi->b = 1.0f; + + shade_input_set_shade_texco(shi); + + /* only do AO for a full bake (and obviously AO bakes) + * AO for light bakes is a leftover and might not be needed */ + if (ELEM3(bs->type, RE_BAKE_ALL, RE_BAKE_AO, RE_BAKE_LIGHT)) + shade_samples_do_AO(ssamp); + + if (shi->mat->nodetree && shi->mat->use_nodes) { + ntreeShaderExecTree(shi->mat->nodetree, shi, &shr); + shi->mat = vlr->mat; /* shi->mat is being set in nodetree */ + } + else + shade_material_loop(shi, &shr); + + if (bs->type == RE_BAKE_NORMALS) { + float nor[3]; + + copy_v3_v3(nor, shi->vn); + + if (R.r.bake_normal_space == R_BAKE_SPACE_CAMERA) { + /* pass */ + } + else if (R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) { + float mat[3][3], imat[3][3]; + + /* bitangent */ + if (tvn && ttang) { + copy_v3_v3(mat[0], ttang); + cross_v3_v3v3(mat[1], tvn, ttang); + mul_v3_fl(mat[1], ttang[3]); + copy_v3_v3(mat[2], tvn); + } + else { + copy_v3_v3(mat[0], shi->nmaptang); + cross_v3_v3v3(mat[1], shi->nmapnorm, shi->nmaptang); + mul_v3_fl(mat[1], shi->nmaptang[3]); + copy_v3_v3(mat[2], shi->nmapnorm); + } + + invert_m3_m3(imat, mat); + mul_m3_v3(imat, nor); + } + else if (R.r.bake_normal_space == R_BAKE_SPACE_OBJECT) + mul_mat3_m4_v3(ob->imat_ren, nor); /* ob->imat_ren includes viewinv! */ + else if (R.r.bake_normal_space == R_BAKE_SPACE_WORLD) + mul_mat3_m4_v3(R.viewinv, nor); + + normalize_v3(nor); /* in case object has scaling */ + + /* The invert of the red channel is to make + * the normal map compliant with the outside world. + * It needs to be done because in Blender + * the normal used in the renderer points inward. It is generated + * this way in calc_vertexnormals(). Should this ever change + * this negate must be removed. */ + shr.combined[0] = (-nor[0]) / 2.0f + 0.5f; + shr.combined[1] = nor[1] / 2.0f + 0.5f; + shr.combined[2] = nor[2] / 2.0f + 0.5f; + } + else if (bs->type == RE_BAKE_TEXTURE) { + copy_v3_v3(shr.combined, &shi->r); + shr.alpha = shi->alpha; + } + else if (bs->type == RE_BAKE_SHADOW) { + copy_v3_v3(shr.combined, shr.shad); + shr.alpha = shi->alpha; + } + else if (bs->type == RE_BAKE_SPEC_COLOR) { + copy_v3_v3(shr.combined, &shi->specr); + shr.alpha = 1.0f; + } + else if (bs->type == RE_BAKE_SPEC_INTENSITY) { + copy_v3_fl(shr.combined, shi->spec); + shr.alpha = 1.0f; + } + else if (bs->type == RE_BAKE_MIRROR_COLOR) { + copy_v3_v3(shr.combined, &shi->mirr); + shr.alpha = 1.0f; + } + else if (bs->type == RE_BAKE_MIRROR_INTENSITY) { + copy_v3_fl(shr.combined, shi->ray_mirror); + shr.alpha = 1.0f; + } + else if (bs->type == RE_BAKE_ALPHA) { + copy_v3_fl(shr.combined, shi->alpha); + shr.alpha = 1.0f; + } + else if (bs->type == RE_BAKE_EMIT) { + copy_v3_fl(shr.combined, shi->emit); + shr.alpha = 1.0f; + } + } + + if (bs->rect_float && !bs->vcol) { + float *col = bs->rect_float + 4 * (bs->rectx * y + x); + copy_v3_v3(col, shr.combined); + if (bs->type == RE_BAKE_ALL || bs->type == RE_BAKE_TEXTURE) { + col[3] = shr.alpha; + } + else { + col[3] = 1.0; + } + } + else { + /* Target is char (LDR). */ + unsigned char col[4]; + + if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) { + float rgb[3]; + + copy_v3_v3(rgb, shr.combined); + if (R.scene_color_manage) { + /* Vertex colors have no way to specify color space, so they + * default to sRGB. */ + if (!bs->vcol) + IMB_colormanagement_scene_linear_to_colorspace_v3(rgb, bs->rect_colorspace); + else + linearrgb_to_srgb_v3_v3(rgb, rgb); + } + rgb_float_to_uchar(col, rgb); + } + else { + rgb_float_to_uchar(col, shr.combined); + } + + if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) { + col[3] = FTOCHAR(shr.alpha); + } + else { + col[3] = 255; + } + + if (bs->vcol) { + /* Vertex color baking. Vcol has no useful alpha channel (it exists + * but is used only for vertex painting). */ + bs->vcol->r = col[0]; + bs->vcol->g = col[1]; + bs->vcol->b = col[2]; + } + else { + unsigned char *imcol = (unsigned char *)(bs->rect + bs->rectx * y + x); + copy_v4_v4_char((char *)imcol, (char *)col); + } + + } + + if (bs->rect_mask) { + bs->rect_mask[bs->rectx * y + x] = FILTER_MASK_USED; + } +} + +static void bake_displacement(void *handle, ShadeInput *UNUSED(shi), float dist, int x, int y) +{ + BakeShade *bs = handle; + float disp; + + if (R.r.bake_flag & R_BAKE_NORMALIZE) { + if (R.r.bake_maxdist) + disp = (dist + R.r.bake_maxdist) / (R.r.bake_maxdist * 2); /* alter the range from [-bake_maxdist, bake_maxdist] to [0, 1]*/ + else + disp = dist; + } + else { + disp = 0.5f + dist; /* alter the range from [-0.5,0.5] to [0,1]*/ + } + + if (bs->displacement_buffer) { + float *displacement = bs->displacement_buffer + (bs->rectx * y + x); + *displacement = disp; + bs->displacement_min = min_ff(bs->displacement_min, disp); + bs->displacement_max = max_ff(bs->displacement_max, disp); + } + + if (bs->rect_float && !bs->vcol) { + float *col = bs->rect_float + 4 * (bs->rectx * y + x); + col[0] = col[1] = col[2] = disp; + col[3] = 1.0f; + } + else { + /* Target is char (LDR). */ + unsigned char col[4]; + col[0] = col[1] = col[2] = FTOCHAR(disp); + col[3] = 255; + + if (bs->vcol) { + /* Vertex color baking. Vcol has no useful alpha channel (it exists + * but is used only for vertex painting). */ + bs->vcol->r = col[0]; + bs->vcol->g = col[1]; + bs->vcol->b = col[2]; + } + else { + char *imcol = (char *)(bs->rect + bs->rectx * y + x); + copy_v4_v4_char((char *)imcol, (char *)col); + } + } + if (bs->rect_mask) { + bs->rect_mask[bs->rectx * y + x] = FILTER_MASK_USED; + } +} + +static int bake_intersect_tree(RayObject *raytree, Isect *isect, float *start, float *dir, float sign, float *hitco, float *dist) +{ + float maxdist; + int hit; + + /* might be useful to make a user setting for maxsize*/ + if (R.r.bake_maxdist > 0.0f) + maxdist = R.r.bake_maxdist; + else + maxdist = RE_RAYTRACE_MAXDIST + R.r.bake_biasdist; + + /* 'dir' is always normalized */ + madd_v3_v3v3fl(isect->start, start, dir, -R.r.bake_biasdist); + + mul_v3_v3fl(isect->dir, dir, sign); + + isect->dist = maxdist; + + hit = RE_rayobject_raycast(raytree, isect); + if (hit) { + madd_v3_v3v3fl(hitco, isect->start, isect->dir, isect->dist); + + *dist = isect->dist; + } + + return hit; +} + +static void bake_set_vlr_dxyco(BakeShade *bs, float *uv1, float *uv2, float *uv3) +{ + VlakRen *vlr = bs->vlr; + float A, d1, d2, d3, *v1, *v2, *v3; + + if (bs->quad) { + v1 = vlr->v1->co; + v2 = vlr->v3->co; + v3 = vlr->v4->co; + } + else { + v1 = vlr->v1->co; + v2 = vlr->v2->co; + v3 = vlr->v3->co; + } + + /* formula derived from barycentric coordinates: + * (uvArea1*v1 + uvArea2*v2 + uvArea3*v3)/uvArea + * then taking u and v partial derivatives to get dxco and dyco */ + A = (uv2[0] - uv1[0]) * (uv3[1] - uv1[1]) - (uv3[0] - uv1[0]) * (uv2[1] - uv1[1]); + + if (fabsf(A) > FLT_EPSILON) { + A = 0.5f / A; + + d1 = uv2[1] - uv3[1]; + d2 = uv3[1] - uv1[1]; + d3 = uv1[1] - uv2[1]; + bs->dxco[0] = (v1[0] * d1 + v2[0] * d2 + v3[0] * d3) * A; + bs->dxco[1] = (v1[1] * d1 + v2[1] * d2 + v3[1] * d3) * A; + bs->dxco[2] = (v1[2] * d1 + v2[2] * d2 + v3[2] * d3) * A; + + d1 = uv3[0] - uv2[0]; + d2 = uv1[0] - uv3[0]; + d3 = uv2[0] - uv1[0]; + bs->dyco[0] = (v1[0] * d1 + v2[0] * d2 + v3[0] * d3) * A; + bs->dyco[1] = (v1[1] * d1 + v2[1] * d2 + v3[1] * d3) * A; + bs->dyco[2] = (v1[2] * d1 + v2[2] * d2 + v3[2] * d3) * A; + } + else { + bs->dxco[0] = bs->dxco[1] = bs->dxco[2] = 0.0f; + bs->dyco[0] = bs->dyco[1] = bs->dyco[2] = 0.0f; + } + + if (bs->obi->flag & R_TRANSFORMED) { + mul_m3_v3(bs->obi->nmat, bs->dxco); + mul_m3_v3(bs->obi->nmat, bs->dyco); + } +} + +static void do_bake_shade(void *handle, int x, int y, float u, float v) +{ + BakeShade *bs = handle; + VlakRen *vlr = bs->vlr; + ObjectInstanceRen *obi = bs->obi; + Object *ob = obi->obr->ob; + float l, *v1, *v2, *v3, tvn[3], ttang[4]; + int quad; + ShadeSample *ssamp = &bs->ssamp; + ShadeInput *shi = ssamp->shi; + + /* fast threadsafe break test */ + if (R.test_break(R.tbh)) + return; + + /* setup render coordinates */ + if (bs->quad) { + v1 = vlr->v1->co; + v2 = vlr->v3->co; + v3 = vlr->v4->co; + } + else { + v1 = vlr->v1->co; + v2 = vlr->v2->co; + v3 = vlr->v3->co; + } + + l = 1.0f - u - v; + + /* shrink barycentric coordinates inwards slightly to avoid some issues + * where baking selected to active might just miss the other face at the + * near the edge of a face */ + if (bs->actob) { + const float eps = 1.0f - 1e-4f; + float invsum; + + u = (u - 0.5f) * eps + 0.5f; + v = (v - 0.5f) * eps + 0.5f; + l = (l - 0.5f) * eps + 0.5f; + + invsum = 1.0f / (u + v + l); + + u *= invsum; + v *= invsum; + l *= invsum; + } + + /* renderco */ + shi->co[0] = l * v3[0] + u * v1[0] + v * v2[0]; + shi->co[1] = l * v3[1] + u * v1[1] + v * v2[1]; + shi->co[2] = l * v3[2] + u * v1[2] + v * v2[2]; + + /* avoid self shadow with vertex bake from adjacent faces [#33729] */ + if ((bs->vcol != NULL) && (bs->actob == NULL)) { + madd_v3_v3fl(shi->co, vlr->n, 0.0001f); + } + + if (obi->flag & R_TRANSFORMED) + mul_m4_v3(obi->mat, shi->co); + + copy_v3_v3(shi->dxco, bs->dxco); + copy_v3_v3(shi->dyco, bs->dyco); + + quad = bs->quad; + bake_set_shade_input(obi, vlr, shi, quad, 0, x, y, u, v); + + if (bs->type == RE_BAKE_NORMALS && R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) { + shade_input_set_shade_texco(shi); + copy_v3_v3(tvn, shi->nmapnorm); + copy_v4_v4(ttang, shi->nmaptang); + } + + /* if we are doing selected to active baking, find point on other face */ + if (bs->actob) { + Isect isec, minisec; + float co[3], minco[3], dist, mindist = 0.0f; + int hit, sign, dir = 1; + + /* intersect with ray going forward and backward*/ + hit = 0; + memset(&minisec, 0, sizeof(minisec)); + minco[0] = minco[1] = minco[2] = 0.0f; + + copy_v3_v3(bs->dir, shi->vn); + + for (sign = -1; sign <= 1; sign += 2) { + memset(&isec, 0, sizeof(isec)); + isec.mode = RE_RAY_MIRROR; + + isec.orig.ob = obi; + isec.orig.face = vlr; + isec.userdata = bs->actob; + isec.check = RE_CHECK_VLR_BAKE; + isec.skip = RE_SKIP_VLR_NEIGHBOUR; + + if (bake_intersect_tree(R.raytree, &isec, shi->co, shi->vn, sign, co, &dist)) { + if (!hit || len_squared_v3v3(shi->co, co) < len_squared_v3v3(shi->co, minco)) { + minisec = isec; + mindist = dist; + copy_v3_v3(minco, co); + hit = 1; + dir = sign; + } + } + } + + if (bs->type == RE_BAKE_DISPLACEMENT) { + if (hit) + bake_displacement(handle, shi, (dir == -1) ? mindist : -mindist, x, y); + else + bake_displacement(handle, shi, 0.0f, x, y); + return; + } + + /* if hit, we shade from the new point, otherwise from point one starting face */ + if (hit) { + obi = (ObjectInstanceRen *)minisec.hit.ob; + vlr = (VlakRen *)minisec.hit.face; + quad = (minisec.isect == 2); + copy_v3_v3(shi->co, minco); + + u = -minisec.u; + v = -minisec.v; + bake_set_shade_input(obi, vlr, shi, quad, 1, x, y, u, v); + } + } + + if (bs->type == RE_BAKE_NORMALS && R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) + bake_shade(handle, ob, shi, quad, x, y, u, v, tvn, ttang); + else + bake_shade(handle, ob, shi, quad, x, y, u, v, 0, 0); +} + +static int get_next_bake_face(BakeShade *bs) +{ + ObjectRen *obr; + VlakRen *vlr; + MTFace *tface; + static int v = 0, vdone = false; + static ObjectInstanceRen *obi = NULL; + + if (bs == NULL) { + vlr = NULL; + v = vdone = false; + obi = R.instancetable.first; + return 0; + } + + BLI_lock_thread(LOCK_CUSTOM1); + + for (; obi; obi = obi->next, v = 0) { + obr = obi->obr; + + for (; v < obr->totvlak; v++) { + vlr = RE_findOrAddVlak(obr, v); + + if ((bs->actob && bs->actob == obr->ob) || (!bs->actob && (obr->ob->flag & SELECT))) { + if (R.r.bake_flag & R_BAKE_VCOL) { + /* Gather face data for vertex color bake */ + Mesh *me; + int *origindex, vcollayer; + CustomDataLayer *cdl; + + if (obr->ob->type != OB_MESH) + continue; + me = obr->ob->data; + + origindex = RE_vlakren_get_origindex(obr, vlr, 0); + if (origindex == NULL) + continue; + if (*origindex >= me->totpoly) { + /* Small hack for Array modifier, which gives false + original indices - z0r */ + continue; + } +#if 0 + /* Only shade selected faces. */ + if ((me->mface[*origindex].flag & ME_FACE_SEL) == 0) + continue; +#endif + + vcollayer = CustomData_get_render_layer_index(&me->ldata, CD_MLOOPCOL); + if (vcollayer == -1) + continue; + + cdl = &me->ldata.layers[vcollayer]; + bs->mpoly = me->mpoly + *origindex; + bs->vcol = ((MLoopCol *)cdl->data) + bs->mpoly->loopstart; + bs->mloop = me->mloop + bs->mpoly->loopstart; + + /* Tag mesh for reevaluation. */ + DAG_id_tag_update(&me->id, 0); + } + else { + Image *ima = NULL; + ImBuf *ibuf = NULL; + const float vec_alpha[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + const float vec_solid[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + + tface = RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0); + + if (!tface || !tface->tpage) + continue; + + ima = tface->tpage; + ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); + + if (ibuf == NULL) + continue; + + if (ibuf->rect == NULL && ibuf->rect_float == NULL) { + BKE_image_release_ibuf(ima, ibuf, NULL); + continue; + } + + if (ibuf->rect_float && !(ibuf->channels == 0 || ibuf->channels == 4)) { + BKE_image_release_ibuf(ima, ibuf, NULL); + continue; + } + + if (ima->flag & IMA_USED_FOR_RENDER) { + ima->id.flag &= ~LIB_DOIT; + BKE_image_release_ibuf(ima, ibuf, NULL); + continue; + } + + /* find the image for the first time? */ + if (ima->id.flag & LIB_DOIT) { + ima->id.flag &= ~LIB_DOIT; + + /* we either fill in float or char, this ensures things go fine */ + if (ibuf->rect_float) + imb_freerectImBuf(ibuf); + /* clear image */ + if (R.r.bake_flag & R_BAKE_CLEAR) + IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid); + + /* might be read by UI to set active image for display */ + R.bakebuf = ima; + } + + /* Tag image for redraw. */ + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + BKE_image_release_ibuf(ima, ibuf, NULL); + } + + bs->obi = obi; + bs->vlr = vlr; + bs->vdone++; /* only for error message if nothing was rendered */ + v++; + BLI_unlock_thread(LOCK_CUSTOM1); + return 1; + } + } + } + + BLI_unlock_thread(LOCK_CUSTOM1); + return 0; +} + +static void bake_single_vertex(BakeShade *bs, VertRen *vert, float u, float v) +{ + int *origindex, i; + MLoopCol *basevcol; + MLoop *mloop; + + origindex = RE_vertren_get_origindex(bs->obi->obr, vert, 0); + if (!origindex || *origindex == ORIGINDEX_NONE) + return; + + /* Search for matching vertex index and apply shading. */ + for (i = 0; i < bs->mpoly->totloop; i++) { + mloop = bs->mloop + i; + if (mloop->v != *origindex) + continue; + basevcol = bs->vcol; + bs->vcol = basevcol + i; + do_bake_shade(bs, 0, 0, u, v); + bs->vcol = basevcol; + break; + } +} + +/* Bake all vertices of a face. Actually, this still works on a face-by-face + basis, and each vertex on each face is shaded. Vertex colors are a property + of loops, not vertices. */ +static void shade_verts(BakeShade *bs) +{ + VlakRen *vlr = bs->vlr; + + /* Disable baking to image; write to vcol instead. vcol pointer is set in + * bake_single_vertex. */ + bs->ima = NULL; + bs->rect = NULL; + bs->rect_float = NULL; + bs->displacement_buffer = NULL; + bs->displacement_min = FLT_MAX; + bs->displacement_max = -FLT_MAX; + + bs->quad = 0; + + /* No anti-aliasing for vertices. */ + zero_v3(bs->dxco); + zero_v3(bs->dyco); + + /* Shade each vertex of the face. u and v are barycentric coordinates; since + we're only interested in vertices, these will be 0 or 1. */ + if ((vlr->flag & R_FACE_SPLIT) == 0) { + /* Processing triangle face, whole quad, or first half of split quad. */ + + bake_single_vertex(bs, bs->vlr->v1, 1.0f, 0.0f); + bake_single_vertex(bs, bs->vlr->v2, 0.0f, 1.0f); + bake_single_vertex(bs, bs->vlr->v3, 0.0f, 0.0f); + + if (vlr->v4) { + bs->quad = 1; + bake_single_vertex(bs, bs->vlr->v4, 0.0f, 0.0f); + } + } + else { + /* Processing second half of split quad. Only one vertex to go. */ + if (vlr->flag & R_DIVIDE_24) { + bake_single_vertex(bs, bs->vlr->v2, 0.0f, 1.0f); + } + else { + bake_single_vertex(bs, bs->vlr->v3, 0.0f, 0.0f); + } + } +} + +/* already have tested for tface and ima and zspan */ +static void shade_tface(BakeShade *bs) +{ + VlakRen *vlr = bs->vlr; + ObjectInstanceRen *obi = bs->obi; + ObjectRen *obr = obi->obr; + MTFace *tface = RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0); + Image *ima = tface->tpage; + float vec[4][2]; + int a, i1, i2, i3; + + /* check valid zspan */ + if (ima != bs->ima) { + BKE_image_release_ibuf(bs->ima, bs->ibuf, NULL); + + bs->ima = ima; + bs->ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); + /* note, these calls only free/fill contents of zspan struct, not zspan itself */ + zbuf_free_span(bs->zspan); + zbuf_alloc_span(bs->zspan, bs->ibuf->x, bs->ibuf->y, R.clipcrop); + } + + bs->rectx = bs->ibuf->x; + bs->recty = bs->ibuf->y; + bs->rect = bs->ibuf->rect; + bs->rect_colorspace = bs->ibuf->rect_colorspace; + bs->rect_float = bs->ibuf->rect_float; + bs->vcol = NULL; + bs->quad = 0; + bs->rect_mask = NULL; + bs->displacement_buffer = NULL; + + if (bs->use_mask || bs->use_displacement_buffer) { + BakeImBufuserData *userdata = bs->ibuf->userdata; + if (userdata == NULL) { + BLI_lock_thread(LOCK_CUSTOM1); + userdata = bs->ibuf->userdata; + if (userdata == NULL) /* since the thread was locked, its possible another thread alloced the value */ + userdata = MEM_callocN(sizeof(BakeImBufuserData), "BakeMask"); + + if (bs->use_mask) + userdata->mask_buffer = MEM_callocN(sizeof(char) * bs->rectx * bs->recty, "BakeMask"); + + if (bs->use_displacement_buffer) + userdata->displacement_buffer = MEM_callocN(sizeof(float) * bs->rectx * bs->recty, "BakeDisp"); + + bs->ibuf->userdata = userdata; + + BLI_unlock_thread(LOCK_CUSTOM1); + } + + bs->rect_mask = userdata->mask_buffer; + bs->displacement_buffer = userdata->displacement_buffer; + } + + /* get pixel level vertex coordinates */ + for (a = 0; a < 4; a++) { + /* Note, workaround for pixel aligned UVs which are common and can screw up our intersection tests + * where a pixel gets in between 2 faces or the middle of a quad, + * camera aligned quads also have this problem but they are less common. + * Add a small offset to the UVs, fixes bug #18685 - Campbell */ + vec[a][0] = tface->uv[a][0] * (float)bs->rectx - (0.5f + 0.001f); + vec[a][1] = tface->uv[a][1] * (float)bs->recty - (0.5f + 0.002f); + } + + /* UV indices have to be corrected for possible quad->tria splits */ + i1 = 0; i2 = 1; i3 = 2; + vlr_set_uv_indices(vlr, &i1, &i2, &i3); + bake_set_vlr_dxyco(bs, vec[i1], vec[i2], vec[i3]); + zspan_scanconvert(bs->zspan, bs, vec[i1], vec[i2], vec[i3], do_bake_shade); + + if (vlr->v4) { + bs->quad = 1; + bake_set_vlr_dxyco(bs, vec[0], vec[2], vec[3]); + zspan_scanconvert(bs->zspan, bs, vec[0], vec[2], vec[3], do_bake_shade); + } +} + +static void *do_bake_thread(void *bs_v) +{ + BakeShade *bs = bs_v; + + while (get_next_bake_face(bs)) { + if (R.r.bake_flag & R_BAKE_VCOL) { + shade_verts(bs); + } + else { + shade_tface(bs); + } + + /* fast threadsafe break test */ + if (R.test_break(R.tbh)) + break; + + /* access is not threadsafe but since its just true/false probably ok + * only used for interactive baking */ + if (bs->do_update) { + *bs->do_update = true; + } + } + bs->ready = true; + + BKE_image_release_ibuf(bs->ima, bs->ibuf, NULL); + + return NULL; +} + +void RE_bake_ibuf_filter(ImBuf *ibuf, char *mask, const int filter) +{ + /* must check before filtering */ + const short is_new_alpha = (ibuf->planes != R_IMF_PLANES_RGBA) && BKE_imbuf_alpha_test(ibuf); + + /* Margin */ + if (filter) { + IMB_filter_extend(ibuf, mask, filter); + } + + /* if the bake results in new alpha then change the image setting */ + if (is_new_alpha) { + ibuf->planes = R_IMF_PLANES_RGBA; + } + else { + if (filter && ibuf->planes != R_IMF_PLANES_RGBA) { + /* clear alpha added by filtering */ + IMB_rectfill_alpha(ibuf, 1.0f); + } + } +} + +void RE_bake_ibuf_normalize_displacement(ImBuf *ibuf, float *displacement, char *mask, float displacement_min, float displacement_max) +{ + int i; + float *current_displacement = displacement; + char *current_mask = mask; + float max_distance; + + max_distance = max_ff(fabsf(displacement_min), fabsf(displacement_max)); + + for (i = 0; i < ibuf->x * ibuf->y; i++) { + if (*current_mask == FILTER_MASK_USED) { + float normalized_displacement; + + if (max_distance > 1e-5f) + normalized_displacement = (*current_displacement + max_distance) / (max_distance * 2); + else + normalized_displacement = 0.5f; + + if (ibuf->rect_float) { + /* currently baking happens to RGBA only */ + float *fp = ibuf->rect_float + i * 4; + fp[0] = fp[1] = fp[2] = normalized_displacement; + fp[3] = 1.0f; + } + + if (ibuf->rect) { + unsigned char *cp = (unsigned char *) (ibuf->rect + i); + cp[0] = cp[1] = cp[2] = FTOCHAR(normalized_displacement); + cp[3] = 255; + } + } + + current_displacement++; + current_mask++; + } +} + +/* using object selection tags, the faces with UV maps get baked */ +/* render should have been setup */ +/* returns 0 if nothing was handled */ +int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_update, float *progress) +{ + BakeShade *handles; + ListBase threads; + Image *ima; + int a, vdone = false, result = BAKE_RESULT_OK; + bool use_mask = false; + bool use_displacement_buffer = false; + + re->scene_color_manage = BKE_scene_check_color_management_enabled(re->scene); + + /* initialize render global */ + R = *re; + R.bakebuf = NULL; + + /* initialize static vars */ + get_next_bake_face(NULL); + + /* do we need a mask? */ + if (re->r.bake_filter) + use_mask = true; + + /* do we need buffer to store displacements */ + if (type == RE_BAKE_DISPLACEMENT) { + if ((R.r.bake_flag & R_BAKE_NORMALIZE) && R.r.bake_maxdist == 0.0f) { + use_displacement_buffer = true; + use_mask = true; + } + } + + /* baker uses this flag to detect if image was initialized */ + if ((R.r.bake_flag & R_BAKE_VCOL) == 0) { + for (ima = G.main->image.first; ima; ima = ima->id.next) { + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); + ima->id.flag |= LIB_DOIT; + ima->flag &= ~IMA_USED_FOR_RENDER; + if (ibuf) { + ibuf->userdata = NULL; /* use for masking if needed */ + } + BKE_image_release_ibuf(ima, ibuf, NULL); + } + } + + BLI_init_threads(&threads, do_bake_thread, re->r.threads); + + handles = MEM_callocN(sizeof(BakeShade) * re->r.threads, "BakeShade"); + + /* get the threads running */ + for (a = 0; a < re->r.threads; a++) { + /* set defaults in handles */ + handles[a].ssamp.shi[0].lay = re->lay; + + if (type == RE_BAKE_SHADOW) { + handles[a].ssamp.shi[0].passflag = SCE_PASS_SHADOW; + } + else { + handles[a].ssamp.shi[0].passflag = SCE_PASS_COMBINED; + } + handles[a].ssamp.shi[0].combinedflag = ~(SCE_PASS_SPEC); + handles[a].ssamp.shi[0].thread = a; + handles[a].ssamp.tot = 1; + + handles[a].type = type; + handles[a].actob = actob; + if (R.r.bake_flag & R_BAKE_VCOL) + handles[a].zspan = NULL; + else + handles[a].zspan = MEM_callocN(sizeof(ZSpan), "zspan for bake"); + + handles[a].use_mask = use_mask; + handles[a].use_displacement_buffer = use_displacement_buffer; + + handles[a].do_update = do_update; /* use to tell the view to update */ + + handles[a].displacement_min = FLT_MAX; + handles[a].displacement_max = -FLT_MAX; + + BLI_insert_thread(&threads, &handles[a]); + } + + /* wait for everything to be done */ + a = 0; + while (a != re->r.threads) { + PIL_sleep_ms(50); + + /* calculate progress */ + for (vdone = false, a = 0; a < re->r.threads; a++) + vdone += handles[a].vdone; + if (progress) + *progress = (float)(vdone / (float)re->totvlak); + + for (a = 0; a < re->r.threads; a++) { + if (handles[a].ready == false) { + break; + } + } + } + + /* filter and refresh images */ + if ((R.r.bake_flag & R_BAKE_VCOL) == 0) { + float displacement_min = FLT_MAX, displacement_max = -FLT_MAX; + + if (use_displacement_buffer) { + for (a = 0; a < re->r.threads; a++) { + displacement_min = min_ff(displacement_min, handles[a].displacement_min); + displacement_max = max_ff(displacement_max, handles[a].displacement_max); + } + } + + for (ima = G.main->image.first; ima; ima = ima->id.next) { + if ((ima->id.flag & LIB_DOIT) == 0) { + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); + BakeImBufuserData *userdata; + + if (ima->flag & IMA_USED_FOR_RENDER) + result = BAKE_RESULT_FEEDBACK_LOOP; + + if (!ibuf) + continue; + + userdata = (BakeImBufuserData *) ibuf->userdata; + RE_bake_ibuf_filter(ibuf, userdata->mask_buffer, re->r.bake_filter); + + if (use_displacement_buffer) { + RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer, + displacement_min, displacement_max); + } + + ibuf->userflags |= IB_BITMAPDIRTY; + BKE_image_release_ibuf(ima, ibuf, NULL); + } + } + + /* calculate return value */ + for (a = 0; a < re->r.threads; a++) { + zbuf_free_span(handles[a].zspan); + MEM_freeN(handles[a].zspan); + } + } + + MEM_freeN(handles); + + BLI_end_threads(&threads); + + if (vdone == 0) { + result = BAKE_RESULT_NO_OBJECTS; + } + + return result; +} + +struct Image *RE_bake_shade_get_image(void) +{ + return R.bakebuf; +} + diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 74aab678ea8..9e9dff63c04 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -153,6 +153,7 @@ static HaloRen *initstar(Render *re, ObjectRen *obr, const float vec[3], float h har->hasize= hasize; har->zd= 0.0; + har->pool = re->pool; return har; } @@ -4853,7 +4854,7 @@ static int allow_render_dupli_instance(Render *UNUSED(re), DupliObject *dob, Obj if (totmaterial) { for (a= 0; a<*totmaterial; a++) { - ma= give_current_material(obd, a); + ma= give_current_material(obd, a + 1); if (ma && (ma->material_type == MA_TYPE_HALO)) return 0; } @@ -5165,8 +5166,8 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l * following calls don't depend on 'RE_SetCamera' */ RE_SetCamera(re, camera); - normalize_m4(camera->obmat); - invert_m4_m4(mat, camera->obmat); + normalize_m4_m4(mat, camera->obmat); + invert_m4(mat); RE_SetView(re, mat); camera->recalc= OB_RECALC_OB; /* force correct matrix for scaled cameras */ } @@ -5315,8 +5316,8 @@ static void database_fromscene_vectors(Render *re, Scene *scene, unsigned int la /* if no camera, viewmat should have been set! */ if (camera) { - normalize_m4(camera->obmat); - invert_m4_m4(mat, camera->obmat); + normalize_m4_m4(mat, camera->obmat); + invert_m4(mat); RE_SetView(re, mat); } @@ -5855,8 +5856,8 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay, /* if no camera, set unit */ if (camera) { - normalize_m4(camera->obmat); - invert_m4_m4(mat, camera->obmat); + normalize_m4_m4(mat, camera->obmat); + invert_m4(mat); RE_SetView(re, mat); } else { diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c index be8b7f6c357..9adae6f49ba 100644 --- a/source/blender/render/intern/source/envmap.c +++ b/source/blender/render/intern/source/envmap.c @@ -668,7 +668,7 @@ static void set_dxtdyt(float r_dxt[3], float r_dyt[3], const float dxt[3], const /* ------------------------------------------------------------------------- */ -int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres) +int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, struct ImagePool *pool) { extern Render R; /* only in this call */ /* texvec should be the already reflected normal */ @@ -687,12 +687,12 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o env->ima = tex->ima; if (env->ima && env->ima->ok) { if (env->cube[1] == NULL) { - ImBuf *ibuf_ima = BKE_image_acquire_ibuf(env->ima, NULL, NULL); + ImBuf *ibuf_ima = BKE_image_pool_acquire_ibuf(env->ima, NULL, pool); if (ibuf_ima) envmap_split_ima(env, ibuf_ima); else env->ok = 0; - BKE_image_release_ibuf(env->ima, ibuf_ima, NULL); + BKE_image_pool_release_ibuf(env->ima, ibuf_ima, pool); } } } @@ -720,7 +720,7 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o mul_mat3_m4_v3(R.viewinv, dyt); } set_dxtdyt(dxts, dyts, dxt, dyt, face); - imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, texres); + imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, texres, pool); /* edges? */ @@ -737,7 +737,7 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o if (face != face1) { ibuf = env->cube[face1]; set_dxtdyt(dxts, dyts, dxt, dyt, face1); - imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr1); + imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr1, pool); } else texr1.tr = texr1.tg = texr1.tb = texr1.ta = 0.0; @@ -750,7 +750,7 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o if (face != face1) { ibuf = env->cube[face1]; set_dxtdyt(dxts, dyts, dxt, dyt, face1); - imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr2); + imagewraposa(tex, NULL, ibuf, sco, dxts, dyts, &texr2, pool); } else texr2.tr = texr2.tg = texr2.tb = texr2.ta = 0.0; @@ -766,7 +766,7 @@ int envmaptex(Tex *tex, const float texvec[3], float dxt[3], float dyt[3], int o } } else { - imagewrap(tex, NULL, ibuf, sco, texres); + imagewrap(tex, NULL, ibuf, sco, texres, pool); } return 1; diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index 296c8b6eba8..22a49bcbbc3 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -1,4 +1,5 @@ /* + * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or @@ -128,9 +129,20 @@ int RE_engine_is_external(Render *re) RenderEngine *RE_engine_create(RenderEngineType *type) { + return RE_engine_create_ex(type, FALSE); +} + +RenderEngine *RE_engine_create_ex(RenderEngineType *type, int use_for_viewport) +{ RenderEngine *engine = MEM_callocN(sizeof(RenderEngine), "RenderEngine"); engine->type = type; + if (use_for_viewport) { + engine->flag |= RE_ENGINE_USED_FOR_VIEWPORT; + + BLI_begin_threaded_malloc(); + } + return engine; } @@ -142,6 +154,10 @@ void RE_engine_free(RenderEngine *engine) } #endif + if (engine->flag & RE_ENGINE_USED_FOR_VIEWPORT) { + BLI_end_threaded_malloc(); + } + if (engine->text) MEM_freeN(engine->text); diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c index 4aaa6247478..0a427d57ebc 100644 --- a/source/blender/render/intern/source/imagetexture.c +++ b/source/blender/render/intern/source/imagetexture.c @@ -110,7 +110,7 @@ static void ibuf_get_color(float col[4], struct ImBuf *ibuf, int x, int y) } } -int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResult *texres) +int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResult *texres, struct ImagePool *pool) { float fx, fy, val1, val2, val3; int x, y, retval; @@ -130,13 +130,13 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul if (ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD)) return retval; - ibuf= BKE_image_acquire_ibuf(ima, &tex->iuser, NULL); + ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool); ima->flag|= IMA_USED_FOR_RENDER; } if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) { if (ima) - BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_pool_release_ibuf(ima, ibuf, pool); return retval; } @@ -164,14 +164,14 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul } else { if (ima) - BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_pool_release_ibuf(ima, ibuf, pool); return retval; } } if ( (tex->flag & TEX_CHECKER_EVEN)==0) { if ((xs+ys) & 1) { if (ima) - BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_pool_release_ibuf(ima, ibuf, pool); return retval; } } @@ -188,14 +188,14 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul if (tex->extend == TEX_CLIPCUBE) { if (x<0 || y<0 || x>=ibuf->x || y>=ibuf->y || texvec[2]<-1.0f || texvec[2]>1.0f) { if (ima) - BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_pool_release_ibuf(ima, ibuf, pool); return retval; } } else if ( tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) { if (x<0 || y<0 || x>=ibuf->x || y>=ibuf->y) { if (ima) - BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_pool_release_ibuf(ima, ibuf, pool); return retval; } } @@ -302,10 +302,10 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul texres->tg*= fx; texres->tb*= fx; } - + if (ima) - BKE_image_release_ibuf(ima, ibuf, NULL); - + BKE_image_pool_release_ibuf(ima, ibuf, pool); + BRICONTRGB; return retval; @@ -1045,7 +1045,7 @@ static void image_mipmap_test(Tex *tex, ImBuf *ibuf) } -static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], float dxt[2], float dyt[2], TexResult *texres) +static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], float dxt[2], float dyt[2], TexResult *texres, struct ImagePool *pool) { TexResult texr; float fx, fy, minx, maxx, miny, maxy; @@ -1076,12 +1076,12 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex if (ima) { /* hack for icon render */ if ((ima->ibufs.first == NULL) && (R.r.scemode & R_NO_IMAGE_LOAD)) return retval; - ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL); + ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool); } if ((ibuf == NULL) || ((ibuf->rect == NULL) && (ibuf->rect_float == NULL))) { if (ima) - BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_pool_release_ibuf(ima, ibuf, pool); return retval; } @@ -1199,12 +1199,12 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex else { if ((tex->flag & TEX_CHECKER_ODD) == 0 && ((xs + ys) & 1) == 0) { if (ima) - BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_pool_release_ibuf(ima, ibuf, pool); return retval; } if ((tex->flag & TEX_CHECKER_EVEN) == 0 && (xs + ys) & 1) { if (ima) - BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_pool_release_ibuf(ima, ibuf, pool); return retval; } fx -= xs; @@ -1224,14 +1224,14 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex if (tex->extend == TEX_CLIPCUBE) { if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f || texvec[2] < -1.f || texvec[2] > 1.f) { if (ima) - BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_pool_release_ibuf(ima, ibuf, pool); return retval; } } else if (tex->extend == TEX_CLIP || tex->extend == TEX_CHECKER) { if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f) { if (ima) - BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_pool_release_ibuf(ima, ibuf, pool); return retval; } } @@ -1455,7 +1455,7 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex } if (ima) - BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_pool_release_ibuf(ima, ibuf, pool); BRICONTRGB; @@ -1463,7 +1463,7 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex } -int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const float DXT[2], const float DYT[2], TexResult *texres) +int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const float DXT[2], const float DYT[2], TexResult *texres, struct ImagePool *pool) { TexResult texr; float fx, fy, minx, maxx, miny, maxy, dx, dy, dxt[2], dyt[2]; @@ -1477,7 +1477,7 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const /* anisotropic filtering */ if (tex->texfilter != TXF_BOX) - return imagewraposa_aniso(tex, ima, ibuf, texvec, dxt, dyt, texres); + return imagewraposa_aniso(tex, ima, ibuf, texvec, dxt, dyt, texres, pool); texres->tin= texres->ta= texres->tr= texres->tg= texres->tb= 0.0f; @@ -1493,13 +1493,13 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const if (ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD)) return retval; - ibuf= BKE_image_acquire_ibuf(ima, &tex->iuser, NULL); + ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool); ima->flag|= IMA_USED_FOR_RENDER; } if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) { if (ima) - BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_pool_release_ibuf(ima, ibuf, pool); return retval; } @@ -1608,14 +1608,14 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const } else { if (ima) - BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_pool_release_ibuf(ima, ibuf, pool); return retval; } } if ( (tex->flag & TEX_CHECKER_EVEN)==0) { if ((xs + ys) & 1) { if (ima) - BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_pool_release_ibuf(ima, ibuf, pool); return retval; } } @@ -1652,14 +1652,14 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const if (tex->extend == TEX_CLIPCUBE) { if (fx+minx<0.0f || fy+miny<0.0f || fx-minx>1.0f || fy-miny>1.0f || texvec[2]<-1.0f || texvec[2]>1.0f) { if (ima) - BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_pool_release_ibuf(ima, ibuf, pool); return retval; } } else if (tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) { if (fx+minx<0.0f || fy+miny<0.0f || fx-minx>1.0f || fy-miny>1.0f) { if (ima) - BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_pool_release_ibuf(ima, ibuf, pool); return retval; } } @@ -1855,17 +1855,17 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const } if (ima) - BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_pool_release_ibuf(ima, ibuf, pool); BRICONTRGB; return retval; } -void image_sample(Image *ima, float fx, float fy, float dx, float dy, float result[4]) +void image_sample(Image *ima, float fx, float fy, float dx, float dy, float result[4], struct ImagePool *pool) { TexResult texres; - ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL); + ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, NULL, pool); if (UNLIKELY(ibuf == NULL)) { zero_v4(result); @@ -1884,7 +1884,7 @@ void image_sample(Image *ima, float fx, float fy, float dx, float dy, float resu ima->flag|= IMA_USED_FOR_RENDER; - BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_pool_release_ibuf(ima, ibuf, pool); } void ibuf_sample(ImBuf *ibuf, float fx, float fy, float dx, float dy, float result[4]) diff --git a/source/blender/render/intern/source/multires_bake.c b/source/blender/render/intern/source/multires_bake.c index 091ba9589d7..89f67335c39 100644 --- a/source/blender/render/intern/source/multires_bake.c +++ b/source/blender/render/intern/source/multires_bake.c @@ -60,14 +60,17 @@ #include "rayobject.h" #include "rendercore.h" -typedef void (*MPassKnownData)(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data, - ImBuf *ibuf, const int face_index, const int lvl, const float st[2], - float tangmat[3][3], const int x, const int y); +typedef void (*MPassKnownData)(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void *thread_data, + void *bake_data, ImBuf *ibuf, const int face_index, const int lvl, + const float st[2], float tangmat[3][3], const int x, const int y); typedef void * (*MInitBakeData)(MultiresBakeRender *bkr, Image *ima); -typedef void (*MApplyBakeData)(void *bake_data); typedef void (*MFreeBakeData)(void *bake_data); +typedef struct MultiresBakeResult { + float height_min, height_max; +} MultiresBakeResult; + typedef struct { MVert *mvert; MFace *mface; @@ -79,6 +82,7 @@ typedef struct { int i0, i1, i2; DerivedMesh *lores_dm, *hires_dm; int lvl; + void *thread_data; void *bake_data; ImBuf *ibuf; MPassKnownData pass_data; @@ -95,7 +99,6 @@ typedef struct { typedef struct { float *heights; - float height_min, height_max; Image *ima; DerivedMesh *ssdm; const int *orig_index_mf_to_mpoly; @@ -161,9 +164,11 @@ static void multiresbake_get_normal(const MResolvePixelData *data, float norm[], static void init_bake_rast(MBakeRast *bake_rast, const ImBuf *ibuf, const MResolvePixelData *data, MFlushPixel flush_pixel) { + BakeImBufuserData *userdata = (BakeImBufuserData *) ibuf->userdata; + memset(bake_rast, 0, sizeof(MBakeRast)); - bake_rast->texels = ibuf->userdata; + bake_rast->texels = userdata->mask_buffer; bake_rast->w = ibuf->x; bake_rast->h = ibuf->y; bake_rast->data = data; @@ -222,7 +227,7 @@ static void flush_pixel(const MResolvePixelData *data, const int x, const int y) zero_m3(to_tang); } - data->pass_data(data->lores_dm, data->hires_dm, data->bake_data, + data->pass_data(data->lores_dm, data->hires_dm, data->thread_data, data->bake_data, data->ibuf, data->face_index, data->lvl, st, to_tang, x, y); } @@ -348,6 +353,9 @@ typedef struct MultiresBakeThread { /* thread-specific data */ MBakeRast bake_rast; MResolvePixelData data; + + /* displacement-specific data */ + float height_min, height_max; } MultiresBakeThread; static int multires_bake_queue_next_face(MultiresBakeQueue *queue) @@ -428,8 +436,29 @@ static void *do_multires_bake_thread(void *data_v) return NULL; } +/* some of arrays inside ccgdm are lazy-initialized, which will generally + * require lock around accessing such data + * this function will ensure all arrays are allocated before threading started + */ +static void init_ccgdm_arrays(DerivedMesh *dm) +{ + CCGElem **grid_data; + CCGKey key; + int grid_size; + int *grid_offset; + + grid_size = dm->getGridSize(dm); + grid_data = dm->getGridData(dm); + grid_offset = dm->getGridOffset(dm); + dm->getGridKey(dm, &key); + + (void) grid_size; + (void) grid_data; + (void) grid_offset; +} + static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, int require_tangent, MPassKnownData passKnownData, - MInitBakeData initBakeData, MApplyBakeData applyBakeData, MFreeBakeData freeBakeData) + MInitBakeData initBakeData, MFreeBakeData freeBakeData, MultiresBakeResult *result) { DerivedMesh *dm = bkr->lores_dm; const int lvl = bkr->lvl; @@ -467,6 +496,8 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, int require_ta handles = MEM_callocN(tot_thread * sizeof(MultiresBakeThread), "do_multires_bake handles"); + init_ccgdm_arrays(bkr->hires_dm); + /* faces queue */ queue.cur_face = 0; queue.tot_face = tot_face; @@ -491,9 +522,13 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, int require_ta handle->data.hires_dm = bkr->hires_dm; handle->data.lvl = lvl; handle->data.pass_data = passKnownData; + handle->data.thread_data = handle; handle->data.bake_data = bake_data; handle->data.ibuf = ibuf; + handle->height_min = FLT_MAX; + handle->height_max = -FLT_MAX; + init_bake_rast(&handle->bake_rast, ibuf, &handle->data, flush_pixel); if (tot_thread > 1) @@ -506,15 +541,23 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, int require_ta else do_multires_bake_thread(&handles[0]); + /* construct bake result */ + result->height_min = handles[0].height_min; + result->height_max = handles[0].height_max; + + for (i = 1; i < tot_thread; i++) { + result->height_min = min_ff(result->height_min, handles[i].height_min); + result->height_max = max_ff(result->height_max, handles[i].height_max); + } + BLI_spin_end(&queue.spin); /* finalize baking */ - if (applyBakeData) - applyBakeData(bake_data); - if (freeBakeData) freeBakeData(bake_data); + MEM_freeN(handles); + BKE_image_release_ibuf(ima, ibuf, NULL); } } @@ -651,13 +694,15 @@ static void *init_heights_data(MultiresBakeRender *bkr, Image *ima) MHeightBakeData *height_data; ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); DerivedMesh *lodm = bkr->lores_dm; + BakeImBufuserData *userdata = ibuf->userdata; + + if (userdata->displacement_buffer == NULL) + userdata->displacement_buffer = MEM_callocN(sizeof(float) * ibuf->x * ibuf->y, "MultiresBake heights"); height_data = MEM_callocN(sizeof(MHeightBakeData), "MultiresBake heightData"); height_data->ima = ima; - height_data->heights = MEM_callocN(sizeof(float) * ibuf->x * ibuf->y, "MultiresBake heights"); - height_data->height_max = -FLT_MAX; - height_data->height_min = FLT_MAX; + height_data->heights = userdata->displacement_buffer; if (!bkr->use_lores_mesh) { SubsurfModifierData smd = {{NULL}}; @@ -673,6 +718,7 @@ static void *init_heights_data(MultiresBakeRender *bkr, Image *ima) smd.subdivType = ME_SIMPLE_SUBSURF; height_data->ssdm = subsurf_make_derived_from_derived(bkr->lores_dm, &smd, NULL, 0); + init_ccgdm_arrays(height_data->ssdm); } } @@ -684,48 +730,6 @@ static void *init_heights_data(MultiresBakeRender *bkr, Image *ima) return (void *)height_data; } -static void apply_heights_data(void *bake_data) -{ - MHeightBakeData *height_data = (MHeightBakeData *)bake_data; - ImBuf *ibuf = BKE_image_acquire_ibuf(height_data->ima, NULL, NULL); - int x, y, i; - float height, *heights = height_data->heights; - float min = height_data->height_min, max = height_data->height_max; - - for (x = 0; x < ibuf->x; x++) { - for (y = 0; y < ibuf->y; y++) { - i = ibuf->x * y + x; - - if (((char *)ibuf->userdata)[i] != FILTER_MASK_USED) - continue; - - if (ibuf->rect_float) { - float *rrgbf = ibuf->rect_float + i * 4; - - if (max - min > 1e-5f) height = (heights[i] - min) / (max - min); - else height = 0; - - rrgbf[0] = rrgbf[1] = rrgbf[2] = height; - } - else { - char *rrgb = (char *)ibuf->rect + i * 4; - - if (max - min > 1e-5f) height = (heights[i] - min) / (max - min); - else height = 0; - - rrgb[0] = rrgb[1] = rrgb[2] = FTOCHAR(height); - } - } - } - - if (ibuf->rect_float) - ibuf->userflags |= IB_RECT_INVALID; - - ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; - - BKE_image_release_ibuf(height_data->ima, ibuf, NULL); -} - static void free_heights_data(void *bake_data) { MHeightBakeData *height_data = (MHeightBakeData *)bake_data; @@ -733,7 +737,6 @@ static void free_heights_data(void *bake_data) if (height_data->ssdm) height_data->ssdm->release(height_data->ssdm); - MEM_freeN(height_data->heights); MEM_freeN(height_data); } @@ -743,13 +746,14 @@ static void free_heights_data(void *bake_data) * - find coord of point and normal with specified UV in lo-res mesh (or subdivided lo-res * mesh to make texture smoother) let's call this point p0 and n. * - height wound be dot(n, p1-p0) */ -static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data, +static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void *thread_data_v, void *bake_data, ImBuf *ibuf, const int face_index, const int lvl, const float st[2], float UNUSED(tangmat[3][3]), const int x, const int y) { MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE); MFace mface; MHeightBakeData *height_data = (MHeightBakeData *)bake_data; + MultiresBakeThread *thread_data = (MultiresBakeThread *) thread_data_v; float uv[2], *st0, *st1, *st2, *st3; int pixel = ibuf->x * y + x; float vec[3], p0[3], p1[3], n[3], len; @@ -771,12 +775,12 @@ static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, CLAMP(uv[1], 0.0f, 1.0f); get_ccgdm_data(lores_dm, hires_dm, - height_data->orig_index_mf_to_mpoly, height_data->orig_index_mf_to_mpoly, + height_data->orig_index_mf_to_mpoly, height_data->orig_index_mp_to_orig, lvl, face_index, uv[0], uv[1], p1, 0); if (height_data->ssdm) { get_ccgdm_data(lores_dm, height_data->ssdm, - height_data->orig_index_mf_to_mpoly, height_data->orig_index_mf_to_mpoly, + height_data->orig_index_mf_to_mpoly, height_data->orig_index_mp_to_orig, 0, face_index, uv[0], uv[1], p0, n); } else { @@ -796,15 +800,18 @@ static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, len = dot_v3v3(n, vec); height_data->heights[pixel] = len; - if (len < height_data->height_min) height_data->height_min = len; - if (len > height_data->height_max) height_data->height_max = len; + + thread_data->height_min = min_ff(thread_data->height_min, len); + thread_data->height_max = max_ff(thread_data->height_max, len); if (ibuf->rect_float) { float *rrgbf = ibuf->rect_float + pixel * 4; + rrgbf[0] = rrgbf[1] = rrgbf[2] = len; rrgbf[3] = 1.0f; } else { char *rrgb = (char *)ibuf->rect + pixel * 4; + rrgb[0] = rrgb[1] = rrgb[2] = FTOCHAR(len); rrgb[3] = 255; } } @@ -836,9 +843,9 @@ static void free_normal_data(void *bake_data) * - find coord and normal of point with specified UV in hi-res mesh * - multiply it by tangmat * - vector in color space would be norm(vec) /2 + (0.5, 0.5, 0.5) */ -static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data, - ImBuf *ibuf, const int face_index, const int lvl, const float st[2], - float tangmat[3][3], const int x, const int y) +static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void *UNUSED(thread_data), + void *bake_data, ImBuf *ibuf, const int face_index, const int lvl, + const float st[2], float tangmat[3][3], const int x, const int y) { MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE); MFace mface; @@ -1073,9 +1080,9 @@ static int trace_ao_ray(MAOBakeData *ao_data, float ray_start[3], float ray_dire return RE_rayobject_raycast(ao_data->raytree, &isect); } -static void apply_ao_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data, - ImBuf *ibuf, const int face_index, const int lvl, const float st[2], - float UNUSED(tangmat[3][3]), const int x, const int y) +static void apply_ao_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void *UNUSED(thread_data), + void *bake_data, ImBuf *ibuf, const int face_index, const int lvl, + const float st[2], float UNUSED(tangmat[3][3]), const int x, const int y) { MAOBakeData *ao_data = (MAOBakeData *) bake_data; MTFace *mtface = CustomData_get_layer(&lores_dm->faceData, CD_MTFACE); @@ -1205,7 +1212,7 @@ static void count_images(MultiresBakeRender *bkr) mtface[a].tpage->id.flag &= ~LIB_DOIT; } -static void bake_images(MultiresBakeRender *bkr) +static void bake_images(MultiresBakeRender *bkr, MultiresBakeResult *result) { LinkData *link; @@ -1214,18 +1221,19 @@ static void bake_images(MultiresBakeRender *bkr) ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (ibuf->x > 0 && ibuf->y > 0) { - ibuf->userdata = MEM_callocN(ibuf->y * ibuf->x, "MultiresBake imbuf mask"); + BakeImBufuserData *userdata = MEM_callocN(sizeof(BakeImBufuserData), "MultiresBake userdata"); + userdata->mask_buffer = MEM_callocN(ibuf->y * ibuf->x, "MultiresBake imbuf mask"); + ibuf->userdata = userdata; switch (bkr->mode) { case RE_BAKE_NORMALS: - do_multires_bake(bkr, ima, TRUE, apply_tangmat_callback, init_normal_data, NULL, free_normal_data); + do_multires_bake(bkr, ima, TRUE, apply_tangmat_callback, init_normal_data, free_normal_data, result); break; case RE_BAKE_DISPLACEMENT: - do_multires_bake(bkr, ima, FALSE, apply_heights_callback, init_heights_data, - apply_heights_data, free_heights_data); + do_multires_bake(bkr, ima, FALSE, apply_heights_callback, init_heights_data, free_heights_data, result); break; case RE_BAKE_AO: - do_multires_bake(bkr, ima, FALSE, apply_ao_callback, init_ao_data, NULL, free_ao_data); + do_multires_bake(bkr, ima, FALSE, apply_ao_callback, init_ao_data, free_ao_data, result); break; } } @@ -1236,18 +1244,25 @@ static void bake_images(MultiresBakeRender *bkr) } } -static void finish_images(MultiresBakeRender *bkr) +static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result) { LinkData *link; + int use_displacement_buffer = bkr->mode == RE_BAKE_DISPLACEMENT; for (link = bkr->image.first; link; link = link->next) { Image *ima = (Image *)link->data; ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); + BakeImBufuserData *userdata = (BakeImBufuserData *) ibuf->userdata; if (ibuf->x <= 0 || ibuf->y <= 0) continue; - RE_bake_ibuf_filter(ibuf, (char *)ibuf->userdata, bkr->bake_filter); + RE_bake_ibuf_filter(ibuf, userdata->mask_buffer, bkr->bake_filter); + + if (use_displacement_buffer) { + RE_bake_ibuf_normalize_displacement(ibuf, userdata->displacement_buffer, userdata->mask_buffer, + result->height_min, result->height_max); + } ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID; @@ -1260,7 +1275,11 @@ static void finish_images(MultiresBakeRender *bkr) } if (ibuf->userdata) { - MEM_freeN(ibuf->userdata); + if (userdata->displacement_buffer) + MEM_freeN(userdata->displacement_buffer); + + MEM_freeN(userdata->mask_buffer); + MEM_freeN(userdata); ibuf->userdata = NULL; } @@ -1270,7 +1289,9 @@ static void finish_images(MultiresBakeRender *bkr) void RE_multires_bake_images(MultiresBakeRender *bkr) { + MultiresBakeResult result; + count_images(bkr); - bake_images(bkr); - finish_images(bkr); + bake_images(bkr, &result); + finish_images(bkr, &result); } diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index e37b24b13a4..866932632c2 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -474,7 +474,7 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, SceneRenderLayer * re->recty = winy; } - if (re->rectx < 2 || re->recty < 2 || (BKE_imtype_is_movie(rd->im_format.imtype) && + if (re->rectx < 1 || re->recty < 1 || (BKE_imtype_is_movie(rd->im_format.imtype) && (re->rectx < 16 || re->recty < 16) )) { BKE_report(re->reports, RPT_ERROR, "Image too small"); @@ -1879,6 +1879,8 @@ static void do_render_all_options(Render *re) /* ensure no images are in memory from previous animated sequences */ BKE_image_all_free_anim_ibufs(re->r.cfra); + re->pool = BKE_image_pool_new(); + if (RE_engine_render(re, 1)) { /* in this case external render overrides all */ } @@ -1903,6 +1905,9 @@ static void do_render_all_options(Render *re) renderresult_stampinfo(re); re->display_draw(re->ddh, re->result, NULL); } + + BKE_image_pool_free(re->pool); + re->pool = NULL; } static int check_valid_camera(Scene *scene, Object *camera_override) @@ -2488,6 +2493,8 @@ void RE_PreviewRender(Render *re, Main *bmain, Scene *sce) RE_InitState(re, NULL, &sce->r, NULL, winx, winy, NULL); + re->pool = BKE_image_pool_new(); + re->main = bmain; re->scene = sce; re->scene_color_manage = BKE_scene_check_color_management_enabled(sce); @@ -2497,6 +2504,9 @@ void RE_PreviewRender(Render *re, Main *bmain, Scene *sce) RE_SetCamera(re, camera); do_render_3d(re); + + BKE_image_pool_free(re->pool); + re->pool = NULL; } /* note; repeated win/disprect calc... solve that nicer, also in compo */ diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index e3bfd535f11..3ea94981cac 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -1099,7 +1099,7 @@ static void do_2d_mapping(MTex *mtex, float texvec[3], VlakRen *vlr, const float /* ************************************** */ -static int multitex(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, const short thread, short which_output) +static int multitex(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, const short thread, short which_output, struct ImagePool *pool) { float tmpvec[3]; int retval = 0; /* return value, int:0, col:1, nor:2, everything:3 */ @@ -1137,12 +1137,12 @@ static int multitex(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int o retval = texnoise(tex, texres); break; case TEX_IMAGE: - if (osatex) retval = imagewraposa(tex, tex->ima, NULL, texvec, dxt, dyt, texres); - else retval = imagewrap(tex, tex->ima, NULL, texvec, texres); + if (osatex) retval = imagewraposa(tex, tex->ima, NULL, texvec, dxt, dyt, texres, pool); + else retval = imagewrap(tex, tex->ima, NULL, texvec, texres, pool); BKE_image_tag_time(tex->ima); /* tag image as having being used */ break; case TEX_ENVMAP: - retval = envmaptex(tex, texvec, dxt, dyt, osatex, texres); + retval = envmaptex(tex, texvec, dxt, dyt, osatex, texres, pool); break; case TEX_MUSGRAVE: /* newnoise: musgrave types */ @@ -1214,7 +1214,7 @@ static int multitex(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int o /* this is called from the shader and texture nodes */ int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, - const short thread, short which_output, ShadeInput *shi, MTex *mtex) + const short thread, short which_output, ShadeInput *shi, MTex *mtex, struct ImagePool *pool) { if (tex==NULL) { memset(texres, 0, sizeof(TexResult)); @@ -1230,16 +1230,16 @@ int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int os if (mtex) { /* we have mtex, use it for 2d mapping images only */ do_2d_mapping(mtex, texvec, shi->vlr, shi->facenor, dxt, dyt); - rgbnor = multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output); + rgbnor = multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output, pool); if (mtex->mapto & (MAP_COL+MAP_COLSPEC+MAP_COLMIR)) { - ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); + ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool); /* don't linearize float buffers, assumed to be linear */ if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) IMB_colormanagement_colorspace_to_scene_linear_v3(&texres->tr, ibuf->rect_colorspace); - BKE_image_release_ibuf(tex->ima, ibuf, NULL); + BKE_image_pool_release_ibuf(tex->ima, ibuf, pool); } } else { @@ -1263,28 +1263,28 @@ int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int os } do_2d_mapping(&localmtex, texvec_l, NULL, NULL, dxt_l, dyt_l); - rgbnor= multitex(tex, texvec_l, dxt_l, dyt_l, osatex, texres, thread, which_output); + rgbnor = multitex(tex, texvec_l, dxt_l, dyt_l, osatex, texres, thread, which_output, pool); { - ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); + ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool); /* don't linearize float buffers, assumed to be linear */ if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) IMB_colormanagement_colorspace_to_scene_linear_v3(&texres->tr, ibuf->rect_colorspace); - BKE_image_release_ibuf(tex->ima, ibuf, NULL); + BKE_image_pool_release_ibuf(tex->ima, ibuf, pool); } } return rgbnor; } else { - return multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output); + return multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output, pool); } } /* this is called for surface shading */ -static int multitex_mtex(ShadeInput *shi, MTex *mtex, float texvec[3], float dxt[3], float dyt[3], TexResult *texres) +static int multitex_mtex(ShadeInput *shi, MTex *mtex, float texvec[3], float dxt[3], float dyt[3], TexResult *texres, struct ImagePool *pool) { Tex *tex = mtex->tex; @@ -1295,24 +1295,24 @@ static int multitex_mtex(ShadeInput *shi, MTex *mtex, float texvec[3], float dxt tex, mtex->which_output, R.r.cfra, (R.r.scemode & R_TEXNODE_PREVIEW) != 0, shi, mtex); } else { - return multitex(mtex->tex, texvec, dxt, dyt, shi->osatex, texres, shi->thread, mtex->which_output); + return multitex(mtex->tex, texvec, dxt, dyt, shi->osatex, texres, shi->thread, mtex->which_output, pool); } } /* Warning, if the texres's values are not declared zero, check the return value to be sure * the color values are set before using the r/g/b values, otherwise you may use uninitialized values - Campbell */ -int multitex_ext(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres) +int multitex_ext(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int osatex, TexResult *texres, struct ImagePool *pool) { - return multitex_nodes(tex, texvec, dxt, dyt, osatex, texres, 0, 0, NULL, NULL); + return multitex_nodes(tex, texvec, dxt, dyt, osatex, texres, 0, 0, NULL, NULL, pool); } /* extern-tex doesn't support nodes (ntreeBeginExec() can't be called when rendering is going on) */ -int multitex_ext_safe(Tex *tex, float texvec[3], TexResult *texres) +int multitex_ext_safe(Tex *tex, float texvec[3], TexResult *texres, struct ImagePool *pool) { int use_nodes= tex->use_nodes, retval; tex->use_nodes = FALSE; - retval= multitex_nodes(tex, texvec, NULL, NULL, 0, texres, 0, 0, NULL, NULL); + retval= multitex_nodes(tex, texvec, NULL, NULL, 0, texres, 0, 0, NULL, NULL, pool); tex->use_nodes= use_nodes; return retval; @@ -1699,7 +1699,8 @@ static void compatible_bump_uv_derivs(CompatibleBump *compat_bump, ShadeInput *s } static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi, MTex *mtex, Tex *tex, TexResult *texres, - float Tnor, const float co[3], const float dx[3], const float dy[3], float texvec[3], float dxt[3], float dyt[3]) + float Tnor, const float co[3], const float dx[3], const float dy[3], float texvec[3], float dxt[3], float dyt[3], + struct ImagePool *pool) { TexResult ttexr = {0, 0, 0, 0, 0, texres->talpha, NULL}; /* temp TexResult */ float tco[3], texv[3], cd, ud, vd, du, dv, idu, idv; @@ -1727,12 +1728,12 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi, if (!shi->osatex && (tex->type == TEX_IMAGE) && tex->ima) { /* in case we have no proper derivatives, fall back to * computing du/dv it based on image size */ - ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); + ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool); if (ibuf) { du = 1.f/(float)ibuf->x; dv = 1.f/(float)ibuf->y; } - BKE_image_release_ibuf(tex->ima, ibuf, NULL); + BKE_image_pool_release_ibuf(tex->ima, ibuf, pool); } else if (shi->osatex) { /* we have derivatives, can compute proper du/dv */ @@ -1752,7 +1753,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi, /* center, main return value */ texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt); - rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres); + rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres, pool); cd = fromrgb ? (texres->tr + texres->tg + texres->tb)*0.33333333f : texres->tin; if (mtex->texco == TEXCO_UV) { @@ -1766,7 +1767,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi, tco[1] = co[1] + compat_bump->dvdnu*du; tco[2] = 0.f; texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt); - multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr); + multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool); ud = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb)*0.33333333f : ttexr.tin)); /* +v val */ @@ -1774,7 +1775,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi, tco[1] = co[1] + compat_bump->dvdnv*du; tco[2] = 0.f; texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt); - multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr); + multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool); vd = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb)*0.33333333f : ttexr.tin)); } else { @@ -1808,7 +1809,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi, tco[1] = co[1] + tu[1]*du; tco[2] = co[2] + tu[2]*du; texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt); - multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr); + multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool); ud = idu*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb)*0.33333333f : ttexr.tin)); /* +v val */ @@ -1816,7 +1817,7 @@ static int compatible_bump_compute(CompatibleBump *compat_bump, ShadeInput *shi, tco[1] = co[1] + tv[1]*dv; tco[2] = co[2] + tv[2]*dv; texco_mapping(shi, tex, mtex, tco, dx, dy, texv, dxt, dyt); - multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr); + multitex_mtex(shi, mtex, texv, dxt, dyt, &ttexr, pool); vd = idv*(cd - (fromrgb ? (ttexr.tr + ttexr.tg + ttexr.tb)*0.33333333f : ttexr.tin)); } @@ -1858,7 +1859,7 @@ static void ntap_bump_init(NTapBump *ntap_bump) static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, Tex *tex, TexResult *texres, float Tnor, const float co[3], const float dx[3], const float dy[3], - float texvec[3], float dxt[3], float dyt[3]) + float texvec[3], float dxt[3], float dyt[3], struct ImagePool *pool) { TexResult ttexr = {0, 0, 0, 0, 0, texres->talpha, NULL}; /* temp TexResult */ @@ -1905,20 +1906,20 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T /* resolve image dimensions */ if (found_deriv_map || (mtex->texflag&MTEX_BUMP_TEXTURESPACE)!=0) { - ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); + ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool); if (ibuf) { dimx = ibuf->x; dimy = ibuf->y; aspect = ((float) dimy) / dimx; } - BKE_image_release_ibuf(tex->ima, ibuf, NULL); + BKE_image_pool_release_ibuf(tex->ima, ibuf, pool); } if (found_deriv_map) { float dBdu, dBdv, auto_bump = 1.0f; float s = 1; /* negate this if flipped texture coordinate */ texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt); - rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres); + rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, texres, pool); if (shi->obr->ob->derivedFinal) { auto_bump = shi->obr->ob->derivedFinal->auto_bump_scale; @@ -1960,14 +1961,14 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T } /* use texres for the center sample, set rgbnor */ - rgbnor = multitex_mtex(shi, mtex, STll, dxt, dyt, texres); + rgbnor = multitex_mtex(shi, mtex, STll, dxt, dyt, texres, pool); Hll = (fromrgb) ? rgb_to_grayscale(&texres->tr) : texres->tin; /* use ttexr for the other 2 taps */ - multitex_mtex(shi, mtex, STlr, dxt, dyt, &ttexr); + multitex_mtex(shi, mtex, STlr, dxt, dyt, &ttexr, pool); Hlr = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin; - multitex_mtex(shi, mtex, STul, dxt, dyt, &ttexr); + multitex_mtex(shi, mtex, STul, dxt, dyt, &ttexr, pool); Hul = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin; dHdx = Hscale*(Hlr - Hll); @@ -1998,17 +1999,17 @@ static int ntap_bump_compute(NTapBump *ntap_bump, ShadeInput *shi, MTex *mtex, T } /* use texres for the center sample, set rgbnor */ - rgbnor = multitex_mtex(shi, mtex, STc, dxt, dyt, texres); + rgbnor = multitex_mtex(shi, mtex, STc, dxt, dyt, texres, pool); /* Hc = (fromrgb) ? rgb_to_grayscale(&texres->tr) : texres->tin; */ /* UNUSED */ /* use ttexr for the other taps */ - multitex_mtex(shi, mtex, STl, dxt, dyt, &ttexr); + multitex_mtex(shi, mtex, STl, dxt, dyt, &ttexr, pool); Hl = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin; - multitex_mtex(shi, mtex, STr, dxt, dyt, &ttexr); + multitex_mtex(shi, mtex, STr, dxt, dyt, &ttexr, pool); Hr = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin; - multitex_mtex(shi, mtex, STd, dxt, dyt, &ttexr); + multitex_mtex(shi, mtex, STd, dxt, dyt, &ttexr, pool); Hd = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin; - multitex_mtex(shi, mtex, STu, dxt, dyt, &ttexr); + multitex_mtex(shi, mtex, STu, dxt, dyt, &ttexr, pool); Hu = (fromrgb) ? rgb_to_grayscale(&ttexr.tr) : ttexr.tin; dHdx = Hscale*(Hr - Hl); @@ -2285,20 +2286,22 @@ void do_material_tex(ShadeInput *shi, Render *re) if (texres.nor && !((tex->type==TEX_IMAGE) && (tex->imaflag & TEX_NORMALMAP))) { if (use_compat_bump) { rgbnor = compatible_bump_compute(&compat_bump, shi, mtex, tex, - &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt); + &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt, + re->pool); } else if (use_ntap_bump) { rgbnor = ntap_bump_compute(&ntap_bump, shi, mtex, tex, - &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt); + &texres, Tnor*stencilTin, co, dx, dy, texvec, dxt, dyt, + re->pool); } else { texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt); - rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres); + rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres, re->pool); } } else { texco_mapping(shi, tex, mtex, co, dx, dy, texvec, dxt, dyt); - rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres); + rgbnor = multitex_mtex(shi, mtex, texvec, dxt, dyt, &texres, re->pool); } /* texture output */ @@ -2402,13 +2405,13 @@ void do_material_tex(ShadeInput *shi, Render *re) /* inverse gamma correction */ if (tex->type==TEX_IMAGE) { Image *ima = tex->ima; - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL); + ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, re->pool); /* don't linearize float buffers, assumed to be linear */ if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) IMB_colormanagement_colorspace_to_scene_linear_v3(tcol, ibuf->rect_colorspace); - BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_pool_release_ibuf(ima, ibuf, re->pool); } if (mtex->mapto & MAP_COL) { @@ -2737,7 +2740,7 @@ void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_ else texvec[2]= mtex->size[2]*(mtex->ofs[2]); } - rgbnor= multitex(tex, texvec, NULL, NULL, 0, &texres, 0, mtex->which_output); /* NULL = dxt/dyt, 0 = shi->osatex - not supported */ + rgbnor = multitex(tex, texvec, NULL, NULL, 0, &texres, 0, mtex->which_output, re->pool); /* NULL = dxt/dyt, 0 = shi->osatex - not supported */ /* texture output */ @@ -2904,7 +2907,7 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4]) if (mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); - rgb= multitex(mtex->tex, texvec, dxt, dyt, osatex, &texres, 0, mtex->which_output); + rgb = multitex(mtex->tex, texvec, dxt, dyt, osatex, &texres, 0, mtex->which_output, har->pool); /* texture output */ if (rgb && (mtex->texflag & MTEX_RGBTOINT)) { @@ -2936,13 +2939,13 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4]) /* inverse gamma correction */ if (mtex->tex->type==TEX_IMAGE) { Image *ima = mtex->tex->ima; - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &mtex->tex->iuser, NULL); + ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &mtex->tex->iuser, har->pool); /* don't linearize float buffers, assumed to be linear */ if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) IMB_colormanagement_colorspace_to_scene_linear_v3(&texres.tr, ibuf->rect_colorspace); - BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_pool_release_ibuf(ima, ibuf, har->pool); } fact= texres.tin*mtex->colfac; @@ -3109,7 +3112,7 @@ void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float h /* texture */ if (tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); - rgb= multitex(mtex->tex, texvec, dxt, dyt, R.osa, &texres, thread, mtex->which_output); + rgb = multitex(mtex->tex, texvec, dxt, dyt, R.osa, &texres, thread, mtex->which_output, R.pool); /* texture output */ if (rgb && (mtex->texflag & MTEX_RGBTOINT)) { @@ -3157,13 +3160,13 @@ void do_sky_tex(const float rco[3], float lo[3], const float dxyview[2], float h /* inverse gamma correction */ if (tex->type==TEX_IMAGE) { Image *ima = tex->ima; - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL); + ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, R.pool); /* don't linearize float buffers, assumed to be linear */ if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) IMB_colormanagement_colorspace_to_scene_linear_v3(tcol, ibuf->rect_colorspace); - BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_pool_release_ibuf(ima, ibuf, R.pool); } if (mtex->mapto & WOMAP_HORIZ) { @@ -3324,7 +3327,7 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); } - rgb= multitex(tex, texvec, dxt, dyt, shi->osatex, &texres, shi->thread, mtex->which_output); + rgb = multitex(tex, texvec, dxt, dyt, shi->osatex, &texres, shi->thread, mtex->which_output, R.pool); /* texture output */ if (rgb && (mtex->texflag & MTEX_RGBTOINT)) { @@ -3373,13 +3376,13 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r /* inverse gamma correction */ if (tex->type==TEX_IMAGE) { Image *ima = tex->ima; - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL); + ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, R.pool); /* don't linearize float buffers, assumed to be linear */ if (ibuf && !(ibuf->rect_float) && R.scene_color_manage) IMB_colormanagement_colorspace_to_scene_linear_v3(&texres.tr, ibuf->rect_colorspace); - BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_pool_release_ibuf(ima, ibuf, R.pool); } /* lamp colors were premultiplied with this */ @@ -3395,7 +3398,7 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r /* ------------------------------------------------------------------------- */ -int externtex(MTex *mtex, const float vec[3], float *tin, float *tr, float *tg, float *tb, float *ta, const int thread) +int externtex(MTex *mtex, const float vec[3], float *tin, float *tr, float *tg, float *tb, float *ta, const int thread, struct ImagePool *pool) { Tex *tex; TexResult texr; @@ -3421,7 +3424,7 @@ int externtex(MTex *mtex, const float vec[3], float *tin, float *tr, float *tg, do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt); } - rgb= multitex(tex, texvec, dxt, dyt, 0, &texr, thread, mtex->which_output); + rgb = multitex(tex, texvec, dxt, dyt, 0, &texr, thread, mtex->which_output, pool); if (rgb) { texr.tin = rgb_to_bw(&texr.tr); @@ -3485,8 +3488,8 @@ void render_realtime_texture(ShadeInput *shi, Image *ima) texr.nor= NULL; - if (shi->osatex) imagewraposa(tex, ima, NULL, texvec, dx, dy, &texr); - else imagewrap(tex, ima, NULL, texvec, &texr); + if (shi->osatex) imagewraposa(tex, ima, NULL, texvec, dx, dy, &texr, R.pool); + else imagewrap(tex, ima, NULL, texvec, &texr, R.pool); shi->vcol[0]*= texr.tr; shi->vcol[1]*= texr.tg; diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 14586f16478..2d0f575b3e3 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -20,7 +20,6 @@ * * Contributors: Hos, Robert Wenzlaff. * Contributors: 2004/2005/2006 Blender Foundation, full recode - * Contributors: Vertex color baking, Copyright 2011 AutoCRC * * ***** END GPL LICENSE BLOCK ***** */ @@ -1139,7 +1138,7 @@ static void addAlphaOverFloatMask(float *dest, float *source, unsigned short dma dest[3]+= source[3]; return; - } + } dest[0]= (mul*dest[0]) + source[0]; dest[1]= (mul*dest[1]) + source[1]; @@ -1991,932 +1990,3 @@ void add_halo_flare(Render *re) R.r.mode= mode; } -/* ************************* bake ************************ */ - - -typedef struct BakeShade { - ShadeSample ssamp; - ObjectInstanceRen *obi; - VlakRen *vlr; - - ZSpan *zspan; - Image *ima; - ImBuf *ibuf; - - int rectx, recty, quad, type, vdone, ready; - - float dir[3]; - Object *actob; - - /* Output: vertex color or image data. If vcol is not NULL, rect and - * rect_float should be NULL. */ - MPoly *mpoly; - MLoop *mloop; - MLoopCol *vcol; - - unsigned int *rect; - float *rect_float; - - int use_mask; - char *rect_mask; /* bake pixel mask */ - - float dxco[3], dyco[3]; - - short *do_update; - - struct ColorSpace *rect_colorspace; -} BakeShade; - -static void bake_set_shade_input(ObjectInstanceRen *obi, VlakRen *vlr, ShadeInput *shi, int quad, int UNUSED(isect), int x, int y, float u, float v) -{ - if (quad) - shade_input_set_triangle_i(shi, obi, vlr, 0, 2, 3); - else - shade_input_set_triangle_i(shi, obi, vlr, 0, 1, 2); - - /* cache for shadow */ - shi->samplenr= R.shadowsamplenr[shi->thread]++; - - shi->mask= 0xFFFF; /* all samples */ - - shi->u= -u; - shi->v= -v; - shi->xs= x; - shi->ys= y; - - shade_input_set_uv(shi); - shade_input_set_normals(shi); - - /* no normal flip */ - if (shi->flippednor) - shade_input_flip_normals(shi); - - /* set up view vector to look right at the surface (note that the normal - * is negated in the renderer so it does not need to be done here) */ - shi->view[0]= shi->vn[0]; - shi->view[1]= shi->vn[1]; - shi->view[2]= shi->vn[2]; -} - -static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int UNUSED(quad), int x, int y, float UNUSED(u), float UNUSED(v), float *tvn, float *ttang) -{ - BakeShade *bs= handle; - ShadeSample *ssamp= &bs->ssamp; - ShadeResult shr; - VlakRen *vlr= shi->vlr; - - shade_input_init_material(shi); - - if (bs->type==RE_BAKE_AO) { - ambient_occlusion(shi); - - if (R.r.bake_flag & R_BAKE_NORMALIZE) { - copy_v3_v3(shr.combined, shi->ao); - } - else { - zero_v3(shr.combined); - environment_lighting_apply(shi, &shr); - } - } - else { - if (bs->type==RE_BAKE_SHADOW) /* Why do shadows set the color anyhow?, ignore material color for baking */ - shi->r = shi->g = shi->b = 1.0f; - - shade_input_set_shade_texco(shi); - - /* only do AO for a full bake (and obviously AO bakes) - * AO for light bakes is a leftover and might not be needed */ - if ( ELEM3(bs->type, RE_BAKE_ALL, RE_BAKE_AO, RE_BAKE_LIGHT)) - shade_samples_do_AO(ssamp); - - if (shi->mat->nodetree && shi->mat->use_nodes) { - ntreeShaderExecTree(shi->mat->nodetree, shi, &shr); - shi->mat= vlr->mat; /* shi->mat is being set in nodetree */ - } - else - shade_material_loop(shi, &shr); - - if (bs->type==RE_BAKE_NORMALS) { - float nor[3]; - - copy_v3_v3(nor, shi->vn); - - if (R.r.bake_normal_space == R_BAKE_SPACE_CAMERA) { - /* pass */ - } - else if (R.r.bake_normal_space == R_BAKE_SPACE_TANGENT) { - float mat[3][3], imat[3][3]; - - /* bitangent */ - if (tvn && ttang) { - copy_v3_v3(mat[0], ttang); - cross_v3_v3v3(mat[1], tvn, ttang); - mul_v3_fl(mat[1], ttang[3]); - copy_v3_v3(mat[2], tvn); - } - else { - copy_v3_v3(mat[0], shi->nmaptang); - cross_v3_v3v3(mat[1], shi->nmapnorm, shi->nmaptang); - mul_v3_fl(mat[1], shi->nmaptang[3]); - copy_v3_v3(mat[2], shi->nmapnorm); - } - - invert_m3_m3(imat, mat); - mul_m3_v3(imat, nor); - } - else if (R.r.bake_normal_space == R_BAKE_SPACE_OBJECT) - mul_mat3_m4_v3(ob->imat_ren, nor); /* ob->imat_ren includes viewinv! */ - else if (R.r.bake_normal_space == R_BAKE_SPACE_WORLD) - mul_mat3_m4_v3(R.viewinv, nor); - - normalize_v3(nor); /* in case object has scaling */ - - /* The invert of the red channel is to make - * the normal map compliant with the outside world. - * It needs to be done because in Blender - * the normal used in the renderer points inward. It is generated - * this way in calc_vertexnormals(). Should this ever change - * this negate must be removed. */ - shr.combined[0]= (-nor[0])/2.0f + 0.5f; - shr.combined[1]= nor[1]/2.0f + 0.5f; - shr.combined[2]= nor[2]/2.0f + 0.5f; - } - else if (bs->type==RE_BAKE_TEXTURE) { - shr.combined[0]= shi->r; - shr.combined[1]= shi->g; - shr.combined[2]= shi->b; - shr.alpha = shi->alpha; - } - else if (bs->type==RE_BAKE_SHADOW) { - copy_v3_v3(shr.combined, shr.shad); - shr.alpha = shi->alpha; - } - else if (bs->type==RE_BAKE_SPEC_COLOR) { - shr.combined[0]= shi->specr; - shr.combined[1]= shi->specg; - shr.combined[2]= shi->specb; - shr.alpha = 1.0f; - } - else if (bs->type==RE_BAKE_SPEC_INTENSITY) { - shr.combined[0]= - shr.combined[1]= - shr.combined[2]= shi->spec; - shr.alpha = 1.0f; - } - else if (bs->type==RE_BAKE_MIRROR_COLOR) { - shr.combined[0]= shi->mirr; - shr.combined[1]= shi->mirg; - shr.combined[2]= shi->mirb; - shr.alpha = 1.0f; - } - else if (bs->type==RE_BAKE_MIRROR_INTENSITY) { - shr.combined[0]= - shr.combined[1]= - shr.combined[2]= shi->ray_mirror; - shr.alpha = 1.0f; - } - else if (bs->type==RE_BAKE_ALPHA) { - shr.combined[0]= - shr.combined[1]= - shr.combined[2]= shi->alpha; - shr.alpha = 1.0f; - } - else if (bs->type==RE_BAKE_EMIT) { - shr.combined[0]= - shr.combined[1]= - shr.combined[2]= shi->emit; - shr.alpha = 1.0f; - } - } - - if (bs->rect_float && !bs->vcol) { - float *col= bs->rect_float + 4*(bs->rectx*y + x); - copy_v3_v3(col, shr.combined); - if (bs->type==RE_BAKE_ALL || bs->type==RE_BAKE_TEXTURE) { - col[3]= shr.alpha; - } - else { - col[3]= 1.0; - } - } - else { - /* Target is char (LDR). */ - unsigned char col[4]; - - if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) { - float rgb[3]; - - copy_v3_v3(rgb, shr.combined); - if (R.scene_color_manage) - IMB_colormanagement_scene_linear_to_colorspace_v3(rgb, bs->rect_colorspace); - rgb_float_to_uchar(col, rgb); - } - else { - rgb_float_to_uchar(col, shr.combined); - } - - if (ELEM(bs->type, RE_BAKE_ALL, RE_BAKE_TEXTURE)) { - col[3]= FTOCHAR(shr.alpha); - } - else { - col[3]= 255; - } - - if (bs->vcol) { - /* Vertex colour baking. Vcol has no useful alpha channel (it exists - * but is used only for vertex painting). */ - bs->vcol->r = col[0]; - bs->vcol->g = col[1]; - bs->vcol->b = col[2]; - } - else { - unsigned char *imcol= (unsigned char *)(bs->rect + bs->rectx*y + x); - copy_v4_v4_char((char *)imcol, (char *)col); - } - - } - - if (bs->rect_mask) { - bs->rect_mask[bs->rectx*y + x] = FILTER_MASK_USED; - } -} - -static void bake_displacement(void *handle, ShadeInput *UNUSED(shi), float dist, int x, int y) -{ - BakeShade *bs= handle; - float disp; - - if (R.r.bake_flag & R_BAKE_NORMALIZE && R.r.bake_maxdist) { - disp = (dist+R.r.bake_maxdist) / (R.r.bake_maxdist*2); /* alter the range from [-bake_maxdist, bake_maxdist] to [0, 1]*/ - } - else { - disp = 0.5f + dist; /* alter the range from [-0.5,0.5] to [0,1]*/ - } - - if (bs->rect_float && !bs->vcol) { - float *col= bs->rect_float + 4*(bs->rectx*y + x); - col[0] = col[1] = col[2] = disp; - col[3]= 1.0f; - } - else { - /* Target is char (LDR). */ - unsigned char col[4]; - col[0] = col[1] = col[2] = FTOCHAR(disp); - col[3] = 255; - - if(bs->vcol) { - /* Vertex colour baking. Vcol has no useful alpha channel (it exists - * but is used only for vertex painting). */ - bs->vcol->r = col[0]; - bs->vcol->g = col[1]; - bs->vcol->b = col[2]; - } - else { - char *imcol= (char *)(bs->rect + bs->rectx*y + x); - copy_v4_v4_char((char *)imcol, (char *)col); - } - } - if (bs->rect_mask) { - bs->rect_mask[bs->rectx*y + x] = FILTER_MASK_USED; - } -} - -static int bake_intersect_tree(RayObject* raytree, Isect* isect, float *start, float *dir, float sign, float *hitco, float *dist) -{ - float maxdist; - int hit; - - /* might be useful to make a user setting for maxsize*/ - if (R.r.bake_maxdist > 0.0f) - maxdist= R.r.bake_maxdist; - else - maxdist= RE_RAYTRACE_MAXDIST + R.r.bake_biasdist; - - /* 'dir' is always normalized */ - madd_v3_v3v3fl(isect->start, start, dir, -R.r.bake_biasdist); - - mul_v3_v3fl(isect->dir, dir, sign); - - isect->dist = maxdist; - - hit = RE_rayobject_raycast(raytree, isect); - if (hit) { - madd_v3_v3v3fl(hitco, isect->start, isect->dir, isect->dist); - - *dist= isect->dist; - } - - return hit; -} - -static void bake_set_vlr_dxyco(BakeShade *bs, float *uv1, float *uv2, float *uv3) -{ - VlakRen *vlr= bs->vlr; - float A, d1, d2, d3, *v1, *v2, *v3; - - if (bs->quad) { - v1= vlr->v1->co; - v2= vlr->v3->co; - v3= vlr->v4->co; - } - else { - v1= vlr->v1->co; - v2= vlr->v2->co; - v3= vlr->v3->co; - } - - /* formula derived from barycentric coordinates: - * (uvArea1*v1 + uvArea2*v2 + uvArea3*v3)/uvArea - * then taking u and v partial derivatives to get dxco and dyco */ - A= (uv2[0] - uv1[0])*(uv3[1] - uv1[1]) - (uv3[0] - uv1[0])*(uv2[1] - uv1[1]); - - if (fabsf(A) > FLT_EPSILON) { - A= 0.5f/A; - - d1= uv2[1] - uv3[1]; - d2= uv3[1] - uv1[1]; - d3= uv1[1] - uv2[1]; - bs->dxco[0]= (v1[0]*d1 + v2[0]*d2 + v3[0]*d3)*A; - bs->dxco[1]= (v1[1]*d1 + v2[1]*d2 + v3[1]*d3)*A; - bs->dxco[2]= (v1[2]*d1 + v2[2]*d2 + v3[2]*d3)*A; - - d1= uv3[0] - uv2[0]; - d2= uv1[0] - uv3[0]; - d3= uv2[0] - uv1[0]; - bs->dyco[0]= (v1[0]*d1 + v2[0]*d2 + v3[0]*d3)*A; - bs->dyco[1]= (v1[1]*d1 + v2[1]*d2 + v3[1]*d3)*A; - bs->dyco[2]= (v1[2]*d1 + v2[2]*d2 + v3[2]*d3)*A; - } - else { - bs->dxco[0]= bs->dxco[1]= bs->dxco[2]= 0.0f; - bs->dyco[0]= bs->dyco[1]= bs->dyco[2]= 0.0f; - } - - if (bs->obi->flag & R_TRANSFORMED) { - mul_m3_v3(bs->obi->nmat, bs->dxco); - mul_m3_v3(bs->obi->nmat, bs->dyco); - } -} - -static void do_bake_shade(void *handle, int x, int y, float u, float v) -{ - BakeShade *bs= handle; - VlakRen *vlr= bs->vlr; - ObjectInstanceRen *obi= bs->obi; - Object *ob= obi->obr->ob; - float l, *v1, *v2, *v3, tvn[3], ttang[4]; - int quad; - ShadeSample *ssamp= &bs->ssamp; - ShadeInput *shi= ssamp->shi; - - /* fast threadsafe break test */ - if (R.test_break(R.tbh)) - return; - - /* setup render coordinates */ - if (bs->quad) { - v1= vlr->v1->co; - v2= vlr->v3->co; - v3= vlr->v4->co; - } - else { - v1= vlr->v1->co; - v2= vlr->v2->co; - v3= vlr->v3->co; - } - - l= 1.0f-u-v; - - /* shrink barycentric coordinates inwards slightly to avoid some issues - * where baking selected to active might just miss the other face at the - * near the edge of a face */ - if (bs->actob) { - const float eps = 1.0f - 1e-4f; - float invsum; - - u = (u - 0.5f)*eps + 0.5f; - v = (v - 0.5f)*eps + 0.5f; - l = (l - 0.5f)*eps + 0.5f; - - invsum = 1.0f/(u + v + l); - - u *= invsum; - v *= invsum; - l *= invsum; - } - - /* renderco */ - shi->co[0]= l*v3[0]+u*v1[0]+v*v2[0]; - shi->co[1]= l*v3[1]+u*v1[1]+v*v2[1]; - shi->co[2]= l*v3[2]+u*v1[2]+v*v2[2]; - - if (obi->flag & R_TRANSFORMED) - mul_m4_v3(obi->mat, shi->co); - - copy_v3_v3(shi->dxco, bs->dxco); - copy_v3_v3(shi->dyco, bs->dyco); - - quad= bs->quad; - bake_set_shade_input(obi, vlr, shi, quad, 0, x, y, u, v); - - if (bs->type==RE_BAKE_NORMALS && R.r.bake_normal_space==R_BAKE_SPACE_TANGENT) { - shade_input_set_shade_texco(shi); - copy_v3_v3(tvn, shi->nmapnorm); - copy_v4_v4(ttang, shi->nmaptang); - } - - /* if we are doing selected to active baking, find point on other face */ - if (bs->actob) { - Isect isec, minisec; - float co[3], minco[3], dist, mindist=0.0f; - int hit, sign, dir=1; - - /* intersect with ray going forward and backward*/ - hit= 0; - memset(&minisec, 0, sizeof(minisec)); - minco[0]= minco[1]= minco[2]= 0.0f; - - copy_v3_v3(bs->dir, shi->vn); - - for (sign=-1; sign<=1; sign+=2) { - memset(&isec, 0, sizeof(isec)); - isec.mode= RE_RAY_MIRROR; - - isec.orig.ob = obi; - isec.orig.face = vlr; - isec.userdata= bs->actob; - isec.check = RE_CHECK_VLR_BAKE; - isec.skip = RE_SKIP_VLR_NEIGHBOUR; - - if (bake_intersect_tree(R.raytree, &isec, shi->co, shi->vn, sign, co, &dist)) { - if (!hit || len_squared_v3v3(shi->co, co) < len_squared_v3v3(shi->co, minco)) { - minisec= isec; - mindist= dist; - copy_v3_v3(minco, co); - hit= 1; - dir = sign; - } - } - } - - if (bs->type==RE_BAKE_DISPLACEMENT) { - if (hit) - bake_displacement(handle, shi, (dir==-1)? mindist:-mindist, x, y); - else - bake_displacement(handle, shi, 0.0f, x, y); - return; - } - - /* if hit, we shade from the new point, otherwise from point one starting face */ - if (hit) { - obi = (ObjectInstanceRen *)minisec.hit.ob; - vlr = (VlakRen *)minisec.hit.face; - quad= (minisec.isect == 2); - copy_v3_v3(shi->co, minco); - - u= -minisec.u; - v= -minisec.v; - bake_set_shade_input(obi, vlr, shi, quad, 1, x, y, u, v); - } - } - - if (bs->type==RE_BAKE_NORMALS && R.r.bake_normal_space==R_BAKE_SPACE_TANGENT) - bake_shade(handle, ob, shi, quad, x, y, u, v, tvn, ttang); - else - bake_shade(handle, ob, shi, quad, x, y, u, v, 0, 0); -} - -static int get_next_bake_face(BakeShade *bs) -{ - ObjectRen *obr; - VlakRen *vlr; - MTFace *tface; - static int v= 0, vdone = FALSE; - static ObjectInstanceRen *obi= NULL; - - if (bs==NULL) { - vlr= NULL; - v= vdone = FALSE; - obi= R.instancetable.first; - return 0; - } - - BLI_lock_thread(LOCK_CUSTOM1); - - for (; obi; obi=obi->next, v=0) { - obr= obi->obr; - - for (; v<obr->totvlak; v++) { - vlr= RE_findOrAddVlak(obr, v); - - if ((bs->actob && bs->actob == obr->ob) || (!bs->actob && (obr->ob->flag & SELECT))) { - if(R.r.bake_flag & R_BAKE_VCOL) { - /* Gather face data for vertex colour bake */ - Mesh *me; - int *origindex, vcollayer; - CustomDataLayer *cdl; - - if(obr->ob->type != OB_MESH) - continue; - me = obr->ob->data; - - origindex = RE_vlakren_get_origindex(obr, vlr, 0); - if(origindex == NULL) - continue; - if (*origindex >= me->totpoly) { - /* Small hack for Array modifier, which gives false - original indices - z0r */ - continue; - } -#if 0 - /* Only shade selected faces. */ - if((me->mface[*origindex].flag & ME_FACE_SEL) == 0) - continue; -#endif - - vcollayer = CustomData_get_render_layer_index(&me->ldata, CD_MLOOPCOL); - if(vcollayer == -1) - continue; - - cdl = &me->ldata.layers[vcollayer]; - bs->mpoly = me->mpoly + *origindex; - bs->vcol = ((MLoopCol*)cdl->data) + bs->mpoly->loopstart; - bs->mloop = me->mloop + bs->mpoly->loopstart; - - /* Tag mesh for reevaluation. */ - DAG_id_tag_update(&me->id, 0); - } - else { - Image *ima = NULL; - ImBuf *ibuf = NULL; - const float vec_alpha[4]= {0.0f, 0.0f, 0.0f, 0.0f}; - const float vec_solid[4]= {0.0f, 0.0f, 0.0f, 1.0f}; - - tface= RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0); - - if (!tface || !tface->tpage) - continue; - - ima = tface->tpage; - ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); - - if (ibuf==NULL) - continue; - - if (ibuf->rect==NULL && ibuf->rect_float==NULL) { - BKE_image_release_ibuf(ima, ibuf, NULL); - continue; - } - - if (ibuf->rect_float && !(ibuf->channels==0 || ibuf->channels==4)) { - BKE_image_release_ibuf(ima, ibuf, NULL); - continue; - } - - if (ima->flag & IMA_USED_FOR_RENDER) { - ima->id.flag &= ~LIB_DOIT; - BKE_image_release_ibuf(ima, ibuf, NULL); - continue; - } - - /* find the image for the first time? */ - if (ima->id.flag & LIB_DOIT) { - ima->id.flag &= ~LIB_DOIT; - - /* we either fill in float or char, this ensures things go fine */ - if (ibuf->rect_float) - imb_freerectImBuf(ibuf); - /* clear image */ - if (R.r.bake_flag & R_BAKE_CLEAR) - IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid); - - /* might be read by UI to set active image for display */ - R.bakebuf= ima; - } - - /* Tag image for redraw. */ - ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; - BKE_image_release_ibuf(ima, ibuf, NULL); - } - - bs->obi = obi; - bs->vlr = vlr; - bs->vdone++; /* only for error message if nothing was rendered */ - v++; - BLI_unlock_thread(LOCK_CUSTOM1); - return 1; - } - } - } - - BLI_unlock_thread(LOCK_CUSTOM1); - return 0; -} - -static void bake_single_vertex(BakeShade *bs, VertRen *vert, float u, float v) -{ - int *origindex, i; - MLoopCol *basevcol; - MLoop *mloop; - - origindex = RE_vertren_get_origindex(bs->obi->obr, vert, 0); - if (!origindex || *origindex == ORIGINDEX_NONE) - return; - - /* Search for matching vertex index and apply shading. */ - for (i = 0; i < bs->mpoly->totloop; i++) { - mloop = bs->mloop + i; - if (mloop->v != *origindex) - continue; - basevcol = bs->vcol; - bs->vcol = basevcol + i; - do_bake_shade(bs, 0, 0, u, v); - bs->vcol = basevcol; - break; - } -} - -/* Bake all vertices of a face. Actually, this still works on a face-by-face - basis, and each vertex on each face is shaded. Vertex colors are a property - of loops, not vertices. */ -static void shade_verts(BakeShade *bs) -{ - VlakRen *vlr = bs->vlr; - - /* Disable baking to image; write to vcol instead. vcol pointer is set in - * bake_single_vertex. */ - bs->ima = NULL; - bs->rect = NULL; - bs->rect_float = NULL; - - bs->quad = 0; - - /* No anti-aliasing for vertices. */ - zero_v3(bs->dxco); - zero_v3(bs->dyco); - - /* Shade each vertex of the face. u and v are barycentric coordinates; since - we're only interested in vertices, these will be 0 or 1. */ - if ((vlr->flag & R_FACE_SPLIT) == 0) { - /* Processing triangle face, whole quad, or first half of split quad. */ - - bake_single_vertex(bs, bs->vlr->v1, 1.0f, 0.0f); - bake_single_vertex(bs, bs->vlr->v2, 0.0f, 1.0f); - bake_single_vertex(bs, bs->vlr->v3, 0.0f, 0.0f); - - if (vlr->v4) { - bs->quad = 1; - bake_single_vertex(bs, bs->vlr->v4, 0.0f, 0.0f); - } - } - else { - /* Processing second half of split quad. Only one vertex to go. */ - if (vlr->flag & R_DIVIDE_24) { - bake_single_vertex(bs, bs->vlr->v2, 0.0f, 1.0f); - } - else { - bake_single_vertex(bs, bs->vlr->v3, 0.0f, 0.0f); - } - } -} - -/* already have tested for tface and ima and zspan */ -static void shade_tface(BakeShade *bs) -{ - VlakRen *vlr= bs->vlr; - ObjectInstanceRen *obi= bs->obi; - ObjectRen *obr= obi->obr; - MTFace *tface= RE_vlakren_get_tface(obr, vlr, obr->bakemtface, NULL, 0); - Image *ima= tface->tpage; - float vec[4][2]; - int a, i1, i2, i3; - - /* check valid zspan */ - if (ima!=bs->ima) { - BKE_image_release_ibuf(bs->ima, bs->ibuf, NULL); - - bs->ima= ima; - bs->ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL); - /* note, these calls only free/fill contents of zspan struct, not zspan itself */ - zbuf_free_span(bs->zspan); - zbuf_alloc_span(bs->zspan, bs->ibuf->x, bs->ibuf->y, R.clipcrop); - } - - bs->rectx= bs->ibuf->x; - bs->recty= bs->ibuf->y; - bs->rect= bs->ibuf->rect; - bs->rect_colorspace= bs->ibuf->rect_colorspace; - bs->rect_float= bs->ibuf->rect_float; - bs->vcol = NULL; - bs->quad= 0; - - if (bs->use_mask) { - if (bs->ibuf->userdata==NULL) { - BLI_lock_thread(LOCK_CUSTOM1); - if (bs->ibuf->userdata==NULL) /* since the thread was locked, its possible another thread alloced the value */ - bs->ibuf->userdata = (void *)MEM_callocN(sizeof(char)*bs->rectx*bs->recty, "BakeMask"); - bs->rect_mask= (char *)bs->ibuf->userdata; - BLI_unlock_thread(LOCK_CUSTOM1); - } - else { - bs->rect_mask= (char *)bs->ibuf->userdata; - } - } - - /* get pixel level vertex coordinates */ - for (a=0; a<4; a++) { - /* Note, workaround for pixel aligned UVs which are common and can screw up our intersection tests - * where a pixel gets in between 2 faces or the middle of a quad, - * camera aligned quads also have this problem but they are less common. - * Add a small offset to the UVs, fixes bug #18685 - Campbell */ - vec[a][0]= tface->uv[a][0]*(float)bs->rectx - (0.5f + 0.001f); - vec[a][1]= tface->uv[a][1]*(float)bs->recty - (0.5f + 0.002f); - } - - /* UV indices have to be corrected for possible quad->tria splits */ - i1= 0; i2= 1; i3= 2; - vlr_set_uv_indices(vlr, &i1, &i2, &i3); - bake_set_vlr_dxyco(bs, vec[i1], vec[i2], vec[i3]); - zspan_scanconvert(bs->zspan, bs, vec[i1], vec[i2], vec[i3], do_bake_shade); - - if (vlr->v4) { - bs->quad= 1; - bake_set_vlr_dxyco(bs, vec[0], vec[2], vec[3]); - zspan_scanconvert(bs->zspan, bs, vec[0], vec[2], vec[3], do_bake_shade); - } -} - -static void *do_bake_thread(void *bs_v) -{ - BakeShade *bs= bs_v; - - while (get_next_bake_face(bs)) { - if (R.r.bake_flag & R_BAKE_VCOL) - shade_verts(bs); - else - shade_tface(bs); - - /* fast threadsafe break test */ - if (R.test_break(R.tbh)) - break; - - /* access is not threadsafe but since its just true/false probably ok - * only used for interactive baking */ - if (bs->do_update) - *bs->do_update= TRUE; - } - bs->ready= 1; - - BKE_image_release_ibuf(bs->ima, bs->ibuf, NULL); - - return NULL; -} - -void RE_bake_ibuf_filter(ImBuf *ibuf, char *mask, const int filter) -{ - /* must check before filtering */ - const short is_new_alpha= (ibuf->planes != R_IMF_PLANES_RGBA) && BKE_imbuf_alpha_test(ibuf); - - /* Margin */ - if (filter) { - IMB_filter_extend(ibuf, mask, filter); - } - - /* if the bake results in new alpha then change the image setting */ - if (is_new_alpha) { - ibuf->planes= R_IMF_PLANES_RGBA; - } - else { - if (filter && ibuf->planes != R_IMF_PLANES_RGBA) { - /* clear alpha added by filtering */ - IMB_rectfill_alpha(ibuf, 1.0f); - } - } -} - -/* using object selection tags, the faces with UV maps get baked */ -/* render should have been setup */ -/* returns 0 if nothing was handled */ -int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_update, float *progress) -{ - BakeShade *handles; - ListBase threads; - Image *ima; - int a, vdone = FALSE, use_mask = FALSE, result = BAKE_RESULT_OK; - - re->scene_color_manage = BKE_scene_check_color_management_enabled(re->scene); - - /* initialize render global */ - R= *re; - R.bakebuf= NULL; - - /* initialize static vars */ - get_next_bake_face(NULL); - - /* do we need a mask? */ - if (re->r.bake_filter) - use_mask = TRUE; - - /* baker uses this flag to detect if image was initialized */ - if ((R.r.bake_flag & R_BAKE_VCOL) == 0) { - for (ima = G.main->image.first; ima; ima = ima->id.next) { - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); - ima->id.flag |= LIB_DOIT; - ima->flag &= ~IMA_USED_FOR_RENDER; - if (ibuf) { - ibuf->userdata = NULL; /* use for masking if needed */ - } - BKE_image_release_ibuf(ima, ibuf, NULL); - } - } - - BLI_init_threads(&threads, do_bake_thread, re->r.threads); - - handles= MEM_callocN(sizeof(BakeShade)*re->r.threads, "BakeShade"); - - /* get the threads running */ - for (a=0; a<re->r.threads; a++) { - /* set defaults in handles */ - handles[a].ssamp.shi[0].lay= re->lay; - - if (type==RE_BAKE_SHADOW) { - handles[a].ssamp.shi[0].passflag= SCE_PASS_SHADOW; - } - else { - handles[a].ssamp.shi[0].passflag= SCE_PASS_COMBINED; - } - handles[a].ssamp.shi[0].combinedflag= ~(SCE_PASS_SPEC); - handles[a].ssamp.shi[0].thread= a; - handles[a].ssamp.tot= 1; - - handles[a].type= type; - handles[a].actob= actob; - if (R.r.bake_flag & R_BAKE_VCOL) - handles[a].zspan = NULL; - else - handles[a].zspan = MEM_callocN(sizeof(ZSpan), "zspan for bake"); - - handles[a].use_mask = use_mask; - - handles[a].do_update = do_update; /* use to tell the view to update */ - - BLI_insert_thread(&threads, &handles[a]); - } - - /* wait for everything to be done */ - a= 0; - while (a!=re->r.threads) { - PIL_sleep_ms(50); - - /* calculate progress */ - for (vdone = FALSE, a=0; a<re->r.threads; a++) - vdone+= handles[a].vdone; - if (progress) - *progress = (float)(vdone / (float)re->totvlak); - - for (a=0; a<re->r.threads; a++) { - if (handles[a].ready==0) - break; - } - } - - /* filter and refresh images */ - if ((R.r.bake_flag & R_BAKE_VCOL) == 0) { - for (ima = G.main->image.first; ima; ima = ima->id.next) { - if ((ima->id.flag & LIB_DOIT)==0) { - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); - - if (ima->flag & IMA_USED_FOR_RENDER) - result = BAKE_RESULT_FEEDBACK_LOOP; - - if (!ibuf) - continue; - - RE_bake_ibuf_filter(ibuf, (char *)ibuf->userdata, re->r.bake_filter); - - ibuf->userflags |= IB_BITMAPDIRTY; - BKE_image_release_ibuf(ima, ibuf, NULL); - } - } - - /* calculate return value */ - for (a = 0; a < re->r.threads; a++) { - zbuf_free_span(handles[a].zspan); - MEM_freeN(handles[a].zspan); - } - } - - MEM_freeN(handles); - - BLI_end_threads(&threads); - - if (vdone==0) - result= BAKE_RESULT_NO_OBJECTS; - - return result; -} - -struct Image *RE_bake_shade_get_image(void) -{ - return R.bakebuf; -} diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index 7ca4f01ae47..b25f2f4201a 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -1051,7 +1051,7 @@ HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma, } } - externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0); + externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0, re->pool); yn= tin*mtex->colfac; //zn= tin*mtex->alphafac; @@ -1070,6 +1070,8 @@ HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma, } } + har->pool = re->pool; + return har; } @@ -1180,7 +1182,7 @@ HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Mater copy_v3_v3(texvec, orco); } - hasrgb = externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0); + hasrgb = externtex(mtex, texvec, &tin, &tr, &tg, &tb, &ta, 0, re->pool); //yn= tin*mtex->colfac; //zn= tin*mtex->alphafac; @@ -1223,6 +1225,8 @@ HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Mater //} } + har->pool = re->pool; + return har; } diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c index 87912f546e8..1a24055c7f4 100644 --- a/source/blender/render/intern/source/shadbuf.c +++ b/source/blender/render/intern/source/shadbuf.c @@ -38,10 +38,6 @@ #include "DNA_lamp_types.h" #include "DNA_material_types.h" -#include "BKE_global.h" -#include "BKE_scene.h" - - #include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_jitter.h" @@ -49,6 +45,9 @@ #include "BLI_rand.h" #include "BLI_utildefines.h" +#include "BKE_global.h" +#include "BKE_scene.h" + #include "PIL_time.h" #include "renderpipeline.h" diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index db93a21de2d..bf0087d0292 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -151,6 +151,7 @@ void shade_material_loop(ShadeInput *shi, ShadeResult *shr) /* do a shade, finish up some passes, apply mist */ void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr) { + bool compat = false; float alpha; /* ------ main shading loop -------- */ @@ -158,10 +159,11 @@ void shade_input_do_shade(ShadeInput *shi, ShadeResult *shr) memset(&shi->raycounter, 0, sizeof(shi->raycounter)); #endif - if (shi->mat->nodetree && shi->mat->use_nodes) { - ntreeShaderExecTree(shi->mat->nodetree, shi, shr); - } - else { + if (shi->mat->nodetree && shi->mat->use_nodes) + compat = ntreeShaderExecTree(shi->mat->nodetree, shi, shr); + + /* also run this when node shaders fail, due to incompatible shader nodes */ + if (compat == false) { /* copy all relevant material vars, note, keep this synced with render_types.h */ shade_input_init_material(shi); diff --git a/source/blender/rigidbody/CMakeLists.txt b/source/blender/rigidbody/CMakeLists.txt new file mode 100644 index 00000000000..903fbe66f01 --- /dev/null +++ b/source/blender/rigidbody/CMakeLists.txt @@ -0,0 +1,35 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2006, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# ***** END GPL LICENSE BLOCK ***** + +SET(INC + . + ../../../extern/bullet2/src +) + +set(SRC + rb_bullet_api.cpp + + RBI_api.h +) + +blender_add_lib(bf_rigidbody "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/rigidbody/RBI_api.h b/source/blender/rigidbody/RBI_api.h new file mode 100644 index 00000000000..ee5006f2838 --- /dev/null +++ b/source/blender/rigidbody/RBI_api.h @@ -0,0 +1,309 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation, + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joshua Leung, Sergej Reich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file RBI_api.h + * \ingroup RigidBody + * \brief Rigid Body API for interfacing with external Physics Engines + */ + +#ifndef __RB_API_H__ +#define __RB_API_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* API Notes: + * Currently, this API is optimised for Bullet RigidBodies, and doesn't + * take into account other Physics Engines. Some tweaking may be necessary + * to allow other systems to be used, in particular there may be references + * to datatypes that aren't used here... + * + * -- Joshua Leung (22 June 2010) + */ + +/* ********************************** */ +/* Partial Type Defines - Aliases for the type of data we store */ + +// ---------- + +/* Dynamics World */ +typedef struct rbDynamicsWorld rbDynamicsWorld; + +/* Rigid Body */ +typedef struct rbRigidBody rbRigidBody; + +/* Collision Shape */ +typedef struct rbCollisionShape rbCollisionShape; + +/* Mesh Data (for Collision Shapes of Meshes) */ +typedef struct rbMeshData rbMeshData; + +/* Constraint */ +typedef struct rbConstraint rbConstraint; + +/* ********************************** */ +/* Dynamics World Methods */ + +/* Setup ---------------------------- */ + +/* Create a new dynamics world instance */ +// TODO: add args to set the type of constraint solvers, etc. +extern rbDynamicsWorld *RB_dworld_new(const float gravity[3]); + +/* Delete the given dynamics world, and free any extra data it may require */ +extern void RB_dworld_delete(rbDynamicsWorld *world); + +/* Settings ------------------------- */ + +/* Gravity */ +extern void RB_dworld_get_gravity(rbDynamicsWorld *world, float g_out[3]); +extern void RB_dworld_set_gravity(rbDynamicsWorld *world, const float g_in[3]); + +/* Constraint Solver */ +extern void RB_dworld_set_solver_iterations(rbDynamicsWorld *world, int num_solver_iterations); +/* Split Impulse */ +extern void RB_dworld_set_split_impulse(rbDynamicsWorld *world, int split_impulse); + +/* Simulation ----------------------- */ + +/* Step the simulation by the desired amount (in seconds) with extra controls on substep sizes and maximum substeps */ +extern void RB_dworld_step_simulation(rbDynamicsWorld *world, float timeStep, int maxSubSteps, float timeSubStep); + +/* Export -------------------------- */ + +/* Exports the dynamics world to physics simulator's serialisation format */ +void RB_dworld_export(rbDynamicsWorld *world, const char *filename); + +/* ********************************** */ +/* Rigid Body Methods */ + +/* Setup ---------------------------- */ + +/* Add RigidBody to dynamics world */ +extern void RB_dworld_add_body(rbDynamicsWorld *world, rbRigidBody *body, int col_groups); + +/* Remove RigidBody from dynamics world */ +extern void RB_dworld_remove_body(rbDynamicsWorld *world, rbRigidBody *body); + +/* ............ */ + +/* Create new RigidBody instance */ +extern rbRigidBody *RB_body_new(rbCollisionShape *shape, const float loc[3], const float rot[4]); + +/* Delete the given RigidBody instance */ +extern void RB_body_delete(rbRigidBody *body); + +/* Settings ------------------------- */ + +/* 'Type' */ +extern void RB_body_set_type(rbRigidBody *body, int type, float mass); + +/* ............ */ + +/* Collision Shape */ +extern void RB_body_set_collision_shape(rbRigidBody *body, rbCollisionShape *shape); + +/* ............ */ + +/* Mass */ +extern float RB_body_get_mass(rbRigidBody *body); +extern void RB_body_set_mass(rbRigidBody *body, float value); + +/* Friction */ +extern float RB_body_get_friction(rbRigidBody *body); +extern void RB_body_set_friction(rbRigidBody *body, float value); + +/* Restitution */ +extern float RB_body_get_restitution(rbRigidBody *body); +extern void RB_body_set_restitution(rbRigidBody *body, float value); + +/* Damping */ +extern float RB_body_get_linear_damping(rbRigidBody *body); +extern void RB_body_set_linear_damping(rbRigidBody *body, float value); + +extern float RB_body_get_angular_damping(rbRigidBody *body); +extern void RB_body_set_angular_damping(rbRigidBody *body, float value); + +extern void RB_body_set_damping(rbRigidBody *object, float linear, float angular); + +/* Sleeping Thresholds */ +extern float RB_body_get_linear_sleep_thresh(rbRigidBody *body); +extern void RB_body_set_linear_sleep_thresh(rbRigidBody *body, float value); + +extern float RB_body_get_angular_sleep_thresh(rbRigidBody *body); +extern void RB_body_set_angular_sleep_thresh(rbRigidBody *body, float value); + +extern void RB_body_set_sleep_thresh(rbRigidBody *body, float linear, float angular); + +/* Linear Velocity */ +extern void RB_body_get_linear_velocity(rbRigidBody *body, float v_out[3]); +extern void RB_body_set_linear_velocity(rbRigidBody *body, const float v_in[3]); + +/* Angular Velocity */ +extern void RB_body_get_angular_velocity(rbRigidBody *body, float v_out[3]); +extern void RB_body_set_angular_velocity(rbRigidBody *body, const float v_in[3]); + +/* Linear/Angular Factor, used to lock translation/roation axes */ +extern void RB_body_set_linear_factor(rbRigidBody *object, float x, float y, float z); +extern void RB_body_set_angular_factor(rbRigidBody *object, float x, float y, float z); + +/* Kinematic State */ +extern void RB_body_set_kinematic_state(rbRigidBody *body, int kinematic); + +/* RigidBody Interface - Rigid Body Activation States */ +extern int RB_body_get_activation_state(rbRigidBody *body); +extern void RB_body_set_activation_state(rbRigidBody *body, int use_deactivation); +extern void RB_body_activate(rbRigidBody *body); +extern void RB_body_deactivate(rbRigidBody *body); + + +/* Simulation ----------------------- */ + +/* Get current transform matrix of RigidBody to use in Blender (OpenGL format) */ +extern void RB_body_get_transform_matrix(rbRigidBody *body, float m_out[4][4]); + +/* Set RigidBody's location and rotation */ +extern void RB_body_set_loc_rot(rbRigidBody *body, const float loc[3], const float rot[4]); +/* Set RigidBody's local scaling */ +extern void RB_body_set_scale(rbRigidBody *body, const float scale[3]); + +/* ............ */ + +/* Get RigidBody's position as vector */ +void RB_body_get_position(rbRigidBody *body, float v_out[3]); +/* Get RigidBody's orientation as quaternion */ +void RB_body_get_orientation(rbRigidBody *body, float v_out[4]); + +/* ............ */ + +extern void RB_body_apply_central_force(rbRigidBody *body, const float v_in[3]); + +/* ********************************** */ +/* Collision Shape Methods */ + +/* Setup (Standard Shapes) ----------- */ + +extern rbCollisionShape *RB_shape_new_box(float x, float y, float z); +extern rbCollisionShape *RB_shape_new_sphere(float radius); +extern rbCollisionShape *RB_shape_new_capsule(float radius, float height); +extern rbCollisionShape *RB_shape_new_cone(float radius, float height); +extern rbCollisionShape *RB_shape_new_cylinder(float radius, float height); + +/* Setup (Convex Hull) ------------ */ + +extern rbCollisionShape *RB_shape_new_convex_hull(float *verts, int stride, int count, float margin, bool *can_embed); + +/* Setup (Triangle Mesh) ---------- */ + +/* 1 */ +extern rbMeshData *RB_trimesh_data_new(void); +extern void RB_trimesh_add_triangle(rbMeshData *mesh, const float v1[3], const float v2[3], const float v3[3]); +/* 2a - Triangle Meshes */ +extern rbCollisionShape *RB_shape_new_trimesh(rbMeshData *mesh); +/* 2b - GImpact Meshes */ +extern rbCollisionShape *RB_shape_new_gimpact_mesh(rbMeshData *mesh); + + +/* Cleanup --------------------------- */ + +extern void RB_shape_delete(rbCollisionShape *shape); + +/* Settings --------------------------- */ + +/* Collision Margin */ +extern float RB_shape_get_margin(rbCollisionShape *shape); +extern void RB_shape_set_margin(rbCollisionShape *shape, float value); + +/* ********************************** */ +/* Constraints */ + +/* Setup ----------------------------- */ + +/* Add Rigid Body Constraint to simulation world */ +extern void RB_dworld_add_constraint(rbDynamicsWorld *world, rbConstraint *con, int disable_collisions); + +/* Remove Rigid Body Constraint from simulation world */ +extern void RB_dworld_remove_constraint(rbDynamicsWorld *world, rbConstraint *con); + +extern rbConstraint *RB_constraint_new_point(float pivot[3], rbRigidBody *rb1, rbRigidBody *rb2); +extern rbConstraint *RB_constraint_new_fixed(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2); +extern rbConstraint *RB_constraint_new_hinge(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2); +extern rbConstraint *RB_constraint_new_slider(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2); +extern rbConstraint *RB_constraint_new_piston(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2); +extern rbConstraint *RB_constraint_new_6dof(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2); +extern rbConstraint *RB_constraint_new_6dof_spring(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2); + +/* ............ */ + +/* Cleanup --------------------------- */ + +extern void RB_constraint_delete(rbConstraint *con); + +/* Settings --------------------------- */ + +/* Enable or disable constraint */ +extern void RB_constraint_set_enabled(rbConstraint *con, int enabled); + +/* Limits */ +#define RB_LIMIT_LIN_X 0 +#define RB_LIMIT_LIN_Y 1 +#define RB_LIMIT_LIN_Z 2 +#define RB_LIMIT_ANG_X 3 +#define RB_LIMIT_ANG_Y 4 +#define RB_LIMIT_ANG_Z 5 +/* Bullet uses the following convention: + * - lower limit == upper limit -> axis is locked + * - lower limit > upper limit -> axis is free + * - lower limit < upper limit -> axis is limited in given range + */ +extern void RB_constraint_set_limits_hinge(rbConstraint *con, float lower, float upper); +extern void RB_constraint_set_limits_slider(rbConstraint *con, float lower, float upper); +extern void RB_constraint_set_limits_piston(rbConstraint *con, float lin_lower, float lin_upper, float ang_lower, float ang_upper); +extern void RB_constraint_set_limits_6dof(rbConstraint *con, float axis, float lower, float upper); + +/* 6dof spring specific */ +extern void RB_constraint_set_stiffness_6dof_spring(rbConstraint *con, float axis, float stiffness); +extern void RB_constraint_set_damping_6dof_spring(rbConstraint *con, float axis, float damping); +extern void RB_constraint_set_spring_6dof_spring(rbConstraint *con, float axis, int enable); +extern void RB_constraint_set_equilibrium_6dof_spring(rbConstraint *con); + +/* Set number of constraint solver iterations made per step, this overrided world setting + * To use default set it to -1 */ +extern void RB_constraint_set_solver_iterations(rbConstraint *con, int num_solver_iterations); + +/* Set breaking impulse threshold, if constraint shouldn't break it can be set to FLT_MAX */ +extern void RB_constraint_set_breaking_threshold(rbConstraint *con, float threshold); + +/* ********************************** */ + +#ifdef __cplusplus +} +#endif + +#endif /* __RB_API_H__ */ + diff --git a/source/blender/rigidbody/SConscript b/source/blender/rigidbody/SConscript new file mode 100644 index 00000000000..14c80304983 --- /dev/null +++ b/source/blender/rigidbody/SConscript @@ -0,0 +1,42 @@ +#!/usr/bin/python +# $Id: SConscript $ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2010, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): Joshua Leung +# +# ***** END GPL LICENSE BLOCK ***** + +Import('env') + +# XXX: we need a contingency plan for when not compiling with Bullet, +# since this module will always get included... +# This problem will also apply to other engines at a later date too... +sources = env.Glob('*.cpp') + +incs = [ + '.', + '../../../extern/bullet2/src', + ] + +env.BlenderLib('bf_rigidbody', sources=sources, + includes=incs, defines=[], + libtype=['core', 'player'], priority=[180, 30]) diff --git a/source/blender/rigidbody/rb_bullet_api.cpp b/source/blender/rigidbody/rb_bullet_api.cpp new file mode 100644 index 00000000000..c4a4532bad1 --- /dev/null +++ b/source/blender/rigidbody/rb_bullet_api.cpp @@ -0,0 +1,949 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Joshua Leung, Sergej Reich + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file rb_bullet_api.cpp + * \ingroup RigidBody + * \brief Rigid Body API implementation for Bullet + */ + +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/* This file defines the "RigidBody interface" for the + * Bullet Physics Engine. This API is designed to be used + * from C-code in Blender as part of the Rigid Body simulation + * system. + * + * It is based on the Bullet C-API, but is heavily modified to + * give access to more data types and to offer a nicer interface. + * + * -- Joshua Leung, June 2010 + */ + +#include <stdio.h> + +#include "RBI_api.h" + +#include "btBulletDynamicsCommon.h" + +#include "LinearMath/btVector3.h" +#include "LinearMath/btScalar.h" +#include "LinearMath/btMatrix3x3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btConvexHullComputer.h" + +#include "BulletCollision/Gimpact/btGImpactShape.h" +#include "BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h" +#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h" + +struct rbDynamicsWorld { + btDiscreteDynamicsWorld *dynamicsWorld; + btDefaultCollisionConfiguration *collisionConfiguration; + btDispatcher *dispatcher; + btBroadphaseInterface *pairCache; + btConstraintSolver *constraintSolver; + btOverlapFilterCallback *filterCallback; +}; +struct rbRigidBody { + btRigidBody *body; + int col_groups; +}; + +struct rbCollisionShape { + btCollisionShape *cshape; + btTriangleMesh *mesh; +}; + +struct rbFilterCallback : public btOverlapFilterCallback +{ + virtual bool needBroadphaseCollision(btBroadphaseProxy *proxy0, btBroadphaseProxy *proxy1) const + { + rbRigidBody *rb0 = (rbRigidBody *)((btRigidBody *)proxy0->m_clientObject)->getUserPointer(); + rbRigidBody *rb1 = (rbRigidBody *)((btRigidBody *)proxy1->m_clientObject)->getUserPointer(); + + bool collides; + collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0; + collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask); + collides = collides && (rb0->col_groups & rb1->col_groups); + + return collides; + } +}; + +static inline void copy_v3_btvec3(float vec[3], const btVector3 &btvec) +{ + vec[0] = (float)btvec[0]; + vec[1] = (float)btvec[1]; + vec[2] = (float)btvec[2]; +} +static inline void copy_quat_btquat(float quat[3], const btQuaternion &btquat) +{ + quat[0] = btquat.getW(); + quat[1] = btquat.getX(); + quat[2] = btquat.getY(); + quat[3] = btquat.getZ(); +} + +/* ********************************** */ +/* Dynamics World Methods */ + +/* Setup ---------------------------- */ + +rbDynamicsWorld *RB_dworld_new(const float gravity[3]) +{ + rbDynamicsWorld *world = new rbDynamicsWorld; + + /* collision detection/handling */ + world->collisionConfiguration = new btDefaultCollisionConfiguration(); + + world->dispatcher = new btCollisionDispatcher(world->collisionConfiguration); + btGImpactCollisionAlgorithm::registerAlgorithm((btCollisionDispatcher *)world->dispatcher); // XXX: experimental + + world->pairCache = new btDbvtBroadphase(); + + world->filterCallback = new rbFilterCallback(); + world->pairCache->getOverlappingPairCache()->setOverlapFilterCallback(world->filterCallback); + + /* constraint solving */ + world->constraintSolver = new btSequentialImpulseConstraintSolver(); + + /* world */ + world->dynamicsWorld = new btDiscreteDynamicsWorld(world->dispatcher, + world->pairCache, + world->constraintSolver, + world->collisionConfiguration); + + RB_dworld_set_gravity(world, gravity); + + return world; +} + +void RB_dworld_delete(rbDynamicsWorld *world) +{ + /* bullet doesn't like if we free these in a different order */ + delete world->dynamicsWorld; + delete world->constraintSolver; + delete world->pairCache; + delete world->dispatcher; + delete world->collisionConfiguration; + delete world->filterCallback; + delete world; +} + +/* Settings ------------------------- */ + +/* Gravity */ +void RB_dworld_get_gravity(rbDynamicsWorld *world, float g_out[3]) +{ + copy_v3_btvec3(g_out, world->dynamicsWorld->getGravity()); +} + +void RB_dworld_set_gravity(rbDynamicsWorld *world, const float g_in[3]) +{ + world->dynamicsWorld->setGravity(btVector3(g_in[0], g_in[1], g_in[2])); +} + +/* Constraint Solver */ +void RB_dworld_set_solver_iterations(rbDynamicsWorld *world, int num_solver_iterations) +{ + btContactSolverInfo& info = world->dynamicsWorld->getSolverInfo(); + + info.m_numIterations = num_solver_iterations; +} + +/* Split Impulse */ +void RB_dworld_set_split_impulse(rbDynamicsWorld *world, int split_impulse) +{ + btContactSolverInfo& info = world->dynamicsWorld->getSolverInfo(); + + info.m_splitImpulse = split_impulse; +} + +/* Simulation ----------------------- */ + +void RB_dworld_step_simulation(rbDynamicsWorld *world, float timeStep, int maxSubSteps, float timeSubStep) +{ + world->dynamicsWorld->stepSimulation(timeStep, maxSubSteps, timeSubStep); +} + +/* Export -------------------------- */ + +/* Exports entire dynamics world to Bullet's "*.bullet" binary format + * which is similar to Blender's SDNA system... + * < rbDynamicsWorld: dynamics world to write to file + * < filename: assumed to be a valid filename, with .bullet extension + */ +void RB_dworld_export(rbDynamicsWorld *world, const char *filename) +{ + //create a large enough buffer. There is no method to pre-calculate the buffer size yet. + int maxSerializeBufferSize = 1024 * 1024 * 5; + + btDefaultSerializer *serializer = new btDefaultSerializer(maxSerializeBufferSize); + world->dynamicsWorld->serialize(serializer); + + FILE *file = fopen(filename, "wb"); + fwrite(serializer->getBufferPointer(), serializer->getCurrentBufferSize(), 1, file); + fclose(file); +} + +/* ********************************** */ +/* Rigid Body Methods */ + +/* Setup ---------------------------- */ + +void RB_dworld_add_body(rbDynamicsWorld *world, rbRigidBody *object, int col_groups) +{ + btRigidBody *body = object->body; + object->col_groups = col_groups; + + world->dynamicsWorld->addRigidBody(body); +} + +void RB_dworld_remove_body(rbDynamicsWorld *world, rbRigidBody *object) +{ + btRigidBody *body = object->body; + + world->dynamicsWorld->removeRigidBody(body); +} + +/* ............ */ + +rbRigidBody *RB_body_new(rbCollisionShape *shape, const float loc[3], const float rot[4]) +{ + rbRigidBody *object = new rbRigidBody; + /* current transform */ + btTransform trans; + trans.setOrigin(btVector3(loc[0], loc[1], loc[2])); + trans.setRotation(btQuaternion(rot[1], rot[2], rot[3], rot[0])); + + /* create motionstate, which is necessary for interpolation (includes reverse playback) */ + btDefaultMotionState *motionState = new btDefaultMotionState(trans); + + /* make rigidbody */ + btRigidBody::btRigidBodyConstructionInfo rbInfo(1.0f, motionState, shape->cshape); + + object->body = new btRigidBody(rbInfo); + + object->body->setUserPointer(object); + + return object; +} + +void RB_body_delete(rbRigidBody *object) +{ + btRigidBody *body = object->body; + + /* motion state */ + btMotionState *ms = body->getMotionState(); + if (ms) + delete ms; + + /* collision shape is done elsewhere... */ + + /* body itself */ + + /* manually remove constraint refs of the rigid body, normally this happens when removing constraints from the world + * but since we delete everything when the world is rebult, we need to do it manually here */ + for (int i = body->getNumConstraintRefs() - 1; i >= 0; i--) { + btTypedConstraint *con = body->getConstraintRef(i); + body->removeConstraintRef(con); + } + + delete body; + delete object; +} + +/* Settings ------------------------- */ + +void RB_body_set_collision_shape(rbRigidBody *object, rbCollisionShape *shape) +{ + btRigidBody *body = object->body; + + /* set new collision shape */ + body->setCollisionShape(shape->cshape); + + /* recalculate inertia, since that depends on the collision shape... */ + RB_body_set_mass(object, RB_body_get_mass(object)); +} + +/* ............ */ + +float RB_body_get_mass(rbRigidBody *object) +{ + btRigidBody *body = object->body; + + /* there isn't really a mass setting, but rather 'inverse mass' + * which we convert back to mass by taking the reciprocal again + */ + float value = (float)body->getInvMass(); + + if (value) + value = 1.0 / value; + + return value; +} + +void RB_body_set_mass(rbRigidBody *object, float value) +{ + btRigidBody *body = object->body; + btVector3 localInertia(0, 0, 0); + + /* calculate new inertia if non-zero mass */ + if (value) { + btCollisionShape *shape = body->getCollisionShape(); + shape->calculateLocalInertia(value, localInertia); + } + + body->setMassProps(value, localInertia); + body->updateInertiaTensor(); +} + + +float RB_body_get_friction(rbRigidBody *object) +{ + btRigidBody *body = object->body; + return body->getFriction(); +} + +void RB_body_set_friction(rbRigidBody *object, float value) +{ + btRigidBody *body = object->body; + body->setFriction(value); +} + + +float RB_body_get_restitution(rbRigidBody *object) +{ + btRigidBody *body = object->body; + return body->getRestitution(); +} + +void RB_body_set_restitution(rbRigidBody *object, float value) +{ + btRigidBody *body = object->body; + body->setRestitution(value); +} + + +float RB_body_get_linear_damping(rbRigidBody *object) +{ + btRigidBody *body = object->body; + return body->getLinearDamping(); +} + +void RB_body_set_linear_damping(rbRigidBody *object, float value) +{ + RB_body_set_damping(object, value, RB_body_get_linear_damping(object)); +} + +float RB_body_get_angular_damping(rbRigidBody *object) +{ + btRigidBody *body = object->body; + return body->getAngularDamping(); +} + +void RB_body_set_angular_damping(rbRigidBody *object, float value) +{ + RB_body_set_damping(object, RB_body_get_linear_damping(object), value); +} + +void RB_body_set_damping(rbRigidBody *object, float linear, float angular) +{ + btRigidBody *body = object->body; + body->setDamping(linear, angular); +} + + +float RB_body_get_linear_sleep_thresh(rbRigidBody *object) +{ + btRigidBody *body = object->body; + return body->getLinearSleepingThreshold(); +} + +void RB_body_set_linear_sleep_thresh(rbRigidBody *object, float value) +{ + RB_body_set_sleep_thresh(object, value, RB_body_get_angular_sleep_thresh(object)); +} + +float RB_body_get_angular_sleep_thresh(rbRigidBody *object) +{ + btRigidBody *body = object->body; + return body->getAngularSleepingThreshold(); +} + +void RB_body_set_angular_sleep_thresh(rbRigidBody *object, float value) +{ + RB_body_set_sleep_thresh(object, RB_body_get_linear_sleep_thresh(object), value); +} + +void RB_body_set_sleep_thresh(rbRigidBody *object, float linear, float angular) +{ + btRigidBody *body = object->body; + body->setSleepingThresholds(linear, angular); +} + +/* ............ */ + +void RB_body_get_linear_velocity(rbRigidBody *object, float v_out[3]) +{ + btRigidBody *body = object->body; + + copy_v3_btvec3(v_out, body->getLinearVelocity()); +} + +void RB_body_set_linear_velocity(rbRigidBody *object, const float v_in[3]) +{ + btRigidBody *body = object->body; + + body->setLinearVelocity(btVector3(v_in[0], v_in[1], v_in[2])); +} + + +void RB_body_get_angular_velocity(rbRigidBody *object, float v_out[3]) +{ + btRigidBody *body = object->body; + + copy_v3_btvec3(v_out, body->getAngularVelocity()); +} + +void RB_body_set_angular_velocity(rbRigidBody *object, const float v_in[3]) +{ + btRigidBody *body = object->body; + + body->setAngularVelocity(btVector3(v_in[0], v_in[1], v_in[2])); +} + +void RB_body_set_linear_factor(rbRigidBody *object, float x, float y, float z) +{ + btRigidBody *body = object->body; + body->setLinearFactor(btVector3(x, y, z)); +} + +void RB_body_set_angular_factor(rbRigidBody *object, float x, float y, float z) +{ + btRigidBody *body = object->body; + body->setAngularFactor(btVector3(x, y, z)); +} + +/* ............ */ + +void RB_body_set_kinematic_state(rbRigidBody *object, int kinematic) +{ + btRigidBody *body = object->body; + if (kinematic) + body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + else + body->setCollisionFlags(body->getCollisionFlags() & ~btCollisionObject::CF_KINEMATIC_OBJECT); +} + +/* ............ */ + +void RB_body_set_activation_state(rbRigidBody *object, int use_deactivation) +{ + btRigidBody *body = object->body; + if (use_deactivation) + body->forceActivationState(ACTIVE_TAG); + else + body->setActivationState(DISABLE_DEACTIVATION); +} +void RB_body_activate(rbRigidBody *object) +{ + btRigidBody *body = object->body; + body->setActivationState(ACTIVE_TAG); +} +void RB_body_deactivate(rbRigidBody *object) +{ + btRigidBody *body = object->body; + body->setActivationState(ISLAND_SLEEPING); +} + +/* ............ */ + + + +/* Simulation ----------------------- */ + +/* The transform matrices Blender uses are OpenGL-style matrices, + * while Bullet uses the Right-Handed coordinate system style instead. + */ + +void RB_body_get_transform_matrix(rbRigidBody *object, float m_out[4][4]) +{ + btRigidBody *body = object->body; + btMotionState *ms = body->getMotionState(); + + btTransform trans; + ms->getWorldTransform(trans); + + trans.getOpenGLMatrix((btScalar *)m_out); +} + +void RB_body_set_loc_rot(rbRigidBody *object, const float loc[3], const float rot[4]) +{ + btRigidBody *body = object->body; + btMotionState *ms = body->getMotionState(); + + /* set transform matrix */ + btTransform trans; + trans.setOrigin(btVector3(loc[0], loc[1], loc[2])); + trans.setRotation(btQuaternion(rot[1], rot[2], rot[3], rot[0])); + + ms->setWorldTransform(trans); +} + +void RB_body_set_scale(rbRigidBody *object, const float scale[3]) +{ + btRigidBody *body = object->body; + + /* apply scaling factor from matrix above to the collision shape */ + btCollisionShape *cshape = body->getCollisionShape(); + if (cshape) { + cshape->setLocalScaling(btVector3(scale[0], scale[1], scale[2])); + + /* GIimpact shapes have to be updated to take scaling into account */ + if (cshape->getShapeType() == GIMPACT_SHAPE_PROXYTYPE) + ((btGImpactMeshShape *)cshape)->updateBound(); + } +} + +/* ............ */ +/* Read-only state info about status of simulation */ + +void RB_body_get_position(rbRigidBody *object, float v_out[3]) +{ + btRigidBody *body = object->body; + + copy_v3_btvec3(v_out, body->getWorldTransform().getOrigin()); +} + +void RB_body_get_orientation(rbRigidBody *object, float v_out[4]) +{ + btRigidBody *body = object->body; + + copy_quat_btquat(v_out, body->getWorldTransform().getRotation()); +} + +/* ............ */ +/* Overrides for simulation */ + +void RB_body_apply_central_force(rbRigidBody *object, const float v_in[3]) +{ + btRigidBody *body = object->body; + + body->applyCentralForce(btVector3(v_in[0], v_in[1], v_in[2])); +} + +/* ********************************** */ +/* Collision Shape Methods */ + +/* Setup (Standard Shapes) ----------- */ + +rbCollisionShape *RB_shape_new_box(float x, float y, float z) +{ + rbCollisionShape *shape = new rbCollisionShape; + shape->cshape = new btBoxShape(btVector3(x, y, z)); + shape->mesh = NULL; + return shape; +} + +rbCollisionShape *RB_shape_new_sphere(float radius) +{ + rbCollisionShape *shape = new rbCollisionShape; + shape->cshape = new btSphereShape(radius); + shape->mesh = NULL; + return shape; +} + +rbCollisionShape *RB_shape_new_capsule(float radius, float height) +{ + rbCollisionShape *shape = new rbCollisionShape; + shape->cshape = new btCapsuleShapeZ(radius, height); + shape->mesh = NULL; + return shape; +} + +rbCollisionShape *RB_shape_new_cone(float radius, float height) +{ + rbCollisionShape *shape = new rbCollisionShape; + shape->cshape = new btConeShapeZ(radius, height); + shape->mesh = NULL; + return shape; +} + +rbCollisionShape *RB_shape_new_cylinder(float radius, float height) +{ + rbCollisionShape *shape = new rbCollisionShape; + shape->cshape = new btCylinderShapeZ(btVector3(radius, radius, height)); + shape->mesh = NULL; + return shape; +} + +/* Setup (Convex Hull) ------------ */ + +rbCollisionShape *RB_shape_new_convex_hull(float *verts, int stride, int count, float margin, bool *can_embed) +{ + btConvexHullComputer hull_computer = btConvexHullComputer(); + + // try to embed the margin, if that fails don't shrink the hull + if (hull_computer.compute(verts, stride, count, margin, 0.0f) < 0.0f) { + hull_computer.compute(verts, stride, count, 0.0f, 0.0f); + *can_embed = false; + } + + rbCollisionShape *shape = new rbCollisionShape; + btConvexHullShape *hull_shape = new btConvexHullShape(&(hull_computer.vertices[0].getX()), hull_computer.vertices.size()); + + shape->cshape = hull_shape; + shape->mesh = NULL; + return shape; +} + +/* Setup (Triangle Mesh) ---------- */ + +/* Need to call rbTriMeshNewData() followed by rbTriMeshAddTriangle() several times + * to set up the mesh buffer BEFORE calling rbShapeNewTriMesh(). Otherwise, + * we get nasty crashes... + */ + +rbMeshData *RB_trimesh_data_new() +{ + // XXX: welding threshold? + return (rbMeshData *) new btTriangleMesh(true, false); +} + +void RB_trimesh_add_triangle(rbMeshData *mesh, const float v1[3], const float v2[3], const float v3[3]) +{ + btTriangleMesh *meshData = reinterpret_cast<btTriangleMesh*>(mesh); + + /* cast vertices to usable forms for Bt-API */ + btVector3 vtx1((btScalar)v1[0], (btScalar)v1[1], (btScalar)v1[2]); + btVector3 vtx2((btScalar)v2[0], (btScalar)v2[1], (btScalar)v2[2]); + btVector3 vtx3((btScalar)v3[0], (btScalar)v3[1], (btScalar)v3[2]); + + /* add to the mesh + * - remove duplicated verts is enabled + */ + meshData->addTriangle(vtx1, vtx2, vtx3, false); +} + +rbCollisionShape *RB_shape_new_trimesh(rbMeshData *mesh) +{ + rbCollisionShape *shape = new rbCollisionShape; + btTriangleMesh *tmesh = reinterpret_cast<btTriangleMesh*>(mesh); + + /* triangle-mesh we create is a BVH wrapper for triangle mesh data (for faster lookups) */ + // RB_TODO perhaps we need to allow saving out this for performance when rebuilding? + btBvhTriangleMeshShape *unscaledShape = new btBvhTriangleMeshShape(tmesh, true, true); + + shape->cshape = new btScaledBvhTriangleMeshShape(unscaledShape, btVector3(1.0f, 1.0f, 1.0f)); + shape->mesh = tmesh; + return shape; +} + +rbCollisionShape *RB_shape_new_gimpact_mesh(rbMeshData *mesh) +{ + rbCollisionShape *shape = new rbCollisionShape; + /* interpret mesh buffer as btTriangleIndexVertexArray (i.e. an impl of btStridingMeshInterface) */ + btTriangleMesh *tmesh = reinterpret_cast<btTriangleMesh*>(mesh); + + btGImpactMeshShape *gimpactShape = new btGImpactMeshShape(tmesh); + gimpactShape->updateBound(); // TODO: add this to the update collision margin call? + + shape->cshape = gimpactShape; + shape->mesh = tmesh; + return shape; +} + +/* Cleanup --------------------------- */ + +void RB_shape_delete(rbCollisionShape *shape) +{ + if (shape->cshape->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE) { + btBvhTriangleMeshShape *child_shape = ((btScaledBvhTriangleMeshShape *)shape->cshape)->getChildShape(); + if (child_shape) + delete child_shape; + } + if (shape->mesh) + delete shape->mesh; + delete shape->cshape; + delete shape; +} + +/* Settings --------------------------- */ + +float RB_shape_get_margin(rbCollisionShape *shape) +{ + return shape->cshape->getMargin(); +} + +void RB_shape_set_margin(rbCollisionShape *shape, float value) +{ + shape->cshape->setMargin(value); +} + +/* ********************************** */ +/* Constraints */ + +/* Setup ----------------------------- */ + +void RB_dworld_add_constraint(rbDynamicsWorld *world, rbConstraint *con, int disable_collisions) +{ + btTypedConstraint *constraint = reinterpret_cast<btTypedConstraint*>(con); + + world->dynamicsWorld->addConstraint(constraint, disable_collisions); +} + +void RB_dworld_remove_constraint(rbDynamicsWorld *world, rbConstraint *con) +{ + btTypedConstraint *constraint = reinterpret_cast<btTypedConstraint*>(con); + + world->dynamicsWorld->removeConstraint(constraint); +} + +/* ............ */ + +static void make_constraint_transforms(btTransform &transform1, btTransform &transform2, btRigidBody *body1, btRigidBody *body2, float pivot[3], float orn[4]) +{ + btTransform pivot_transform = btTransform(); + pivot_transform.setOrigin(btVector3(pivot[0], pivot[1], pivot[2])); + pivot_transform.setRotation(btQuaternion(orn[1], orn[2], orn[3], orn[0])); + + transform1 = body1->getWorldTransform().inverse() * pivot_transform; + transform2 = body2->getWorldTransform().inverse() * pivot_transform; +} + +rbConstraint *RB_constraint_new_point(float pivot[3], rbRigidBody *rb1, rbRigidBody *rb2) +{ + btRigidBody *body1 = rb1->body; + btRigidBody *body2 = rb2->body; + + btVector3 pivot1 = body1->getWorldTransform().inverse() * btVector3(pivot[0], pivot[1], pivot[2]); + btVector3 pivot2 = body2->getWorldTransform().inverse() * btVector3(pivot[0], pivot[1], pivot[2]); + + btTypedConstraint *con = new btPoint2PointConstraint(*body1, *body2, pivot1, pivot2); + + return (rbConstraint *)con; +} + +rbConstraint *RB_constraint_new_fixed(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2) +{ + btRigidBody *body1 = rb1->body; + btRigidBody *body2 = rb2->body; + btTransform transform1; + btTransform transform2; + + make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn); + + btGeneric6DofConstraint *con = new btGeneric6DofConstraint(*body1, *body2, transform1, transform2, true); + + /* lock all axes */ + for (int i = 0; i < 6; i++) + con->setLimit(i, 0, 0); + + return (rbConstraint *)con; +} + +rbConstraint *RB_constraint_new_hinge(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2) +{ + btRigidBody *body1 = rb1->body; + btRigidBody *body2 = rb2->body; + btTransform transform1; + btTransform transform2; + + make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn); + + btHingeConstraint *con = new btHingeConstraint(*body1, *body2, transform1, transform2); + + return (rbConstraint *)con; +} + +rbConstraint *RB_constraint_new_slider(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2) +{ + btRigidBody *body1 = rb1->body; + btRigidBody *body2 = rb2->body; + btTransform transform1; + btTransform transform2; + + make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn); + + btSliderConstraint *con = new btSliderConstraint(*body1, *body2, transform1, transform2, true); + + return (rbConstraint *)con; +} + +rbConstraint *RB_constraint_new_piston(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2) +{ + btRigidBody *body1 = rb1->body; + btRigidBody *body2 = rb2->body; + btTransform transform1; + btTransform transform2; + + make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn); + + btSliderConstraint *con = new btSliderConstraint(*body1, *body2, transform1, transform2, true); + con->setUpperAngLimit(-1.0f); // unlock rotation axis + + return (rbConstraint *)con; +} + +rbConstraint *RB_constraint_new_6dof(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2) +{ + btRigidBody *body1 = rb1->body; + btRigidBody *body2 = rb2->body; + btTransform transform1; + btTransform transform2; + + make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn); + + btTypedConstraint *con = new btGeneric6DofConstraint(*body1, *body2, transform1, transform2, true); + + return (rbConstraint *)con; +} + +rbConstraint *RB_constraint_new_6dof_spring(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2) +{ + btRigidBody *body1 = rb1->body; + btRigidBody *body2 = rb2->body; + btTransform transform1; + btTransform transform2; + + make_constraint_transforms(transform1, transform2, body1, body2, pivot, orn); + + btTypedConstraint *con = new btGeneric6DofSpringConstraint(*body1, *body2, transform1, transform2, true); + + return (rbConstraint *)con; +} + +/* Cleanup ----------------------------- */ + +void RB_constraint_delete(rbConstraint *con) +{ + btTypedConstraint *constraint = reinterpret_cast<btTypedConstraint*>(con); + delete constraint; +} + +/* Settings ------------------------- */ + +void RB_constraint_set_enabled(rbConstraint *con, int enabled) +{ + btTypedConstraint *constraint = reinterpret_cast<btTypedConstraint*>(con); + + constraint->setEnabled(enabled); +} + +void RB_constraint_set_limits_hinge(rbConstraint *con, float lower, float upper) +{ + btHingeConstraint *constraint = reinterpret_cast<btHingeConstraint*>(con); + + // RB_TODO expose these + float softness = 0.9f; + float bias_factor = 0.3f; + float relaxation_factor = 1.0f; + + constraint->setLimit(lower, upper, softness, bias_factor, relaxation_factor); +} + +void RB_constraint_set_limits_slider(rbConstraint *con, float lower, float upper) +{ + btSliderConstraint *constraint = reinterpret_cast<btSliderConstraint*>(con); + + constraint->setLowerLinLimit(lower); + constraint->setUpperLinLimit(upper); +} + +void RB_constraint_set_limits_piston(rbConstraint *con, float lin_lower, float lin_upper, float ang_lower, float ang_upper) +{ + btSliderConstraint *constraint = reinterpret_cast<btSliderConstraint*>(con); + + constraint->setLowerLinLimit(lin_lower); + constraint->setUpperLinLimit(lin_upper); + constraint->setLowerAngLimit(ang_lower); + constraint->setUpperAngLimit(ang_upper); +} + +void RB_constraint_set_limits_6dof(rbConstraint *con, float axis, float lower, float upper) +{ + btGeneric6DofConstraint *constraint = reinterpret_cast<btGeneric6DofConstraint*>(con); + + constraint->setLimit(axis, lower, upper); +} + +void RB_constraint_set_stiffness_6dof_spring(rbConstraint *con, float axis, float stiffness) +{ + btGeneric6DofSpringConstraint *constraint = reinterpret_cast<btGeneric6DofSpringConstraint*>(con); + + constraint->setStiffness(axis, stiffness); +} + +void RB_constraint_set_damping_6dof_spring(rbConstraint *con, float axis, float damping) +{ + btGeneric6DofSpringConstraint *constraint = reinterpret_cast<btGeneric6DofSpringConstraint*>(con); + + constraint->setDamping(axis, damping); +} + +void RB_constraint_set_spring_6dof_spring(rbConstraint *con, float axis, int enable) +{ + btGeneric6DofSpringConstraint *constraint = reinterpret_cast<btGeneric6DofSpringConstraint*>(con); + + constraint->enableSpring(axis, enable); +} + +void RB_constraint_set_equilibrium_6dof_spring(rbConstraint *con) +{ + btGeneric6DofSpringConstraint *constraint = reinterpret_cast<btGeneric6DofSpringConstraint*>(con); + + constraint->setEquilibriumPoint(); +} + +void RB_constraint_set_solver_iterations(rbConstraint *con, int num_solver_iterations) +{ + btTypedConstraint *constraint = reinterpret_cast<btTypedConstraint*>(con); + + constraint->setOverrideNumSolverIterations(num_solver_iterations); +} + +void RB_constraint_set_breaking_threshold(rbConstraint *con, float threshold) +{ + btTypedConstraint *constraint = reinterpret_cast<btTypedConstraint*>(con); + + constraint->setBreakingImpulseThreshold(threshold); +} + +/* ********************************** */ diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index eb1aad75a88..bea54154e47 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -131,6 +131,7 @@ void *WM_paint_cursor_activate(struct wmWindowManager *wm, void WM_paint_cursor_end(struct wmWindowManager *wm, void *handle); void WM_cursor_warp (struct wmWindow *win, int x, int y); +float WM_cursor_pressure (const struct wmWindow *win); /* event map */ int WM_userdef_event_map(int kmitype); @@ -201,6 +202,7 @@ int WM_operator_confirm_message(struct bContext *C, struct wmOperator *op, con /* operator api */ void WM_operator_free (struct wmOperator *op); void WM_operator_stack_clear(struct wmWindowManager *wm); +void WM_operator_handlers_clear(wmWindowManager *wm, struct wmOperatorType *ot); struct wmOperatorType *WM_operatortype_find(const char *idnamem, int quiet); struct GHashIterator *WM_operatortype_iter(void); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 197d585bff4..942cce1b6dd 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -448,7 +448,10 @@ typedef struct wmEvent { /* keymap item, set by handler (weak?) */ const char *keymap_idname; - + + /* tablet info, only use when the tablet is active */ + struct wmTabletData *tablet_data; + /* custom data */ short custom; /* custom data type, stylus, 6dof, see wm_event_types.h */ short customdatafree; diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index 53e67e91bd2..a01f7301ec2 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -149,6 +149,31 @@ void WM_operator_stack_clear(wmWindowManager *wm) WM_main_add_notifier(NC_WM | ND_HISTORY, NULL); } +/** + * This function is needed in the case when an addon id disabled + * while a modal operator it defined is running. + */ +void WM_operator_handlers_clear(wmWindowManager *wm, wmOperatorType *ot) +{ + wmWindow *win; + for (win = wm->windows.first; win; win = win->next) { + ListBase *lb[2] = {&win->handlers, &win->modalhandlers}; + wmEventHandler *handler; + int i; + + for (i = 0; i < 2; i++) { + for (handler = lb[i]->first; handler; handler = handler->next) { + if (handler->op && handler->op->type == ot) { + /* don't run op->cancel because it needs the context, + * assume whoever unregisters the operator will cleanup */ + handler->flag |= WM_HANDLER_DO_FREE; + WM_operator_free(handler->op); + handler->op = NULL; + } + } + } + } +} /* ************ uiListType handling ************** */ diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c index ebde6407a48..794bfdde114 100644 --- a/source/blender/windowmanager/intern/wm_cursors.c +++ b/source/blender/windowmanager/intern/wm_cursors.c @@ -188,12 +188,26 @@ void WM_cursor_grab_enable(wmWindow *win, int wrap, int hide, int bounds[4]) * It helps not to get a stuck WM when hitting a breakpoint * */ GHOST_TGrabCursorMode mode = GHOST_kGrabNormal; - - if (hide) mode = GHOST_kGrabHide; - else if (wrap) mode = GHOST_kGrabWrap; + float fac = GHOST_GetNativePixelSize(win->ghostwin); + + /* in case pixel coords differ from window/mouse coords */ + if (bounds) { + bounds[0] /= fac; + bounds[1] /= fac; + bounds[2] /= fac; + bounds[3] /= fac; + } + + if (hide) { + mode = GHOST_kGrabHide; + } + else if (wrap) { + mode = GHOST_kGrabWrap; + } if ((G.debug & G_DEBUG) == 0) { - if (win && win->ghostwin) { + if (win->ghostwin) { const GHOST_TabletData *tabletdata = GHOST_GetTabletData(win->ghostwin); + /* Note: There is no tabletdata on Windows if no tablet device is connected. */ if (!tabletdata) GHOST_SetCursorGrab(win->ghostwin, mode, bounds, NULL); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 48cad9e020b..84fee9ff34c 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -84,6 +84,8 @@ # include "RNA_enum_types.h" #endif +static void update_tablet_data(wmWindow *win, wmEvent *event); + static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, PointerRNA *properties, ReportList *reports, short context, short poll_only); @@ -94,6 +96,9 @@ void wm_event_add(wmWindow *win, wmEvent *event_to_add) wmEvent *event = MEM_callocN(sizeof(wmEvent), "wmEvent"); *event = *event_to_add; + + update_tablet_data(win, event); + BLI_addtail(&win->queue, event); } @@ -108,6 +113,11 @@ void wm_event_free(wmEvent *event) MEM_freeN(event->customdata); } } + + if (event->tablet_data) { + MEM_freeN(event->tablet_data); + } + MEM_freeN(event); } @@ -2652,9 +2662,12 @@ static void update_tablet_data(wmWindow *win, wmEvent *event) wmtab->Xtilt = td->Xtilt; wmtab->Ytilt = td->Ytilt; - event->custom = EVT_DATA_TABLET; - event->customdata = wmtab; - event->customdatafree = 1; + event->tablet_data = wmtab; + // printf("%s: using tablet %.5f\n", __func__, wmtab->Pressure); + } + else { + event->tablet_data = NULL; + // printf("%s: not using tablet\n", __func__); } } @@ -2747,6 +2760,24 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi return NULL; } +static bool wm_event_is_double_click(wmEvent *event, wmEvent *event_state) +{ + if ((event->type == event_state->prevtype) && + (event_state->prevval == KM_RELEASE) && + (event->val == KM_PRESS)) + { + if ((ISMOUSE(event->type) == false) || ((ABS(event->x - event_state->prevclickx)) <= 2 && + (ABS(event->y - event_state->prevclicky)) <= 2)) + { + if ((PIL_check_seconds_timer() - event_state->prevclicktime) * 1000 < U.dbl_click_time) { + return true; + } + } + } + + return false; +} + /* windows store own event queues, no bContext here */ /* time is in 1000s of seconds, from ghost */ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int UNUSED(time), void *customdata) @@ -2756,7 +2787,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U /* initialize and copy state (only mouse x y and modifiers) */ event = *evt; - + switch (type) { /* mouse move, also to inactive window (X11 does this) */ case GHOST_kEventCursorMove: @@ -2778,7 +2809,6 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U if (lastevent && lastevent->type == MOUSEMOVE) lastevent->type = INBETWEEN_MOUSEMOVE; - update_tablet_data(win, &event); wm_event_add(win, &event); /* also add to other window if event is there, this makes overdraws disappear nicely */ @@ -2791,7 +2821,6 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U oevent.y = owin->eventstate->y = event.y; oevent.type = MOUSEMOVE; - update_tablet_data(owin, &oevent); wm_event_add(owin, &oevent); } @@ -2823,7 +2852,6 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U event.prevx = event.x - pd->deltaX; event.prevy = event.y - (-pd->deltaY); - update_tablet_data(win, &event); wm_event_add(win, &event); break; } @@ -2868,15 +2896,10 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U } /* double click test */ - if (event.type == evt->prevtype && event.val == KM_PRESS) { - if ((ABS(event.x - evt->prevclickx)) <= 2 && - (ABS(event.y - evt->prevclicky)) <= 2 && - ((PIL_check_seconds_timer() - evt->prevclicktime) * 1000 < U.dbl_click_time)) - { - if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) ) - printf("%s Send double click\n", __func__); - event.val = KM_DBL_CLICK; - } + if (wm_event_is_double_click(&event, evt)) { + if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) ) + printf("%s Send double click\n", __func__); + event.val = KM_DBL_CLICK; } if (event.val == KM_PRESS) { evt->prevclicktime = PIL_check_seconds_timer(); @@ -2894,11 +2917,9 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U oevent.type = event.type; oevent.val = event.val; - update_tablet_data(owin, &oevent); wm_event_add(owin, &oevent); } else { - update_tablet_data(win, &event); wm_event_add(win, &event); } @@ -2982,15 +3003,10 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U /* double click test */ /* if previous event was same type, and previous was release, and now it presses... */ - if (event.type == evt->prevtype && evt->prevval == KM_RELEASE && event.val == KM_PRESS) { - if ((ABS(event.x - evt->prevclickx)) <= 2 && - (ABS(event.y - evt->prevclicky)) <= 2 && - ((PIL_check_seconds_timer() - evt->prevclicktime) * 1000 < U.dbl_click_time)) - { - if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) ) - printf("%s Send double click\n", __func__); - evt->val = event.val = KM_DBL_CLICK; - } + if (wm_event_is_double_click(&event, evt)) { + if (G.debug & (G_DEBUG_HANDLERS | G_DEBUG_EVENTS) ) + printf("%s Send double click\n", __func__); + evt->val = event.val = KM_DBL_CLICK; } /* this case happens on holding a key pressed, it should not generate @@ -3100,4 +3116,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U } +#if 0 + WM_event_print(&event); +#endif } diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 550a9f83cff..2d4e4a5334a 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -306,11 +306,6 @@ static void wm_init_userdef(bContext *C) /* update tempdir from user preferences */ BLI_init_temporary_dir(U.tempdir); - - /* displays with larger native pixels, like Macbook. Used to scale dpi with */ - if (G.background == FALSE) - U.pixelsize = GHOST_GetNativePixelSize(); - if (U.pixelsize == 0) U.pixelsize = 1; BKE_userdef_state(); } diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index b2c3c935553..03a81e944c0 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -69,6 +69,7 @@ #include "BKE_library.h" #include "BKE_global.h" #include "BKE_main.h" +#include "BKE_material.h" #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_screen.h" /* BKE_ST_MAXNAME */ @@ -561,6 +562,7 @@ char *WM_operator_pystring(bContext *C, wmOperatorType *ot, PointerRNA *opptr, i } /* return NULL if no match is found */ +#if 0 static char *wm_prop_pystring_from_context(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index) { @@ -583,7 +585,7 @@ static char *wm_prop_pystring_from_context(bContext *C, PointerRNA *ptr, Propert for (link = lb.first; link; link = link->next) { const char *identifier = link->data; - PointerRNA ctx_item_ptr = {{0}}; // CTX_data_pointer_get(C, identifier); + PointerRNA ctx_item_ptr = {{0}} // CTX_data_pointer_get(C, identifier); // XXX, this isnt working if (ctx_item_ptr.type == NULL) { continue; @@ -624,6 +626,94 @@ static char *wm_prop_pystring_from_context(bContext *C, PointerRNA *ptr, Propert return ret; } +#else + +/* use hard coded checks for now */ +static char *wm_prop_pystring_from_context(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index) +{ + const char *member_id = NULL; + + char *prop_str = NULL; + char *ret = NULL; + + if (ptr->id.data) { + ID *idptr = ptr->id.data; + +#define CTX_TEST_PTR_ID(C, member, idptr) \ + { \ + const char *ctx_member = member; \ + PointerRNA ctx_item_ptr = CTX_data_pointer_get(C, ctx_member); \ + if (ctx_item_ptr.id.data == idptr) { \ + member_id = ctx_member; \ + break; \ + } \ + } (void)0 + +#define CTX_TEST_PTR_ID_CAST(C, member, member_full, cast, idptr) \ + { \ + const char *ctx_member = member; \ + const char *ctx_member_full = member_full; \ + PointerRNA ctx_item_ptr = CTX_data_pointer_get(C, ctx_member); \ + if (ctx_item_ptr.id.data && cast(ctx_item_ptr.id.data) == idptr) { \ + member_id = ctx_member_full; \ + break; \ + } \ + } (void)0 + + switch (GS(idptr->name)) { + case ID_SCE: + { + CTX_TEST_PTR_ID(C, "scene", ptr->id.data); + break; + } + case ID_OB: + { + CTX_TEST_PTR_ID(C, "object", ptr->id.data); + break; + } + /* from rna_Main_objects_new */ + case OB_DATA_SUPPORT_ID_CASE: + { +#define ID_CAST_OBDATA(id_pt) (((Object *)(id_pt))->data) + CTX_TEST_PTR_ID_CAST(C, "object", "object.data", ID_CAST_OBDATA, ptr->id.data); + break; +#undef ID_CAST_OBDATA + } + case ID_MA: + { +#define ID_CAST_OBMATACT(id_pt) (give_current_material(((Object *)id_pt), ((Object *)id_pt)->actcol)) + CTX_TEST_PTR_ID_CAST(C, "object", "object.active_material", ID_CAST_OBMATACT, ptr->id.data); + break; +#undef ID_CAST_OBMATACT + } + case ID_WO: + { +#define ID_CAST_SCENEWORLD(id_pt) (((Scene *)(id_pt))->world) + CTX_TEST_PTR_ID_CAST(C, "scene", "scene.world", ID_CAST_SCENEWORLD, ptr->id.data); + break; +#undef ID_CAST_SCENEWORLD + } + case ID_SCR: + { + CTX_TEST_PTR_ID(C, "screen", ptr->id.data); + break; + } + } + + if (member_id) { + prop_str = RNA_path_struct_property_py(ptr, prop, index); + if (prop_str) { + ret = BLI_sprintfN("bpy.context.%s.%s", member_id, prop_str); + MEM_freeN(prop_str); + } + } +#undef CTX_TEST_PTR_ID +#undef CTX_TEST_PTR_ID_CAST + } + + return ret; +} +#endif char *WM_prop_pystring_assign(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index) { @@ -1589,7 +1679,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar uiItemL(col, "Links", ICON_NONE); uiItemStringO(col, IFACE_("Donations"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/blenderorg/blender-foundation/donation-payment"); uiItemStringO(col, IFACE_("Credits"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/development/credits"); - uiItemStringO(col, IFACE_("Release Log"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/development/release-logs/blender-265"); + uiItemStringO(col, IFACE_("Release Log"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/development/release-logs/blender-266"); uiItemStringO(col, IFACE_("Manual"), ICON_URL, "WM_OT_url_open", "url", "http://wiki.blender.org/index.php/Doc:2.6/Manual"); uiItemStringO(col, IFACE_("Blender Website"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org"); uiItemStringO(col, IFACE_("User Community"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/community/user-community"); diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index 8b387196da7..fd44f4a7169 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -689,7 +689,8 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) break; } case GHOST_kEventWindowActivate: - case GHOST_kEventWindowDeactivate: { + case GHOST_kEventWindowDeactivate: + { g_WS.qual &= ~WS_QUAL_MOUSE; break; } diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c index 1ed9ffb3b6c..20406ac463d 100644 --- a/source/blender/windowmanager/intern/wm_subwindow.c +++ b/source/blender/windowmanager/intern/wm_subwindow.c @@ -255,7 +255,7 @@ void wmSubWindowScissorSet(wmWindow *win, int swinid, rcti *srct) width = BLI_rcti_size_x(&_curswin->winrct) + 1; height = BLI_rcti_size_y(&_curswin->winrct) + 1; glViewport(_curswin->winrct.xmin, _curswin->winrct.ymin, width, height); - + if (srct) { int width = BLI_rcti_size_x(srct) + 1; /* only here */ int height = BLI_rcti_size_y(srct) + 1; @@ -266,11 +266,10 @@ void wmSubWindowScissorSet(wmWindow *win, int swinid, rcti *srct) wmOrtho2(-GLA_PIXEL_OFS, (float)width - GLA_PIXEL_OFS, -GLA_PIXEL_OFS, (float)height - GLA_PIXEL_OFS); glLoadIdentity(); - + glFlush(); } - /* enable the WM versions of opengl calls */ void wmSubWindowSet(wmWindow *win, int swinid) { diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 9e0f8613a1a..44c5693c3e3 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -75,6 +75,11 @@ #include "UI_interface.h" +/* for assert */ +#ifndef NDEBUG +# include "BLI_threads.h" +#endif + /* the global to talk to ghost */ static GHOST_SystemHandle g_system = NULL; @@ -377,7 +382,7 @@ static void wm_window_add_ghostwindow(const char *title, wmWindow *win) /* displays with larger native pixels, like Macbook. Used to scale dpi with */ /* needed here, because it's used before it reads userdef */ - U.pixelsize = GHOST_GetNativePixelSize(); + U.pixelsize = GHOST_GetNativePixelSize(win->ghostwin); BKE_userdef_state(); /* store actual window size in blender window */ @@ -595,12 +600,13 @@ int wm_window_fullscreen_toggle_exec(bContext *C, wmOperator *UNUSED(op)) static void wm_convert_cursor_position(wmWindow *win, int *x, int *y) { - + float fac = GHOST_GetNativePixelSize(win->ghostwin); + GHOST_ScreenToClient(win->ghostwin, *x, *y, x, y); - *x *= GHOST_GetNativePixelSize(); + *x *= fac; *y = (win->sizey - 1) - *y; - *y *= GHOST_GetNativePixelSize(); + *y *= fac; } @@ -661,6 +667,10 @@ void wm_window_make_drawable(bContext *C, wmWindow *win) printf("%s: set drawable %d\n", __func__, win->winid); } GHOST_ActivateWindowDrawingContext(win->ghostwin); + + /* this can change per window */ + U.pixelsize = GHOST_GetNativePixelSize(win->ghostwin); + BKE_userdef_state(); } } @@ -947,6 +957,15 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr break; } + case GHOST_kEventNativeResolutionChange: + // printf("change, pixel size %f\n", GHOST_GetNativePixelSize(win->ghostwin)); + + U.pixelsize = GHOST_GetNativePixelSize(win->ghostwin); + BKE_userdef_state(); + WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL); + WM_event_add_notifier(C, NC_WINDOW | NA_EDITED, NULL); + + break; case GHOST_kEventTrackpad: { GHOST_TEventTrackpadData *pd = data; @@ -1022,8 +1041,12 @@ static int wm_window_timer(const bContext *C) void wm_window_process_events(const bContext *C) { - int hasevent = GHOST_ProcessEvents(g_system, 0); /* 0 is no wait */ - + int hasevent; + + BLI_assert(BLI_thread_is_main()); + + hasevent = GHOST_ProcessEvents(g_system, 0); /* 0 is no wait */ + if (hasevent) GHOST_DispatchEvents(g_system); @@ -1045,7 +1068,9 @@ void wm_window_testbreak(void) { static double ltime = 0; double curtime = PIL_check_seconds_timer(); - + + BLI_assert(BLI_thread_is_main()); + /* only check for breaks every 50 milliseconds * if we get called more often. */ @@ -1289,7 +1314,7 @@ void WM_init_native_pixels(int do_it) void WM_cursor_warp(wmWindow *win, int x, int y) { if (win && win->ghostwin) { - float f = GHOST_GetNativePixelSize(); + float f = GHOST_GetNativePixelSize(win->ghostwin); int oldx = x, oldy = y; x = x / f; @@ -1304,18 +1329,33 @@ void WM_cursor_warp(wmWindow *win, int x, int y) } } +/** + * Get the cursor pressure, in most cases you'll want to use wmTabletData from the event + */ +float WM_cursor_pressure(const struct wmWindow *win) +{ + const GHOST_TabletData *td = GHOST_GetTabletData(win->ghostwin); + /* if there's tablet data from an active tablet device then add it */ + if ((td != NULL) && td->Active != GHOST_kTabletModeNone) { + return td->Pressure; + } + else { + return -1.0f; + } +} + /* support for native pixel size */ /* mac retina opens window in size X, but it has up to 2 x more pixels */ int WM_window_pixels_x(wmWindow *win) { - float f = GHOST_GetNativePixelSize(); + float f = GHOST_GetNativePixelSize(win->ghostwin); return (int)(f * (float)win->sizex); } int WM_window_pixels_y(wmWindow *win) { - float f = GHOST_GetNativePixelSize(); + float f = GHOST_GetNativePixelSize(win->ghostwin); return (int)(f * (float)win->sizey); diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h index 2fbfdc41bce..d12e1d47fa0 100644 --- a/source/blender/windowmanager/wm_event_system.h +++ b/source/blender/windowmanager/wm_event_system.h @@ -45,7 +45,8 @@ struct ARegion; typedef struct wmEventHandler { struct wmEventHandler *next, *prev; - int type, flag; /* type default=0, rest is custom */ + int type; /* WM_HANDLER_DEFAULT, ... */ + int flag; /* WM_HANDLER_BLOCKING, ... */ /* keymap handler */ wmKeyMap *keymap; /* pointer to builtin/custom keymaps */ @@ -72,21 +73,17 @@ typedef struct wmEventHandler { } wmEventHandler; - -/* handler flag */ - /* after this handler all others are ignored */ -#define WM_HANDLER_BLOCKING 1 - /* handler tagged to be freed in wm_handlers_do() */ -#define WM_HANDLER_DO_FREE 2 - - - /* custom types for handlers, for signalling, freeing */ enum { WM_HANDLER_DEFAULT, WM_HANDLER_FILESELECT }; +/* handler flag */ +enum { + WM_HANDLER_BLOCKING = 1, /* after this handler all others are ignored */ + WM_HANDLER_DO_FREE = 2 /* handler tagged to be freed in wm_handlers_do() */ +}; /* wm_event_system.c */ void wm_event_free_all (wmWindow *win); diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index 78a67a31e0f..bc7e7efdcfd 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -39,11 +39,10 @@ #define __WM_EVENT_TYPES_H__ /* customdata type */ -#define EVT_DATA_TABLET 1 -#define EVT_DATA_GESTURE 2 -#define EVT_DATA_TIMER 3 -#define EVT_DATA_LISTBASE 4 -#define EVT_DATA_NDOF_MOTION 5 +#define EVT_DATA_GESTURE 1 +#define EVT_DATA_TIMER 2 +#define EVT_DATA_LISTBASE 3 +#define EVT_DATA_NDOF_MOTION 4 /* tablet active, matches GHOST_TTabletMode */ #define EVT_TABLET_NONE 0 diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt index d606605e8d5..b2a47115630 100644 --- a/source/blenderplayer/CMakeLists.txt +++ b/source/blenderplayer/CMakeLists.txt @@ -95,6 +95,7 @@ endif() bf_rna bf_bmesh bf_blenkernel + bf_rigidbody bf_blenloader ge_blen_routines bf_editor_datafiles diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 71881a99419..dc6f40b9e8a 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -121,6 +121,7 @@ struct wmEvent; struct wmKeyConfig; struct wmKeyMap; struct wmOperator; +struct wmOperatorType; struct wmWindow; struct wmWindowManager; @@ -203,6 +204,7 @@ int WM_operator_props_dialog_popup(struct bContext *C, struct wmOperator *op, in int WM_operator_confirm(struct bContext *C, struct wmOperator *op, struct wmEvent *event) {return 0;} struct MenuType *WM_menutype_find(const char *idname, int quiet) {return (struct MenuType *) NULL;} void WM_operator_stack_clear(struct bContext *C) {} +void WM_operator_handlers_clear(struct bContext *C, struct wmOperatorType *ot) {} void WM_autosave_init(struct bContext *C) {} void WM_jobs_kill_all_except(struct wmWindowManager *wm) {} @@ -341,6 +343,7 @@ void uiLayoutSetEnabled(struct uiLayout *layout, int enabled) {} void uiLayoutSetAlignment(struct uiLayout *layout, int alignment) {} void uiLayoutSetScaleX(struct uiLayout *layout, float scale) {} void uiLayoutSetScaleY(struct uiLayout *layout, float scale) {} +void uiTemplateIconView(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname) {} void ED_base_object_free_and_unlink(struct Scene *scene, struct Base *base) {} void ED_mesh_calc_normals(struct Mesh *me) {} void ED_mesh_geometry_add(struct Mesh *mesh, struct ReportList *reports, int verts, int edges, int faces) {} @@ -533,6 +536,7 @@ void macro_wrapper(struct wmOperatorType *ot, void *userdata) {} int pyrna_id_FromPyObject(struct PyObject *obj, struct ID **id) { return 0; } struct PyObject *pyrna_id_CreatePyObject(struct ID *id) {return NULL; } void BPY_context_update(struct bContext *C) {}; +const char *BPY_app_translations_py_pgettext(const char *msgctxt, const char *msgid) { return msgid; } #ifdef WITH_FREESTYLE /* Freestyle */ diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 7db4b5bfc89..4ac8364aa19 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -985,6 +985,10 @@ endif() list(APPEND BLENDER_SORTED_LIBS bf_intern_locale) endif() + if(WITH_BULLET) + list_insert_after(BLENDER_SORTED_LIBS "bf_blenkernel" "bf_rigidbody") + endif() + if(WITH_BULLET AND NOT WITH_BULLET_SYSTEM) list_insert_after(BLENDER_SORTED_LIBS "ge_logic_ngnetwork" "extern_bullet") endif() diff --git a/source/creator/creator.c b/source/creator/creator.c index 55a24971c61..5aa0ca51a58 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -46,16 +46,19 @@ #else # include <unistd.h> /* getpid */ #endif -/* for backtrace */ -#ifndef WIN32 -# include <execinfo.h> -#endif #ifdef WIN32 # include <Windows.h> # include "utfconv.h" #endif +/* for backtrace */ +#if defined(__linux__) || defined(__APPLE__) +# include <execinfo.h> +#elif defined(_MSV_VER) +# include <DbgHelp.h> +#endif + #include <stdlib.h> #include <stddef.h> #include <string.h> @@ -166,9 +169,10 @@ static int print_version(int argc, const char **argv, void *data); /* for the callbacks: */ -#define BLEND_VERSION_STRING_FMT \ - "Blender %d.%02d (sub %d)\n", \ - BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION \ +#define BLEND_VERSION_FMT "Blender %d.%02d (sub %d)" +#define BLEND_VERSION_ARG BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION +/* pass directly to printf */ +#define BLEND_VERSION_STRING_FMT BLEND_VERSION_FMT "\n", BLEND_VERSION_ARG /* Initialize callbacks for the modules that need them */ static void setCallbacks(void); @@ -448,9 +452,11 @@ static int set_fpe(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(dat return 0; } +#if defined(__linux__) || defined(__APPLE__) + +/* Unix */ static void blender_crash_handler_backtrace(FILE *fp) { -#ifndef WIN32 #define SIZE 100 void *buffer[SIZE]; int nptrs; @@ -469,11 +475,51 @@ static void blender_crash_handler_backtrace(FILE *fp) free(strings); #undef SIZE -#else /* WIN32 */ - /* TODO */ +} + +#elif defined(_MSV_VER) + +static void blender_crash_handler_backtrace(FILE *fp) +{ (void)fp; + +#if 0 +#define MAXSYMBOL 256 + 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%0X\n", nframes - i - 1, symbolinfo->Name, symbolinfo->Address); + } + + MEM_freeN(symbolinfo); #endif } + +#else /* non msvc/osx/linux */ + +static void blender_crash_handler_backtrace(FILE *fp) +{ + (void)fp; +} + +#endif + static void blender_crash_handler(int signum) { @@ -513,14 +559,20 @@ static void blender_crash_handler(int signum) printf("Writing: %s\n", fname); fflush(stdout); - BLI_snprintf(header, sizeof(header), "# " BLEND_VERSION_STRING_FMT); + BLI_snprintf(header, sizeof(header), "# " BLEND_VERSION_FMT ", Revision: %s\n", BLEND_VERSION_ARG, +#ifdef BUILD_DATE + build_rev +#else + "Unknown" +#endif + ); /* open the crash log */ errno = 0; fp = BLI_fopen(fname, "wb"); if (fp == NULL) { fprintf(stderr, "Unable to save '%s': %s\n", - fname, errno ? strerror(errno) : "Unknown error opening file"); + fname, errno ? strerror(errno) : "Unknown error opening file"); } else { if (wm) { @@ -538,8 +590,7 @@ static void blender_crash_handler(int signum) #ifndef WIN32 kill(getpid(), signum); #else - /* force crash on windows for now */ - *((void **)NULL) = NULL; + TerminateProcess(GetCurrentProcess(), signum); #endif } diff --git a/source/gameengine/BlenderRoutines/CMakeLists.txt b/source/gameengine/BlenderRoutines/CMakeLists.txt index d833534605b..32efc5bde21 100644 --- a/source/gameengine/BlenderRoutines/CMakeLists.txt +++ b/source/gameengine/BlenderRoutines/CMakeLists.txt @@ -73,7 +73,7 @@ if(WITH_BULLET) list(APPEND INC_SYS ${BULLET_INCLUDE_DIRS} ) - add_definitions(-DUSE_BULLET) + add_definitions(-DWITH_BULLET) endif() diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 9267b2b9fed..409a3bfec8f 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -164,7 +164,7 @@ extern Material defmaterial; /* material.c */ #include "SG_Tree.h" #include "KX_ConvertPhysicsObject.h" -#ifdef USE_BULLET +#ifdef WITH_BULLET #include "CcdPhysicsEnvironment.h" #include "CcdGraphicController.h" #endif @@ -1526,7 +1526,7 @@ static void BL_CreateGraphicObjectNew(KX_GameObject* gameobj, { switch (physics_engine) { -#ifdef USE_BULLET +#ifdef WITH_BULLET case UseBullet: { CcdPhysicsEnvironment* env = (CcdPhysicsEnvironment*)kxscene->GetPhysicsEnvironment(); @@ -1829,7 +1829,7 @@ static void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, switch (physics_engine) { -#ifdef USE_BULLET +#ifdef WITH_BULLET case UseBullet: KX_ConvertBulletObject(gameobj, meshobj, dm, kxscene, shapeprops, smmaterial, &objprop); break; @@ -1980,7 +1980,7 @@ static KX_GameObject *gameobject_from_blenderobject( bool bHasDvert = mesh->dvert != NULL && ob->defbase.first; bool bHasArmature = (BL_ModifierDeformer::HasArmatureDeformer(ob) && ob->parent && ob->parent->type == OB_ARMATURE && bHasDvert); bool bHasModifier = BL_ModifierDeformer::HasCompatibleDeformer(ob); -#ifdef USE_BULLET +#ifdef WITH_BULLET bool bHasSoftBody = (!ob->parent && (ob->gameflag & OB_SOFT_BODY)); #endif if (bHasModifier) { @@ -2007,7 +2007,7 @@ static KX_GameObject *gameobject_from_blenderobject( BL_MeshDeformer *dcont = new BL_MeshDeformer((BL_DeformableGameObject*)gameobj, ob, meshobj); ((BL_DeformableGameObject*)gameobj)->SetDeformer(dcont); -#ifdef USE_BULLET +#ifdef WITH_BULLET } else if (bHasSoftBody) { KX_SoftBodyDeformer *dcont = new KX_SoftBodyDeformer(meshobj, (BL_DeformableGameObject*)gameobj); ((BL_DeformableGameObject*)gameobj)->SetDeformer(dcont); diff --git a/source/gameengine/Converter/CMakeLists.txt b/source/gameengine/Converter/CMakeLists.txt index 8ac9e523d5d..38c0d71d24d 100644 --- a/source/gameengine/Converter/CMakeLists.txt +++ b/source/gameengine/Converter/CMakeLists.txt @@ -114,7 +114,7 @@ if(WITH_BULLET) list(APPEND INC_SYS ${BULLET_INCLUDE_DIRS} ) - add_definitions(-DUSE_BULLET) + add_definitions(-DWITH_BULLET) endif() if(WITH_AUDASPACE) diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index 5524612f707..376f75959ed 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -55,7 +55,7 @@ #include "KX_ConvertPhysicsObject.h" -#ifdef USE_BULLET +#ifdef WITH_BULLET #include "CcdPhysicsEnvironment.h" #endif @@ -193,7 +193,7 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter() itm++; } -#ifdef USE_BULLET +#ifdef WITH_BULLET KX_ClearBulletSharedShapes(); #endif @@ -254,7 +254,7 @@ Scene *KX_BlenderSceneConverter::GetBlenderSceneForName(const STR_String& name) } #include "KX_PythonInit.h" -#ifdef USE_BULLET +#ifdef WITH_BULLET #include "LinearMath/btIDebugDraw.h" @@ -348,7 +348,7 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene, switch (physics_engine) { -#ifdef USE_BULLET +#ifdef WITH_BULLET case UseBullet: { CcdPhysicsEnvironment* ccdPhysEnv = new CcdPhysicsEnvironment(useDbvtCulling); @@ -398,7 +398,7 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene, //that would result from this is fixed in RemoveScene() m_map_mesh_to_gamemesh.clear(); -#ifndef USE_BULLET +#ifndef WITH_BULLET /* quiet compiler warning */ (void)useDbvtCulling; #endif diff --git a/source/gameengine/Converter/KX_SoftBodyDeformer.cpp b/source/gameengine/Converter/KX_SoftBodyDeformer.cpp index 72d0c8733f2..d860b2ee694 100644 --- a/source/gameengine/Converter/KX_SoftBodyDeformer.cpp +++ b/source/gameengine/Converter/KX_SoftBodyDeformer.cpp @@ -42,7 +42,7 @@ #include "CTR_Map.h" #include "CTR_HashedPtr.h" -#ifdef USE_BULLET +#ifdef WITH_BULLET #include "CcdPhysicsEnvironment.h" #include "CcdPhysicsController.h" diff --git a/source/gameengine/Converter/SConscript b/source/gameengine/Converter/SConscript index 28ad742545e..ef546ce1b19 100644 --- a/source/gameengine/Converter/SConscript +++ b/source/gameengine/Converter/SConscript @@ -64,7 +64,7 @@ if env['WITH_BF_CXX_GUARDEDALLOC']: defs.append('WITH_CXX_GUARDEDALLOC') if env['WITH_BF_BULLET']: - defs.append('USE_BULLET') + defs.append('WITH_BULLET') if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): incs += ' ' + env['BF_PTHREADS_INC'] diff --git a/source/gameengine/Expressions/InputParser.cpp b/source/gameengine/Expressions/InputParser.cpp index 0a5af4a18ea..ed89fb13337 100644 --- a/source/gameengine/Expressions/InputParser.cpp +++ b/source/gameengine/Expressions/InputParser.cpp @@ -260,7 +260,8 @@ void CParser::NextSym() opkind = OPless; } break; - case '\"' : { + case '\"' : + { int start; sym = constsym; constkind = stringtype; @@ -354,7 +355,7 @@ int CParser::MakeInt() } #endif -STR_String CParser::Symbol2Str(int s) +const char *CParser::Symbol2Str(int s) { // returns a string representation of of symbol s, // for use in Term when generating an error @@ -370,18 +371,20 @@ STR_String CParser::Symbol2Str(int s) case whocodedsym: return "WHOMADE"; case eolsym: return "end of line"; case idsym: return "identifier"; - default: return "unknown"; // should not happen } + return "unknown"; // should not happen } void CParser::Term(int s) { // generates an error if the next symbol isn't the specified symbol s // otherwise, skip the symbol - if (s == sym) NextSym(); + if (s == sym) { + NextSym(); + } else { STR_String msg; - msg.Format("Warning: " + Symbol2Str(s) + " expected\ncontinuing without it"); + msg.Format("Warning: %s expected\ncontinuing without it", Symbol2Str(s)); // AfxMessageBox(msg,MB_ICONERROR); @@ -462,7 +465,8 @@ CExpression *CParser::Ex(int i) } else { switch (sym) { - case constsym: { + case constsym: + { switch (constkind) { case booltype: e1 = new CConstExpr(new CBoolValue(boolvalue)); diff --git a/source/gameengine/Expressions/InputParser.h b/source/gameengine/Expressions/InputParser.h index 6dfeff55105..50bb1ae2f6e 100644 --- a/source/gameengine/Expressions/InputParser.h +++ b/source/gameengine/Expressions/InputParser.h @@ -102,7 +102,7 @@ private: #if 0 /* not used yet */ int MakeInt(); #endif - STR_String Symbol2Str(int s); + const char *Symbol2Str(int s); void Term(int s); int Priority(int optor); CExpression *Ex(int i); diff --git a/source/gameengine/Expressions/Operator2Expr.cpp b/source/gameengine/Expressions/Operator2Expr.cpp index d0240b5ec75..b03d00e7f77 100644 --- a/source/gameengine/Expressions/Operator2Expr.cpp +++ b/source/gameengine/Expressions/Operator2Expr.cpp @@ -113,61 +113,61 @@ and m_rhs } -/* +#if 0 bool COperator2Expr::IsInside(float x, float y, float z,bool bBorderInclude) { bool inside; inside = false; - switch (m_op) - { - case VALUE_ADD_OPERATOR: { - // inside = first || second; // optimized with early out if first is inside - // todo: calculate smallest leaf first ! is much faster... - - bool second;//first ;//,second; - - //first = m_lhs->IsInside(x,y,z); - second = m_rhs->IsInside(x,y,z,bBorderInclude); - if (second) - return true; //early out - - // second = m_rhs->IsInside(x,y,z); + switch (m_op) { + case VALUE_ADD_OPERATOR: + { + // inside = first || second; // optimized with early out if first is inside + // todo: calculate smallest leaf first ! is much faster... - return m_lhs->IsInside(x,y,z,bBorderInclude); - - break; - } - - case VALUE_SUB_OPERATOR: { - //inside = first && !second; // optimized with early out - // todo: same as with add_operator: calc smallest leaf first + bool second;//first ;//,second; - bool second;//first ;//,second; - //first = m_lhs->IsInside(x,y,z); - second = m_rhs->IsInside(x,y,z,bBorderInclude); - if (second) - return false; + //first = m_lhs->IsInside(x,y,z); + second = m_rhs->IsInside(x,y,z,bBorderInclude); + if (second) + return true; //early out - // second space get subtracted -> negate! - //second = m_rhs->IsInside(x,y,z); + // second = m_rhs->IsInside(x,y,z); - return (m_lhs->IsInside(x,y,z,bBorderInclude)); + return m_lhs->IsInside(x,y,z,bBorderInclude); - - break; - } - default:{ - assert(false); - // not yet implemented, only add or sub csg operations - } + break; + } + + case VALUE_SUB_OPERATOR: + { + //inside = first && !second; // optimized with early out + // todo: same as with add_operator: calc smallest leaf first + + bool second;//first ;//,second; + //first = m_lhs->IsInside(x,y,z); + second = m_rhs->IsInside(x,y,z,bBorderInclude); + if (second) + return false; + + // second space get subtracted -> negate! + //second = m_rhs->IsInside(x,y,z); + + return (m_lhs->IsInside(x,y,z,bBorderInclude)); + + + break; + } + default: + { + assert(false); + // not yet implemented, only add or sub csg operations + } } return inside; } - - bool COperator2Expr::IsRightInside(float x, float y, float z,bool bBorderInclude) { return m_rhs->IsInside(x,y,z,bBorderInclude); @@ -177,7 +177,8 @@ bool COperator2Expr::IsLeftInside(float x, float y, float z,bool bBorderInclude) { return m_lhs->IsInside(x,y,z,bBorderInclude); } -*/ +#endif + bool COperator2Expr::NeedsRecalculated() { // added some lines, just for debugging purposes, it could be a one-liner :) diff --git a/source/gameengine/GameLogic/SCA_PythonJoystick.cpp b/source/gameengine/GameLogic/SCA_PythonJoystick.cpp index 8c0a0c5ae33..9b24ad7bcf2 100644 --- a/source/gameengine/GameLogic/SCA_PythonJoystick.cpp +++ b/source/gameengine/GameLogic/SCA_PythonJoystick.cpp @@ -46,6 +46,10 @@ m_joystick(joystick) SCA_PythonJoystick::~SCA_PythonJoystick() { + // The joystick reference we got in the constructor was a new instance, + // so we release it here + m_joystick->ReleaseInstance(); + #ifdef WITH_PYTHON PyDict_Clear(m_event_dict); Py_DECREF(m_event_dict); diff --git a/source/gameengine/Ketsji/CMakeLists.txt b/source/gameengine/Ketsji/CMakeLists.txt index e42c2a74a8e..fc322d80cd0 100644 --- a/source/gameengine/Ketsji/CMakeLists.txt +++ b/source/gameengine/Ketsji/CMakeLists.txt @@ -254,7 +254,7 @@ if(WITH_BULLET) list(APPEND INC ${BULLET_INCLUDE_DIRS} ) - add_definitions(-DUSE_BULLET) + add_definitions(-DWITH_BULLET) endif() blender_add_lib(ge_logic_ketsji "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index a55dd701826..231ec27030d 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -400,6 +400,8 @@ KX_BlenderMaterial::ActivatShaders( if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) tmp->setShaderData(true, rasty); + else if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW && IsAlpha() && !rasty->GetUsingOverrideShader()) + tmp->setShaderData(true, rasty); else tmp->setShaderData(false, rasty); @@ -445,6 +447,8 @@ KX_BlenderMaterial::ActivateBlenderShaders( if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) tmp->setBlenderShaderData(true, rasty); + else if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW && IsAlpha() && !rasty->GetUsingOverrideShader()) + tmp->setBlenderShaderData(true, rasty); else tmp->setBlenderShaderData(false, rasty); @@ -494,6 +498,8 @@ KX_BlenderMaterial::ActivateMat( if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) tmp->setTexData( true,rasty ); + else if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW && IsAlpha() && !rasty->GetUsingOverrideShader()) + tmp->setTexData(true, rasty); else tmp->setTexData( false,rasty); @@ -628,7 +634,8 @@ void KX_BlenderMaterial::ActivatGLMaterials( RAS_IRasterizer* rasty )const void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const { - if (ras->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) { + if (ras->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED || + (ras->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW && IsAlpha() && !ras->GetUsingOverrideShader())) { ras->SetAttribNum(0); if (mShader && GLEW_ARB_shader_objects) { if (mShader->GetAttribute() == BL_Shader::SHD_TANGENT) { diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp index 20c41b95dd3..6ef0aed9fe2 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp @@ -4,7 +4,7 @@ //under visual studio the #define in KX_ConvertPhysicsObject.h is quicker for recompilation #include "KX_ConvertPhysicsObject.h" -#ifdef USE_BULLET +#ifdef WITH_BULLET #include "KX_BulletPhysicsController.h" @@ -536,4 +536,4 @@ const char* KX_BulletPhysicsController::getName() return 0; } -#endif // USE_BULLET +#endif // WITH_BULLET diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.h b/source/gameengine/Ketsji/KX_BulletPhysicsController.h index 4813b39a34e..aa42bf61a78 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.h +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.h @@ -8,7 +8,7 @@ #include "KX_IPhysicsController.h" -#ifdef USE_BULLET +#ifdef WITH_BULLET #include "CcdPhysicsController.h" #endif @@ -25,7 +25,7 @@ private: btCollisionShape* m_bulletChildShape; public: -#ifdef USE_BULLET +#ifdef WITH_BULLET KX_BulletPhysicsController (const CcdConstructionInfo& ci, bool dyna, bool sensor, bool character, bool compound); virtual ~KX_BulletPhysicsController (); #endif diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h index e71037d08a0..903966b79be 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h @@ -145,7 +145,7 @@ void KX_ConvertDynamoObject(KX_GameObject* gameobj, struct KX_ObjectProperties* objprop); -#ifdef USE_BULLET +#ifdef WITH_BULLET void KX_ConvertBulletObject( class KX_GameObject* gameobj, class RAS_MeshObject* meshobj, diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index ff3c46cb8ab..4a5a1704979 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -58,7 +58,7 @@ extern "C"{ #include "BKE_DerivedMesh.h" } -#ifdef USE_BULLET +#ifdef WITH_BULLET #include "BulletSoftBody/btSoftBody.h" #include "CcdPhysicsEnvironment.h" @@ -574,4 +574,4 @@ bool KX_ReInstanceBulletShapeFromMesh(KX_GameObject *gameobj, KX_GameObject *fro spc->ReplaceControllerShape(bm); return true; } -#endif // USE_BULLET +#endif // WITH_BULLET diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index eec45669e04..63854c6aebd 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -1777,7 +1777,7 @@ PyObject *KX_GameObject::PyReinstancePhysicsMesh(PyObject *args) ) { return NULL; } -#ifdef USE_BULLET +#ifdef WITH_BULLET /* gameobj and mesh can be NULL */ if (KX_ReInstanceBulletShapeFromMesh(this, gameobj, mesh)) Py_RETURN_TRUE; diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 87683f8b57b..0ddac9c897a 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -1457,15 +1457,14 @@ void KX_KetsjiEngine::RenderDebugProperties() RAS_Rect viewport; m_canvas->SetViewPort(0, 0, int(m_canvas->GetWidth()), int(m_canvas->GetHeight())); - if (m_show_framerate || m_show_profile) { + if (m_show_framerate || m_show_profile) { /* Title for profiling("Profile") */ - debugtxt.Format("Profile"); m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, - debugtxt.Ptr(), - xcoord + const_xindent + title_xmargin, // Adds the constant x indent (0 for now) to the title x margin - ycoord, - m_canvas->GetWidth() /* RdV, TODO ?? */, - m_canvas->GetHeight() /* RdV, TODO ?? */); + "Profile", + xcoord + const_xindent + title_xmargin, // Adds the constant x indent (0 for now) to the title x margin + ycoord, + m_canvas->GetWidth() /* RdV, TODO ?? */, + m_canvas->GetHeight() /* RdV, TODO ?? */); // Increase the indent by default increase ycoord += const_ysize; @@ -1475,35 +1474,31 @@ void KX_KetsjiEngine::RenderDebugProperties() /* Framerate display */ if (m_show_framerate) { - debugtxt.Format("Frametime :"); - m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, - debugtxt.Ptr(), - xcoord + const_xindent, - ycoord, - m_canvas->GetWidth() /* RdV, TODO ?? */, - m_canvas->GetHeight() /* RdV, TODO ?? */); + m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, + "Frametime :", + xcoord + const_xindent, + ycoord, + m_canvas->GetWidth() /* RdV, TODO ?? */, + m_canvas->GetHeight() /* RdV, TODO ?? */); debugtxt.Format("%5.1fms (%5.1f fps)", tottime * 1000.f, 1.0/tottime); - m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, - debugtxt.Ptr(), - xcoord + const_xindent + profile_indent, - ycoord, - m_canvas->GetWidth() /* RdV, TODO ?? */, - m_canvas->GetHeight() /* RdV, TODO ?? */); + m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, + debugtxt.ReadPtr(), + xcoord + const_xindent + profile_indent, + ycoord, + m_canvas->GetWidth() /* RdV, TODO ?? */, + m_canvas->GetHeight() /* RdV, TODO ?? */); // Increase the indent by default increase ycoord += const_ysize; } /* Profile display */ - if (m_show_profile) - { - for (int j = tc_first; j < tc_numCategories; j++) - { - debugtxt.Format(m_profileLabels[j]); + if (m_show_profile) { + for (int j = tc_first; j < tc_numCategories; j++) { m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, - debugtxt.Ptr(), + m_profileLabels[j], xcoord + const_xindent, - ycoord, + ycoord, m_canvas->GetWidth(), m_canvas->GetHeight()); @@ -1511,7 +1506,7 @@ void KX_KetsjiEngine::RenderDebugProperties() debugtxt.Format("%5.2fms (%2d%%)", time*1000.f, (int)(time/tottime * 100.f)); m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, - debugtxt.Ptr(), + debugtxt.ReadPtr(), xcoord + const_xindent + profile_indent, ycoord, m_canvas->GetWidth(), m_canvas->GetHeight()); @@ -1522,17 +1517,15 @@ void KX_KetsjiEngine::RenderDebugProperties() ycoord += title_y_top_margin; /* Property display*/ - if (m_show_debug_properties && m_propertiesPresent) - { + if (m_show_debug_properties && m_propertiesPresent) { /* Title for debugging("Debug properties") */ - debugtxt.Format("Debug Properties"); - m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, - debugtxt.Ptr(), - xcoord + const_xindent + title_xmargin, // Adds the constant x indent (0 for now) to the title x margin - ycoord, - m_canvas->GetWidth() /* RdV, TODO ?? */, - m_canvas->GetHeight() /* RdV, TODO ?? */); + m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, + "Debug Properties", + xcoord + const_xindent + title_xmargin, // Adds the constant x indent (0 for now) to the title x margin + ycoord, + m_canvas->GetWidth() /* RdV, TODO ?? */, + m_canvas->GetHeight() /* RdV, TODO ?? */); // Increase the indent by default increase ycoord += const_ysize; @@ -1540,20 +1533,18 @@ void KX_KetsjiEngine::RenderDebugProperties() ycoord += title_y_bottom_margin; KX_SceneList::iterator sceneit; - for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++) - { + for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++) { KX_Scene* scene = *sceneit; /* the 'normal' debug props */ vector<SCA_DebugProp*>& debugproplist = scene->GetDebugProperties(); for (vector<SCA_DebugProp*>::iterator it = debugproplist.begin(); - !(it==debugproplist.end());it++) + !(it==debugproplist.end());it++) { - CValue* propobj = (*it)->m_obj; + CValue *propobj = (*it)->m_obj; STR_String objname = propobj->GetName(); STR_String propname = (*it)->m_name; - if (propname == "__state__") - { + if (propname == "__state__") { // reserve name for object state KX_GameObject* gameobj = static_cast<KX_GameObject*>(propobj); unsigned int state = gameobj->GetState(); @@ -1571,27 +1562,25 @@ void KX_KetsjiEngine::RenderDebugProperties() first = false; } } - m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, - debugtxt.Ptr(), - xcoord + const_xindent, - ycoord, - m_canvas->GetWidth(), - m_canvas->GetHeight()); + m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, + debugtxt.ReadPtr(), + xcoord + const_xindent, + ycoord, + m_canvas->GetWidth(), + m_canvas->GetHeight()); ycoord += const_ysize; } - else - { - CValue* propval = propobj->GetProperty(propname); - if (propval) - { + else { + CValue *propval = propobj->GetProperty(propname); + if (propval) { STR_String text = propval->GetText(); debugtxt = objname + ": '" + propname + "' = " + text; - m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, - debugtxt.Ptr(), - xcoord + const_xindent, - ycoord, - m_canvas->GetWidth(), - m_canvas->GetHeight()); + m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, + debugtxt.ReadPtr(), + xcoord + const_xindent, + ycoord, + m_canvas->GetWidth(), + m_canvas->GetHeight()); ycoord += const_ysize; } } @@ -1627,19 +1616,14 @@ KX_Scene* KX_KetsjiEngine::FindScene(const STR_String& scenename) void KX_KetsjiEngine::ConvertAndAddScene(const STR_String& scenename,bool overlay) { // only add scene when it doesn't exist! - if (FindScene(scenename)) - { - STR_String tmpname = scenename; - printf("warning: scene %s already exists, not added!\n",tmpname.Ptr()); + if (FindScene(scenename)) { + printf("warning: scene %s already exists, not added!\n",scenename.ReadPtr()); } - else - { - if (overlay) - { + else { + if (overlay) { m_addingOverlayScenes.insert(scenename); } - else - { + else { m_addingBackgroundScenes.insert(scenename); } } diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index 5414a4df0f8..a8f309cc592 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -246,6 +246,9 @@ void KX_LightObject::BindShadowBuffer(RAS_IRasterizer *ras, RAS_ICanvas *canvas, lamp = GetGPULamp(); GPU_lamp_shadow_buffer_bind(lamp, viewmat, &winsize, winmat); + if (GPU_lamp_shadow_buffer_type(lamp) == LA_SHADMAP_VARIANCE) + ras->SetUsingOverrideShader(true); + /* GPU_lamp_shadow_buffer_bind() changes the viewport, so update the canvas */ canvas->UpdateViewPort(0, 0, winsize, winsize); @@ -276,6 +279,9 @@ void KX_LightObject::UnbindShadowBuffer(RAS_IRasterizer *ras) { GPULamp *lamp = GetGPULamp(); GPU_lamp_shadow_buffer_unbind(lamp); + + if (GPU_lamp_shadow_buffer_type(lamp) == LA_SHADMAP_VARIANCE) + ras->SetUsingOverrideShader(false); } struct Image *KX_LightObject::GetTextureImage(short texslot) diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp index 9bb09d56de6..2e9b988dff1 100644 --- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp +++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp @@ -43,7 +43,7 @@ #include "PyObjectPlus.h" -#ifdef USE_BULLET +#ifdef WITH_BULLET # include "LinearMath/btIDebugDraw.h" #endif @@ -716,7 +716,7 @@ PyObject *initPythonConstraintBinding() PyDict_SetItemString(d, "error", ErrorObject); Py_DECREF(ErrorObject); -#ifdef USE_BULLET +#ifdef WITH_BULLET //Debug Modes constants to be used with setDebugMode() python function KX_MACRO_addTypesToDict(d, DBG_NODEBUG, btIDebugDraw::DBG_NoDebug); KX_MACRO_addTypesToDict(d, DBG_DRAWWIREFRAME, btIDebugDraw::DBG_DrawWireframe); @@ -732,7 +732,7 @@ PyObject *initPythonConstraintBinding() KX_MACRO_addTypesToDict(d, DBG_DRAWCONSTRAINTS, btIDebugDraw::DBG_DrawConstraints); KX_MACRO_addTypesToDict(d, DBG_DRAWCONSTRAINTLIMITS, btIDebugDraw::DBG_DrawConstraintLimits); KX_MACRO_addTypesToDict(d, DBG_FASTWIREFRAME, btIDebugDraw::DBG_FastWireframe); -#endif // USE_BULLET +#endif // WITH_BULLET //Constraint types to be used with createConstraint() python function KX_MACRO_addTypesToDict(d, POINTTOPOINT_CONSTRAINT, PHY_POINT2POINT_CONSTRAINT); diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 6b3f745b899..a54d4909db9 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -1428,15 +1428,15 @@ PyObject *initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack PyDict_SetItemString(d, "mouse", gp_PythonMouse->NewProxy(true)); PyObject* joylist = PyList_New(JOYINDEX_MAX); - SCA_JoystickManager* joyevent = (SCA_JoystickManager*)gp_KetsjiScene->GetLogicManager()->FindEventManager(SCA_EventManager::JOY_EVENTMGR); for (int i=0; i<JOYINDEX_MAX; ++i) { - SCA_Joystick* joy = joyevent->GetJoystickDevice(i); + SCA_Joystick* joy = SCA_Joystick::GetInstance(i); if (joy && joy->Connected()) { gp_PythonJoysticks[i] = new SCA_PythonJoystick(joy); PyObject* tmp = gp_PythonJoysticks[i]->NewProxy(true); Py_INCREF(tmp); PyList_SET_ITEM(joylist, i, tmp); } else { + joy->ReleaseInstance(); Py_INCREF(Py_None); PyList_SET_ITEM(joylist, i, Py_None); } diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 55c9ff5307f..bb2f9a8354a 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -88,7 +88,7 @@ #include "BL_DeformableGameObject.h" #include "KX_ObstacleSimulation.h" -#ifdef USE_BULLET +#ifdef WITH_BULLET #include "KX_SoftBodyDeformer.h" #include "KX_ConvertPhysicsObject.h" #include "CcdPhysicsEnvironment.h" @@ -1131,7 +1131,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj, bool use_gfx, bool u blendobj->parent && // original object had armature (not sure this test is needed) blendobj->parent->type == OB_ARMATURE && blendmesh->dvert!=NULL; // mesh has vertex group -#ifdef USE_BULLET +#ifdef WITH_BULLET bool bHasSoftBody = (!parentobj && (blendobj->gameflag & OB_SOFT_BODY)); #endif bool releaseParent = true; @@ -1222,7 +1222,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj, bool use_gfx, bool u ); newobj->SetDeformer(meshdeformer); } -#ifdef USE_BULLET +#ifdef WITH_BULLET else if (bHasSoftBody) { KX_SoftBodyDeformer *softdeformer = new KX_SoftBodyDeformer(mesh, newobj); @@ -1239,7 +1239,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj, bool use_gfx, bool u gameobj->AddMeshUser(); } -#ifdef USE_BULLET +#ifdef WITH_BULLET if (use_phys) { /* update the new assigned mesh with the physics mesh */ KX_ReInstanceBulletShapeFromMesh(gameobj, NULL, use_gfx?NULL:mesh); } @@ -1756,7 +1756,7 @@ short KX_Scene::GetAnimationFPS() return m_blenderScene->r.frs_sec; } -#ifdef USE_BULLET +#ifdef WITH_BULLET #include "KX_BulletPhysicsController.h" #endif @@ -1768,7 +1768,7 @@ static void MergeScene_LogicBrick(SCA_ILogicBrick* brick, KX_Scene *to) brick->Replace_NetworkScene(to->GetNetworkScene()); /* near sensors have physics controllers */ -#ifdef USE_BULLET +#ifdef WITH_BULLET KX_TouchSensor *touch_sensor = dynamic_cast<class KX_TouchSensor *>(brick); if (touch_sensor) { touch_sensor->GetPhysicsController()->SetPhysicsEnvironment(to->GetPhysicsEnvironment()); @@ -1789,7 +1789,7 @@ static void MergeScene_LogicBrick(SCA_ILogicBrick* brick, KX_Scene *to) } } -#ifdef USE_BULLET +#ifdef WITH_BULLET #include "CcdGraphicController.h" // XXX ctrl->SetPhysicsEnvironment(to->GetPhysicsEnvironment()); #include "CcdPhysicsEnvironment.h" // XXX ctrl->SetPhysicsEnvironment(to->GetPhysicsEnvironment()); #include "KX_BulletPhysicsController.h" @@ -1858,7 +1858,7 @@ static void MergeScene_GameObject(KX_GameObject* gameobj, KX_Scene *to, KX_Scene for (int i=0; i<children.size(); i++) children[i]->SetSGClientInfo(to); } -#ifdef USE_BULLET +#ifdef WITH_BULLET SGControllerList::iterator contit; SGControllerList& controllers = sg->GetSGControllerList(); for (contit = controllers.begin();contit!=controllers.end();++contit) @@ -1867,7 +1867,7 @@ static void MergeScene_GameObject(KX_GameObject* gameobj, KX_Scene *to, KX_Scene if (phys_ctrl) phys_ctrl->SetPhysicsEnvironment(to->GetPhysicsEnvironment()); } -#endif // USE_BULLET +#endif // WITH_BULLET } /* If the object is a light, update it's scene */ if (gameobj->GetGameObjectType() == SCA_IObject::OBJ_LIGHT) @@ -1886,7 +1886,7 @@ static void MergeScene_GameObject(KX_GameObject* gameobj, KX_Scene *to, KX_Scene bool KX_Scene::MergeScene(KX_Scene *other) { -#ifdef USE_BULLET +#ifdef WITH_BULLET CcdPhysicsEnvironment *env= dynamic_cast<CcdPhysicsEnvironment *>(this->GetPhysicsEnvironment()); CcdPhysicsEnvironment *env_other= dynamic_cast<CcdPhysicsEnvironment *>(other->GetPhysicsEnvironment()); @@ -1896,7 +1896,7 @@ bool KX_Scene::MergeScene(KX_Scene *other) printf("\tsource %d, terget %d\n", (int)(env!=NULL), (int)(env_other!=NULL)); return false; } -#endif // USE_BULLET +#endif // WITH_BULLET if (GetSceneConverter() != other->GetSceneConverter()) { printf("KX_Scene::MergeScene: converters differ, aborting\n"); @@ -1939,7 +1939,7 @@ bool KX_Scene::MergeScene(KX_Scene *other) GetLightList()->MergeList(other->GetLightList()); other->GetLightList()->ReleaseAndRemoveAll(); -#ifdef USE_BULLET +#ifdef WITH_BULLET if (env) /* bullet scene? - dummy scenes don't need touching */ env->MergeEnvironment(env_other); #endif diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp index 1597948bafe..44a6e2fd7ee 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp +++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp @@ -294,7 +294,7 @@ bool KX_TrackToActuator::Update(double curtime, bool frame) { // (1.0 , 0.0 , 0.0 ) x direction is forward, z (0.0 , 0.0 , 1.0 ) up left = dir.safe_normalized(); - dir = (left.cross(up)).safe_normalized(); + dir = up.cross(left).safe_normalized(); mat.setValue ( left[0], dir[0],up[0], left[1], dir[1],up[1], @@ -334,7 +334,7 @@ bool KX_TrackToActuator::Update(double curtime, bool frame) { // (1.0 , 0.0 , 0.0 ) x direction is forward, z (0.0 , 0.0 , 1.0 ) up left = -dir.safe_normalized(); - dir = -(left.cross(up)).safe_normalized(); + dir = up.cross(left).safe_normalized(); mat.setValue ( left[0], dir[0],up[0], left[1], dir[1],up[1], @@ -373,7 +373,7 @@ bool KX_TrackToActuator::Update(double curtime, bool frame) { // (1.0 , 0.0 , 0.0 ) -x direction is forward, z (0.0 , 0.0 , 1.0 ) up left = -dir.safe_normalized(); - dir = -(left.cross(up)).safe_normalized(); + dir = up.cross(left).safe_normalized(); mat.setValue ( left[0], dir[0],up[0], left[1], dir[1],up[1], diff --git a/source/gameengine/Ketsji/SConscript b/source/gameengine/Ketsji/SConscript index da1a72b4758..0690bdd6538 100644 --- a/source/gameengine/Ketsji/SConscript +++ b/source/gameengine/Ketsji/SConscript @@ -71,7 +71,7 @@ if env['WITH_BF_CXX_GUARDEDALLOC']: defs.append('WITH_CXX_GUARDEDALLOC') if env['WITH_BF_BULLET']: - defs.append('USE_BULLET') + defs.append('WITH_BULLET') incs += ' #source/gameengine/Physics/Bullet' if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): diff --git a/source/gameengine/Physics/Bullet/CMakeLists.txt b/source/gameengine/Physics/Bullet/CMakeLists.txt index afb166eee57..c5b601361d9 100644 --- a/source/gameengine/Physics/Bullet/CMakeLists.txt +++ b/source/gameengine/Physics/Bullet/CMakeLists.txt @@ -62,7 +62,7 @@ if(WITH_BULLET) list(APPEND INC ${BULLET_INCLUDE_DIRS} ) - add_definitions(-DUSE_BULLET) + add_definitions(-DWITH_BULLET) endif() blender_add_lib(ge_phys_bullet "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/gameengine/Physics/Bullet/SConscript b/source/gameengine/Physics/Bullet/SConscript index 83239cf979a..6ef2750e8d6 100644 --- a/source/gameengine/Physics/Bullet/SConscript +++ b/source/gameengine/Physics/Bullet/SConscript @@ -56,6 +56,6 @@ if env['WITH_BF_CXX_GUARDEDALLOC']: defs.append('WITH_CXX_GUARDEDALLOC') if env['WITH_BF_BULLET']: - defs.append('USE_BULLET') + defs.append('WITH_BULLET') env.BlenderLib ( 'ge_phys_bullet', Split(sources), Split(incs), defs, libtype=['core','player'], priority=[350,50], cxx_compileflags=env['BGE_CXXFLAGS']) diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index 5a720857d50..99026fa259a 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -417,6 +417,8 @@ public: virtual void SetAnisotropicFiltering(short level)=0; virtual short GetAnisotropicFiltering()=0; + virtual void SetUsingOverrideShader(bool val)=0; + virtual bool GetUsingOverrideShader()=0; #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("GE:RAS_IRasterizer") diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index a9609a266e8..8c46618ee36 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -93,6 +93,7 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas, int storage) m_noOfScanlines(32), m_motionblur(0), m_motionblurvalue(-1.0), + m_usingoverrideshader(false), m_texco_num(0), m_attrib_num(0), //m_last_alphablend(GPU_BLEND_SOLID), @@ -1057,3 +1058,14 @@ short RAS_OpenGLRasterizer::GetAnisotropicFiltering() { return (short)GPU_get_anisotropic(); } + +void RAS_OpenGLRasterizer::SetUsingOverrideShader(bool val) +{ + m_usingoverrideshader = val; +} + +bool RAS_OpenGLRasterizer::GetUsingOverrideShader() +{ + return m_usingoverrideshader; +} + diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h index c156ee53ed3..5ff2709747d 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h @@ -103,6 +103,8 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer int m_motionblur; float m_motionblurvalue; + bool m_usingoverrideshader; + protected: int m_drawingmode; TexCoGen m_texco[RAS_MAX_TEXCO]; @@ -320,6 +322,8 @@ public: virtual void SetAnisotropicFiltering(short level); virtual short GetAnisotropicFiltering(); + virtual void SetUsingOverrideShader(bool val); + virtual bool GetUsingOverrideShader(); #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("GE:RAS_OpenGLRasterizer") diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp index 8976a21376a..10eef9e0cf2 100644 --- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp +++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp @@ -174,7 +174,7 @@ int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AV if (avformat_open_input(&formatCtx, filename, inputFormat, formatParams)!=0) return -1; - if (av_find_stream_info(formatCtx)<0) + if (avformat_find_stream_info(formatCtx, NULL) < 0) { av_close_input_file(formatCtx); return -1; @@ -209,7 +209,7 @@ int VideoFFmpeg::openStream(const char *filename, AVInputFormat *inputFormat, AV return -1; } codecCtx->workaround_bugs = 1; - if (avcodec_open(codecCtx, codec)<0) + if (avcodec_open2(codecCtx, codec, NULL) < 0) { av_close_input_file(formatCtx); return -1; diff --git a/source/tests/batch_import.py b/source/tests/batch_import.py index 177ab8ea0b0..77595bd091f 100644 --- a/source/tests/batch_import.py +++ b/source/tests/batch_import.py @@ -112,7 +112,7 @@ def batch_import(operator="", for i, f in enumerate(files): print(" %s(filepath=%r) # %d of %d" % (operator, f, i + start, len(files))) - # hack so loading the new file doesnt undo our loaded addons + # hack so loading the new file doesn't undo our loaded addons addon_utils.reset_all = lambda: None # XXX, hack bpy.ops.wm.read_factory_settings() diff --git a/source/tests/bl_load_addons.py b/source/tests/bl_load_addons.py index fab2e2ead11..83bdfb42c95 100644 --- a/source/tests/bl_load_addons.py +++ b/source/tests/bl_load_addons.py @@ -26,6 +26,7 @@ import addon_utils import sys import imp + def disable_addons(): # first disable all addons = bpy.context.user_preferences.addons @@ -86,7 +87,7 @@ def reload_addons(do_reload=True, do_reverse=True): imp.reload(sys.modules[mod_name]) if do_reverse: - # in case order matters when it shouldnt + # in case order matters when it shouldn't modules.reverse() diff --git a/source/tests/bl_load_py_modules.py b/source/tests/bl_load_py_modules.py index b634b4c4385..d65b9605d36 100644 --- a/source/tests/bl_load_py_modules.py +++ b/source/tests/bl_load_py_modules.py @@ -107,7 +107,7 @@ def load_modules(): modules.append(mod_imp) # - # check which filepaths we didnt load + # check which filepaths we didn't load source_files = [] for mod_dir in module_paths: source_files.extend(source_list(mod_dir, filename_check=lambda f: f.endswith(".py"))) diff --git a/source/tests/bl_mesh_modifiers.py b/source/tests/bl_mesh_modifiers.py index 92fae25df16..2f342f2c65e 100644 --- a/source/tests/bl_mesh_modifiers.py +++ b/source/tests/bl_mesh_modifiers.py @@ -34,7 +34,7 @@ USE_QUICK_RENDER = False IS_BMESH = hasattr(__import__("bpy").types, "LoopColors") # ----------------------------------------------------------------------------- -# utility funcs +# utility functions def render_gl(context, filepath, shade): @@ -147,7 +147,7 @@ def ctx_viewport_camera(context): def ctx_camera_setup(context, location=(0.0, 0.0, 0.0), lookat=(0.0, 0.0, 0.0), - # most likely the followuing vars can be left as defaults + # most likely the following vars can be left as defaults up=(0.0, 0.0, 1.0), lookat_axis='-Z', up_axis='Y', @@ -258,7 +258,7 @@ def mesh_uv_add(obj): uv_lay = obj.data.uv_textures.new() if IS_BMESH: - # XXX, odd that we need to do this. until uvs and texface + # XXX, odd that we need to do this. until UV's and texface # are separated we will need to keep it uv_loops = obj.data.uv_layers[-1] uv_list = uv_loops.data[:] diff --git a/source/tests/bl_mesh_validate.py b/source/tests/bl_mesh_validate.py index a57a06d65e3..ac5be7d08d7 100644 --- a/source/tests/bl_mesh_validate.py +++ b/source/tests/bl_mesh_validate.py @@ -98,7 +98,7 @@ def test_meshes(): data.loops.add(len(m[2])) for idx, v in enumerate(m[2]): data.loops[idx].vertex_index = v - # Polys. + # Polygons. data.polygons.add(len(m[3])) for idx, l in enumerate(m[3]): data.polygons[idx].loop_start = l[0] @@ -131,7 +131,7 @@ def test_builtins(): data.loops[l].edge_index = \ random.randrange(0, len(data.edges) * 2) elif rnd == 3: - # Make fun with some poly. + # Make fun with some polygons. p = random.randrange(0, len(data.polygons)) if random.randint(0, 1): data.polygons[p].loop_start = \ diff --git a/source/tests/bl_rst_completeness.py b/source/tests/bl_rst_completeness.py index e9e2779bda8..6e67f8d908d 100644 --- a/source/tests/bl_rst_completeness.py +++ b/source/tests/bl_rst_completeness.py @@ -56,6 +56,7 @@ modules = ( ("gpu.rst", "gpu", False), ) + def is_directive_pydata(filepath, directive): if directive.type in {"function", "method", "class", "attribute", "data"}: return True @@ -113,7 +114,6 @@ def module_validate(filepath, mod, mod_name, doctree, partial_ok): print(directive_to_str(filepath, directive_child), end=" ") print("rst contains non existing class member %r" % attr_id) - # MODULE member missing from RST ??? doctree_dict = directive_members_dict(filepath, doctree) for attr in dir(mod): @@ -136,7 +136,7 @@ def module_validate(filepath, mod, mod_name, doctree, partial_ok): def main(): - + if bge is None: print("Skipping BGE modules!") @@ -151,7 +151,7 @@ def main(): doctree = rst_to_doctree_mini.parse_rst_py(filepath) __import__(modname) mod = sys.modules[modname] - + module_validate(filepath, mod, modname, doctree, partial_ok) diff --git a/source/tests/pep8.py b/source/tests/pep8.py index ccaaeb7c0cd..cb86953e00e 100644 --- a/source/tests/pep8.py +++ b/source/tests/pep8.py @@ -21,20 +21,20 @@ import os # depends on pep8, pyflakes, pylint -# for ubuntu +# for Ubuntu # # sudo apt-get install pylint pyflakes # # sudo apt-get install python-setuptools python-pip # sudo pip install pep8 # -# in debian install pylint pyflakes pep8 with apt-get/aptitude/etc +# in Debian install pylint pyflakes pep8 with apt-get/aptitude/etc # # on *nix run # python source/tests/pep8.py > test_pep8.log 2>&1 # how many lines to read into the file, pep8 comment -# should be directly after the licence header, ~20 in most cases +# should be directly after the license header, ~20 in most cases PEP8_SEEK_COMMENT = 40 SKIP_PREFIX = "./tools", "./config", "./scons", "./extern" FORCE_PEP8_ALL = False @@ -115,7 +115,7 @@ def main(): # let pep8 complain about line length os.system("pylint " "--disable=" - "C0111," # missing docstring + "C0111," # missing doc string "C0103," # invalid name "W0613," # unused argument, may add this back # but happens a lot for 'context' for eg. diff --git a/source/tests/rna_info_dump.py b/source/tests/rna_info_dump.py index 615c3b035ce..40d7b7c38a6 100644 --- a/source/tests/rna_info_dump.py +++ b/source/tests/rna_info_dump.py @@ -18,7 +18,7 @@ # <pep8 compliant> -# Used for generating API diff's between releases +# Used for generating API diffs between releases # ./blender.bin --background -noaudio --python source/tests/rna_info_dump.py import bpy diff --git a/source/tests/rst_to_doctree_mini.py b/source/tests/rst_to_doctree_mini.py index 181037299cf..cb7b0291296 100644 --- a/source/tests/rst_to_doctree_mini.py +++ b/source/tests/rst_to_doctree_mini.py @@ -45,7 +45,7 @@ def parse_rst_py(filepath): # --> # ("foo", "bar") re_prefix = re.compile(r"^\.\.\s([a-zA-Z09\-]+)::\s*(.*)\s*$") - + tree = collections.defaultdict(list) indent_map = {} indent_prev = 0 |