diff options
Diffstat (limited to 'source')
363 files changed, 9849 insertions, 7148 deletions
diff --git a/source/blender/avi/intern/avi_rgb.c b/source/blender/avi/intern/avi_rgb.c index 11d9bdf8612..c6a78eccce2 100644 --- a/source/blender/avi/intern/avi_rgb.c +++ b/source/blender/avi/intern/avi_rgb.c @@ -98,7 +98,7 @@ void *avi_converter_from_avi_rgb(AviMovie *movie, int stream, unsigned char *buf buf = MEM_mallocN(movie->header->Height * movie->header->Width * 3, "fromavirgbbuf"); rowstride = movie->header->Width * 3; - if (bits != 16) if (movie->header->Width % 2) rowstride++; + if ((bits != 16) && (movie->header->Width % 2)) rowstride++; for (y = 0; y < movie->header->Height; y++) { memcpy(&buf[y * movie->header->Width * 3], &buffer[((movie->header->Height - 1) - y) * rowstride], movie->header->Width * 3); diff --git a/source/blender/blenfont/BLF_translation.h b/source/blender/blenfont/BLF_translation.h index b01ce93cb65..159d4b067b6 100644 --- a/source/blender/blenfont/BLF_translation.h +++ b/source/blender/blenfont/BLF_translation.h @@ -35,16 +35,6 @@ #define TEXT_DOMAIN_NAME "blender" -/* blf_translation.c */ - -#ifdef WITH_INTERNATIONAL -unsigned char *BLF_get_unifont(int *unifont_size); -void BLF_free_unifont(void); -#endif - -const char *BLF_gettext(const char *msgid); -const char *BLF_pgettext(const char *context, const char *message); - /* blf_lang.c */ /* Search the path directory to the locale files, this try all @@ -61,22 +51,29 @@ void BLF_lang_set(const char *); /* Get the current locale (short code, e.g. es_ES). */ const char *BLF_lang_get(void); -/* Set the current encoding name. */ -void BLF_lang_encoding(const char *str); - /* 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); -const char *BLF_translate_do_iface(const char *contex, const char *msgid); -const char *BLF_translate_do_tooltip(const char *contex, const char *msgid); +const char *BLF_translate_do_iface(const char *msgctxt, const char *msgid); +const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid); /* The "translation-marker" macro. */ #define N_(msgid) msgid #define CTX_N_(context, msgid) msgid + /* Those macros should be used everywhere in UI code. */ #ifdef WITH_INTERNATIONAL /* #define _(msgid) BLF_gettext(msgid) */ @@ -88,10 +85,17 @@ const char *BLF_translate_do_tooltip(const char *contex, const char *msgid); /* #define _(msgid) msgid */ #define IFACE_(msgid) msgid #define TIP_(msgid) msgid - #define CTX_IFACE_(context, msgid) msgid - #define CTX_TIP_(context, msgid) msgid + #define CTX_IFACE_(context, msgid) ((void)context, msgid) + #define CTX_TIP_(context, msgid) ((void)context, msgid) #endif +/* Helper macro, when we want to define a same msgid for multiple msgctxt... + * Does nothing in C, but is "parsed" by our i18n py tools. + * XXX Currently limited to at most 16 contexts at most + * (but you can call it several times with the same msgid, should you need more contexts!). + */ +#define BLF_I18N_MSGID_MULTI_CTXT(msgid, ...) + /****************************************************************************** * All i18n contexts must be defined here. * This is a nice way to be sure not to use a context twice for different @@ -104,8 +108,39 @@ const char *BLF_translate_do_tooltip(const char *contex, const char *msgid); /* Default context for operator names/labels. */ #define BLF_I18NCONTEXT_OPERATOR_DEFAULT "Operator" -/* Audio disambiguation context. */ -#define BLF_I18NCONTEXT_AUDIO "Audio" - +/* ID-types contexts. */ +/* WARNING! Keep it in sync with idtypes in blenkernel/intern/idcode.c */ +#define BLF_I18NCONTEXT_ID_ACTION "Action" +#define BLF_I18NCONTEXT_ID_ARMATURE "Armature" +#define BLF_I18NCONTEXT_ID_BRUSH "Brush" +#define BLF_I18NCONTEXT_ID_CAMERA "Camera" +#define BLF_I18NCONTEXT_ID_CURVE "Curve" +#define BLF_I18NCONTEXT_ID_GPENCIL "GPencil" +#define BLF_I18NCONTEXT_ID_GROUP "Group" +#define BLF_I18NCONTEXT_ID_ID "ID" +#define BLF_I18NCONTEXT_ID_IMAGE "Image" +/*#define BLF_I18NCONTEXT_ID_IPO "Ipo"*/ /* Deprecated */ +#define BLF_I18NCONTEXT_ID_SHAPEKEY "Key" +#define BLF_I18NCONTEXT_ID_LAMP "Lamp" +#define BLF_I18NCONTEXT_ID_LIBRARY "Library" +#define BLF_I18NCONTEXT_ID_LATTICE "Lattice" +#define BLF_I18NCONTEXT_ID_MATERIAL "Material" +#define BLF_I18NCONTEXT_ID_METABALL "Metaball" +#define BLF_I18NCONTEXT_ID_MESH "Mesh" +#define BLF_I18NCONTEXT_ID_NODETREE "NodeTree" +#define BLF_I18NCONTEXT_ID_OBJECT "Object" +#define BLF_I18NCONTEXT_ID_PARTICLESETTINGS "ParticleSettings" +#define BLF_I18NCONTEXT_ID_SCENE "Scene" +#define BLF_I18NCONTEXT_ID_SCREEN "Screen" +#define BLF_I18NCONTEXT_ID_SEQUENCE "Sequence" +#define BLF_I18NCONTEXT_ID_SPEAKER "Speaker" +#define BLF_I18NCONTEXT_ID_SOUND "Sound" +#define BLF_I18NCONTEXT_ID_TEXTURE "Texture" +#define BLF_I18NCONTEXT_ID_TEXT "Text" +#define BLF_I18NCONTEXT_ID_VFONT "VFont" +#define BLF_I18NCONTEXT_ID_WORLD "World" +#define BLF_I18NCONTEXT_ID_WINDOWMANAGER "WindowManager" +#define BLF_I18NCONTEXT_ID_MOVIECLIP "MovieClip" +#define BLF_I18NCONTEXT_ID_MASK "Mask" #endif /* __BLF_TRANSLATION_H__ */ diff --git a/source/blender/blenfont/CMakeLists.txt b/source/blender/blenfont/CMakeLists.txt index 40d5d6c75f2..6daa879db0f 100644 --- a/source/blender/blenfont/CMakeLists.txt +++ b/source/blender/blenfont/CMakeLists.txt @@ -31,6 +31,7 @@ set(INC ../makesrna ../imbuf ../../../intern/guardedalloc + ../../../intern/locale ../gpu ) @@ -55,9 +56,6 @@ set(SRC ) if(WITH_INTERNATIONAL) - list(APPEND INC_SYS - ${GETTEXT_INCLUDE_DIRS} - ) add_definitions(-DWITH_INTERNATIONAL) endif() diff --git a/source/blender/blenfont/SConscript b/source/blender/blenfont/SConscript index 9971adb885b..aaf5f3c0f08 100644 --- a/source/blender/blenfont/SConscript +++ b/source/blender/blenfont/SConscript @@ -4,11 +4,10 @@ Import ('env') sources = env.Glob('intern/*.c') -incs = '. intern #/intern/guardedalloc ../blenkernel ../blenlib ../blenloader' +incs = '. intern #/intern/guardedalloc #/intern/locale ../blenkernel ../blenlib ../blenloader' incs += ' ../makesdna ../makesrna ../imbuf ../editors/include ../gpu' incs += ' #/extern/glew/include' incs += ' ' + env['BF_FREETYPE_INC'] -incs += ' ' + env['BF_GETTEXT_INC'] defs = ['GLEW_STATIC'] diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c index 27db65f87ac..c77118deb45 100644 --- a/source/blender/blenfont/intern/blf.c +++ b/source/blender/blenfont/intern/blf.c @@ -28,7 +28,6 @@ * \ingroup blf */ - #include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/source/blender/blenfont/intern/blf_lang.c b/source/blender/blenfont/intern/blf_lang.c index f02d4a25554..0ed48623dd5 100644 --- a/source/blender/blenfont/intern/blf_lang.c +++ b/source/blender/blenfont/intern/blf_lang.c @@ -28,20 +28,17 @@ */ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "BKE_global.h" - -#include "BLF_api.h" #include "BLF_translation.h" /* own include */ #ifdef WITH_INTERNATIONAL -#include <locale.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> -#include "libintl.h" +#include "boost_locale_wrapper.h" + +#include "BKE_global.h" #include "DNA_userdef_types.h" @@ -49,30 +46,20 @@ #include "MEM_guardedalloc.h" -#include "BLI_string.h" -#include "BLI_utildefines.h" -#include "BLI_path_util.h" #include "BLI_fileops.h" #include "BLI_linklist.h" +#include "BLI_path_util.h" #include "BLI_string.h" - -#define SYSTEM_ENCODING_DEFAULT "UTF-8" -#define FONT_SIZE_DEFAULT 12 +#include "BLI_utildefines.h" /* Locale options. */ -static char global_messagepath[1024]; -static char global_language[32]; -static char global_encoding_name[32]; - static const char **locales = NULL; -static char **long_locales = NULL; /* XXX Temp fix until we get a final solution with modern intl lib under windows! */ 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] : "") -#define LONG_LOCALE(_id) (long_locales ? long_locales[_id] : "") static void free_locales(void) { @@ -84,17 +71,8 @@ static void free_locales(void) MEM_freeN((void *)locales_menu[idx].description); /* Also frees locales's relevant value! */ } - idx = num_locales; - while (idx--) { - if (long_locales[idx]) { - MEM_freeN(long_locales[idx]); - } - } - MEM_freeN(locales); locales = NULL; - MEM_freeN(long_locales); - long_locales = NULL; } if (locales_menu) { MEM_freeN(locales_menu); @@ -140,7 +118,6 @@ static void fill_locales(void) /* Do not allocate locales with zero-sized mem, as LOCALE macro uses NULL locales as invalid marker! */ if (num_locales > 0) { locales = MEM_callocN(num_locales * sizeof(char*), __func__); - long_locales = MEM_callocN(num_locales * sizeof(char*), __func__); while (line) { int id; char *loc, *sep1, *sep2, *sep3; @@ -163,26 +140,28 @@ static void fill_locales(void) sep2++; sep3 = strchr(sep2, ':'); + if (sep3) { locales_menu[idx].identifier = loc = BLI_strdupn(sep2, sep3 - sep2); + } + else { + locales_menu[idx].identifier = loc = BLI_strdup(sep2); + } - if (id == 0) { - /* The DEFAULT item... */ - if (BLI_strnlen(loc, 2)) { - locales[id] = locales_menu[idx].description = BLI_strdup(""); - long_locales[id] = BLI_strdup(""); - } - /* Menu "label", not to be stored in locales! */ - else { - locales_menu[idx].description = BLI_strdup(""); - } + if (id == 0) { + /* The DEFAULT item... */ + if (BLI_strnlen(loc, 2)) { + locales[id] = locales_menu[idx].description = BLI_strdup(""); } + /* Menu "label", not to be stored in locales! */ else { - locales[id] = locales_menu[idx].description = BLI_strdup(loc); - long_locales[id] = BLI_strdup(sep3 + 1); + locales_menu[idx].description = BLI_strdup(""); } - idx++; } + else { + locales[id] = locales_menu[idx].description = BLI_strdup(loc); + } + idx++; } } @@ -207,15 +186,12 @@ void BLF_lang_init(void) { char *messagepath = BLI_get_folder(BLENDER_DATAFILES, "locale"); - BLI_strncpy(global_encoding_name, SYSTEM_ENCODING_DEFAULT, sizeof(global_encoding_name)); - if (messagepath) { - BLI_strncpy(global_messagepath, messagepath, sizeof(global_messagepath)); + bl_locale_init(messagepath, TEXT_DOMAIN_NAME); fill_locales(); } else { printf("%s: 'locale' data path for translations not found, continuing\n", __func__); - global_messagepath[0] = '\0'; } } @@ -224,159 +200,37 @@ void BLF_lang_free(void) free_locales(); } -/* Get LANG/LANGUAGE environment variable. */ -static void get_language_variable(const char *varname, char *var, const size_t maxlen) -{ - char *env = getenv(varname); - - if (env) { - char *s; - - /* Store defaul locale. */ - BLI_strncpy(var, env, maxlen); - - /* Use first language as default. */ - s = strchr(var, ':'); - if (s) - s[0] = 0; - } -} - -/* Get language to be used based on locale (which might be empty when using default language) and - * LANG environment variable. - */ -static void get_language(const char *locale, const char *lang, char *language, const size_t maxlen) -{ - if (locale[0]) { - BLI_strncpy(language, locale, maxlen); - } - else { - char *s; - - BLI_strncpy(language, lang, maxlen); - - s = strchr(language, '.'); - if (s) - s[0] = 0; - } -} - -/* XXX WARNING!!! In osx somehow the previous function call jumps in this one??? (ton, ppc) */ void BLF_lang_set(const char *str) { - char *locreturn; - int ok = TRUE; int ulang = ULANGUAGE; + const char *short_locale = str ? str : LOCALE(ulang); + const char *short_locale_utf8 = NULL; if ((U.transopts & USER_DOTRANSLATE) == 0) return; -#if defined(_WIN32) && !defined(FREE_WINDOWS) - { - const char *long_locale = str ? str : LONG_LOCALE(ulang); - if (long_locale) { - char *envStr; - - if (ulang) - envStr = BLI_sprintfN("LANG=%s", long_locale); - else /* Use system setting. */ - envStr = BLI_sprintfN("LANG=%s", getenv("LANG")); - - gettext_putenv(envStr); - MEM_freeN(envStr); - } - - locreturn = setlocale(LC_ALL, long_locale); - - if (locreturn == NULL) { - if (G.debug & G_DEBUG) - printf("Could not change locale to %s\n", long_locale); - - ok = FALSE; - } - } -#else - { - const char *short_locale = str ? str : LOCALE(ulang); - static char default_lang[64] = "\0"; - static char default_language[64] = "\0"; - - if (default_lang[0] == 0) - get_language_variable("LANG", default_lang, sizeof(default_lang)); - - if (default_language[0] == 0) - get_language_variable("LANGUAGE", default_language, sizeof(default_language)); - - if (short_locale[0]) { - char *short_locale_utf8 = BLI_sprintfN("%s.UTF-8", short_locale); - - if (G.debug & G_DEBUG) - printf("Setting LANG and LANGUAGE to %s\n", short_locale_utf8); - - locreturn = setlocale(LC_ALL, short_locale_utf8); - - if (locreturn != NULL) { - BLI_setenv("LANG", short_locale_utf8); - BLI_setenv("LANGUAGE", short_locale_utf8); - } - else { - if (G.debug & G_DEBUG) - printf("Setting LANG and LANGUAGE to %s\n", short_locale); - - locreturn = setlocale(LC_ALL, short_locale); - - if (locreturn != NULL) { - BLI_setenv("LANG", short_locale); - BLI_setenv("LANGUAGE", short_locale); - } - } - - if (G.debug & G_DEBUG && locreturn == NULL) - printf("Could not change locale to %s nor %s\n", short_locale, short_locale_utf8); - - MEM_freeN(short_locale_utf8); + /* We want to avoid locales like '.UTF-8'! */ + if (short_locale[0]) { + /* Hurrey! encoding needs to be placed *before* variant! */ + char *variant = strchr(short_locale, '@'); + if (variant) { + char *locale = BLI_strdupn(short_locale, variant - short_locale); + short_locale_utf8 = BLI_sprintfN("%s.UTF-8%s", locale, variant); + MEM_freeN(locale); } else { - if (G.debug & G_DEBUG) - printf("Setting LANG=%s and LANGUAGE=%s\n", default_lang, default_language); - - BLI_setenv("LANG", default_lang); - BLI_setenv("LANGUAGE", default_language); - locreturn = setlocale(LC_ALL, ""); - - if (G.debug & G_DEBUG && locreturn == NULL) - printf("Could not reset locale\n"); - } - - if (locreturn == NULL) { - char language[65]; - - get_language(short_locale, default_lang, language, sizeof(language)); - - if (G.debug & G_DEBUG) - printf("Fallback to LANG=%s and LANGUAGE=%s\n", default_lang, language); - - /* Fallback to default settings. */ - BLI_setenv("LANG", default_lang); - BLI_setenv("LANGUAGE", language); - - locreturn = setlocale(LC_ALL, ""); - - ok = FALSE; + short_locale_utf8 = BLI_sprintfN("%s.UTF-8", short_locale); } } -#endif - - if (ok) { - /*printf("Change locale to %s\n", locreturn ); */ - BLI_strncpy(global_language, locreturn, sizeof(global_language)); + else { + short_locale_utf8 = short_locale; } - setlocale(LC_NUMERIC, "C"); + bl_locale_set(short_locale_utf8); - textdomain(TEXT_DOMAIN_NAME); - bindtextdomain(TEXT_DOMAIN_NAME, global_messagepath); - bind_textdomain_codeset(TEXT_DOMAIN_NAME, global_encoding_name); + if (short_locale[0]) { + MEM_freeN((void*)short_locale_utf8); + } } const char *BLF_lang_get(void) @@ -385,12 +239,6 @@ const char *BLF_lang_get(void) return LOCALE(uilang); } -void BLF_lang_encoding(const char *str) -{ - BLI_strncpy(global_encoding_name, str, sizeof(global_encoding_name)); - /* bind_textdomain_codeset(TEXT_DOMAIN_NAME, encoding_name); */ -} - #undef LOCALE #undef ULANGUAGE @@ -406,12 +254,6 @@ void BLF_lang_free(void) return; } -void BLF_lang_encoding(const char *str) -{ - (void)str; - return; -} - void BLF_lang_set(const char *str) { (void)str; diff --git a/source/blender/blenfont/intern/blf_translation.c b/source/blender/blenfont/intern/blf_translation.c index 9c863da9eba..5d4b631688a 100644 --- a/source/blender/blenfont/intern/blf_translation.c +++ b/source/blender/blenfont/intern/blf_translation.c @@ -31,18 +31,11 @@ #include <stdlib.h> #include <string.h> -#ifdef WITH_INTERNATIONAL -#include <libintl.h> -#include <locale.h> - -#define GETTEXT_CONTEXT_GLUE "\004" +#include "BLF_translation.h" -/* needed for windows version of gettext */ -#ifndef LC_MESSAGES -# define LC_MESSAGES 1729 -#endif +#ifdef WITH_INTERNATIONAL -#endif +#include "boost_locale_wrapper.h" #include "MEM_guardedalloc.h" @@ -52,11 +45,8 @@ #include "BLI_path_util.h" #include "BLI_fileops.h" -#include "BLF_translation.h" - #include "DNA_userdef_types.h" /* For user settings. */ -#ifdef WITH_INTERNATIONAL static const char unifont_filename[] = "droidsans.ttf.gz"; static unsigned char *unifont_ttf = NULL; static int unifont_size = 0; @@ -90,55 +80,19 @@ void BLF_free_unifont(void) #endif -const char *BLF_gettext(const char *msgid) +const char *BLF_pgettext(const char *msgctxt, const char *msgid) { #ifdef WITH_INTERNATIONAL - if (msgid && msgid[0]) - return gettext(msgid); + if (msgid && msgid[0]) { + return bl_locale_pgettext(msgctxt, msgid); + } return ""; #else + (void)msgctxt; return msgid; #endif } -const char *BLF_pgettext(const char *context, const char *message) -{ -#ifdef WITH_INTERNATIONAL - char static_msg_ctxt_id[1024]; - char *dynamic_msg_ctxt_id = NULL; - char *msg_ctxt_id; - const char *translation; - - size_t overall_length = strlen(context) + strlen(message) + sizeof(GETTEXT_CONTEXT_GLUE) + 1; - - if (!message || !context || !message[0]) - return ""; - - if (overall_length > sizeof(static_msg_ctxt_id)) { - dynamic_msg_ctxt_id = malloc(overall_length); - msg_ctxt_id = dynamic_msg_ctxt_id; - } - else { - msg_ctxt_id = static_msg_ctxt_id; - } - - sprintf(msg_ctxt_id, "%s%s%s", context, GETTEXT_CONTEXT_GLUE, message); - - translation = (char *)dcgettext(TEXT_DOMAIN_NAME, msg_ctxt_id, LC_MESSAGES); - - if (dynamic_msg_ctxt_id) - free(dynamic_msg_ctxt_id); - - if (translation == msg_ctxt_id) - translation = message; - - return translation; -#else - (void)context; - return message; -#endif -} - int BLF_translate_iface(void) { #ifdef WITH_INTERNATIONAL @@ -157,36 +111,32 @@ int BLF_translate_tooltips(void) #endif } -const char *BLF_translate_do_iface(const char *context, const char *msgid) +const char *BLF_translate_do_iface(const char *msgctxt, const char *msgid) { #ifdef WITH_INTERNATIONAL if (BLF_translate_iface()) { - if (context) - return BLF_pgettext(context, msgid); - else - return BLF_gettext(msgid); + return BLF_pgettext(msgctxt, msgid); } - else + else { return msgid; + } #else - (void)context; + (void)msgctxt; return msgid; #endif } -const char *BLF_translate_do_tooltip(const char *context, const char *msgid) +const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid) { #ifdef WITH_INTERNATIONAL if (BLF_translate_tooltips()) { - if (context) - return BLF_pgettext(context, msgid); - else - return BLF_gettext(msgid); + return BLF_pgettext(msgctxt, msgid); } - else + else { return msgid; + } #else - (void)context; + (void)msgctxt; return msgid; #endif } diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 7733a59b810..32b2274692c 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -75,6 +75,8 @@ #include "BKE_customdata.h" #include "BKE_bvhutils.h" +#include "BLI_utildefines.h" + struct CCGElem; struct CCGKey; struct MVert; diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 1875fd66628..1f9630d9fce 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -48,6 +48,9 @@ struct Main; #define IMA_MAX_SPACE 64 +void BKE_images_init(void); +void BKE_images_exit(void); + /* call from library */ void BKE_image_free(struct Image *me); @@ -133,14 +136,13 @@ enum { #define IMA_CHAN_FLAG_RGB 2 #define IMA_CHAN_FLAG_ALPHA 4 -/* depending Image type, and (optional) ImageUser setting it returns ibuf */ -/* always call to make signals work */ -struct ImBuf *BKE_image_get_ibuf(struct Image *ima, struct ImageUser *iuser); +/* checks whether there's an image buffer for given image and user */ +int BKE_image_has_ibuf(struct Image *ima, struct ImageUser *iuser); /* same as above, but can be used to retrieve images being rendered in * a thread safe way, always call both acquire and release */ struct ImBuf *BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **lock_r); -void BKE_image_release_ibuf(struct Image *ima, void *lock); +void BKE_image_release_ibuf(struct Image *ima, struct ImBuf *ibuf, void *lock); /* returns a new image or NULL if it can't load */ struct Image *BKE_image_load(const char *filepath); diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 7ee1c85d0de..2fa78b30835 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -319,8 +319,8 @@ int modifier_dependsOnTime(struct ModifierData *md); int modifier_supportsMapping(struct ModifierData *md); int modifier_couldBeCage(struct Scene *scene, struct ModifierData *md); int modifier_isCorrectableDeformed(struct ModifierData *md); -int modifier_sameTopology(ModifierData *md); -int modifier_nonGeometrical(ModifierData *md); +int modifier_isSameTopology(ModifierData *md); +int modifier_isNonGeometrical(ModifierData *md); int modifier_isEnabled(struct Scene *scene, struct ModifierData *md, int required_mode); void modifier_setError(struct ModifierData *md, const char *format, ...) #ifdef __GNUC__ diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index b365d93b246..65610b5c989 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -706,6 +706,8 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria #define CMP_NODE_SWITCH 317 #define CMP_NODE_PIXELATE 318 +#define CMP_NODE_MAP_RANGE 319 + /* channel toggles */ #define CMP_CHAN_RGB 1 #define CMP_CHAN_A 2 diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index ba611817c8f..88294cb30b6 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -248,7 +248,7 @@ void BKE_sequencer_cache_cleanup(void); struct ImBuf *BKE_sequencer_cache_get(SeqRenderData context, struct Sequence *seq, float cfra, seq_stripelem_ibuf_t type); /* passed ImBuf is properly refed, so ownership is *not* - * transfered to the cache. + * transferred to the cache. * you can pass the same ImBuf multiple times to the cache without problems. */ diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h index 875903f2e20..accac8694a9 100644 --- a/source/blender/blenkernel/BKE_text.h +++ b/source/blender/blenkernel/BKE_text.h @@ -83,7 +83,7 @@ void txt_sel_line (struct Text *text); char* txt_sel_to_buf (struct Text *text); void txt_insert_buf (struct Text *text, const char *in_buffer); void txt_print_undo (struct Text *text); -void txt_undo_add_toop (struct Text *text, int op, unsigned int froml, unsigned short fromc, unsigned int tol, unsigned short toc); +void txt_undo_add_op (struct Text *text, int op); void txt_do_undo (struct Text *text); void txt_do_redo (struct Text *text); void txt_split_curline (struct Text *text); @@ -100,14 +100,6 @@ void txt_move_lines (struct Text *text, const int direction); void txt_duplicate_line (struct Text *text); int setcurr_tab_spaces (struct Text *text, int space); -void txt_add_marker (struct Text *text, struct TextLine *line, int start, int end, const unsigned char color[4], int group, int flags); -short txt_clear_marker_region (struct Text *text, struct TextLine *line, int start, int end, int group, int flags); -short txt_clear_markers (struct Text *text, int group, int flags); -struct TextMarker *txt_find_marker (struct Text *text, struct TextLine *line, int curs, int group, int flags); -struct TextMarker *txt_find_marker_region (struct Text *text, struct TextLine *line, int start, int end, int group, int flags); -struct TextMarker *txt_prev_marker (struct Text *text, struct TextMarker *marker); -struct TextMarker *txt_next_marker (struct Text *text, struct TextMarker *marker); - /* utility functions, could be moved somewhere more generic but are python/text related */ int text_check_bracket(const char ch); int text_check_delim(const char ch); @@ -123,24 +115,6 @@ enum { /* Undo opcodes */ -/* Simple main cursor movement */ -#define UNDO_CLEFT 001 -#define UNDO_CRIGHT 002 -#define UNDO_CUP 003 -#define UNDO_CDOWN 004 - -/* Simple selection cursor movement */ -#define UNDO_SLEFT 005 -#define UNDO_SRIGHT 006 -#define UNDO_SUP 007 -#define UNDO_SDOWN 010 - -/* Complex movement (opcode is followed - * by 4 character line ID + a 2 character - * position ID and opcode (repeat)) */ -#define UNDO_CTO 011 -#define UNDO_STO 012 - /* Complex editing */ /* 1 - opcode is followed by 1 byte for ascii character and opcode (repeat)) */ /* 2 - opcode is followed by 2 bytes for utf-8 character and opcode (repeat)) */ @@ -169,8 +143,6 @@ enum { #define UNDO_IBLOCK 030 /* Insert block */ /* Misc */ -#define UNDO_SWAP 031 /* Swap cursors */ - #define UNDO_INDENT 032 #define UNDO_UNINDENT 033 #define UNDO_COMMENT 034 @@ -181,10 +153,6 @@ enum { #define UNDO_DUPLICATE 040 -/* Marker flags */ -#define TMARK_TEMP 0x01 /* Remove on non-editing events, don't save */ -#define TMARK_EDITALL 0x02 /* Edit all markers of the same group as one */ - #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index f7b8f59fa57..db06f4104a4 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -4,6 +4,7 @@ import os sources = env.Glob('intern/*.c') sources.remove('intern' + os.sep + 'mask_rasterize.c') +sources.remove('intern' + os.sep + 'mask_evaluate.c') sources.remove('intern' + os.sep + 'mask.c') sources_mask = env.Glob('intern/mask*.c') diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index b329a502c42..db8fb288d87 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2166,6 +2166,8 @@ static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask, /* weight paint and face select need original indices because of selection buffer drawing */ int needMapping = (ob == obact) && (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT | OB_MODE_VERTEX_PAINT | OB_MODE_TEXTURE_PAINT))); + BLI_assert(ob->type == OB_MESH); + clear_mesh_caches(ob); mesh_calc_modifiers(scene, ob, NULL, &ob->derivedDeform, diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index e95451252d0..dd27cc70ba3 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -512,7 +512,7 @@ const char *BKE_pose_ikparam_get_name(bPose *pose) { if (pose) { switch (pose->iksolver) { - case IKSOLVER_LEGACY: + case IKSOLVER_STANDARD: return NULL; case IKSOLVER_ITASC: return "bItasc"; @@ -587,7 +587,7 @@ void BKE_pose_ikparam_init(bPose *pose) BKE_pose_itasc_init(itasc); pose->ikparam = itasc; break; - case IKSOLVER_LEGACY: + case IKSOLVER_STANDARD: default: pose->ikparam = NULL; break; diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index b3cbc1f2b16..1970df54339 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1822,8 +1822,15 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos */ /* only happens on reload file, but violates depsgraph still... fix! */ - if ((cu->path == NULL) || (cu->path->data == NULL)) + if (ELEM(NULL, cu->path, cu->path->data)) { BKE_displist_make_curveTypes(scene, ikData->tar, 0); + + /* path building may fail in EditMode after removing verts [#33268]*/ + if (ELEM(NULL, cu->path, cu->path->data)) { + /* BLI_assert(cu->path != NULL); */ + return; + } + } } /* find the root bone and the chain of bones from the root to the tip diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index e1e868b234e..40cd5b3d403 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -70,6 +70,7 @@ #include "BKE_displist.h" #include "BKE_global.h" #include "BKE_idprop.h" +#include "BKE_image.h" #include "BKE_ipo.h" #include "BKE_library.h" #include "BKE_main.h" @@ -113,6 +114,7 @@ void free_blender(void) BKE_spacetypes_free(); /* after free main, it uses space callbacks */ IMB_exit(); + BKE_images_exit(); BLI_callback_global_finalize(); diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 98b206712d6..f310895f590 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -1287,8 +1287,6 @@ unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side) texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache"); - BKE_image_get_ibuf(mtex->tex->ima, NULL); - /*do normalized cannonical view coords for texture*/ for (y = -1.0, iy = 0; iy < side; iy++, y += step) { for (x = -1.0, ix = 0; ix < side; ix++, x += step) { diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index b7ad135fa72..7ac046c092f 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -2408,6 +2408,11 @@ void CDDM_calc_normals_tessface(DerivedMesh *dm) * this is a really horribly written function. ger. - joeedh * * note, CDDM_recalc_tessellation has to run on the returned DM if you want to access tessfaces. + * + * Note: This function is currently only used by the Mirror modifier, so it + * skips any faces that have all vertices merged (to avoid creating pairs + * of faces sharing the same set of vertices). If used elsewhere, it may + * be necessary to make this functionality optional. */ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) { @@ -2451,14 +2456,11 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) newv[i] = newv[vtargetmap[i]]; } } - - /* find-replace merged vertices with target vertices */ - ml = cddm->mloop; - for (i = 0; i < totloop; i++, ml++) { - if (vtargetmap[ml->v] != -1) { - ml->v = vtargetmap[ml->v]; - } - } + + /* Don't remap vertices in cddm->mloop, because we need to know the original + * indices in order to skip faces with all vertices merged. + * The "update loop indices..." section further down remaps vertices in mloop. + */ /* now go through and fix edges and faces */ med = cddm->medge; @@ -2492,6 +2494,24 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) ml = cddm->mloop + mp->loopstart; + /* skip faces with all vertices merged */ + { + int all_vertices_merged = TRUE; + + for (j = 0; j < mp->totloop; j++, ml++) { + if (vtargetmap[ml->v] == -1) { + all_vertices_merged = FALSE; + break; + } + } + + if (UNLIKELY(all_vertices_merged)) { + continue; + } + } + + ml = cddm->mloop + mp->loopstart; + c = 0; for (j = 0; j < mp->totloop; j++, ml++) { med = cddm->medge + ml->e; @@ -2650,7 +2670,7 @@ void CDDM_calc_edges(DerivedMesh *dm) EdgeHashIterator *ehi; MPoly *mp = cddm->mpoly; MLoop *ml; - MEdge *med; + MEdge *med, *origmed; EdgeHash *eh = BLI_edgehash_new(); int v1, v2; int *eindex; @@ -2683,6 +2703,7 @@ void CDDM_calc_edges(DerivedMesh *dm) CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges); CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); + origmed = cddm->medge; med = CustomData_get_layer(&edgeData, CD_MEDGE); index = CustomData_get_layer(&edgeData, CD_ORIGINDEX); @@ -2693,8 +2714,14 @@ void CDDM_calc_edges(DerivedMesh *dm) BLI_edgehashIterator_getKey(ehi, &med->v1, &med->v2); j = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi)); - med->flag = ME_EDGEDRAW | ME_EDGERENDER; - *index = j == 0 ? ORIGINDEX_NONE : eindex[j - 1]; + if (j == 0) { + med->flag = ME_EDGEDRAW | ME_EDGERENDER; + *index = ORIGINDEX_NONE; + } + else { + med->flag = ME_EDGEDRAW | ME_EDGERENDER | origmed[j - 1].flag; + *index = eindex[j - 1]; + } BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(i)); } diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index b488e683947..4641a02265a 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -198,8 +198,10 @@ static void collision_compute_barycentric ( float pv[3], float p1[3], float p2[3 w3[0] = 1.0f - w1[0] - w2[0]; } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdouble-promotion" +#ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wdouble-promotion" +#endif DO_INLINE void collision_interpolateOnTriangle ( float to[3], float v1[3], float v2[3], float v3[3], double w1, double w2, double w3 ) { @@ -371,7 +373,9 @@ static int cloth_collision_response_static ( ClothModifierData *clmd, CollisionM return result; } -#pragma GCC diagnostic pop +#ifdef __GNUC__ +# pragma GCC diagnostic pop +#endif //Determines collisions on overlap, collisions are written to collpair[i] and collision+number_collision_found is returned static CollPair* cloth_collision(ModifierData *md1, ModifierData *md2, diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 75276adf518..529fe07cab3 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -1008,8 +1008,8 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings * const ColorManagedDisplaySettings *display_settings) { int x, y, c; - unsigned int n, nl; - double div, divl; + unsigned int nl, na, nr, ng, nb; + double divl, diva, divr, divg, divb; float *rf = NULL; unsigned char *rc = NULL; unsigned int *bin_lum, *bin_r, *bin_g, *bin_b, *bin_a; @@ -1149,24 +1149,37 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings * savedlines += 1; } + /* test for nicer distribution even - non standard, leave it out for a while */ +#if 0 + for (x = 0; x < 256; x++) { + bin_lum[x] = sqrt (bin_lum[x]); + bin_r[x] = sqrt(bin_r[x]); + bin_g[x] = sqrt(bin_g[x]); + bin_b[x] = sqrt(bin_b[x]); + bin_a[x] = sqrt(bin_a[x]); + } +#endif + /* convert hist data to float (proportional to max count) */ - n = 0; - nl = 0; + nl = na = nr = nb = ng = 0; for (x = 0; x < 256; x++) { if (bin_lum[x] > nl) nl = bin_lum[x]; - if (bin_r[x] > n) n = bin_r[x]; - if (bin_g[x] > n) n = bin_g[x]; - if (bin_b[x] > n) n = bin_b[x]; - if (bin_a[x] > n) n = bin_a[x]; + if (bin_r[x] > nr) nr = bin_r[x]; + if (bin_g[x] > ng) ng = bin_g[x]; + if (bin_b[x] > nb) nb = bin_b[x]; + if (bin_a[x] > na) na = bin_a[x]; } - div = 1.0 / (double)n; divl = 1.0 / (double)nl; + diva = 1.0 / (double)na; + divr = 1.0 / (double)nr; + divg = 1.0 / (double)ng; + divb = 1.0 / (double)nb; for (x = 0; x < 256; x++) { scopes->hist.data_luma[x] = bin_lum[x] * divl; - scopes->hist.data_r[x] = bin_r[x] * div; - scopes->hist.data_g[x] = bin_g[x] * div; - scopes->hist.data_b[x] = bin_b[x] * div; - scopes->hist.data_a[x] = bin_a[x] * div; + scopes->hist.data_r[x] = bin_r[x] * divr; + scopes->hist.data_g[x] = bin_g[x] * divg; + scopes->hist.data_b[x] = bin_b[x] * divb; + scopes->hist.data_a[x] = bin_a[x] * diva; } MEM_freeN(bin_lum); MEM_freeN(bin_r); diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 719ae7357b4..ffb93139358 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -44,6 +44,7 @@ #include "BLI_listbase.h" #include "BLI_string.h" +#include "BLI_threads.h" #include "BLI_utildefines.h" #include "BKE_context.h" @@ -245,6 +246,10 @@ static void *ctx_wm_python_context_get(const bContext *C, const char *member, vo (void)C, (void)member; #endif + /* don't allow UI context access from non-main threads */ + if (!BLI_thread_is_main()) + return NULL; + return fall_through; } @@ -264,6 +269,11 @@ static int ctx_data_get(bContext *C, const char *member, bContextDataResult *res // return 1; } #endif + + /* don't allow UI context access from non-main threads */ + if (!BLI_thread_is_main()) + return done; + /* we check recursion to ensure that we do not get infinite * loops requesting data from ourselfs in a context callback */ diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index f2cd695d64a..754a4fbc0c8 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -1116,7 +1116,7 @@ void BKE_nurb_makeCurve(Nurb *nu, float *coord_array, float *tilt_array, float * *fp = basisu[i] * bp->vec[3]; sumdiv += *fp; } - if (sumdiv != 0.0f) if (sumdiv < 0.999f || sumdiv > 1.001f) { + if ((sumdiv != 0.0f) && (sumdiv < 0.999f || sumdiv > 1.001f)) { /* is normalizing needed? */ fp = sum; for (i = istart; i <= iend; i++, fp++) { diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 93c776ae30e..b2f8db0dcce 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -761,7 +761,7 @@ static void layerDoMinMax_mloopuv(void *data, void *vmin, void *vmax) { MLoopUV *min = vmin, *max = vmax, *luv = data; - DO_MINMAX2(luv->uv, min->uv, max->uv); + minmax_v2v2_v2(min->uv, max->uv, luv->uv); } static void layerAdd_mloopuv(void *data1, void *data2) @@ -833,7 +833,7 @@ static void layerDoMinMax_mloop_origspace(void *data, void *vmin, void *vmax) { OrigSpaceLoop *min = vmin, *max = vmax, *luv = data; - DO_MINMAX2(luv->uv, min->uv, max->uv); + minmax_v2v2_v2(min->uv, max->uv, luv->uv); } static void layerAdd_mloop_origspace(void *data1, void *data2) diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 9d3a7ec57cf..d23a608d31f 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -671,8 +671,9 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O } } } - else if(ob->type == OB_LAMP) + else if (ob->type == OB_LAMP) { dag_add_lamp_driver_relations(dag, node, ob->data); + } /* particles */ psys = ob->particlesystem.first; diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 89d728c0419..bb3836e3c08 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -86,11 +86,13 @@ #include "RE_shader_ext.h" #ifdef _OPENMP -#include <omp.h> +# include <omp.h> #endif /* could enable at some point but for now there are far too many conversions */ -#pragma GCC diagnostic ignored "-Wdouble-promotion" +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wdouble-promotion" +#endif /* precalculated gaussian factors for 5x super sampling */ static float gaussianFactors[5] = {0.996849f, diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c index 30427a81c4b..c3008d17bd1 100644 --- a/source/blender/blenkernel/intern/idcode.c +++ b/source/blender/blenkernel/intern/idcode.c @@ -47,39 +47,40 @@ typedef struct { } IDType; /* plural need to match rna_main.c's MainCollectionDef */ +/* WARNING! Keep it in sync with i18n contexts in BLF_translation.h */ static IDType idtypes[] = { - { ID_AC, "Action", "actions", IDTYPE_FLAGS_ISLINKABLE}, - { ID_AR, "Armature", "armatures", IDTYPE_FLAGS_ISLINKABLE}, - { ID_BR, "Brush", "brushes", IDTYPE_FLAGS_ISLINKABLE}, - { ID_CA, "Camera", "cameras", IDTYPE_FLAGS_ISLINKABLE}, - { ID_CU, "Curve", "curves", IDTYPE_FLAGS_ISLINKABLE}, - { ID_GD, "GPencil", "grease_pencil", IDTYPE_FLAGS_ISLINKABLE}, /* rename gpencil */ - { ID_GR, "Group", "groups", IDTYPE_FLAGS_ISLINKABLE}, - { ID_ID, "ID", "ids", 0}, /* plural is fake */ - { ID_IM, "Image", "images", IDTYPE_FLAGS_ISLINKABLE}, - { ID_IP, "Ipo", "ipos", IDTYPE_FLAGS_ISLINKABLE}, /* deprecated */ - { ID_KE, "Key", "shape_keys", 0}, - { ID_LA, "Lamp", "lamps", IDTYPE_FLAGS_ISLINKABLE}, - { ID_LI, "Library", "libraries", 0}, - { ID_LT, "Lattice", "lattices", IDTYPE_FLAGS_ISLINKABLE}, - { ID_MA, "Material", "materials", IDTYPE_FLAGS_ISLINKABLE}, - { ID_MB, "Metaball", "metaballs", IDTYPE_FLAGS_ISLINKABLE}, - { ID_ME, "Mesh", "meshes", IDTYPE_FLAGS_ISLINKABLE}, - { ID_NT, "NodeTree", "node_groups", IDTYPE_FLAGS_ISLINKABLE}, - { ID_OB, "Object", "objects", IDTYPE_FLAGS_ISLINKABLE}, - { ID_PA, "ParticleSettings", "particles", 0}, - { ID_SCE, "Scene", "scenes", IDTYPE_FLAGS_ISLINKABLE}, - { ID_SCR, "Screen", "screens", 0}, - { ID_SEQ, "Sequence", "sequences", 0}, /* not actually ID data */ - { ID_SPK, "Speaker", "speakers", IDTYPE_FLAGS_ISLINKABLE}, - { ID_SO, "Sound", "sounds", IDTYPE_FLAGS_ISLINKABLE}, - { ID_TE, "Texture", "textures", IDTYPE_FLAGS_ISLINKABLE}, - { ID_TXT, "Text", "texts", IDTYPE_FLAGS_ISLINKABLE}, - { ID_VF, "VFont", "fonts", IDTYPE_FLAGS_ISLINKABLE}, - { ID_WO, "World", "worlds", IDTYPE_FLAGS_ISLINKABLE}, - { ID_WM, "WindowManager", "window_managers", 0}, - { ID_MC, "MovieClip", "movieclips", IDTYPE_FLAGS_ISLINKABLE}, - { ID_MSK, "Mask", "masks", IDTYPE_FLAGS_ISLINKABLE}, + { ID_AC, "Action", "actions", IDTYPE_FLAGS_ISLINKABLE }, + { ID_AR, "Armature", "armatures", IDTYPE_FLAGS_ISLINKABLE }, + { ID_BR, "Brush", "brushes", IDTYPE_FLAGS_ISLINKABLE }, + { ID_CA, "Camera", "cameras", IDTYPE_FLAGS_ISLINKABLE }, + { ID_CU, "Curve", "curves", IDTYPE_FLAGS_ISLINKABLE }, + { ID_GD, "GPencil", "grease_pencil", IDTYPE_FLAGS_ISLINKABLE }, /* rename gpencil */ + { ID_GR, "Group", "groups", IDTYPE_FLAGS_ISLINKABLE }, + { ID_ID, "ID", "ids", 0 }, /* plural is fake */ + { ID_IM, "Image", "images", IDTYPE_FLAGS_ISLINKABLE }, + { ID_IP, "Ipo", "ipos", IDTYPE_FLAGS_ISLINKABLE }, /* deprecated */ + { ID_KE, "Key", "shape_keys", 0 }, + { ID_LA, "Lamp", "lamps", IDTYPE_FLAGS_ISLINKABLE }, + { ID_LI, "Library", "libraries", 0 }, + { ID_LT, "Lattice", "lattices", IDTYPE_FLAGS_ISLINKABLE }, + { ID_MA, "Material", "materials", IDTYPE_FLAGS_ISLINKABLE }, + { ID_MB, "Metaball", "metaballs", IDTYPE_FLAGS_ISLINKABLE }, + { ID_MC, "MovieClip", "movieclips", IDTYPE_FLAGS_ISLINKABLE }, + { ID_ME, "Mesh", "meshes", IDTYPE_FLAGS_ISLINKABLE }, + { ID_MSK, "Mask", "masks", IDTYPE_FLAGS_ISLINKABLE }, + { ID_NT, "NodeTree", "node_groups", IDTYPE_FLAGS_ISLINKABLE }, + { ID_OB, "Object", "objects", IDTYPE_FLAGS_ISLINKABLE }, + { ID_PA, "ParticleSettings", "particles", 0 }, + { ID_SCE, "Scene", "scenes", IDTYPE_FLAGS_ISLINKABLE }, + { ID_SCR, "Screen", "screens", 0 }, + { ID_SEQ, "Sequence", "sequences", 0 }, /* not actually ID data */ + { ID_SPK, "Speaker", "speakers", IDTYPE_FLAGS_ISLINKABLE }, + { ID_SO, "Sound", "sounds", IDTYPE_FLAGS_ISLINKABLE }, + { ID_TE, "Texture", "textures", IDTYPE_FLAGS_ISLINKABLE }, + { ID_TXT, "Text", "texts", IDTYPE_FLAGS_ISLINKABLE }, + { ID_VF, "VFont", "fonts", IDTYPE_FLAGS_ISLINKABLE }, + { ID_WO, "World", "worlds", IDTYPE_FLAGS_ISLINKABLE }, + { ID_WM, "WindowManager", "window_managers", 0 }, }; static int nidtypes = sizeof(idtypes) / sizeof(idtypes[0]); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 55d37c91859..e4b9edacc7e 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -100,6 +100,8 @@ #include "WM_api.h" +static SpinLock image_spin; + /* max int, to indicate we don't store sequences in ibuf */ #define IMA_NO_INDEX 0x7FEFEFEF @@ -108,6 +110,16 @@ #define IMA_INDEX_FRAME(index) (index >> 10) #define IMA_INDEX_PASS(index) (index & ~1023) +void BKE_images_init(void) +{ + BLI_spin_init(&image_spin); +} + +void BKE_images_exit(void) +{ + BLI_spin_end(&image_spin); +} + /* ******** IMAGE PROCESSING ************* */ static void de_interlace_ng(struct ImBuf *ibuf) /* neogeo fields */ @@ -168,13 +180,14 @@ static void de_interlace_st(struct ImBuf *ibuf) /* standard fields */ void BKE_image_de_interlace(Image *ima, int odd) { - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (ibuf) { if (odd) de_interlace_st(ibuf); else de_interlace_ng(ibuf); } + BKE_image_release_ibuf(ima, ibuf, NULL); } /* ***************** ALLOC & FREE, DATA MANAGING *************** */ @@ -260,8 +273,9 @@ static ImBuf *image_get_ibuf(Image *ima, int index, int frame) /* this function is intended to be thread safe. with IMA_NO_INDEX this * should be OK, but when iterating over the list this is more tricky * */ - if (index == IMA_NO_INDEX) + if (index == IMA_NO_INDEX) { return ima->ibufs.first; + } else { ImBuf *ibuf; @@ -269,9 +283,9 @@ static ImBuf *image_get_ibuf(Image *ima, int index, int frame) for (ibuf = ima->ibufs.first; ibuf; ibuf = ibuf->next) if (ibuf->index == index) return ibuf; - - return NULL; } + + return NULL; } /* no ima->ibuf anymore, but listbase */ @@ -534,7 +548,7 @@ int BKE_image_scale(Image *image, int width, int height) ibuf->userflags |= IB_BITMAPDIRTY; } - BKE_image_release_ibuf(image, lock); + BKE_image_release_ibuf(image, ibuf, lock); return (ibuf != NULL); } @@ -2081,6 +2095,8 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) if (ima == NULL) return; + BLI_spin_lock(&image_spin); + switch (signal) { case IMA_SIGNAL_FREE: image_free_buffers(ima); @@ -2157,6 +2173,8 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal) break; } + BLI_spin_unlock(&image_spin); + /* don't use notifiers because they are not 100% sure to succeeded * this also makes sure all scenes are accounted for. */ { @@ -2320,7 +2338,7 @@ static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int frame) if (ibuf) { #ifdef WITH_OPENEXR - /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_get_ibuf */ + /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_acquire_ibuf */ if (ibuf->ftype == OPENEXR && ibuf->userdata) { image_create_multilayer(ima, ibuf, frame); ima->type = IMA_TYPE_MULTILAYER; @@ -2482,7 +2500,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra) } if (ibuf) { - /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_get_ibuf */ + /* handle multilayer case, don't assign ibuf. will be handled in BKE_image_acquire_ibuf */ if (ibuf->ftype == OPENEXR && ibuf->userdata) { image_create_multilayer(ima, ibuf, cfra); ima->type = IMA_TYPE_MULTILAYER; @@ -2751,38 +2769,32 @@ static ImBuf *image_get_ibuf_threadsafe(Image *ima, ImageUser *iuser, int *frame * a big bottleneck */ } - *frame_r = frame; - *index_r = index; + if (frame_r) + *frame_r = frame; + + if (index_r) + *index_r = index; return ibuf; } -/* Checks optional ImageUser and verifies/creates ImBuf. */ -/* use this one if you want to get a render result in progress, - * if not, use BKE_image_get_ibuf which doesn't require a release */ -ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) +/* Checks optional ImageUser and verifies/creates ImBuf. + * + * not thread-safe, so callee should worry about thread locks + */ +static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) { ImBuf *ibuf = NULL; float color[] = {0, 0, 0, 1}; int frame = 0, index = 0; - /* This function is intended to be thread-safe. It postpones the mutex lock - * until it needs to load the image, if the image is already there it - * should just get the pointer and return. The reason is that a lot of mutex - * locks appears to be very slow on certain multicore macs, causing a render - * with image textures to actually slow down as more threads are used. - * - * Note that all the image loading functions should also make sure they do - * things in a threadsafe way for image_get_ibuf_threadsafe to work correct. - * That means, the last two steps must be, 1) add the ibuf to the list and - * 2) set ima/iuser->ok to 0 to IMA_OK_LOADED */ - if (lock_r) *lock_r = NULL; /* quick reject tests */ if (ima == NULL) return NULL; + if (iuser) { if (iuser->ok == 0) return NULL; @@ -2790,95 +2802,71 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) else if (ima->ok == 0) return NULL; - /* try to get the ibuf without locking */ ibuf = image_get_ibuf_threadsafe(ima, iuser, &frame, &index); if (ibuf == NULL) { - /* couldn't get ibuf and image is not ok, so let's lock and try to - * load the image */ - BLI_lock_thread(LOCK_IMAGE); - - /* need to check ok flag and loading ibuf again, because the situation - * might have changed in the meantime */ - if (iuser) { - if (iuser->ok == 0) { - BLI_unlock_thread(LOCK_IMAGE); - return NULL; - } - } - else if (ima->ok == 0) { - BLI_unlock_thread(LOCK_IMAGE); - return NULL; - } - - ibuf = image_get_ibuf_threadsafe(ima, iuser, &frame, &index); - - if (ibuf == NULL) { - /* we are sure we have to load the ibuf, using source and type */ - if (ima->source == IMA_SRC_MOVIE) { - /* source is from single file, use flipbook to store ibuf */ - ibuf = image_load_movie_file(ima, iuser, frame); - } - else if (ima->source == IMA_SRC_SEQUENCE) { - if (ima->type == IMA_TYPE_IMAGE) { - /* regular files, ibufs in flipbook, allows saving */ - ibuf = image_load_sequence_file(ima, iuser, frame); - } - /* no else; on load the ima type can change */ - if (ima->type == IMA_TYPE_MULTILAYER) { - /* only 1 layer/pass stored in imbufs, no exrhandle anim storage, no saving */ - ibuf = image_load_sequence_multilayer(ima, iuser, frame); - } + /* we are sure we have to load the ibuf, using source and type */ + if (ima->source == IMA_SRC_MOVIE) { + /* source is from single file, use flipbook to store ibuf */ + ibuf = image_load_movie_file(ima, iuser, frame); + } + else if (ima->source == IMA_SRC_SEQUENCE) { + if (ima->type == IMA_TYPE_IMAGE) { + /* regular files, ibufs in flipbook, allows saving */ + ibuf = image_load_sequence_file(ima, iuser, frame); } - else if (ima->source == IMA_SRC_FILE) { - - if (ima->type == IMA_TYPE_IMAGE) - ibuf = image_load_image_file(ima, iuser, frame); /* cfra only for '#', this global is OK */ - /* no else; on load the ima type can change */ - if (ima->type == IMA_TYPE_MULTILAYER) - /* keeps render result, stores ibufs in listbase, allows saving */ - ibuf = image_get_ibuf_multilayer(ima, iuser); - + /* no else; on load the ima type can change */ + if (ima->type == IMA_TYPE_MULTILAYER) { + /* only 1 layer/pass stored in imbufs, no exrhandle anim storage, no saving */ + ibuf = image_load_sequence_multilayer(ima, iuser, frame); } - else if (ima->source == IMA_SRC_GENERATED) { - /* generated is: ibuf is allocated dynamically */ - /* UV testgrid or black or solid etc */ - if (ima->gen_x == 0) ima->gen_x = 1024; - if (ima->gen_y == 0) ima->gen_y = 1024; - ibuf = add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, 24, (ima->gen_flag & IMA_GEN_FLOAT) != 0, ima->gen_type, - color, &ima->colorspace_settings); - image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); - ima->ok = IMA_OK_LOADED; + } + else if (ima->source == IMA_SRC_FILE) { + + if (ima->type == IMA_TYPE_IMAGE) + ibuf = image_load_image_file(ima, iuser, frame); /* cfra only for '#', this global is OK */ + /* no else; on load the ima type can change */ + if (ima->type == IMA_TYPE_MULTILAYER) + /* keeps render result, stores ibufs in listbase, allows saving */ + ibuf = image_get_ibuf_multilayer(ima, iuser); + + } + else if (ima->source == IMA_SRC_GENERATED) { + /* generated is: ibuf is allocated dynamically */ + /* UV testgrid or black or solid etc */ + if (ima->gen_x == 0) ima->gen_x = 1024; + if (ima->gen_y == 0) ima->gen_y = 1024; + ibuf = add_ibuf_size(ima->gen_x, ima->gen_y, ima->name, 24, (ima->gen_flag & IMA_GEN_FLOAT) != 0, ima->gen_type, + color, &ima->colorspace_settings); + image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0); + ima->ok = IMA_OK_LOADED; + } + else if (ima->source == IMA_SRC_VIEWER) { + if (ima->type == IMA_TYPE_R_RESULT) { + /* always verify entirely, and potentially + * returns pointer to release later */ + ibuf = image_get_render_result(ima, iuser, lock_r); } - else if (ima->source == IMA_SRC_VIEWER) { - if (ima->type == IMA_TYPE_R_RESULT) { - /* always verify entirely, and potentially - * returns pointer to release later */ - ibuf = image_get_render_result(ima, iuser, lock_r); - } - else if (ima->type == IMA_TYPE_COMPOSITE) { - /* requires lock/unlock, otherwise don't return image */ - if (lock_r) { - /* unlock in BKE_image_release_ibuf */ - BLI_lock_thread(LOCK_VIEWER); - *lock_r = ima; - - /* XXX anim play for viewer nodes not yet supported */ - frame = 0; // XXX iuser?iuser->framenr:0; - ibuf = image_get_ibuf(ima, 0, frame); - - if (!ibuf) { - /* Composite Viewer, all handled in compositor */ - /* fake ibuf, will be filled in compositor */ - ibuf = IMB_allocImBuf(256, 256, 32, IB_rect); - image_assign_ibuf(ima, ibuf, 0, frame); - } + else if (ima->type == IMA_TYPE_COMPOSITE) { + /* requires lock/unlock, otherwise don't return image */ + if (lock_r) { + /* unlock in BKE_image_release_ibuf */ + BLI_lock_thread(LOCK_VIEWER); + *lock_r = ima; + + /* XXX anim play for viewer nodes not yet supported */ + frame = 0; // XXX iuser?iuser->framenr:0; + ibuf = image_get_ibuf(ima, 0, frame); + + if (!ibuf) { + /* Composite Viewer, all handled in compositor */ + /* fake ibuf, will be filled in compositor */ + ibuf = IMB_allocImBuf(256, 256, 32, IB_rect); + image_assign_ibuf(ima, ibuf, 0, frame); } } } } - - BLI_unlock_thread(LOCK_IMAGE); } BKE_image_tag_time(ima); @@ -2886,23 +2874,79 @@ ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) return ibuf; } -void BKE_image_release_ibuf(Image *ima, void *lock) +/* return image buffer for given image and user + * + * - will lock render result if image type is render result and lock is not NULL + * - will return NULL if image type if render or composite result and lock is NULL + * + * references the result, BKE_image_release_ibuf should be used to de-reference + */ +ImBuf *BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **lock_r) +{ + ImBuf *ibuf; + + BLI_spin_lock(&image_spin); + + ibuf = image_acquire_ibuf(ima, iuser, lock_r); + + if (ibuf) + IMB_refImBuf(ibuf); + + BLI_spin_unlock(&image_spin); + + return ibuf; +} + +void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock) { - /* for getting image during threaded render / compositing, need to release */ - if (lock == ima) { - BLI_unlock_thread(LOCK_VIEWER); /* viewer image */ + if (lock) { + /* for getting image during threaded render / compositing, need to release */ + if (lock == ima) { + BLI_unlock_thread(LOCK_VIEWER); /* viewer image */ + } + else if (lock) { + RE_ReleaseResultImage(lock); /* render result */ + BLI_unlock_thread(LOCK_VIEWER); /* view image imbuf */ + } } - else if (lock) { - RE_ReleaseResultImage(lock); /* render result */ - BLI_unlock_thread(LOCK_VIEWER); /* view image imbuf */ + + if (ibuf) { + BLI_spin_lock(&image_spin); + IMB_freeImBuf(ibuf); + BLI_spin_unlock(&image_spin); } } -/* warning, this can allocate generated images */ -ImBuf *BKE_image_get_ibuf(Image *ima, ImageUser *iuser) +/* checks whether there's an image buffer for given image and user */ +int BKE_image_has_ibuf(Image *ima, ImageUser *iuser) { - /* here (+fie_ima/2-1) makes sure that division happens correctly */ - return BKE_image_acquire_ibuf(ima, iuser, NULL); + ImBuf *ibuf; + + /* quick reject tests */ + if (ima == NULL) + return FALSE; + + if (iuser) { + if (iuser->ok == 0) + return FALSE; + } + else if (ima->ok == 0) + return FALSE; + + ibuf = image_get_ibuf_threadsafe(ima, iuser, NULL, NULL); + + if (!ibuf) { + BLI_spin_lock(&image_spin); + + ibuf = image_get_ibuf_threadsafe(ima, iuser, NULL, NULL); + + if (!ibuf) + ibuf = image_acquire_ibuf(ima, iuser, NULL); + + BLI_spin_unlock(&image_spin); + } + + return ibuf != NULL; } int BKE_image_user_frame_get(const ImageUser *iuser, int cfra, int fieldnr, short *r_is_in_range) @@ -3020,7 +3064,7 @@ int BKE_image_has_alpha(struct Image *image) ibuf = BKE_image_acquire_ibuf(image, NULL, &lock); planes = (ibuf ? ibuf->planes : 0); - BKE_image_release_ibuf(image, lock); + BKE_image_release_ibuf(image, ibuf, lock); if (planes == 32) return 1; @@ -3044,7 +3088,7 @@ void BKE_image_get_size(Image *image, ImageUser *iuser, int *width, int *height) *height = IMG_SIZE_FALLBACK; } - BKE_image_release_ibuf(image, lock); + BKE_image_release_ibuf(image, ibuf, lock); } void BKE_image_get_size_fl(Image *image, ImageUser *iuser, float size[2]) diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 9deff12f124..eb0612a75bd 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -1520,7 +1520,9 @@ void test_idbutton(char *name) /* search for id */ idtest = BLI_findstring(lb, name, offsetof(ID, name) + 2); - if (idtest) if (new_id(lb, idtest, name) == 0) id_sort_by_name(lb, idtest); + if (idtest && (new_id(lb, idtest, name) == 0)) { + id_sort_by_name(lb, idtest); + } } void text_idbutton(struct ID *id, char *text) diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c index 7d89678d36f..a2f6b3c1929 100644 --- a/source/blender/blenkernel/intern/mask_evaluate.c +++ b/source/blender/blenkernel/intern/mask_evaluate.c @@ -289,10 +289,10 @@ static void feather_bucket_check_intersect(float (*feather_points)[2], int tot_f /* collapse loop with smaller AABB */ for (k = 0; k < tot_feather_point; k++) { if (k >= check_b && k <= cur_a) { - DO_MINMAX2(feather_points[k], min_a, max_a); + minmax_v2v2_v2(min_a, max_a, feather_points[k]); } else { - DO_MINMAX2(feather_points[k], min_b, max_b); + minmax_v2v2_v2(min_b, max_b, feather_points[k]); } } @@ -379,7 +379,7 @@ void BKE_mask_spline_feather_collapse_inner_loops(MaskSpline *spline, float (*fe int next = i + 1; float delta; - DO_MINMAX2(feather_points[i], min, max); + minmax_v2v2_v2(min, max, feather_points[i]); if (next == tot_feather_point) { if (spline->flag & MASK_SPLINE_CYCLIC) diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 068059dc29a..fd5af6a20bb 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -3011,7 +3011,7 @@ float BKE_mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart, MLoop *l_iter = loopstart; float area, polynorm_local[3], (*vertexcos)[3]; const float *no = polynormal ? polynormal : polynorm_local; - BLI_array_fixedstack_declare(vertexcos, BM_NGON_STACK_SIZE, mpoly->totloop, __func__); + BLI_array_fixedstack_declare(vertexcos, BM_DEFAULT_NGON_STACK_SIZE, mpoly->totloop, __func__); /* pack vertex cos into an array for area_poly_v3 */ for (i = 0; i < mpoly->totloop; i++, l_iter++) { diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 9c7cbc42bdd..25b70ce1793 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -249,13 +249,13 @@ int modifier_couldBeCage(struct Scene *scene, ModifierData *md) modifier_supportsMapping(md)); } -int modifier_sameTopology(ModifierData *md) +int modifier_isSameTopology(ModifierData *md) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); return ELEM(mti->type, eModifierTypeType_OnlyDeform, eModifierTypeType_NonGeometrical); } -int modifier_nonGeometrical(ModifierData *md) +int modifier_isNonGeometrical(ModifierData *md) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); return (mti->type == eModifierTypeType_NonGeometrical); diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 2d76484b60a..06b846a6df9 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -2184,6 +2184,7 @@ static void registerCompositNodes(bNodeTreeType *ttype) register_node_type_cmp_normal(ttype); register_node_type_cmp_curve_vec(ttype); register_node_type_cmp_map_value(ttype); + register_node_type_cmp_map_range(ttype); register_node_type_cmp_normalize(ttype); register_node_type_cmp_filter(ttype); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 6ec173a5908..47ca502d247 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -196,18 +196,18 @@ int BKE_object_support_modifier_type_check(Object *ob, int modifier_type) return TRUE; } -void BKE_object_link_modifiers(struct Object *ob, struct Object *from) +void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src) { ModifierData *md; - BKE_object_free_modifiers(ob); + BKE_object_free_modifiers(ob_dst); - if (!ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) { + if (!ELEM5(ob_dst->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) { /* only objects listed above can have modifiers and linking them to objects * which doesn't have modifiers stack is quite silly */ return; } - for (md = from->modifiers.first; md; md = md->next) { + for (md = ob_src->modifiers.first; md; md = md->next) { ModifierData *nmd = NULL; if (ELEM4(md->type, @@ -219,16 +219,18 @@ void BKE_object_link_modifiers(struct Object *ob, struct Object *from) continue; } - if (!BKE_object_support_modifier_type_check(ob, md->type)) + if (!BKE_object_support_modifier_type_check(ob_dst, md->type)) continue; nmd = modifier_new(md->type); + BLI_strncpy(nmd->name, md->name, sizeof(nmd->name)); modifier_copyData(md, nmd); - BLI_addtail(&ob->modifiers, nmd); + BLI_addtail(&ob_dst->modifiers, nmd); + modifier_unique_name(&ob_dst->modifiers, nmd); } - BKE_object_copy_particlesystems(ob, from); - BKE_object_copy_softbody(ob, from); + BKE_object_copy_particlesystems(ob_dst, ob_src); + BKE_object_copy_softbody(ob_dst, ob_src); /* TODO: smoke?, cloth? */ } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index d645204d29c..93bf5a5c0b4 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -3786,14 +3786,22 @@ static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int face_index, co return 1; } -#define SET_PARTICLE_TEXTURE(type, pvalue, texfac) \ - if ((event & mtex->mapto) & type) { pvalue = texture_value_blend(def, pvalue, value, texfac, blend); } (void)0 - -#define CLAMP_PARTICLE_TEXTURE_POS(type, pvalue) \ - if (event & type) { if (pvalue < 0.0f) pvalue = 1.0f + pvalue; CLAMP(pvalue, 0.0f, 1.0f); } (void)0 - -#define CLAMP_PARTICLE_TEXTURE_POSNEG(type, pvalue) \ - if (event & type) { CLAMP(pvalue, -1.0f, 1.0f); } (void)0 +#define SET_PARTICLE_TEXTURE(type, pvalue, texfac) \ + if ((event & mtex->mapto) & type) { \ + pvalue = texture_value_blend(def, pvalue, value, texfac, blend); \ + } (void)0 + +#define CLAMP_PARTICLE_TEXTURE_POS(type, pvalue) \ + if (event & type) { \ + if (pvalue < 0.0f) \ + pvalue = 1.0f + pvalue; \ + CLAMP(pvalue, 0.0f, 1.0f); \ + } (void)0 + +#define CLAMP_PARTICLE_TEXTURE_POSNEG(type, pvalue) \ + if (event & type) { \ + CLAMP(pvalue, -1.0f, 1.0f); \ + } (void)0 static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSettings *part, ParticleData *par, int child_index, int face_index, const float fw[4], float *orco, ParticleTexture *ptex, int event, float cfra) { @@ -3802,8 +3810,8 @@ static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSetti float value, rgba[4], texvec[3]; ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp = - ptex->gravity = ptex->field = ptex->time = ptex->clump = ptex->kink = - ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.f; + ptex->gravity = ptex->field = ptex->time = ptex->clump = ptex->kink = + ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.0f; ptex->length = 1.0f - part->randlength * PSYS_FRAND(child_index + 26); ptex->length *= part->clength_thres < PSYS_FRAND(child_index + 27) ? part->clength : 1.0f; diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index f195b3d71b0..3f2eb32f61c 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -2568,10 +2568,12 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) sbFreeSimulation(pid->calldata); else if (pid->type == PTCACHE_TYPE_PARTICLES) psys_reset(pid->calldata, PSYS_RESET_DEPSGRAPH); - /*else if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) +#if 0 + else if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) smokeModifier_reset(pid->calldata); else if (pid->type == PTCACHE_TYPE_SMOKE_HIGHRES) - smokeModifier_reset_turbulence(pid->calldata);*/ + smokeModifier_reset_turbulence(pid->calldata); +#endif else if (pid->type == PTCACHE_TYPE_DYNAMICPAINT) dynamicPaint_clearSurface((DynamicPaintSurface*)pid->calldata); } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 4f62732f5e6..9b1425584a7 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -1045,7 +1045,7 @@ static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scen /* always update layer, so that animating layers works (joshua july 2010) */ /* XXX commented out, this has depsgraph issues anyway - and this breaks setting scenes - (on scene-set, the base-lay is copied to ob-lay (ton nov 2012) */ + * (on scene-set, the base-lay is copied to ob-lay (ton nov 2012) */ // base->lay = ob->lay; } diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 469881020c1..0b7fdaa7c1d 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -139,6 +139,9 @@ static ImBuf *prepare_effect_imbufs(SeqRenderData context, ImBuf *ibuf1, ImBuf * IMB_rect_from_float(ibuf3); } + if (out->rect_float) + IMB_colormanagement_assign_float_colorspace(out, context.scene->sequencer_colorspace_settings.name); + return out; } diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index a947a48938e..e023a3e20ae 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -2338,11 +2338,13 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float */ const short is_rendering = G.is_rendering; + const short is_background = G.background; const int do_seq_gl = G.is_rendering ? 0 /* (context.scene->r.seq_flag & R_SEQ_GL_REND) */ : (context.scene->r.seq_flag & R_SEQ_GL_PREV); int do_seq; int have_seq = FALSE; + int have_comp = FALSE; Scene *scene; int is_thread_main = BLI_thread_is_main(); @@ -2355,6 +2357,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float frame = scene->r.sfra + nr + seq->anim_startofs; have_seq = (scene->r.scemode & R_DOSEQ) && scene->ed && scene->ed->seqbase.first; + have_comp = (scene->r.scemode & R_DOCOMP) && scene->use_nodes && scene->nodetree; oldcfra = scene->r.cfra; scene->r.cfra = frame; @@ -2367,7 +2370,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float camera = scene->camera; } - if (have_seq == FALSE && camera == NULL) { + if (have_comp == FALSE && camera == NULL) { scene->r.cfra = oldcfra; return NULL; } @@ -2384,8 +2387,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float (void)oldmarkers; #endif - if ((sequencer_view3d_cb && do_seq_gl && camera) && is_thread_main) - { + if ((sequencer_view3d_cb && do_seq_gl && camera) && is_thread_main) { char err_out[256] = "unknown"; /* for old scened this can be uninitialized, * should probably be added to do_versions at some point if the functionality stays */ @@ -2408,11 +2410,15 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float * * disable rendered preview for sequencer while rendering -- it's very much possible * that preview render will went into conflict with final render + * + * When rendering from command line renderer is called from main thread, in this + * case it's always safe to render scene here */ - if (!is_thread_main || is_rendering == FALSE) { + if (!is_thread_main || is_rendering == FALSE || is_background) { if (re == NULL) re = RE_NewRender(scene->id.name); + BKE_scene_update_for_newframe(context.bmain, scene, scene->lay); RE_BlenderFrame(re, context.bmain, scene, NULL, camera, scene->lay, frame, FALSE); /* restore previous state after it was toggled on & off by RE_BlenderFrame */ diff --git a/source/blender/blenkernel/intern/suggestions.c b/source/blender/blenkernel/intern/suggestions.c index 99e33594a3e..ff9774f85af 100644 --- a/source/blender/blenkernel/intern/suggestions.c +++ b/source/blender/blenkernel/intern/suggestions.c @@ -47,6 +47,7 @@ static SuggList suggestions = {NULL, NULL, NULL, NULL, NULL}; static char *documentation = NULL; //static int doc_lines = 0; +/* TODO, replace with BLI_strncasecmp() */ static int txttl_cmp(const char *first, const char *second, int len) { int cmp, i; @@ -113,19 +114,18 @@ short texttool_text_is_active(Text *text) void texttool_suggest_add(const char *name, char type) { + const int len = strlen(name); + int cmp; SuggItem *newitem, *item; - int len, cmp; - newitem = MEM_mallocN(sizeof(SuggItem) + strlen(name) + 1, "SuggestionItem"); + newitem = MEM_mallocN(sizeof(SuggItem) + len + 1, "SuggItem"); if (!newitem) { printf("Failed to allocate memory for suggestion.\n"); return; } newitem->name = (char *) (newitem + 1); - len = strlen(name); - strncpy(newitem->name, name, len); - newitem->name[len] = '\0'; + memcpy(newitem->name, name, len + 1); newitem->type = type; newitem->prev = newitem->next = NULL; diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index d230cf8f1fe..e6339d07e66 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -96,17 +96,6 @@ * If the user moves the cursor the st containing that cursor should * be popped ... other st's retain their own top location. * - * Markers - * -- - * The mrk->flags define the behavior and relationships between markers. The - * upper two bytes are used to hold a group ID, the lower two are normal flags. If - * TMARK_EDITALL is set the group ID defines which other markers should be edited. - * - * The mrk->clr field is used to visually group markers where the flags may not - * match. A template system, for example, may allow editing of repeating tokens - * (in one group) but include other marked positions (in another group) all in the - * same template with the same color. - * * Undo * -- * Undo/Redo works by storing @@ -136,8 +125,7 @@ static void txt_pop_first(Text *text); static void txt_pop_last(Text *text); -static void txt_undo_add_op(Text *text, int op); -static void txt_undo_add_block(Text *text, int op, const char *buf); +static void txt_undo_add_blockop(Text *text, int op, const char *buf); static void txt_delete_line(Text *text, TextLine *line); static void txt_delete_sel(Text *text); static void txt_make_dirty(Text *text); @@ -175,7 +163,6 @@ void BKE_text_free(Text *text) } BLI_freelistN(&text->lines); - BLI_freelistN(&text->markers); if (text->name) MEM_freeN(text->name); MEM_freeN(text->undo_buf); @@ -203,7 +190,6 @@ Text *BKE_text_add(const char *name) ta->flags |= TXT_TABSTOSPACES; ta->lines.first = ta->lines.last = NULL; - ta->markers.first = ta->markers.last = NULL; tmp = (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line = (char *) MEM_mallocN(1, "textline_string"); @@ -399,7 +385,6 @@ Text *BKE_text_load(const char *file, const char *relpath) ta->id.us = 1; ta->lines.first = ta->lines.last = NULL; - ta->markers.first = ta->markers.last = NULL; ta->curl = ta->sell = NULL; if ((U.flag & USER_TXT_TABSTOSPACES_DISABLE) == 0) @@ -496,7 +481,6 @@ Text *BKE_text_copy(Text *ta) tan->flags = ta->flags | TXT_ISDIRTY; tan->lines.first = tan->lines.last = NULL; - tan->markers.first = tan->markers.last = NULL; tan->curl = tan->sell = NULL; tan->nlines = ta->nlines; @@ -785,23 +769,6 @@ static void txt_curs_sel(Text *text, TextLine ***linep, int **charp) *linep = &text->sell; *charp = &text->selc; } -static void txt_curs_first(Text *text, TextLine **linep, int *charp) -{ - if (text->curl == text->sell) { - *linep = text->curl; - if (text->curc < text->selc) *charp = text->curc; - else *charp = text->selc; - } - else if (txt_get_span(text->lines.first, text->curl) < txt_get_span(text->lines.first, text->sell)) { - *linep = text->curl; - *charp = text->curc; - } - else { - *linep = text->sell; - *charp = text->selc; - } -} - /*****************************/ /* Cursor movement functions */ /*****************************/ @@ -843,13 +810,11 @@ void txt_move_up(Text *text, short sel) { TextLine **linep; int *charp; - /* int old; */ /* UNUSED */ if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - /* old = *charp; */ /* UNUSED */ if ((*linep)->prev) { int index = txt_utf8_offset_to_index((*linep)->line, *charp); @@ -857,8 +822,6 @@ void txt_move_up(Text *text, short sel) if (index > txt_utf8_len((*linep)->line)) *charp = (*linep)->len; else *charp = txt_utf8_index_to_offset((*linep)->line, index); - if (!undoing) - txt_undo_add_op(text, sel ? UNDO_SUP : UNDO_CUP); } else { txt_move_bol(text, sel); @@ -871,22 +834,17 @@ void txt_move_down(Text *text, short sel) { TextLine **linep; int *charp; - /* int old; */ /* UNUSED */ if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - /* old = *charp; */ /* UNUSED */ if ((*linep)->next) { int index = txt_utf8_offset_to_index((*linep)->line, *charp); *linep = (*linep)->next; if (index > txt_utf8_len((*linep)->line)) *charp = (*linep)->len; else *charp = txt_utf8_index_to_offset((*linep)->line, index); - - if (!undoing) - txt_undo_add_op(text, sel ? UNDO_SDOWN : UNDO_CDOWN); } else { txt_move_eol(text, sel); @@ -898,7 +856,7 @@ void txt_move_down(Text *text, short sel) void txt_move_left(Text *text, short sel) { TextLine **linep; - int *charp, oundoing = undoing; + int *charp; int tabsize = 0, i = 0; if (!text) return; @@ -906,8 +864,6 @@ void txt_move_left(Text *text, short sel) else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - undoing = 1; - if (*charp == 0) { if ((*linep)->prev) { txt_move_up(text, sel); @@ -939,24 +895,19 @@ void txt_move_left(Text *text, short sel) } } - undoing = oundoing; - if (!undoing) txt_undo_add_op(text, sel ? UNDO_SLEFT : UNDO_CLEFT); - if (!sel) txt_pop_sel(text); } void txt_move_right(Text *text, short sel) { TextLine **linep; - int *charp, oundoing = undoing, do_tab = FALSE, i; + int *charp, do_tab = FALSE, i; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - undoing = 1; - if (*charp == (*linep)->len) { if ((*linep)->next) { txt_move_down(text, sel); @@ -984,124 +935,103 @@ void txt_move_right(Text *text, short sel) else (*charp) += BLI_str_utf8_size((*linep)->line + *charp); } - undoing = oundoing; - if (!undoing) txt_undo_add_op(text, sel ? UNDO_SRIGHT : UNDO_CRIGHT); - if (!sel) txt_pop_sel(text); } void txt_jump_left(Text *text, short sel) { TextLine **linep; - int *charp, oldc; + int *charp; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - oldc = *charp; BLI_str_cursor_step_utf8((*linep)->line, (*linep)->len, charp, STRCUR_DIR_PREV, STRCUR_JUMP_DELIM); if (!sel) txt_pop_sel(text); - if (!undoing) { - int span = txt_get_span(text->lines.first, *linep); - txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, span, oldc, span, (unsigned short)*charp); - } } void txt_jump_right(Text *text, short sel) { TextLine **linep; - int *charp, oldc; + int *charp; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); } if (!*linep) return; - oldc = *charp; BLI_str_cursor_step_utf8((*linep)->line, (*linep)->len, charp, STRCUR_DIR_NEXT, STRCUR_JUMP_DELIM); if (!sel) txt_pop_sel(text); - if (!undoing) { - int span = txt_get_span(text->lines.first, *linep); - txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, span, oldc, span, (unsigned short)*charp); - } } void txt_move_bol(Text *text, short sel) { TextLine **linep; - int *charp, old; + int *charp; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; - old = *charp; *charp = 0; if (!sel) txt_pop_sel(text); - if (!undoing) txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); } void txt_move_eol(Text *text, short sel) { TextLine **linep; - int *charp, old; + int *charp; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; - old = *charp; - + *charp = (*linep)->len; if (!sel) txt_pop_sel(text); - if (!undoing) txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); } void txt_move_bof(Text *text, short sel) { TextLine **linep; - int *charp, old; + int *charp; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; - old = *charp; *linep = text->lines.first; *charp = 0; if (!sel) txt_pop_sel(text); - if (!undoing) txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); } void txt_move_eof(Text *text, short sel) { TextLine **linep; - int *charp, old; + int *charp; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; - old = *charp; *linep = text->lines.last; *charp = (*linep)->len; if (!sel) txt_pop_sel(text); - if (!undoing) txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); } void txt_move_toline(Text *text, unsigned int line, short sel) @@ -1112,16 +1042,14 @@ void txt_move_toline(Text *text, unsigned int line, short sel) /* Moves to a certain byte in a line, not a certain utf8-character! */ void txt_move_to(Text *text, unsigned int line, unsigned int ch, short sel) { - TextLine **linep, *oldl; - int *charp, oldc; + TextLine **linep; + int *charp; unsigned int i; if (!text) return; if (sel) txt_curs_sel(text, &linep, &charp); else txt_curs_cur(text, &linep, &charp); if (!*linep) return; - oldc = *charp; - oldl = *linep; *linep = text->lines.first; for (i = 0; i < line; i++) { @@ -1133,7 +1061,6 @@ void txt_move_to(Text *text, unsigned int line, unsigned int ch, short sel) *charp = ch; if (!sel) txt_pop_sel(text); - if (!undoing) txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); } /****************************/ @@ -1152,8 +1079,6 @@ static void txt_curs_swap(Text *text) tmpc = text->curc; text->curc = text->selc; text->selc = tmpc; - - if (!undoing) txt_undo_add_op(text, UNDO_SWAP); } static void txt_pop_first(Text *text) @@ -1164,12 +1089,6 @@ static void txt_pop_first(Text *text) { txt_curs_swap(text); } - - if (!undoing) txt_undo_add_toop(text, UNDO_STO, - txt_get_span(text->lines.first, text->sell), - text->selc, - txt_get_span(text->lines.first, text->curl), - text->curc); txt_pop_sel(text); } @@ -1181,12 +1100,6 @@ static void txt_pop_last(Text *text) { txt_curs_swap(text); } - - if (!undoing) txt_undo_add_toop(text, UNDO_STO, - txt_get_span(text->lines.first, text->sell), - text->selc, - txt_get_span(text->lines.first, text->curl), - text->curc); txt_pop_sel(text); } @@ -1222,9 +1135,7 @@ int txt_has_sel(Text *text) static void txt_delete_sel(Text *text) { TextLine *tmpl; - TextMarker *mrk; char *buf; - int move, lineno; if (!text) return; if (!text->curl) return; @@ -1236,33 +1147,11 @@ static void txt_delete_sel(Text *text) if (!undoing) { buf = txt_sel_to_buf(text); - txt_undo_add_block(text, UNDO_DBLOCK, buf); + txt_undo_add_blockop(text, UNDO_DBLOCK, buf); MEM_freeN(buf); } buf = MEM_mallocN(text->curc + (text->sell->len - text->selc) + 1, "textline_string"); - - if (text->curl != text->sell) { - txt_clear_marker_region(text, text->curl, text->curc, text->curl->len, 0, 0); - move = txt_get_span(text->curl, text->sell); - } - else { - mrk = txt_find_marker_region(text, text->curl, text->curc, text->selc, 0, 0); - if (mrk && (mrk->start > text->curc || mrk->end < text->selc)) - txt_clear_marker_region(text, text->curl, text->curc, text->selc, 0, 0); - move = 0; - } - - mrk = txt_find_marker_region(text, text->sell, text->selc - 1, text->sell->len, 0, 0); - if (mrk) { - lineno = mrk->lineno; - do { - mrk->lineno -= move; - if (mrk->start > text->curc) mrk->start -= text->selc - text->curc; - mrk->end -= text->selc - text->curc; - mrk = mrk->next; - } while (mrk && mrk->lineno == lineno); - } strncpy(buf, text->curl->line, text->curc); strcpy(buf + text->curc, text->sell->line + text->selc); @@ -1491,19 +1380,9 @@ char *txt_sel_to_buf(Text *text) return buf; } -static void txt_shift_markers(Text *text, int lineno, int count) -{ - TextMarker *marker; - - for (marker = text->markers.first; marker; marker = marker->next) - if (marker->lineno >= lineno) { - marker->lineno += count; - } -} - void txt_insert_buf(Text *text, const char *in_buffer) { - int l = 0, u, len, lineno = -1, count = 0; + int l = 0, u, len; size_t i = 0, j; TextLine *add; char *buffer; @@ -1517,7 +1396,7 @@ void txt_insert_buf(Text *text, const char *in_buffer) buffer = BLI_strdupn(in_buffer, len); len += txt_extended_ascii_as_utf8(&buffer); - if (!undoing) txt_undo_add_block(text, UNDO_IBLOCK, buffer); + if (!undoing) txt_undo_add_blockop(text, UNDO_IBLOCK, buffer); u = undoing; undoing = 1; @@ -1530,9 +1409,6 @@ void txt_insert_buf(Text *text, const char *in_buffer) else { undoing = u; MEM_freeN(buffer); return; } i++; - /* Read as many full lines as we can */ - lineno = txt_get_span(text->lines.first, text->curl); - while (i < len) { l = 0; @@ -1544,14 +1420,8 @@ void txt_insert_buf(Text *text, const char *in_buffer) add = txt_new_linen(buffer + (i - l), l); BLI_insertlinkbefore(&text->lines, text->curl, add); i++; - count++; } else { - if (count) { - txt_shift_markers(text, lineno, count); - count = 0; - } - for (j = i - l; j < i && j < len; ) txt_add_raw_char(text, BLI_str_utf8_as_unicode_step(buffer, &j)); break; @@ -1560,10 +1430,6 @@ void txt_insert_buf(Text *text, const char *in_buffer) MEM_freeN(buffer); - if (count) { - txt_shift_markers(text, lineno, count); - } - undoing = u; } @@ -1599,6 +1465,7 @@ static void dump_buffer(Text *text) while (i++ < text->undo_pos) printf("%d: %d %c\n", i, text->undo_buf[i], text->undo_buf[i]); } +/* Note: this function is outdated and must be updated if needed for future use */ void txt_print_undo(Text *text) { int i = 0; @@ -1615,37 +1482,7 @@ void txt_print_undo(Text *text) while (i <= text->undo_pos) { op = text->undo_buf[i]; - if (op == UNDO_CLEFT) { - ops = "Cursor left"; - } - else if (op == UNDO_CRIGHT) { - ops = "Cursor right"; - } - else if (op == UNDO_CUP) { - ops = "Cursor up"; - } - else if (op == UNDO_CDOWN) { - ops = "Cursor down"; - } - else if (op == UNDO_SLEFT) { - ops = "Selection left"; - } - else if (op == UNDO_SRIGHT) { - ops = "Selection right"; - } - else if (op == UNDO_SUP) { - ops = "Selection up"; - } - else if (op == UNDO_SDOWN) { - ops = "Selection down"; - } - else if (op == UNDO_STO) { - ops = "Selection "; - } - else if (op == UNDO_CTO) { - ops = "Cursor "; - } - else if (op == UNDO_INSERT_1) { + if (op == UNDO_INSERT_1) { ops = "Insert ascii "; } else if (op == UNDO_INSERT_2) { @@ -1681,9 +1518,6 @@ void txt_print_undo(Text *text) else if (op == UNDO_DEL_4) { ops = "Delete unicode "; } - else if (op == UNDO_SWAP) { - ops = "Cursor swap"; - } else if (op == UNDO_DBLOCK) { ops = "Delete text block"; } @@ -1738,29 +1572,6 @@ void txt_print_undo(Text *text) } } } - else if (op == UNDO_STO || op == UNDO_CTO) { - i++; - - charp = text->undo_buf[i]; i++; - charp = charp + (text->undo_buf[i] << 8); i++; - - linep = text->undo_buf[i]; i++; - linep = linep + (text->undo_buf[i] << 8); i++; - linep = linep + (text->undo_buf[i] << 16); i++; - linep = linep + (text->undo_buf[i] << 24); i++; - - printf("to <%d, %d> ", linep, charp); - - charp = text->undo_buf[i]; i++; - charp = charp + (text->undo_buf[i] << 8); i++; - - linep = text->undo_buf[i]; i++; - linep = linep + (text->undo_buf[i] << 8); i++; - linep = linep + (text->undo_buf[i] << 16); i++; - linep = linep + (text->undo_buf[i] << 24); i++; - - printf("from <%d, %d>", linep, charp); - } else if (op == UNDO_DBLOCK || op == UNDO_IBLOCK) { i++; @@ -1811,16 +1622,6 @@ void txt_print_undo(Text *text) } } -static void txt_undo_add_op(Text *text, int op) -{ - if (!max_undo_test(text, 2)) - return; - - text->undo_pos++; - text->undo_buf[text->undo_pos] = op; - text->undo_buf[text->undo_pos + 1] = 0; -} - static void txt_undo_store_uint16(char *undo_buf, int *undo_pos, unsigned short value) { undo_buf[*undo_pos] = (value) & 0xff; @@ -1841,17 +1642,41 @@ static void txt_undo_store_uint32(char *undo_buf, int *undo_pos, unsigned int va (*undo_pos)++; } -static void txt_undo_add_block(Text *text, int op, const char *buf) +/* store the cur cursor to the undo buffer */ +static void txt_undo_store_cur(Text *text) +{ + txt_undo_store_uint16(text->undo_buf, &text->undo_pos, text->curc); + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, txt_get_span(text->lines.first, text->curl)); +} + +/* store the sel cursor to the undo buffer */ +static void txt_undo_store_sel(Text *text) +{ + txt_undo_store_uint16(text->undo_buf, &text->undo_pos, text->selc); + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, txt_get_span(text->lines.first, text->sell)); +} + +/* store both cursors to the undo buffer */ +static void txt_undo_store_cursors(Text *text) +{ + txt_undo_store_cur(text); + txt_undo_store_sel(text); +} + +/* store an operator along with a block of data */ +static void txt_undo_add_blockop(Text *text, int op, const char *buf) { unsigned int length = strlen(buf); - if (!max_undo_test(text, length + 11)) + if (!max_undo_test(text, length + 11 + 12)) return; text->undo_pos++; text->undo_buf[text->undo_pos] = op; text->undo_pos++; + txt_undo_store_cursors(text); + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, length); strncpy(text->undo_buf + text->undo_pos, buf, length); @@ -1863,34 +1688,30 @@ static void txt_undo_add_block(Text *text, int op, const char *buf) text->undo_buf[text->undo_pos + 1] = 0; } -void txt_undo_add_toop(Text *text, int op, unsigned int froml, unsigned short fromc, unsigned int tol, unsigned short toc) +/* store a regular operator */ +void txt_undo_add_op(Text *text, int op) { if (!max_undo_test(text, 15)) return; - if (froml == tol && fromc == toc) return; - text->undo_pos++; text->undo_buf[text->undo_pos] = op; text->undo_pos++; - txt_undo_store_uint16(text->undo_buf, &text->undo_pos, fromc); - txt_undo_store_uint32(text->undo_buf, &text->undo_pos, froml); - txt_undo_store_uint16(text->undo_buf, &text->undo_pos, toc); - txt_undo_store_uint32(text->undo_buf, &text->undo_pos, tol); + txt_undo_store_cursors(text); text->undo_buf[text->undo_pos] = op; - text->undo_buf[text->undo_pos + 1] = 0; } +/* store an operator for a single character */ static void txt_undo_add_charop(Text *text, int op_start, unsigned int c) { char utf8[BLI_UTF8_MAX]; size_t i, utf8_size = BLI_str_utf8_from_unicode(c, utf8); - if (!max_undo_test(text, 3 + utf8_size)) + if (!max_undo_test(text, 3 + utf8_size + 12)) return; text->undo_pos++; @@ -1899,6 +1720,8 @@ static void txt_undo_add_charop(Text *text, int op_start, unsigned int c) text->undo_buf[text->undo_pos] = op_start + utf8_size - 1; text->undo_pos++; + txt_undo_store_cur(text); + for (i = 0; i < utf8_size; i++) { text->undo_buf[text->undo_pos] = utf8[i]; text->undo_pos++; @@ -1909,6 +1732,9 @@ static void txt_undo_add_charop(Text *text, int op_start, unsigned int c) else { text->undo_buf[text->undo_pos] = op_start + 3; text->undo_pos++; + + txt_undo_store_cursors(text); + txt_undo_store_uint32(text->undo_buf, &text->undo_pos, c); text->undo_buf[text->undo_pos] = op_start + 3; } @@ -1934,6 +1760,29 @@ static unsigned int txt_undo_read_uint32(const char *undo_buf, int *undo_pos) return val; } +/* read the cur cursor from the undo buffer */ +static void txt_undo_read_cur(const char *undo_buf, int *undo_pos, unsigned int *curln, unsigned short *curc) +{ + *curln = txt_undo_read_uint32(undo_buf, undo_pos); + *curc = txt_undo_read_uint16(undo_buf, undo_pos); +} + +/* read the sel cursor from the undo buffer */ +static void txt_undo_read_sel(const char *undo_buf, int *undo_pos, unsigned int *selln, unsigned short *selc) +{ + *selln = txt_undo_read_uint32(undo_buf, undo_pos); + *selc = txt_undo_read_uint16(undo_buf, undo_pos); +} + +/* read both cursors from the undo buffer */ +static void txt_undo_read_cursors(const char *undo_buf, int *undo_pos, + unsigned int *curln, unsigned short *curc, + unsigned int *selln, unsigned short *selc) +{ + txt_undo_read_sel(undo_buf, undo_pos, selln, selc); + txt_undo_read_cur(undo_buf, undo_pos, curln, curc); +} + static unsigned int txt_undo_read_unicode(const char *undo_buf, int *undo_pos, short bytes) { unsigned int unicode; @@ -1986,6 +1835,29 @@ static unsigned int txt_redo_read_uint32(const char *undo_buf, int *undo_pos) return val; } +/* redo read cur cursor from the undo buffer */ +static void txt_redo_read_cur(const char *undo_buf, int *undo_pos, unsigned int *curln, unsigned short *curc) +{ + *curc = txt_redo_read_uint16(undo_buf, undo_pos); + *curln = txt_redo_read_uint32(undo_buf, undo_pos); +} + +/* redo read sel cursor from the undo buffer */ +static void txt_redo_read_sel(const char *undo_buf, int *undo_pos, unsigned int *selln, unsigned short *selc) +{ + *selc = txt_redo_read_uint16(undo_buf, undo_pos); + *selln = txt_redo_read_uint32(undo_buf, undo_pos); +} + +/* redo read both cursors from the undo buffer */ +static void txt_redo_read_cursors(const char *undo_buf, int *undo_pos, + unsigned int *curln, unsigned short *curc, + unsigned int *selln, unsigned short *selc) +{ + txt_redo_read_cur(undo_buf, undo_pos, curln, curc); + txt_redo_read_sel(undo_buf, undo_pos, selln, selc); +} + static unsigned int txt_redo_read_unicode(const char *undo_buf, int *undo_pos, short bytes) { unsigned int unicode; @@ -2024,9 +1896,10 @@ void txt_do_undo(Text *text) { int op = text->undo_buf[text->undo_pos]; unsigned int linep, i; + unsigned int uchar; + unsigned int curln, selln; + unsigned short curc, selc; unsigned short charp; - TextLine *holdl; - int holdc, holdln; char *buf; if (text->undo_pos < 0) { @@ -2038,88 +1911,60 @@ void txt_do_undo(Text *text) undoing = 1; switch (op) { - case UNDO_CLEFT: - txt_move_right(text, 0); - break; + case UNDO_INSERT_1: + case UNDO_INSERT_2: + case UNDO_INSERT_3: + case UNDO_INSERT_4: + text->undo_pos -= op - UNDO_INSERT_1 + 1; - case UNDO_CRIGHT: - txt_move_left(text, 0); - break; + /* get and restore the cursors */ + txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); - case UNDO_CUP: - txt_move_down(text, 0); - break; + txt_delete_char(text); - case UNDO_CDOWN: - txt_move_up(text, 0); - break; - - case UNDO_SLEFT: - txt_move_right(text, 1); - break; - - case UNDO_SRIGHT: - txt_move_left(text, 1); - break; - - case UNDO_SUP: - txt_move_down(text, 1); + text->undo_pos--; break; - case UNDO_SDOWN: - txt_move_up(text, 1); - break; - - case UNDO_CTO: - case UNDO_STO: - text->undo_pos--; - text->undo_pos--; - text->undo_pos--; - text->undo_pos--; - - text->undo_pos--; - text->undo_pos--; - - linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos); - charp = txt_undo_read_uint16(text->undo_buf, &text->undo_pos); - - if (op == UNDO_CTO) { - txt_move_toline(text, linep, 0); - text->curc = charp; - txt_pop_sel(text); - } - else { - txt_move_toline(text, linep, 1); - text->selc = charp; - } + case UNDO_BS_1: + case UNDO_BS_2: + case UNDO_BS_3: + case UNDO_BS_4: + charp = op - UNDO_BS_1 + 1; + uchar = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp); - text->undo_pos--; - break; + /* get and restore the cursors */ + txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); - case UNDO_INSERT_1: case UNDO_INSERT_2: case UNDO_INSERT_3: case UNDO_INSERT_4: - txt_backspace_char(text); - text->undo_pos -= op - UNDO_INSERT_1 + 1; - text->undo_pos--; - break; + txt_add_char(text, uchar); - case UNDO_BS_1: case UNDO_BS_2: case UNDO_BS_3: case UNDO_BS_4: - charp = op - UNDO_BS_1 + 1; - txt_add_char(text, txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp)); text->undo_pos--; break; - - case UNDO_DEL_1: case UNDO_DEL_2: case UNDO_DEL_3: case UNDO_DEL_4: + + case UNDO_DEL_1: + case UNDO_DEL_2: + case UNDO_DEL_3: + case UNDO_DEL_4: charp = op - UNDO_DEL_1 + 1; - txt_add_char(text, txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp)); + uchar = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp); + + /* get and restore the cursors */ + txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); + + txt_add_char(text, uchar); + txt_move_left(text, 0); - text->undo_pos--; - break; - case UNDO_SWAP: - txt_curs_swap(text); + text->undo_pos--; break; case UNDO_DBLOCK: + /* length of the string in the buffer */ linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos); buf = MEM_mallocN(linep + 1, "dblock buffer"); @@ -2128,34 +1973,33 @@ void txt_do_undo(Text *text) text->undo_pos--; } buf[i] = 0; - - txt_curs_first(text, &holdl, &holdc); - holdln = txt_get_span(text->lines.first, holdl); - - txt_insert_buf(text, buf); - MEM_freeN(buf); - - text->curl = text->lines.first; - while (holdln > 0) { - if (text->curl->next) - text->curl = text->curl->next; - - holdln--; - } - text->curc = holdc; + /* skip over the length that was stored again */ text->undo_pos--; text->undo_pos--; text->undo_pos--; text->undo_pos--; + /* Get the cursor positions */ + txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + + /* move cur to location that needs buff inserted */ + txt_move_to(text, curln, curc, 0); + + txt_insert_buf(text, buf); + MEM_freeN(buf); + + /* restore the cursors */ + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); + text->undo_pos--; break; case UNDO_IBLOCK: + /* length of the string in the buffer */ linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos); - txt_delete_sel(text); /* txt_backspace_char removes utf8-characters, not bytes */ buf = MEM_mallocN(linep + 1, "iblock buffer"); @@ -2167,47 +2011,32 @@ void txt_do_undo(Text *text) linep = txt_utf8_len(buf); MEM_freeN(buf); - while (linep > 0) { - txt_backspace_char(text); - linep--; - } - + /* skip over the length that was stored again */ text->undo_pos--; text->undo_pos--; - text->undo_pos--; text->undo_pos--; - text->undo_pos--; + + /* get and restore the cursors */ + txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc + linep, 1); + + txt_delete_selected(text); + text->undo_pos--; break; case UNDO_INDENT: case UNDO_UNINDENT: case UNDO_COMMENT: case UNDO_UNCOMMENT: - linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos); - //linep is now the end line of the selection - - charp = txt_undo_read_uint16(text->undo_buf, &text->undo_pos); - //charp is the last char selected or text->line->len - - //set the selection for this now - text->selc = charp; - text->sell = text->lines.first; - for (i = 0; i < linep; i++) { - text->sell = text->sell->next; - } - - linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos); - //first line to be selected - - charp = txt_undo_read_uint16(text->undo_buf, &text->undo_pos); - //first postion to be selected - text->curc = charp; - text->curl = text->lines.first; - for (i = 0; i < linep; i++) { - text->curl = text->curl->next; - } - + case UNDO_DUPLICATE: + case UNDO_MOVE_LINES_UP: + case UNDO_MOVE_LINES_DOWN: + /* get and restore the cursors */ + txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); if (op == UNDO_INDENT) { txt_unindent(text); @@ -2221,37 +2050,24 @@ void txt_do_undo(Text *text) else if (op == UNDO_UNCOMMENT) { txt_comment(text); } + else if (op == UNDO_DUPLICATE) { + txt_delete_line(text, text->curl->next); + } + else if (op == UNDO_MOVE_LINES_UP) { + txt_move_lines(text, TXT_MOVE_LINE_DOWN); + } + else if (op == UNDO_MOVE_LINES_DOWN) { + txt_move_lines(text, TXT_MOVE_LINE_UP); + } text->undo_pos--; break; - case UNDO_DUPLICATE: - txt_delete_line(text, text->curl->next); - break; - case UNDO_MOVE_LINES_UP: - txt_move_lines(text, TXT_MOVE_LINE_DOWN); - break; - case UNDO_MOVE_LINES_DOWN: - txt_move_lines(text, TXT_MOVE_LINE_UP); - break; default: //XXX error("Undo buffer error - resetting"); text->undo_pos = -1; break; } - - /* next undo step may need evaluating */ - if (text->undo_pos >= 0) { - switch (text->undo_buf[text->undo_pos]) { - case UNDO_STO: - txt_do_undo(text); - txt_do_redo(text); /* selections need restoring */ - break; - case UNDO_SWAP: - txt_do_undo(text); /* swaps should appear transparent */ - break; - } - } undoing = 0; } @@ -2259,9 +2075,12 @@ void txt_do_undo(Text *text) void txt_do_redo(Text *text) { char op; - unsigned int linep, i; - unsigned short charp; char *buf; + unsigned int linep; + unsigned short charp; + unsigned int uchar; + unsigned int curln, selln; + unsigned short curc, selc; text->undo_pos++; op = text->undo_buf[text->undo_pos]; @@ -2274,104 +2093,91 @@ void txt_do_redo(Text *text) undoing = 1; switch (op) { - case UNDO_CLEFT: - txt_move_left(text, 0); - break; - - case UNDO_CRIGHT: - txt_move_right(text, 0); - break; + case UNDO_INSERT_1: + case UNDO_INSERT_2: + case UNDO_INSERT_3: + case UNDO_INSERT_4: + text->undo_pos++; - case UNDO_CUP: - txt_move_up(text, 0); - break; + /* get and restore the cursors */ + txt_redo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); - case UNDO_CDOWN: - txt_move_down(text, 0); - break; - - case UNDO_SLEFT: - txt_move_left(text, 1); - break; - - case UNDO_SRIGHT: - txt_move_right(text, 1); - break; - - case UNDO_SUP: - txt_move_up(text, 1); - break; - - case UNDO_SDOWN: - txt_move_down(text, 1); - break; - - case UNDO_INSERT_1: case UNDO_INSERT_2: case UNDO_INSERT_3: case UNDO_INSERT_4: - text->undo_pos++; charp = op - UNDO_INSERT_1 + 1; - txt_add_char(text, txt_redo_read_unicode(text->undo_buf, &text->undo_pos, charp)); - break; + uchar = txt_redo_read_unicode(text->undo_buf, &text->undo_pos, charp); - case UNDO_BS_1: case UNDO_BS_2: case UNDO_BS_3: case UNDO_BS_4: - text->undo_pos++; - txt_backspace_char(text); - text->undo_pos += op - UNDO_BS_1 + 1; + txt_add_char(text, uchar); break; - case UNDO_DEL_1: case UNDO_DEL_2: case UNDO_DEL_3: case UNDO_DEL_4: + case UNDO_BS_1: + case UNDO_BS_2: + case UNDO_BS_3: + case UNDO_BS_4: text->undo_pos++; - txt_delete_char(text); - text->undo_pos += op - UNDO_DEL_1 + 1; - break; - case UNDO_SWAP: - txt_curs_swap(text); - txt_do_redo(text); /* swaps should appear transparent a*/ - break; + /* get and restore the cursors */ + txt_redo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); + + text->undo_pos += op - UNDO_BS_1 + 1; - case UNDO_CTO: - case UNDO_STO: - text->undo_pos++; - text->undo_pos++; + /* move right so we backspace the correct char */ + txt_move_right(text, 0); + txt_backspace_char(text); - text->undo_pos++; - text->undo_pos++; - text->undo_pos++; - text->undo_pos++; + break; + case UNDO_DEL_1: + case UNDO_DEL_2: + case UNDO_DEL_3: + case UNDO_DEL_4: text->undo_pos++; - charp = txt_redo_read_uint16(text->undo_buf, &text->undo_pos); - linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos); + /* get and restore the cursors */ + txt_redo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); - if (op == UNDO_CTO) { - txt_move_toline(text, linep, 0); - text->curc = charp; - txt_pop_sel(text); - } - else { - txt_move_toline(text, linep, 1); - text->selc = charp; - } + text->undo_pos += op - UNDO_DEL_1 + 1; + + txt_delete_char(text); break; case UNDO_DBLOCK: text->undo_pos++; + + /* get and restore the cursors */ + txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); + + /* length of the block */ linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos); - txt_delete_sel(text); text->undo_pos += linep; + /* skip over the length that was stored again */ text->undo_pos++; text->undo_pos++; text->undo_pos++; text->undo_pos++; + txt_delete_sel(text); + break; case UNDO_IBLOCK: text->undo_pos++; + + /* get and restore the cursors */ + txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, curln, curc, 1); + + /* length of the block */ linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos); buf = MEM_mallocN(linep + 1, "iblock buffer"); @@ -2382,40 +2188,27 @@ void txt_do_redo(Text *text) txt_insert_buf(text, buf); MEM_freeN(buf); + /* skip over the length that was stored again */ text->undo_pos++; text->undo_pos++; text->undo_pos++; text->undo_pos++; + break; case UNDO_INDENT: case UNDO_UNINDENT: case UNDO_COMMENT: case UNDO_UNCOMMENT: + case UNDO_DUPLICATE: + case UNDO_MOVE_LINES_UP: + case UNDO_MOVE_LINES_DOWN: text->undo_pos++; - charp = txt_redo_read_uint16(text->undo_buf, &text->undo_pos); - //charp is the first char selected or 0 - - linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos); - //linep is now the first line of the selection - //set the selcetion for this now - text->curc = charp; - text->curl = text->lines.first; - for (i = 0; i < linep; i++) { - text->curl = text->curl->next; - } - - charp = txt_redo_read_uint16(text->undo_buf, &text->undo_pos); - //last postion to be selected - - linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos); - //Last line to be selected - - text->selc = charp; - text->sell = text->lines.first; - for (i = 0; i < linep; i++) { - text->sell = text->sell->next; - } + + /* get and restore the cursors */ + txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc); + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); if (op == UNDO_INDENT) { txt_indent(text); @@ -2429,15 +2222,28 @@ void txt_do_redo(Text *text) else if (op == UNDO_UNCOMMENT) { txt_uncomment(text); } - break; - case UNDO_DUPLICATE: - txt_duplicate_line(text); - break; - case UNDO_MOVE_LINES_UP: - txt_move_lines(text, TXT_MOVE_LINE_UP); - break; - case UNDO_MOVE_LINES_DOWN: - txt_move_lines(text, TXT_MOVE_LINE_DOWN); + else if (op == UNDO_DUPLICATE) { + txt_duplicate_line(text); + } + else if (op == UNDO_MOVE_LINES_UP) { + /* offset the cursor by + 1 */ + txt_move_to(text, curln + 1, curc, 0); + txt_move_to(text, selln + 1, selc, 1); + + txt_move_lines(text, TXT_MOVE_LINE_UP); + } + else if (op == UNDO_MOVE_LINES_DOWN) { + /* offset the cursor by - 1 */ + txt_move_to(text, curln - 1, curc, 0); + txt_move_to(text, selln - 1, selc, 1); + + txt_move_lines(text, TXT_MOVE_LINE_DOWN); + } + + /* re-restore the cursors since they got moved when redoing */ + txt_move_to(text, curln, curc, 0); + txt_move_to(text, selln, selc, 1); + break; default: //XXX error("Undo buffer error - resetting"); @@ -2456,31 +2262,13 @@ void txt_do_redo(Text *text) void txt_split_curline(Text *text) { TextLine *ins; - TextMarker *mrk; char *left, *right; - int lineno = -1; if (!text) return; if (!text->curl) return; txt_delete_sel(text); - /* Move markers */ - - lineno = txt_get_span(text->lines.first, text->curl); - mrk = text->markers.first; - while (mrk) { - if (mrk->lineno == lineno && mrk->start > text->curc) { - mrk->lineno++; - mrk->start -= text->curc; - mrk->end -= text->curc; - } - else if (mrk->lineno > lineno) { - mrk->lineno++; - } - mrk = mrk->next; - } - /* Make the two half strings */ left = MEM_mallocN(text->curc + 1, "textline_string"); @@ -2517,23 +2305,9 @@ void txt_split_curline(Text *text) static void txt_delete_line(Text *text, TextLine *line) { - TextMarker *mrk = NULL, *nxt; - int lineno = -1; - if (!text) return; if (!text->curl) return; - lineno = txt_get_span(text->lines.first, line); - mrk = text->markers.first; - while (mrk) { - nxt = mrk->next; - if (mrk->lineno == lineno) - BLI_freelinkN(&text->markers, mrk); - else if (mrk->lineno > lineno) - mrk->lineno--; - mrk = nxt; - } - BLI_remlink(&text->lines, line); if (line->line) MEM_freeN(line->line); @@ -2548,25 +2322,12 @@ static void txt_delete_line(Text *text, TextLine *line) static void txt_combine_lines(Text *text, TextLine *linea, TextLine *lineb) { char *tmp; - TextMarker *mrk = NULL; - int lineno = -1; - + if (!text) return; if (!linea || !lineb) return; - mrk = txt_find_marker_region(text, lineb, 0, lineb->len, 0, 0); - if (mrk) { - lineno = mrk->lineno; - do { - mrk->lineno--; - mrk->start += linea->len; - mrk->end += linea->len; - mrk = mrk->next; - } while (mrk && mrk->lineno == lineno); - } - if (lineno == -1) lineno = txt_get_span(text->lines.first, lineb); - + tmp = MEM_mallocN(linea->len + lineb->len + 1, "textline_string"); strcpy(tmp, linea->line); @@ -2619,27 +2380,7 @@ void txt_delete_char(Text *text) } else { /* Just deleting a char */ size_t c_len = 0; - TextMarker *mrk; c = BLI_str_utf8_as_unicode_and_size(text->curl->line + text->curc, &c_len); - - mrk = txt_find_marker_region(text, text->curl, text->curc - c_len, text->curl->len, 0, 0); - if (mrk) { - int lineno = mrk->lineno; - if (mrk->end == text->curc) { - if ((mrk->flags & TMARK_TEMP) && !(mrk->flags & TMARK_EDITALL)) { - txt_clear_markers(text, mrk->group, TMARK_TEMP); - } - else { - BLI_freelinkN(&text->markers, mrk); - } - return; - } - do { - if (mrk->start > text->curc) mrk->start -= c_len; - mrk->end -= c_len; - mrk = mrk->next; - } while (mrk && mrk->lineno == lineno); - } memmove(text->curl->line + text->curc, text->curl->line + text->curc + c_len, text->curl->len - text->curc - c_len + 1); @@ -2683,28 +2424,8 @@ void txt_backspace_char(Text *text) } else { /* Just backspacing a char */ size_t c_len = 0; - TextMarker *mrk; char *prev = BLI_str_prev_char_utf8(text->curl->line + text->curc); c = BLI_str_utf8_as_unicode_and_size(prev, &c_len); - - mrk = txt_find_marker_region(text, text->curl, text->curc - c_len, text->curl->len, 0, 0); - if (mrk) { - int lineno = mrk->lineno; - if (mrk->start == text->curc) { - if ((mrk->flags & TMARK_TEMP) && !(mrk->flags & TMARK_EDITALL)) { - txt_clear_markers(text, mrk->group, TMARK_TEMP); - } - else { - BLI_freelinkN(&text->markers, mrk); - } - return; - } - do { - if (mrk->start > text->curc - c_len) mrk->start -= c_len; - mrk->end -= c_len; - mrk = mrk->next; - } while (mrk && mrk->lineno == lineno); - } /* source and destination overlap, don't use memcpy() */ memmove(text->curl->line + text->curc - c_len, @@ -2746,9 +2467,7 @@ static void txt_convert_tab_to_spaces(Text *text) static int txt_add_char_intern(Text *text, unsigned int add, int replace_tabs) { - int lineno; char *tmp, ch[BLI_UTF8_MAX]; - TextMarker *mrk; size_t add_len; if (!text) return 0; @@ -2767,16 +2486,9 @@ static int txt_add_char_intern(Text *text, unsigned int add, int replace_tabs) txt_delete_sel(text); + if (!undoing) txt_undo_add_charop(text, UNDO_INSERT_1, add); + add_len = BLI_str_utf8_from_unicode(add, ch); - mrk = txt_find_marker_region(text, text->curl, text->curc - 1, text->curl->len, 0, 0); - if (mrk) { - lineno = mrk->lineno; - do { - if (mrk->start > text->curc) mrk->start += add_len; - mrk->end += add_len; - mrk = mrk->next; - } while (mrk && mrk->lineno == lineno); - } tmp = MEM_mallocN(text->curl->len + add_len + 1, "textline_string"); @@ -2793,7 +2505,6 @@ static int txt_add_char_intern(Text *text, unsigned int add, int replace_tabs) txt_make_dirty(text); txt_clean_text(text); - if (!undoing) txt_undo_add_charop(text, UNDO_INSERT_1, add); return 1; } @@ -2824,10 +2535,7 @@ int txt_replace_char(Text *text, unsigned int add) /* If text is selected or we're at the end of the line just use txt_add_char */ if (text->curc == text->curl->len || txt_has_sel(text) || add == '\n') { - int i = txt_add_char(text, add); - TextMarker *mrk = txt_find_marker(text, text->curl, text->curc, 0, 0); - if (mrk) BLI_freelinkN(&text->markers, mrk); - return i; + return txt_add_char(text, add); } del = BLI_str_utf8_as_unicode_and_size(text->curl->line + text->curc, &del_size); @@ -2854,8 +2562,8 @@ int txt_replace_char(Text *text, unsigned int add) /* Should probably create a new op for this */ if (!undoing) { - txt_undo_add_charop(text, UNDO_DEL_1, del); txt_undo_add_charop(text, UNDO_INSERT_1, add); + txt_undo_add_charop(text, UNDO_DEL_1, del); } return 1; } @@ -2924,7 +2632,7 @@ void txt_indent(Text *text) } if (!undoing) { - txt_undo_add_toop(text, UNDO_INDENT, txt_get_span(text->lines.first, text->curl), text->curc, txt_get_span(text->lines.first, text->sell), text->selc); + txt_undo_add_op(text, UNDO_INDENT); } } @@ -2982,7 +2690,7 @@ void txt_unindent(Text *text) } if (!undoing) { - txt_undo_add_toop(text, UNDO_UNINDENT, txt_get_span(text->lines.first, text->curl), text->curc, txt_get_span(text->lines.first, text->sell), text->selc); + txt_undo_add_op(text, UNDO_UNINDENT); } } @@ -3031,7 +2739,7 @@ void txt_comment(Text *text) } if (!undoing) { - txt_undo_add_toop(text, UNDO_COMMENT, txt_get_span(text->lines.first, text->curl), text->curc, txt_get_span(text->lines.first, text->sell), text->selc); + txt_undo_add_op(text, UNDO_COMMENT); } } @@ -3076,7 +2784,7 @@ void txt_uncomment(Text *text) } if (!undoing) { - txt_undo_add_toop(text, UNDO_UNCOMMENT, txt_get_span(text->lines.first, text->curl), text->curc, txt_get_span(text->lines.first, text->sell), text->selc); + txt_undo_add_op(text, UNDO_UNCOMMENT); } } @@ -3165,157 +2873,6 @@ int setcurr_tab_spaces(Text *text, int space) return i; } -/*********************************/ -/* Text marker utility functions */ -/*********************************/ - -/* Creates and adds a marker to the list maintaining sorted order */ -void txt_add_marker(Text *text, TextLine *line, int start, int end, const unsigned char color[4], int group, int flags) -{ - TextMarker *tmp, *marker; - - marker = MEM_mallocN(sizeof(TextMarker), "text_marker"); - - marker->lineno = txt_get_span(text->lines.first, line); - marker->start = MIN2(start, end); - marker->end = MAX2(start, end); - marker->group = group; - marker->flags = flags; - - marker->color[0] = color[0]; - marker->color[1] = color[1]; - marker->color[2] = color[2]; - marker->color[3] = color[3]; - - for (tmp = text->markers.last; tmp; tmp = tmp->prev) - if (tmp->lineno < marker->lineno || (tmp->lineno == marker->lineno && tmp->start < marker->start)) - break; - - if (tmp) BLI_insertlinkafter(&text->markers, tmp, marker); - else BLI_addhead(&text->markers, marker); -} - -/* Returns the first matching marker on the specified line between two points. - * If the group or flags fields are non-zero the returned flag must be in the - * specified group and have at least the specified flags set. */ -TextMarker *txt_find_marker_region(Text *text, TextLine *line, int start, int end, int group, int flags) -{ - TextMarker *marker, *next; - int lineno = txt_get_span(text->lines.first, line); - - for (marker = text->markers.first; marker; marker = next) { - next = marker->next; - - if (group && marker->group != group) continue; - else if ((marker->flags & flags) != flags) continue; - else if (marker->lineno < lineno) continue; - else if (marker->lineno > lineno) break; - - if ((marker->start == marker->end && start <= marker->start && marker->start <= end) || - (marker->start < end && marker->end > start)) - { - return marker; - } - } - return NULL; -} - -/* Clears all markers on the specified line between two points. If the group or - * flags fields are non-zero the returned flag must be in the specified group - * and have at least the specified flags set. */ -short txt_clear_marker_region(Text *text, TextLine *line, int start, int end, int group, int flags) -{ - TextMarker *marker, *next; - int lineno = txt_get_span(text->lines.first, line); - short cleared = 0; - - for (marker = text->markers.first; marker; marker = next) { - next = marker->next; - - if (group && marker->group != group) continue; - else if ((marker->flags & flags) != flags) continue; - else if (marker->lineno < lineno) continue; - else if (marker->lineno > lineno) break; - - if ((marker->start == marker->end && start <= marker->start && marker->start <= end) || - (marker->start < end && marker->end > start)) - { - BLI_freelinkN(&text->markers, marker); - cleared = 1; - } - } - return cleared; -} - -/* Clears all markers in the specified group (if given) with at least the - * specified flags set. Useful for clearing temporary markers (group = 0, - * flags = TMARK_TEMP) */ -short txt_clear_markers(Text *text, int group, int flags) -{ - TextMarker *marker, *next; - short cleared = 0; - - for (marker = text->markers.first; marker; marker = next) { - next = marker->next; - - if ((!group || marker->group == group) && - (marker->flags & flags) == flags) - { - BLI_freelinkN(&text->markers, marker); - cleared = 1; - } - } - return cleared; -} - -/* Finds the marker at the specified line and cursor position with at least the - * specified flags set in the given group (if non-zero). */ -TextMarker *txt_find_marker(Text *text, TextLine *line, int curs, int group, int flags) -{ - TextMarker *marker; - int lineno = txt_get_span(text->lines.first, line); - - for (marker = text->markers.first; marker; marker = marker->next) { - if (group && marker->group != group) continue; - else if ((marker->flags & flags) != flags) continue; - else if (marker->lineno < lineno) continue; - else if (marker->lineno > lineno) break; - - if (marker->start <= curs && curs <= marker->end) - return marker; - } - return NULL; -} - -/* Finds the previous marker in the same group. If no other is found, the same - * marker will be returned */ -TextMarker *txt_prev_marker(Text *text, TextMarker *marker) -{ - TextMarker *tmp = marker; - while (tmp) { - if (tmp->prev) tmp = tmp->prev; - else tmp = text->markers.last; - if (tmp->group == marker->group) - return tmp; - } - return NULL; /* Only if (marker == NULL) */ -} - -/* Finds the next marker in the same group. If no other is found, the same - * marker will be returned */ -TextMarker *txt_next_marker(Text *text, TextMarker *marker) -{ - TextMarker *tmp = marker; - while (tmp) { - if (tmp->next) tmp = tmp->next; - else tmp = text->markers.first; - if (tmp->group == marker->group) - return tmp; - } - return NULL; /* Only if (marker == NULL) */ -} - - /*******************************/ /* Character utility functions */ /*******************************/ diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index b174f27b7e1..30b48401046 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1124,10 +1124,10 @@ void BKE_tracking_marker_pattern_minmax(const MovieTrackingMarker *marker, float { INIT_MINMAX2(min, max); - DO_MINMAX2(marker->pattern_corners[0], min, max); - DO_MINMAX2(marker->pattern_corners[1], min, max); - DO_MINMAX2(marker->pattern_corners[2], min, max); - DO_MINMAX2(marker->pattern_corners[3], min, max); + minmax_v2v2_v2(min, max, marker->pattern_corners[0]); + minmax_v2v2_v2(min, max, marker->pattern_corners[1]); + minmax_v2v2_v2(min, max, marker->pattern_corners[2]); + minmax_v2v2_v2(min, max, marker->pattern_corners[3]); } void BKE_tracking_marker_get_subframe_position(MovieTrackingTrack *track, float framenr, float pos[2]) @@ -3161,7 +3161,7 @@ static int stabilization_median_point_get(MovieTracking *tracking, int framenr, if (track->flag & TRACK_USE_2D_STAB) { MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); - DO_MINMAX2(marker->pos, min, max); + minmax_v2v2_v2(min, max, marker->pos); ok = TRUE; } diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index da9c919c109..0f861a7ed37 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -111,6 +111,11 @@ static void delete_picture(AVFrame *f) } } +static int use_float_audio_buffer(int codec_id) +{ + return codec_id == CODEC_ID_AAC || codec_id == CODEC_ID_AC3 || codec_id == CODEC_ID_VORBIS; +} + #ifdef WITH_AUDASPACE static int write_audio_frame(void) { @@ -599,12 +604,14 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex /* Prepare an audio stream for the output file */ -static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContext *of) +static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContext *of, char *error, int error_size) { AVStream *st; AVCodecContext *c; AVCodec *codec; + error[0] = '\0'; + st = av_new_stream(of, 1); if (!st) return NULL; @@ -616,6 +623,10 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex c->bit_rate = ffmpeg_audio_bitrate * 1000; c->sample_fmt = AV_SAMPLE_FMT_S16; c->channels = rd->ffcodecdata.audio_channels; + if (use_float_audio_buffer(codec_id)) { + c->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; + c->sample_fmt = AV_SAMPLE_FMT_FLT; + } codec = avcodec_find_encoder(c->codec_id); if (!codec) { //XXX error("Couldn't find a valid audio codec"); @@ -626,6 +637,7 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex if (avcodec_open(c, codec) < 0) { //XXX error("Couldn't initialize audio codec"); + BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size); return NULL; } @@ -646,7 +658,12 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex audio_output_buffer = (uint8_t *) av_malloc(audio_outbuf_size); - audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * sizeof(int16_t)); + if (use_float_audio_buffer(codec_id)) { + audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * sizeof(float)); + } + else { + audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * sizeof(int16_t)); + } audio_time = 0.0f; @@ -801,9 +818,12 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report } if (ffmpeg_audio_codec != CODEC_ID_NONE) { - audio_stream = alloc_audio_stream(rd, fmt->audio_codec, of); + audio_stream = alloc_audio_stream(rd, fmt->audio_codec, of, error, sizeof(error)); if (!audio_stream) { - BKE_report(reports, RPT_ERROR, "Error initializing audio stream"); + if (error[0]) + BKE_report(reports, RPT_ERROR, error); + else + BKE_report(reports, RPT_ERROR, "Error initializing audio stream"); av_dict_free(&opts); return 0; } @@ -943,7 +963,12 @@ int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty, AVCodecContext *c = audio_stream->codec; AUD_DeviceSpecs specs; specs.channels = c->channels; - specs.format = AUD_FORMAT_S16; + if (use_float_audio_buffer(c->codec_id)) { + specs.format = AUD_FORMAT_FLOAT32; + } + else { + specs.format = AUD_FORMAT_S16; + } specs.rate = rd->ffcodecdata.audio_mixrate; audio_mixdown_device = sound_mixdown(scene, specs, rd->sfra, rd->ffcodecdata.audio_volume); #ifdef FFMPEG_CODEC_TIME_BASE diff --git a/source/blender/blenlib/BLI_endian_switch_inline.h b/source/blender/blenlib/BLI_endian_switch_inline.h index 4bc6d3828b9..358206f1177 100644 --- a/source/blender/blenlib/BLI_endian_switch_inline.h +++ b/source/blender/blenlib/BLI_endian_switch_inline.h @@ -38,41 +38,43 @@ /* *** 16 *** */ BLI_INLINE void BLI_endian_switch_int16(short *val) { - short tval = *val; - *val = (tval >> 8) | - (tval << 8); - + BLI_endian_switch_uint16((unsigned short *)val); } BLI_INLINE void BLI_endian_switch_uint16(unsigned short *val) { - BLI_endian_switch_int16((short *)val); + unsigned short tval = *val; + *val = (tval >> 8) | + (tval << 8); } /* *** 32 *** */ BLI_INLINE void BLI_endian_switch_int32(int *val) { - int tval = *val; + BLI_endian_switch_uint32((unsigned int *)val); +} +BLI_INLINE void BLI_endian_switch_uint32(unsigned int *val) +{ + unsigned int tval = *val; *val = ((tval >> 24)) | ((tval << 8) & 0x00ff0000) | ((tval >> 8) & 0x0000ff00) | ((tval << 24)); - -} -BLI_INLINE void BLI_endian_switch_uint32(unsigned int *val) -{ - BLI_endian_switch_int32((int *)val); } BLI_INLINE void BLI_endian_switch_float(float *val) { - BLI_endian_switch_int32((int *)val); + BLI_endian_switch_uint32((unsigned int *)val); } /* *** 64 *** */ BLI_INLINE void BLI_endian_switch_int64(int64_t *val) { - int64_t tval = *val; + BLI_endian_switch_uint64((uint64_t *)val); +} +BLI_INLINE void BLI_endian_switch_uint64(uint64_t *val) +{ + uint64_t tval = *val; *val = ((tval >> 56)) | ((tval << 40) & 0x00ff000000000000ll) | ((tval << 24) & 0x0000ff0000000000ll) | @@ -82,13 +84,9 @@ BLI_INLINE void BLI_endian_switch_int64(int64_t *val) ((tval >> 40) & 0x000000000000ff00ll) | ((tval << 56)); } -BLI_INLINE void BLI_endian_switch_uint64(uint64_t *val) -{ - BLI_endian_switch_int64((int64_t *)val); -} BLI_INLINE void BLI_endian_switch_double(double *val) { - BLI_endian_switch_int64((int64_t *)val); + BLI_endian_switch_uint64((uint64_t *)val); } #endif /* __BLI_ENDIAN_SWITCH_INLINE_H__ */ diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h index c26e6cd15b3..7eac1425a5c 100644 --- a/source/blender/blenlib/BLI_ghash.h +++ b/source/blender/blenlib/BLI_ghash.h @@ -71,7 +71,7 @@ void BLI_ghash_insert(GHash *gh, void *key, void *val); void *BLI_ghash_lookup(GHash *gh, const void *key); int BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp); -int BLI_ghash_haskey(GHash *gh, void *key); +int BLI_ghash_haskey(GHash *gh, const void *key); int BLI_ghash_size(GHash *gh); /* *** */ diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h index 2b513cbec41..69d6478e0e2 100644 --- a/source/blender/blenlib/BLI_math_base.h +++ b/source/blender/blenlib/BLI_math_base.h @@ -170,7 +170,7 @@ } (void)0 #endif -#ifdef __BLI_MATH_INLINE_H__ +#if BLI_MATH_DO_INLINE #include "intern/math_base_inline.c" #endif @@ -203,7 +203,7 @@ MINLINE int is_power_of_2_i(int n); MINLINE int power_of_2_max_i(int n); MINLINE int power_of_2_min_i(int n); -MINLINE float shell_angle_to_dist(float angle); +MINLINE float shell_angle_to_dist(const float angle); #if (defined(WIN32) || defined(WIN64)) && !defined(FREE_WINDOWS) extern double copysign(double x, double y); diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h index 7c8bf88943d..c71463da61d 100644 --- a/source/blender/blenlib/BLI_math_color.h +++ b/source/blender/blenlib/BLI_math_color.h @@ -121,7 +121,7 @@ MINLINE int compare_rgb_uchar(const unsigned char a[3], const unsigned char b[3] void lift_gamma_gain_to_asc_cdl(float *lift, float *gamma, float *gain, float *offset, float *slope, float *power); -#ifdef __BLI_MATH_INLINE_H__ +#if BLI_MATH_DO_INLINE #include "intern/math_color_inline.c" #endif diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 80169e952bf..cfd163d4e57 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -36,7 +36,7 @@ extern "C" { #include "BLI_math_inline.h" -#ifdef __BLI_MATH_INLINE_H__ +#if BLI_MATH_DO_INLINE #include "intern/math_geom_inline.c" #endif @@ -187,6 +187,10 @@ int barycentric_inside_triangle_v2(const float w[3]); void resolve_tri_uv(float r_uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2]); void resolve_quad_uv(float uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2]); +/* use to find the point of a UV on a face */ +void interp_bilinear_quad_v3(float data[4][3], float u, float v, float res[3]); +void interp_barycentric_tri_v3(float data[3][3], float u, float v, float res[3]); + /***************************** View & Projection *****************************/ void lookat_m4(float mat[4][4], float vx, float vy, diff --git a/source/blender/blenlib/BLI_math_inline.h b/source/blender/blenlib/BLI_math_inline.h index ce43d5fb941..6dad44644f2 100644 --- a/source/blender/blenlib/BLI_math_inline.h +++ b/source/blender/blenlib/BLI_math_inline.h @@ -35,9 +35,10 @@ extern "C" { #endif /* add platform/compiler checks here if it is not supported */ -#define __BLI_MATH_INLINE_H__ +/* all platforms support forcing inline so this is always enabled */ +#define BLI_MATH_DO_INLINE 1 -#ifdef __BLI_MATH_INLINE_H__ +#if BLI_MATH_DO_INLINE # ifdef _MSC_VER # define MINLINE static __forceinline # define MALWAYS_INLINE MINLINE diff --git a/source/blender/blenlib/BLI_math_interp.h b/source/blender/blenlib/BLI_math_interp.h index 3a107be32bd..21975763779 100644 --- a/source/blender/blenlib/BLI_math_interp.h +++ b/source/blender/blenlib/BLI_math_interp.h @@ -29,7 +29,16 @@ #ifndef BLI_MATH_INTERP #define BLI_MATH_INTERP -void BLI_bicubic_interpolation(const float *buffer, float *output, int width, int height, int components, float u, float v); -void BLI_bilinear_interpolation(const float *buffer, float *output, int width, int height, int components, float u, float v); +void BLI_bicubic_interpolation_fl(const float *buffer, float *output, int width, int height, + int components, float u, float v); + +void BLI_bicubic_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height, + int components, float u, float v); + +void BLI_bilinear_interpolation_fl(const float *buffer, float *output, int width, int height, + int components, float u, float v); + +void BLI_bilinear_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height, + int components, float u, float v); #endif diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 77c0ec0a88f..f4572afec84 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -36,7 +36,7 @@ extern "C" { #include "BLI_math_inline.h" -#ifdef __BLI_MATH_INLINE_H__ +#if BLI_MATH_DO_INLINE #include "intern/math_vector_inline.c" #endif @@ -169,6 +169,7 @@ void interp_v4_v4v4v4v4(float p[4], const float v1[4], const float v2[4], const 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]); /********************************* Comparison ********************************/ diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h index 9cd801f819d..ec8e567c0ef 100644 --- a/source/blender/blenlib/BLI_threads.h +++ b/source/blender/blenlib/BLI_threads.h @@ -37,6 +37,10 @@ extern "C" { #include <pthread.h> +#ifdef __APPLE__ +#include <libkern/OSAtomic.h> +#endif + /* for tables, button in UI, etc */ #define BLENDER_MAX_THREADS 64 @@ -92,6 +96,19 @@ void BLI_mutex_lock(ThreadMutex *mutex); void BLI_mutex_unlock(ThreadMutex *mutex); void BLI_mutex_end(ThreadMutex *mutex); +/* Spin Lock */ + +#ifdef __APPLE__ +typedef OSSpinLock SpinLock; +#else +typedef pthread_spinlock_t SpinLock; +#endif + +void BLI_spin_init(SpinLock *spin); +void BLI_spin_lock(SpinLock *spin); +void BLI_spin_unlock(SpinLock *spin); +void BLI_spin_end(SpinLock *spin); + /* Read/Write Mutex Lock */ #define THREAD_LOCK_READ 1 diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index fb064b5403f..46bb7d51d13 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -263,6 +263,15 @@ #define IN_RANGE(a, b, c) ((b < c) ? ((b < a && a < c) ? 1 : 0) : ((c < a && a < b) ? 1 : 0)) #define IN_RANGE_INCL(a, b, c) ((b < c) ? ((b <= a && a <= c) ? 1 : 0) : ((c <= a && a <= b) ? 1 : 0)) +/* unpack vector for args */ +#define UNPACK2(a) ((a)[0]), ((a)[1]) +#define UNPACK3(a) ((a)[0]), ((a)[1]), ((a)[2]) +#define UNPACK4(a) ((a)[0]), ((a)[1]), ((a)[2]), ((a)[3]) +/* op may be '&' or '*' */ +#define UNPACK2OP(a, op) op((a)[0]), op((a)[1]) +#define UNPACK3OP(a, op) op((a)[0]), op((a)[1]), op((a)[2]) +#define UNPACK4OP(a, op) op((a)[0]), op((a)[1]), op((a)[2]), op((a)[3]) + /* array helpers */ #define ARRAY_LAST_ITEM(arr_start, arr_dtype, elem_size, tot) \ (arr_dtype *)((char *)arr_start + (elem_size * (tot - 1))) diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index a6435bcbd50..10ae26d3757 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -174,3 +174,9 @@ if(WIN32) endif() blender_add_lib(bf_blenlib "${SRC}" "${INC}" "${INC_SYS}") + +if(MSVC) + # Quiet warning about inline math library files that do not export symbols. + # (normally you'd exclude from project, but we still want to see the files in MSVC) + set_target_properties(bf_blenlib PROPERTIES STATIC_LIBRARY_FLAGS /ignore:4221) +endif() diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 0cae9bab531..c4094920c2a 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -178,7 +178,7 @@ void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp) return NULL; } -int BLI_ghash_haskey(GHash *gh, void *key) +int BLI_ghash_haskey(GHash *gh, const void *key) { unsigned int hash = gh->hashfp(key) % gh->nbuckets; Entry *e; diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 7968fcabda6..6cf167b8823 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -1410,7 +1410,7 @@ static float ray_nearest_hit(BVHRayCastData *data, const float bv[6]) * Based on Tactical Optimization of Ray/Box Intersection, by Graham Fyffe * [http://tog.acm.org/resources/RTNews/html/rtnv21n1.html#art9] * - * TODO this doens't has data->ray.radius in consideration */ + * TODO this doesn't take data->ray.radius into consideration */ static float fast_ray_nearest_hit(const BVHRayCastData *data, const BVHNode *node) { const float *bv = node->bv; diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c index f27da759482..b9866f9c6e6 100644 --- a/source/blender/blenlib/intern/math_base_inline.c +++ b/source/blender/blenlib/intern/math_base_inline.c @@ -27,6 +27,8 @@ * \ingroup bli */ +#ifndef __MATH_BASE_INLINE_C__ +#define __MATH_BASE_INLINE_C__ #include <float.h> #include <stdio.h> @@ -35,9 +37,6 @@ #include "BLI_math.h" -#ifndef __MATH_BASE_INLINE_C__ -#define __MATH_BASE_INLINE_C__ - /* A few small defines. Keep'em local! */ #define SMALL_NUMBER 1.e-8f @@ -139,6 +138,25 @@ MINLINE int power_of_2_min_i(int n) return n; } +MINLINE unsigned int highest_order_bit_i(unsigned int n) +{ + n |= (n >> 1); + n |= (n >> 2); + n |= (n >> 4); + n |= (n >> 8); + n |= (n >> 16); + return n - (n >> 1); +} + +MINLINE unsigned short highest_order_bit_s(unsigned short n) +{ + n |= (n >> 1); + n |= (n >> 2); + n |= (n >> 4); + n |= (n >> 8); + return n - (n >> 1); +} + MINLINE float min_ff(float a, float b) { return (a < b) ? a : b; diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index e10229f11da..cd726179f56 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -2399,6 +2399,33 @@ void resolve_quad_uv(float r_uv[2], const float st[2], const float st0[2], const #undef IS_ZERO +/* reverse of the functions above */ +void interp_bilinear_quad_v3(float data[4][3], float u, float v, float res[3]) +{ + float vec[3]; + + copy_v3_v3(res, data[0]); + mul_v3_fl(res, (1 - u) * (1 - v)); + copy_v3_v3(vec, data[1]); + mul_v3_fl(vec, u * (1 - v)); add_v3_v3(res, vec); + copy_v3_v3(vec, data[2]); + mul_v3_fl(vec, u * v); add_v3_v3(res, vec); + copy_v3_v3(vec, data[3]); + mul_v3_fl(vec, (1 - u) * v); add_v3_v3(res, vec); +} + +void interp_barycentric_tri_v3(float data[3][3], float u, float v, float res[3]) +{ + float vec[3]; + + copy_v3_v3(res, data[0]); + mul_v3_fl(res, u); + copy_v3_v3(vec, data[1]); + mul_v3_fl(vec, v); add_v3_v3(res, vec); + copy_v3_v3(vec, data[2]); + mul_v3_fl(vec, 1.0f - u - v); add_v3_v3(res, vec); +} + /***************************** View & Projection *****************************/ void orthographic_m4(float matrix[][4], const float left, const float right, const float bottom, const float top, diff --git a/source/blender/blenlib/intern/math_geom_inline.c b/source/blender/blenlib/intern/math_geom_inline.c index 01585c93bc8..ba9770e1bd1 100644 --- a/source/blender/blenlib/intern/math_geom_inline.c +++ b/source/blender/blenlib/intern/math_geom_inline.c @@ -27,11 +27,12 @@ * \ingroup bli */ +#ifndef __MATH_GEOM_INLINE_C__ +#define __MATH_GEOM_INLINE_C__ #include "BLI_math.h" -#ifndef __MATH_GEOM_INLINE_C__ -#define __MATH_GEOM_INLINE_C__ +#include <string.h> /****************************** Spherical Harmonics **************************/ diff --git a/source/blender/blenlib/intern/math_interp.c b/source/blender/blenlib/intern/math_interp.c index 742669354a9..5a9e8244a46 100644 --- a/source/blender/blenlib/intern/math_interp.c +++ b/source/blender/blenlib/intern/math_interp.c @@ -60,12 +60,44 @@ static float P(float k) } #endif +static void vector_from_float(const float *data, float vector[4], int components) +{ + if (components == 1) { + vector[0] = data[0]; + } + else if (components == 3) { + copy_v3_v3(vector, data); + } + else { + copy_v4_v4(vector, data); + } +} + +static void vector_from_byte(const unsigned char *data, float vector[4], int components) +{ + if (components == 1) { + vector[0] = data[0]; + } + else if (components == 3) { + vector[0] = data[0]; + vector[1] = data[1]; + vector[2] = data[2]; + } + else { + vector[0] = data[0]; + vector[1] = data[1]; + vector[2] = data[2]; + vector[3] = data[3]; + } +} + /* BICUBIC INTERPOLATION */ -void BLI_bicubic_interpolation(const float *buffer, float *output, int width, int height, int components, float u, float v) +BLI_INLINE void bicubic_interpolation(const unsigned char *byte_buffer, const float *float_buffer, + unsigned char *byte_output, float *float_output, int width, int height, + int components, float u, float v) { int i, j, n, m, x1, y1; float a, b, w, wx, wy[4], out[4]; - const float *data; /* sample area entirely outside image? */ if (ceil(u) < 0 || floor(u) > width - 1 || ceil(v) < 0 || floor(v) > height - 1) { @@ -92,6 +124,8 @@ void BLI_bicubic_interpolation(const float *buffer, float *output, int width, in CLAMP(x1, 0, width - 1); wx = P(n - a); for (m = -1; m <= 2; m++) { + float data[4]; + y1 = j + m; CLAMP(y1, 0, height - 1); /* normally we could do this */ @@ -99,14 +133,19 @@ void BLI_bicubic_interpolation(const float *buffer, float *output, int width, in /* except that would call P() 16 times per pixel therefor pow() 64 times, better precalc these */ w = wx * wy[m + 1]; - data = buffer + width * y1 * 4 + 4 * x1; + if (float_output) { + const float *float_data = float_buffer + width * y1 * components + components * x1; - if (components == 1) { - out[0] += data[0] * w; + vector_from_float(float_data, data, components); + } + else { + const unsigned char *byte_data = byte_buffer + width * y1 * components + components * x1; + + vector_from_byte(byte_data, data, components); } - else if (components == 2) { + + if (components == 1) { out[0] += data[0] * w; - out[1] += data[1] * w; } else if (components == 3) { out[0] += data[0] * w; @@ -131,14 +170,21 @@ void BLI_bicubic_interpolation(const float *buffer, float *output, int width, in x1 = i + n; y1 = j + m; if (x1 > 0 && x1 < width && y1 > 0 && y1 < height) { - data = in->rect_float + width * y1 * 4 + 4 * x1; + float data[4]; - if (components == 1) { - out[0] += data[0] * P(n - a) * P(b - m); + if (float_output) { + const float *float_data = float_buffer + width * y1 * components + components * x1; + + vector_from_float(float_data, data, components); } - else if (components == 2) { + else { + const unsigned char *byte_data = byte_buffer + width * y1 * components + components * x1; + + vector_from_byte(byte_data, data, components); + } + + if (components == 1) { out[0] += data[0] * P(n - a) * P(b - m); - out[1] += data[1] * P(n - a) * P(b - m); } else if (components == 3) { out[0] += data[0] * P(n - a) * P(b - m); @@ -156,33 +202,54 @@ void BLI_bicubic_interpolation(const float *buffer, float *output, int width, in } #endif - if (components == 1) { - output[0] = out[0]; - } - else if (components == 2) { - output[0] = out[0]; - output[1] = out[1]; - } - else if (components == 3) { - output[0] = out[0]; - output[1] = out[1]; - output[2] = out[2]; + if (float_output) { + if (components == 1) { + float_output[0] = out[0]; + } + else if (components == 3) { + copy_v3_v3(float_output, out); + } + else { + copy_v4_v4(float_output, out); + } } else { - output[0] = out[0]; - output[1] = out[1]; - output[2] = out[2]; - output[3] = out[3]; + if (components == 1) { + byte_output[0] = out[0]; + } + else if (components == 3) { + byte_output[0] = out[0]; + byte_output[1] = out[1]; + byte_output[2] = out[2]; + } + else { + byte_output[0] = out[0]; + byte_output[1] = out[1]; + byte_output[2] = out[2]; + byte_output[3] = out[3]; + } } } +void BLI_bicubic_interpolation_fl(const float *buffer, float *output, int width, int height, + int components, float u, float v) +{ + bicubic_interpolation(NULL, buffer, NULL, output, width, height, components, u, v); +} + +void BLI_bicubic_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height, + int components, float u, float v) +{ + bicubic_interpolation(buffer, NULL, output, NULL, width, height, components, u, v); +} + /* BILINEAR INTERPOLATION */ -void BLI_bilinear_interpolation(const float *buffer, float *output, int width, int height, int components, float u, float v) +BLI_INLINE void bilinear_interpolation(const unsigned char *byte_buffer, const float *float_buffer, + unsigned char *byte_output, float *float_output, int width, int height, + int components, float u, float v) { - const float *row1, *row2, *row3, *row4; float a, b; float a_b, ma_b, a_mb, ma_mb; - float empty[4] = {0.0f, 0.0f, 0.0f, 0.0f}; int y1, y2, x1, x2; /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ @@ -197,39 +264,88 @@ void BLI_bilinear_interpolation(const float *buffer, float *output, int width, i return; } - /* sample including outside of edges of image */ - if (x1 < 0 || y1 < 0) row1 = empty; - else row1 = buffer + width * y1 * 4 + 4 * x1; + if (float_output) { + const float *row1, *row2, *row3, *row4; + float empty[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - if (x1 < 0 || y2 > height - 1) row2 = empty; - else row2 = buffer + width * y2 * 4 + 4 * x1; + /* sample including outside of edges of image */ + if (x1 < 0 || y1 < 0) row1 = empty; + else row1 = float_buffer + width * y1 * components + components * x1; - if (x2 > width - 1 || y1 < 0) row3 = empty; - else row3 = buffer + width * y1 * 4 + 4 * x2; + if (x1 < 0 || y2 > height - 1) row2 = empty; + else row2 = float_buffer + width * y2 * components + components * x1; - if (x2 > width - 1 || y2 > height - 1) row4 = empty; - else row4 = buffer + width * y2 * 4 + 4 * x2; + if (x2 > width - 1 || y1 < 0) row3 = empty; + else row3 = float_buffer + width * y1 * components + components * x2; - a = u - floorf(u); - b = v - floorf(v); - a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b); + if (x2 > width - 1 || y2 > height - 1) row4 = empty; + else row4 = float_buffer + width * y2 * components + components * x2; - if (components == 1) { - output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; - } - else if (components == 2) { - output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; - output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; - } - else if (components == 3) { - output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; - output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; - output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; + a = u - floorf(u); + b = v - floorf(v); + a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b); + + if (components == 1) { + float_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + } + else if (components == 3) { + float_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + float_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; + float_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; + } + else { + float_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + float_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; + float_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; + float_output[3] = ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3]; + } } else { - output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; - output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; - output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; - output[3] = ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3]; + const unsigned char *row1, *row2, *row3, *row4; + unsigned char empty[4] = {0, 0, 0, 0}; + + /* sample including outside of edges of image */ + if (x1 < 0 || y1 < 0) row1 = empty; + else row1 = byte_buffer + width * y1 * components + components * x1; + + if (x1 < 0 || y2 > height - 1) row2 = empty; + else row2 = byte_buffer + width * y2 * components + components * x1; + + if (x2 > width - 1 || y1 < 0) row3 = empty; + else row3 = byte_buffer + width * y1 * components + components * x2; + + if (x2 > width - 1 || y2 > height - 1) row4 = empty; + else row4 = byte_buffer + width * y2 * components + components * x2; + + a = u - floorf(u); + b = v - floorf(v); + a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b); + + if (components == 1) { + byte_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + } + else if (components == 3) { + byte_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + byte_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; + byte_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; + } + else { + byte_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + byte_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; + byte_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; + byte_output[3] = ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3]; + } } } + +void BLI_bilinear_interpolation_fl(const float *buffer, float *output, int width, int height, + int components, float u, float v) +{ + bilinear_interpolation(NULL, buffer, NULL, output, width, height, components, u, v); +} + +void BLI_bilinear_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height, + int components, float u, float v) +{ + bilinear_interpolation(buffer, NULL, output, NULL, width, height, components, u, v); +} diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index b0c4724e1ec..3069542107e 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -84,7 +84,7 @@ void mul_qt_qtqt(float q[4], const float q1[4], const float q2[4]) * \note: * Assumes a unit quaternion? * - * in fact not, but you may wan't to use a unit quat, read on... + * in fact not, but you may want to use a unit quat, read on... * * Shortcut for 'q v q*' when \a v is actually a quaternion. * This removes the need for converting a vector to a quaternion, diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c index 976895fe6fc..812e2b3e63d 100644 --- a/source/blender/blenlib/intern/math_vector.c +++ b/source/blender/blenlib/intern/math_vector.c @@ -115,6 +115,13 @@ void mid_v2_v2v2(float v[2], const float v1[2], const float v2[2]) v[1] = 0.5f * (v1[1] + v2[1]); } +void mid_v3_v3v3v3(float v[3], const float v1[3], const float v2[3], const float v3[3]) +{ + v[0] = (v1[0] + v2[0] + v3[0]) / 3.0f; + v[1] = (v1[1] + v2[1] + v3[1]) / 3.0f; + v[2] = (v1[2] + v2[2] + v3[2]) / 3.0f; +} + /********************************** Angles ***********************************/ /* Return the angle in radians between vecs 1-2 and 2-3 in radians @@ -201,6 +208,13 @@ float angle_signed_v2v2(const float v1[2], const float v2[2]) float angle_normalized_v3v3(const float v1[3], const float v2[3]) { + /* double check they are normalized */ +#ifdef DEBUG + float test; + BLI_assert(fabsf((test = len_squared_v3(v1)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f); + BLI_assert(fabsf((test = len_squared_v3(v2)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f); +#endif + /* this is the same as acos(dot_v3v3(v1, v2)), but more accurate */ if (dot_v3v3(v1, v2) < 0.0f) { float vec[3]; @@ -217,6 +231,13 @@ float angle_normalized_v3v3(const float v1[3], const float v2[3]) float angle_normalized_v2v2(const float v1[2], const float v2[2]) { + /* double check they are normalized */ +#ifdef DEBUG + float test; + BLI_assert(fabsf((test = len_squared_v2(v1)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f); + BLI_assert(fabsf((test = len_squared_v2(v2)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f); +#endif + /* this is the same as acos(dot_v3v3(v1, v2)), but more accurate */ if (dot_v2v2(v1, v2) < 0.0f) { float vec[2]; @@ -401,6 +422,12 @@ void rotate_normalized_v3_v3v3fl(float r[3], const float p[3], const float axis[ const float costheta = cos(angle); const float sintheta = sin(angle); + /* double check they are normalized */ +#ifdef DEBUG + float test; + BLI_assert(fabsf((test = len_squared_v3(axis)) - 1.0f) < 0.0001f || fabsf(test) < 0.0001f); +#endif + r[0] = ((costheta + (1 - costheta) * axis[0] * axis[0]) * p[0]) + (((1 - costheta) * axis[0] * axis[1] - axis[2] * sintheta) * p[1]) + (((1 - costheta) * axis[0] * axis[2] + axis[1] * sintheta) * p[2]); diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c index d96beadd63b..84e4c513e12 100644 --- a/source/blender/blenlib/intern/math_vector_inline.c +++ b/source/blender/blenlib/intern/math_vector_inline.c @@ -27,12 +27,11 @@ * \ingroup bli */ - -#include "BLI_math.h" - #ifndef __MATH_VECTOR_INLINE_C__ #define __MATH_VECTOR_INLINE_C__ +#include "BLI_math.h" + /********************************** Init *************************************/ MINLINE void zero_v2(float r[2]) diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c index fb33d7ce127..f37e1e03f39 100644 --- a/source/blender/blenlib/intern/noise.c +++ b/source/blender/blenlib/intern/noise.c @@ -398,7 +398,8 @@ static float orgBlenderNoise(float x, float y, float z) h = hashvectf + 3 * hash[b21 + b11]; n += i * (h[0] * jx + h[1] * jy + h[2] * jz); - if (n < 0.0f) n = 0.0f; else if (n > 1.0f) n = 1.0f; + if (n < 0.0f) n = 0.0f; + else if (n > 1.0f) n = 1.0f; return n; } @@ -456,16 +457,50 @@ float BLI_turbulence1(float noisesize, float x, float y, float z, int nr) /* ********************* FROM PERLIN HIMSELF: ******************** */ -static char p[512 + 2] = { - 0xA2, 0xA0, 0x19, 0x3B, 0xF8, 0xEB, 0xAA, 0xEE, 0xF3, 0x1C, 0x67, 0x28, 0x1D, 0xED, 0x0, 0xDE, 0x95, 0x2E, 0xDC, 0x3F, 0x3A, 0x82, 0x35, 0x4D, 0x6C, 0xBA, 0x36, 0xD0, 0xF6, 0xC, 0x79, 0x32, 0xD1, 0x59, 0xF4, 0x8, 0x8B, 0x63, 0x89, 0x2F, 0xB8, 0xB4, 0x97, 0x83, 0xF2, 0x8F, 0x18, 0xC7, 0x51, 0x14, 0x65, 0x87, 0x48, 0x20, 0x42, 0xA8, 0x80, 0xB5, 0x40, 0x13, 0xB2, 0x22, 0x7E, 0x57, - 0xBC, 0x7F, 0x6B, 0x9D, 0x86, 0x4C, 0xC8, 0xDB, 0x7C, 0xD5, 0x25, 0x4E, 0x5A, 0x55, 0x74, 0x50, 0xCD, 0xB3, 0x7A, 0xBB, 0xC3, 0xCB, 0xB6, 0xE2, 0xE4, 0xEC, 0xFD, 0x98, 0xB, 0x96, 0xD3, 0x9E, 0x5C, 0xA1, 0x64, 0xF1, 0x81, 0x61, 0xE1, 0xC4, 0x24, 0x72, 0x49, 0x8C, 0x90, 0x4B, 0x84, 0x34, 0x38, 0xAB, 0x78, 0xCA, 0x1F, 0x1, 0xD7, 0x93, 0x11, 0xC1, 0x58, 0xA9, 0x31, 0xF9, 0x44, 0x6D, - 0xBF, 0x33, 0x9C, 0x5F, 0x9, 0x94, 0xA3, 0x85, 0x6, 0xC6, 0x9A, 0x1E, 0x7B, 0x46, 0x15, 0x30, 0x27, 0x2B, 0x1B, 0x71, 0x3C, 0x5B, 0xD6, 0x6F, 0x62, 0xAC, 0x4F, 0xC2, 0xC0, 0xE, 0xB1, 0x23, 0xA7, 0xDF, 0x47, 0xB0, 0x77, 0x69, 0x5, 0xE9, 0xE6, 0xE7, 0x76, 0x73, 0xF, 0xFE, 0x6E, 0x9B, 0x56, 0xEF, 0x12, 0xA5, 0x37, 0xFC, 0xAE, 0xD9, 0x3, 0x8E, 0xDD, 0x10, 0xB9, 0xCE, 0xC9, 0x8D, - 0xDA, 0x2A, 0xBD, 0x68, 0x17, 0x9F, 0xBE, 0xD4, 0xA, 0xCC, 0xD2, 0xE8, 0x43, 0x3D, 0x70, 0xB7, 0x2, 0x7D, 0x99, 0xD8, 0xD, 0x60, 0x8A, 0x4, 0x2C, 0x3E, 0x92, 0xE5, 0xAF, 0x53, 0x7, 0xE0, 0x29, 0xA6, 0xC5, 0xE3, 0xF5, 0xF7, 0x4A, 0x41, 0x26, 0x6A, 0x16, 0x5E, 0x52, 0x2D, 0x21, 0xAD, 0xF0, 0x91, 0xFF, 0xEA, 0x54, 0xFA, 0x66, 0x1A, 0x45, 0x39, 0xCF, 0x75, 0xA4, 0x88, 0xFB, 0x5D, - 0xA2, 0xA0, 0x19, 0x3B, 0xF8, 0xEB, 0xAA, 0xEE, 0xF3, 0x1C, 0x67, 0x28, 0x1D, 0xED, 0x0, 0xDE, 0x95, 0x2E, 0xDC, 0x3F, 0x3A, 0x82, 0x35, 0x4D, 0x6C, 0xBA, 0x36, 0xD0, 0xF6, 0xC, 0x79, 0x32, 0xD1, 0x59, 0xF4, 0x8, 0x8B, 0x63, 0x89, 0x2F, 0xB8, 0xB4, 0x97, 0x83, 0xF2, 0x8F, 0x18, 0xC7, 0x51, 0x14, 0x65, 0x87, 0x48, 0x20, 0x42, 0xA8, 0x80, 0xB5, 0x40, 0x13, 0xB2, 0x22, 0x7E, 0x57, - 0xBC, 0x7F, 0x6B, 0x9D, 0x86, 0x4C, 0xC8, 0xDB, 0x7C, 0xD5, 0x25, 0x4E, 0x5A, 0x55, 0x74, 0x50, 0xCD, 0xB3, 0x7A, 0xBB, 0xC3, 0xCB, 0xB6, 0xE2, 0xE4, 0xEC, 0xFD, 0x98, 0xB, 0x96, 0xD3, 0x9E, 0x5C, 0xA1, 0x64, 0xF1, 0x81, 0x61, 0xE1, 0xC4, 0x24, 0x72, 0x49, 0x8C, 0x90, 0x4B, 0x84, 0x34, 0x38, 0xAB, 0x78, 0xCA, 0x1F, 0x1, 0xD7, 0x93, 0x11, 0xC1, 0x58, 0xA9, 0x31, 0xF9, 0x44, 0x6D, - 0xBF, 0x33, 0x9C, 0x5F, 0x9, 0x94, 0xA3, 0x85, 0x6, 0xC6, 0x9A, 0x1E, 0x7B, 0x46, 0x15, 0x30, 0x27, 0x2B, 0x1B, 0x71, 0x3C, 0x5B, 0xD6, 0x6F, 0x62, 0xAC, 0x4F, 0xC2, 0xC0, 0xE, 0xB1, 0x23, 0xA7, 0xDF, 0x47, 0xB0, 0x77, 0x69, 0x5, 0xE9, 0xE6, 0xE7, 0x76, 0x73, 0xF, 0xFE, 0x6E, 0x9B, 0x56, 0xEF, 0x12, 0xA5, 0x37, 0xFC, 0xAE, 0xD9, 0x3, 0x8E, 0xDD, 0x10, 0xB9, 0xCE, 0xC9, 0x8D, - 0xDA, 0x2A, 0xBD, 0x68, 0x17, 0x9F, 0xBE, 0xD4, 0xA, 0xCC, 0xD2, 0xE8, 0x43, 0x3D, 0x70, 0xB7, 0x2, 0x7D, 0x99, 0xD8, 0xD, 0x60, 0x8A, 0x4, 0x2C, 0x3E, 0x92, 0xE5, 0xAF, 0x53, 0x7, 0xE0, 0x29, 0xA6, 0xC5, 0xE3, 0xF5, 0xF7, 0x4A, 0x41, 0x26, 0x6A, 0x16, 0x5E, 0x52, 0x2D, 0x21, 0xAD, 0xF0, 0x91, 0xFF, 0xEA, 0x54, 0xFA, 0x66, 0x1A, 0x45, 0x39, 0xCF, 0x75, 0xA4, 0x88, 0xFB, 0x5D, - 0xA2, 0xA0 +static const char p[512 + 2] = { + 0xA2, 0xA0, 0x19, 0x3B, 0xF8, 0xEB, 0xAA, 0xEE, 0xF3, 0x1C, 0x67, 0x28, + 0x1D, 0xED, 0x0, 0xDE, 0x95, 0x2E, 0xDC, 0x3F, 0x3A, 0x82, 0x35, 0x4D, + 0x6C, 0xBA, 0x36, 0xD0, 0xF6, 0xC, 0x79, 0x32, 0xD1, 0x59, 0xF4, 0x8, + 0x8B, 0x63, 0x89, 0x2F, 0xB8, 0xB4, 0x97, 0x83, 0xF2, 0x8F, 0x18, 0xC7, + 0x51, 0x14, 0x65, 0x87, 0x48, 0x20, 0x42, 0xA8, 0x80, 0xB5, 0x40, 0x13, + 0xB2, 0x22, 0x7E, 0x57, 0xBC, 0x7F, 0x6B, 0x9D, 0x86, 0x4C, 0xC8, 0xDB, + 0x7C, 0xD5, 0x25, 0x4E, 0x5A, 0x55, 0x74, 0x50, 0xCD, 0xB3, 0x7A, 0xBB, + 0xC3, 0xCB, 0xB6, 0xE2, 0xE4, 0xEC, 0xFD, 0x98, 0xB, 0x96, 0xD3, 0x9E, + 0x5C, 0xA1, 0x64, 0xF1, 0x81, 0x61, 0xE1, 0xC4, 0x24, 0x72, 0x49, 0x8C, + 0x90, 0x4B, 0x84, 0x34, 0x38, 0xAB, 0x78, 0xCA, 0x1F, 0x1, 0xD7, 0x93, + 0x11, 0xC1, 0x58, 0xA9, 0x31, 0xF9, 0x44, 0x6D, 0xBF, 0x33, 0x9C, 0x5F, + 0x9, 0x94, 0xA3, 0x85, 0x6, 0xC6, 0x9A, 0x1E, 0x7B, 0x46, 0x15, 0x30, + 0x27, 0x2B, 0x1B, 0x71, 0x3C, 0x5B, 0xD6, 0x6F, 0x62, 0xAC, 0x4F, 0xC2, + 0xC0, 0xE, 0xB1, 0x23, 0xA7, 0xDF, 0x47, 0xB0, 0x77, 0x69, 0x5, 0xE9, + 0xE6, 0xE7, 0x76, 0x73, 0xF, 0xFE, 0x6E, 0x9B, 0x56, 0xEF, 0x12, 0xA5, + 0x37, 0xFC, 0xAE, 0xD9, 0x3, 0x8E, 0xDD, 0x10, 0xB9, 0xCE, 0xC9, 0x8D, + 0xDA, 0x2A, 0xBD, 0x68, 0x17, 0x9F, 0xBE, 0xD4, 0xA, 0xCC, 0xD2, 0xE8, + 0x43, 0x3D, 0x70, 0xB7, 0x2, 0x7D, 0x99, 0xD8, 0xD, 0x60, 0x8A, 0x4, + 0x2C, 0x3E, 0x92, 0xE5, 0xAF, 0x53, 0x7, 0xE0, 0x29, 0xA6, 0xC5, 0xE3, + 0xF5, 0xF7, 0x4A, 0x41, 0x26, 0x6A, 0x16, 0x5E, 0x52, 0x2D, 0x21, 0xAD, + 0xF0, 0x91, 0xFF, 0xEA, 0x54, 0xFA, 0x66, 0x1A, 0x45, 0x39, 0xCF, 0x75, + 0xA4, 0x88, 0xFB, 0x5D, 0xA2, 0xA0, 0x19, 0x3B, 0xF8, 0xEB, 0xAA, 0xEE, + 0xF3, 0x1C, 0x67, 0x28, 0x1D, 0xED, 0x0, 0xDE, 0x95, 0x2E, 0xDC, 0x3F, + 0x3A, 0x82, 0x35, 0x4D, 0x6C, 0xBA, 0x36, 0xD0, 0xF6, 0xC, 0x79, 0x32, + 0xD1, 0x59, 0xF4, 0x8, 0x8B, 0x63, 0x89, 0x2F, 0xB8, 0xB4, 0x97, 0x83, + 0xF2, 0x8F, 0x18, 0xC7, 0x51, 0x14, 0x65, 0x87, 0x48, 0x20, 0x42, 0xA8, + 0x80, 0xB5, 0x40, 0x13, 0xB2, 0x22, 0x7E, 0x57, 0xBC, 0x7F, 0x6B, 0x9D, + 0x86, 0x4C, 0xC8, 0xDB, 0x7C, 0xD5, 0x25, 0x4E, 0x5A, 0x55, 0x74, 0x50, + 0xCD, 0xB3, 0x7A, 0xBB, 0xC3, 0xCB, 0xB6, 0xE2, 0xE4, 0xEC, 0xFD, 0x98, + 0xB, 0x96, 0xD3, 0x9E, 0x5C, 0xA1, 0x64, 0xF1, 0x81, 0x61, 0xE1, 0xC4, + 0x24, 0x72, 0x49, 0x8C, 0x90, 0x4B, 0x84, 0x34, 0x38, 0xAB, 0x78, 0xCA, + 0x1F, 0x1, 0xD7, 0x93, 0x11, 0xC1, 0x58, 0xA9, 0x31, 0xF9, 0x44, 0x6D, + 0xBF, 0x33, 0x9C, 0x5F, 0x9, 0x94, 0xA3, 0x85, 0x6, 0xC6, 0x9A, 0x1E, + 0x7B, 0x46, 0x15, 0x30, 0x27, 0x2B, 0x1B, 0x71, 0x3C, 0x5B, 0xD6, 0x6F, + 0x62, 0xAC, 0x4F, 0xC2, 0xC0, 0xE, 0xB1, 0x23, 0xA7, 0xDF, 0x47, 0xB0, + 0x77, 0x69, 0x5, 0xE9, 0xE6, 0xE7, 0x76, 0x73, 0xF, 0xFE, 0x6E, 0x9B, + 0x56, 0xEF, 0x12, 0xA5, 0x37, 0xFC, 0xAE, 0xD9, 0x3, 0x8E, 0xDD, 0x10, + 0xB9, 0xCE, 0xC9, 0x8D, 0xDA, 0x2A, 0xBD, 0x68, 0x17, 0x9F, 0xBE, 0xD4, + 0xA, 0xCC, 0xD2, 0xE8, 0x43, 0x3D, 0x70, 0xB7, 0x2, 0x7D, 0x99, 0xD8, + 0xD, 0x60, 0x8A, 0x4, 0x2C, 0x3E, 0x92, 0xE5, 0xAF, 0x53, 0x7, 0xE0, + 0x29, 0xA6, 0xC5, 0xE3, 0xF5, 0xF7, 0x4A, 0x41, 0x26, 0x6A, 0x16, 0x5E, + 0x52, 0x2D, 0x21, 0xAD, 0xF0, 0x91, 0xFF, 0xEA, 0x54, 0xFA, 0x66, 0x1A, + 0x45, 0x39, 0xCF, 0x75, 0xA4, 0x88, 0xFB, 0x5D, 0xA2, 0xA0 }; @@ -1856,7 +1891,8 @@ float mg_RidgedMultiFractal(float x, float y, float z, float H, float lacunarity y *= lacunarity; z *= lacunarity; weight = signal * gain; - if (weight > 1.0f) weight = 1.0f; else if (weight < 0.0f) weight = 0.0f; + if (weight > 1.0f) weight = 1.0f; + else if (weight < 0.0f) weight = 0.0f; signal = offset - fabsf(noisefunc(x, y, z)); signal *= signal; signal *= weight; diff --git a/source/blender/blenlib/intern/pbvh.c b/source/blender/blenlib/intern/pbvh.c index 9fd214c0f86..29982fb7744 100644 --- a/source/blender/blenlib/intern/pbvh.c +++ b/source/blender/blenlib/intern/pbvh.c @@ -1717,11 +1717,14 @@ void BLI_pbvh_grids_update(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj, bvh->grids = grids; bvh->gridadj = gridadj; bvh->gridfaces = gridfaces; - bvh->grid_flag_mats = flagmats; - bvh->grid_hidden = grid_hidden; - for (a = 0; a < bvh->totnode; ++a) - BLI_pbvh_node_mark_rebuild_draw(&bvh->nodes[a]); + if (flagmats != bvh->grid_flag_mats || bvh->grid_hidden != grid_hidden) { + bvh->grid_flag_mats = flagmats; + bvh->grid_hidden = grid_hidden; + + for (a = 0; a < bvh->totnode; ++a) + BLI_pbvh_node_mark_rebuild_draw(&bvh->nodes[a]); + } } float (*BLI_pbvh_get_vertCos(PBVH * pbvh))[3] diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c index 362a87782c6..1b7858f7f88 100644 --- a/source/blender/blenlib/intern/scanfill.c +++ b/source/blender/blenlib/intern/scanfill.c @@ -985,7 +985,7 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const short do_quad_tri_speedu /* CURRENT STATUS: - * - eve->f :1 = availalble in edges + * - eve->f :1 = available in edges * - eve->xs :polynumber * - eve->h :amount of edges connected to vertex * - eve->tmp.v :store! original vertex number diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index ff589764287..14e0dc2f049 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -56,7 +56,7 @@ char *BLI_strdup(const char *str) return BLI_strdupn(str, strlen(str)); } -char *BLI_strdupcat(const char *str1, const char *str2) +char *BLI_strdupcat(const char *__restrict str1, const char *__restrict str2) { size_t len; char *n; @@ -69,7 +69,7 @@ char *BLI_strdupcat(const char *str1, const char *str2) return n; } -char *BLI_strncpy(char *dst, const char *src, const size_t maxncpy) +char *BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) { size_t srclen = strlen(src); size_t cpylen = (srclen > (maxncpy - 1)) ? (maxncpy - 1) : srclen; @@ -81,7 +81,7 @@ char *BLI_strncpy(char *dst, const char *src, const size_t maxncpy) return dst; } -size_t BLI_vsnprintf(char *buffer, size_t count, const char *format, va_list arg) +size_t BLI_vsnprintf(char *__restrict buffer, size_t count, const char *__restrict format, va_list arg) { size_t n; @@ -97,7 +97,7 @@ size_t BLI_vsnprintf(char *buffer, size_t count, const char *format, va_list arg return n; } -size_t BLI_snprintf(char *buffer, size_t count, const char *format, ...) +size_t BLI_snprintf(char *__restrict buffer, size_t count, const char *__restrict format, ...) { size_t n; va_list arg; @@ -109,7 +109,7 @@ size_t BLI_snprintf(char *buffer, size_t count, const char *format, ...) return n; } -char *BLI_sprintfN(const char *format, ...) +char *BLI_sprintfN(const char *__restrict format, ...) { DynStr *ds; va_list arg; @@ -133,7 +133,7 @@ char *BLI_sprintfN(const char *format, ...) * TODO: support more fancy string escaping. current code is primitive * this basically is an ascii version of PyUnicode_EncodeUnicodeEscape() * which is a useful reference. */ -size_t BLI_strescape(char *dst, const char *src, const size_t maxncpy) +size_t BLI_strescape(char *__restrict dst, const char *__restrict src, const size_t maxncpy) { size_t len = 0; @@ -186,7 +186,7 @@ escape_finish: * * TODO, return the offset and a length so as to avoid doing an allocation. */ -char *BLI_str_quoted_substrN(const char *str, const char *prefix) +char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict prefix) { size_t prefixLen = strlen(prefix); char *startMatch, *endMatch; @@ -207,7 +207,7 @@ char *BLI_str_quoted_substrN(const char *str, const char *prefix) /* A rather wasteful string-replacement utility, though this shall do for now... * Feel free to replace this with an even safe + nicer alternative */ -char *BLI_replacestr(char *str, const char *oldText, const char *newText) +char *BLI_replacestr(char *__restrict str, const char *__restrict oldText, const char *__restrict newText) { DynStr *ds = NULL; size_t lenOld = strlen(oldText); diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c index e80f96ee0fe..16a5f03095d 100644 --- a/source/blender/blenlib/intern/string_utf8.c +++ b/source/blender/blenlib/intern/string_utf8.c @@ -184,7 +184,7 @@ static const size_t utf8_skip_data[256] = { *dst = '\0'; \ } (void)0 -char *BLI_strncpy_utf8(char *dst, const char *src, size_t maxncpy) +char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) { char *dst_r = dst; @@ -196,7 +196,7 @@ char *BLI_strncpy_utf8(char *dst, const char *src, size_t maxncpy) return dst_r; } -char *BLI_strncat_utf8(char *dst, const char *src, size_t maxncpy) +char *BLI_strncat_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) { while (*dst && maxncpy > 0) { dst++; @@ -213,7 +213,7 @@ char *BLI_strncat_utf8(char *dst, const char *src, size_t maxncpy) /* --------------------------------------------------------------------------*/ /* wchar_t / utf8 functions */ -size_t BLI_strncpy_wchar_as_utf8(char *dst, const wchar_t *src, const size_t maxncpy) +size_t BLI_strncpy_wchar_as_utf8(char *__restrict dst, const wchar_t *__restrict src, const size_t maxncpy) { size_t len = 0; @@ -289,7 +289,7 @@ size_t BLI_strnlen_utf8(const char *start, const size_t maxlen) return len; } -size_t BLI_strncpy_wchar_from_utf8(wchar_t *dst_w, const char *src_c, const size_t maxncpy) +size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst_w, const char *__restrict src_c, const size_t maxncpy) { int len = 0; @@ -419,7 +419,7 @@ unsigned int BLI_str_utf8_as_unicode(const char *p) } /* variant that increments the length */ -unsigned int BLI_str_utf8_as_unicode_and_size(const char *p, size_t *index) +unsigned int BLI_str_utf8_as_unicode_and_size(const char *__restrict p, size_t *__restrict index) { int i, mask = 0, len; unsigned int result; @@ -435,7 +435,7 @@ unsigned int BLI_str_utf8_as_unicode_and_size(const char *p, size_t *index) /* another variant that steps over the index, * note, currently this also falls back to latin1 for text drawing. */ -unsigned int BLI_str_utf8_as_unicode_step(const char *p, size_t *index) +unsigned int BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t *__restrict index) { int i, mask = 0, len; unsigned int result; diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index 66527b9b92a..146e1d531f1 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -400,6 +400,42 @@ void BLI_mutex_end(ThreadMutex *mutex) pthread_mutex_destroy(mutex); } +/* Spin Locks */ + +void BLI_spin_init(SpinLock *spin) +{ +#ifdef __APPLE__ + *spin = OS_SPINLOCK_INIT; +#else + pthread_spin_init(spin, 0); +#endif +} + +void BLI_spin_lock(SpinLock *spin) +{ +#ifdef __APPLE__ + OSSpinLockLock(spin); +#else + pthread_spin_lock(spin); +#endif +} + +void BLI_spin_unlock(SpinLock *spin) +{ +#ifdef __APPLE__ + OSSpinLockUnlock(spin); +#else + pthread_spin_unlock(spin); +#endif +} + +void BLI_spin_end(SpinLock *spin) +{ +#ifndef __APPLE__ + pthread_spin_destroy(spin); +#endif +} + /* Read/Write Mutex Lock */ void BLI_rw_mutex_init(ThreadRWMutex *mutex) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 30331713463..bcd67d8bd0b 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2983,7 +2983,6 @@ static void direct_link_text(FileData *fd, Text *text) #endif link_list(fd, &text->lines); - link_list(fd, &text->markers); text->curl = newdataadr(fd, text->curl); text->sell = newdataadr(fd, text->sell); @@ -3043,7 +3042,7 @@ static void direct_link_image(FileData *fd, Image *ima) link_ibuf_list(fd, &ima->ibufs); else ima->ibufs.first = ima->ibufs.last = NULL; - + /* if not restored, we keep the binded opengl index */ if (ima->ibufs.first == NULL) { ima->bindcode = 0; @@ -8313,11 +8312,17 @@ static void do_versions(FileData *fd, Library *lib, Main *main) for (scene = main->scene.first; scene; scene = scene->id.next) { if (scene->r.tilex == 0 || scene->r.tiley == 1) { - /* scene could be set for panoramic rendering, so clamp with the - * lowest possible tile size value - */ - scene->r.tilex = max_ii(scene->r.xsch * scene->r.size / scene->r.xparts / 100, 8); - scene->r.tiley = max_ii(scene->r.ysch * scene->r.size / scene->r.yparts / 100, 8); + if (scene->r.xparts && scene->r.yparts) { + /* scene could be set for panoramic rendering, so clamp with the + * lowest possible tile size value + */ + scene->r.tilex = max_ii(scene->r.xsch * scene->r.size / scene->r.xparts / 100, 8); + scene->r.tiley = max_ii(scene->r.ysch * scene->r.size / scene->r.yparts / 100, 8); + } + else { + /* happens when mixing using current trunk and previous release */ + scene->r.tilex = scene->r.tiley = 64; + } } } } @@ -8339,7 +8344,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) for (clip = main->movieclip.first; clip; clip = clip->id.next) { if (clip->tracking.settings.reconstruction_success_threshold == 0.0f) { - clip->tracking.settings.reconstruction_success_threshold = 1e-3; + clip->tracking.settings.reconstruction_success_threshold = 1e-3f; } } } @@ -8364,6 +8369,17 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } + { + Object *ob; + for (ob = main->object.first; ob; ob = ob->id.next) { + if (ob->step_height == 0.0f) { + ob->step_height = 0.15f; + ob->jump_speed = 10.0f; + ob->fall_speed = 55.0f; + } + } + } + /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */ diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index d75339252d9..1521739258e 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -901,7 +901,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main) ob->matbits = MEM_callocN(sizeof(char)*ob->totcol, "ob->matbits"); for (a = 0; a < ob->totcol; a++) - ob->matbits[a] = ob->colbits & (1<<a); + ob->matbits[a] = (ob->colbits & (1<<a)) != 0; } } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index ac5366c26a3..b010cae6893 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2607,7 +2607,6 @@ static void write_texts(WriteData *wd, ListBase *idbase) { Text *text; TextLine *tmp; - TextMarker *mrk; text= idbase->first; while (text) { @@ -2631,13 +2630,6 @@ static void write_texts(WriteData *wd, ListBase *idbase) writedata(wd, DATA, tmp->len+1, tmp->line); tmp= tmp->next; } - - /* write markers */ - mrk= text->markers.first; - while (mrk) { - writestruct(wd, DATA, "TextMarker", 1, mrk); - mrk= mrk->next; - } } diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt index d7858ebbc0d..2a23658f5d0 100644 --- a/source/blender/bmesh/CMakeLists.txt +++ b/source/blender/bmesh/CMakeLists.txt @@ -68,10 +68,6 @@ set(SRC intern/bmesh_construct.h intern/bmesh_core.c intern/bmesh_core.h - intern/bmesh_decimate_collapse.c - intern/bmesh_decimate_dissolve.c - intern/bmesh_decimate_unsubdivide.c - intern/bmesh_decimate.h intern/bmesh_inline.h intern/bmesh_interp.c intern/bmesh_interp.h @@ -109,6 +105,12 @@ set(SRC intern/bmesh_error.h tools/BME_bevel.c + tools/bmesh_bevel.c + tools/bmesh_bevel.h + tools/bmesh_decimate_collapse.c + tools/bmesh_decimate_dissolve.c + tools/bmesh_decimate_unsubdivide.c + tools/bmesh_decimate.h bmesh.h bmesh_class.h diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h index a672ec0b6a7..6257aa4bf3e 100644 --- a/source/blender/bmesh/bmesh.h +++ b/source/blender/bmesh/bmesh.h @@ -252,7 +252,6 @@ extern "C" { #include "intern/bmesh_construct.h" #include "intern/bmesh_core.h" -#include "intern/bmesh_decimate.h" #include "intern/bmesh_interp.h" #include "intern/bmesh_iterators.h" #include "intern/bmesh_marking.h" @@ -267,6 +266,9 @@ extern "C" { #include "intern/bmesh_inline.h" +#include "tools/bmesh_decimate.h" +#include "tools/bmesh_bevel.h" + #ifdef __cplusplus } #endif diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h index cff7da78ef2..f9dbf51a629 100644 --- a/source/blender/bmesh/bmesh_class.h +++ b/source/blender/bmesh/bmesh_class.h @@ -48,6 +48,8 @@ struct Object; * hrm. it doesn't but stull works ok, remove the comment above? - campbell. */ +// #pragma GCC diagnostic error "-Wpadded" + /** * BMHeader * @@ -69,10 +71,19 @@ typedef struct BMHeader { * this is abused by various tools which set it dirty. * - For loops this is used for sorting during tessellation. */ - char htype; /* element geometric type (verts/edges/loops/faces) */ - char hflag; /* this would be a CD layer, see below */ + char htype; /* element geometric type (verts/edges/loops/faces) */ + char hflag; /* this would be a CD layer, see below */ + + /* internal use only! + * note,.we are very picky about not bloating this struct + * but in this case its padded up to 16 bytes anyway, + * so adding a flag here gives no increase in size */ + char api_flag; +// char _pad; } BMHeader; +BLI_STATIC_ASSERT((sizeof(BMHeader) <= 16), "BMHeader size has grown!"); + /* note: need some way to specify custom locations for custom data layers. so we can * make them point directly into structs. and some way to make it only happen to the * active layer, and properly update when switching active layers.*/ @@ -122,7 +133,10 @@ typedef struct BMLoop { /* can cast BMFace/BMEdge/BMVert, but NOT BMLoop, since these don't have a flag layer */ typedef struct BMElemF { BMHeader head; - struct BMFlagLayer *oflags; /* keep after header, an array of flags, mostly used by the operator stack */ + + /* keep directly after header, + * optional array of flags, only used by the operator stack */ + struct BMFlagLayer *oflags; } BMElemF; /* can cast anything to this, including BMLoop */ @@ -142,21 +156,24 @@ typedef struct BMFace { BMHeader head; struct BMFlagLayer *oflags; /* an array of flags, mostly used by the operator stack */ - int len; /*includes all boundary loops*/ #ifdef USE_BMESH_HOLES int totbounds; /*total boundaries, is one plus the number of holes in the face*/ ListBase loops; #else BMLoop *l_first; #endif - float no[3]; /*yes, we do store this here*/ + int len; /* includes all boundary loops */ + float no[3]; /* yes, we do store this here */ short mat_nr; +// short _pad[3]; } BMFace; typedef struct BMFlagLayer { - short f, pflag; /* flags */ + short f; /* flags */ } BMFlagLayer; +// #pragma GCC diagnostic ignored "-Wpadded" + typedef struct BMesh { int totvert, totedge, totloop, totface; int totvertsel, totedgesel, totfacesel; @@ -166,7 +183,7 @@ typedef struct BMesh { * valid flags are - BM_VERT | BM_EDGE | BM_FACE. * BM_LOOP isn't handled so far. */ char elem_index_dirty; - + /*element pools*/ struct BLI_mempool *vpool, *epool, *lpool, *fpool; @@ -192,7 +209,7 @@ typedef struct BMesh { int walkers, totflags; ListBase selected, error_stack; - + BMFace *act_face; ListBase errorstack; @@ -243,10 +260,16 @@ enum { # define BM_FACE_FIRST_LOOP(p) ((p)->l_first) #endif -/* size to use for static arrays when dealing with NGons, +/** + * size to use for stack arrays when dealing with NGons, * alloc after this limit is reached. * this value is rather arbitrary */ -#define BM_NGON_STACK_SIZE 32 +#define BM_DEFAULT_NGON_STACK_SIZE 32 +/** + * size to use for stack arrays dealing with connected mesh data + * verts of faces, edges of vert - etc. + * often used with #BM_iter_as_arrayN() */ +#define BM_DEFAULT_ITER_STACK_SIZE 16 /* avoid inf loop, this value is arbitrary * but should not error on valid cases */ diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index eae78c6cc25..770196108f0 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -99,7 +99,7 @@ BMFace *BM_face_create_quad_tri_v(BMesh *bm, BMVert **verts, int len, const BMFa if (nodouble) { /* check if face exists or overlaps */ - is_overlap = BM_face_exists(bm, verts, len, &f); + is_overlap = BM_face_exists(verts, len, &f); } /* make new face */ @@ -174,9 +174,9 @@ void BM_face_copy_shared(BMesh *bm, BMFace *f) BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, int nodouble) { BMEdge **edges2 = NULL; - BLI_array_staticdeclare(edges2, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(edges2, BM_DEFAULT_NGON_STACK_SIZE); BMVert **verts = NULL; - BLI_array_staticdeclare(verts, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(verts, BM_DEFAULT_NGON_STACK_SIZE); BMFace *f = NULL; BMEdge *e; BMVert *v, *ev1, *ev2; @@ -187,8 +187,10 @@ BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, i * _and_ the old bmesh_mf functions, so its kindof smashed together * - joeedh */ - if (!len || !v1 || !v2 || !edges || !bm) + if (!len || !v1 || !v2 || !edges || !bm) { + BLI_assert(0); return NULL; + } /* put edges in correct order */ for (i = 0; i < len; i++) { diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 0910dd82701..03094873e25 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -76,7 +76,9 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example) } /* allocate flag */ - v->oflags = BLI_mempool_calloc(bm->toolflagpool); + if (bm->toolflagpool) { + v->oflags = BLI_mempool_calloc(bm->toolflagpool); + } CustomData_bmesh_set_default(&bm->vdata, &v->head.data); @@ -125,12 +127,14 @@ BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, e->head.htype = BM_EDGE; /* allocate flag */ - e->oflags = BLI_mempool_calloc(bm->toolflagpool); + if (bm->toolflagpool) { + e->oflags = BLI_mempool_calloc(bm->toolflagpool); + } e->v1 = v1; e->v2 = v2; - BM_elem_flag_enable(e, BM_ELEM_SMOOTH); + BM_elem_flag_enable(e, BM_ELEM_SMOOTH | BM_ELEM_DRAW); CustomData_bmesh_set_default(&bm->edata, &e->head.data); @@ -195,8 +199,8 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short co { BMVert **verts = NULL; BMEdge **edges = NULL; - BLI_array_fixedstack_declare(verts, BM_NGON_STACK_SIZE, f->len, __func__); - BLI_array_fixedstack_declare(edges, BM_NGON_STACK_SIZE, f->len, __func__); + BLI_array_fixedstack_declare(verts, BM_DEFAULT_NGON_STACK_SIZE, f->len, __func__); + BLI_array_fixedstack_declare(edges, BM_DEFAULT_NGON_STACK_SIZE, f->len, __func__); BMLoop *l_iter; BMLoop *l_first; BMLoop *l_copy; @@ -278,7 +282,9 @@ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm) f->head.htype = BM_FACE; /* allocate flag */ - f->oflags = BLI_mempool_calloc(bm->toolflagpool); + if (bm->toolflagpool) { + f->oflags = BLI_mempool_calloc(bm->toolflagpool); + } CustomData_bmesh_set_default(&bm->pdata, &f->head.data); @@ -305,7 +311,7 @@ BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, if (nodouble) { /* Check if face already exists */ - overlap = BM_face_exists(bm, verts, len, &f); + overlap = BM_face_exists(verts, len, &f); if (overlap) { return f; } @@ -495,7 +501,9 @@ static void bm_kill_only_vert(BMesh *bm, BMVert *v) if (v->head.data) CustomData_bmesh_free_block(&bm->vdata, &v->head.data); - BLI_mempool_free(bm->toolflagpool, v->oflags); + if (bm->toolflagpool) { + BLI_mempool_free(bm->toolflagpool, v->oflags); + } BLI_mempool_free(bm->vpool, v); } @@ -513,7 +521,9 @@ static void bm_kill_only_edge(BMesh *bm, BMEdge *e) if (e->head.data) CustomData_bmesh_free_block(&bm->edata, &e->head.data); - BLI_mempool_free(bm->toolflagpool, e->oflags); + if (bm->toolflagpool) { + BLI_mempool_free(bm->toolflagpool, e->oflags); + } BLI_mempool_free(bm->epool, e); } @@ -534,7 +544,9 @@ static void bm_kill_only_face(BMesh *bm, BMFace *f) if (f->head.data) CustomData_bmesh_free_block(&bm->pdata, &f->head.data); - BLI_mempool_free(bm->toolflagpool, f->oflags); + if (bm->toolflagpool) { + BLI_mempool_free(bm->toolflagpool, f->oflags); + } BLI_mempool_free(bm->fpool, f); } @@ -558,7 +570,7 @@ static void bm_kill_only_loop(BMesh *bm, BMLoop *l) void BM_face_edges_kill(BMesh *bm, BMFace *f) { BMEdge **edges = NULL; - BLI_array_staticdeclare(edges, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE); BMLoop *l_iter; BMLoop *l_first; int i; @@ -582,7 +594,7 @@ void BM_face_edges_kill(BMesh *bm, BMFace *f) void BM_face_verts_kill(BMesh *bm, BMFace *f) { BMVert **verts = NULL; - BLI_array_staticdeclare(verts, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(verts, BM_DEFAULT_NGON_STACK_SIZE); BMLoop *l_iter; BMLoop *l_first; int i; @@ -734,7 +746,7 @@ static int bm_loop_reverse_loop(BMesh *bm, BMFace *f const int do_disps = CustomData_has_layer(&bm->ldata, CD_MDISPS); BMLoop *l_iter, *oldprev, *oldnext; BMEdge **edar = NULL; - BLI_array_fixedstack_declare(edar, BM_NGON_STACK_SIZE, len, __func__); + BLI_array_fixedstack_declare(edar, BM_DEFAULT_NGON_STACK_SIZE, len, __func__); int i, j, edok; for (i = 0, l_iter = l_first; i < len; i++, l_iter = l_iter->next) { @@ -937,9 +949,9 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const short do_del BMEdge **edges = NULL; BMEdge **deledges = NULL; BMVert **delverts = NULL; - BLI_array_staticdeclare(edges, BM_NGON_STACK_SIZE); - BLI_array_staticdeclare(deledges, BM_NGON_STACK_SIZE); - BLI_array_staticdeclare(delverts, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE); + BLI_array_staticdeclare(deledges, BM_DEFAULT_NGON_STACK_SIZE); + BLI_array_staticdeclare(delverts, BM_DEFAULT_NGON_STACK_SIZE); BMVert *v1 = NULL, *v2 = NULL; const char *err = NULL; int i, tote = 0; @@ -1587,7 +1599,7 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const short check_edge_dou if (LIKELY(radlen)) { BMLoop **loops = NULL; - BLI_array_fixedstack_declare(loops, BM_NGON_STACK_SIZE, radlen, __func__); + BLI_array_fixedstack_declare(loops, BM_DEFAULT_NGON_STACK_SIZE, radlen, __func__); killoop = ke->l; @@ -1773,14 +1785,18 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) bmesh_disk_edge_remove(f1loop->e, f1loop->e->v2); /* deallocate edge and its two loops as well as f2 */ - BLI_mempool_free(bm->toolflagpool, f1loop->e->oflags); + if (bm->toolflagpool) { + BLI_mempool_free(bm->toolflagpool, f1loop->e->oflags); + } BLI_mempool_free(bm->epool, f1loop->e); bm->totedge--; BLI_mempool_free(bm->lpool, f1loop); bm->totloop--; BLI_mempool_free(bm->lpool, f2loop); bm->totloop--; - BLI_mempool_free(bm->toolflagpool, f2->oflags); + if (bm->toolflagpool) { + BLI_mempool_free(bm->toolflagpool, f2->oflags); + } BLI_mempool_free(bm->fpool, f2); bm->totface--; /* account for both above */ @@ -1808,23 +1824,28 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) */ int BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target) { - BMEdge *e; - + void *loops_stack[BM_DEFAULT_ITER_STACK_SIZE]; BMLoop **loops; int i, loops_tot; + BMEdge *e; + /* verts already spliced */ if (v == v_target) { return FALSE; } /* we can't modify the vert while iterating so first allocate an array of loops */ - loops = BM_iter_as_arrayN(bm, BM_LOOPS_OF_VERT, v, &loops_tot); - if (loops) { + loops = BM_iter_as_arrayN(bm, BM_LOOPS_OF_VERT, v, &loops_tot, + loops_stack, BM_DEFAULT_ITER_STACK_SIZE); + + if (LIKELY(loops != NULL)) { for (i = 0; i < loops_tot; i++) { loops[i]->v = v_target; } - MEM_freeN(loops); + if (loops != (BMLoop **)loops_stack) { + MEM_freeN(loops); + } } /* move all the edges from v's disk to vtarget's disk */ diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c index 508b3b8fcdf..caf9f3c70d5 100644 --- a/source/blender/bmesh/intern/bmesh_interp.c +++ b/source/blender/bmesh/intern/bmesh_interp.c @@ -174,9 +174,9 @@ void BM_face_interp_from_face(BMesh *bm, BMFace *target, BMFace *source) void **blocks = NULL; float (*cos)[3] = NULL, *w = NULL; - BLI_array_fixedstack_declare(cos, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(w, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(blocks, BM_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(cos, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(w, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(blocks, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); int i; BM_elem_attrs_copy(bm, bm, source, target); @@ -613,10 +613,10 @@ void BM_loop_interp_from_face(BMesh *bm, BMLoop *target, BMFace *source, void **vblocks = NULL; float (*cos)[3] = NULL, co[3], *w = NULL; float cent[3] = {0.0f, 0.0f, 0.0f}; - BLI_array_fixedstack_declare(cos, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(w, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(blocks, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(vblocks, BM_NGON_STACK_SIZE, do_vertex ? source->len : 0, __func__); + BLI_array_fixedstack_declare(cos, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(w, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(blocks, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(vblocks, BM_DEFAULT_NGON_STACK_SIZE, do_vertex ? source->len : 0, __func__); int i, ax, ay; BM_elem_attrs_copy(bm, bm, source, target->f); @@ -689,9 +689,9 @@ void BM_vert_interp_from_face(BMesh *bm, BMVert *v, BMFace *source) void **blocks = NULL; float (*cos)[3] = NULL, *w = NULL; float cent[3] = {0.0f, 0.0f, 0.0f}; - BLI_array_fixedstack_declare(cos, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(w, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(blocks, BM_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(cos, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(w, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); + BLI_array_fixedstack_declare(blocks, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); int i; i = 0; diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c index 1cb95d94e9b..c3f33eb95e1 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.c +++ b/source/blender/bmesh/intern/bmesh_iterators.c @@ -116,10 +116,14 @@ int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, cons * * Caller needs to free the array. */ -void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len) +void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len, + /* optional args to avoid an alloc (normally stack array) */ + void **stack_array, int stack_array_size) { BMIter iter; + BLI_assert(stack_array_size == 0 || (stack_array_size && stack_array)); + /* we can't rely on coun't being set */ switch (itype) { case BM_VERTS_OF_MESH: @@ -137,7 +141,9 @@ void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len) if (BM_iter_init(&iter, bm, itype, data) && iter.count > 0) { BMElem *ele; - BMElem **array = MEM_mallocN(sizeof(ele) * iter.count, __func__); + BMElem **array = iter.count > stack_array_size ? + MEM_mallocN(sizeof(ele) * iter.count, __func__) : + stack_array; int i = 0; *r_len = iter.count; /* set before iterating */ diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h index 3c42b3d610c..7291bca6356 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.h +++ b/source/blender/bmesh/intern/bmesh_iterators.h @@ -107,14 +107,14 @@ typedef struct BMIter { BMesh *bm; void (*begin)(struct BMIter *iter); void *(*step)(struct BMIter *iter); - /* +#if 0 union { void *p; int i; long l; float f; } filter; - */ +#endif int count; /* note, only some iterators set this, don't rely on it */ char itype; } BMIter; @@ -125,7 +125,8 @@ __attribute__((warn_unused_result)) #endif ; int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len); -void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len) +void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len, + void **stack_array, int stack_array_size) #ifdef __GNUC__ __attribute__((warn_unused_result)) #endif diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index d3e3bcd3556..ba5e7569c31 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -59,9 +59,45 @@ static void bm_mempool_init(BMesh *bm, const BMAllocTemplate *allocsize) #ifdef USE_BMESH_HOLES bm->looplistpool = BLI_mempool_create(sizeof(BMLoopList), 512, 512, 0); #endif +} - /* allocate one flag pool that we don't get rid of. */ - bm->toolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), 512, 512, 0); +void BM_mesh_elem_toolflags_ensure(BMesh *bm) +{ + if (bm->toolflagpool == NULL) { + const int totflagpool_size = max_ii(512, bm->totvert + bm->totedge + bm->totface); + BLI_mempool *toolflagpool; + + BMIter iter; + BMElemF *ele; + const char iter_types[3] = {BM_VERTS_OF_MESH, + BM_EDGES_OF_MESH, + BM_FACES_OF_MESH}; + + int i; + + BLI_assert(bm->totflags == 0); + + /* allocate one flag pool that we don't get rid of. */ + toolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), totflagpool_size, 512, 0); + + + for (i = 0; i < 3; i++) { + BM_ITER_MESH (ele, &iter, bm, iter_types[i]) { + ele->oflags = BLI_mempool_calloc(toolflagpool); + } + } + + bm->toolflagpool = toolflagpool; + bm->totflags = 1; + } +} + +void BM_mesh_elem_toolflags_clear(BMesh *bm) +{ + if (bm->toolflagpool) { + BLI_mempool_destroy(bm->toolflagpool); + bm->toolflagpool = NULL; + } } /** @@ -83,7 +119,7 @@ BMesh *BM_mesh_create(BMAllocTemplate *allocsize) /* allocate one flag pool that we don't get rid of. */ bm->stackdepth = 1; - bm->totflags = 1; + bm->totflags = 0; CustomData_reset(&bm->vdata); CustomData_reset(&bm->edata); @@ -143,7 +179,7 @@ void BM_mesh_data_free(BMesh *bm) BLI_mempool_destroy(bm->fpool); /* destroy flag pool */ - BLI_mempool_destroy(bm->toolflagpool); + BM_mesh_elem_toolflags_clear(bm); #ifdef USE_BMESH_HOLES BLI_mempool_destroy(bm->looplistpool); diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h index 8b6ef9aa3e0..b592f863cd1 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.h +++ b/source/blender/bmesh/intern/bmesh_mesh.h @@ -29,6 +29,8 @@ struct BMAllocTemplate; +void BM_mesh_elem_toolflags_ensure(BMesh *bm); +void BM_mesh_elem_toolflags_clear(BMesh *bm); BMesh *BM_mesh_create(struct BMAllocTemplate *allocsize); void BM_mesh_free(BMesh *bm); @@ -58,4 +60,8 @@ typedef struct BMAllocTemplate { extern BMAllocTemplate bm_mesh_allocsize_default; extern BMAllocTemplate bm_mesh_chunksize_default; +enum { + BM_MESH_CREATE_USE_TOOLFLAGS = (1 << 0) +}; + #endif /* __BMESH_MESH_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 398e6bbedcf..ec07eb5d9f7 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -47,9 +47,9 @@ * "in" (e.g. edgefacein). for three-type slots, use geom. * * for output slots, for single-type geometry slots, use the type name plus "out", - * (e.g. vertout), for double-type slots, use the two type names plus "out", - * (e.g. vertfaceout), for three-type slots, use geom. note that you can also - * use more esohteric names (e.g. skirtout) so long as the comment next to the + * (e.g. verts.out), for double-type slots, use the two type names plus "out", + * (e.g. vertfaces.out), for three-type slots, use geom. note that you can also + * use more esohteric names (e.g. geom_skirt.out) so long as the comment next to the * slot definition tells you what types of elements are in it. * */ @@ -82,7 +82,7 @@ * would be extracted from comments * next to them, e.g. * - * {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, //output slot, boundary region + * {BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, //output slot, boundary region * * the doc generator would automatically detect the presence of "output slot" * and flag the slot as an output. the same happens for "input slot". also @@ -99,16 +99,18 @@ */ static BMOpDefine bmo_smooth_vert_def = { "smooth_vert", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_BOOL, "mirror_clip_x"}, /* set vertices close to the x axis before the operation to 0 */ - {BMO_OP_SLOT_BOOL, "mirror_clip_y"}, /* set vertices close to the y axis before the operation to 0 */ - {BMO_OP_SLOT_BOOL, "mirror_clip_z"}, /* set vertices close to the z axis before the operation to 0 */ - {BMO_OP_SLOT_FLT, "clipdist"}, /* clipping threshod for the above three slots */ - {BMO_OP_SLOT_BOOL, "use_axis_x"}, /* smooth vertices along X axis */ - {BMO_OP_SLOT_BOOL, "use_axis_y"}, /* smooth vertices along Y axis */ - {BMO_OP_SLOT_BOOL, "use_axis_z"}, /* smooth vertices along Z axis */ - {0} /* null-terminating sentinel */, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ + {BMO_OP_SLOT_BOOL, "mirror_clip_x"}, /* set vertices close to the x axis before the operation to 0 */ + {BMO_OP_SLOT_BOOL, "mirror_clip_y"}, /* set vertices close to the y axis before the operation to 0 */ + {BMO_OP_SLOT_BOOL, "mirror_clip_z"}, /* set vertices close to the z axis before the operation to 0 */ + {BMO_OP_SLOT_FLT, "clip_dist"}, /* clipping threshod for the above three slots */ + {BMO_OP_SLOT_BOOL, "use_axis_x"}, /* smooth vertices along X axis */ + {BMO_OP_SLOT_BOOL, "use_axis_y"}, /* smooth vertices along Y axis */ + {BMO_OP_SLOT_BOOL, "use_axis_z"}, /* smooth vertices along Z axis */ + {0}, }, + {{0}}, /* no output */ bmo_smooth_vert_exec, 0 }; @@ -117,18 +119,20 @@ static BMOpDefine bmo_smooth_vert_def = { * Vertext Smooth Laplacian * Smooths vertices by using Laplacian smoothing propose by. * Desbrun, et al. Implicit Fairing of Irregular Meshes using Diffusion and Curvature Flow -*/ + */ static BMOpDefine bmo_smooth_laplacian_vert_def = { "smooth_laplacian_vert", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, //input vertices - {BMO_OP_SLOT_FLT, "lambda"}, //lambda param - {BMO_OP_SLOT_FLT, "lambda_border"}, //lambda param in border - {BMO_OP_SLOT_BOOL, "use_x"}, //Smooth object along X axis - {BMO_OP_SLOT_BOOL, "use_y"}, //Smooth object along Y axis - {BMO_OP_SLOT_BOOL, "use_z"}, //Smooth object along Z axis - {BMO_OP_SLOT_BOOL, "volume_preservation"}, //Apply volume preservation after smooth - {0} /* null-terminating sentinel */, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ + {BMO_OP_SLOT_FLT, "lambda"}, /* lambda param */ + {BMO_OP_SLOT_FLT, "lambda_border"}, /* lambda param in border */ + {BMO_OP_SLOT_BOOL, "use_x"}, /* Smooth object along X axis */ + {BMO_OP_SLOT_BOOL, "use_y"}, /* Smooth object along Y axis */ + {BMO_OP_SLOT_BOOL, "use_z"}, /* Smooth object along Z axis */ + {BMO_OP_SLOT_BOOL, "preserve_volume"}, /* Apply volume preservation after smooth */ + {0}, }, + {{0}}, /* no output */ bmo_smooth_laplacian_vert_exec, 0 }; @@ -141,10 +145,12 @@ static BMOpDefine bmo_smooth_laplacian_vert_def = { static BMOpDefine bmo_recalc_face_normals_def = { "recalc_face_normals", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, - {BMO_OP_SLOT_BOOL, "do_flip"}, /* internal flag, used by bmesh_rationalize_normals */ - {0} /* null-terminating sentinel */, + {BMO_OP_SLOT_BOOL, "use_flip"}, /* internal flag, used by bmesh_rationalize_normals */ + {0}, }, + {{0}}, /* no output */ bmo_recalc_face_normals_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; @@ -154,18 +160,22 @@ static BMOpDefine bmo_recalc_face_normals_def = { * * used to implement the select more/less tools. * this puts some geometry surrounding regions of - * geometry in geom into geomout. + * geometry in geom into geom.out. * - * if usefaces is 0 then geomout spits out verts and edges, + * if usefaces is 0 then geom.out spits out verts and edges, * otherwise it spits out faces. */ static BMOpDefine bmo_region_extend_def = { "region_extend", - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry */ - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* output slot, computed boundary geometry. */ - {BMO_OP_SLOT_BOOL, "constrict"}, /* find boundary inside the regions, not outside. */ - {BMO_OP_SLOT_BOOL, "use_faces"}, /* extend from faces instead of edges */ - {0} /* null-terminating sentinel */, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry */ + {BMO_OP_SLOT_BOOL, "use_constrict"}, /* find boundary inside the regions, not outside. */ + {BMO_OP_SLOT_BOOL, "use_faces"}, /* extend from faces instead of edges */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* output slot, computed boundary geometry. */ + {0}, }, bmo_region_extend_exec, 0 @@ -179,10 +189,14 @@ static BMOpDefine bmo_region_extend_def = { */ static BMOpDefine bmo_rotate_edges_def = { "rotate_edges", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* newly spun edges */ - {BMO_OP_SLOT_BOOL, "ccw"}, /* rotate edge counter-clockwise if true, othewise clockwise */ - {0} /* null-terminating sentinel */, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ + {BMO_OP_SLOT_BOOL, "use_ccw"}, /* rotate edge counter-clockwise if true, othewise clockwise */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* newly spun edges */ + {0}, }, bmo_rotate_edges_exec, BMO_OP_FLAG_UNTAN_MULTIRES @@ -196,9 +210,11 @@ static BMOpDefine bmo_rotate_edges_def = { */ static BMOpDefine bmo_reverse_faces_def = { "reverse_faces", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {0} /* null-terminating sentinel */, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ + {0}, }, + {{0}}, /* no output */ bmo_reverse_faces_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; @@ -211,10 +227,14 @@ static BMOpDefine bmo_reverse_faces_def = { */ static BMOpDefine bmo_bisect_edges_def = { "bisect_edges", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_INT, "numcuts"}, /* number of cuts */ - {BMO_OP_SLOT_ELEMENT_BUF, "outsplit"}, /* newly created vertices and edges */ - {0} /* null-terminating sentinel */, + {BMO_OP_SLOT_INT, "cuts"}, /* number of cuts */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom_split.out"}, /* newly created vertices and edges */ + {0}, }, bmo_bisect_edges_exec, BMO_OP_FLAG_UNTAN_MULTIRES @@ -224,20 +244,25 @@ static BMOpDefine bmo_bisect_edges_def = { * Mirror * * Mirrors geometry along an axis. The resulting geometry is welded on using - * mergedist. Pairs of original/mirrored vertices are welded using the mergedist + * merge_dist. Pairs of original/mirrored vertices are welded using the merge_dist * parameter (which defines the minimum distance for welding to happen). */ static BMOpDefine bmo_mirror_def = { "mirror", - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix defining the mirror transformation */ - {BMO_OP_SLOT_FLT, "mergedist"}, /* maximum distance for merging. does no merging if 0. */ - {BMO_OP_SLOT_ELEMENT_BUF, "newout"}, /* output geometry, mirrored */ - {BMO_OP_SLOT_INT, "axis"}, /* the axis to use, 0, 1, or 2 for x, y, z */ + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry */ + {BMO_OP_SLOT_MAT, "mat"}, /* matrix defining the mirror transformation */ + {BMO_OP_SLOT_FLT, "merge_dist"}, /* maximum distance for merging. does no merging if 0. */ + {BMO_OP_SLOT_INT, "axis"}, /* the axis to use, 0, 1, or 2 for x, y, z */ {BMO_OP_SLOT_BOOL, "mirror_u"}, /* mirror UVs across the u axis */ {BMO_OP_SLOT_BOOL, "mirror_v"}, /* mirror UVs across the v axis */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* output geometry, mirrored */ + {0}, + }, bmo_mirror_exec, 0, }; @@ -253,11 +278,16 @@ static BMOpDefine bmo_mirror_def = { */ static BMOpDefine bmo_find_doubles_def = { "find_doubles", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ {BMO_OP_SLOT_ELEMENT_BUF, "keep_verts"}, /* list of verts to keep */ {BMO_OP_SLOT_FLT, "dist"}, /* minimum distance */ - {BMO_OP_SLOT_MAPPING, "targetmapout"}, - {0, /* null-terminating sentinel */}}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_MAPPING, "targetmap.out"}, + {0}, + }, bmo_find_doubles_exec, 0, }; @@ -270,9 +300,12 @@ static BMOpDefine bmo_find_doubles_def = { */ static BMOpDefine bmo_remove_doubles_def = { "remove_doubles", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input verts */ {BMO_OP_SLOT_FLT, "dist"}, /* minimum distance */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + {{0}}, /* no output */ bmo_remove_doubles_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; @@ -286,9 +319,12 @@ static BMOpDefine bmo_remove_doubles_def = { */ static BMOpDefine bmo_automerge_def = { "automerge", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input verts */ {BMO_OP_SLOT_FLT, "dist"}, /* minimum distance */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + {{0}}, /* no output */ bmo_automerge_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; @@ -300,8 +336,11 @@ static BMOpDefine bmo_automerge_def = { */ static BMOpDefine bmo_collapse_def = { "collapse", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + {{0}}, /* no output */ bmo_collapse_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; @@ -314,9 +353,12 @@ static BMOpDefine bmo_collapse_def = { */ static BMOpDefine bmo_pointmerge_facedata_def = { "pointmerge_facedata", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertice */ - {BMO_OP_SLOT_ELEMENT_BUF, "snapv"}, /* snap verte */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ + {BMO_OP_SLOT_ELEMENT_BUF, "snapv"}, /* snap vertex */ + {0}, + }, + {{0}}, /* no output */ bmo_pointmerge_facedata_exec, 0, }; @@ -330,8 +372,11 @@ static BMOpDefine bmo_pointmerge_facedata_def = { */ static BMOpDefine bmo_average_vert_facedata_def = { "average_vert_facedata", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertice */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + {{0}}, /* no output */ bmo_average_vert_facedata_exec, 0, }; @@ -343,9 +388,12 @@ static BMOpDefine bmo_average_vert_facedata_def = { */ static BMOpDefine bmo_pointmerge_def = { "pointmerge", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertice */ {BMO_OP_SLOT_VEC, "merge_co"}, - {0, /* null-terminating sentinel */}}, + {0}, + }, + {{0}}, /* no output */ bmo_pointmerge_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; @@ -357,8 +405,11 @@ static BMOpDefine bmo_pointmerge_def = { */ static BMOpDefine bmo_collapse_uvs_def = { "collapse_uvs", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + {{0}}, /* no output */ bmo_collapse_uvs_exec, 0, }; @@ -372,8 +423,11 @@ static BMOpDefine bmo_collapse_uvs_def = { */ static BMOpDefine bmo_weld_verts_def = { "weld_verts", + /* slots_in */ {{BMO_OP_SLOT_MAPPING, "targetmap"}, /* maps welded vertices to verts they should weld to */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + {{0}}, /* no output */ bmo_weld_verts_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; @@ -386,9 +440,14 @@ static BMOpDefine bmo_weld_verts_def = { */ static BMOpDefine bmo_create_vert_def = { "create_vert", + /* slots_in */ {{BMO_OP_SLOT_VEC, "co"}, /* the coordinate of the new vert */ - {BMO_OP_SLOT_ELEMENT_BUF, "newvertout"}, /* the new vert */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "vert.out"}, /* the new vert */ + {0}, + }, bmo_create_vert_exec, 0, }; @@ -401,14 +460,19 @@ static BMOpDefine bmo_create_vert_def = { */ static BMOpDefine bmo_join_triangles_def = { "join_triangles", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input geometry. */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* joined faces */ {BMO_OP_SLOT_BOOL, "cmp_sharp"}, {BMO_OP_SLOT_BOOL, "cmp_uvs"}, {BMO_OP_SLOT_BOOL, "cmp_vcols"}, {BMO_OP_SLOT_BOOL, "cmp_materials"}, {BMO_OP_SLOT_FLT, "limit"}, - {0, /* null-terminating sentinel */}}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* joined faces */ + {0}, + }, bmo_join_triangles_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; @@ -426,13 +490,18 @@ static BMOpDefine bmo_join_triangles_def = { */ static BMOpDefine bmo_contextual_create_def = { "contextual_create", - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry. */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* newly-made face(s) */ + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry. */ + {BMO_OP_SLOT_INT, "mat_nr"}, /* material to use */ + {BMO_OP_SLOT_BOOL, "use_smooth"}, /* smooth to use */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* newly-made face(s) */ /* note, this is for stand-alone edges only, not edges which are apart of newly created faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* newly-made edge(s) */ - {BMO_OP_SLOT_INT, "mat_nr"}, /* material to use */ - {BMO_OP_SLOT_BOOL, "use_smooth"}, /* material to use */ - {0, /* null-terminating sentinel */}}, + {BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* newly-made edge(s) */ + {0}, + }, bmo_contextual_create_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; @@ -442,27 +511,37 @@ static BMOpDefine bmo_contextual_create_def = { */ static BMOpDefine bmo_bridge_loops_def = { "bridge_loops", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* new face */ {BMO_OP_SLOT_BOOL, "use_merge"}, {BMO_OP_SLOT_FLT, "merge_factor"}, - {0, /* null-terminating sentinel */}}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* new faces */ + {0}, + }, bmo_bridge_loops_exec, 0, }; static BMOpDefine bmo_edgenet_fill_def = { "edgenet_fill", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */ {BMO_OP_SLOT_MAPPING, "restrict"}, /* restricts edges to groups. maps edges to integer */ {BMO_OP_SLOT_BOOL, "use_restrict"}, {BMO_OP_SLOT_BOOL, "use_fill_check"}, - {BMO_OP_SLOT_ELEMENT_BUF, "excludefaces"}, /* list of faces to ignore for manifold check */ - {BMO_OP_SLOT_MAPPING, "faceout_groupmap"}, /* maps new faces to the group numbers they came fro */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* new face */ + {BMO_OP_SLOT_ELEMENT_BUF, "exclude_faces"}, /* list of faces to ignore for manifold check */ {BMO_OP_SLOT_INT, "mat_nr"}, /* material to use */ {BMO_OP_SLOT_BOOL, "use_smooth"}, /* material to use */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_MAPPING, "face_groupmap.out"}, /* maps new faces to the group numbers they came from */ + {BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* new face */ + {0}, + }, bmo_edgenet_fill_exec, 0, }; @@ -479,9 +558,14 @@ static BMOpDefine bmo_edgenet_fill_def = { */ static BMOpDefine bmo_edgenet_prepare_def = { "edgenet_prepare", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* new edges */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* new edges */ + {0}, + }, bmo_edgenet_prepare, 0, }; @@ -494,10 +578,13 @@ static BMOpDefine bmo_edgenet_prepare_def = { */ static BMOpDefine bmo_rotate_def = { "rotate", + /* slots_in */ {{BMO_OP_SLOT_VEC, "cent"}, /* center of rotation */ {BMO_OP_SLOT_MAT, "mat"}, /* matrix defining rotation */ {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + {{0}}, /* no output */ bmo_rotate_exec, 0, }; @@ -510,9 +597,12 @@ static BMOpDefine bmo_rotate_def = { */ static BMOpDefine bmo_translate_def = { "translate", + /* slots_in */ {{BMO_OP_SLOT_VEC, "vec"}, /* translation offset */ {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + {{0}}, /* no output */ bmo_translate_exec, 0, }; @@ -524,9 +614,12 @@ static BMOpDefine bmo_translate_def = { */ static BMOpDefine bmo_scale_def = { "scale", + /* slots_in */ {{BMO_OP_SLOT_VEC, "vec"}, /* scale factor */ {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + {{0}}, /* no output */ bmo_scale_exec, 0, }; @@ -540,9 +633,12 @@ static BMOpDefine bmo_scale_def = { */ static BMOpDefine bmo_transform_def = { "transform", + /* slots_in */ {{BMO_OP_SLOT_MAT, "mat"}, /* transform matrix */ {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + {{0}}, /* no output */ bmo_transform_exec, 0, }; @@ -555,9 +651,12 @@ static BMOpDefine bmo_transform_def = { */ static BMOpDefine bmo_object_load_bmesh_def = { "object_load_bmesh", + /* slots_in */ {{BMO_OP_SLOT_PTR, "scene"}, {BMO_OP_SLOT_PTR, "object"}, - {0, /* null-terminating sentinel */}}, + {0}, + }, + {{0}}, /* no output */ bmo_object_load_bmesh_exec, 0, }; @@ -570,10 +669,13 @@ static BMOpDefine bmo_object_load_bmesh_def = { */ static BMOpDefine bmo_bmesh_to_mesh_def = { "bmesh_to_mesh", + /* slots_in */ {{BMO_OP_SLOT_PTR, "mesh"}, /* pointer to a mesh structure to fill in */ {BMO_OP_SLOT_PTR, "object"}, /* pointer to an object structure */ - {BMO_OP_SLOT_BOOL, "notessellation"}, /* don't calculate mfaces */ - {0, /* null-terminating sentinel */}}, + {BMO_OP_SLOT_BOOL, "skip_tessface"}, /* don't calculate mfaces */ + {0}, + }, + {{0}}, /* no output */ bmo_bmesh_to_mesh_exec, 0, }; @@ -586,10 +688,13 @@ static BMOpDefine bmo_bmesh_to_mesh_def = { */ static BMOpDefine bmo_mesh_to_bmesh_def = { "mesh_to_bmesh", + /* slots_in */ {{BMO_OP_SLOT_PTR, "mesh"}, /* pointer to a Mesh structure */ {BMO_OP_SLOT_PTR, "object"}, /* pointer to an Object structure */ - {BMO_OP_SLOT_BOOL, "set_shapekey"}, /* load active shapekey coordinates into verts */ - {0, /* null-terminating sentinel */}}, + {BMO_OP_SLOT_BOOL, "use_shapekey"}, /* load active shapekey coordinates into verts */ + {0}, + }, + {{0}}, /* no output */ bmo_mesh_to_bmesh_exec, 0 }; @@ -601,10 +706,15 @@ static BMOpDefine bmo_mesh_to_bmesh_def = { */ static BMOpDefine bmo_extrude_discrete_faces_def = { "extrude_discrete_faces", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "skirtout"}, /* output skirt geometry, faces and edges */ - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* output faces */ + {BMO_OP_SLOT_ELEMENT_BUF, "geom_skirt.out"}, /* output skirt geometry, faces and edges */ + {0}, + }, bmo_extrude_discrete_faces_exec, 0 }; @@ -617,9 +727,14 @@ static BMOpDefine bmo_extrude_discrete_faces_def = { */ static BMOpDefine bmo_extrude_edge_only_def = { "extrude_edge_only", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input vertices */ - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* output geometry */ - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* output geometry */ + {0}, + }, bmo_extrude_edge_only_exec, 0 }; @@ -631,125 +746,171 @@ static BMOpDefine bmo_extrude_edge_only_def = { */ static BMOpDefine bmo_extrude_vert_indiv_def = { "extrude_vert_indiv", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* output wire edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output vertices */ - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* output wire edges */ + {BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output vertices */ + {0}, + }, bmo_extrude_vert_indiv_exec, 0 }; static BMOpDefine bmo_connect_verts_def = { "connect_verts", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, + {0}, + }, bmo_connect_verts_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; static BMOpDefine bmo_extrude_face_region_def = { "extrude_face_region", - {{BMO_OP_SLOT_ELEMENT_BUF, "edgefacein"}, - {BMO_OP_SLOT_MAPPING, "exclude"}, - {BMO_OP_SLOT_BOOL, "alwayskeeporig"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* edges and faces */ + {BMO_OP_SLOT_MAPPING, "edges_exclude"}, + {BMO_OP_SLOT_BOOL, "use_keep_orig"}, /* keep original geometry */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, + {0}, + }, bmo_extrude_face_region_exec, 0 }; static BMOpDefine bmo_dissolve_verts_def = { "dissolve_verts", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, - {0} /* null-terminating sentinel */}, + {0}, + }, + {{0}}, /* no output */ bmo_dissolve_verts_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; static BMOpDefine bmo_dissolve_edges_def = { "dissolve_edges", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, - {BMO_OP_SLOT_ELEMENT_BUF, "regionout"}, {BMO_OP_SLOT_BOOL, "use_verts"}, /* dissolve verts left between only 2 edges. */ - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "region.out"}, + {0}, + }, bmo_dissolve_edges_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; static BMOpDefine bmo_dissolve_edge_loop_def = { "dissolve_edge_loop", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, - {BMO_OP_SLOT_ELEMENT_BUF, "regionout"}, - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "region.out"}, + {0}, + }, bmo_dissolve_edgeloop_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; static BMOpDefine bmo_dissolve_faces_def = { "dissolve_faces", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, - {BMO_OP_SLOT_ELEMENT_BUF, "regionout"}, {BMO_OP_SLOT_BOOL, "use_verts"}, /* dissolve verts left between only 2 edges. */ - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "region.out"}, + {0}, + }, bmo_dissolve_faces_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; static BMOpDefine bmo_dissolve_limit_def = { "dissolve_limit", + /* slots_in */ {{BMO_OP_SLOT_FLT, "angle_limit"}, /* total rotation angle (degrees) */ {BMO_OP_SLOT_BOOL, "use_dissolve_boundaries"}, {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, {BMO_OP_SLOT_ELEMENT_BUF, "edges"}, - {0} /* null-terminating sentinel */}, + {0}, + }, + {{0}}, /* no output */ bmo_dissolve_limit_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; static BMOpDefine bmo_triangulate_def = { "triangulate", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, - {BMO_OP_SLOT_MAPPING, "facemap"}, {BMO_OP_SLOT_BOOL, "use_beauty"}, - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, + {BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, + {BMO_OP_SLOT_MAPPING, "facemap.out"}, + {0}, + }, bmo_triangulate_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; static BMOpDefine bmo_unsubdivide_def = { "unsubdivide", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ {BMO_OP_SLOT_INT, "iterations"}, - {0} /* null-terminating sentinel */}, + {0}, + }, + {{0}}, /* no output */ bmo_unsubdivide_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; static BMOpDefine bmo_subdivide_edges_def = { "subdivide_edges", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, {BMO_OP_SLOT_FLT, "smooth"}, {BMO_OP_SLOT_FLT, "fractal"}, {BMO_OP_SLOT_FLT, "along_normal"}, - {BMO_OP_SLOT_INT, "numcuts"}, + {BMO_OP_SLOT_INT, "cuts"}, {BMO_OP_SLOT_INT, "seed"}, {BMO_OP_SLOT_MAPPING, "custompatterns"}, {BMO_OP_SLOT_MAPPING, "edgepercents"}, - /* these next three can have multiple types of elements in them */ - {BMO_OP_SLOT_ELEMENT_BUF, "outinner"}, - {BMO_OP_SLOT_ELEMENT_BUF, "outsplit"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* contains all output geometr */ - - {BMO_OP_SLOT_INT, "quadcornertype"}, /* quad corner type, see bmesh_operators.h */ + {BMO_OP_SLOT_INT, "quad_corner_type"}, /* quad corner type, see bmesh_operators.h */ {BMO_OP_SLOT_BOOL, "use_gridfill"}, /* fill in fully-selected faces with a grid */ {BMO_OP_SLOT_BOOL, "use_singleedge"}, /* tessellate the case of one edge selected in a quad or triangle */ {BMO_OP_SLOT_BOOL, "use_sphere"}, /* for making new primitives only */ - - {0} /* null-terminating sentinel */, + {0}, + }, + /* slots_out */ + {/* these next three can have multiple types of elements in them */ + {BMO_OP_SLOT_ELEMENT_BUF, "geom_inner.out"}, + {BMO_OP_SLOT_ELEMENT_BUF, "geom_split.out"}, + {BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* contains all output geometr */ + {0}, }, bmo_subdivide_edges_exec, BMO_OP_FLAG_UNTAN_MULTIRES @@ -757,38 +918,51 @@ static BMOpDefine bmo_subdivide_edges_def = { static BMOpDefine bmo_delete_def = { "delete", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, {BMO_OP_SLOT_INT, "context"}, - {0} /* null-terminating sentinel */}, + {0}, + }, + {{0}}, /* no output */ bmo_delete_exec, 0 }; static BMOpDefine bmo_duplicate_def = { "duplicate", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {BMO_OP_SLOT_ELEMENT_BUF, "origout"}, - {BMO_OP_SLOT_ELEMENT_BUF, "newout"}, + {BMO_OP_SLOT_PTR, "dest"}, /* destination bmesh, if NULL will use current on */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom_orig.out"}, + {BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* facemap maps from source faces to dupe * faces, and from dupe faces to source faces */ - {BMO_OP_SLOT_MAPPING, "facemap"}, - {BMO_OP_SLOT_MAPPING, "boundarymap"}, - {BMO_OP_SLOT_MAPPING, "isovertmap"}, - {BMO_OP_SLOT_PTR, "dest"}, /* destination bmesh, if NULL will use current on */ - {0} /* null-terminating sentinel */}, + {BMO_OP_SLOT_MAPPING, "facemap.out"}, + {BMO_OP_SLOT_MAPPING, "boundarymap.out"}, + {BMO_OP_SLOT_MAPPING, "isovertmap.out"}, + {0}, + }, bmo_duplicate_exec, 0 }; static BMOpDefine bmo_split_def = { "split", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, - {BMO_OP_SLOT_MAPPING, "boundarymap"}, - {BMO_OP_SLOT_MAPPING, "isovertmap"}, - {BMO_OP_SLOT_PTR, "dest"}, /* destination bmesh, if NULL will use current on */ - {BMO_OP_SLOT_BOOL, "use_only_faces"}, /* when enabled. don't duplicate loose verts/edges */ - {0} /* null-terminating sentinel */}, + {BMO_OP_SLOT_PTR, "dest"}, /* destination bmesh, if NULL will use current one */ + {BMO_OP_SLOT_BOOL, "use_only_faces"}, /* when enabled. don't duplicate loose verts/edges */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, + {BMO_OP_SLOT_MAPPING, "boundarymap.out"}, + {BMO_OP_SLOT_MAPPING, "isovertmap.out"}, + {0}, + }, bmo_split_exec, 0 }; @@ -801,15 +975,20 @@ static BMOpDefine bmo_split_def = { */ static BMOpDefine bmo_spin_def = { "spin", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {BMO_OP_SLOT_ELEMENT_BUF, "lastout"}, /* result of last step */ - {BMO_OP_SLOT_VEC, "cent"}, /* rotation center */ - {BMO_OP_SLOT_VEC, "axis"}, /* rotation axis */ - {BMO_OP_SLOT_VEC, "dvec"}, /* translation delta per step */ - {BMO_OP_SLOT_FLT, "ang"}, /* total rotation angle (degrees) */ - {BMO_OP_SLOT_INT, "steps"}, /* number of steps */ - {BMO_OP_SLOT_BOOL, "do_dupli"}, /* duplicate or extrude? */ - {0} /* null-terminating sentinel */}, + {BMO_OP_SLOT_VEC, "cent"}, /* rotation center */ + {BMO_OP_SLOT_VEC, "axis"}, /* rotation axis */ + {BMO_OP_SLOT_VEC, "dvec"}, /* translation delta per step */ + {BMO_OP_SLOT_FLT, "angle"}, /* total rotation angle (degrees) */ + {BMO_OP_SLOT_INT, "steps"}, /* number of steps */ + {BMO_OP_SLOT_BOOL, "use_duplicate"}, /* duplicate or extrude? */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom_last.out"}, /* result of last step */ + {0}, + }, bmo_spin_exec, 0 }; @@ -822,12 +1001,17 @@ static BMOpDefine bmo_spin_def = { */ static BMOpDefine bmo_similar_faces_def = { "similar_faces", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output faces */ {BMO_OP_SLOT_INT, "type"}, /* type of selection */ {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ {BMO_OP_SLOT_INT, "compare"}, /* comparison method */ - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* output faces */ + {0}, + }, bmo_similar_faces_exec, 0 }; @@ -839,12 +1023,17 @@ static BMOpDefine bmo_similar_faces_def = { */ static BMOpDefine bmo_similar_edges_def = { "similar_edges", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* output edges */ {BMO_OP_SLOT_INT, "type"}, /* type of selection */ {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ {BMO_OP_SLOT_INT, "compare"}, /* comparison method */ - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* output edges */ + {0}, + }, bmo_similar_edges_exec, 0 }; @@ -856,12 +1045,17 @@ static BMOpDefine bmo_similar_edges_def = { */ static BMOpDefine bmo_similar_verts_def = { "similar_verts", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output vertices */ {BMO_OP_SLOT_INT, "type"}, /* type of selection */ {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ {BMO_OP_SLOT_INT, "compare"}, /* comparison method */ - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output vertices */ + {0}, + }, bmo_similar_verts_exec, 0 }; @@ -872,9 +1066,13 @@ static BMOpDefine bmo_similar_verts_def = { */ static BMOpDefine bmo_rotate_uvs_def = { "rotate_uvs", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_INT, "dir"}, /* direction */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ + {BMO_OP_SLOT_BOOL, "use_ccw"}, /* rotate counter-clockwise if true, othewise clockwise */ + {0}, + }, + /* slots_out */ + {{0}}, /* no output */ bmo_rotate_uvs_exec, 0 }; @@ -885,8 +1083,11 @@ static BMOpDefine bmo_rotate_uvs_def = { */ static BMOpDefine bmo_reverse_uvs_def = { "reverse_uvs", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ + {0}, + }, + {{0}}, /* no output */ bmo_reverse_uvs_exec, 0 }; @@ -897,9 +1098,12 @@ static BMOpDefine bmo_reverse_uvs_def = { */ static BMOpDefine bmo_rotate_colors_def = { "rotate_colors", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_INT, "dir"}, /* direction */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ + {BMO_OP_SLOT_BOOL, "use_ccw"}, /* rotate counter-clockwise if true, othewise clockwise */ + {0}, + }, + {{0}}, /* no output */ bmo_rotate_colors_exec, 0 }; @@ -910,8 +1114,11 @@ static BMOpDefine bmo_rotate_colors_def = { */ static BMOpDefine bmo_reverse_colors_def = { "reverse_colors", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ + {0}, + }, + {{0}}, /* no output */ bmo_reverse_colors_exec, 0 }; @@ -923,11 +1130,16 @@ static BMOpDefine bmo_reverse_colors_def = { */ static BMOpDefine bmo_shortest_path_def = { "shortest_path", - {{BMO_OP_SLOT_ELEMENT_BUF, "startv"}, /* start vertex */ - {BMO_OP_SLOT_ELEMENT_BUF, "endv"}, /* end vertex */ - {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output vertices */ - {BMO_OP_SLOT_INT, "type"}, /* type of selection */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "startv"}, /* start vertex */ + {BMO_OP_SLOT_ELEMENT_BUF, "endv"}, /* end vertex */ + {BMO_OP_SLOT_INT, "type"}, /* type of selection */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output vertices */ + {0}, + }, bmo_shortest_path_exec, 0 }; @@ -939,12 +1151,17 @@ static BMOpDefine bmo_shortest_path_def = { */ static BMOpDefine bmo_split_edges_def = { "split_edges", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* old output disconnected edges */ + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ /* needed for vertex rip so we can rip only half an edge at a boundary wich would otherwise split off */ - {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* optional tag verts, use to have greater control of splits */ + {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* optional tag verts, use to have greater control of splits */ {BMO_OP_SLOT_BOOL, "use_verts"}, /* use 'verts' for splitting, else just find verts to split from edges */ - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* old output disconnected edges */ + {0}, + }, bmo_split_edges_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; @@ -956,12 +1173,17 @@ static BMOpDefine bmo_split_edges_def = { */ static BMOpDefine bmo_create_grid_def = { "create_grid", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_INT, "xsegments"}, /* number of x segments */ - {BMO_OP_SLOT_INT, "ysegments"}, /* number of y segments */ - {BMO_OP_SLOT_FLT, "size"}, /* size of the grid */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{BMO_OP_SLOT_INT, "x_segments"}, /* number of x segments */ + {BMO_OP_SLOT_INT, "y_segments"}, /* number of y segments */ + {BMO_OP_SLOT_FLT, "size"}, /* size of the grid */ + {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ + {0}, + }, bmo_create_grid_exec, 0, }; @@ -973,12 +1195,17 @@ static BMOpDefine bmo_create_grid_def = { */ static BMOpDefine bmo_create_uvsphere_def = { "create_uvsphere", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_INT, "segments"}, /* number of u segments */ - {BMO_OP_SLOT_INT, "revolutions"}, /* number of v segment */ + /* slots_in */ + {{BMO_OP_SLOT_INT, "u_segments"}, /* number of u segments */ + {BMO_OP_SLOT_INT, "v_segments"}, /* number of v segment */ {BMO_OP_SLOT_FLT, "diameter"}, /* diameter */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with-- */ - {0, /* null-terminating sentinel */}}, + {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ + {0}, + }, bmo_create_uvsphere_exec, 0, }; @@ -990,11 +1217,16 @@ static BMOpDefine bmo_create_uvsphere_def = { */ static BMOpDefine bmo_create_icosphere_def = { "create_icosphere", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_INT, "subdivisions"}, /* how many times to recursively subdivide the sphere */ + /* slots_in */ + {{BMO_OP_SLOT_INT, "subdivisions"}, /* how many times to recursively subdivide the sphere */ {BMO_OP_SLOT_FLT, "diameter"}, /* diameter */ {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ + {0}, + }, bmo_create_icosphere_exec, 0, }; @@ -1006,9 +1238,14 @@ static BMOpDefine bmo_create_icosphere_def = { */ static BMOpDefine bmo_create_monkey_def = { "create_monkey", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with-- */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ + {0}, + }, bmo_create_monkey_exec, 0, }; @@ -1020,15 +1257,20 @@ static BMOpDefine bmo_create_monkey_def = { */ static BMOpDefine bmo_create_cone_def = { "create_cone", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_BOOL, "cap_ends"}, /* wheter or not to fill in the ends with faces */ - {BMO_OP_SLOT_BOOL, "cap_tris"}, /* fill ends with triangles instead of ngons */ + /* slots_in */ + {{BMO_OP_SLOT_BOOL, "cap_ends"}, /* wheter or not to fill in the ends with faces */ + {BMO_OP_SLOT_BOOL, "cap_tris"}, /* fill ends with triangles instead of ngons */ {BMO_OP_SLOT_INT, "segments"}, - {BMO_OP_SLOT_FLT, "diameter1"}, /* diameter of one end */ - {BMO_OP_SLOT_FLT, "diameter2"}, /* diameter of the opposite */ - {BMO_OP_SLOT_FLT, "depth"}, /* distance between ends */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with-- */ - {0, /* null-terminating sentinel */}}, + {BMO_OP_SLOT_FLT, "diameter1"}, /* diameter of one end */ + {BMO_OP_SLOT_FLT, "diameter2"}, /* diameter of the opposite */ + {BMO_OP_SLOT_FLT, "depth"}, /* distance between ends */ + {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ + {0}, + }, bmo_create_cone_exec, 0, }; @@ -1038,13 +1280,18 @@ static BMOpDefine bmo_create_cone_def = { */ static BMOpDefine bmo_create_circle_def = { "create_circle", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_BOOL, "cap_ends"}, /* wheter or not to fill in the ends with faces */ - {BMO_OP_SLOT_BOOL, "cap_tris"}, /* fill ends with triangles instead of ngons */ + /* slots_in */ + {{BMO_OP_SLOT_BOOL, "cap_ends"}, /* wheter or not to fill in the ends with faces */ + {BMO_OP_SLOT_BOOL, "cap_tris"}, /* fill ends with triangles instead of ngons */ {BMO_OP_SLOT_INT, "segments"}, - {BMO_OP_SLOT_FLT, "diameter"}, /* diameter of one end */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with-- */ - {0, /* null-terminating sentinel */}}, + {BMO_OP_SLOT_FLT, "diameter"}, /* diameter of one end */ + {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ + {0}, + }, bmo_create_circle_exec, 0, }; @@ -1056,15 +1303,19 @@ static BMOpDefine bmo_create_circle_def = { */ static BMOpDefine bmo_create_cube_def = { "create_cube", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_FLT, "size"}, /* size of the cube */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with-- */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{BMO_OP_SLOT_FLT, "size"}, /* size of the cube */ + {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ + {0}, + }, bmo_create_cube_exec, 0, }; -#define NEW_BEVEL 1 /* * Bevel * @@ -1072,12 +1323,17 @@ static BMOpDefine bmo_create_cube_def = { */ static BMOpDefine bmo_bevel_def = { "bevel", -#ifdef NEW_BEVEL - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input edges and vertices */ - {BMO_OP_SLOT_FLT, "offset"}, /* amount to offset beveled edge */ - {BMO_OP_SLOT_INT, "segments"}, /* number of segments in bevel */ - {0} /* null-terminating sentinel */}, -#else + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input edges and vertices */ + {BMO_OP_SLOT_FLT, "offset"}, /* amount to offset beveled edge */ + {BMO_OP_SLOT_INT, "segments"}, /* number of segments in bevel */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* output faces */ + {0}, + }, +#if 0 /* old bevel*/ {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input edges and vertices */ {BMO_OP_SLOT_ELEMENT_BUF, "face_spans"}, /* new geometry */ {BMO_OP_SLOT_ELEMENT_BUF, "face_holes"}, /* new geometry */ @@ -1087,7 +1343,8 @@ static BMOpDefine bmo_bevel_def = { * modifier uses this. We could do this as another float setting */ {BMO_OP_SLOT_INT, "lengthlayer"}, /* which PROP_FLT layer to us */ {BMO_OP_SLOT_FLT, "percent"}, /* percentage to expand beveled edge */ - {0} /* null-terminating sentinel */}, + {0}, + }, #endif bmo_bevel_exec, BMO_OP_FLAG_UNTAN_MULTIRES @@ -1100,10 +1357,15 @@ static BMOpDefine bmo_bevel_def = { */ static BMOpDefine bmo_beautify_fill_def = { "beautify_fill", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ {BMO_OP_SLOT_ELEMENT_BUF, "constrain_edges"}, /* edges that can't be flipped */ - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* new flipped faces and edges */ - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* new flipped faces and edges */ + {0}, + }, bmo_beautify_fill_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; @@ -1115,9 +1377,14 @@ static BMOpDefine bmo_beautify_fill_def = { */ static BMOpDefine bmo_triangle_fill_def = { "triangle_fill", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* new faces and edges */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* new faces and edges */ + {0}, + }, bmo_triangle_fill_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; @@ -1129,10 +1396,15 @@ static BMOpDefine bmo_triangle_fill_def = { */ static BMOpDefine bmo_solidify_def = { "solidify", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, {BMO_OP_SLOT_FLT, "thickness"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, - {0}}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, + {0}, + }, bmo_solidify_face_region_exec, 0 }; @@ -1144,15 +1416,20 @@ static BMOpDefine bmo_solidify_def = { */ static BMOpDefine bmo_inset_def = { "inset", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output faces */ + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ {BMO_OP_SLOT_BOOL, "use_boundary"}, {BMO_OP_SLOT_BOOL, "use_even_offset"}, {BMO_OP_SLOT_BOOL, "use_relative_offset"}, {BMO_OP_SLOT_FLT, "thickness"}, {BMO_OP_SLOT_FLT, "depth"}, {BMO_OP_SLOT_BOOL, "use_outset"}, - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* output faces */ + {0}, + }, bmo_inset_exec, 0 }; @@ -1164,15 +1441,20 @@ static BMOpDefine bmo_inset_def = { */ static BMOpDefine bmo_wireframe_def = { "wireframe", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output faces */ {BMO_OP_SLOT_BOOL, "use_boundary"}, {BMO_OP_SLOT_BOOL, "use_even_offset"}, {BMO_OP_SLOT_BOOL, "use_crease"}, {BMO_OP_SLOT_FLT, "thickness"}, {BMO_OP_SLOT_BOOL, "use_relative_offset"}, {BMO_OP_SLOT_FLT, "depth"}, - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* output faces */ + {0}, + }, bmo_wireframe_exec, 0 }; @@ -1184,11 +1466,16 @@ static BMOpDefine bmo_wireframe_def = { */ static BMOpDefine bmo_slide_vert_def = { "slide_vert", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "vert"}, {BMO_OP_SLOT_ELEMENT_BUF, "edge"}, - {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, {BMO_OP_SLOT_FLT, "distance_t"}, - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, + {0}, + }, bmo_slide_vert_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; @@ -1202,7 +1489,7 @@ static BMOpDefine bmo_slide_vert_def = { * If 'use_existing_faces' is true, the hull will not output triangles * that are covered by a pre-existing face. * - * All hull vertices, faces, and edges are added to 'geomout'. Any + * All hull vertices, faces, and edges are added to 'geom.out'. Any * input elements that end up inside the hull (i.e. are not used by an * output face) are added to the 'interior_geom' slot. The * 'unused_geom' slot will contain all interior geometry that is @@ -1211,15 +1498,18 @@ static BMOpDefine bmo_slide_vert_def = { */ static BMOpDefine bmo_convex_hull_def = { "convex_hull", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "input"}, {BMO_OP_SLOT_BOOL, "use_existing_faces"}, - - /* Outputs */ - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, - {BMO_OP_SLOT_ELEMENT_BUF, "interior_geom"}, - {BMO_OP_SLOT_ELEMENT_BUF, "unused_geom"}, - {BMO_OP_SLOT_ELEMENT_BUF, "holes_geom"}, - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, + {BMO_OP_SLOT_ELEMENT_BUF, "geom_interior.out"}, + {BMO_OP_SLOT_ELEMENT_BUF, "geom_unused.out"}, + {BMO_OP_SLOT_ELEMENT_BUF, "geom_holes.out"}, + {0}, + }, bmo_convex_hull_exec, 0 }; @@ -1233,17 +1523,19 @@ static BMOpDefine bmo_convex_hull_def = { * the "direction" slot. The edges and faces that cross the plane of * symmetry are split as needed to enforce symmetry. * - * All new vertices, edges, and faces are added to the "geomout" slot. + * All new vertices, edges, and faces are added to the "geom.out" slot. */ static BMOpDefine bmo_symmetrize_def = { "symmetrize", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "input"}, {BMO_OP_SLOT_INT, "direction"}, - - /* Outputs */ - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, - - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, + {0}, + }, bmo_symmetrize_exec, 0 }; diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h index 671cfbbc55e..b87e023e63a 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.h +++ b/source/blender/bmesh/intern/bmesh_operator_api.h @@ -116,30 +116,45 @@ enum { * for when your defining an operator with BMOpDefine.*/ typedef struct BMOpSlot { + const char *slot_name; /* pointer to BMOpDefine.slot_args */ int slot_type; int len; - int flag; - int index; /* index within slot array */ +// int flag; /* UNUSED */ +// int index; /* index within slot array */ /* UNUSED */ union { int i; float f; void *p; float vec[3]; - void *buf; + void **buf; GHash *ghash; } data; } BMOpSlot; -#define BMO_OP_MAX_SLOTS 16 /* way more than probably needed */ +/* mainly for use outside bmesh internal code */ +#define BMO_SLOT_AS_BOOL(slot) ((slot)->data.i) +#define BMO_SLOT_AS_INT(slot) ((slot)->data.i) +#define BMO_SLOT_AS_FLOAT(slot) ((slot)->data.f) +#define BMO_SLOT_AS_VECTOR(slot) ((slot)->data.vec) +#define BMO_SLOT_AS_MATRIX(slot ) ((float (*)[4])((slot)->data.p)) +#define BMO_SLOT_AS_BUFFER(slot ) ((slot)->data.buf) +#define BMO_SLOT_AS_GHASH(slot ) ((slot)->data.ghash) + +#define BMO_ASSERT_SLOT_IN_OP(slot, op) \ + BLI_assert(((slot >= (op)->slots_in) && (slot < &(op)->slots_in[BMO_OP_MAX_SLOTS])) || \ + ((slot >= (op)->slots_out) && (slot < &(op)->slots_out[BMO_OP_MAX_SLOTS]))) + +/* way more than probably needed, compiler complains if limit hit */ +#define BMO_OP_MAX_SLOTS 16 typedef struct BMOperator { + struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS]; + struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS]; + void (*exec)(BMesh *bm, struct BMOperator *op); + struct MemArena *arena; int type; - int slot_type; int type_flag; int flag; /* runtime options */ - struct BMOpSlot slot_args[BMO_OP_MAX_SLOTS]; - void (*exec)(BMesh *bm, struct BMOperator *op); - struct MemArena *arena; } BMOperator; enum { @@ -156,8 +171,9 @@ typedef struct BMOSlotType { } BMOSlotType; typedef struct BMOpDefine { - const char *name; - BMOSlotType slot_types[BMO_OP_MAX_SLOTS]; + const char *opname; + BMOSlotType slot_types_in[BMO_OP_MAX_SLOTS]; + BMOSlotType slot_types_out[BMO_OP_MAX_SLOTS]; void (*exec)(BMesh *bm, BMOperator *op); int type_flag; } BMOpDefine; @@ -245,15 +261,22 @@ int BMO_op_initf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, ... int 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(BMOperator *op, const char *slot_name); +int 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(BMOperator *op, const char *slot_name); +BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier); /* copies the data of a slot from one operator to another. src and dst are the * source/destination slot codes, respectively. */ -void BMO_slot_copy(BMOperator *source_op, BMOperator *dest_op, - const char *src, const char *dst); +#define BMO_slot_copy(op_src, slots_src, slot_name_src, \ + op_dst, slots_dst, slot_name_dst) \ + _bmo_slot_copy((op_src)->slots_src, slot_name_src, \ + (op_dst)->slots_dst, slot_name_dst, \ + (op_dst)->arena) + +void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, + BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, + struct MemArena *arena_dst); /* del "context" slot values, used for operator too */ enum { @@ -279,13 +302,13 @@ typedef enum { void BMO_op_flag_enable(BMesh *bm, BMOperator *op, const int op_flag); void BMO_op_flag_disable(BMesh *bm, BMOperator *op, const int op_flag); -void BMO_slot_float_set(BMOperator *op, const char *slot_name, const float f); -float BMO_slot_float_get(BMOperator *op, const char *slot_name); -void BMO_slot_int_set(BMOperator *op, const char *slot_name, const int i); -int BMO_slot_int_get(BMOperator *op, const char *slot_name); -void BMO_slot_bool_set(BMOperator *op, const char *slot_name, const int i); -int BMO_slot_bool_get(BMOperator *op, const char *slot_name); -void *BMO_slot_as_arrayN(BMOperator *op, const char *slot_name, int *len); +void BMO_slot_float_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float f); +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_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int *len); /* don't pass in arrays that are supposed to map to elements this way. @@ -293,69 +316,81 @@ void *BMO_slot_as_arrayN(BMOperator *op, const char *slot_name, int *len); * so, e.g. passing in list of floats per element in another slot is bad. * passing in, e.g. pointer to an editmesh for the conversion operator is fine * though. */ -void BMO_slot_ptr_set(BMOperator *op, const char *slot_name, void *p); -void *BMO_slot_ptr_get(BMOperator *op, const char *slot_name); -void BMO_slot_vec_set(BMOperator *op, const char *slot_name, const float vec[3]); -void BMO_slot_vec_get(BMOperator *op, const char *slot_name, float r_vec[3]); +void BMO_slot_ptr_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, void *p); +void *BMO_slot_ptr_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +void BMO_slot_vec_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float vec[3]); +void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_vec[3]); /* only supports square mats */ /* size must be 3 or 4; this api is meant only for transformation matrices. * note that internally the matrix is stored in 4x4 form, and it's safe to * call whichever BMO_Get_MatXXX function you want. */ -void BMO_slot_mat_set(BMOperator *op, const char *slot_name, const float *mat, int size); -void BMO_slot_mat4_get(BMOperator *op, const char *slot_name, float r_mat[4][4]); -void BMO_slot_mat3_set(BMOperator *op, const char *slot_name, float r_mat[3][3]); +void BMO_slot_mat_set(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float *mat, int size); +void BMO_slot_mat4_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[4][4]); +void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[3][3]); void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *op, const char htype, const short oflag); /* copies the values from another slot to the end of the output slot */ -void BMO_slot_buffer_append(BMOperator *output_op, const char *output_op_slot, - BMOperator *other_op, const char *other_op_slot); +#define BMO_slot_buffer_append(op_src, slots_src, slot_name_src, \ + op_dst, slots_dst, slot_name_dst) \ + _bmo_slot_buffer_append((op_src)->slots_src, slot_name_src, \ + (op_dst)->slots_dst, slot_name_dst, \ + (op_dst)->arena) +void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, + BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, + struct MemArena *arena_dst); /* puts every element of type 'type' (which is a bitmask) with tool * flag 'flag', into a slot. */ -void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, const char *slot_name, +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); /* puts every element of type 'type' (which is a bitmask) without tool * flag 'flag', into a slot. */ -void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, const char *slot_name, +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); /* tool-flags all elements inside an element slot array with flag flag. */ -void BMO_slot_buffer_flag_enable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_flag_enable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag); /* clears tool-flag flag from all elements inside a slot array. */ -void BMO_slot_buffer_flag_disable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_flag_disable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag); /* tool-flags all elements inside an element slot array with flag flag. */ -void BMO_slot_buffer_hflag_enable(BMesh *bm, BMOperator *op, const char *slot_name, +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); /* clears tool-flag flag from all elements inside a slot array. */ -void BMO_slot_buffer_hflag_disable(BMesh *bm, BMOperator *op, const char *slot_name, +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); /* puts every element of type 'type' (which is a bitmask) with header * flag 'flag', into a slot. note: ignores hidden elements * (e.g. elements with header flag BM_ELEM_HIDDEN set).*/ void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op, - const char *slot_name, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag); /* puts every element of type 'type' (which is a bitmask) without * header flag 'flag', into a slot. note: ignores hidden elements * (e.g. elements with header flag BM_ELEM_HIDDEN set).*/ void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op, - const char *slot_name, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag); /* counts number of elements inside a slot array. */ -int BMO_slot_buffer_count(BMesh *bm, BMOperator *op, const char *slot_name); -int BMO_slot_map_count(BMesh *bm, BMOperator *op, const char *slot_name); +int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); -void BMO_slot_map_insert(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name, - void *element, void *data, int len); +void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, + const void *element, void *data, int len); /* Counts the number of edges with tool flag toolflag around */ @@ -363,13 +398,14 @@ int BMO_vert_edge_flags_count(BMesh *bm, BMVert *v, const short oflag); /* flags all elements in a mapping. note that the mapping must only have * bmesh elements in it.*/ -void BMO_slot_map_to_flag(BMesh *bm, BMOperator *op, const char *slot_name, - const char hflag, const short oflag); +void BMO_slot_map_to_flag(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, const char hflag, const short oflag); -void *BMO_slot_buffer_alloc(BMOperator *op, const char *slot_name, const int len); +void *BMO_slot_buffer_alloc(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, const int len); -void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, const char *slot_name, - const char htype); +void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, const char htype); /* this part of the API is used to iterate over element buffer or * mapping slots. @@ -412,10 +448,11 @@ typedef struct BMOIter { char restrictmask; /* bitwise '&' with BMHeader.htype */ } BMOIter; -void *BMO_slot_buffer_elem_first(BMOperator *op, const char *slot_name); +void *BMO_slot_buffer_elem_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); -void *BMO_iter_new(BMOIter *iter, BMesh *bm, BMOperator *op, - const char *slot_name, const char restrictmask); +void *BMO_iter_new(BMOIter *iter, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char restrictmask); void *BMO_iter_step(BMOIter *iter); /* returns a pointer to the key value when iterating over mappings. @@ -428,8 +465,8 @@ void *BMO_iter_map_value_p(BMOIter *iter); /* use this for float mappings */ float BMO_iter_map_value_f(BMOIter *iter); -#define BMO_ITER(ele, iter, bm, op, slot_name, restrict) \ - for (ele = BMO_iter_new(iter, bm, op, slot_name, restrict); ele; ele = BMO_iter_step(iter)) +#define BMO_ITER(ele, iter, slot_args, slot_name, restrict_flag) \ + for (ele = BMO_iter_new(iter, slot_args, slot_name, restrict_flag); ele; ele = BMO_iter_step(iter)) /******************* Inlined Functions********************/ typedef void (*opexec)(BMesh *bm, BMOperator *op); diff --git a/source/blender/bmesh/intern/bmesh_operator_api_inline.h b/source/blender/bmesh/intern/bmesh_operator_api_inline.h index 16c2b8b0505..b405ecc1841 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api_inline.h +++ b/source/blender/bmesh/intern/bmesh_operator_api_inline.h @@ -69,16 +69,16 @@ BLI_INLINE void _bmo_elem_flag_toggle(BMesh *bm, BMFlagLayer *oflags, const shor oflags[bm->stackdepth - 1].f ^= oflag; } -BLI_INLINE void BMO_slot_map_int_insert(BMesh *bm, BMOperator *op, const char *slot_name, +BLI_INLINE void BMO_slot_map_int_insert(BMOperator *op, BMOpSlot *slot, void *element, int val) { - BMO_slot_map_insert(bm, op, slot_name, element, &val, sizeof(int)); + BMO_slot_map_insert(op, slot, element, &val, sizeof(int)); } -BLI_INLINE void BMO_slot_map_float_insert(BMesh *bm, BMOperator *op, const char *slot_name, +BLI_INLINE void BMO_slot_map_float_insert(BMOperator *op, BMOpSlot *slot, void *element, float val) { - BMO_slot_map_insert(bm, op, slot_name, element, &val, sizeof(float)); + BMO_slot_map_insert(op, slot, element, &val, sizeof(float)); } @@ -87,62 +87,62 @@ BLI_INLINE void BMO_slot_map_float_insert(BMesh *bm, BMOperator *op, const char * do NOT use these for non-operator-api-allocated memory! instead * use BMO_slot_map_data_get and BMO_slot_map_insert, which copies the data. */ -BLI_INLINE void BMO_slot_map_ptr_insert(BMesh *bm, BMOperator *op, const char *slot_name, - void *element, void *val) +BLI_INLINE void BMO_slot_map_ptr_insert(BMOperator *op, BMOpSlot *slot, + const void *element, void *val) { - BMO_slot_map_insert(bm, op, slot_name, element, &val, sizeof(void *)); + BMO_slot_map_insert(op, slot, element, &val, sizeof(void *)); } -BLI_INLINE int BMO_slot_map_contains(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name, void *element) +BLI_INLINE int BMO_slot_map_contains(BMOpSlot *slot, const void *element) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); /* sanity check */ - if (!slot->data.ghash) return 0; + if (UNLIKELY(slot->data.ghash == NULL)) { + return 0; + } return BLI_ghash_haskey(slot->data.ghash, element); } -BLI_INLINE void *BMO_slot_map_data_get(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name, - void *element) +BLI_INLINE void *BMO_slot_map_data_get(BMOpSlot *slot, const void *element) { BMOElemMapping *mapping; - BMOpSlot *slot = BMO_slot_get(op, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); /* sanity check */ - if (!slot->data.ghash) return NULL; + if (UNLIKELY(slot->data.ghash == NULL)) { + return NULL; + } mapping = (BMOElemMapping *)BLI_ghash_lookup(slot->data.ghash, element); - if (!mapping) return NULL; + if (!mapping) { + return NULL; + } return mapping + 1; } -BLI_INLINE float BMO_slot_map_float_get(BMesh *bm, BMOperator *op, const char *slot_name, - void *element) +BLI_INLINE float BMO_slot_map_float_get(BMOpSlot *slot, const void *element) { - float *val = (float *) BMO_slot_map_data_get(bm, op, slot_name, element); + float *val = (float *) BMO_slot_map_data_get(slot, element); if (val) return *val; return 0.0f; } -BLI_INLINE int BMO_slot_map_int_get(BMesh *bm, BMOperator *op, const char *slot_name, - void *element) +BLI_INLINE int BMO_slot_map_int_get(BMOpSlot *slot, const void *element) { - int *val = (int *) BMO_slot_map_data_get(bm, op, slot_name, element); + int *val = (int *) BMO_slot_map_data_get(slot, element); if (val) return *val; return 0; } -BLI_INLINE void *BMO_slot_map_ptr_get(BMesh *bm, BMOperator *op, const char *slot_name, - void *element) +BLI_INLINE void *BMO_slot_map_ptr_get(BMOpSlot *slot, const void *element) { - void **val = (void **) BMO_slot_map_data_get(bm, op, slot_name, element); + void **val = (void **) BMO_slot_map_data_get(slot, element); if (val) return *val; return NULL; diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index 9d1054dc042..157837a13c0 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -45,8 +45,8 @@ static void bmo_flag_layer_alloc(BMesh *bm); static void bmo_flag_layer_free(BMesh *bm); static void bmo_flag_layer_clear(BMesh *bm); -static int bmo_name_to_slotcode(BMOpDefine *def, const char *name); -static int bmo_name_to_slotcode_check(BMOpDefine *def, const char *name); +static int bmo_name_to_slotcode(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier); +static int bmo_name_to_slotcode_check(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier); static int bmo_opname_to_opcode(const char *opname); static const char *bmo_error_messages[] = { @@ -80,7 +80,7 @@ const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES] = { }; /* Dummy slot so there is something to return when slot name lookup fails */ -static BMOpSlot BMOpEmptySlot = {0}; +// static BMOpSlot BMOpEmptySlot = {0}; void BMO_op_flag_enable(BMesh *UNUSED(bm), BMOperator *op, const int op_flag) { @@ -101,6 +101,8 @@ void BMO_push(BMesh *bm, BMOperator *UNUSED(op)) { bm->stackdepth++; + BLI_assert(bm->totflags > 0); + /* add flag layer, if appropriate */ if (bm->stackdepth > 1) bmo_flag_layer_alloc(bm); @@ -123,6 +125,18 @@ void BMO_pop(BMesh *bm) bm->stackdepth--; } + +/* use for both slot_types_in and slot_types_out */ +static void bmo_op_slots_init(BMOSlotType *slot_types, BMOpSlot *slot_args) +{ + unsigned int i; + for (i = 0; slot_types[i].type; i++) { + slot_args[i].slot_name = slot_types[i].name; + slot_args[i].slot_type = slot_types[i].type; + // slot_args[i].index = i; // UNUSED + } +} + /** * \brief BMESH OPSTACK INIT OP * @@ -130,7 +144,7 @@ void BMO_pop(BMesh *bm) */ void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname) { - int i, opcode = bmo_opname_to_opcode(opname); + int opcode = bmo_opname_to_opcode(opname); #ifdef DEBUG BM_ELEM_INDEX_VALIDATE(bm, "pre bmo", opname); @@ -148,10 +162,8 @@ void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname) op->flag = flag; /* initialize the operator slot types */ - for (i = 0; opdefines[opcode]->slot_types[i].type; i++) { - op->slot_args[i].slot_type = opdefines[opcode]->slot_types[i].type; - op->slot_args[i].index = i; - } + bmo_op_slots_init(opdefines[opcode]->slot_types_in, op->slots_in); + bmo_op_slots_init(opdefines[opcode]->slot_types_out, op->slots_out); /* callback */ op->exec = opdefines[opcode]->exec; @@ -172,7 +184,9 @@ void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname) */ void BMO_op_exec(BMesh *bm, BMOperator *op) { - + /* allocate tool flags on demand */ + BM_mesh_elem_toolflags_ensure(bm); + BMO_push(bm, op); if (bm->stackdepth == 2) @@ -185,6 +199,20 @@ void BMO_op_exec(BMesh *bm, BMOperator *op) BMO_pop(bm); } +static void bmo_op_slots_free(BMOSlotType *slot_types, BMOpSlot *slot_args) +{ + BMOpSlot *slot; + unsigned int i; + for (i = 0; slot_types[i].type; i++) { + slot = &slot_args[i]; + if (slot->slot_type == BMO_OP_SLOT_MAPPING) { + if (slot->data.ghash) { + BLI_ghash_free(slot->data.ghash, NULL, NULL); + } + } + } +} + /** * \brief BMESH OPSTACK FINISH OP * @@ -192,21 +220,13 @@ void BMO_op_exec(BMesh *bm, BMOperator *op) */ void BMO_op_finish(BMesh *bm, BMOperator *op) { - BMOpSlot *slot; - int i; - - for (i = 0; opdefines[op->type]->slot_types[i].type; i++) { - slot = &op->slot_args[i]; - if (slot->slot_type == BMO_OP_SLOT_MAPPING) { - if (slot->data.ghash) - BLI_ghash_free(slot->data.ghash, NULL, NULL); - } - } + bmo_op_slots_free(opdefines[op->type]->slot_types_in, op->slots_in); + bmo_op_slots_free(opdefines[op->type]->slot_types_out, op->slots_out); BLI_memarena_free(op->arena); #ifdef DEBUG - BM_ELEM_INDEX_VALIDATE(bm, "post bmo", opdefines[op->type]->name); + BM_ELEM_INDEX_VALIDATE(bm, "post bmo", opdefines[op->type]->opname); #else (void)bm; #endif @@ -217,9 +237,9 @@ void BMO_op_finish(BMesh *bm, BMOperator *op) * * \return Success if the slot if found. */ -int BMO_slot_exists(BMOperator *op, const char *slot_name) +int BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier) { - int slot_code = bmo_name_to_slotcode(opdefines[op->type], slot_name); + int slot_code = bmo_name_to_slotcode(slot_args, identifier); return (slot_code >= 0); } @@ -228,73 +248,78 @@ int BMO_slot_exists(BMOperator *op, const char *slot_name) * * Returns a pointer to the slot of type 'slot_code' */ -BMOpSlot *BMO_slot_get(BMOperator *op, const char *slot_name) +BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier) { - int slot_code = bmo_name_to_slotcode_check(opdefines[op->type], slot_name); + int slot_code = bmo_name_to_slotcode_check(slot_args, identifier); - if (slot_code < 0) { - return &BMOpEmptySlot; + if (UNLIKELY(slot_code < 0)) { + //return &BMOpEmptySlot; + BLI_assert(0); + NULL; /* better crash */ } - return &(op->slot_args[slot_code]); + return &slot_args[slot_code]; } /** * \brief BMESH OPSTACK COPY SLOT * + * define used. * Copies data from one slot to another. */ -void BMO_slot_copy(BMOperator *source_op, BMOperator *dest_op, const char *src, const char *dst) +void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, + BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, + struct MemArena *arena_dst) { - BMOpSlot *source_slot = BMO_slot_get(source_op, src); - BMOpSlot *dest_slot = BMO_slot_get(dest_op, dst); + BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src); + BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst); - if (source_slot == dest_slot) + if (slot_src == slot_dst) return; - if (source_slot->slot_type != dest_slot->slot_type) { - /* possibly assert here? */ + BLI_assert(slot_src->slot_type == slot_dst->slot_type); + if (slot_src->slot_type != slot_dst->slot_type) { return; } - if (dest_slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF) { + if (slot_dst->slot_type == BMO_OP_SLOT_ELEMENT_BUF) { /* do buffer copy */ - dest_slot->data.buf = NULL; - dest_slot->len = source_slot->len; - if (dest_slot->len) { - const int slot_alloc_size = BMO_OPSLOT_TYPEINFO[dest_slot->slot_type] * dest_slot->len; - dest_slot->data.buf = BLI_memarena_alloc(dest_op->arena, slot_alloc_size); - memcpy(dest_slot->data.buf, source_slot->data.buf, slot_alloc_size); + slot_dst->data.buf = NULL; + slot_dst->len = slot_src->len; + if (slot_dst->len) { + const int slot_alloc_size = BMO_OPSLOT_TYPEINFO[slot_dst->slot_type] * slot_dst->len; + slot_dst->data.buf = BLI_memarena_alloc(arena_dst, slot_alloc_size); + memcpy(slot_dst->data.buf, slot_src->data.buf, slot_alloc_size); } } - else if (dest_slot->slot_type == BMO_OP_SLOT_MAPPING) { + else if (slot_dst->slot_type == BMO_OP_SLOT_MAPPING) { GHashIterator it; BMOElemMapping *srcmap, *dstmap; /* sanity check */ - if (!source_slot->data.ghash) { + if (!slot_src->data.ghash) { return; } - if (!dest_slot->data.ghash) { - dest_slot->data.ghash = BLI_ghash_ptr_new("bmesh operator 2"); + if (!slot_dst->data.ghash) { + slot_dst->data.ghash = BLI_ghash_ptr_new("bmesh operator 2"); } - BLI_ghashIterator_init(&it, source_slot->data.ghash); - for ( ; (srcmap = BLI_ghashIterator_getValue(&it)); - BLI_ghashIterator_step(&it)) + for (BLI_ghashIterator_init(&it, slot_src->data.ghash); + (srcmap = BLI_ghashIterator_getValue(&it)); + BLI_ghashIterator_step(&it)) { - dstmap = BLI_memarena_alloc(dest_op->arena, sizeof(*dstmap) + srcmap->len); + dstmap = BLI_memarena_alloc(arena_dst, sizeof(*dstmap) + srcmap->len); dstmap->element = srcmap->element; dstmap->len = srcmap->len; memcpy(dstmap + 1, srcmap + 1, srcmap->len); - BLI_ghash_insert(dest_slot->data.ghash, dstmap->element, dstmap); + BLI_ghash_insert(slot_dst->data.ghash, dstmap->element, dstmap); } } else { - dest_slot->data = source_slot->data; + slot_dst->data = slot_src->data; } } @@ -304,9 +329,9 @@ void BMO_slot_copy(BMOperator *source_op, BMOperator *dest_op, const char *src, * Sets the value of a slot depending on it's type */ -void BMO_slot_float_set(BMOperator *op, const char *slot_name, const float f) +void BMO_slot_float_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float f) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_FLT); if (!(slot->slot_type == BMO_OP_SLOT_FLT)) return; @@ -314,9 +339,9 @@ void BMO_slot_float_set(BMOperator *op, const char *slot_name, const float f) slot->data.f = f; } -void BMO_slot_int_set(BMOperator *op, const char *slot_name, const int i) +void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_INT); if (!(slot->slot_type == BMO_OP_SLOT_INT)) return; @@ -324,9 +349,9 @@ void BMO_slot_int_set(BMOperator *op, const char *slot_name, const int i) slot->data.i = i; } -void BMO_slot_bool_set(BMOperator *op, const char *slot_name, const int i) +void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_BOOL); if (!(slot->slot_type == BMO_OP_SLOT_BOOL)) return; @@ -335,9 +360,9 @@ void BMO_slot_bool_set(BMOperator *op, const char *slot_name, const int i) } /* only supports square mats */ -void BMO_slot_mat_set(BMOperator *op, const char *slot_name, const float *mat, int size) +void BMO_slot_mat_set(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float *mat, int size) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT); if (!(slot->slot_type == BMO_OP_SLOT_MAT)) return; @@ -358,39 +383,39 @@ void BMO_slot_mat_set(BMOperator *op, const char *slot_name, const float *mat, i } } -void BMO_slot_mat4_get(BMOperator *op, const char *slot_name, float r_mat[4][4]) +void BMO_slot_mat4_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[4][4]) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT); if (!(slot->slot_type == BMO_OP_SLOT_MAT)) return; if (slot->data.p) { - copy_m4_m4(r_mat, (float (*)[4])slot->data.p); + copy_m4_m4(r_mat, BMO_SLOT_AS_MATRIX(slot)); } else { unit_m4(r_mat); } } -void BMO_slot_mat3_set(BMOperator *op, const char *slot_name, float r_mat[3][3]) +void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[3][3]) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT); if (!(slot->slot_type == BMO_OP_SLOT_MAT)) return; if (slot->data.p) { - copy_m3_m4(r_mat, slot->data.p); + copy_m3_m4(r_mat, BMO_SLOT_AS_MATRIX(slot)); } else { unit_m3(r_mat); } } -void BMO_slot_ptr_set(BMOperator *op, const char *slot_name, void *p) +void BMO_slot_ptr_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, void *p) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_PTR); if (!(slot->slot_type == BMO_OP_SLOT_PTR)) return; @@ -398,9 +423,9 @@ void BMO_slot_ptr_set(BMOperator *op, const char *slot_name, void *p) slot->data.p = p; } -void BMO_slot_vec_set(BMOperator *op, const char *slot_name, const float vec[3]) +void BMO_slot_vec_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float vec[3]) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_VEC); if (!(slot->slot_type == BMO_OP_SLOT_VEC)) return; @@ -409,9 +434,9 @@ void BMO_slot_vec_set(BMOperator *op, const char *slot_name, const float vec[3]) } -float BMO_slot_float_get(BMOperator *op, const char *slot_name) +float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_FLT); if (!(slot->slot_type == BMO_OP_SLOT_FLT)) return 0.0f; @@ -419,9 +444,9 @@ float BMO_slot_float_get(BMOperator *op, const char *slot_name) return slot->data.f; } -int BMO_slot_int_get(BMOperator *op, const char *slot_name) +int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_INT); if (!(slot->slot_type == BMO_OP_SLOT_INT)) return 0; @@ -429,9 +454,9 @@ int BMO_slot_int_get(BMOperator *op, const char *slot_name) return slot->data.i; } -int BMO_slot_bool_get(BMOperator *op, const char *slot_name) +int BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_BOOL); if (!(slot->slot_type == BMO_OP_SLOT_BOOL)) return 0; @@ -440,23 +465,23 @@ int BMO_slot_bool_get(BMOperator *op, const char *slot_name) } /* if you want a copy of the elem buffer */ -void *BMO_slot_as_arrayN(BMOperator *op, const char *slot_name, int *len) +void *BMO_slot_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int *len) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); void *ret; /* could add support for mapping type */ BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); - ret = MEM_mallocN(sizeof(void *) * slot->len, __func__); - memcpy(ret, slot->data.buf, sizeof(void *) * slot->len); + ret = MEM_mallocN(sizeof(void **) * slot->len, __func__); + memcpy(ret, slot->data.buf, sizeof(void **) * slot->len); *len = slot->len; return ret; } -void *BMO_slot_ptr_get(BMOperator *op, const char *slot_name) +void *BMO_slot_ptr_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_PTR); if (!(slot->slot_type == BMO_OP_SLOT_PTR)) return NULL; @@ -464,9 +489,9 @@ void *BMO_slot_ptr_get(BMOperator *op, const char *slot_name) return slot->data.p; } -void BMO_slot_vec_get(BMOperator *op, const char *slot_name, float r_vec[3]) +void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_vec[3]) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_VEC); if (!(slot->slot_type == BMO_OP_SLOT_VEC)) return; @@ -542,9 +567,9 @@ void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char hty } } -int BMO_slot_buffer_count(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name) +int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); /* check if its actually a buffer */ @@ -554,9 +579,9 @@ int BMO_slot_buffer_count(BMesh *UNUSED(bm), BMOperator *op, const char *slot_na return slot->len; } -int BMO_slot_map_count(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name) +int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); /* check if its actually a buffer */ @@ -569,12 +594,12 @@ int BMO_slot_map_count(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name) /* inserts a key/value mapping into a mapping slot. note that it copies the * value, it doesn't store a reference to it. */ -void BMO_slot_map_insert(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name, - void *element, void *data, int len) +void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, + const void *element, void *data, int len) { BMOElemMapping *mapping; - BMOpSlot *slot = BMO_slot_get(op, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); + BMO_ASSERT_SLOT_IN_OP(slot, op); mapping = (BMOElemMapping *) BLI_memarena_alloc(op->arena, sizeof(*mapping) + len); @@ -586,7 +611,7 @@ void BMO_slot_map_insert(BMesh *UNUSED(bm), BMOperator *op, const char *slot_nam slot->data.ghash = BLI_ghash_ptr_new("bmesh slot map hash"); } - BLI_ghash_insert(slot->data.ghash, element, mapping); + BLI_ghash_insert(slot->data.ghash, (void *)element, mapping); } #if 0 @@ -632,11 +657,11 @@ void *bmo_slot_buffer_grow(BMesh *bm, BMOperator *op, int slot_code, int totadd) } #endif -void BMO_slot_map_to_flag(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_map_to_flag(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag) { GHashIterator it; - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BMElemF *ele_f; BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); @@ -652,18 +677,22 @@ void BMO_slot_map_to_flag(BMesh *bm, BMOperator *op, const char *slot_name, } } -void *BMO_slot_buffer_alloc(BMOperator *op, const char *slot_name, const int len) +void *BMO_slot_buffer_alloc(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int len) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); - BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); /* check if its actually a buffer */ if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) return NULL; slot->len = len; - if (len) + if (len) { slot->data.buf = BLI_memarena_alloc(op->arena, BMO_OPSLOT_TYPEINFO[slot->slot_type] * len); + } + else { + slot->data.buf = NULL; + } + return slot->data.buf; } @@ -672,9 +701,10 @@ void *BMO_slot_buffer_alloc(BMOperator *op, const char *slot_name, const int len * * Copies all elements of a certain type into an operator slot. */ -void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, const char *slot_name, const char htype) +void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, const char htype) { - BMOpSlot *output = BMO_slot_get(op, slot_name); + BMOpSlot *output = BMO_slot_get(slot_args, slot_name); int totelement = 0, i = 0; if (htype & BM_VERT) totelement += bm->totvert; @@ -685,27 +715,27 @@ void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, const char *slot_name, BMIter iter; BMHeader *ele; - BMO_slot_buffer_alloc(op, slot_name, totelement); + BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement); /* TODO - collapse these loops into one */ if (htype & BM_VERT) { BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { - ((BMHeader **)output->data.p)[i] = ele; + output->data.buf[i] = ele; i++; } } if (htype & BM_EDGE) { BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { - ((BMHeader **)output->data.p)[i] = ele; + output->data.buf[i] = ele; i++; } } if (htype & BM_FACE) { BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { - ((BMHeader **)output->data.p)[i] = ele; + output->data.buf[i] = ele; i++; } } @@ -718,11 +748,11 @@ void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, const char *slot_name, * Copies elements of a certain type, which have a certain header flag * enabled/disabled into a slot for an operator. */ -static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *slot_name, +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) { - BMOpSlot *output = BMO_slot_get(op, slot_name); + BMOpSlot *output = BMO_slot_get(slot_args, slot_name); int totelement = 0, i = 0; const int respecthide = (op->flag & BMO_FLAG_RESPECT_HIDE) != 0; @@ -737,7 +767,7 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *sl BMIter iter; BMElem *ele; - BMO_slot_buffer_alloc(op, slot_name, totelement); + BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement); /* TODO - collapse these loops into one */ @@ -746,7 +776,7 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *sl if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) && BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) { - ((BMElem **)output->data.p)[i] = ele; + output->data.buf[i] = ele; i++; } } @@ -757,7 +787,7 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *sl if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) && BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) { - ((BMElem **)output->data.p)[i] = ele; + output->data.buf[i] = ele; i++; } } @@ -768,7 +798,7 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *sl if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) && BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) { - ((BMElem **)output->data.p)[i] = ele; + output->data.buf[i] = ele; i++; } } @@ -779,46 +809,51 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *sl } } -void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op, const char *slot_name, +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_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, const char *slot_name, +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_name, htype, hflag, FALSE); + bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, FALSE); } /** * Copies the values from another slot to the end of the output slot. */ -void BMO_slot_buffer_append(BMOperator *output_op, const char *output_slot_name, - BMOperator *other_op, const char *other_slot_name) +void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, + BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, + struct MemArena *arena_dst) { - BMOpSlot *output_slot = BMO_slot_get(output_op, output_slot_name); - BMOpSlot *other_slot = BMO_slot_get(other_op, other_slot_name); + BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst); + BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src); - BLI_assert(output_slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF && - other_slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(slot_dst->slot_type == BMO_OP_SLOT_ELEMENT_BUF && + slot_src->slot_type == BMO_OP_SLOT_ELEMENT_BUF); - if (output_slot->len == 0) { + if (slot_dst->len == 0) { /* output slot is empty, copy rather than append */ - BMO_slot_copy(other_op, output_op, other_slot_name, output_slot_name); + _bmo_slot_copy(slot_args_src, slot_name_src, + slot_args_dst, slot_name_dst, + arena_dst); } - else if (other_slot->len != 0) { - int elem_size = BMO_OPSLOT_TYPEINFO[output_slot->slot_type]; - int alloc_size = elem_size * (output_slot->len + other_slot->len); + else if (slot_src->len != 0) { + int elem_size = BMO_OPSLOT_TYPEINFO[slot_dst->slot_type]; + int alloc_size = elem_size * (slot_dst->len + slot_src->len); /* allocate new buffer */ - void *buf = BLI_memarena_alloc(output_op->arena, alloc_size); + void *buf = BLI_memarena_alloc(arena_dst, alloc_size); /* copy slot data */ - memcpy(buf, output_slot->data.buf, elem_size * output_slot->len); - memcpy(((char *)buf) + elem_size * output_slot->len, other_slot->data.buf, elem_size * other_slot->len); + memcpy(buf, slot_dst->data.buf, elem_size * slot_dst->len); + memcpy(((char *)buf) + elem_size * slot_dst->len, slot_src->data.buf, elem_size * slot_src->len); - output_slot->data.buf = buf; - output_slot->len += other_slot->len; + slot_dst->data.buf = buf; + slot_dst->len += slot_src->len; } } @@ -828,13 +863,15 @@ void BMO_slot_buffer_append(BMOperator *output_op, const char *output_slot_name, * Copies elements of a certain type, which have a certain flag set * into an output slot for an operator. */ -static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, const char *slot_name, +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) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + 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)); if (test_for_enabled) @@ -849,9 +886,9 @@ static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, const char *slo BMHeader *ele; BMHeader **ele_array; - BMO_slot_buffer_alloc(op, slot_name, totelement); + BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement); - ele_array = (BMHeader **)slot->data.p; + ele_array = (BMHeader **)slot->data.buf; /* TODO - collapse these loops into one */ @@ -887,16 +924,18 @@ static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, const char *slo } } -void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, const char *slot_name, +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_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, const char *slot_name, +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_name, htype, oflag, FALSE); + bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, FALSE); } /** @@ -905,11 +944,12 @@ void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, const char *s * Header Flags elements in a slots buffer, automatically * using the selection API where appropriate. */ -void BMO_slot_buffer_hflag_enable(BMesh *bm, BMOperator *op, const char *slot_name, +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) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); - BMElem **data = slot->data.p; + 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)); @@ -938,11 +978,12 @@ void BMO_slot_buffer_hflag_enable(BMesh *bm, BMOperator *op, const char *slot_na * Removes flags from elements in a slots buffer, automatically * using the selection API where appropriate. */ -void BMO_slot_buffer_hflag_disable(BMesh *bm, BMOperator *op, const char *slot_name, +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) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); - BMElem **data = slot->data.p; + 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)); @@ -989,10 +1030,11 @@ int BMO_vert_edge_flags_count(BMesh *bm, BMVert *v, const short oflag) * * Flags elements in a slots buffer */ -void BMO_slot_buffer_flag_enable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_flag_enable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BMHeader **data = slot->data.p; int i; @@ -1011,11 +1053,12 @@ void BMO_slot_buffer_flag_enable(BMesh *bm, BMOperator *op, const char *slot_nam * * Removes flags from elements in a slots buffer */ -void BMO_slot_buffer_flag_disable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_flag_disable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); - BMHeader **data = slot->data.p; + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BMHeader **data = (BMHeader **)slot->data.buf; int i; BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); @@ -1056,7 +1099,9 @@ static void bmo_flag_layer_alloc(BMesh *bm) /* store memcpy size for reuse */ const size_t old_totflags_size = (bm->totflags * sizeof(BMFlagLayer)); - + + BLI_assert(oldpool != NULL); + bm->totflags++; /* allocate new flag poo */ @@ -1068,18 +1113,21 @@ static void bmo_flag_layer_alloc(BMesh *bm) ele->oflags = BLI_mempool_calloc(newpool); memcpy(ele->oflags, oldflags, old_totflags_size); BM_elem_index_set(ele, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); } BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) { oldflags = ele->oflags; ele->oflags = BLI_mempool_calloc(newpool); memcpy(ele->oflags, oldflags, old_totflags_size); BM_elem_index_set(ele, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); } BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) { oldflags = ele->oflags; ele->oflags = BLI_mempool_calloc(newpool); memcpy(ele->oflags, oldflags, old_totflags_size); BM_elem_index_set(ele, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); } bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE); @@ -1113,18 +1161,21 @@ static void bmo_flag_layer_free(BMesh *bm) ele->oflags = BLI_mempool_calloc(newpool); memcpy(ele->oflags, oldflags, new_totflags_size); BM_elem_index_set(ele, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); } BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) { oldflags = ele->oflags; ele->oflags = BLI_mempool_calloc(newpool); memcpy(ele->oflags, oldflags, new_totflags_size); BM_elem_index_set(ele, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); } BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) { oldflags = ele->oflags; ele->oflags = BLI_mempool_calloc(newpool); memcpy(ele->oflags, oldflags, new_totflags_size); BM_elem_index_set(ele, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); } bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE); @@ -1159,14 +1210,14 @@ static void bmo_flag_layer_clear(BMesh *bm) bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE); } -void *BMO_slot_buffer_elem_first(BMOperator *op, const char *slot_name) +void *BMO_slot_buffer_elem_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) return NULL; - return slot->data.buf ? *(void **)slot->data.buf : NULL; + return slot->data.buf ? *slot->data.buf : NULL; } /** @@ -1175,10 +1226,11 @@ void *BMO_slot_buffer_elem_first(BMOperator *op, const char *slot_name) * \param restrictmask restricts the iteration to certain element types * (e.g. combination of BM_VERT, BM_EDGE, BM_FACE), if iterating * over an element buffer (not a mapping). */ -void *BMO_iter_new(BMOIter *iter, BMesh *UNUSED(bm), BMOperator *op, - const char *slot_name, const char restrictmask) +void *BMO_iter_new(BMOIter *iter, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char restrictmask) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); memset(iter, 0, sizeof(BMOIter)); @@ -1207,13 +1259,13 @@ void *BMO_iter_step(BMOIter *iter) return NULL; } - h = ((void **)iter->slot->data.buf)[iter->cur++]; + h = iter->slot->data.buf[iter->cur++]; while (!(iter->restrictmask & h->htype)) { if (iter->cur >= iter->slot->len) { return NULL; } - h = ((void **)iter->slot->data.buf)[iter->cur++]; + h = iter->slot->data.buf[iter->cur++]; } return h; @@ -1312,24 +1364,26 @@ int BMO_error_pop(BMesh *bm, const char **msg, BMOperator **op) #define NEXT_CHAR(fmt) ((fmt)[0] != 0 ? (fmt)[1] : 0) -static int bmo_name_to_slotcode(BMOpDefine *def, const char *name) +static int bmo_name_to_slotcode(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier) { - int i; + int i = 0; - for (i = 0; def->slot_types[i].type; i++) { - if (!strncmp(name, def->slot_types[i].name, MAX_SLOTNAME)) { + while (slot_args->slot_name) { + if (strncmp(identifier, slot_args->slot_name, MAX_SLOTNAME) == 0) { return i; } + slot_args++; + i++; } return -1; } -static int bmo_name_to_slotcode_check(BMOpDefine *def, const char *name) +static int bmo_name_to_slotcode_check(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier) { - int i = bmo_name_to_slotcode(def, name); + int i = bmo_name_to_slotcode(slot_args, identifier); if (i < 0) { - fprintf(stderr, "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, name); + fprintf(stderr, "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, identifier); } return i; @@ -1340,12 +1394,12 @@ static int bmo_opname_to_opcode(const char *opname) int i; for (i = 0; i < bmesh_total_ops; i++) { - if (!strcmp(opname, opdefines[i]->name)) { + if (!strcmp(opname, opdefines[i]->opname)) { return i; } } - fprintf(stderr, "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, opname); + fprintf(stderr, "%s: could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, opname); return -1; } @@ -1355,6 +1409,8 @@ static int bmo_opname_to_opcode(const char *opname) * i - int * b - boolean (same as int but 1/0 only) * f - float + * s - slot_in + * S - slot_out * hv - header flagged verts (hflag) * he - header flagged edges (hflag) * hf - header flagged faces (hflag) @@ -1368,7 +1424,7 @@ static int bmo_opname_to_opcode(const char *opname) int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, va_list vlist) { - BMOpDefine *def; +// BMOpDefine *def; char *opname, *ofmt, *fmt; char slot_name[64] = {0}; int i /*, n = strlen(fmt) */, stop /*, slot_code = -1 */, type, state; @@ -1407,7 +1463,7 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v } BMO_op_init(bm, op, flag, opname); - def = opdefines[i]; +// def = opdefines[i]; i = 0; state = 1; /* 0: not inside slot_code name, 1: inside slot_code name */ @@ -1430,7 +1486,7 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v fmt[i] = 0; - if (bmo_name_to_slotcode_check(def, fmt) < 0) { + if (bmo_name_to_slotcode_check(op->slots_in, fmt) < 0) { GOTO_ERROR("name to slot code check failed"); } @@ -1456,47 +1512,57 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v else if (c == '4') size = 4; else GOTO_ERROR("matrix size was not 3 or 4"); - BMO_slot_mat_set(op, slot_name, va_arg(vlist, void *), size); + BMO_slot_mat_set(op, op->slots_in, slot_name, va_arg(vlist, void *), size); state = 1; break; } case 'v': { - BMO_slot_vec_set(op, slot_name, va_arg(vlist, float *)); + BMO_slot_vec_set(op->slots_in, slot_name, va_arg(vlist, float *)); state = 1; break; } case 'e': { BMHeader *ele = va_arg(vlist, void *); - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(op->slots_in, slot_name); slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(void *) * 4); slot->len = 1; - *((void **)slot->data.buf) = ele; + *slot->data.buf = ele; state = 1; break; } case 's': + case 'S': { - BMOperator *op2 = va_arg(vlist, void *); - const char *slot_name2 = va_arg(vlist, char *); + BMOperator *op_other = va_arg(vlist, void *); + const char *slot_name_other = va_arg(vlist, char *); - BMO_slot_copy(op2, op, slot_name2, slot_name); + if (*fmt == 's') { + BLI_assert(bmo_name_to_slotcode_check(op_other->slots_in, slot_name_other) != -1); + BMO_slot_copy(op_other, slots_in, slot_name_other, + op, slots_in, slot_name); + } + else { + BLI_assert(bmo_name_to_slotcode_check(op_other->slots_out, slot_name_other) != -1); + BMO_slot_copy(op_other, slots_out, slot_name_other, + op, slots_in, slot_name); + } state = 1; break; } case 'i': - BMO_slot_int_set(op, slot_name, va_arg(vlist, int)); + BMO_slot_int_set(op->slots_in, slot_name, va_arg(vlist, int)); state = 1; break; case 'b': - BMO_slot_bool_set(op, slot_name, va_arg(vlist, int)); + BMO_slot_bool_set(op->slots_in, slot_name, va_arg(vlist, int)); state = 1; break; case 'p': - BMO_slot_ptr_set(op, slot_name, va_arg(vlist, void *)); + BMO_slot_ptr_set(op->slots_in, slot_name, va_arg(vlist, void *)); state = 1; break; case 'f': @@ -1507,7 +1573,7 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v type = *fmt; if (NEXT_CHAR(fmt) == ' ' || NEXT_CHAR(fmt) == '\0') { - BMO_slot_float_set(op, slot_name, va_arg(vlist, double)); + BMO_slot_float_set(op->slots_in, slot_name, va_arg(vlist, double)); } else { htype = 0; @@ -1529,19 +1595,19 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v } if (type == 'h') { - BMO_slot_buffer_from_enabled_hflag(bm, op, slot_name, htype, va_arg(vlist, int)); + BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int)); } else if (type == 'H') { - BMO_slot_buffer_from_disabled_hflag(bm, op, slot_name, htype, va_arg(vlist, int)); + BMO_slot_buffer_from_disabled_hflag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int)); } else if (type == 'a') { - BMO_slot_buffer_from_all(bm, op, slot_name, htype); + BMO_slot_buffer_from_all(bm, op, op->slots_in, slot_name, htype); } else if (type == 'f') { - BMO_slot_buffer_from_enabled_flag(bm, op, slot_name, htype, va_arg(vlist, int)); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int)); } else if (type == 'F') { - BMO_slot_buffer_from_disabled_flag(bm, op, slot_name, htype, va_arg(vlist, int)); + BMO_slot_buffer_from_disabled_flag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int)); } } diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h index 14da93302b9..b74d97c9bb5 100644 --- a/source/blender/bmesh/intern/bmesh_operators.h +++ b/source/blender/bmesh/intern/bmesh_operators.h @@ -88,11 +88,6 @@ enum { OPUVC_AXIS_Y }; -enum { - DIRECTION_CW = 1, - DIRECTION_CCW -}; - /* vertex path selection values */ enum { VPATH_SELECT_EDGE_LENGTH = 0, diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 98edceb30a2..2e0471863d4 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -162,7 +162,7 @@ float BM_face_calc_area(BMFace *f) float area; int i; - BLI_array_fixedstack_declare(verts, BM_NGON_STACK_SIZE, f->len, __func__); + BLI_array_fixedstack_declare(verts, BM_DEFAULT_NGON_STACK_SIZE, f->len, __func__); BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, i) { copy_v3_v3(verts[i], l->v->co); @@ -677,6 +677,7 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], const int use_beauty, floa BMLoop *l_first; const float cos_threshold = 0.9f; + const float bias = 1.0f + 1e-6f; if (f->len == 4) { BMLoop *larr[4]; @@ -691,7 +692,7 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], const int use_beauty, floa /* pick 0/1 based on best lenth */ /* XXX Can't only rely on such test, also must check we do not get (too much) degenerated triangles!!! */ i = (((len_squared_v3v3(larr[0]->v->co, larr[2]->v->co) > - len_squared_v3v3(larr[1]->v->co, larr[3]->v->co))) != use_beauty); + len_squared_v3v3(larr[1]->v->co, larr[3]->v->co) * bias)) != use_beauty); i4 = (i + 3) % 4; /* Check produced tris aren’t too flat/narrow... * Probably not the best test, but is quite efficient and should at least avoid null-area faces! */ @@ -965,8 +966,8 @@ void BM_face_legal_splits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len) float fac1 = 1.0000001f, fac2 = 0.9f; //9999f; //0.999f; int i, j, a = 0, clen; - BLI_array_fixedstack_declare(projverts, BM_NGON_STACK_SIZE, f->len, "projvertsb"); - BLI_array_fixedstack_declare(edgeverts, BM_NGON_STACK_SIZE * 2, len * 2, "edgevertsb"); + BLI_array_fixedstack_declare(projverts, BM_DEFAULT_NGON_STACK_SIZE, f->len, "projvertsb"); + BLI_array_fixedstack_declare(edgeverts, BM_DEFAULT_NGON_STACK_SIZE * 2, len * 2, "edgevertsb"); i = 0; l = BM_iter_new(&iter, bm, BM_LOOPS_OF_FACE, f); diff --git a/source/blender/bmesh/intern/bmesh_private.h b/source/blender/bmesh/intern/bmesh_private.h index b3fe3676ab8..850e81ba3ac 100644 --- a/source/blender/bmesh/intern/bmesh_private.h +++ b/source/blender/bmesh/intern/bmesh_private.h @@ -56,15 +56,21 @@ int bmesh_elem_check(void *element, const char htype); int bmesh_radial_length(BMLoop *l); int bmesh_disk_count(BMVert *v); -/* NOTE: ensure different parts of the API do not conflict +/** + * Internal BMHeader.api_flag + * \note Ensure different parts of the API do not conflict * on using these internal flags!*/ -#define _FLAG_JF 1 /* join faces */ -#define _FLAG_MF 2 /* make face */ -#define _FLAG_MV 2 /* make face, vertex */ +enum { + _FLAG_JF = (1 << 0), /* join faces */ + _FLAG_MF = (1 << 1), /* make face */ + _FLAG_MV = (1 << 1), /* make face, vertex */ + _FLAG_OVERLAP = (1 << 2) /* general overlap flag */ +}; -#define BM_ELEM_API_FLAG_ENABLE(element, f) ((element)->oflags[0].pflag |= (f)) -#define BM_ELEM_API_FLAG_DISABLE(element, f) ((element)->oflags[0].pflag &= ~(f)) -#define BM_ELEM_API_FLAG_TEST(element, f) ((element)->oflags[0].pflag & (f)) +#define BM_ELEM_API_FLAG_ENABLE(element, f) ((element)->head.api_flag |= (f)) +#define BM_ELEM_API_FLAG_DISABLE(element, f) ((element)->head.api_flag &= ~(f)) +#define BM_ELEM_API_FLAG_TEST(element, f) ((element)->head.api_flag & (f)) +#define BM_ELEM_API_FLAG_CLEAR(element) ((element)->head.api_flag = 0) void calc_poly_plane(float (*verts)[3], const int nverts); void poly_rotate_plane(const float normal[3], float (*verts)[3], const int nverts); diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 1e1d7d1becb..ec2e90591cc 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -39,8 +39,6 @@ #include "bmesh.h" #include "intern/bmesh_private.h" -#define BM_OVERLAP (1 << 13) - /** * Returns whether or not a given vertex is * is part of a given edge. @@ -240,7 +238,7 @@ int BM_vert_in_face(BMFace *f, BMVert *v) * Compares the number of vertices in an array * that appear in a given face */ -int BM_verts_in_face(BMesh *bm, BMFace *f, BMVert **varr, int len) +int BM_verts_in_face(BMFace *f, BMVert **varr, int len) { BMLoop *l_iter, *l_first; @@ -251,7 +249,7 @@ int BM_verts_in_face(BMesh *bm, BMFace *f, BMVert **varr, int len) int i, count = 0; for (i = 0; i < len; i++) { - BMO_elem_flag_enable(bm, varr[i], BM_OVERLAP); + BM_ELEM_API_FLAG_ENABLE(varr[i], _FLAG_OVERLAP); } #ifdef USE_BMESH_HOLES @@ -266,14 +264,16 @@ int BM_verts_in_face(BMesh *bm, BMFace *f, BMVert **varr, int len) #endif do { - if (BMO_elem_flag_test(bm, l_iter->v, BM_OVERLAP)) { + if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP)) { count++; } } while ((l_iter = l_iter->next) != l_first); } - for (i = 0; i < len; i++) BMO_elem_flag_disable(bm, varr[i], BM_OVERLAP); + for (i = 0; i < len; i++) { + BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP); + } return count; } @@ -1217,7 +1217,7 @@ BMEdge *BM_edge_find_double(BMEdge *e) * \returns TRUE for overlap * */ -int BM_face_exists_overlap(BMesh *bm, BMVert **varr, int len, BMFace **r_overlapface) +int BM_face_exists_overlap(BMVert **varr, int len, BMFace **r_overlapface) { BMIter viter; BMFace *f; @@ -1225,7 +1225,7 @@ int BM_face_exists_overlap(BMesh *bm, BMVert **varr, int len, BMFace **r_overlap for (i = 0; i < len; i++) { BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) { - amount = BM_verts_in_face(bm, f, varr, len); + amount = BM_verts_in_face(f, varr, len); if (amount >= len) { if (r_overlapface) { *r_overlapface = f; @@ -1247,7 +1247,7 @@ int BM_face_exists_overlap(BMesh *bm, BMVert **varr, int len, BMFace **r_overlap * there is a face with exactly those vertices * (and only those vertices). */ -int BM_face_exists(BMesh *bm, BMVert **varr, int len, BMFace **r_existface) +int BM_face_exists(BMVert **varr, int len, BMFace **r_existface) { BMIter viter; BMFace *f; @@ -1255,7 +1255,7 @@ int BM_face_exists(BMesh *bm, BMVert **varr, int len, BMFace **r_existface) for (i = 0; i < len; i++) { BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) { - amount = BM_verts_in_face(bm, f, varr, len); + amount = BM_verts_in_face(f, varr, len); if (amount == len && amount == f->len) { if (r_existface) { *r_existface = f; @@ -1393,7 +1393,7 @@ int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len) int BM_face_exists_multi_edge(BMEdge **earr, int len) { BMVert **varr; - BLI_array_fixedstack_declare(varr, BM_NGON_STACK_SIZE, len, __func__); + BLI_array_fixedstack_declare(varr, BM_DEFAULT_NGON_STACK_SIZE, len, __func__); int ok; int i, i_next; @@ -1419,3 +1419,38 @@ int BM_face_exists_multi_edge(BMEdge **earr, int len) return ok; } + +/* convenience functions for checking flags */ +int 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) +{ + BMLoop *l_iter; + BMLoop *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (BM_elem_flag_test(l_iter->v, hflag)) { + return TRUE; + } + } while ((l_iter = l_iter->next) != l_first); + return FALSE; +} + +int BM_face_is_any_edge_flag_test(BMFace *f, const char hflag) +{ + BMLoop *l_iter; + BMLoop *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (BM_elem_flag_test(l_iter->e, hflag)) { + return TRUE; + } + } while ((l_iter = l_iter->next) != l_first); + return FALSE; +} diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index 579a1397b0c..d97faebf021 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -28,7 +28,7 @@ */ int BM_vert_in_face(BMFace *f, BMVert *v); -int BM_verts_in_face(BMesh *bm, BMFace *f, BMVert **varr, int len); +int 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); @@ -77,9 +77,9 @@ 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(BMesh *bm, BMVert **varr, int len, BMFace **r_existface); +int BM_face_exists_overlap(BMVert **varr, int len, BMFace **r_existface); -int BM_face_exists(BMesh *bm, 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); @@ -100,4 +100,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); + #endif /* __BMESH_QUERIES_H__ */ diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c index 7df5aa8fe9c..126d0f46119 100644 --- a/source/blender/bmesh/operators/bmo_bevel.c +++ b/source/blender/bmesh/operators/bmo_bevel.c @@ -15,7 +15,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * Contributor(s): Joseph Eagar, Aleksandr Mokhov, Howard Trickey + * Contributor(s): * * ***** END GPL LICENSE BLOCK ***** */ @@ -24,2211 +24,38 @@ * \ingroup bmesh */ -#include "MEM_guardedalloc.h" - -#include "BLI_listbase.h" -#include "BLI_array.h" -#include "BLI_math.h" -#include "BLI_smallhash.h" - -#include "BKE_customdata.h" +#include "BLI_utildefines.h" #include "bmesh.h" #include "intern/bmesh_operators_private.h" /* own include */ -#define NEW_BEVEL 1 - -#ifdef NEW_BEVEL -#define BEVEL_FLAG 1 -#define EDGE_SELECTED 2 - -#define BEVEL_EPSILON 1e-6 - -/* Constructed vertex, sometimes later instantiated as BMVert */ -typedef struct NewVert { - float co[3]; - BMVert *v; -} NewVert; - -struct BoundVert; - -/* Data for one end of an edge involved in a bevel */ -typedef struct EdgeHalf { - struct EdgeHalf *next, *prev; /* in CCW order */ - BMEdge *e; /* original mesh edge */ - int isbev; /* is this edge beveled? */ - int isrev; /* is e->v2 the vertex at this end? */ - int seg; /* how many segments for the bevel */ - float offset; /* offset for this edge */ - BMFace *fprev; /* face between this edge and previous, if any */ - BMFace *fnext; /* face between this edge and next, if any */ - struct BoundVert *leftv; /* left boundary vert (looking along edge to end) */ - struct BoundVert *rightv; /* right boundary vert, if beveled */ -} EdgeHalf; - -/* An element in a cyclic boundary of a Vertex Mesh (VMesh) */ -typedef struct BoundVert { - struct BoundVert *next, *prev; /* in CCW order */ - int index; /* used for vmesh indexing */ - NewVert nv; - EdgeHalf *efirst; /* first of edges attached here: in CCW order */ - EdgeHalf *elast; - EdgeHalf *ebev; /* beveled edge whose left side is attached here, if any */ -} BoundVert; - -/* Mesh structure replacing a vertex */ -typedef struct VMesh { - enum { - M_NONE, /* no polygon mesh needed */ - M_POLY, /* a simple polygon */ - M_ADJ, /* "adjacent edges" mesh pattern */ - M_CROSS, /* "cross edges" mesh pattern */ - } mesh_kind; - int count; /* number of vertices in the boundary */ - int seg; /* common # of segments for segmented edges */ - BoundVert *boundstart; /* start of boundary double-linked list */ - NewVert *mesh; /* allocated array - size and structure depends on kind */ -} VMesh; - -/* Data for a vertex involved in a bevel */ -typedef struct BevVert { - struct BevVert *next, *prev; - BMVert *v; /* original mesh vertex */ - int edgecount; /* total number of edges around the vertex */ - int selcount; /* number of selected edges around the vertex */ - EdgeHalf *edges; /* array of size edgecount; CCW order from vertex normal side */ - VMesh *vmesh; /* mesh structure for replacing vertex */ -} BevVert; - -/* - * Bevel parameters and state - */ -typedef struct BevelParams { - ListBase vertList; /* list of BevVert for each vertex involved in bevel */ - float offset; /* blender units to offset each side of a beveled edge */ - int seg; /* number of segments in beveled edge profile */ - - BMOperator *op; -} BevelParams; - -/* 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. */ -static BoundVert *add_new_bound_vert(VMesh *vm, float co[3]) -{ - BoundVert *ans = (BoundVert *) MEM_callocN(sizeof(BoundVert), "BoundVert"); - copy_v3_v3(ans->nv.co, co); - if (!vm->boundstart) { - ans->index = 0; - vm->boundstart = ans; - ans->next = ans->prev = ans; - } - else { - BoundVert *tail = vm->boundstart->prev; - ans->index = tail->index + 1; - ans->prev = tail; - ans->next = vm->boundstart; - tail->next = ans; - vm->boundstart->prev = ans; - } - vm->count++; - return ans; -} - -/* Mesh verts are indexed (i, j, k) where - * i = boundvert index (0 <= i < nv) - * j = ring index (0 <= j <= ns2) - * k = segment index (0 <= k <= ns) - * Not all of these are used, and some will share BMVerts */ -static NewVert *mesh_vert(VMesh *vm, int i, int j, int k) -{ - int nj = (vm->seg / 2) + 1; - int nk = vm->seg + 1; - - return &vm->mesh[i * nk * nj + j * nk + k]; -} - -static void create_mesh_bmvert(BMesh *bm, VMesh *vm, int i, int j, int k, BMVert *eg) -{ - NewVert *nv = mesh_vert(vm, i, j, k); - nv->v = BM_vert_create(bm, nv->co, eg); -} - -static void copy_mesh_vert(VMesh *vm, int ito, int jto, int kto, - int ifrom, int jfrom, int kfrom) -{ - NewVert *nvto, *nvfrom; - - nvto = mesh_vert(vm, ito, jto, kto); - nvfrom = mesh_vert(vm, ifrom, jfrom, kfrom); - nvto->v = nvfrom->v; - copy_v3_v3(nvto->co, nvfrom->co); -} - -/* find the EdgeHalf in bv's array that has edge bme */ -static EdgeHalf *find_edge_half(BevVert *bv, BMEdge *bme) -{ - int i; - - for (i = 0; i < bv->edgecount; i++) { - if (bv->edges[i].e == bme) - return &bv->edges[i]; - } - return NULL; -} - -/* Return the next EdgeHalf after from_e that is beveled. - * If from_e is NULL, find the first beveled edge. */ -static EdgeHalf *next_bev(BevVert *bv, EdgeHalf *from_e) -{ - EdgeHalf *e; - - if (from_e == NULL) - from_e = &bv->edges[bv->edgecount - 1]; - e = from_e; - do { - if (e->isbev) - return e; - e = e->next; - } while (e != from_e); - return NULL; -} - -/* find the BevVert corresponding to BMVert bmv */ -static BevVert *find_bevvert(BevelParams *bp, BMVert *bmv) -{ - BevVert *bv; - - for (bv = bp->vertList.first; bv; bv = bv->next) { - if (bv->v == bmv) - return bv; - } - return NULL; -} - -/* Return a good respresentative face (for materials, etc.) for faces - * created around/near BoundVert v */ -static BMFace *boundvert_rep_face(BoundVert *v) -{ - BMFace *fans = NULL; - BMFace *firstf = NULL; - BMEdge *e1, *e2; - BMFace *f1, *f2; - BMIter iter1, iter2; - - BLI_assert(v->efirst != NULL && v->elast != NULL); - e1 = v->efirst->e; - e2 = v->elast->e; - BM_ITER_ELEM (f1, &iter1, e1, BM_FACES_OF_EDGE) { - if (!firstf) - firstf = f1; - BM_ITER_ELEM (f2, &iter2, e2, BM_FACES_OF_EDGE) { - if (f1 == f2) { - fans = f1; - break; - } - } - } - if (!fans) - fans = firstf; - - return fans; -} - -/* Make ngon from verts alone. - * Make sure to properly copy face attributes and do custom data interpolation from - * example face, facerep. */ -static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, int totv, BMFace *facerep) -{ - BMIter iter; - BMLoop *l; - BMFace *f; - - if (totv == 3) { - f = BM_face_create_quad_tri(bm, - vert_arr[0], vert_arr[1], vert_arr[2], NULL, facerep, 0); - } - else if (totv == 4) { - f = BM_face_create_quad_tri(bm, - vert_arr[0], vert_arr[1], vert_arr[2], vert_arr[3], facerep, 0); - } - else { - int i; - BMEdge *e; - BMEdge **ee = NULL; - BLI_array_staticdeclare(ee, 30); - - for (i = 0; i < totv; i++) { - e = BM_edge_create(bm, vert_arr[i], vert_arr[(i + 1) % totv], NULL, TRUE); - BLI_array_append(ee, e); - } - f = BM_face_create_ngon(bm, vert_arr[0], vert_arr[1], ee, totv, FALSE); - BLI_array_free(ee); - } - if (facerep && f) { - int has_mdisps = CustomData_has_layer(&bm->ldata, CD_MDISPS); - BM_elem_attrs_copy(bm, bm, facerep, f); - BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) { - BM_loop_interp_from_face(bm, l, facerep, TRUE, TRUE); - if (has_mdisps) - BM_loop_interp_multires(bm, l, facerep); - } - } - return f; -} - -static BMFace *bev_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, - BMFace *facerep) -{ - BMVert *varr[4]; - - varr[0] = v1; - varr[1] = v2; - varr[2] = v3; - varr[3] = v4; - return bev_create_ngon(bm, varr, v4 ? 4 : 3, facerep); -} - -/* - * Calculate the meeting point between the offset edges for e1 and e2, putting answer in meetco. - * e1 and e2 share vertex v and face f (may be NULL) and viewed from the normal side of - * the bevel vertex, e1 precedes e2 in CCW order. - * If on_right is true, offset edge is on right of both edges, where e1 enters v and - * e2 leave it. If on_right is false, then the offset edge is on the left. - * When offsets are equal, the new point is on the edge bisector, with length offset/sin(angle/2), - * but if the offsets are not equal (allowing for this, as bevel modifier has edge weights that may - * lead to different offsets) then meeting point can be found be intersecting offset lines. - */ -static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, - int on_right, float meetco[3]) -{ - float dir1[3], dir2[3], norm_v[3], norm_perp1[3], norm_perp2[3], - off1a[3], off1b[3], off2a[3], off2b[3], isect2[3]; - - /* get direction vectors for two offset lines */ - sub_v3_v3v3(dir1, v->co, BM_edge_other_vert(e1->e, v)->co); - sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co); - - /* get normal to plane where meet point should be */ - cross_v3_v3v3(norm_v, dir2, dir1); - normalize_v3(norm_v); - if (!on_right) - negate_v3(norm_v); - if (is_zero_v3(norm_v)) { - /* 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 */ - if (f) - copy_v3_v3(norm_v, f->no); - else - copy_v3_v3(norm_v, v->no); - cross_v3_v3v3(norm_perp1, dir1, norm_v); - normalize_v3(norm_perp1); - copy_v3_v3(off1a, v->co); - madd_v3_v3fl(off1a, norm_perp1, e1->offset); - copy_v3_v3(meetco, off1a); - } - else { - /* get vectors perp to each edge, perp to norm_v, and pointing into face */ - if (f) { - copy_v3_v3(norm_v, f->no); - normalize_v3(norm_v); - } - cross_v3_v3v3(norm_perp1, dir1, norm_v); - cross_v3_v3v3(norm_perp2, dir2, norm_v); - normalize_v3(norm_perp1); - normalize_v3(norm_perp2); - - /* get points that are offset distances from each line, then another point on each line */ - copy_v3_v3(off1a, v->co); - madd_v3_v3fl(off1a, norm_perp1, e1->offset); - add_v3_v3v3(off1b, off1a, dir1); - copy_v3_v3(off2a, v->co); - madd_v3_v3fl(off2a, norm_perp2, e2->offset); - add_v3_v3v3(off2b, off2a, dir2); - - /* intersect the lines; by construction they should be on the same plane and not parallel */ - if (!isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2)) { - BLI_assert(!"offset_meet failure"); - copy_v3_v3(meetco, off1a); /* just to do something */ - } - } -} - -/* Like offset_meet, but here f1 and f2 must not be NULL and give the - * planes in which to run the offset lines. They may not meet exactly, - * but the line intersection routine will find the closest approach point. */ -static void offset_in_two_planes(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, - BMFace *f1, BMFace *f2, float meetco[3]) -{ - float dir1[3], dir2[3], norm_perp1[3], norm_perp2[3], - off1a[3], off1b[3], off2a[3], off2b[3], isect2[3]; - - BLI_assert(f1 != NULL && f2 != NULL); - - /* get direction vectors for two offset lines */ - sub_v3_v3v3(dir1, v->co, BM_edge_other_vert(e1->e, v)->co); - sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co); - - /* get directions into offset planes */ - cross_v3_v3v3(norm_perp1, dir1, f1->no); - normalize_v3(norm_perp1); - cross_v3_v3v3(norm_perp2, dir2, f2->no); - normalize_v3(norm_perp2); - - /* get points that are offset distances from each line, then another point on each line */ - copy_v3_v3(off1a, v->co); - madd_v3_v3fl(off1a, norm_perp1, e1->offset); - add_v3_v3v3(off1b, off1a, dir1); - copy_v3_v3(off2a, v->co); - madd_v3_v3fl(off2a, norm_perp2, e2->offset); - add_v3_v3v3(off2b, off2a, dir2); - - /* intersect the lines; by construction they should be on the same plane and not parallel */ - if (!isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2)) { - BLI_assert(!"offset_meet failure"); - copy_v3_v3(meetco, off1a); /* just to do something */ - } -} - -/* Offset by e->offset in plane with normal plane_no, on left if left==TRUE, - * else on right. If no is NULL, choose an arbitrary plane different - * from eh's direction. */ -static void offset_in_plane(EdgeHalf *e, float plane_no[3], int left, float r[3]) -{ - float dir[3], no[3]; - BMVert *v; - - v = e->isrev ? e->e->v1 : e->e->v2; - - sub_v3_v3v3(dir, BM_edge_other_vert(e->e, v)->co, v->co); - normalize_v3(dir); - if (plane_no) { - copy_v3_v3(no, plane_no); - } - else { - zero_v3(no); - if (fabs(dir[0]) < fabs(dir[1])) - no[0] = 1.0f; - else - no[1] = 1.0f; - } - if (left) - cross_v3_v3v3(r, no, dir); - else - cross_v3_v3v3(r, dir, no); - normalize_v3(r); - mul_v3_fl(r, e->offset); -} - -/* Calculate coordinates of a point a distance d from v on e->e and return it in slideco */ -static void slide_dist(EdgeHalf *e, BMVert *v, float d, float slideco[3]) -{ - float dir[3], len; - - sub_v3_v3v3(dir, v->co, BM_edge_other_vert(e->e, v)->co); - len = len_v3(dir); - normalize_v3(dir); - if (d > len) - d = len - (float)(50 * BEVEL_EPSILON); - copy_v3_v3(slideco, v->co); - madd_v3_v3fl(slideco, dir, -d); -} - -/* Calculate the point on e where line (co_a, co_b) comes closest to and return it in projco */ -static void project_to_edge(BMEdge *e, float co_a[3], float co_b[3], float projco[3]) -{ - float otherco[3]; - - if (!isect_line_line_v3(e->v1->co, e->v2->co, co_a, co_b, - projco, otherco)) { - BLI_assert(!"project meet failure"); - copy_v3_v3(projco, e->v1->co); - } -} - - -/* return 1 if a and b are in CCW order on the normal side of f, - * and -1 if they are reversed, and 0 if there is no shared face f */ -static int bev_ccw_test(BMEdge *a, BMEdge *b, BMFace *f) -{ - BMLoop *la, *lb; - - if (!f) - return 0; - la = BM_face_edge_share_loop(f, a); - lb = BM_face_edge_share_loop(f, b); - if (!la || !lb) - return 0; - return lb->next == la ? 1 : -1; -} - -/* - * calculation of points on the round profile - * r - result, coordinate of point on round profile - * method: - * Inscribe a circle in angle va - v -vb - * such that it touches the arms at offset from v. - * Rotate the center-va segment by (i/n) of the - * angle va - center -vb, and put the endpoint - * of that segment in r. - */ -static void get_point_on_round_profile(float r[3], float offset, int i, int count, - float va[3], float v[3], float vb[3]) -{ - float vva[3], vvb[3], angle, center[3], rv[3], axis[3], co[3]; - - sub_v3_v3v3(vva, va, v); - sub_v3_v3v3(vvb, vb, v); - normalize_v3(vva); - normalize_v3(vvb); - angle = angle_v3v3(vva, vvb); - - add_v3_v3v3(center, vva, vvb); - normalize_v3(center); - mul_v3_fl(center, offset * (1.0f / cosf(0.5f * angle))); - add_v3_v3(center, v); /* coordinates of the center of the inscribed circle */ - - - sub_v3_v3v3(rv, va, center); /* radius vector */ - - - sub_v3_v3v3(co, v, center); - cross_v3_v3v3(axis, rv, co); /* calculate axis */ - - sub_v3_v3v3(vva, va, center); - sub_v3_v3v3(vvb, vb, center); - angle = angle_v3v3(vva, vvb); - - rotate_v3_v3v3fl(co, rv, axis, angle * (float)(i) / (float)(count)); - - add_v3_v3(co, center); - copy_v3_v3(r, co); -} - -/* - * Find the point (i/n) of the way around the round profile for e, - * where start point is va, midarc point is vmid, and end point is vb. - * Return the answer in profileco. - * Method: - * Adjust va and vb (along edge direction) so that they are perpendicular - * to edge at v, then use get_point_on_round_profile, then project - * back onto original va - vmid - vb plane. - * If va, vmid, and vb are all on the same plane, just interpolate between va and vb. - */ -static void get_point_on_round_edge(EdgeHalf *e, int i, - float va[3], float vmid[3], float vb[3], float profileco[3]) -{ - float vva[3], vvb[3], point[3], dir[3], vaadj[3], vbadj[3], p2[3], pn[3]; - int n = e->seg; - - sub_v3_v3v3(vva, va, vmid); - sub_v3_v3v3(vvb, vb, vmid); - if (e->isrev) - sub_v3_v3v3(dir, e->e->v1->co, e->e->v2->co); - else - sub_v3_v3v3(dir, e->e->v2->co, e->e->v1->co); - normalize_v3(dir); - if (fabsf(angle_v3v3(vva, vvb) - (float)M_PI) > (float)BEVEL_EPSILON) { - copy_v3_v3(vaadj, va); - madd_v3_v3fl(vaadj, dir, -len_v3(vva) * cosf(angle_v3v3(vva, dir))); - copy_v3_v3(vbadj, vb); - madd_v3_v3fl(vbadj, dir, -len_v3(vvb) * cosf(angle_v3v3(vvb, dir))); - - get_point_on_round_profile(point, e->offset, i, n, vaadj, vmid, vbadj); - - add_v3_v3v3(p2, profileco, dir); - cross_v3_v3v3(pn, vva, vvb); - if (!isect_line_plane_v3(profileco, point, p2, vmid, pn, 0)) { - BLI_assert(!"bevel: unexpected non-intersection"); - copy_v3_v3(profileco, point); - } - } - else { - /* planar case */ - interp_v3_v3v3(profileco, va, vb, (float) i / (float) n); - } -} - -static void mid_v3_v3v3v3(float v[3], const float v1[3], const float v2[3], const float v3[3]) -{ - v[0] = (v1[0] + v2[0] + v3[0]) / 3.0f; - v[1] = (v1[1] + v2[1] + v3[1]) / 3.0f; - v[2] = (v1[2] + v2[2] + v3[2]) / 3.0f; -} - -/* 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. - * Doesn't make the actual BMVerts */ -static void build_boundary(BevVert *bv) -{ - EdgeHalf *efirst, *e; - BoundVert *v; - VMesh *vm; - float co[3], *no; - float lastd; - - e = efirst = next_bev(bv, NULL); - vm = bv->vmesh; - - BLI_assert(bv->edgecount >= 2); /* since bevel edges incident to 2 faces */ - - if (bv->edgecount == 2 && bv->selcount == 1) { - /* special case: beveled edge meets non-beveled one at valence 2 vert */ - no = e->fprev ? e->fprev->no : (e->fnext ? e->fnext->no : NULL); - offset_in_plane(e, no, TRUE, co); - v = add_new_bound_vert(vm, co); - v->efirst = v->elast = v->ebev = e; - e->leftv = v; - no = e->fnext ? e->fnext->no : (e->fprev ? e->fprev->no : NULL); - offset_in_plane(e, no, FALSE, co); - v = add_new_bound_vert(vm, co); - v->efirst = v->elast = e; - e->rightv = v; - /* make artifical extra point along unbeveled edge, and form triangle */ - slide_dist(e->next, bv->v, e->offset, co); - v = add_new_bound_vert(vm, co); - v->efirst = v->elast = e->next; - vm->mesh_kind = M_POLY; - return; - } - - lastd = e->offset; - vm->boundstart = NULL; - do { - if (e->isbev) { - /* handle only left side of beveled edge e here: next iteration should do right side */ - if (e->prev->isbev) { - BLI_assert(e->prev != e); /* see: wire edge special case */ - offset_meet(e->prev, e, bv->v, e->fprev, TRUE, co); - v = add_new_bound_vert(vm, co); - v->efirst = e->prev; - v->elast = v->ebev = e; - e->leftv = v; - e->prev->rightv = v; - } - else { - /* e->prev is not beveled */ - if (e->prev->prev->isbev) { - BLI_assert(e->prev->prev != e); /* see: edgecount 2, selcount 1 case */ - /* find meet point between e->prev->prev and e and attach e->prev there */ - /* TODO: fix case when one or both faces in following are NULL */ - offset_in_two_planes(e->prev->prev, e, bv->v, - e->prev->prev->fnext, e->fprev, co); - v = add_new_bound_vert(vm, co); - v->efirst = e->prev->prev; - v->elast = v->ebev = e; - e->leftv = v; - e->prev->leftv = v; - e->prev->prev->rightv = v; - } - else { - /* neither e->prev nor e->prev->prev are beveled: make on-edge on e->prev */ - offset_meet(e->prev, e, bv->v, e->fprev, TRUE, co); - v = add_new_bound_vert(vm, co); - v->efirst = e->prev; - v->elast = v->ebev = e; - e->leftv = v; - e->prev->leftv = v; - } - } - lastd = len_v3v3(bv->v->co, v->nv.co); - } - else { - /* e is not beveled */ - if (e->next->isbev) { - /* next iteration will place e between beveled previous and next edges */ - e = e->next; - continue; - } - if (e->prev->isbev) { - /* on-edge meet between e->prev and e */ - offset_meet(e->prev, e, bv->v, e->fprev, TRUE, co); - v = add_new_bound_vert(vm, co); - v->efirst = e->prev; - v->elast = e; - e->leftv = v; - e->prev->rightv = v; - } - else { - /* None of e->prev, e, e->next are beveled. - * could either leave alone or add slide points to make - * one polygon around bv->v. For now, we choose latter. - * Could slide to make an even bevel plane but for now will - * just use last distance a meet point moved from bv->v. */ - slide_dist(e, bv->v, lastd, co); - v = add_new_bound_vert(vm, co); - v->efirst = v->elast = e; - e->leftv = v; - } - } - e = e->next; - } while (e != efirst); - - BLI_assert(vm->count >= 2); - if (vm->count == 2 && bv->edgecount == 3) - vm->mesh_kind = M_NONE; - else if (efirst->seg == 1 || bv->selcount < 3) - vm->mesh_kind = M_POLY; - else - vm->mesh_kind = M_ADJ; - /* TODO: if vm->count == 4 and bv->selcount == 4, use M_CROSS pattern */ -} - -/* - * 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 pattern, - * then make the BMVerts and the new faces. */ -static void bevel_build_rings(BMesh *bm, BevVert *bv) -{ - int k, ring, i, n, ns, ns2, nn; - VMesh *vm = bv->vmesh; - BoundVert *v, *vprev, *vnext; - NewVert *nv, *nvprev, *nvnext; - BMVert *bmv, *bmv1, *bmv2, *bmv3, *bmv4; - BMFace *f; - float co[3], coa[3], cob[3], midco[3]; - - n = vm->count; - ns = vm->seg; - ns2 = ns / 2; - BLI_assert(n > 2 && ns > 1); - - /* Make initial rings, going between points on neighbors */ - for (ring = 1; ring <= ns2; ring++) { - v = vm->boundstart; - do { - i = v->index; - if (v->ebev) { - /* get points coords of points a and b, on outer rings - * of prev and next edges, k away from this edge */ - vprev = v->prev; - vnext = v->next; - - if (vprev->ebev) - nvprev = mesh_vert(vm, vprev->index, 0, ns - ring); - else - nvprev = mesh_vert(vm, vprev->index, 0, ns); - copy_v3_v3(coa, nvprev->co); - nv = mesh_vert(vm, i, ring, 0); - copy_v3_v3(nv->co, coa); - nv->v = nvprev->v; - - if (vnext->ebev) - nvnext = mesh_vert(vm, vnext->index, 0, ring); - else - nvnext = mesh_vert(vm, vnext->index, 0, 0); - copy_v3_v3(cob, nvnext->co); - nv = mesh_vert(vm, i, ring, ns); - copy_v3_v3(nv->co, cob); - nv->v = nvnext->v; - - /* TODO: better calculation of new midarc point? */ - project_to_edge(v->ebev->e, coa, cob, midco); - - for (k = 1; k < ns; k++) { - get_point_on_round_edge(v->ebev, k, coa, midco, cob, co); - copy_v3_v3(mesh_vert(vm, i, ring, k)->co, co); - } - } - v = v->next; - } while (v != vm->boundstart); - } - - /* Now make sure cross points of rings share coordinates and vertices */ - v = vm->boundstart; - do { - i = v->index; - if (v->ebev) { - vprev = v->prev; - vnext = v->next; - if (vprev->ebev) { - for (ring = 1; ring <= ns2; ring++) { - for (k = 1; k <= ns2; k++) { - if (ns % 2 == 0 && (k == ns2 || ring == ns2)) - continue; /* center line is special case: do after the rest are done */ - nv = mesh_vert(vm, i, ring, k); - nvprev = mesh_vert(vm, vprev->index, k, ns - ring); - mid_v3_v3v3(co, nv->co, nvprev->co); - copy_v3_v3(nv->co, co); - 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); - } - } - if (!vprev->prev->ebev) { - for (ring = 1; ring <= ns2; ring++) { - for (k = 1; k <= ns2; k++) { - if (ns % 2 == 0 && (k == ns2 || ring == ns2)) - continue; - create_mesh_bmvert(bm, vm, vprev->index, ring, k, bv->v); - } - } - } - if (!vnext->ebev) { - for (ring = 1; ring <= ns2; ring++) { - for (k = ns - ns2; k < ns; k++) { - if (ns % 2 == 0 && (k == ns2 || ring == ns2)) - continue; - create_mesh_bmvert(bm, vm, i, ring, k, bv->v); - } - } - } - } - } - v = v->next; - } while (v != vm->boundstart); - - if (ns % 2 == 0) { - /* do special case center lines */ - v = vm->boundstart; - do { - i = v->index; - if (v->ebev) { - vprev = v->prev; - vnext = v->next; - for (k = 1; k < ns2; k++) { - nv = mesh_vert(vm, i, k, ns2); - if (vprev->ebev) - nvprev = mesh_vert(vm, vprev->index, ns2, ns - k); - if (vnext->ebev) - nvnext = mesh_vert(vm, vnext->index, ns2, k); - if (vprev->ebev && vnext->ebev) { - mid_v3_v3v3v3(co, nvprev->co, nv->co, nvnext->co); - copy_v3_v3(nv->co, co); - 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); - - } - else if (vprev->ebev) { - mid_v3_v3v3(co, nvprev->co, nv->co); - copy_v3_v3(nv->co, co); - create_mesh_bmvert(bm, vm, i, k, ns2, bv->v); - copy_mesh_vert(vm, vprev->index, ns2, ns - k, i, k, ns2); - } - else if (vnext->ebev) { - mid_v3_v3v3(co, nv->co, nvnext->co); - copy_v3_v3(nv->co, co); - create_mesh_bmvert(bm, vm, i, k, ns2, bv->v); - copy_mesh_vert(vm, vnext->index, ns2, k, i, k, ns2); - } - } - } - v = v->next; - } while (v != vm->boundstart); - - /* center point need to be average of all centers of rings */ - /* TODO: this is wrong if not all verts have ebev: could have - * several disconnected sections of mesh. */ - zero_v3(midco); - nn = 0; - v = vm->boundstart; - do { - i = v->index; - if (v->ebev) { - nv = mesh_vert(vm, i, ns2, ns2); - add_v3_v3(midco, nv->co); - nn++; - } - v = v->next; - } while (v != vm->boundstart); - mul_v3_fl(midco, 1.0f / nn); - bmv = BM_vert_create(bm, midco, NULL); - v = vm->boundstart; - do { - i = v->index; - if (v->ebev) { - nv = mesh_vert(vm, i, ns2, ns2); - copy_v3_v3(nv->co, midco); - nv->v = bmv; - } - v = v->next; - } while (v != vm->boundstart); - } - - /* Make the ring quads */ - for (ring = 0; ring < ns2; ring++) { - v = vm->boundstart; - do { - i = v->index; - f = boundvert_rep_face(v); - if (v->ebev && (v->prev->ebev || v->next->ebev)) { - for (k = 0; k < ns2 + (ns % 2); k++) { - bmv1 = mesh_vert(vm, i, ring, k)->v; - bmv2 = mesh_vert(vm, i, ring, k + 1)->v; - bmv3 = mesh_vert(vm, i, ring + 1, k + 1)->v; - bmv4 = mesh_vert(vm, i, ring + 1, k)->v; - BLI_assert(bmv1 && bmv2 && bmv3 && bmv4); - if (bmv3 == bmv4 || bmv1 == bmv4) - bmv4 = NULL; - bev_create_quad_tri(bm, bmv1, bmv2, bmv3, bmv4, f); - } - } - else if (v->prev->ebev && v->prev->prev->ebev) { - /* finish off a sequence of beveled edges */ - i = v->prev->index; - f = boundvert_rep_face(v->prev); - for (k = ns2 + (ns % 2); k < ns; k++) { - bmv1 = mesh_vert(vm, i, ring + 1, k)->v; - bmv2 = mesh_vert(vm, i, ring, k)->v; - bmv3 = mesh_vert(vm, i, ring, k + 1)->v; - BLI_assert(bmv1 && bmv2 && bmv3); - bev_create_quad_tri(bm, bmv1, bmv2, bmv3, NULL, f); - } - } - v = v->next; - } while (v != vm->boundstart); - } - - /* Make center ngon if odd number of segments and fully beveled */ - if (ns % 2 == 1 && vm->count == bv->selcount) { - BMVert **vv = NULL; - BLI_array_declare(vv); - - v = vm->boundstart; - do { - i = v->index; - BLI_assert(v->ebev); - BLI_array_append(vv, mesh_vert(vm, i, ns2, ns2)->v); - v = v->next; - } while (v != vm->boundstart); - f = boundvert_rep_face(vm->boundstart); - bev_create_ngon(bm, vv, BLI_array_count(vv), f); - - BLI_array_free(vv); - } - - /* Make 'rest-of-vmesh' polygon if not fully beveled */ - if (vm->count > bv->selcount) { - int j; - BMVert **vv = NULL; - BLI_array_declare(vv); - - v = vm->boundstart; - f = boundvert_rep_face(v); - j = 0; - do { - i = v->index; - if (v->ebev) { - if (!v->prev->ebev) { - for (k = 0; k < ns2; k++) { - bmv1 = mesh_vert(vm, i, ns2, k)->v; - if (!(j > 0 && bmv1 == vv[j - 1])) { - BLI_array_append(vv, bmv1); - j++; - } - } - } - bmv1 = mesh_vert(vm, i, ns2, ns2)->v; - if (!(j > 0 && bmv1 == vv[j - 1])) { - BLI_array_append(vv, bmv1); - j++; - } - if (!v->next->ebev) { - for (k = ns - ns2; k < ns; k++) { - bmv1 = mesh_vert(vm, i, ns2, k)->v; - if (!(j > 0 && bmv1 == vv[j - 1])) { - BLI_array_append(vv, bmv1); - j++; - } - } - } - } - else { - BLI_array_append(vv, mesh_vert(vm, i, 0, 0)->v); - j++; - } - v = v->next; - } while (v != vm->boundstart); - if (vv[0] == vv[j - 1]) - j--; - bev_create_ngon(bm, vv, j, f); - - BLI_array_free(vv); - } -} - -static void bevel_build_poly(BMesh *bm, BevVert *bv) -{ - int n, k; - VMesh *vm = bv->vmesh; - BoundVert *v; - BMVert **vv = NULL; - BLI_array_declare(vv); - - v = vm->boundstart; - n = 0; - do { - /* accumulate vertices for vertex ngon */ - BLI_array_append(vv, v->nv.v); - n++; - if (v->ebev && v->ebev->seg > 1) { - for (k = 1; k < v->ebev->seg; k++) { - BLI_array_append(vv, mesh_vert(vm, v->index, 0, k)->v); - n++; - } - } - v = v->next; - } while (v != vm->boundstart); - if (n > 2) - bev_create_ngon(bm, vv, n, boundvert_rep_face(v)); - BLI_array_free(vv); -} - -/* Given that the boundary is built, now make the actual BMVerts - * for the boundary and the interior of the vertex mesh. */ -static void build_vmesh(BMesh *bm, BevVert *bv) -{ - VMesh *vm = bv->vmesh; - BoundVert *v, *weld1, *weld2; - int n, ns, ns2, i, k, weld; - float *va, *vb, co[3], midco[3]; - - n = vm->count; - ns = vm->seg; - ns2 = ns / 2; - - vm->mesh = (NewVert *)MEM_callocN(n * (ns2 + 1) * (ns + 1) * sizeof(NewVert), "NewVert"); - - /* special case: two beveled ends welded together */ - weld = (bv->selcount == 2) && (vm->count == 2); - weld1 = weld2 = NULL; /* will hold two BoundVerts involved in weld */ - - /* make (i, 0, 0) mesh verts for all i */ - v = vm->boundstart; - do { - i = v->index; - copy_v3_v3(mesh_vert(vm, i, 0, 0)->co, v->nv.co); - create_mesh_bmvert(bm, vm, i, 0, 0, bv->v); - v->nv.v = mesh_vert(vm, i, 0, 0)->v; - if (weld && v->ebev) { - if (!weld1) - weld1 = v; - else - weld2 = v; - } - v = v->next; - } while (v != vm->boundstart); - - /* copy other ends to (i, 0, ns) for all i, and fill in profiles for beveled edges */ - v = vm->boundstart; - do { - i = v->index; - copy_mesh_vert(vm, i, 0, ns, v->next->index, 0, 0); - if (v->ebev) { - 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); - for (k = 1; k < ns; k++) { - get_point_on_round_edge(v->ebev, k, va, midco, vb, co); - copy_v3_v3(mesh_vert(vm, i, 0, k)->co, co); - if (!weld) - create_mesh_bmvert(bm, vm, i, 0, k, bv->v); - } - } - v = v->next; - } while (v != vm->boundstart); - - if (weld) { - for (k = 1; k < ns; k++) { - mid_v3_v3v3(co, mesh_vert(vm, weld1->index, 0, k)->co, - mesh_vert(vm, weld2->index, 0, ns - k)->co); - copy_v3_v3(mesh_vert(vm, weld1->index, 0, k)->co, co); - create_mesh_bmvert(bm, vm, weld1->index, 0, k, bv->v); - } - for (k = 1; k < ns; k++) - copy_mesh_vert(vm, weld2->index, 0, ns - k, weld1->index, 0, k); - } - - if (vm->mesh_kind == M_ADJ) - bevel_build_rings(bm, bv); - else if (vm->mesh_kind == M_POLY) - bevel_build_poly(bm, bv); -} - -/* - * Construction around the vertex - */ -static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMOperator *op, BMVert *v) -{ - - BMOIter siter; - BMEdge *bme; - BevVert *bv; - BMEdge *bme2, *unflagged_bme; - BMFace *f; - BMIter iter, iter2; - EdgeHalf *e; - int i, ntot, found_shared_face, ccw_test_sum; - int nsel = 0; - - /* Gather input selected edges. - * Only bevel selected edges that have exactly two incident faces. */ - BMO_ITER (bme, &siter, bm, op, "geom", BM_EDGE) { - if ((bme->v1 == v) || (BM_edge_other_vert(bme, bme->v1) == v)) { - if (BM_edge_face_count(bme) == 2) { - BMO_elem_flag_enable(bm, bme, EDGE_SELECTED); - nsel++; - } - } - } - - if (nsel == 0) - return; - - ntot = BM_vert_edge_count(v); - bv = (BevVert *)MEM_callocN(sizeof(BevVert), "BevVert"); - bv->v = v; - bv->edgecount = ntot; - bv->selcount = nsel; - bv->edges = (EdgeHalf *)MEM_callocN(ntot * sizeof(EdgeHalf), "EdgeHalf"); - bv->vmesh = (VMesh *)MEM_callocN(sizeof(VMesh), "VMesh"); - bv->vmesh->seg = bp->seg; - BLI_addtail(&bp->vertList, bv); - - /* add edges to bv->edges in order that keeps adjacent edges sharing - * a face, if possible */ - i = 0; - bme = v->e; - BMO_elem_flag_enable(bm, bme, BEVEL_FLAG); - e = &bv->edges[0]; - e->e = bme; - for (i = 0; i < ntot; i++) { - if (i > 0) { - /* find an unflagged edge bme2 that shares a face f with previous bme */ - found_shared_face = 0; - unflagged_bme = NULL; - BM_ITER_ELEM (bme2, &iter, v, BM_EDGES_OF_VERT) { - if (BMO_elem_flag_test(bm, bme2, BEVEL_FLAG)) - continue; - if (!unflagged_bme) - unflagged_bme = bme2; - BM_ITER_ELEM (f, &iter2, bme2, BM_FACES_OF_EDGE) { - if (BM_face_edge_share_loop(f, bme)) { - found_shared_face = 1; - break; - } - } - if (found_shared_face) - break; - } - e = &bv->edges[i]; - if (found_shared_face) { - e->e = bme2; - e->fprev = f; - bv->edges[i - 1].fnext = f; - } - else { - e->e = unflagged_bme; - } - } - bme = e->e; - BMO_elem_flag_enable(bm, bme, BEVEL_FLAG); - if (BMO_elem_flag_test(bm, bme, EDGE_SELECTED)) { - e->isbev = 1; - e->seg = bp->seg; - } - else { - e->isbev = 0; - e->seg = 0; - } - e->isrev = (bme->v2 == v); - e->offset = e->isbev ? bp->offset : 0.0f; - } - /* find wrap-around shared face */ - BM_ITER_ELEM (f, &iter2, bme, BM_FACES_OF_EDGE) { - if (BM_face_edge_share_loop(f, bv->edges[0].e)) { - if (bv->edges[0].fnext == f) - continue; /* if two shared faces, want the other one now */ - bv->edges[ntot - 1].fnext = f; - bv->edges[0].fprev = f; - break; - } - } - - /* remove BEVEL_FLAG now that we are finished with it*/ - for (i = 0; i < ntot; i++) - BMO_elem_flag_disable(bm, bv->edges[i].e, BEVEL_FLAG); - - /* if edge array doesn't go CCW around vertex from average normal side, - * reverse the array, being careful to reverse face pointers too */ - if (ntot > 1) { - ccw_test_sum = 0; - for (i = 0; i < ntot; i++) - ccw_test_sum += bev_ccw_test(bv->edges[i].e, bv->edges[(i + 1) % ntot].e, - bv->edges[i].fnext); - if (ccw_test_sum < 0) { - for (i = 0; i <= (ntot / 2) - 1; i++) { - SWAP(EdgeHalf, bv->edges[i], bv->edges[ntot - i - 1]); - SWAP(BMFace *, bv->edges[i].fprev, bv->edges[i].fnext); - SWAP(BMFace *, bv->edges[ntot - i - 1].fprev, bv->edges[ntot - i - 1].fnext); - } - if (ntot % 2 == 1) { - i = ntot / 2; - SWAP(BMFace *, bv->edges[i].fprev, bv->edges[i].fnext); - } - } - } - - for (i = 0; i < ntot; i++) { - e = &bv->edges[i]; - e->next = &bv->edges[(i + 1) % ntot]; - e->prev = &bv->edges[(i + ntot - 1) % ntot]; - } - - build_boundary(bv); - build_vmesh(bm, bv); -} - -/* Face f has at least one beveled vertex. Rebuild f */ -static void rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) -{ - BMIter liter; - BMLoop *l, *lprev; - BevVert *bv; - BoundVert *v, *vstart, *vend; - EdgeHalf *e, *eprev; - VMesh *vm; - int i, k; - BMVert *bmv; - BMVert **vv = NULL; - BLI_array_declare(vv); - - BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - bv = find_bevvert(bp, l->v); - if (bv) { - lprev = l->prev; - e = find_edge_half(bv, l->e); - eprev = find_edge_half(bv, lprev->e); - BLI_assert(e != NULL && eprev != NULL); - vstart = eprev->leftv; - if (e->isbev) - vend = e->rightv; - else - vend = e->leftv; - v = vstart; - vm = bv->vmesh; - BLI_array_append(vv, v->nv.v); - while (v != vend) { - if (vm->mesh_kind == M_NONE && v->ebev && v->ebev->seg > 1 && v->ebev != e && v->ebev != eprev) { - /* case of 3rd face opposite a beveled edge, with no vmesh */ - i = v->index; - e = v->ebev; - for (k = 1; k < e->seg; k++) { - bmv = mesh_vert(vm, i, 0, k)->v; - BLI_array_append(vv, bmv); - } - } - v = v->prev; - BLI_array_append(vv, v->nv.v); - } - } - else { - BLI_array_append(vv, l->v); - } - } - bev_create_ngon(bm, vv, BLI_array_count(vv), f); - BLI_array_free(vv); -} - -/* All polygons touching v need rebuilding because beveling v has made new vertices */ -static void bevel_rebuild_existing_polygons(BMesh *bm, BevelParams *bp, BMVert *v) -{ - BMFace *f; - BMIter iter; - - /* TODO: don't iterate through all faces, but just local geometry around v */ - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - BMLoop *l = f->l_first; - do { - if (l->v == v) { - rebuild_polygon(bm, bp, f); - BM_face_kill(bm, f); - } - l = l->next; - } while (l != f->l_first); - } -} - - - -/* - * Build the polygons along the selected Edge - */ -static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme) -{ - BevVert *bv1, *bv2; - BMVert *bmv1, *bmv2, *bmv3, *bmv4, *bmv1i, *bmv2i, *bmv3i, *bmv4i; - VMesh *vm1, *vm2; - EdgeHalf *e1, *e2; - BMFace *f1, *f2, *f; - int k, nseg, i1, i2; - - if (BM_edge_face_count(bme) != 2) - return; - - bv1 = find_bevvert(bp, bme->v1); - bv2 = find_bevvert(bp, bme->v2); - - BLI_assert(bv1 && bv2); - - e1 = find_edge_half(bv1, bme); - e2 = find_edge_half(bv2, bme); - - BLI_assert(e1 && e2); - - /* v4 v3 - * \ / - * e->v1 - e->v2 - * / \ - * v1 v2 */ - - nseg = e1->seg; - BLI_assert(nseg > 0 && nseg == e2->seg); - - bmv1 = e1->leftv->nv.v; - bmv4 = e1->rightv->nv.v; - bmv2 = e2->rightv->nv.v; - bmv3 = e2->leftv->nv.v; - - BLI_assert(bmv1 && bmv2 && bmv3 && bmv4); - - f1 = boundvert_rep_face(e1->leftv); - f2 = boundvert_rep_face(e1->rightv); - - if (nseg == 1) { - bev_create_quad_tri(bm, bmv1, bmv2, bmv3, bmv4, f1); - } - else { - i1 = e1->leftv->index; - i2 = e2->leftv->index; - vm1 = bv1->vmesh; - vm2 = bv2->vmesh; - bmv1i = bmv1; - bmv2i = bmv2; - for (k = 1; k <= nseg; k++) { - bmv4i = mesh_vert(vm1, i1, 0, k)->v; - bmv3i = mesh_vert(vm2, i2, 0, nseg - k)->v; - f = (k <= nseg / 2 + (nseg % 2)) ? f1 : f2; - bev_create_quad_tri(bm, bmv1i, bmv2i, bmv3i, bmv4i, f); - bmv1i = bmv4i; - bmv2i = bmv3i; - } - } -} - - -static void free_bevel_params(BevelParams *bp) -{ - BevVert *bv; - VMesh *vm; - BoundVert *v, *vnext; - - for (bv = bp->vertList.first; bv; bv = bv->next) { - MEM_freeN(bv->edges); - vm = bv->vmesh; - v = vm->boundstart; - if (v) { - do { - vnext = v->next; - MEM_freeN(v); - v = vnext; - } while (v != vm->boundstart); - } - if (vm->mesh) - MEM_freeN(vm->mesh); - MEM_freeN(vm); - } - BLI_freelistN(&bp->vertList); -} - void bmo_bevel_exec(BMesh *bm, BMOperator *op) { - BMOIter siter; - BMVert *v; - BMEdge *e; - BevelParams bp; - - bp.offset = BMO_slot_float_get(op, "offset"); - bp.op = op; - bp.seg = BMO_slot_int_get(op, "segments"); - - if (bp.offset > 0) { - bp.vertList.first = bp.vertList.last = NULL; - - /* The analysis of the input vertices and execution additional constructions */ - BMO_ITER (v, &siter, bm, op, "geom", BM_VERT) { - bevel_vert_construct(bm, &bp, op, v); - } - /* Build polygons for edges */ - BMO_ITER (e, &siter, bm, op, "geom", BM_EDGE) { - bevel_build_edge_polygons(bm, &bp, e); - } - - BMO_ITER (v, &siter, bm, op, "geom", BM_VERT) { - bevel_rebuild_existing_polygons(bm, &bp, v); - } - - BMO_ITER (v, &siter, bm, op, "geom", BM_VERT) { - if (find_bevvert(&bp, v)) - BM_vert_kill(bm, v); - } - free_bevel_params(&bp); - } - -} - -#else -#define BEVEL_FLAG 1 -#define BEVEL_DEL 2 -#define FACE_NEW 4 -#define EDGE_OLD 8 -#define FACE_OLD 16 -#define VERT_OLD 32 -#define FACE_SPAN 64 -#define FACE_HOLE 128 - -typedef struct LoopTag { - BMVert *newv; -} LoopTag; - -typedef struct EdgeTag { - BMVert *newv1, *newv2; -} EdgeTag; - -static void calc_corner_co(BMLoop *l, const float fac, float r_co[3], - const short do_dist, const short do_even) -{ - float no[3], l_vec_prev[3], l_vec_next[3], l_co_prev[3], l_co[3], l_co_next[3], co_ofs[3]; - int is_concave; - - /* first get the prev/next verts */ - if (l->f->len > 2) { - copy_v3_v3(l_co_prev, l->prev->v->co); - copy_v3_v3(l_co, l->v->co); - copy_v3_v3(l_co_next, l->next->v->co); - - /* calculate normal */ - sub_v3_v3v3(l_vec_prev, l_co_prev, l_co); - sub_v3_v3v3(l_vec_next, l_co_next, l_co); - - cross_v3_v3v3(no, l_vec_prev, l_vec_next); - is_concave = dot_v3v3(no, l->f->no) > 0.0f; - } - else { - BMIter iter; - BMLoop *l2; - float up[3] = {0.0f, 0.0f, 1.0f}; - - copy_v3_v3(l_co_prev, l->prev->v->co); - copy_v3_v3(l_co, l->v->co); - - BM_ITER_ELEM (l2, &iter, l->v, BM_LOOPS_OF_VERT) { - if (l2->f != l->f) { - copy_v3_v3(l_co_next, BM_edge_other_vert(l2->e, l2->next->v)->co); - break; - } - } - - sub_v3_v3v3(l_vec_prev, l_co_prev, l_co); - sub_v3_v3v3(l_vec_next, l_co_next, l_co); - - cross_v3_v3v3(no, l_vec_prev, l_vec_next); - if (dot_v3v3(no, no) == 0.0f) { - no[0] = no[1] = 0.0f; no[2] = -1.0f; - } - - is_concave = dot_v3v3(no, up) < 0.0f; - } - - - /* now calculate the new location */ - if (do_dist) { /* treat 'fac' as distance */ - - normalize_v3(l_vec_prev); - normalize_v3(l_vec_next); - - add_v3_v3v3(co_ofs, l_vec_prev, l_vec_next); - if (UNLIKELY(normalize_v3(co_ofs) == 0.0f)) { /* edges form a straight line */ - cross_v3_v3v3(co_ofs, l_vec_prev, l->f->no); - } + const float offset = BMO_slot_float_get(op->slots_in, "offset"); + const int seg = BMO_slot_int_get(op->slots_in, "segments"); - if (do_even) { - negate_v3(l_vec_next); - mul_v3_fl(co_ofs, fac * shell_angle_to_dist(0.5f * angle_normalized_v3v3(l_vec_prev, l_vec_next))); - /* negate_v3(l_vec_next); */ /* no need unless we use again */ - } - else { - mul_v3_fl(co_ofs, fac); - } - } - else { /* treat as 'fac' as a factor (0 - 1) */ - - /* not strictly necessary, balance vectors - * so the longer edge doesn't skew the result, - * gives nicer, move even output. - * - * Use the minimum rather then the middle value so skinny faces don't flip along the short axis */ - float min_fac = min_ff(normalize_v3(l_vec_prev), normalize_v3(l_vec_next)); - float angle; - - if (do_even) { - negate_v3(l_vec_next); - angle = angle_normalized_v3v3(l_vec_prev, l_vec_next); - negate_v3(l_vec_next); /* no need unless we use again */ - } - else { - angle = 0.0f; - } - - mul_v3_fl(l_vec_prev, min_fac); - mul_v3_fl(l_vec_next, min_fac); - - add_v3_v3v3(co_ofs, l_vec_prev, l_vec_next); - - if (UNLIKELY(is_zero_v3(co_ofs))) { - cross_v3_v3v3(co_ofs, l_vec_prev, l->f->no); - normalize_v3(co_ofs); - mul_v3_fl(co_ofs, min_fac); - } - - /* done */ - if (do_even) { - mul_v3_fl(co_ofs, (fac * 0.5f) * shell_angle_to_dist(0.5f * angle)); - } - else { - mul_v3_fl(co_ofs, fac * 0.5f); - } - } - - /* apply delta vec */ - if (is_concave) - negate_v3(co_ofs); - - add_v3_v3v3(r_co, co_ofs, l->v->co); -} - - -#define ETAG_SET(e, v, nv) ( \ - (v) == (e)->v1 ? \ - (etags[BM_elem_index_get((e))].newv1 = (nv)) : \ - (etags[BM_elem_index_get((e))].newv2 = (nv)) \ - ) - -#define ETAG_GET(e, v) ( \ - (v) == (e)->v1 ? \ - (etags[BM_elem_index_get((e))].newv1) : \ - (etags[BM_elem_index_get((e))].newv2) \ - ) - -void bmo_bevel_exec(BMesh *bm, BMOperator *op) -{ - BMOIter siter; - BMIter iter; - BMEdge *e; - BMVert *v; - BMFace **faces = NULL, *f; - LoopTag *tags = NULL, *tag; - EdgeTag *etags = NULL; - BMVert **verts = NULL; - BMEdge **edges = NULL; - BLI_array_declare(faces); - BLI_array_declare(tags); - BLI_array_declare(etags); - BLI_array_declare(verts); - BLI_array_declare(edges); - SmallHash hash; - float fac = BMO_slot_float_get(op, "percent"); - const short do_even = BMO_slot_bool_get(op, "use_even"); - const short do_dist = BMO_slot_bool_get(op, "use_dist"); - int i, li, has_elens, HasMDisps = CustomData_has_layer(&bm->ldata, CD_MDISPS); - - has_elens = CustomData_has_layer(&bm->edata, CD_PROP_FLT) && BMO_slot_bool_get(op, "use_lengths"); - if (has_elens) { - li = BMO_slot_int_get(op, "lengthlayer"); - } - - BLI_smallhash_init(&hash); - - BMO_ITER (e, &siter, bm, op, "geom", BM_EDGE) { - BMO_elem_flag_enable(bm, e, BEVEL_FLAG | BEVEL_DEL); - BMO_elem_flag_enable(bm, e->v1, BEVEL_FLAG | BEVEL_DEL); - BMO_elem_flag_enable(bm, e->v2, BEVEL_FLAG | BEVEL_DEL); - - if (BM_edge_face_count(e) < 2) { - BMO_elem_flag_disable(bm, e, BEVEL_DEL); - BMO_elem_flag_disable(bm, e->v1, BEVEL_DEL); - BMO_elem_flag_disable(bm, e->v2, BEVEL_DEL); - } -#if 0 - if (BM_edge_face_count(e) == 0) { - BMVert *verts[2] = {e->v1, e->v2}; - BMEdge *edges[2] = {e, BM_edge_create(bm, e->v1, e->v2, e, 0)}; - - BMO_elem_flag_enable(bm, edges[1], BEVEL_FLAG); - BM_face_create(bm, verts, edges, 2, FALSE); - } -#endif - } - - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - BMO_elem_flag_enable(bm, v, VERT_OLD); - } - -#if 0 - /* a bit of cleaner code that, alas, doens't work. */ - /* build edge tag */ - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - if (BMO_elem_flag_test(bm, e->v1, BEVEL_FLAG) || BMO_elem_flag_test(bm, e->v2, BEVEL_FLAG)) { - BMIter liter; - BMLoop *l; - - if (!BMO_elem_flag_test(bm, e, EDGE_OLD)) { - BM_elem_index_set(e, BLI_array_count(etags)); /* set_dirty! */ - BLI_array_grow_one(etags); - - BMO_elem_flag_enable(bm, e, EDGE_OLD); - } - - BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) { - BMLoop *l2; - BMIter liter2; - - if (BMO_elem_flag_test(bm, l->f, BEVEL_FLAG)) - continue; - - BM_ITER_ELEM (l2, &liter2, l->f, BM_LOOPS_OF_FACE) { - BM_elem_index_set(l2, BLI_array_count(tags)); /* set_loop */ - BLI_array_grow_one(tags); - - if (!BMO_elem_flag_test(bm, l2->e, EDGE_OLD)) { - BM_elem_index_set(l2->e, BLI_array_count(etags)); /* set_dirty! */ - BLI_array_grow_one(etags); - - BMO_elem_flag_enable(bm, l2->e, EDGE_OLD); - } - } - - BMO_elem_flag_enable(bm, l->f, BEVEL_FLAG); - BLI_array_append(faces, l->f); - } - } - else { - BM_elem_index_set(e, -1); /* set_dirty! */ - } - } -#endif - - /* create and assign looptag structure */ - BMO_ITER (e, &siter, bm, op, "geom", BM_EDGE) { - BMLoop *l; - BMIter liter; - - BMO_elem_flag_enable(bm, e->v1, BEVEL_FLAG | BEVEL_DEL); - BMO_elem_flag_enable(bm, e->v2, BEVEL_FLAG | BEVEL_DEL); - - if (BM_edge_face_count(e) < 2) { - BMO_elem_flag_disable(bm, e, BEVEL_DEL); - BMO_elem_flag_disable(bm, e->v1, BEVEL_DEL); - BMO_elem_flag_disable(bm, e->v2, BEVEL_DEL); - } - - if (!BLI_smallhash_haskey(&hash, (intptr_t)e)) { - BLI_array_grow_one(etags); - BM_elem_index_set(e, BLI_array_count(etags) - 1); /* set_dirty! */ - BLI_smallhash_insert(&hash, (intptr_t)e, NULL); - BMO_elem_flag_enable(bm, e, EDGE_OLD); - } - - /* find all faces surrounding e->v1 and, e->v2 */ - for (i = 0; i < 2; i++) { - BM_ITER_ELEM (l, &liter, i ? e->v2 : e->v1, BM_LOOPS_OF_VERT) { - BMLoop *l2; - BMIter liter2; - - /* see if we've already processed this loop's fac */ - if (BLI_smallhash_haskey(&hash, (intptr_t)l->f)) - continue; - - /* create tags for all loops in l-> */ - BM_ITER_ELEM (l2, &liter2, l->f, BM_LOOPS_OF_FACE) { - BLI_array_grow_one(tags); - BM_elem_index_set(l2, BLI_array_count(tags) - 1); /* set_loop */ - - if (!BLI_smallhash_haskey(&hash, (intptr_t)l2->e)) { - BLI_array_grow_one(etags); - BM_elem_index_set(l2->e, BLI_array_count(etags) - 1); /* set_dirty! */ - BLI_smallhash_insert(&hash, (intptr_t)l2->e, NULL); - BMO_elem_flag_enable(bm, l2->e, EDGE_OLD); - } - } - - BLI_smallhash_insert(&hash, (intptr_t)l->f, NULL); - BMO_elem_flag_enable(bm, l->f, BEVEL_FLAG); - BLI_array_append(faces, l->f); - } - } - } - - bm->elem_index_dirty |= BM_EDGE; - - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - BMIter eiter; - - if (!BMO_elem_flag_test(bm, v, BEVEL_FLAG)) - continue; - - BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { - if (!BMO_elem_flag_test(bm, e, BEVEL_FLAG) && !ETAG_GET(e, v)) { - BMVert *v2; - float co[3]; - - v2 = BM_edge_other_vert(e, v); - sub_v3_v3v3(co, v2->co, v->co); - if (has_elens) { - float elen = *(float *)CustomData_bmesh_get_n(&bm->edata, e->head.data, CD_PROP_FLT, li); - - normalize_v3(co); - mul_v3_fl(co, elen); - } - - mul_v3_fl(co, fac); - add_v3_v3(co, v->co); - - v2 = BM_vert_create(bm, co, v); - ETAG_SET(e, v, v2); - } - } - } - - for (i = 0; i < BLI_array_count(faces); i++) { - BMLoop *l; - BMIter liter; - - BMO_elem_flag_enable(bm, faces[i], FACE_OLD); - - BM_ITER_ELEM (l, &liter, faces[i], BM_LOOPS_OF_FACE) { - float co[3]; - - if (BMO_elem_flag_test(bm, l->e, BEVEL_FLAG)) { - if (BMO_elem_flag_test(bm, l->prev->e, BEVEL_FLAG)) { - tag = tags + BM_elem_index_get(l); - calc_corner_co(l, fac, co, do_dist, do_even); - tag->newv = BM_vert_create(bm, co, l->v); - } - else { - tag = tags + BM_elem_index_get(l); - tag->newv = ETAG_GET(l->prev->e, l->v); - - if (!tag->newv) { - sub_v3_v3v3(co, l->prev->v->co, l->v->co); - if (has_elens) { - float elen = *(float *)CustomData_bmesh_get_n(&bm->edata, l->prev->e->head.data, - CD_PROP_FLT, li); - - normalize_v3(co); - mul_v3_fl(co, elen); - } - - mul_v3_fl(co, fac); - add_v3_v3(co, l->v->co); - - tag->newv = BM_vert_create(bm, co, l->v); - - ETAG_SET(l->prev->e, l->v, tag->newv); - } - } - } - else if (BMO_elem_flag_test(bm, l->v, BEVEL_FLAG)) { - tag = tags + BM_elem_index_get(l); - tag->newv = ETAG_GET(l->e, l->v); - - if (!tag->newv) { - sub_v3_v3v3(co, l->next->v->co, l->v->co); - if (has_elens) { - float elen = *(float *)CustomData_bmesh_get_n(&bm->edata, l->e->head.data, CD_PROP_FLT, li); - - normalize_v3(co); - mul_v3_fl(co, elen); - } - - mul_v3_fl(co, fac); - add_v3_v3(co, l->v->co); - - tag = tags + BM_elem_index_get(l); - tag->newv = BM_vert_create(bm, co, l->v); - - ETAG_SET(l->e, l->v, tag->newv); - } - } - else { - tag = tags + BM_elem_index_get(l); - tag->newv = l->v; - BMO_elem_flag_disable(bm, l->v, BEVEL_DEL); - } - } - } - - /* create new faces inset from original face */ - for (i = 0; i < BLI_array_count(faces); i++) { - BMLoop *l; - BMIter liter; - BMFace *f; - BMVert *lastv = NULL, *firstv = NULL; - - BMO_elem_flag_enable(bm, faces[i], BEVEL_DEL); - - BLI_array_empty(verts); - BLI_array_empty(edges); - - BM_ITER_ELEM (l, &liter, faces[i], BM_LOOPS_OF_FACE) { - BMVert *v2; - - tag = tags + BM_elem_index_get(l); - BLI_array_append(verts, tag->newv); - - if (!firstv) - firstv = tag->newv; - - if (lastv) { - e = BM_edge_create(bm, lastv, tag->newv, l->e, TRUE); - BM_elem_attrs_copy(bm, bm, l->prev->e, e); - BLI_array_append(edges, e); - } - lastv = tag->newv; - - v2 = ETAG_GET(l->e, l->next->v); - - tag = &tags[BM_elem_index_get(l->next)]; - if (!BMO_elem_flag_test(bm, l->e, BEVEL_FLAG) && v2 && v2 != tag->newv) { - BLI_array_append(verts, v2); - - e = BM_edge_create(bm, lastv, v2, l->e, TRUE); - BM_elem_attrs_copy(bm, bm, l->e, e); - - BLI_array_append(edges, e); - lastv = v2; - } - } - - e = BM_edge_create(bm, firstv, lastv, BM_FACE_FIRST_LOOP(faces[i])->e, TRUE); - if (BM_FACE_FIRST_LOOP(faces[i])->prev->e != e) { - BM_elem_attrs_copy(bm, bm, BM_FACE_FIRST_LOOP(faces[i])->prev->e, e); - } - BLI_array_append(edges, e); - - f = BM_face_create_ngon(bm, verts[0], verts[1], edges, BLI_array_count(edges), FALSE); - if (UNLIKELY(f == NULL)) { - printf("%s: could not make face!\n", __func__); - continue; - } - - BMO_elem_flag_enable(bm, f, FACE_NEW); - } - - for (i = 0; i < BLI_array_count(faces); i++) { - BMLoop *l; - BMIter liter; - int j; - - /* create quad spans between split edge */ - BM_ITER_ELEM (l, &liter, faces[i], BM_LOOPS_OF_FACE) { - BMVert *v1 = NULL, *v2 = NULL, *v3 = NULL, *v4 = NULL; - - if (!BMO_elem_flag_test(bm, l->e, BEVEL_FLAG)) - continue; - - v1 = tags[BM_elem_index_get(l)].newv; - v2 = tags[BM_elem_index_get(l->next)].newv; - if (l->radial_next != l) { - v3 = tags[BM_elem_index_get(l->radial_next)].newv; - if (l->radial_next->next->v == l->next->v) { - v4 = v3; - v3 = tags[BM_elem_index_get(l->radial_next->next)].newv; - } - else { - v4 = tags[BM_elem_index_get(l->radial_next->next)].newv; - } - } - else { - /* the loop is on a boundar */ - v3 = l->next->v; - v4 = l->v; - - for (j = 0; j < 2; j++) { - BMIter eiter; - BMVert *v = j ? v4 : v3; - - BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { - if (!BM_vert_in_edge(e, v3) || !BM_vert_in_edge(e, v4)) - continue; - - if (!BMO_elem_flag_test(bm, e, BEVEL_FLAG) && BMO_elem_flag_test(bm, e, EDGE_OLD)) { - BMVert *vv; - - vv = ETAG_GET(e, v); - if (!vv || BMO_elem_flag_test(bm, vv, BEVEL_FLAG)) - continue; - - if (j) { - v1 = vv; - } - else { - v2 = vv; - } - break; - } - } - } - - BMO_elem_flag_disable(bm, v3, BEVEL_DEL); - BMO_elem_flag_disable(bm, v4, BEVEL_DEL); - } - - if (v1 != v2 && v2 != v3 && v3 != v4) { - BMIter liter2; - BMLoop *l2, *l3; - BMEdge *e1, *e2; - float d1, d2, *d3; - - f = BM_face_create_quad_tri(bm, v4, v3, v2, v1, l->f, TRUE); - - e1 = BM_edge_exists(v4, v3); - e2 = BM_edge_exists(v2, v1); - BM_elem_attrs_copy(bm, bm, l->e, e1); - BM_elem_attrs_copy(bm, bm, l->e, e2); - - /* set edge lengths of cross edges as the average of the cross edges they're based o */ - if (has_elens) { - /* angle happens not to be used. why? - not sure it just isn't - campbell. - * leave this in in case we need to use it later */ -#if 0 - float ang; -#endif - e1 = BM_edge_exists(v1, v4); - e2 = BM_edge_exists(v2, v3); - - if (l->radial_next->v == l->v) { - l2 = l->radial_next->prev; - l3 = l->radial_next->next; - } - else { - l2 = l->radial_next->next; - l3 = l->radial_next->prev; - } - - d3 = CustomData_bmesh_get_n(&bm->edata, e1->head.data, CD_PROP_FLT, li); - d1 = *(float *)CustomData_bmesh_get_n(&bm->edata, l->prev->e->head.data, CD_PROP_FLT, li); - d2 = *(float *)CustomData_bmesh_get_n(&bm->edata, l2->e->head.data, CD_PROP_FLT, li); -#if 0 - ang = angle_v3v3v3(l->prev->v->co, l->v->co, BM_edge_other_vert(l2->e, l->v)->co); -#endif - *d3 = (d1 + d2) * 0.5f; - - d3 = CustomData_bmesh_get_n(&bm->edata, e2->head.data, CD_PROP_FLT, li); - d1 = *(float *)CustomData_bmesh_get_n(&bm->edata, l->next->e->head.data, CD_PROP_FLT, li); - d2 = *(float *)CustomData_bmesh_get_n(&bm->edata, l3->e->head.data, CD_PROP_FLT, li); -#if 0 - ang = angle_v3v3v3(BM_edge_other_vert(l->next->e, l->next->v)->co, l->next->v->co, - BM_edge_other_vert(l3->e, l->next->v)->co); -#endif - *d3 = (d1 + d2) * 0.5f; - } - - if (UNLIKELY(f == NULL)) { - fprintf(stderr, "%s: face index out of range! (bmesh internal error)\n", __func__); - continue; - } - - BMO_elem_flag_enable(bm, f, FACE_NEW | FACE_SPAN); - - /* un-tag edges in f for deletio */ - BM_ITER_ELEM (l2, &liter2, f, BM_LOOPS_OF_FACE) { - BMO_elem_flag_disable(bm, l2->e, BEVEL_DEL); - } - } - else { - f = NULL; - } - } - } - - /* fill in holes at vertices */ - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - BMIter eiter; - BMVert *vv, *vstart = NULL, *lastv = NULL; - SmallHash tmphash; - int rad, insorig = 0, err = 0; + if (offset > 0) { + BMOIter siter; + BMEdge *e; + BMVert *v; - BLI_smallhash_init(&tmphash); + /* 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); - if (!BMO_elem_flag_test(bm, v, BEVEL_FLAG)) - continue; - - BLI_array_empty(verts); - BLI_array_empty(edges); - - BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { - BMIter liter; - BMVert *v1 = NULL, *v2 = NULL; - BMLoop *l; - - if (BM_edge_face_count(e) < 2) - insorig = 1; - - if (BM_elem_index_get(e) == -1) - continue; - - rad = 0; - BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) { - if (!BMO_elem_flag_test(bm, l->f, FACE_OLD)) - continue; - - rad++; - - tag = tags + BM_elem_index_get((l->v == v) ? l : l->next); - - if (!v1) - v1 = tag->newv; - else if (!v2) - v2 = tag->newv; - } - - if (rad < 2) - insorig = 1; - - if (!v1) - v1 = ETAG_GET(e, v); - if (!v2 || v1 == v2) - v2 = ETAG_GET(e, v); - - if (v1) { - if (!BLI_smallhash_haskey(&tmphash, (intptr_t)v1)) { - BLI_array_append(verts, v1); - BLI_smallhash_insert(&tmphash, (intptr_t)v1, NULL); - } - - if (v2 && v1 != v2 && !BLI_smallhash_haskey(&tmphash, (intptr_t)v2)) { - BLI_array_append(verts, v2); - BLI_smallhash_insert(&tmphash, (intptr_t)v2, NULL); - } - } - } - - if (!BLI_array_count(verts)) - continue; - - if (insorig) { - BLI_array_append(verts, v); - BLI_smallhash_insert(&tmphash, (intptr_t)v, NULL); + BMO_ITER (v, &siter, op->slots_in, "geom", BM_VERT) { + BM_elem_flag_enable(v, BM_ELEM_TAG); } - - /* find edges that exist between vertices in verts. this is basically - * a topological walk of the edges connecting them */ - vstart = vstart ? vstart : verts[0]; - vv = vstart; - do { - BM_ITER_ELEM (e, &eiter, vv, BM_EDGES_OF_VERT) { - BMVert *vv2 = BM_edge_other_vert(e, vv); - - if (vv2 != lastv && BLI_smallhash_haskey(&tmphash, (intptr_t)vv2)) { - /* if we've go over the same vert twice, break out of outer loop */ - if (BLI_smallhash_lookup(&tmphash, (intptr_t)vv2) != NULL) { - e = NULL; - err = 1; - break; - } - - /* use self pointer as ta */ - BLI_smallhash_remove(&tmphash, (intptr_t)vv2); - BLI_smallhash_insert(&tmphash, (intptr_t)vv2, vv2); - - lastv = vv; - BLI_array_append(edges, e); - vv = vv2; - break; - } - } - if (e == NULL) { - break; - } - } while (vv != vstart); - - if (err) { - continue; - } - - /* there may not be a complete loop of edges, so start again and make - * final edge afterwards. in this case, the previous loop worked to - * find one of the two edges at the extremes. */ - if (vv != vstart) { - /* undo previous taggin */ - for (i = 0; i < BLI_array_count(verts); i++) { - BLI_smallhash_remove(&tmphash, (intptr_t)verts[i]); - BLI_smallhash_insert(&tmphash, (intptr_t)verts[i], NULL); - } - - vstart = vv; - lastv = NULL; - BLI_array_empty(edges); - do { - BM_ITER_ELEM (e, &eiter, vv, BM_EDGES_OF_VERT) { - BMVert *vv2 = BM_edge_other_vert(e, vv); - - if (vv2 != lastv && BLI_smallhash_haskey(&tmphash, (intptr_t)vv2)) { - /* if we've go over the same vert twice, break out of outer loo */ - if (BLI_smallhash_lookup(&tmphash, (intptr_t)vv2) != NULL) { - e = NULL; - err = 1; - break; - } - - /* use self pointer as ta */ - BLI_smallhash_remove(&tmphash, (intptr_t)vv2); - BLI_smallhash_insert(&tmphash, (intptr_t)vv2, vv2); - - lastv = vv; - BLI_array_append(edges, e); - vv = vv2; - break; - } - } - if (e == NULL) - break; - } while (vv != vstart); - - if (!err) { - e = BM_edge_create(bm, vv, vstart, NULL, TRUE); - BLI_array_append(edges, e); - } - } - - if (err) - continue; - - if (BLI_array_count(edges) >= 3) { - BMFace *f; - - if (BM_face_exists(bm, verts, BLI_array_count(verts), &f)) - continue; - - f = BM_face_create_ngon(bm, lastv, vstart, edges, BLI_array_count(edges), FALSE); - if (UNLIKELY(f == NULL)) { - fprintf(stderr, "%s: in bevel vert fill! (bmesh internal error)\n", __func__); - } - else { - BMO_elem_flag_enable(bm, f, FACE_NEW | FACE_HOLE); + BMO_ITER (e, &siter, op->slots_in, "geom", BM_EDGE) { + if (BM_edge_is_manifold(e)) { + BM_elem_flag_enable(e, BM_ELEM_TAG); } } - BLI_smallhash_release(&tmphash); - } - - /* copy over customdat */ - for (i = 0; i < BLI_array_count(faces); i++) { - BMLoop *l; - BMIter liter; - BMFace *f = faces[i]; - - BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - BMLoop *l2; - BMIter liter2; - - tag = tags + BM_elem_index_get(l); - if (!tag->newv) - continue; - - BM_ITER_ELEM (l2, &liter2, tag->newv, BM_LOOPS_OF_VERT) { - if (!BMO_elem_flag_test(bm, l2->f, FACE_NEW) || (l2->v != tag->newv && l2->v != l->v)) - continue; - - if (tag->newv != l->v || HasMDisps) { - BM_elem_attrs_copy(bm, bm, l->f, l2->f); - BM_loop_interp_from_face(bm, l2, l->f, TRUE, TRUE); - } - else { - BM_elem_attrs_copy(bm, bm, l->f, l2->f); - BM_elem_attrs_copy(bm, bm, l, l2); - } - - if (HasMDisps) { - BMLoop *l3; - BMIter liter3; - - BM_ITER_ELEM (l3, &liter3, l2->f, BM_LOOPS_OF_FACE) { - BM_loop_interp_multires(bm, l3, l->f); - } - } - } - } - } - - /* handle vertices along boundary edge */ - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - if (BMO_elem_flag_test(bm, v, VERT_OLD) && - BMO_elem_flag_test(bm, v, BEVEL_FLAG) && - !BMO_elem_flag_test(bm, v, BEVEL_DEL)) - { - BMLoop *l; - BMLoop *lorig = NULL; - BMIter liter; - - BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { - // BMIter liter2; - // BMLoop *l2 = l->v == v ? l : l->next, *l3; - - if (BMO_elem_flag_test(bm, l->f, FACE_OLD)) { - lorig = l; - break; - } - } - - if (!lorig) - continue; - - BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { - BMLoop *l2 = l->v == v ? l : l->next; - - BM_elem_attrs_copy(bm, bm, lorig->f, l2->f); - BM_elem_attrs_copy(bm, bm, lorig, l2); - } - } - } -#if 0 - /* clean up any remaining 2-edged face */ - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - if (f->len == 2) { - BMFace *faces[2] = {f, BM_FACE_FIRST_LOOP(f)->radial_next->f}; - - if (faces[0] == faces[1]) - BM_face_kill(bm, f); - else - BM_faces_join(bm, faces, 2); - } - } -#endif - BMO_op_callf(bm, op->flag, "delete geom=%fv context=%i", BEVEL_DEL, DEL_VERTS); + BM_mesh_bevel(bm, offset, seg); - /* clean up any edges that might not get properly delete */ - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - if (BMO_elem_flag_test(bm, e, EDGE_OLD) && !e->l) - BMO_elem_flag_enable(bm, e, BEVEL_DEL); + BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG); } - - BMO_op_callf(bm, op->flag, "delete geom=%fe context=%i", BEVEL_DEL, DEL_EDGES); - BMO_op_callf(bm, op->flag, "delete geom=%ff context=%i", BEVEL_DEL, DEL_FACES); - - BLI_smallhash_release(&hash); - BLI_array_free(tags); - BLI_array_free(etags); - BLI_array_free(verts); - BLI_array_free(edges); - BLI_array_free(faces); - - BMO_slot_buffer_from_enabled_flag(bm, op, "face_spans", BM_FACE, FACE_SPAN); - BMO_slot_buffer_from_enabled_flag(bm, op, "face_holes", BM_FACE, FACE_HOLE); } -#endif /* NEW_BEVEL */ diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c index ebd848ff8b2..b7bb57bb19d 100644 --- a/source/blender/bmesh/operators/bmo_connect.c +++ b/source/blender/bmesh/operators/bmo_connect.c @@ -52,7 +52,7 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op) BLI_array_declare(verts_pair); int i; - BMO_slot_buffer_flag_enable(bm, op, "verts", BM_VERT, VERT_INPUT); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts", BM_VERT, VERT_INPUT); for (f = BM_iter_new(&iter, bm, BM_FACES_OF_MESH, NULL); f; f = BM_iter_step(&iter)) { BLI_array_empty(loops_split); @@ -117,7 +117,7 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, EDGE_OUT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT); BLI_array_free(loops_split); BLI_array_free(verts_pair); @@ -219,12 +219,12 @@ 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, "use_merge"); - const float merge_factor = BMO_slot_float_get(op, "merge_factor"); + const int 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, "edges", BM_EDGE, EDGE_MARK); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK); - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { if (!BMO_elem_flag_test(bm, e, EDGE_DONE)) { BMVert *v, *ov; /* BMEdge *e2, *e3, *oe = e; */ /* UNUSED */ @@ -523,7 +523,7 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, FACE_OUT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_OUT); cleanup: BLI_array_free(ee1); diff --git a/source/blender/bmesh/operators/bmo_create.c b/source/blender/bmesh/operators/bmo_create.c index 093f567d995..987aa8cdf99 100644 --- a/source/blender/bmesh/operators/bmo_create.c +++ b/source/blender/bmesh/operators/bmo_create.c @@ -168,7 +168,7 @@ static void rotsys_reverse(BMEdge *UNUSED(e), BMVert *v, EdgeData *edata, VertDa BMEdge **edges = NULL; BMEdge *e_first; BMEdge *e; - BLI_array_staticdeclare(edges, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE); int i, totedge; e = e_first = vdata[BM_elem_index_get(v)].e; @@ -359,10 +359,10 @@ static void init_rotsys(BMesh *bm, EdgeData *edata, VertData *vdata) BMIter iter; BMEdge *e; BMEdge **edges = NULL; - BLI_array_staticdeclare(edges, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE); BMVert *v; /* BMVert **verts = NULL; */ - /* BLI_array_staticdeclare(verts, BM_NGON_STACK_SIZE); */ /* UNUSE */ + /* BLI_array_staticdeclare(verts, BM_DEFAULT_NGON_STACK_SIZE); */ /* UNUSE */ int i; BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { @@ -741,7 +741,10 @@ static EPath *edge_find_shortest_path(BMesh *bm, BMOperator *op, BMEdge *edge, E BMVert *startv; BMVert *endv; EPathNode *node; - int i, use_restrict = BMO_slot_bool_get(op, "use_restrict"); + int i; + const int use_restrict = BMO_slot_bool_get(op->slots_in, "use_restrict"); + BMOpSlot *slot_restrict = BMO_slot_get(op->slots_in, "restrict"); + startv = edata[BM_elem_index_get(edge)].ftag ? edge->v2 : edge->v1; endv = edata[BM_elem_index_get(edge)].ftag ? edge->v1 : edge->v2; @@ -769,7 +772,7 @@ static EPath *edge_find_shortest_path(BMesh *bm, BMOperator *op, BMEdge *edge, E verts[i] = node->v; } - if (BM_face_exists(bm, verts, i, &f)) { + if (BM_face_exists(verts, i, &f)) { if (!BMO_elem_flag_test(bm, f, FACE_IGNORE)) { BLI_ghash_remove(gh, endv, NULL, NULL); continue; @@ -806,12 +809,13 @@ static EPath *edge_find_shortest_path(BMesh *bm, BMOperator *op, BMEdge *edge, E continue; } - if (use_restrict && BMO_slot_map_contains(bm, op, "restrict", e)) { - int group = BMO_slot_map_int_get(bm, op, "restrict", e); - - if (!(group & path->group)) { - v2 = NULL; - continue; + if (use_restrict) { + int *group = (int *)BMO_slot_map_data_get(slot_restrict, e); + if (group) { + if (!(*group & path->group)) { + v2 = NULL; + continue; + } } } @@ -895,12 +899,14 @@ 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, "use_restrict"); - int use_fill_check = BMO_slot_bool_get(op, "use_fill_check"); - const short mat_nr = BMO_slot_int_get(op, "mat_nr"); - const short use_smooth = BMO_slot_bool_get(op, "use_smooth"); + 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"); 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"); + BMOpSlot *slot_face_groupmap_out = BMO_slot_get(op->slots_out, "face_groupmap.out"); if (!bm->totvert || !bm->totedge) return; @@ -910,8 +916,8 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) edata = MEM_callocN(sizeof(EdgeData) * bm->totedge, "EdgeData"); vdata = MEM_callocN(sizeof(VertData) * bm->totvert, "VertData"); - BMO_slot_buffer_flag_enable(bm, op, "edges", BM_EDGE, EDGE_MARK); - BMO_slot_buffer_flag_enable(bm, op, "excludefaces", BM_FACE, FACE_IGNORE); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "exclude_faces", BM_FACE, FACE_IGNORE); BM_mesh_elem_index_ensure(bm, BM_VERT); @@ -932,14 +938,14 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) bm->elem_index_dirty &= ~BM_EDGE; init_rotsys(bm, edata, vdata); - + while (1) { edge = NULL; group = 0; - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { /* if restrict is on, only start on faces in the restrict map */ - if (use_restrict && !BMO_slot_map_contains(bm, op, "restrict", e)) + if (use_restrict && !BMO_slot_map_contains(slot_restrict, e)) continue; if (edata[BM_elem_index_get(e)].tag < 2) { @@ -948,7 +954,7 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) if (use_restrict) { int i = 0, j = 0, gi = 0; - group = BMO_slot_map_int_get(bm, op, "restrict", e); + group = BMO_slot_map_int_get(slot_restrict, e); for (i = 0; i < 30; i++) { if (group & (1 << i)) { @@ -1055,7 +1061,7 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) } if (use_restrict) { - BMO_slot_map_int_insert(bm, op, "faceout_groupmap", f, path->group); + BMO_slot_map_int_insert(op, slot_face_groupmap_out, f, path->group); } } } @@ -1063,7 +1069,7 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) edge_free_path(pathbase, path); } - BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, FACE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_NEW); BLI_array_free(edges); BLI_array_free(verts); @@ -1103,11 +1109,11 @@ void bmo_edgenet_prepare(BMesh *bm, BMOperator *op) int ok = 1; int i, count; - BMO_slot_buffer_flag_enable(bm, op, "edges", BM_EDGE, EDGE_MARK); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK); /* validate that each edge has at most one other tagged edge in the * disk cycle around each of it's vertices */ - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { for (i = 0; i < 2; i++) { count = BMO_vert_edge_flags_count(bm, i ? e->v2 : e->v1, EDGE_MARK); if (count > 2) { @@ -1129,7 +1135,7 @@ void bmo_edgenet_prepare(BMesh *bm, BMOperator *op) /* find connected loops within the input edge */ count = 0; while (1) { - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { if (!BMO_elem_flag_test(bm, e, EDGE_VIS)) { if (BMO_vert_edge_flags_count(bm, e->v1, EDGE_MARK) == 1 || BMO_vert_edge_flags_count(bm, e->v2, EDGE_MARK) == 1) @@ -1260,7 +1266,7 @@ void bmo_edgenet_prepare(BMesh *bm, BMOperator *op) } } - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, ELE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_NEW); BLI_array_free(edges1); BLI_array_free(edges2); @@ -1280,11 +1286,11 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) BMEdge *e; BMFace *f; int totv = 0, tote = 0, totf = 0, amount; - const short mat_nr = BMO_slot_int_get(op, "mat_nr"); - const short use_smooth = BMO_slot_bool_get(op, "use_smooth"); + 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"); /* count number of each element type we were passe */ - BMO_ITER (h, &oiter, bm, op, "geom", BM_VERT | BM_EDGE | BM_FACE) { + BMO_ITER (h, &oiter, op->slots_in, "geom", BM_VERT | BM_EDGE | BM_FACE) { switch (h->htype) { case BM_VERT: totv++; break; case BM_EDGE: tote++; break; @@ -1318,7 +1324,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) int ok = TRUE; - BMO_ITER (v, &oiter, bm, op, "geom", BM_VERT) { + BMO_ITER (v, &oiter, op->slots_in, "geom", BM_VERT) { /* count how many flagged edges this vertex uses */ int tot_edges = 0; BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { @@ -1366,7 +1372,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) /* call edgenet prepare op so additional face creation cases wore */ BMO_op_initf(bm, &op2, op->flag, "edgenet_prepare edges=%fe", ELE_NEW); BMO_op_exec(bm, &op2); - BMO_slot_buffer_flag_enable(bm, &op2, "edgeout", BM_EDGE, ELE_NEW); + BMO_slot_buffer_flag_enable(bm, op2.slots_out, "edges.out", BM_EDGE, ELE_NEW); BMO_op_finish(bm, &op2); BMO_op_initf(bm, &op2, op->flag, @@ -1376,8 +1382,9 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) BMO_op_exec(bm, &op2); /* return if edge net create did something */ - if (BMO_slot_buffer_count(bm, &op2, "faceout")) { - BMO_slot_copy(&op2, op, "faceout", "faceout"); + if (BMO_slot_buffer_count(op2.slots_out, "faces.out")) { + BMO_slot_copy(&op2, slots_out, "faces.out", + op, slots_out, "faces.out"); BMO_op_finish(bm, &op2); return; } @@ -1389,8 +1396,9 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) BMO_op_exec(bm, &op2); /* if we dissolved anything, then return */ - if (BMO_slot_buffer_count(bm, &op2, "regionout")) { - BMO_slot_copy(&op2, op, "regionout", "faceout"); + if (BMO_slot_buffer_count(op2.slots_out, "region.out")) { + BMO_slot_copy(&op2, slots_out, "region.out", + op, slots_out, "faces.out"); BMO_op_finish(bm, &op2); return; } @@ -1414,7 +1422,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) /* create edge */ e = BM_edge_create(bm, verts[0], verts[1], NULL, TRUE); BMO_elem_flag_enable(bm, e, ELE_OUT); - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, ELE_OUT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_OUT); } else if (0) { /* nice feature but perhaps it should be a different tool? */ @@ -1460,7 +1468,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) } } } - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, ELE_OUT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, ELE_OUT); /* done creating edges */ } else if (amount > 2) { @@ -1470,7 +1478,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) BMVert **vert_arr = MEM_mallocN(sizeof(BMVert **) * totv, __func__); int i = 0; - BMO_ITER (v, &oiter, bm, op, "geom", BM_VERT) { + BMO_ITER (v, &oiter, op->slots_in, "geom", BM_VERT) { vert_arr[i] = v; i++; } diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c index 9addb1b1657..7c3bcd60daa 100644 --- a/source/blender/bmesh/operators/bmo_dissolve.c +++ b/source/blender/bmesh/operators/bmo_dissolve.c @@ -85,7 +85,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) BMWalker regwalker; int i; - int use_verts = BMO_slot_bool_get(op, "use_verts"); + int use_verts = BMO_slot_bool_get(op->slots_in, "use_verts"); if (use_verts) { /* tag verts that start out with only 2 edges, @@ -98,10 +98,10 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_buffer_flag_enable(bm, op, "faces", BM_FACE, FACE_MARK); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "faces", BM_FACE, FACE_MARK); /* collect region */ - BMO_ITER (f, &oiter, bm, op, "faces", BM_FACE) { + BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) { if (!BMO_elem_flag_test(bm, f, FACE_MARK)) { continue; @@ -184,7 +184,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) goto cleanup; } - BMO_slot_buffer_from_enabled_flag(bm, op, "regionout", BM_FACE, FACE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "region.out", BM_FACE, FACE_NEW); cleanup: /* free/cleanup */ @@ -208,7 +208,7 @@ void bmo_dissolve_edgeloop_exec(BMesh *bm, BMOperator *op) int i; - BMO_ITER (e, &oiter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &oiter, op->slots_in, "edges", BM_EDGE) { if (BM_edge_face_pair(e, &fa, &fb)) { BMO_elem_flag_enable(bm, e->v1, VERT_MARK); BMO_elem_flag_enable(bm, e->v2, VERT_MARK); @@ -237,7 +237,7 @@ void bmo_dissolve_edgeloop_exec(BMesh *bm, BMOperator *op) //BMO_op_initf(bm, &fop, "dissolve_faces faces=%ff", FACE_MARK); //BMO_op_exec(bm, &fop); - //BMO_slot_copy(op, &fop, "regionout", "regionout"); + //BMO_slot_copy(op, &fop, "region.out", "region.out"); //BMO_op_finish(bm, &fop); } @@ -254,7 +254,7 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op) BMIter viter; BMVert *v; - int use_verts = BMO_slot_bool_get(op, "use_verts"); + int use_verts = BMO_slot_bool_get(op->slots_in, "use_verts"); if (use_verts) { BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { @@ -262,7 +262,7 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op) } } - BMO_ITER (e, &eiter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &eiter, op->slots_in, "edges", BM_EDGE) { BMFace *fa, *fb; if (BM_edge_face_pair(e, &fa, &fb)) { @@ -338,7 +338,7 @@ void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op) BMFace *f; /* int i; */ - BMO_slot_buffer_flag_enable(bm, op, "verts", BM_VERT, VERT_MARK); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts", BM_VERT, VERT_MARK); for (v = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL); v; v = BM_iter_step(&iter)) { if (BMO_elem_flag_test(bm, v, VERT_MARK)) { @@ -479,13 +479,13 @@ void dummy_exec(BMesh *bm, BMOperator *op) /* Limited Dissolve */ void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op) { - BMOpSlot *einput = BMO_slot_get(op, "edges"); - BMOpSlot *vinput = BMO_slot_get(op, "verts"); + BMOpSlot *einput = BMO_slot_get(op->slots_in, "edges"); + 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, "angle_limit")); - const int do_dissolve_boundaries = BMO_slot_bool_get(op, "use_dissolve_boundaries"); + 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"); BM_mesh_decimate_dissolve_ex(bm, angle_limit, do_dissolve_boundaries, - vinput->data.p, vinput->len, - einput->data.p, einput->len); + (BMVert **)BMO_SLOT_AS_BUFFER(vinput), vinput->len, + (BMEdge **)BMO_SLOT_AS_BUFFER(einput), einput->len); } diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c index 32270007a0b..c4f6c821320 100644 --- a/source/blender/bmesh/operators/bmo_dupe.c +++ b/source/blender/bmesh/operators/bmo_dupe.c @@ -68,7 +68,9 @@ static BMVert *copy_vertex(BMesh *source_mesh, BMVert *source_vertex, BMesh *tar * * Copy an existing edge from one bmesh to another. */ -static BMEdge *copy_edge(BMOperator *op, BMesh *source_mesh, +static BMEdge *copy_edge(BMOperator *op, + BMOpSlot *slot_boundarymap_out, + BMesh *source_mesh, BMEdge *source_edge, BMesh *target_mesh, GHash *vhash, GHash *ehash) { @@ -102,7 +104,7 @@ static BMEdge *copy_edge(BMOperator *op, BMesh *source_mesh, if (rlen < 2) { /* not sure what non-manifold cases of greater then three * radial should do. */ - BMO_slot_map_ptr_insert(source_mesh, op, "boundarymap", + BMO_slot_map_ptr_insert(op, slot_boundarymap_out, source_edge, target_edge); } @@ -124,7 +126,9 @@ static BMEdge *copy_edge(BMOperator *op, BMesh *source_mesh, * Copy an existing face from one bmesh to another. */ -static BMFace *copy_face(BMOperator *op, BMesh *source_mesh, +static BMFace *copy_face(BMOperator *op, + BMOpSlot *slot_facemap_out, + BMesh *source_mesh, BMFace *source_face, BMesh *target_mesh, BMVert **vtar, BMEdge **edar, GHash *vhash, GHash *ehash) { @@ -151,11 +155,11 @@ static BMFace *copy_face(BMOperator *op, BMesh *source_mesh, vtar[i] = BLI_ghash_lookup(vhash, source_loop->v); edar[i] = BLI_ghash_lookup(ehash, source_loop->e); } - + /* create new face */ target_face = BM_face_create(target_mesh, vtar, edar, source_face->len, FALSE); - BMO_slot_map_ptr_insert(source_mesh, op, "facemap", source_face, target_face); - BMO_slot_map_ptr_insert(source_mesh, op, "facemap", target_face, source_face); + BMO_slot_map_ptr_insert(op, slot_facemap_out, source_face, target_face); + BMO_slot_map_ptr_insert(op, slot_facemap_out, target_face, source_face); BM_elem_attrs_copy(source_mesh, target_mesh, source_face, target_face); @@ -181,7 +185,7 @@ static BMFace *copy_face(BMOperator *op, BMesh *source_mesh, * Internal Copy function. */ -static void BKE_mesh_copy(BMOperator *op, BMesh *source, BMesh *target) +static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst) { BMVert *v = NULL, *v2; @@ -196,22 +200,26 @@ static void BKE_mesh_copy(BMOperator *op, BMesh *source, BMesh *target) BMIter viter, eiter, fiter; GHash *vhash, *ehash; + BMOpSlot *slot_boundarymap_out = BMO_slot_get(op->slots_out, "boundarymap.out"); + BMOpSlot *slot_facemap_out = BMO_slot_get(op->slots_out, "facemap.out"); + BMOpSlot *slot_isovertmap_out = BMO_slot_get(op->slots_out, "isovertmap.out"); + /* initialize pointer hashes */ vhash = BLI_ghash_ptr_new("bmesh dupeops v"); ehash = BLI_ghash_ptr_new("bmesh dupeops e"); /* duplicate flagged vertices */ - BM_ITER_MESH (v, &viter, source, BM_VERTS_OF_MESH) { - if (BMO_elem_flag_test(source, v, DUPE_INPUT) && - !BMO_elem_flag_test(source, v, DUPE_DONE)) + BM_ITER_MESH (v, &viter, bm_src, BM_VERTS_OF_MESH) { + if (BMO_elem_flag_test(bm_src, v, DUPE_INPUT) && + !BMO_elem_flag_test(bm_src, v, DUPE_DONE)) { BMIter iter; int isolated = 1; - v2 = copy_vertex(source, v, target, vhash); + v2 = copy_vertex(bm_src, v, bm_dst, vhash); BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) { - if (BMO_elem_flag_test(source, f, DUPE_INPUT)) { + if (BMO_elem_flag_test(bm_src, f, DUPE_INPUT)) { isolated = 0; break; } @@ -219,7 +227,7 @@ static void BKE_mesh_copy(BMOperator *op, BMesh *source, BMesh *target) if (isolated) { BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { - if (BMO_elem_flag_test(source, e, DUPE_INPUT)) { + if (BMO_elem_flag_test(bm_src, e, DUPE_INPUT)) { isolated = 0; break; } @@ -227,49 +235,49 @@ static void BKE_mesh_copy(BMOperator *op, BMesh *source, BMesh *target) } if (isolated) { - BMO_slot_map_ptr_insert(source, op, "isovertmap", v, v2); + BMO_slot_map_ptr_insert(op, slot_isovertmap_out, v, v2); } - BMO_elem_flag_enable(source, v, DUPE_DONE); + BMO_elem_flag_enable(bm_src, v, DUPE_DONE); } } /* now we dupe all the edges */ - BM_ITER_MESH (e, &eiter, source, BM_EDGES_OF_MESH) { - if (BMO_elem_flag_test(source, e, DUPE_INPUT) && - !BMO_elem_flag_test(source, e, DUPE_DONE)) + BM_ITER_MESH (e, &eiter, bm_src, BM_EDGES_OF_MESH) { + if (BMO_elem_flag_test(bm_src, e, DUPE_INPUT) && + !BMO_elem_flag_test(bm_src, e, DUPE_DONE)) { /* make sure that verts are copied */ - if (!BMO_elem_flag_test(source, e->v1, DUPE_DONE)) { - copy_vertex(source, e->v1, target, vhash); - BMO_elem_flag_enable(source, e->v1, DUPE_DONE); + if (!BMO_elem_flag_test(bm_src, e->v1, DUPE_DONE)) { + copy_vertex(bm_src, e->v1, bm_dst, vhash); + BMO_elem_flag_enable(bm_src, e->v1, DUPE_DONE); } - if (!BMO_elem_flag_test(source, e->v2, DUPE_DONE)) { - copy_vertex(source, e->v2, target, vhash); - BMO_elem_flag_enable(source, e->v2, DUPE_DONE); + if (!BMO_elem_flag_test(bm_src, e->v2, DUPE_DONE)) { + copy_vertex(bm_src, e->v2, bm_dst, vhash); + BMO_elem_flag_enable(bm_src, e->v2, DUPE_DONE); } /* now copy the actual edge */ - copy_edge(op, source, e, target, vhash, ehash); - BMO_elem_flag_enable(source, e, DUPE_DONE); + copy_edge(op, slot_boundarymap_out, bm_src, e, bm_dst, vhash, ehash); + BMO_elem_flag_enable(bm_src, e, DUPE_DONE); } } /* first we dupe all flagged faces and their elements from source */ - BM_ITER_MESH (f, &fiter, source, BM_FACES_OF_MESH) { - if (BMO_elem_flag_test(source, f, DUPE_INPUT)) { + BM_ITER_MESH (f, &fiter, bm_src, BM_FACES_OF_MESH) { + if (BMO_elem_flag_test(bm_src, f, DUPE_INPUT)) { /* vertex pass */ BM_ITER_ELEM (v, &viter, f, BM_VERTS_OF_FACE) { - if (!BMO_elem_flag_test(source, v, DUPE_DONE)) { - copy_vertex(source, v, target, vhash); - BMO_elem_flag_enable(source, v, DUPE_DONE); + if (!BMO_elem_flag_test(bm_src, v, DUPE_DONE)) { + copy_vertex(bm_src, v, bm_dst, vhash); + BMO_elem_flag_enable(bm_src, v, DUPE_DONE); } } /* edge pass */ BM_ITER_ELEM (e, &eiter, f, BM_EDGES_OF_FACE) { - if (!BMO_elem_flag_test(source, e, DUPE_DONE)) { - copy_edge(op, source, e, target, vhash, ehash); - BMO_elem_flag_enable(source, e, DUPE_DONE); + if (!BMO_elem_flag_test(bm_src, e, DUPE_DONE)) { + copy_edge(op, slot_boundarymap_out, bm_src, e, bm_dst, vhash, ehash); + BMO_elem_flag_enable(bm_src, e, DUPE_DONE); } } @@ -280,8 +288,8 @@ static void BKE_mesh_copy(BMOperator *op, BMesh *source, BMesh *target) BLI_array_grow_items(vtar, f->len); BLI_array_grow_items(edar, f->len); - copy_face(op, source, f, target, vtar, edar, vhash, ehash); - BMO_elem_flag_enable(source, f, DUPE_DONE); + copy_face(op, slot_facemap_out, bm_src, f, bm_dst, vtar, edar, vhash, ehash); + BMO_elem_flag_enable(bm_src, f, DUPE_DONE); } } @@ -317,23 +325,24 @@ static void BKE_mesh_copy(BMOperator *op, BMesh *source, BMesh *target) void bmo_duplicate_exec(BMesh *bm, BMOperator *op) { BMOperator *dupeop = op; - BMesh *bm2 = BMO_slot_ptr_get(op, "dest"); + BMesh *bm2 = BMO_slot_ptr_get(op->slots_in, "dest"); if (!bm2) bm2 = bm; /* flag input */ - BMO_slot_buffer_flag_enable(bm, dupeop, "geom", BM_ALL, DUPE_INPUT); + BMO_slot_buffer_flag_enable(bm, dupeop->slots_in, "geom", BM_ALL, DUPE_INPUT); /* use the internal copy function */ - BKE_mesh_copy(dupeop, bm, bm2); + bmo_mesh_copy(dupeop, bm, bm2); /* Output */ /* First copy the input buffers to output buffers - original data */ - BMO_slot_copy(dupeop, dupeop, "geom", "origout"); + BMO_slot_copy(dupeop, slots_in, "geom", + dupeop, slots_out, "geom_orig.out"); /* Now alloc the new output buffers */ - BMO_slot_buffer_from_enabled_flag(bm, dupeop, "newout", BM_ALL, DUPE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, dupeop, dupeop->slots_out, "geom.out", BM_ALL, DUPE_NEW); } #if 0 /* UNUSED */ @@ -378,16 +387,17 @@ 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, "use_only_faces"); + const short 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"); BMO_op_init(bm, &delop, op->flag, "delete"); - BMO_slot_copy(splitop, &dupeop, "geom", "geom"); + BMO_slot_copy(splitop, slots_in, "geom", + &dupeop, slots_in, "geom"); BMO_op_exec(bm, &dupeop); - BMO_slot_buffer_flag_enable(bm, splitop, "geom", BM_ALL, SPLIT_INPUT); + BMO_slot_buffer_flag_enable(bm, splitop->slots_in, "geom", BM_ALL, SPLIT_INPUT); if (use_only_faces) { BMVert *v; @@ -427,16 +437,22 @@ void bmo_split_exec(BMesh *bm, BMOperator *op) } /* connect outputs of dupe to delete, exluding keep geometry */ - BMO_slot_int_set(&delop, "context", DEL_FACES); - BMO_slot_buffer_from_enabled_flag(bm, &delop, "geom", BM_ALL, SPLIT_INPUT); + BMO_slot_int_set(delop.slots_in, "context", DEL_FACES); + BMO_slot_buffer_from_enabled_flag(bm, &delop, delop.slots_in, "geom", BM_ALL, SPLIT_INPUT); BMO_op_exec(bm, &delop); /* now we make our outputs by copying the dupe output */ - BMO_slot_copy(&dupeop, splitop, "newout", "geomout"); - BMO_slot_copy(&dupeop, splitop, "boundarymap", "boundarymap"); - BMO_slot_copy(&dupeop, splitop, "isovertmap", "isovertmap"); - + BMO_slot_copy(&dupeop, slots_out, "geom.out", + splitop, slots_out, "geom.out"); + + BMO_slot_copy(&dupeop, slots_out, "boundarymap.out", + splitop, slots_out, "boundarymap.out"); + + BMO_slot_copy(&dupeop, slots_out, "isovertmap.out", + splitop, slots_out, "isovertmap.out"); + + /* cleanup */ BMO_op_finish(bm, &delop); BMO_op_finish(bm, &dupeop); @@ -450,9 +466,9 @@ void bmo_delete_exec(BMesh *bm, BMOperator *op) BMOperator *delop = op; /* Mark Buffer */ - BMO_slot_buffer_flag_enable(bm, delop, "geom", BM_ALL, DEL_INPUT); + BMO_slot_buffer_flag_enable(bm, delop->slots_in, "geom", BM_ALL, DEL_INPUT); - BMO_remove_tagged_context(bm, DEL_INPUT, BMO_slot_int_get(op, "context")); + BMO_remove_tagged_context(bm, DEL_INPUT, BMO_slot_int_get(op->slots_in, "context")); #undef DEL_INPUT } @@ -473,44 +489,47 @@ void bmo_spin_exec(BMesh *bm, BMOperator *op) float phi; int steps, do_dupli, a, usedvec; - BMO_slot_vec_get(op, "cent", cent); - BMO_slot_vec_get(op, "axis", axis); + BMO_slot_vec_get(op->slots_in, "cent", cent); + BMO_slot_vec_get(op->slots_in, "axis", axis); normalize_v3(axis); - BMO_slot_vec_get(op, "dvec", dvec); + BMO_slot_vec_get(op->slots_in, "dvec", dvec); usedvec = !is_zero_v3(dvec); - steps = BMO_slot_int_get(op, "steps"); - phi = BMO_slot_float_get(op, "ang") * DEG2RADF(1.0f) / steps; - do_dupli = BMO_slot_bool_get(op, "do_dupli"); + steps = BMO_slot_int_get(op->slots_in, "steps"); + phi = BMO_slot_float_get(op->slots_in, "angle") * DEG2RADF(1.0f) / steps; + do_dupli = BMO_slot_bool_get(op->slots_in, "use_duplicate"); axis_angle_to_mat3(rmat, axis, phi); - BMO_slot_copy(op, op, "geom", "lastout"); + BMO_slot_copy(op, slots_in, "geom", + op, slots_out, "geom_last.out"); for (a = 0; a < steps; a++) { if (do_dupli) { - BMO_op_initf(bm, &dupop, op->flag, "duplicate geom=%s", op, "lastout"); + BMO_op_initf(bm, &dupop, op->flag, "duplicate geom=%S", op, "geom_last.out"); BMO_op_exec(bm, &dupop); BMO_op_callf(bm, op->flag, - "rotate cent=%v mat=%m3 verts=%s", - cent, rmat, &dupop, "newout"); - BMO_slot_copy(&dupop, op, "newout", "lastout"); + "rotate cent=%v mat=%m3 verts=%S", + cent, rmat, &dupop, "geom.out"); + BMO_slot_copy(&dupop, slots_out, "geom.out", + op, slots_out, "geom_last.out"); BMO_op_finish(bm, &dupop); } else { - BMO_op_initf(bm, &extop, op->flag, "extrude_face_region edgefacein=%s", - op, "lastout"); + BMO_op_initf(bm, &extop, op->flag, "extrude_face_region geom=%S", + op, "geom_last.out"); BMO_op_exec(bm, &extop); BMO_op_callf(bm, op->flag, - "rotate cent=%v mat=%m3 verts=%s", - cent, rmat, &extop, "geomout"); - BMO_slot_copy(&extop, op, "geomout", "lastout"); + "rotate cent=%v mat=%m3 verts=%S", + cent, rmat, &extop, "geom.out"); + BMO_slot_copy(&extop, slots_out, "geom.out", + op, slots_out, "geom_last.out"); BMO_op_finish(bm, &extop); } if (usedvec) { mul_m3_v3(rmat, dvec); BMO_op_callf(bm, op->flag, - "translate vec=%v verts=%s", - dvec, op, "lastout"); + "translate vec=%v verts=%S", + dvec, op, "geom_last.out"); } } } diff --git a/source/blender/bmesh/operators/bmo_edgesplit.c b/source/blender/bmesh/operators/bmo_edgesplit.c index 1f6689ed06c..9e9e4b8c962 100644 --- a/source/blender/bmesh/operators/bmo_edgesplit.c +++ b/source/blender/bmesh/operators/bmo_edgesplit.c @@ -81,14 +81,14 @@ static void bm_edgesplit_validate_seams(BMesh *bm, BMOperator *op) /* single marked edges unconnected to any other marked edges * are illegal, go through and unmark them */ - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { /* lame, but we don't want the count to exceed 255, * so just count to 2, its all we need */ unsigned char *vt; vt = &vtouch[BM_elem_index_get(e->v1)]; if (*vt < 2) (*vt)++; vt = &vtouch[BM_elem_index_get(e->v2)]; if (*vt < 2) (*vt)++; } - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { if (vtouch[BM_elem_index_get(e->v1)] == 1 && vtouch[BM_elem_index_get(e->v2)] == 1) { @@ -104,13 +104,13 @@ void bmo_split_edges_exec(BMesh *bm, BMOperator *op) { BMOIter siter; BMEdge *e; - const int use_verts = BMO_slot_bool_get(op, "use_verts"); + const int use_verts = BMO_slot_bool_get(op->slots_in, "use_verts"); - BMO_slot_buffer_flag_enable(bm, op, "edges", BM_EDGE, EDGE_SEAM); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_SEAM); if (use_verts) { /* this slows down the operation but its ok because the modifier doesn't use */ - BMO_slot_buffer_flag_enable(bm, op, "verts", BM_VERT, VERT_SEAM); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts", BM_VERT, VERT_SEAM); /* prevent one edge having both verts unflagged * we could alternately disable these edges, either way its a corner case. @@ -118,7 +118,7 @@ void bmo_split_edges_exec(BMesh *bm, BMOperator *op) * This is needed so we don't split off the edge but then none of its verts which * would leave a duplicate edge. */ - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { if (UNLIKELY((BMO_elem_flag_test(bm, e->v1, VERT_SEAM) == FALSE && (BMO_elem_flag_test(bm, e->v2, VERT_SEAM) == FALSE)))) { @@ -130,7 +130,7 @@ void bmo_split_edges_exec(BMesh *bm, BMOperator *op) bm_edgesplit_validate_seams(bm, op); - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { if (BMO_elem_flag_test(bm, e, EDGE_SEAM)) { /* this flag gets copied so we can be sure duplicate edges get it too (important) */ BM_elem_flag_enable(e, BM_ELEM_INTERNAL_TAG); @@ -146,7 +146,7 @@ void bmo_split_edges_exec(BMesh *bm, BMOperator *op) } if (use_verts) { - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { if (BMO_elem_flag_test(bm, e->v1, VERT_SEAM) == FALSE) { BM_elem_flag_disable(e->v1, BM_ELEM_TAG); } @@ -156,7 +156,7 @@ void bmo_split_edges_exec(BMesh *bm, BMOperator *op) } } - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { if (BMO_elem_flag_test(bm, e, EDGE_SEAM)) { if (BM_elem_flag_test(e->v1, BM_ELEM_TAG)) { BM_elem_flag_disable(e->v1, BM_ELEM_TAG); @@ -169,5 +169,5 @@ void bmo_split_edges_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_buffer_from_enabled_hflag(bm, op, "edgeout", BM_EDGE, BM_ELEM_INTERNAL_TAG); + 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 627351ead11..6a9d9c1e48b 100644 --- a/source/blender/bmesh/operators/bmo_extrude.c +++ b/source/blender/bmesh/operators/bmo_extrude.c @@ -60,7 +60,7 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op) BLI_array_declare(edges); int i; - BMO_ITER (f, &siter, bm, op, "faces", BM_FACE) { + BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) { BLI_array_empty(edges); BLI_array_grow_items(edges, f->len); @@ -122,7 +122,7 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op) BMO_op_callf(bm, op->flag, "delete geom=%ff context=%i", EXT_DEL, DEL_ONLYFACES); - BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, EXT_KEEP); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, EXT_KEEP); } /** @@ -181,7 +181,7 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op) BMFace *f; BMEdge *e, *e_new; - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { BMO_elem_flag_enable(bm, e, EXT_INPUT); BMO_elem_flag_enable(bm, e->v1, EXT_INPUT); BMO_elem_flag_enable(bm, e->v2, EXT_INPUT); @@ -193,12 +193,12 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op) /* disable root flag on all new skin nodes */ if (CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) { BMVert *v; - BMO_ITER(v, &siter, bm, &dupeop, "newout", BM_VERT) { + BMO_ITER(v, &siter, dupeop.slots_out, "geom.out", BM_VERT) { bm_extrude_disable_skin_root(bm, v); } } - for (e = BMO_iter_new(&siter, bm, &dupeop, "boundarymap", 0); e; e = BMO_iter_step(&siter)) { + for (e = BMO_iter_new(&siter, dupeop.slots_out, "boundarymap.out", 0); e; e = BMO_iter_step(&siter)) { BMVert *f_verts[4]; e_new = *(BMEdge **)BMO_iter_map_value(&siter); @@ -230,7 +230,7 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op) BMO_op_finish(bm, &dupeop); - BMO_slot_buffer_from_enabled_flag(bm, op, "geomout", BM_ALL, EXT_KEEP); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL, EXT_KEEP); } void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op) @@ -240,7 +240,7 @@ void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op) BMEdge *e; const int has_vskin = CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN); - for (v = BMO_iter_new(&siter, bm, op, "verts", BM_VERT); v; v = BMO_iter_step(&siter)) { + 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); if (has_vskin) bm_extrude_disable_skin_root(bm, v); @@ -251,8 +251,8 @@ void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op) BMO_elem_flag_enable(bm, dupev, EXT_KEEP); } - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, EXT_KEEP); - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, EXT_KEEP); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, EXT_KEEP); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EXT_KEEP); } void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) @@ -264,15 +264,17 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) BMVert *v, *v2; BMFace *f; int found, fwd, delorig = FALSE; + BMOpSlot *slot_facemap_out; + BMOpSlot *slot_edges_exclude; /* initialize our sub-operators */ BMO_op_init(bm, &dupeop, op->flag, "duplicate"); - BMO_slot_buffer_flag_enable(bm, op, "edgefacein", BM_EDGE | BM_FACE, EXT_INPUT); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "geom", BM_EDGE | BM_FACE, EXT_INPUT); /* if one flagged face is bordered by an un-flagged face, then we delete * original geometry unless caller explicitly asked to keep it. */ - if (!BMO_slot_bool_get(op, "alwayskeeporig")) { + if (!BMO_slot_bool_get(op->slots_in, "use_keep_orig")) { BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { int edge_face_tot; @@ -339,18 +341,21 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) EXT_DEL, DEL_ONLYTAGGED); } - BMO_slot_copy(op, &dupeop, "edgefacein", "geom"); + BMO_slot_copy(op, slots_in, "geom", + &dupeop, slots_in, "geom"); BMO_op_exec(bm, &dupeop); /* disable root flag on all new skin nodes */ if (CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) { - BMO_ITER(v, &siter, bm, &dupeop, "newout", BM_VERT) { + BMO_ITER(v, &siter, dupeop.slots_out, "geom.out", BM_VERT) { bm_extrude_disable_skin_root(bm, v); } } - if (bm->act_face && BMO_elem_flag_test(bm, bm->act_face, EXT_INPUT)) - bm->act_face = BMO_slot_map_ptr_get(bm, &dupeop, "facemap", bm->act_face); + slot_facemap_out = BMO_slot_get(dupeop.slots_out, "facemap.out"); + if (bm->act_face && BMO_elem_flag_test(bm, bm->act_face, EXT_INPUT)) { + bm->act_face = BMO_slot_map_ptr_get(slot_facemap_out, bm->act_face); + } if (delorig) { BMO_op_exec(bm, &delop); @@ -365,13 +370,15 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_copy(&dupeop, op, "newout", "geomout"); + BMO_slot_copy(&dupeop, slots_out, "geom.out", + op, slots_out, "geom.out"); - for (e = BMO_iter_new(&siter, bm, &dupeop, "boundarymap", 0); e; e = BMO_iter_step(&siter)) { + slot_edges_exclude = BMO_slot_get(op->slots_in, "edges_exclude"); + for (e = BMO_iter_new(&siter, dupeop.slots_out, "boundarymap.out", 0); e; e = BMO_iter_step(&siter)) { BMVert *f_verts[4]; /* this should always be wire, so this is mainly a speedup to avoid map lookup */ - if (BM_edge_is_wire(e) && BMO_slot_map_contains(bm, op, "exclude", e)) { + if (BM_edge_is_wire(e) && BMO_slot_map_contains(slot_edges_exclude, e)) { BMVert *v1 = e->v1, *v2 = e->v2; /* The original edge was excluded, @@ -421,7 +428,7 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) } /* link isolated vert */ - for (v = BMO_iter_new(&siter, bm, &dupeop, "isovertmap", 0); v; v = BMO_iter_step(&siter)) { + for (v = BMO_iter_new(&siter, dupeop.slots_out, "isovertmap.out", 0); v; v = BMO_iter_step(&siter)) { v2 = *((void **)BMO_iter_map_value(&siter)); BM_edge_create(bm, v, v2, v->e, TRUE); } @@ -595,10 +602,10 @@ static void solidify_add_thickness(BMesh *bm, const float dist) /* array for passing verts to angle_poly_v3 */ float **verts = NULL; - BLI_array_staticdeclare(verts, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(verts, BM_DEFAULT_NGON_STACK_SIZE); /* array for receiving angles from angle_poly_v3 */ float *face_angles = NULL; - BLI_array_staticdeclare(face_angles, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(face_angles, BM_DEFAULT_NGON_STACK_SIZE); BM_mesh_elem_index_ensure(bm, BM_VERT); @@ -647,25 +654,28 @@ void bmo_solidify_face_region_exec(BMesh *bm, BMOperator *op) BMOperator reverseop; float thickness; - thickness = BMO_slot_float_get(op, "thickness"); + thickness = BMO_slot_float_get(op->slots_in, "thickness"); /* Flip original faces (so the shell is extruded inward) */ BMO_op_init(bm, &reverseop, op->flag, "reverse_faces"); - BMO_slot_copy(op, &reverseop, "geom", "faces"); + BMO_slot_copy(op, slots_in, "geom", + &reverseop, slots_in, "faces"); BMO_op_exec(bm, &reverseop); BMO_op_finish(bm, &reverseop); /* Extrude the region */ - BMO_op_initf(bm, &extrudeop, op->flag, "extrude_face_region alwayskeeporig=%b", TRUE); - BMO_slot_copy(op, &extrudeop, "geom", "edgefacein"); + 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); /* Push the verts of the extruded faces inward to create thickness */ - BMO_slot_buffer_flag_enable(bm, &extrudeop, "geomout", BM_FACE, FACE_MARK); + BMO_slot_buffer_flag_enable(bm, extrudeop.slots_out, "geom.out", BM_FACE, FACE_MARK); calc_solidify_normals(bm); solidify_add_thickness(bm, thickness); - BMO_slot_copy(&extrudeop, op, "geomout", "geomout"); + BMO_slot_copy(&extrudeop, slots_out, "geom.out", + op, slots_out, "geom.out"); BMO_op_finish(bm, &extrudeop); } diff --git a/source/blender/bmesh/operators/bmo_hull.c b/source/blender/bmesh/operators/bmo_hull.c index b9c9398fbfa..117f65ae4ea 100644 --- a/source/blender/bmesh/operators/bmo_hull.c +++ b/source/blender/bmesh/operators/bmo_hull.c @@ -119,7 +119,7 @@ static void hull_output_triangles(BMesh *bm, GHash *hull_triangles) }; BMFace *f, *example = NULL; - if (BM_face_exists(bm, t->v, 3, &f)) { + if (BM_face_exists(t->v, 3, &f)) { /* If the operator is run with "use_existing_faces" * disabled, but an output face in the hull is the * same as a face in the existing mesh, it should not @@ -139,17 +139,17 @@ static void hull_output_triangles(BMesh *bm, GHash *hull_triangles) f = BM_face_create_quad_tri_v(bm, t->v, 3, example, TRUE); BM_face_copy_shared(bm, f); } - /* Mark face for 'geomout' slot and select */ + /* 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); - /* Mark edges for 'geomout' slot */ + /* Mark edges for 'geom.out' slot */ for (i = 0; i < 3; i++) { BMO_elem_flag_enable(bm, edges[i], HULL_FLAG_OUTPUT_GEOM); } } else { - /* Mark input edges for 'geomout' slot */ + /* Mark input edges for 'geom.out' slot */ for (i = 0; i < 3; i++) { const int next = (i == 2 ? 0 : i + 1); BMEdge *e = BM_edge_exists(t->v[i], t->v[next]); @@ -161,7 +161,7 @@ static void hull_output_triangles(BMesh *bm, GHash *hull_triangles) } } - /* Mark verts for 'geomout' slot */ + /* Mark verts for 'geom.out' slot */ for (i = 0; i < 3; i++) { BMO_elem_flag_enable(bm, t->v[i], HULL_FLAG_OUTPUT_GEOM); } @@ -304,14 +304,14 @@ static void hull_mark_interior_elements(BMesh *bm, BMOperator *op, BMOIter oiter; /* Check for interior edges too */ - BMO_ITER (e, &oiter, bm, op, "input", BM_EDGE) { + BMO_ITER (e, &oiter, op->slots_in, "input", BM_EDGE) { if (!hull_final_edges_lookup(final_edges, e->v1, e->v2)) BMO_elem_flag_enable(bm, e, HULL_FLAG_INTERIOR_ELE); } /* Mark all input faces as interior, some may be unmarked in * hull_remove_overlapping() */ - BMO_ITER (f, &oiter, bm, op, "input", BM_FACE) { + BMO_ITER (f, &oiter, op->slots_in, "input", BM_FACE) { BMO_elem_flag_enable(bm, f, HULL_FLAG_INTERIOR_ELE); } } @@ -328,7 +328,7 @@ static void hull_tag_unused(BMesh *bm, BMOperator *op) * interior (i.e. were already part of the input, but not part of * the hull), but that aren't also used by elements outside the * input set */ - BMO_ITER (v, &oiter, bm, op, "input", BM_VERT) { + BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) { if (BMO_elem_flag_test(bm, v, HULL_FLAG_INTERIOR_ELE)) { int del = TRUE; @@ -351,7 +351,7 @@ static void hull_tag_unused(BMesh *bm, BMOperator *op) } } - BMO_ITER (e, &oiter, bm, op, "input", BM_EDGE) { + BMO_ITER (e, &oiter, op->slots_in, "input", BM_EDGE) { if (BMO_elem_flag_test(bm, e, HULL_FLAG_INTERIOR_ELE)) { int del = TRUE; @@ -367,7 +367,7 @@ static void hull_tag_unused(BMesh *bm, BMOperator *op) } } - BMO_ITER (f, &oiter, bm, op, "input", BM_FACE) { + BMO_ITER (f, &oiter, op->slots_in, "input", BM_FACE) { if (BMO_elem_flag_test(bm, f, HULL_FLAG_INTERIOR_ELE)) BMO_elem_flag_enable(bm, f, HULL_FLAG_DEL); } @@ -382,10 +382,10 @@ static void hull_tag_holes(BMesh *bm, BMOperator *op) /* Unmark any hole faces if they are isolated or part of a * border */ - BMO_ITER (f, &oiter, bm, op, "input", BM_FACE) { + BMO_ITER (f, &oiter, op->slots_in, "input", BM_FACE) { if (BMO_elem_flag_test(bm, f, HULL_FLAG_HOLE)) { BM_ITER_ELEM (e, &iter, f, BM_EDGES_OF_FACE) { - if (BM_edge_face_count(e) == 1) { + if (BM_edge_is_boundary(e)) { BMO_elem_flag_disable(bm, f, HULL_FLAG_HOLE); break; } @@ -395,7 +395,7 @@ 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, bm, op, "input", BM_EDGE) { + BMO_ITER (e, &oiter, op->slots_in, "input", BM_EDGE) { int hole = TRUE; int any_faces = FALSE; @@ -412,20 +412,20 @@ static void hull_tag_holes(BMesh *bm, BMOperator *op) } } -static int hull_input_vert_count(BMesh *bm, BMOperator *op) +static int hull_input_vert_count(BMOperator *op) { BMOIter oiter; BMVert *v; int count = 0; - BMO_ITER (v, &oiter, bm, op, "input", BM_VERT) { + BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) { count++; } return count; } -static BMVert **hull_input_verts_copy(BMesh *bm, BMOperator *op, +static BMVert **hull_input_verts_copy(BMOperator *op, const int num_input_verts) { BMOIter oiter; @@ -434,7 +434,7 @@ static BMVert **hull_input_verts_copy(BMesh *bm, BMOperator *op, num_input_verts, AT); int i = 0; - BMO_ITER (v, &oiter, bm, op, "input", BM_VERT) { + BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) { input_verts[i++] = v; } @@ -492,9 +492,9 @@ static void hull_from_bullet(BMesh *bm, BMOperator *op, plConvexHull hull; int i, count = 0; - const int num_input_verts = hull_input_vert_count(bm, op); + const int num_input_verts = hull_input_vert_count(op); - input_verts = hull_input_verts_copy(bm, op, num_input_verts); + input_verts = hull_input_verts_copy(op, num_input_verts); coords = hull_verts_for_bullet(input_verts, num_input_verts); hull = plConvexHullCompute(coords, num_input_verts); @@ -535,13 +535,13 @@ static void hull_from_bullet(BMesh *bm, BMOperator *op, } /* Check that there are at least three vertices in the input */ -static int hull_num_input_verts_is_ok(BMesh *bm, BMOperator *op) +static int hull_num_input_verts_is_ok(BMOperator *op) { BMOIter oiter; BMVert *v; int partial_num_verts = 0; - BMO_ITER (v, &oiter, bm, op, "input", BM_VERT) { + BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) { partial_num_verts++; if (partial_num_verts >= 3) break; @@ -559,14 +559,14 @@ void bmo_convex_hull_exec(BMesh *bm, BMOperator *op) GHash *hull_triangles; /* Verify that at least three verts in the input */ - if (!hull_num_input_verts_is_ok(bm, op)) { + if (!hull_num_input_verts_is_ok(op)) { BMO_error_raise(bm, op, BMERR_CONVEX_HULL_FAILED, "Requires at least three vertices"); return; } /* Tag input elements */ - BMO_ITER (ele, &oiter, bm, op, "input", BM_ALL) { + BMO_ITER (ele, &oiter, op->slots_in, "input", BM_ALL) { BMO_elem_flag_enable(bm, ele, HULL_FLAG_INPUT); /* Mark all vertices as interior to begin with */ @@ -584,7 +584,7 @@ void bmo_convex_hull_exec(BMesh *bm, BMOperator *op) hull_mark_interior_elements(bm, op, final_edges); /* Remove hull triangles covered by an existing face */ - if (BMO_slot_bool_get(op, "use_existing_faces")) { + if (BMO_slot_bool_get(op->slots_in, "use_existing_faces")) { hull_remove_overlapping(bm, hull_triangles, final_edges); hull_tag_holes(bm, op); @@ -603,23 +603,23 @@ void bmo_convex_hull_exec(BMesh *bm, BMOperator *op) /* Output slot of input elements that ended up inside the hull * rather than part of it */ - BMO_slot_buffer_from_enabled_flag(bm, op, "interior_geom", BM_ALL, - HULL_FLAG_INTERIOR_ELE); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_interior.out", + BM_ALL, HULL_FLAG_INTERIOR_ELE); /* Output slot of input elements that ended up inside the hull and * are are unused by other geometry. */ - BMO_slot_buffer_from_enabled_flag(bm, op, "unused_geom", BM_ALL, - HULL_FLAG_DEL); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_unused.out", + BM_ALL, HULL_FLAG_DEL); /* Output slot of faces and edges that were in the input and on * the hull (useful for cases like bridging where you want to * delete some input geometry) */ - BMO_slot_buffer_from_enabled_flag(bm, op, "holes_geom", BM_ALL, - HULL_FLAG_HOLE); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_holes.out", + BM_ALL, HULL_FLAG_HOLE); /* Output slot of all hull vertices, faces, and edges */ - BMO_slot_buffer_from_enabled_flag(bm, op, "geomout", BM_ALL, - HULL_FLAG_OUTPUT_GEOM); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", + BM_ALL, HULL_FLAG_OUTPUT_GEOM); } #endif /* WITH_BULLET */ diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c index 132d7050b31..9abf129a529 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, "use_outset"); - const int use_boundary = BMO_slot_bool_get(op, "use_boundary") && (use_outset == FALSE); - const int use_even_offset = BMO_slot_bool_get(op, "use_even_offset"); + 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, "use_relative_offset"); - const float thickness = BMO_slot_float_get(op, "thickness"); - const float depth = BMO_slot_float_get(op, "depth"); + 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"); int edge_info_len = 0; @@ -113,11 +113,11 @@ void bmo_inset_exec(BMesh *bm, BMOperator *op) if (use_outset == FALSE) { BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, FALSE); - BMO_slot_buffer_hflag_enable(bm, op, "faces", 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, "faces", 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 */ @@ -477,11 +477,48 @@ void bmo_inset_exec(BMesh *bm, BMOperator *op) /* copy for loop data, otherwise UV's and vcols are no good. * tiny speedup here we could be more clever and copy from known adjacent data * also - we could attempt to interpolate the loop data, this would be much slower but more useful too */ +#if 0 + /* don't use this because face boundaries have no adjacent loops and won't be filled in. + * instead copy from the opposite side with the code below */ BM_face_copy_shared(bm, f); +#else + { + /* 2 inner loops on the edge between the new face and the original */ + BMLoop *l_a; + BMLoop *l_b; + BMLoop *l_a_other; + BMLoop *l_b_other; + + l_a = BM_FACE_FIRST_LOOP(f); + l_b = l_a->next; + + /* we know this side has a radial_next because of the order of created verts in the quad */ + l_a_other = BM_edge_other_loop(l_a->e, l_a); + l_b_other = BM_edge_other_loop(l_a->e, l_b); + BM_elem_attrs_copy(bm, bm, l_a_other, l_a); + BM_elem_attrs_copy(bm, bm, l_b_other, l_b); + + /* step around to the opposite side of the quad - warning, this may have no other edges! */ + l_a = l_a->next->next; + l_b = l_a->next; + if (!BM_edge_is_boundary(l_a->e)) { + /* same as above */ + l_a_other = BM_edge_other_loop(l_a->e, l_a); + l_b_other = BM_edge_other_loop(l_a->e, l_b); + BM_elem_attrs_copy(bm, bm, l_a_other, l_a); + BM_elem_attrs_copy(bm, bm, l_b_other, l_b); + } + else { /* boundary edges have no useful data to copy from, use opposite side of face */ + /* swap a<->b intentionally */ + BM_elem_attrs_copy(bm, bm, l_a_other, l_b); + BM_elem_attrs_copy(bm, bm, l_b_other, l_a); + } + } +#endif } /* we could flag new edges/verts too, is it useful? */ - BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, ELE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, ELE_NEW); /* cheap feature to add depth to the inset */ if (depth != 0.0f) { @@ -514,7 +551,7 @@ void bmo_inset_exec(BMesh *bm, BMOperator *op) BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, FALSE); /* tag face verts */ - BMO_ITER (f, &oiter, bm, op, "faces", BM_FACE) { + BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) { BM_ITER_ELEM (v, &iter, f, BM_VERTS_OF_FACE) { BM_elem_flag_enable(v, BM_ELEM_TAG); } diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c index 3dbc0d0a5eb..1e18a83a0a0 100644 --- a/source/blender/bmesh/operators/bmo_join_triangles.c +++ b/source/blender/bmesh/operators/bmo_join_triangles.c @@ -204,16 +204,16 @@ 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, "cmp_sharp"); - int do_uv = BMO_slot_bool_get(op, "cmp_uvs"); + 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, "cmp_vcols"); - int do_mat = BMO_slot_bool_get(op, "cmp_materials"); - float limit = BMO_slot_float_get(op, "limit"); + 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 */ - BMO_ITER (f, &siter, bm, op, "faces", BM_FACE) { + BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) { BMO_elem_flag_enable(bm, f, FACE_INPUT); BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { BMO_elem_flag_enable(bm, l->e, EDGE_MARK); diff --git a/source/blender/bmesh/operators/bmo_mesh_conv.c b/source/blender/bmesh/operators/bmo_mesh_conv.c index c4b988ae82d..4b897a24c8a 100644 --- a/source/blender/bmesh/operators/bmo_mesh_conv.c +++ b/source/blender/bmesh/operators/bmo_mesh_conv.c @@ -53,9 +53,9 @@ void bmo_mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) { - Object *ob = BMO_slot_ptr_get(op, "object"); - Mesh *me = BMO_slot_ptr_get(op, "mesh"); - int set_key = BMO_slot_bool_get(op, "set_shapekey"); + 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"); BM_mesh_bm_from_me(bm, me, set_key, ob->shapenr); @@ -66,20 +66,20 @@ void bmo_mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) void bmo_object_load_bmesh_exec(BMesh *bm, BMOperator *op) { - Object *ob = BMO_slot_ptr_get(op, "object"); + Object *ob = BMO_slot_ptr_get(op->slots_in, "object"); /* Scene *scene = BMO_slot_ptr_get(op, "scene"); */ Mesh *me = ob->data; BMO_op_callf(bm, op->flag, - "bmesh_to_mesh mesh=%p object=%p notessellation=%b", + "bmesh_to_mesh mesh=%p object=%p skip_tessface=%b", me, ob, TRUE); } void bmo_bmesh_to_mesh_exec(BMesh *bm, BMOperator *op) { - Mesh *me = BMO_slot_ptr_get(op, "mesh"); + 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, "notessellation"); + int 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 937601712b0..01bce976ec0 100644 --- a/source/blender/bmesh/operators/bmo_mirror.c +++ b/source/blender/bmesh/operators/bmo_mirror.c @@ -50,27 +50,28 @@ void bmo_mirror_exec(BMesh *bm, BMOperator *op) float mtx[4][4]; float imtx[4][4]; float scale[3] = {1.0f, 1.0f, 1.0f}; - float dist = BMO_slot_float_get(op, "mergedist"); + float dist = BMO_slot_float_get(op->slots_in, "merge_dist"); int i, ototvert /*, ototedge */; - int axis = BMO_slot_int_get(op, "axis"); - int mirroru = BMO_slot_bool_get(op, "mirror_u"); - int mirrorv = BMO_slot_bool_get(op, "mirror_v"); + 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"); + BMOpSlot *slot_targetmap; ototvert = bm->totvert; /* ototedge = bm->totedge; */ /* UNUSED */ - BMO_slot_mat4_get(op, "mat", mtx); + BMO_slot_mat4_get(op->slots_in, "mat", mtx); invert_m4_m4(imtx, mtx); BMO_op_initf(bm, &dupeop, op->flag, "duplicate geom=%s", op, "geom"); BMO_op_exec(bm, &dupeop); - BMO_slot_buffer_flag_enable(bm, &dupeop, "newout", BM_ALL, ELE_NEW); + BMO_slot_buffer_flag_enable(bm, dupeop.slots_out, "geom.out", BM_ALL, ELE_NEW); /* create old -> new mappin */ i = 0; /* v2 = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL); */ /* UNUSED */ - BMO_ITER (v, &siter, bm, &dupeop, "newout", BM_VERT) { + BMO_ITER (v, &siter, dupeop.slots_out, "geom.out", BM_VERT) { BLI_array_grow_one(vmap); vmap[i] = v; /* v2 = BM_iter_step(&iter); */ /* UNUSED */ @@ -86,10 +87,12 @@ void bmo_mirror_exec(BMesh *bm, BMOperator *op) BMO_op_init(bm, &weldop, op->flag, "weld_verts"); + slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap"); + v = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL); for (i = 0; i < ototvert; i++) { if (fabsf(v->co[axis]) <= dist) { - BMO_slot_map_ptr_insert(bm, &weldop, "targetmap", vmap[i], v); + BMO_slot_map_ptr_insert(&weldop, slot_targetmap, vmap[i], v); } v = BM_iter_step(&iter); } @@ -101,7 +104,7 @@ void bmo_mirror_exec(BMesh *bm, BMOperator *op) int totlayer; BMIter liter; - BMO_ITER (f, &siter, bm, &dupeop, "newout", BM_FACE) { + BMO_ITER (f, &siter, dupeop.slots_out, "geom.out", BM_FACE) { BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { totlayer = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV); for (i = 0; i < totlayer; i++) { @@ -120,7 +123,7 @@ void bmo_mirror_exec(BMesh *bm, BMOperator *op) BMO_op_finish(bm, &weldop); BMO_op_finish(bm, &dupeop); - BMO_slot_buffer_from_enabled_flag(bm, op, "newout", BM_ALL, ELE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL, ELE_NEW); BLI_array_free(vmap); BLI_array_free(emap); diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c index d7b163cb760..71f63bbaf28 100644 --- a/source/blender/bmesh/operators/bmo_primitive.c +++ b/source/blender/bmesh/operators/bmo_primitive.c @@ -227,16 +227,17 @@ static signed char monkeyf[250][4] = { void bmo_create_grid_exec(BMesh *bm, BMOperator *op) { + const float dia = BMO_slot_float_get(op->slots_in, "size"); + const int tot = max_ii(2, BMO_slot_int_get(op->slots_in, "x_segments")); + const int seg = max_ii(2, BMO_slot_int_get(op->slots_in, "y_segments")); + BMOperator bmop, prevop; BMVert *eve, *preveve; BMEdge *e; - float vec[3], mat[4][4], phi, phid, dia = BMO_slot_float_get(op, "size"); - int a, tot = BMO_slot_int_get(op, "xsegments"), seg = BMO_slot_int_get(op, "ysegments"); - - if (tot < 2) tot = 2; - if (seg < 2) seg = 2; + float vec[3], mat[4][4], phi, phid; + int a; - BMO_slot_mat4_get(op, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "mat", mat); /* one segment first: the X axis */ phi = 1.0f; @@ -267,39 +268,43 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op) for (a = 0; a < seg - 1; a++) { if (a) { - BMO_op_initf(bm, &bmop, op->flag, "extrude_edge_only edges=%s", &prevop, "geomout"); + BMO_op_initf(bm, &bmop, op->flag, "extrude_edge_only edges=%S", &prevop, "geom.out"); BMO_op_exec(bm, &bmop); BMO_op_finish(bm, &prevop); - BMO_slot_buffer_flag_enable(bm, &bmop, "geomout", BM_VERT, VERT_MARK); + BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_VERT, VERT_MARK); } else { BMO_op_initf(bm, &bmop, op->flag, "extrude_edge_only edges=%fe", EDGE_ORIG); BMO_op_exec(bm, &bmop); - BMO_slot_buffer_flag_enable(bm, &bmop, "geomout", BM_VERT, VERT_MARK); + BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_VERT, VERT_MARK); } - BMO_op_callf(bm, op->flag, "translate vec=%v verts=%s", vec, &bmop, "geomout"); + BMO_op_callf(bm, op->flag, "translate vec=%v verts=%S", vec, &bmop, "geom.out"); prevop = bmop; } if (a) BMO_op_finish(bm, &bmop); - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) { + const float dia = BMO_slot_float_get(op->slots_in, "diameter"); + const int seg = BMO_slot_int_get(op->slots_in, "u_segments"); + const int tot = BMO_slot_int_get(op->slots_in, "v_segments"); + BMOperator bmop, prevop; BMVert *eve, *preveve; BMEdge *e; BMIter iter; float vec[3], mat[4][4], cmat[3][3], phi, q[4]; - float phid, dia = BMO_slot_float_get(op, "diameter"); - int a, seg = BMO_slot_int_get(op, "segments"), tot = BMO_slot_int_get(op, "revolutions"); + float phid; + int a; - BMO_slot_mat4_get(op, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "mat", mat); phid = 2.0f * (float)M_PI / tot; /* phi = 0.25f * (float)M_PI; */ /* UNUSED */ @@ -333,7 +338,7 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) for (a = 0; a < seg; a++) { if (a) { - BMO_op_initf(bm, &bmop, op->flag, "extrude_edge_only edges=%s", &prevop, "geomout"); + BMO_op_initf(bm, &bmop, op->flag, "extrude_edge_only edges=%S", &prevop, "geom.out"); BMO_op_exec(bm, &bmop); BMO_op_finish(bm, &prevop); } @@ -342,8 +347,8 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) BMO_op_exec(bm, &bmop); } - BMO_slot_buffer_flag_enable(bm, &bmop, "geomout", BM_VERT, VERT_MARK); - BMO_op_callf(bm, op->flag, "rotate cent=%v mat=%m3 verts=%s", vec, cmat, &bmop, "geomout"); + BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_VERT, VERT_MARK); + BMO_op_callf(bm, op->flag, "rotate cent=%v mat=%m3 verts=%S", vec, cmat, &bmop, "geom.out"); prevop = bmop; } @@ -375,30 +380,33 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op) { + const float dia = BMO_slot_float_get(op->slots_in, "diameter"); + const float dia_div = dia / 200.0f; + const int subdiv = BMO_slot_int_get(op->slots_in, "subdivisions"); + BMVert *eva[12]; BMVert *v; BMIter liter; BMIter viter; BMLoop *l; float vec[3], mat[4][4] /* , phi, phid */; - float dia = BMO_slot_float_get(op, "diameter"); - int a, subdiv = BMO_slot_int_get(op, "subdivisions"); + int a; - BMO_slot_mat4_get(op, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "mat", mat); /* phid = 2.0f * (float)M_PI / subdiv; */ /* UNUSED */ /* phi = 0.25f * (float)M_PI; */ /* UNUSED */ - dia /= 200.0f; + for (a = 0; a < 12; a++) { - vec[0] = dia * icovert[a][0]; - vec[1] = dia * icovert[a][1]; - vec[2] = dia * icovert[a][2]; + vec[0] = dia_div * icovert[a][0]; + vec[1] = dia_div * icovert[a][1]; + vec[2] = dia_div * icovert[a][2]; eva[a] = BM_vert_create(bm, vec, NULL); BMO_elem_flag_enable(bm, eva[a], VERT_MARK); @@ -421,22 +429,20 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op) BMO_elem_flag_enable(bm, eftemp, FACE_MARK); } - dia *= 200.0f; - if (subdiv > 1) { BMOperator bmop; BMO_op_initf(bm, &bmop, op->flag, "subdivide_edges edges=%fe " "smooth=%f " - "numcuts=%i " + "cuts=%i " "use_gridfill=%b use_sphere=%b", EDGE_MARK, dia, (1 << (subdiv - 1)) - 1, TRUE, TRUE); BMO_op_exec(bm, &bmop); - BMO_slot_buffer_flag_enable(bm, &bmop, "geomout", BM_VERT, VERT_MARK); - BMO_slot_buffer_flag_enable(bm, &bmop, "geomout", BM_EDGE, EDGE_MARK); + BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_VERT, VERT_MARK); + BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_EDGE, EDGE_MARK); BMO_op_finish(bm, &bmop); } @@ -447,7 +453,7 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } void bmo_create_monkey_exec(BMesh *bm, BMOperator *op) @@ -457,7 +463,7 @@ void bmo_create_monkey_exec(BMesh *bm, BMOperator *op) float mat[4][4]; int i; - BMO_slot_mat4_get(op, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "mat", mat); for (i = 0; i < monkeynv; i++) { float v[3]; @@ -494,24 +500,25 @@ void bmo_create_monkey_exec(BMesh *bm, BMOperator *op) MEM_freeN(tv); - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } 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"); + BMVert *v1, *lastv1 = NULL, *cent1, *firstv1 = NULL; float vec[3], mat[4][4], phi, phid; - float dia = BMO_slot_float_get(op, "diameter"); - int segs = BMO_slot_int_get(op, "segments"); - int cap_ends = BMO_slot_bool_get(op, "cap_ends"); - int cap_tris = BMO_slot_bool_get(op, "cap_tris"); int a; if (!segs) return; - BMO_slot_mat4_get(op, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "mat", mat); phid = 2.0f * (float)M_PI / segs; phi = 0; @@ -566,25 +573,25 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op) BMO_op_callf(bm, op->flag, "dissolve_faces faces=%ff", FACE_NEW); } - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } void bmo_create_cone_exec(BMesh *bm, BMOperator *op) { BMVert *v1, *v2, *lastv1 = NULL, *lastv2 = NULL, *cent1, *cent2, *firstv1, *firstv2; float vec[3], mat[4][4], phi, phid; - float dia1 = BMO_slot_float_get(op, "diameter1"); - float dia2 = BMO_slot_float_get(op, "diameter2"); - float depth = BMO_slot_float_get(op, "depth"); - int segs = BMO_slot_int_get(op, "segments"); - int cap_ends = BMO_slot_bool_get(op, "cap_ends"); - int cap_tris = BMO_slot_bool_get(op, "cap_tris"); + float dia1 = BMO_slot_float_get(op->slots_in, "diameter1"); + 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"); int a; if (!segs) return; - BMO_slot_mat4_get(op, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "mat", mat); phid = 2.0f * (float)M_PI / segs; phi = 0; @@ -662,15 +669,15 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op) 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, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); } void bmo_create_cube_exec(BMesh *bm, BMOperator *op) { BMVert *v1, *v2, *v3, *v4, *v5, *v6, *v7, *v8; - float vec[3], mat[4][4], off = BMO_slot_float_get(op, "size") / 2.0f; + float vec[3], mat[4][4], off = BMO_slot_float_get(op->slots_in, "size") / 2.0f; - BMO_slot_mat4_get(op, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "mat", mat); if (!off) off = 0.5f; @@ -740,5 +747,5 @@ void bmo_create_cube_exec(BMesh *bm, BMOperator *op) 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, "vertout", BM_VERT, VERT_MARK); + 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 ea6cd747037..45e678b96bb 100644 --- a/source/blender/bmesh/operators/bmo_removedoubles.c +++ b/source/blender/bmesh/operators/bmo_removedoubles.c @@ -36,7 +36,7 @@ #include "intern/bmesh_operators_private.h" /* own include */ -static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op) +static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op, BMOpSlot *slot_targetmap) { BMIter liter; BMLoop *l; @@ -44,7 +44,7 @@ static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op) int split = FALSE; BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - v2 = BMO_slot_map_ptr_get(bm, op, "targetmap", l->v); + v2 = BMO_slot_map_ptr_get(slot_targetmap, l->v); /* ok: if v2 is NULL (e.g. not in the map) then it's * a target vert, otherwise it's a double */ if ((v2 && BM_vert_in_face(f, v2)) && @@ -61,8 +61,8 @@ static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op) BMLoop *nl; BMFace *f2 = BM_face_split(bm, f, doub, v2, &nl, NULL, FALSE); - remdoubles_splitface(f, bm, op); - remdoubles_splitface(f2, bm, op); + remdoubles_splitface(f, bm, op, slot_targetmap); + remdoubles_splitface(f2, bm, op, slot_targetmap); } } @@ -106,10 +106,11 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op) BLI_array_declare(loops); BMFace *f, *f2; int a, b; + BMOpSlot *slot_targetmap = BMO_slot_get(op->slots_in, "targetmap"); /* mark merge verts for deletion */ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - if ((v2 = BMO_slot_map_ptr_get(bm, op, "targetmap", v))) { + if ((v2 = BMO_slot_map_ptr_get(slot_targetmap, v))) { BMO_elem_flag_enable(bm, v, ELE_DEL); /* merge the vertex flags, else we get randomly selected/unselected verts */ @@ -120,13 +121,13 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op) /* check if any faces are getting their own corners merged * together, split face if so */ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - remdoubles_splitface(f, bm, op); + remdoubles_splitface(f, bm, op, slot_targetmap); } BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (BMO_elem_flag_test(bm, e->v1, ELE_DEL) || BMO_elem_flag_test(bm, e->v2, ELE_DEL)) { - v = BMO_slot_map_ptr_get(bm, op, "targetmap", e->v1); - v2 = BMO_slot_map_ptr_get(bm, op, "targetmap", e->v2); + v = BMO_slot_map_ptr_get(slot_targetmap, e->v1); + v2 = BMO_slot_map_ptr_get(slot_targetmap, e->v2); if (!v) v = e->v1; if (!v2) v2 = e->v2; @@ -174,10 +175,10 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op) v = l->v; v2 = l->next->v; if (BMO_elem_flag_test(bm, v, ELE_DEL)) { - v = BMO_slot_map_ptr_get(bm, op, "targetmap", v); + v = BMO_slot_map_ptr_get(slot_targetmap, v); } if (BMO_elem_flag_test(bm, v2, ELE_DEL)) { - v2 = BMO_slot_map_ptr_get(bm, op, "targetmap", v2); + v2 = BMO_slot_map_ptr_get(slot_targetmap, v2); } e2 = v != v2 ? BM_edge_exists(v, v2) : NULL; @@ -207,10 +208,10 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op) v2 = loops[1]->v; if (BMO_elem_flag_test(bm, v, ELE_DEL)) { - v = BMO_slot_map_ptr_get(bm, op, "targetmap", v); + v = BMO_slot_map_ptr_get(slot_targetmap, v); } if (BMO_elem_flag_test(bm, v2, ELE_DEL)) { - v2 = BMO_slot_map_ptr_get(bm, op, "targetmap", v2); + v2 = BMO_slot_map_ptr_get(slot_targetmap, v2); } f2 = BM_face_create_ngon(bm, v, v2, edges, a, TRUE); @@ -262,7 +263,7 @@ void bmo_pointmerge_facedata_exec(BMesh *bm, BMOperator *op) float fac; int i, tot; - snapv = BMO_iter_new(&siter, bm, op, "snapv", BM_VERT); + snapv = BMO_iter_new(&siter, op->slots_in, "snapv", BM_VERT); tot = BM_vert_face_count(snapv); if (!tot) @@ -290,7 +291,7 @@ void bmo_pointmerge_facedata_exec(BMesh *bm, BMOperator *op) } } - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) { if (l == firstl) { continue; @@ -318,7 +319,7 @@ void bmo_average_vert_facedata_exec(BMesh *bm, BMOperator *op) type = bm->ldata.layers[i].type; CustomData_data_initminmax(type, &min, &max); - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) { block = CustomData_bmesh_get_layer_n(&bm->ldata, l->head.data, i); CustomData_data_dominmax(type, block, &min, &max); @@ -329,7 +330,7 @@ void bmo_average_vert_facedata_exec(BMesh *bm, BMOperator *op) CustomData_data_multiply(type, &max, 0.5f); CustomData_data_add(type, &min, &max); - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) { block = CustomData_bmesh_get_layer_n(&bm->ldata, l->head.data, i); CustomData_data_copy_value(type, &min, block); @@ -344,19 +345,22 @@ void bmo_pointmerge_exec(BMesh *bm, BMOperator *op) BMOIter siter; BMVert *v, *snapv = NULL; float vec[3]; + BMOpSlot *slot_targetmap; - BMO_slot_vec_get(op, "merge_co", vec); + BMO_slot_vec_get(op->slots_in, "merge_co", vec); //BMO_op_callf(bm, op->flag, "collapse_uvs edges=%s", op, "edges"); BMO_op_init(bm, &weldop, op->flag, "weld_verts"); - - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + + slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap"); + + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { if (!snapv) { snapv = v; copy_v3_v3(snapv->co, vec); } else { - BMO_slot_map_ptr_insert(bm, &weldop, "targetmap", v, snapv); + BMO_slot_map_ptr_insert(&weldop, slot_targetmap, v, snapv); } } @@ -373,11 +377,13 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op) BLI_array_declare(edges); float min[3], max[3], center[3]; int i, tot; + BMOpSlot *slot_targetmap; BMO_op_callf(bm, op->flag, "collapse_uvs edges=%s", op, "edges"); BMO_op_init(bm, &weldop, op->flag, "weld_verts"); + slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap"); - BMO_slot_buffer_flag_enable(bm, op, "edges", BM_EDGE, EDGE_MARK); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK); BMW_init(&walker, bm, BMW_SHELL, BMW_MASK_NOP, EDGE_MARK, BMW_MASK_NOP, @@ -408,9 +414,9 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op) copy_v3_v3(edges[i]->v2->co, center); if (edges[i]->v1 != edges[0]->v1) - BMO_slot_map_ptr_insert(bm, &weldop, "targetmap", edges[i]->v1, edges[0]->v1); + BMO_slot_map_ptr_insert(&weldop, slot_targetmap, edges[i]->v1, edges[0]->v1); if (edges[i]->v2 != edges[0]->v1) - BMO_slot_map_ptr_insert(bm, &weldop, "targetmap", edges[i]->v2, edges[0]->v1); + BMO_slot_map_ptr_insert(&weldop, slot_targetmap, edges[i]->v2, edges[0]->v1); } } @@ -436,7 +442,7 @@ static void bmo_collapsecon_do_layer(BMesh *bm, BMOperator *op, int layer) /* clear all short flags */ BMO_mesh_flag_disable_all(bm, op, BM_ALL, (1 << 16) - 1); - BMO_slot_buffer_flag_enable(bm, op, "edges", BM_EDGE, EDGE_MARK); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK); BMW_init(&walker, bm, BMW_LOOPDATA_ISLAND, BMW_MASK_NOP, EDGE_MARK, BMW_MASK_NOP, @@ -486,31 +492,32 @@ void bmo_collapse_uvs_exec(BMesh *bm, BMOperator *op) } } -static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op, BMOperator *optarget, const char *targetmapname) +static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op, + BMOperator *optarget, BMOpSlot *optarget_slot) { BMVert **verts; int verts_len; int i, j, keepvert = 0; - const float dist = BMO_slot_float_get(op, "dist"); + const float dist = BMO_slot_float_get(op->slots_in, "dist"); const float dist3 = dist * 3.0f; /* Test whether keep_verts arg exists and is non-empty */ - if (BMO_slot_exists(op, "keep_verts")) { + if (BMO_slot_exists(op->slots_in, "keep_verts")) { BMOIter oiter; - keepvert = BMO_iter_new(&oiter, bm, op, "keep_verts", BM_VERT) != NULL; + keepvert = BMO_iter_new(&oiter, op->slots_in, "keep_verts", BM_VERT) != NULL; } /* get the verts as an array we can sort */ - verts = BMO_slot_as_arrayN(op, "verts", &verts_len); + verts = BMO_slot_as_arrayN(op->slots_in, "verts", &verts_len); /* sort by vertex coordinates added together */ qsort(verts, verts_len, sizeof(BMVert *), vergaverco); /* Flag keep_verts */ if (keepvert) { - BMO_slot_buffer_flag_enable(bm, op, "keep_verts", BM_VERT, VERT_KEEP); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "keep_verts", BM_VERT, VERT_KEEP); } for (i = 0; i < verts_len; i++) { @@ -547,7 +554,7 @@ static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op, BMOperator *opt BMO_elem_flag_enable(bm, v_other, VERT_DOUBLE); BMO_elem_flag_enable(bm, v_check, VERT_TARGET); - BMO_slot_map_ptr_insert(bm, optarget, targetmapname, v_other, v_check); + BMO_slot_map_ptr_insert(optarget, optarget_slot, v_other, v_check); } } } @@ -558,9 +565,12 @@ static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op, BMOperator *opt void bmo_remove_doubles_exec(BMesh *bm, BMOperator *op) { BMOperator weldop; + BMOpSlot *slot_targetmap; BMO_op_init(bm, &weldop, op->flag, "weld_verts"); - bmesh_find_doubles_common(bm, op, &weldop, "targetmap"); + slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap"); + bmesh_find_doubles_common(bm, op, + &weldop, slot_targetmap); BMO_op_exec(bm, &weldop); BMO_op_finish(bm, &weldop); } @@ -568,7 +578,10 @@ void bmo_remove_doubles_exec(BMesh *bm, BMOperator *op) void bmo_find_doubles_exec(BMesh *bm, BMOperator *op) { - bmesh_find_doubles_common(bm, op, op, "targetmapout"); + BMOpSlot *slot_targetmap_out; + slot_targetmap_out = BMO_slot_get(op->slots_out, "targetmap.out"); + bmesh_find_doubles_common(bm, op, + op, slot_targetmap_out); } void bmo_automerge_exec(BMesh *bm, BMOperator *op) @@ -580,7 +593,7 @@ void bmo_automerge_exec(BMesh *bm, BMOperator *op) /* The "verts" input sent to this op is the set of verts that * can be merged away into any other verts. Mark all other verts * as VERT_KEEP. */ - BMO_slot_buffer_flag_enable(bm, op, "verts", BM_VERT, VERT_IN); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts", BM_VERT, VERT_IN); BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { if (!BMO_elem_flag_test(bm, v, VERT_IN)) { BMO_elem_flag_enable(bm, v, VERT_KEEP); @@ -590,12 +603,14 @@ void bmo_automerge_exec(BMesh *bm, BMOperator *op) /* Search for doubles among all vertices, but only merge non-VERT_KEEP * vertices into VERT_KEEP vertices. */ BMO_op_initf(bm, &findop, op->flag, "find_doubles verts=%av keep_verts=%fv", VERT_KEEP); - BMO_slot_copy(op, &findop, "dist", "dist"); + BMO_slot_copy(op, slots_in, "dist", + &findop, slots_in, "dist"); BMO_op_exec(bm, &findop); /* weld the vertices */ BMO_op_init(bm, &weldop, op->flag, "weld_verts"); - BMO_slot_copy(&findop, &weldop, "targetmapout", "targetmap"); + BMO_slot_copy(&findop, slots_out, "targetmap.out", + &weldop, slots_in, "targetmap"); BMO_op_exec(bm, &weldop); BMO_op_finish(bm, &findop); diff --git a/source/blender/bmesh/operators/bmo_similar.c b/source/blender/bmesh/operators/bmo_similar.c index df03e50d2c4..548e1adf17d 100644 --- a/source/blender/bmesh/operators/bmo_similar.c +++ b/source/blender/bmesh/operators/bmo_similar.c @@ -103,10 +103,10 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op) SimSel_FaceExt *f_ext = NULL; int *indices = NULL; float t_no[3]; /* temporary normal */ - const int type = BMO_slot_int_get(op, "type"); - const float thresh = BMO_slot_float_get(op, "thresh"); + const int type = BMO_slot_int_get(op->slots_in, "type"); + const float thresh = BMO_slot_float_get(op->slots_in, "thresh"); const float thresh_radians = thresh * (float)M_PI; - const int compare = BMO_slot_int_get(op, "compare"); + const int compare = BMO_slot_int_get(op->slots_in, "compare"); /* initial_elem - other_elem */ float delta_fl; @@ -121,7 +121,7 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op) * so the overall complexity will be less than $O(mn)$ where is the total number of selected faces, * and n is the total number of faces */ - BMO_ITER (fs, &fs_iter, bm, op, "faces", BM_FACE) { + BMO_ITER (fs, &fs_iter, op->slots_in, "faces", BM_FACE) { if (!BMO_elem_flag_test(bm, fs, FACE_MARK)) { /* is this really needed ? */ BMO_elem_flag_enable(bm, fs, FACE_MARK); num_sels++; @@ -256,7 +256,7 @@ void bmo_similar_faces_exec(BMesh *bm, BMOperator *op) MEM_freeN(indices); /* transfer all marked faces to the output slot */ - BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, FACE_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_MARK); #undef FACE_MARK } @@ -299,9 +299,9 @@ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op) float angle; int num_sels = 0, num_total = 0; - const int type = BMO_slot_int_get(op, "type"); - const float thresh = BMO_slot_float_get(op, "thresh"); - const int compare = BMO_slot_int_get(op, "compare"); + const int type = BMO_slot_int_get(op->slots_in, "type"); + const float thresh = BMO_slot_float_get(op->slots_in, "thresh"); + const int compare = BMO_slot_int_get(op->slots_in, "compare"); /* initial_elem - other_elem */ float delta_fl; @@ -324,7 +324,7 @@ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op) num_total = BM_mesh_elem_count(bm, BM_EDGE); /* iterate through all selected edges and mark them */ - BMO_ITER (es, &es_iter, bm, op, "edges", BM_EDGE) { + BMO_ITER (es, &es_iter, op->slots_in, "edges", BM_EDGE) { BMO_elem_flag_enable(bm, es, EDGE_MARK); num_sels++; } @@ -474,7 +474,7 @@ void bmo_similar_edges_exec(BMesh *bm, BMOperator *op) MEM_freeN(indices); /* transfer all marked edges to the output slot */ - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, EDGE_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_MARK); #undef EDGE_MARK } @@ -507,10 +507,10 @@ void bmo_similar_verts_exec(BMesh *bm, BMOperator *op) SimSel_VertExt *v_ext = NULL; int *indices = NULL; int num_total = 0, num_sels = 0, i = 0, idx = 0; - const int type = BMO_slot_int_get(op, "type"); - const float thresh = BMO_slot_float_get(op, "thresh"); + const int type = BMO_slot_int_get(op->slots_in, "type"); + const float thresh = BMO_slot_float_get(op->slots_in, "thresh"); const float thresh_radians = thresh * (float)M_PI; - const int compare = BMO_slot_int_get(op, "compare"); + const int compare = BMO_slot_int_get(op->slots_in, "compare"); /* initial_elem - other_elem */ // float delta_fl; @@ -519,7 +519,7 @@ void bmo_similar_verts_exec(BMesh *bm, BMOperator *op) num_total = BM_mesh_elem_count(bm, BM_VERT); /* iterate through all selected edges and mark them */ - BMO_ITER (vs, &vs_iter, bm, op, "verts", BM_VERT) { + BMO_ITER (vs, &vs_iter, op->slots_in, "verts", BM_VERT) { BMO_elem_flag_enable(bm, vs, VERT_MARK); num_sels++; } @@ -608,7 +608,7 @@ void bmo_similar_verts_exec(BMesh *bm, BMOperator *op) MEM_freeN(indices); MEM_freeN(v_ext); - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); #undef VERT_MARK } diff --git a/source/blender/bmesh/operators/bmo_slide.c b/source/blender/bmesh/operators/bmo_slide.c index 6db76119205..9dde2461364 100644 --- a/source/blender/bmesh/operators/bmo_slide.c +++ b/source/blender/bmesh/operators/bmo_slide.c @@ -53,10 +53,10 @@ void bmo_slide_vert_exec(BMesh *bm, BMOperator *op) int selected_edges = 0; /* Get slide amount */ - const float distance_t = BMO_slot_float_get(op, "distance_t"); + const float distance_t = BMO_slot_float_get(op->slots_in, "distance_t"); /* Get start vertex */ - vertex = BMO_iter_new(&oiter, bm, op, "vert", BM_VERT); + vertex = BMO_iter_new(&oiter, op->slots_in, "vert", BM_VERT); if (!vertex) { @@ -68,7 +68,7 @@ void bmo_slide_vert_exec(BMesh *bm, BMOperator *op) } /* Count selected edges */ - BMO_ITER (h, &oiter, bm, op, "edge", BM_VERT | BM_EDGE) { + BMO_ITER (h, &oiter, op->slots_in, "edge", BM_VERT | BM_EDGE) { switch (h->htype) { case BM_EDGE: selected_edges++; @@ -108,7 +108,7 @@ void bmo_slide_vert_exec(BMesh *bm, BMOperator *op) } /* Return the new edge. The same previously marked with VERT_MARK */ - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, VERT_MARK); return; } diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c index 362123e412d..4137c31961c 100644 --- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c +++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c @@ -78,8 +78,8 @@ static void delete_laplacian_system(LaplacianSystem *sys); static void delete_void_pointer(void *data); static void fill_laplacian_matrix(LaplacianSystem *sys); static void memset_laplacian_system(LaplacianSystem *sys, int val); -static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez, int volumepreservation); -static void volume_preservation(BMesh *bm, BMOperator *op, float vini, float vend, int usex, int usey, int usez); +static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez, int preserve_volume); +static void volume_preservation(BMOperator *op, float vini, float vend, int usex, int usey, int usez); static void delete_void_pointer(void *data) { @@ -455,7 +455,7 @@ static float compute_volume(BMesh *bm) return fabs(vol); } -static void volume_preservation(BMesh *bm, BMOperator *op, float vini, float vend, int usex, int usey, int usez) +static void volume_preservation(BMOperator *op, float vini, float vend, int usex, int usey, int usez) { float beta; BMOIter siter; @@ -463,9 +463,9 @@ static void volume_preservation(BMesh *bm, BMOperator *op, float vini, float ven if (vend != 0.0f) { beta = pow(vini / vend, 1.0f / 3.0f); - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { if (usex) { - v->co[0] *= beta; + v->co[0] *= beta; } if (usey) { v->co[1] *= beta; @@ -478,7 +478,7 @@ static void volume_preservation(BMesh *bm, BMOperator *op, float vini, float ven } } -static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez, int volumepreservation) +static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez, int preserve_volume) { int m_vertex_id; float leni, lene; @@ -509,10 +509,10 @@ static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez } } - if (volumepreservation) { + if (preserve_volume) { vini = compute_volume(sys->bm); } - BMO_ITER (v, &siter, sys->bm, sys->op, "verts", BM_VERT) { + BMO_ITER (v, &siter, sys->op->slots_in, "verts", BM_VERT) { m_vertex_id = BM_elem_index_get(v); if (sys->zerola[m_vertex_id] == 0) { if (usex) { @@ -526,9 +526,9 @@ static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez } } } - if (volumepreservation) { + if (preserve_volume) { vend = compute_volume(sys->bm); - volume_preservation(sys->bm, sys->op, vini, vend, usex, usey, usez); + volume_preservation(sys->op, vini, vend, usex, usey, usez); } } @@ -537,7 +537,7 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) { int i; int m_vertex_id; - int usex, usey, usez, volumepreservation; + int usex, usey, usez, preserve_volume; float lambda, lambda_border; float w; BMOIter siter; @@ -552,13 +552,13 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) memset_laplacian_system(sys, 0); BM_mesh_elem_index_ensure(bm, BM_VERT); - lambda = BMO_slot_float_get(op, "lambda"); - lambda_border = BMO_slot_float_get(op, "lambda_border"); + lambda = BMO_slot_float_get(op->slots_in, "lambda"); + lambda_border = BMO_slot_float_get(op->slots_in, "lambda_border"); sys->min_area = 0.00001f; - usex = BMO_slot_bool_get(op, "use_x"); - usey = BMO_slot_bool_get(op, "use_y"); - usez = BMO_slot_bool_get(op, "use_z"); - volumepreservation = BMO_slot_bool_get(op, "volume_preservation"); + usex = BMO_slot_bool_get(op->slots_in, "use_x"); + usey = BMO_slot_bool_get(op->slots_in, "use_y"); + usez = BMO_slot_bool_get(op->slots_in, "use_z"); + preserve_volume = BMO_slot_bool_get(op->slots_in, "preserve_volume"); nlNewContext(); @@ -573,7 +573,7 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) for (i = 0; i < bm->totvert; i++) { nlLockVariable(i); } - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { m_vertex_id = BM_elem_index_get(v); nlUnlockVariable(m_vertex_id); nlSetVariable(0, m_vertex_id, v->co[0]); @@ -583,7 +583,7 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) nlBegin(NL_MATRIX); init_laplacian_matrix(sys); - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { m_vertex_id = BM_elem_index_get(v); nlRightHandSideAdd(0, m_vertex_id, v->co[0]); nlRightHandSideAdd(1, m_vertex_id, v->co[1]); @@ -612,7 +612,7 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) nlEnd(NL_SYSTEM); if (nlSolveAdvanced(NULL, NL_TRUE) ) { - validate_solution(sys, usex, usey, usez, volumepreservation); + validate_solution(sys, usex, usey, usez, preserve_volume); } delete_laplacian_system(sys); diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index f6b9b18d716..f9b6611c88b 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -165,7 +165,7 @@ static void alter_co(BMesh *bm, BMVert *v, BMEdge *UNUSED(origed), const SubDPar } /* apply the new difference to the rest of the shape keys, - * note that this doent take rotations into account, we _could_ support + * note that this dosn't take rotations into account, we _could_ support * this by getting the normals and coords for each shape key and * re-calculate the smooth value for each but this is quite involved. * for now its ok to simply apply the difference IMHO - campbell */ @@ -225,8 +225,9 @@ static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge, BMEdge *oedge, BMVert *ev; float percent, percent2 = 0.0f; - if (BMO_elem_flag_test(bm, edge, EDGE_PERCENT) && totpoint == 1) - percent = BMO_slot_map_float_get(bm, params->op, "edgepercents", edge); + if (BMO_elem_flag_test(bm, edge, EDGE_PERCENT) && totpoint == 1) { + percent = BMO_slot_map_float_get(params->slot_edgepercents, edge); + } else { percent = 1.0f / (float)(totpoint + 1 - curpoint); percent2 = (float)(curpoint + 1) / (float)(totpoint + 1); @@ -717,18 +718,18 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) int use_sphere, cornertype, use_singleedge, use_gridfill; int skey, seed, i, j, matched, a, b, numcuts, totesel; - BMO_slot_buffer_flag_enable(bm, op, "edges", BM_EDGE, SUBD_SPLIT); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, SUBD_SPLIT); - numcuts = BMO_slot_int_get(op, "numcuts"); - seed = BMO_slot_int_get(op, "seed"); - smooth = BMO_slot_float_get(op, "smooth"); - fractal = BMO_slot_float_get(op, "fractal"); - along_normal = BMO_slot_float_get(op, "along_normal"); - cornertype = BMO_slot_int_get(op, "quadcornertype"); - - use_singleedge = BMO_slot_bool_get(op, "use_singleedge"); - use_gridfill = BMO_slot_bool_get(op, "use_gridfill"); - use_sphere = BMO_slot_bool_get(op, "use_sphere"); + numcuts = BMO_slot_int_get(op->slots_in, "cuts"); + seed = BMO_slot_int_get(op->slots_in, "seed"); + smooth = BMO_slot_float_get(op->slots_in, "smooth"); + fractal = BMO_slot_float_get(op->slots_in, "fractal"); + along_normal = BMO_slot_float_get(op->slots_in, "along_normal"); + cornertype = BMO_slot_int_get(op->slots_in, "quad_corner_type"); + + use_singleedge = BMO_slot_bool_get(op->slots_in, "use_singleedge"); + use_gridfill = BMO_slot_bool_get(op->slots_in, "use_gridfill"); + use_sphere = BMO_slot_bool_get(op->slots_in, "use_sphere"); BLI_srandom(seed); @@ -774,10 +775,12 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) } /* first go through and tag edges */ - BMO_slot_buffer_from_enabled_flag(bm, op, "edges", BM_EDGE, SUBD_SPLIT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_in, "edges", BM_EDGE, SUBD_SPLIT); params.numcuts = numcuts; params.op = op; + params.slot_edgepercents = BMO_slot_get(op->slots_in, "edgepercents"); + params.slot_custompatterns = BMO_slot_get(op->slots_in, "custompatterns"); params.smooth = smooth; params.seed = seed; params.fractal = fractal; @@ -790,10 +793,10 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) params.off[1] = (float)BLI_drand() * 200.0f; params.off[2] = (float)BLI_drand() * 200.0f; - BMO_slot_map_to_flag(bm, op, "custompatterns", + BMO_slot_map_to_flag(bm, op->slots_in, "custompatterns", BM_FACE, FACE_CUSTOMFILL); - BMO_slot_map_to_flag(bm, op, "edgepercents", + BMO_slot_map_to_flag(bm, op->slots_in, "edgepercents", BM_EDGE, EDGE_PERCENT); @@ -837,8 +840,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) } if (BMO_elem_flag_test(bm, face, FACE_CUSTOMFILL)) { - pat = BMO_slot_map_data_get(bm, op, - "custompatterns", face); + pat = BMO_slot_map_data_get(params.slot_custompatterns, face); for (i = 0; i < pat->len; i++) { matched = 1; for (j = 0; j < pat->len; j++) { @@ -910,11 +912,11 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) } } - einput = BMO_slot_get(op, "edges"); + einput = BMO_slot_get(op->slots_in, "edges"); /* go through and split edges */ for (i = 0; i < einput->len; i++) { - edge = ((BMEdge **)einput->data.p)[i]; + edge = einput->data.buf[i]; bm_subdivide_multicut(bm, edge, ¶ms, edge->v1, edge->v2); } @@ -1075,10 +1077,10 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) BLI_array_free(loops_split); BLI_array_free(loops); - BMO_slot_buffer_from_enabled_flag(bm, op, "outinner", BM_ALL, ELE_INNER); - BMO_slot_buffer_from_enabled_flag(bm, op, "outsplit", BM_ALL, ELE_SPLIT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_inner.out", BM_ALL, ELE_INNER); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_split.out", BM_ALL, ELE_SPLIT); - BMO_slot_buffer_from_enabled_flag(bm, op, "geomout", BM_ALL, ELE_INNER | ELE_SPLIT | SUBD_SPLIT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL, ELE_INNER | ELE_SPLIT | SUBD_SPLIT); } /* editmesh-emulating function */ @@ -1095,8 +1097,8 @@ void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, BMO_op_initf(bm, &op, BMO_FLAG_DEFAULTS, "subdivide_edges edges=%he " "smooth=%f fractal=%f along_normal=%f " - "numcuts=%i " - "quadcornertype=%i " + "cuts=%i " + "quad_corner_type=%i " "use_singleedge=%b use_gridfill=%b " "seed=%i", edge_hflag, @@ -1112,7 +1114,7 @@ void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, BMOIter iter; BMElem *ele; - for (ele = BMO_iter_new(&iter, bm, &op, "outinner", BM_EDGE | BM_VERT); ele; ele = BMO_iter_step(&iter)) { + 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); } } @@ -1123,7 +1125,7 @@ void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, /* deselect input */ BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, FALSE); - for (ele = BMO_iter_new(&iter, bm, &op, "outinner", BM_EDGE | BM_VERT); ele; ele = BMO_iter_step(&iter)) { + 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); if (ele->head.htype == BM_VERT) { @@ -1158,8 +1160,9 @@ void bmo_bisect_edges_exec(BMesh *bm, BMOperator *op) SubDParams params = {0}; int skey; - params.numcuts = BMO_slot_int_get(op, "numcuts"); + params.numcuts = BMO_slot_int_get(op->slots_in, "cuts"); params.op = op; + params.slot_edgepercents = BMO_slot_get(op->slots_in, "edgepercents"); BM_data_layer_add(bm, &bm->vdata, CD_SHAPEKEY); skey = CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY) - 1; @@ -1167,11 +1170,11 @@ void bmo_bisect_edges_exec(BMesh *bm, BMOperator *op) params.origkey = skey; /* go through and split edges */ - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { bm_subdivide_multicut(bm, e, ¶ms, e->v1, e->v2); } - BMO_slot_buffer_from_enabled_flag(bm, op, "outsplit", BM_ALL, ELE_SPLIT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_split.out", BM_ALL, ELE_SPLIT); BM_data_layer_free_n(bm, &bm->vdata, CD_SHAPEKEY, skey); } diff --git a/source/blender/bmesh/operators/bmo_subdivide.h b/source/blender/bmesh/operators/bmo_subdivide.h index d4b926b9275..d0676508917 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.h +++ b/source/blender/bmesh/operators/bmo_subdivide.h @@ -39,6 +39,8 @@ typedef struct SubDParams { int seed; int origkey; /* shapekey holding displaced vertex coordinates for current geometry */ BMOperator *op; + BMOpSlot *slot_edgepercents; /* BMO_slot_get(params->op->slots_in, "edgepercents"); */ + BMOpSlot *slot_custompatterns; /* BMO_slot_get(params->op->slots_in, "custompatterns"); */ float off[3]; } SubDParams; diff --git a/source/blender/bmesh/operators/bmo_symmetrize.c b/source/blender/bmesh/operators/bmo_symmetrize.c index a428405fb8b..8c440cae83e 100644 --- a/source/blender/bmesh/operators/bmo_symmetrize.c +++ b/source/blender/bmesh/operators/bmo_symmetrize.c @@ -96,7 +96,7 @@ static void symm_verts_mirror(Symm *symm) symm->vert_symm_map = BLI_ghash_ptr_new(AT); - BMO_ITER (src_v, &oiter, symm->bm, symm->op, "input", BM_VERT) { + BMO_ITER (src_v, &oiter, symm->op->slots_in, "input", BM_VERT) { SymmSide side = symm_co_side(symm, src_v->co); float co[3]; @@ -145,7 +145,7 @@ static void symm_split_asymmetric_edges(Symm *symm) symm->edge_split_map = BLI_ghash_ptr_new(AT); - BMO_ITER (e, &oiter, symm->bm, symm->op, "input", BM_EDGE) { + BMO_ITER (e, &oiter, symm->op->slots_in, "input", BM_EDGE) { float flipped[3]; copy_v3_v3(flipped, e->v1->co); @@ -195,7 +195,7 @@ static void symm_mirror_edges(Symm *symm) BMOIter oiter; BMEdge *e; - BMO_ITER (e, &oiter, symm->bm, symm->op, "input", BM_EDGE) { + BMO_ITER (e, &oiter, symm->op->slots_in, "input", BM_EDGE) { BMVert *v1 = NULL, *v2 = NULL; BMEdge *e_new; @@ -448,7 +448,7 @@ static void symm_mirror_polygons(Symm *symm) BLI_array_declare(fv); BLI_array_declare(fe); - BMO_ITER (f, &oiter, symm->bm, symm->op, "input", BM_FACE) { + BMO_ITER (f, &oiter, symm->op->slots_in, "input", BM_FACE) { BMIter iter; BMLoop *l; int mirror_all = TRUE, ignore_all = TRUE; @@ -607,7 +607,7 @@ static void symm_kill_unused(Symm *symm) BMVert *v; /* Kill unused edges */ - BMO_ITER (e, &oiter, symm->bm, symm->op, "input", BM_EDGE) { + BMO_ITER (e, &oiter, symm->op->slots_in, "input", BM_EDGE) { const int crosses = symm_edge_crosses_axis(symm, e); const int symmetric = (crosses && (!BLI_ghash_haskey(symm->edge_split_map, e))); @@ -617,13 +617,13 @@ static void symm_kill_unused(Symm *symm) !symmetric) { /* The edge might be used by a face outside the input set */ - if (BM_edge_face_count(e) == 0) + if (BM_edge_is_wire(e)) BM_edge_kill(symm->bm, e); } } /* Kill unused vertices */ - BMO_ITER (v, &oiter, symm->bm, symm->op, "input", BM_VERT) { + BMO_ITER (v, &oiter, symm->op->slots_in, "input", BM_VERT) { if (symm_co_side(symm, v->co) == SYMM_SIDE_KILL) { if (BM_vert_edge_count(v) == 0) BM_vert_kill(symm->bm, v); @@ -634,7 +634,7 @@ static void symm_kill_unused(Symm *symm) void bmo_symmetrize_exec(BMesh *bm, BMOperator *op) { Symm symm; - BMO_SymmDirection direction = BMO_slot_int_get(op, "direction"); + BMO_SymmDirection direction = BMO_slot_int_get(op->slots_in, "direction"); symm.bm = bm; symm.op = op; @@ -658,6 +658,6 @@ void bmo_symmetrize_exec(BMesh *bm, BMOperator *op) BLI_ghash_free(symm.vert_symm_map, NULL, NULL); BLI_ghash_free(symm.edge_split_map, NULL, NULL); - BMO_slot_buffer_from_enabled_flag(bm, op, "geomout", BM_ALL, - SYMM_OUTPUT_GEOM); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", + BM_ALL, SYMM_OUTPUT_GEOM); } diff --git a/source/blender/bmesh/operators/bmo_triangulate.c b/source/blender/bmesh/operators/bmo_triangulate.c index de876477e5a..775fa0cb60d 100644 --- a/source/blender/bmesh/operators/bmo_triangulate.c +++ b/source/blender/bmesh/operators/bmo_triangulate.c @@ -52,9 +52,10 @@ 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, "use_beauty"); + const int use_beauty = BMO_slot_bool_get(op->slots_in, "use_beauty"); + BMOpSlot *slot_facemap_out = BMO_slot_get(op->slots_out, "facemap.out"); - for (face = BMO_iter_new(&siter, bm, op, "faces", BM_FACE); face; face = BMO_iter_step(&siter)) { + for (face = BMO_iter_new(&siter, op->slots_in, "faces", BM_FACE); face; face = BMO_iter_step(&siter)) { BLI_array_empty(projectverts); BLI_array_empty(newfaces); @@ -64,16 +65,14 @@ void bmo_triangulate_exec(BMesh *bm, BMOperator *op) BM_face_triangulate(bm, face, projectverts, EDGE_NEW, FACE_NEW, newfaces, use_beauty); - BMO_slot_map_ptr_insert(bm, op, "facemap", face, face); + BMO_slot_map_ptr_insert(op, slot_facemap_out, face, face); for (i = 0; newfaces[i]; i++) { - BMO_slot_map_ptr_insert(bm, op, "facemap", - newfaces[i], face); - + BMO_slot_map_ptr_insert(op, slot_facemap_out, newfaces[i], face); } } - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, EDGE_NEW); - BMO_slot_buffer_from_enabled_flag(bm, op, "faceout", BM_FACE, FACE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_NEW); BLI_array_free(projectverts); BLI_array_free(newfaces); @@ -87,9 +86,9 @@ void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op) BMEdge *e; int stop = 0; - BMO_slot_buffer_flag_enable(bm, op, "constrain_edges", BM_EDGE, EDGE_MARK); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "constrain_edges", BM_EDGE, EDGE_MARK); - BMO_ITER (f, &siter, bm, op, "faces", BM_FACE) { + BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) { if (f->len == 3) { BMO_elem_flag_enable(bm, f, FACE_MARK); } @@ -152,7 +151,7 @@ void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_buffer_from_enabled_flag(bm, op, "geomout", BM_EDGE | BM_FACE, ELE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_EDGE | BM_FACE, ELE_NEW); } void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op) @@ -170,7 +169,7 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op) BLI_scanfill_begin(&sf_ctx); - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { BMO_elem_flag_enable(bm, e, EDGE_MARK); if (!BLI_smallhash_haskey(&hash, (uintptr_t)e->v1)) { @@ -214,8 +213,8 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op) /* clean up fill */ BMO_op_initf(bm, &bmop, op->flag, "beautify_fill faces=%ff constrain_edges=%fe", ELE_NEW, EDGE_MARK); BMO_op_exec(bm, &bmop); - BMO_slot_buffer_flag_enable(bm, &bmop, "geomout", BM_FACE | BM_EDGE, ELE_NEW); + BMO_slot_buffer_flag_enable(bm, bmop.slots_out, "geom.out", BM_FACE | BM_EDGE, ELE_NEW); BMO_op_finish(bm, &bmop); - BMO_slot_buffer_from_enabled_flag(bm, op, "geomout", BM_EDGE | BM_FACE, ELE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_EDGE | BM_FACE, ELE_NEW); } diff --git a/source/blender/bmesh/operators/bmo_unsubdivide.c b/source/blender/bmesh/operators/bmo_unsubdivide.c index 3d44feac380..fae7db3d175 100644 --- a/source/blender/bmesh/operators/bmo_unsubdivide.c +++ b/source/blender/bmesh/operators/bmo_unsubdivide.c @@ -39,10 +39,10 @@ void bmo_unsubdivide_exec(BMesh *bm, BMOperator *op) BMVert *v; BMIter iter; - const int iterations = max_ii(1, BMO_slot_int_get(op, "iterations")); + const int iterations = max_ii(1, BMO_slot_int_get(op->slots_in, "iterations")); - BMOpSlot *vinput = BMO_slot_get(op, "verts"); - BMVert **vinput_arr = (BMVert **)vinput->data.p; + BMOpSlot *vinput = BMO_slot_get(op->slots_in, "verts"); + BMVert **vinput_arr = (BMVert **)vinput->data.buf; int v_index; /* tag verts */ diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c index aa514a5c0a7..d56b2ca0d73 100644 --- a/source/blender/bmesh/operators/bmo_utils.c +++ b/source/blender/bmesh/operators/bmo_utils.c @@ -45,21 +45,21 @@ void bmo_create_vert_exec(BMesh *bm, BMOperator *op) { float vec[3]; - BMO_slot_vec_get(op, "co", vec); + BMO_slot_vec_get(op->slots_in, "co", vec); BMO_elem_flag_enable(bm, BM_vert_create(bm, vec, NULL), 1); - BMO_slot_buffer_from_enabled_flag(bm, op, "newvertout", BM_VERT, 1); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "vert.out", BM_VERT, 1); } -void bmo_transform_exec(BMesh *bm, BMOperator *op) +void bmo_transform_exec(BMesh *UNUSED(bm), BMOperator *op) { BMOIter iter; BMVert *v; float mat[4][4]; - BMO_slot_mat4_get(op, "mat", mat); + BMO_slot_mat4_get(op->slots_in, "mat", mat); - BMO_ITER (v, &iter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &iter, op->slots_in, "verts", BM_VERT) { mul_m4_v3(mat, v->co); } } @@ -68,7 +68,7 @@ void bmo_translate_exec(BMesh *bm, BMOperator *op) { float mat[4][4], vec[3]; - BMO_slot_vec_get(op, "vec", vec); + BMO_slot_vec_get(op->slots_in, "vec", vec); unit_m4(mat); copy_v3_v3(mat[3], vec); @@ -80,7 +80,7 @@ void bmo_scale_exec(BMesh *bm, BMOperator *op) { float mat[3][3], vec[3]; - BMO_slot_vec_get(op, "vec", vec); + BMO_slot_vec_get(op->slots_in, "vec", vec); unit_m3(mat); mat[0][0] = vec[0]; @@ -94,7 +94,7 @@ void bmo_rotate_exec(BMesh *bm, BMOperator *op) { float vec[3]; - BMO_slot_vec_get(op, "cent", vec); + BMO_slot_vec_get(op->slots_in, "cent", vec); /* there has to be a proper matrix way to do this, but * this is how editmesh did it and I'm too tired to think @@ -113,7 +113,7 @@ void bmo_reverse_faces_exec(BMesh *bm, BMOperator *op) BMOIter siter; BMFace *f; - BMO_ITER (f, &siter, bm, op, "faces", BM_FACE) { + BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) { BM_face_normal_flip(bm, f); } } @@ -122,8 +122,8 @@ void bmo_rotate_edges_exec(BMesh *bm, BMOperator *op) { BMOIter siter; BMEdge *e, *e2; - int ccw = BMO_slot_bool_get(op, "ccw"); - int is_single = BMO_slot_buffer_count(bm, op, "edges") == 1; + 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; short check_flag = is_single ? BM_EDGEROT_CHECK_EXISTS : BM_EDGEROT_CHECK_EXISTS | BM_EDGEROT_CHECK_DEGENERATE; @@ -131,7 +131,7 @@ void bmo_rotate_edges_exec(BMesh *bm, BMOperator *op) #define EDGE_OUT 1 #define FACE_TAINT 1 - BMO_ITER (e, &siter, bm, op, "edges", BM_EDGE) { + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { /** * this ends up being called twice, could add option to not to call check in * #BM_edge_rotate to get some extra speed */ @@ -144,7 +144,7 @@ void bmo_rotate_edges_exec(BMesh *bm, BMOperator *op) BMO_elem_flag_test(bm, fb, FACE_TAINT) == FALSE) { - if (!(e2 = BM_edge_rotate(bm, e, ccw, check_flag))) { + if (!(e2 = BM_edge_rotate(bm, e, use_ccw, check_flag))) { #if 0 BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Could not rotate edge"); return; @@ -162,7 +162,7 @@ void bmo_rotate_edges_exec(BMesh *bm, BMOperator *op) } } - BMO_slot_buffer_from_enabled_flag(bm, op, "edgeout", BM_EDGE, EDGE_OUT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EDGE_OUT); #undef EDGE_OUT #undef FACE_TAINT @@ -180,7 +180,7 @@ static void bmo_region_extend_extend(BMesh *bm, BMOperator *op, int usefaces) BMOIter siter; if (!usefaces) { - BMO_ITER (v, &siter, bm, op, "geom", BM_VERT) { + 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)) if (!BMO_elem_flag_test(bm, e, SEL_ORIG)) @@ -202,7 +202,7 @@ static void bmo_region_extend_extend(BMesh *bm, BMOperator *op, int usefaces) BMFace *f, *f2; BMLoop *l; - BMO_ITER (f, &siter, bm, op, "geom", BM_FACE) { + BMO_ITER (f, &siter, op->slots_in, "geom", BM_FACE) { BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { BM_ITER_ELEM (f2, &fiter, l->e, BM_FACES_OF_EDGE) { if (!BM_elem_flag_test(f2, BM_ELEM_HIDDEN)) { @@ -224,7 +224,7 @@ static void bmo_region_extend_constrict(BMesh *bm, BMOperator *op, int usefaces) BMOIter siter; if (!usefaces) { - BMO_ITER (v, &siter, bm, op, "geom", BM_VERT) { + 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)) if (!BMO_elem_flag_test(bm, e, SEL_ORIG)) @@ -248,7 +248,7 @@ static void bmo_region_extend_constrict(BMesh *bm, BMOperator *op, int usefaces) BMFace *f, *f2; BMLoop *l; - BMO_ITER (f, &siter, bm, op, "geom", BM_FACE) { + BMO_ITER (f, &siter, op->slots_in, "geom", BM_FACE) { BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { BM_ITER_ELEM (f2, &fiter, l->e, BM_FACES_OF_EDGE) { if (!BM_elem_flag_test(f2, BM_ELEM_HIDDEN)) { @@ -265,17 +265,17 @@ 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, "use_faces"); - int constrict = BMO_slot_bool_get(op, "constrict"); + int use_faces = BMO_slot_bool_get(op->slots_in, "use_faces"); + int constrict = BMO_slot_bool_get(op->slots_in, "use_constrict"); - BMO_slot_buffer_flag_enable(bm, op, "geom", BM_ALL, SEL_ORIG); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "geom", BM_ALL, SEL_ORIG); if (constrict) bmo_region_extend_constrict(bm, op, use_faces); else bmo_region_extend_extend(bm, op, use_faces); - BMO_slot_buffer_from_enabled_flag(bm, op, "geomout", BM_ALL, SEL_FLAG); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL, SEL_FLAG); } /********* righthand faces implementation ****** */ @@ -314,15 +314,15 @@ 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, "do_flip"); + int i, i_max, flagflip = BMO_slot_bool_get(op->slots_in, "use_flip"); startf = NULL; maxx = -1.0e10; - BMO_slot_buffer_flag_enable(bm, op, "faces", BM_FACE, FACE_FLAG); + BMO_slot_buffer_flag_enable(bm, op->slots_in, "faces", BM_FACE, FACE_FLAG); /* find a starting face */ - BMO_ITER (f, &siter, bm, op, "faces", BM_FACE) { + BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) { /* clear dirty flag */ BM_elem_flag_disable(f, BM_ELEM_TAG); @@ -405,7 +405,7 @@ void bmo_recalc_face_normals_exec(BMesh *bm, BMOperator *op) BLI_array_free(fstack); /* check if we have faces yet to do. if so, recurse */ - BMO_ITER (f, &siter, bm, op, "faces", BM_FACE) { + BMO_ITER (f, &siter, op->slots_in, "faces", BM_FACE) { if (!BMO_elem_flag_test(bm, f, FACE_VIS)) { bmo_recalc_face_normals_exec(bm, op); break; @@ -413,7 +413,7 @@ void bmo_recalc_face_normals_exec(BMesh *bm, BMOperator *op) } } -void bmo_smooth_vert_exec(BMesh *bm, BMOperator *op) +void bmo_smooth_vert_exec(BMesh *UNUSED(bm), BMOperator *op) { BMOIter siter; BMIter iter; @@ -421,20 +421,20 @@ void bmo_smooth_vert_exec(BMesh *bm, BMOperator *op) BMEdge *e; BLI_array_declare(cos); float (*cos)[3] = NULL; - float *co, *co2, clipdist = BMO_slot_float_get(op, "clipdist"); + float *co, *co2, clip_dist = BMO_slot_float_get(op->slots_in, "clip_dist"); int i, j, clipx, clipy, clipz; int xaxis, yaxis, zaxis; - clipx = BMO_slot_bool_get(op, "mirror_clip_x"); - clipy = BMO_slot_bool_get(op, "mirror_clip_y"); - clipz = BMO_slot_bool_get(op, "mirror_clip_z"); + clipx = BMO_slot_bool_get(op->slots_in, "mirror_clip_x"); + clipy = BMO_slot_bool_get(op->slots_in, "mirror_clip_y"); + clipz = BMO_slot_bool_get(op->slots_in, "mirror_clip_z"); - xaxis = BMO_slot_bool_get(op, "use_axis_x"); - yaxis = BMO_slot_bool_get(op, "use_axis_y"); - zaxis = BMO_slot_bool_get(op, "use_axis_z"); + xaxis = BMO_slot_bool_get(op->slots_in, "use_axis_x"); + yaxis = BMO_slot_bool_get(op->slots_in, "use_axis_y"); + zaxis = BMO_slot_bool_get(op->slots_in, "use_axis_z"); i = 0; - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { BLI_array_grow_one(cos); co = cos[i]; @@ -454,18 +454,18 @@ void bmo_smooth_vert_exec(BMesh *bm, BMOperator *op) mul_v3_fl(co, 1.0f / (float)j); mid_v3_v3v3(co, co, v->co); - if (clipx && fabsf(v->co[0]) <= clipdist) + if (clipx && fabsf(v->co[0]) <= clip_dist) co[0] = 0.0f; - if (clipy && fabsf(v->co[1]) <= clipdist) + if (clipy && fabsf(v->co[1]) <= clip_dist) co[1] = 0.0f; - if (clipz && fabsf(v->co[2]) <= clipdist) + if (clipz && fabsf(v->co[2]) <= clip_dist) co[2] = 0.0f; i++; } i = 0; - BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) { + BMO_ITER (v, &siter, op->slots_in, "verts", BM_VERT) { if (xaxis) v->co[0] = cos[i][0]; if (yaxis) @@ -489,11 +489,11 @@ void bmo_rotate_uvs_exec(BMesh *bm, BMOperator *op) BMFace *fs; /* current face */ BMIter l_iter; /* iteration loop */ - int dir = BMO_slot_int_get(op, "dir"); + const int use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw"); - BMO_ITER (fs, &fs_iter, bm, op, "faces", BM_FACE) { + BMO_ITER (fs, &fs_iter, op->slots_in, "faces", BM_FACE) { if (CustomData_has_layer(&(bm->ldata), CD_MLOOPUV)) { - if (dir == DIRECTION_CW) { /* 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 */ @@ -517,7 +517,7 @@ void bmo_rotate_uvs_exec(BMesh *bm, BMOperator *op) copy_v2_v2(f_luv->uv, p_uv); } - else if (dir == DIRECTION_CCW) { /* counter loop direction */ + else { /* counter loop direction */ BMLoop *lf; /* current face loops */ MLoopUV *p_luv; /* previous loop uv */ MLoopUV *luv; @@ -556,7 +556,7 @@ void bmo_reverse_uvs_exec(BMesh *bm, BMOperator *op) BLI_array_declare(uvs); float (*uvs)[2] = NULL; - BMO_ITER (fs, &fs_iter, bm, op, "faces", BM_FACE) { + BMO_ITER (fs, &fs_iter, op->slots_in, "faces", BM_FACE) { if (CustomData_has_layer(&(bm->ldata), CD_MLOOPUV)) { BMLoop *lf; /* current face loops */ int i; @@ -594,11 +594,11 @@ void bmo_rotate_colors_exec(BMesh *bm, BMOperator *op) BMFace *fs; /* current face */ BMIter l_iter; /* iteration loop */ - int dir = BMO_slot_int_get(op, "dir"); + const int use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw"); - BMO_ITER (fs, &fs_iter, bm, op, "faces", BM_FACE) { + BMO_ITER (fs, &fs_iter, op->slots_in, "faces", BM_FACE) { if (CustomData_has_layer(&(bm->ldata), CD_MLOOPCOL)) { - if (dir == DIRECTION_CW) { /* 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 */ @@ -622,7 +622,7 @@ void bmo_rotate_colors_exec(BMesh *bm, BMOperator *op) *f_lcol = p_col; } - else if (dir == DIRECTION_CCW) { /* counter loop direction */ + else { /* counter loop direction */ BMLoop *lf; /* current face loops */ MLoopCol *p_lcol; /* previous loop color */ MLoopCol *lcol; @@ -661,7 +661,7 @@ void bmo_reverse_colors_exec(BMesh *bm, BMOperator *op) BLI_array_declare(cols); MLoopCol *cols = NULL; - BMO_ITER (fs, &fs_iter, bm, op, "faces", BM_FACE) { + BMO_ITER (fs, &fs_iter, op->slots_in, "faces", BM_FACE) { if (CustomData_has_layer(&(bm->ldata), CD_MLOOPCOL)) { BMLoop *lf; /* current face loops */ int i; @@ -710,12 +710,13 @@ void bmo_shortest_path_exec(BMesh *bm, BMOperator *op) ElemNode *vert_list = NULL; int num_total = 0 /*, num_sels = 0 */, i = 0; - const int type = BMO_slot_int_get(op, "type"); + const int type = BMO_slot_int_get(op->slots_in, "type"); - BMO_ITER (vs, &vs_iter, bm, op, "startv", BM_VERT) { + /* BMESH_TODO use BMO_slot_buffer_elem_first here? */ + BMO_ITER (vs, &vs_iter, op->slots_in, "startv", BM_VERT) { sv = vs; } - BMO_ITER (vs, &vs_iter, bm, op, "endv", BM_VERT) { + BMO_ITER (vs, &vs_iter, op->slots_in, "endv", BM_VERT) { ev = vs; } @@ -795,5 +796,5 @@ void bmo_shortest_path_exec(BMesh *bm, BMOperator *op) BLI_heap_free(h, NULL); MEM_freeN(vert_list); - BMO_slot_buffer_from_enabled_flag(bm, op, "vertout", BM_VERT, VERT_MARK); + 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_wireframe.c b/source/blender/bmesh/operators/bmo_wireframe.c index d572a1c5863..532145ab129 100644 --- a/source/blender/bmesh/operators/bmo_wireframe.c +++ b/source/blender/bmesh/operators/bmo_wireframe.c @@ -77,39 +77,60 @@ static void bm_vert_boundary_tangent(BMVert *v, float r_no[3], float r_no_face[3 } } - l_a = bm_edge_tag_faceloop(e_a); - l_b = bm_edge_tag_faceloop(e_b); + if (e_a && e_b) { + l_a = bm_edge_tag_faceloop(e_a); + l_b = bm_edge_tag_faceloop(e_b); + + /* average edge face normal */ + add_v3_v3v3(no_face, l_a->f->no, l_b->f->no); + + /* average edge direction */ + v_a = BM_edge_other_vert(e_a, v); + v_b = BM_edge_other_vert(e_b, v); + + sub_v3_v3v3(tvec_a, v->co, v_a->co); + sub_v3_v3v3(tvec_b, v_b->co, v->co); + normalize_v3(tvec_a); + normalize_v3(tvec_b); + add_v3_v3v3(no_edge, tvec_a, tvec_b); /* not unit length but this is ok */ + + /* check are we flipped the right way */ + BM_edge_calc_face_tangent(e_a, l_a, tvec_a); + BM_edge_calc_face_tangent(e_b, l_b, tvec_b); + add_v3_v3(tvec_a, tvec_b); + + *r_va_other = v_a; + *r_vb_other = v_b; + } + else { + /* degenerate case - vertex connects a boundary edged face to other faces, + * so we have only one boundary face - only use it for calculations */ + l_a = bm_edge_tag_faceloop(e_a); - /* average edge face normal */ - add_v3_v3v3(no_face, l_a->f->no, l_b->f->no); + copy_v3_v3(no_face, l_a->f->no); - /* average edge direction */ - v_a = BM_edge_other_vert(e_a, v); - v_b = BM_edge_other_vert(e_b, v); + /* edge direction */ + v_a = BM_edge_other_vert(e_a, v); + v_b = NULL; - sub_v3_v3v3(tvec_a, v->co, v_a->co); - sub_v3_v3v3(tvec_b, v_b->co, v->co); - normalize_v3(tvec_a); - normalize_v3(tvec_b); - add_v3_v3v3(no_edge, tvec_a, tvec_b); /* not unit length but this is ok */ + sub_v3_v3v3(no_edge, v->co, v_a->co); + /* check are we flipped the right way */ + BM_edge_calc_face_tangent(e_a, l_a, tvec_a); + + *r_va_other = NULL; + *r_vb_other = NULL; + } /* find the normal */ cross_v3_v3v3(r_no, no_edge, no_face); normalize_v3(r_no); - /* check are we flipped the right way */ - BM_edge_calc_face_tangent(e_a, l_a, tvec_a); - BM_edge_calc_face_tangent(e_b, l_b, tvec_b); - add_v3_v3(tvec_a, tvec_b); - if (dot_v3v3(r_no, tvec_a) > 0.0f) { negate_v3(r_no); } copy_v3_v3(r_no_face, no_face); - *r_va_other = v_a; - *r_vb_other = v_b; } /* check if we are the only tagged loop-face around this edge */ @@ -134,12 +155,12 @@ 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, "use_boundary"); - const int use_even_offset = BMO_slot_bool_get(op, "use_even_offset"); - const int use_relative_offset = BMO_slot_bool_get(op, "use_relative_offset"); - const int use_crease = (BMO_slot_bool_get(op, "use_crease") && + 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, "thickness"); + const float depth = BMO_slot_float_get(op->slots_in, "thickness"); const float inset = depth; const int totvert_orig = bm->totvert; @@ -184,7 +205,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); - BMO_ITER (f_src, &oiter, bm, op, "faces", BM_FACE) { + BMO_ITER (f_src, &oiter, op->slots_in, "faces", BM_FACE) { verts_loop_tot += f_src->len; BM_elem_flag_enable(f_src, BM_ELEM_TAG); BM_ITER_ELEM (l, &itersub, f_src, BM_LOOPS_OF_FACE) { @@ -230,7 +251,7 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) verts_loop = MEM_mallocN(sizeof(BMVert **) * verts_loop_tot, __func__); verts_loop_tot = 0; /* count up again */ - BMO_ITER (f_src, &oiter, bm, op, "faces", BM_FACE) { + BMO_ITER (f_src, &oiter, op->slots_in, "faces", BM_FACE) { BM_ITER_ELEM (l, &itersub, f_src, BM_LOOPS_OF_FACE) { BM_elem_index_set(l, verts_loop_tot); /* set_loop */ @@ -269,10 +290,12 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) /* similar to code above but different angle calc */ fac = inset; if (use_even_offset) { - fac *= shell_angle_to_dist(((float)M_PI - angle_on_axis_v3v3v3_v3(va_other->co, - l_pair[i]->v->co, - vb_other->co, - no_face)) * 0.5f); + if (va_other) { /* for verts with only one boundary edge - this will be NULL */ + fac *= shell_angle_to_dist(((float)M_PI - angle_on_axis_v3v3v3_v3(va_other->co, + l_pair[i]->v->co, + vb_other->co, + no_face)) * 0.5f); + } } if (use_relative_offset) { fac *= verts_relfac[BM_elem_index_get(l_pair[i]->v)]; @@ -288,7 +311,7 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) } } - BMO_ITER (f_src, &oiter, bm, op, "faces", BM_FACE) { + BMO_ITER (f_src, &oiter, op->slots_in, "faces", BM_FACE) { BM_elem_flag_disable(f_src, BM_ELEM_TAG); BM_ITER_ELEM (l, &itersub, f_src, BM_LOOPS_OF_FACE) { BMFace *f_new; @@ -400,5 +423,5 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) MEM_freeN(verts_pos); MEM_freeN(verts_loop); - BMO_slot_buffer_from_enabled_hflag(bm, op, "faceout", BM_FACE, BM_ELEM_TAG); + BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG); } diff --git a/source/blender/bmesh/tools/BME_bevel.c b/source/blender/bmesh/tools/BME_bevel.c index a632a4446ed..cdfd8372d61 100644 --- a/source/blender/bmesh/tools/BME_bevel.c +++ b/source/blender/bmesh/tools/BME_bevel.c @@ -1110,10 +1110,13 @@ BMesh *BME_bevel(BMesh *bm, float value, int res, int options, int defgrp_index, td = BME_init_transdata(BLI_MEMARENA_STD_BUFSIZE); /* recursion math courtesy of Martin Poirier (theeth) */ for (i = 0; i < res - 1; i++) { - if (i == 0) fac += 1.0 / 3.0; else fac += 1.0 / (3.0 * i * 2.0); + if (i == 0) fac += 1.0 / 3.0; + else fac += 1.0 / (3.0 * i * 2.0); } d = 1.0 / fac; + BM_mesh_elem_toolflags_ensure(bm); + for (i = 0; i < res || (res == 0 && i == 0); i++) { BMO_push(bm, NULL); BME_bevel_initialize(bm, options, defgrp_index, angle, td); diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c new file mode 100644 index 00000000000..4d8fc8e9c3f --- /dev/null +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -0,0 +1,1749 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): + * Joseph Eagar, + * Aleksandr Mokhov, + * Howard Trickey, + * Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/bmesh/tools/bmesh_bevel.c + * \ingroup bmesh + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_array.h" +#include "BLI_math.h" +#include "BLI_memarena.h" + +#include "BKE_customdata.h" + +#include "bmesh.h" + + + +/* experemental - Campbell */ +// #define USE_ALTERNATE_ADJ + +#define BEVEL_EPSILON 1e-6 + +/* for testing */ +// #pragma GCC diagnostic error "-Wpadded" + +/* Constructed vertex, sometimes later instantiated as BMVert */ +typedef struct NewVert { + BMVert *v; + float co[3]; +// int _pad; +} NewVert; + +struct BoundVert; + +/* Data for one end of an edge involved in a bevel */ +typedef struct EdgeHalf { + struct EdgeHalf *next, *prev; /* in CCW order */ + BMEdge *e; /* original mesh edge */ + BMFace *fprev; /* face between this edge and previous, if any */ + BMFace *fnext; /* face between this edge and next, if any */ + struct BoundVert *leftv; /* left boundary vert (looking along edge to end) */ + struct BoundVert *rightv; /* right boundary vert, if beveled */ + short is_bev; /* is this edge beveled? */ + short is_rev; /* is e->v2 the vertex at this end? */ + int seg; /* how many segments for the bevel */ + float offset; /* offset for this edge */ +// int _pad; +} EdgeHalf; + +/* An element in a cyclic boundary of a Vertex Mesh (VMesh) */ +typedef struct BoundVert { + struct BoundVert *next, *prev; /* in CCW order */ + NewVert nv; + EdgeHalf *efirst; /* first of edges attached here: in CCW order */ + EdgeHalf *elast; + EdgeHalf *ebev; /* beveled edge whose left side is attached here, if any */ + int index; /* used for vmesh indexing */ +// int _pad; +} BoundVert; + +/* Mesh structure replacing a vertex */ +typedef struct VMesh { + NewVert *mesh; /* allocated array - size and structure depends on kind */ + BoundVert *boundstart; /* start of boundary double-linked list */ + int count; /* number of vertices in the boundary */ + int seg; /* common # of segments for segmented edges */ + enum { + M_NONE, /* no polygon mesh needed */ + M_POLY, /* a simple polygon */ + M_ADJ, /* "adjacent edges" mesh pattern */ +// M_CROSS, /* "cross edges" mesh pattern */ + M_TRI_FAN, /* a simple polygon - fan filled */ + M_QUAD_STRIP, /* a simple polygon - cut into paralelle strips */ + } mesh_kind; +// int _pad; +} VMesh; + +/* Data for a vertex involved in a bevel */ +typedef struct BevVert { + BMVert *v; /* original mesh vertex */ + int edgecount; /* total number of edges around the vertex */ + int selcount; /* number of selected edges around the vertex */ + EdgeHalf *edges; /* array of size edgecount; CCW order from vertex normal side */ + VMesh *vmesh; /* mesh structure for replacing vertex */ +} BevVert; + +/* Bevel parameters and state */ +typedef struct BevelParams { + /* hash of BevVert for each vertex involved in bevel + * GHash: (key=(BMVert *), value=(BevVert *)) */ + GHash *vert_hash; + MemArena *mem_arena; /* use for all allocs while bevel runs, if we need to free we can switch to mempool */ + + float offset; /* blender units to offset each side of a beveled edge */ + int seg; /* number of segments in beveled edge profile */ +} BevelParams; + +// #pragma GCC diagnostic ignored "-Wpadded" + +//#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. */ +static BoundVert *add_new_bound_vert(MemArena *mem_arena, VMesh *vm, const float co[3]) +{ + BoundVert *ans = (BoundVert *)BLI_memarena_alloc(mem_arena, sizeof(BoundVert)); + + copy_v3_v3(ans->nv.co, co); + if (!vm->boundstart) { + ans->index = 0; + vm->boundstart = ans; + ans->next = ans->prev = ans; + } + else { + BoundVert *tail = vm->boundstart->prev; + ans->index = tail->index + 1; + ans->prev = tail; + ans->next = vm->boundstart; + tail->next = ans; + vm->boundstart->prev = ans; + } + vm->count++; + return ans; +} + +/* Mesh verts are indexed (i, j, k) where + * i = boundvert index (0 <= i < nv) + * j = ring index (0 <= j <= ns2) + * k = segment index (0 <= k <= ns) + * Not all of these are used, and some will share BMVerts */ +static NewVert *mesh_vert(VMesh *vm, int i, int j, int k) +{ + int nj = (vm->seg / 2) + 1; + int nk = vm->seg + 1; + + return &vm->mesh[i * nk * nj + j * nk + k]; +} + +static void create_mesh_bmvert(BMesh *bm, VMesh *vm, int i, int j, int k, BMVert *eg) +{ + NewVert *nv = mesh_vert(vm, i, j, k); + nv->v = BM_vert_create(bm, nv->co, eg); +} + +static void copy_mesh_vert(VMesh *vm, int ito, int jto, int kto, + int ifrom, int jfrom, int kfrom) +{ + NewVert *nvto, *nvfrom; + + nvto = mesh_vert(vm, ito, jto, kto); + nvfrom = mesh_vert(vm, ifrom, jfrom, kfrom); + nvto->v = nvfrom->v; + copy_v3_v3(nvto->co, nvfrom->co); +} + +/* find the EdgeHalf in bv's array that has edge bme */ +static EdgeHalf *find_edge_half(BevVert *bv, BMEdge *bme) +{ + int i; + + for (i = 0; i < bv->edgecount; i++) { + if (bv->edges[i].e == bme) + return &bv->edges[i]; + } + return NULL; +} + +/* Return the next EdgeHalf after from_e that is beveled. + * If from_e is NULL, find the first beveled edge. */ +static EdgeHalf *next_bev(BevVert *bv, EdgeHalf *from_e) +{ + EdgeHalf *e; + + if (from_e == NULL) + from_e = &bv->edges[bv->edgecount - 1]; + e = from_e; + do { + if (e->is_bev) { + return e; + } + } while ((e = e->next) != from_e); + return NULL; +} + +/* find the BevVert corresponding to BMVert bmv */ +static BevVert *find_bevvert(BevelParams *bp, BMVert *bmv) +{ + return BLI_ghash_lookup(bp->vert_hash, bmv); +} + +/* Return a good respresentative face (for materials, etc.) for faces + * created around/near BoundVert v */ +static BMFace *boundvert_rep_face(BoundVert *v) +{ + BMFace *fans = NULL; + BMFace *firstf = NULL; + BMEdge *e1, *e2; + BMFace *f1, *f2; + BMIter iter1, iter2; + + BLI_assert(v->efirst != NULL && v->elast != NULL); + e1 = v->efirst->e; + e2 = v->elast->e; + BM_ITER_ELEM (f1, &iter1, e1, BM_FACES_OF_EDGE) { + if (!firstf) + firstf = f1; + BM_ITER_ELEM (f2, &iter2, e2, BM_FACES_OF_EDGE) { + if (f1 == f2) { + fans = f1; + break; + } + } + } + if (!fans) + fans = firstf; + + return fans; +} + +/** + * Make ngon from verts alone. + * Make sure to properly copy face attributes and do custom data interpolation from + * example face, facerep. + * + * \note ALL face creation goes through this function, this is important to keep! + */ +static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, const int totv, BMFace *facerep) +{ + BMIter iter; + BMLoop *l; + BMFace *f; + + if (totv == 3) { + f = BM_face_create_quad_tri_v(bm, vert_arr, 3, facerep, FALSE); + } + else if (totv == 4) { + f = BM_face_create_quad_tri_v(bm, vert_arr, 4, facerep, FALSE); + } + else { + int i; + BMEdge **ee = NULL; + BLI_array_staticdeclare(ee, BM_DEFAULT_NGON_STACK_SIZE); + + BLI_array_grow_items(ee, totv); + for (i = 0; i < totv; i++) { + ee[i] = BM_edge_create(bm, vert_arr[i], vert_arr[(i + 1) % totv], NULL, TRUE); + } + f = BM_face_create_ngon(bm, vert_arr[0], vert_arr[1], ee, totv, FALSE); + BLI_array_free(ee); + } + if (facerep && f) { + int has_mdisps = CustomData_has_layer(&bm->ldata, CD_MDISPS); + BM_elem_attrs_copy(bm, bm, facerep, f); + BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) { + BM_loop_interp_from_face(bm, l, facerep, TRUE, TRUE); + if (has_mdisps) + BM_loop_interp_multires(bm, l, facerep); + } + } + + /* not essential for bevels own internal logic, + * this is done so the operator can select newly created faces */ + if (f) { + BM_elem_flag_enable(f, BM_ELEM_TAG); + } + + return f; +} + +static BMFace *bev_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, + BMFace *facerep) +{ + BMVert *varr[4] = {v1, v2, v3, v4}; + return bev_create_ngon(bm, varr, v4 ? 4 : 3, facerep); +} + +/* + * Calculate the meeting point between the offset edges for e1 and e2, putting answer in meetco. + * e1 and e2 share vertex v and face f (may be NULL) and viewed from the normal side of + * the bevel vertex, e1 precedes e2 in CCW order. + * If on_right is true, offset edge is on right of both edges, where e1 enters v and + * e2 leave it. If on_right is false, then the offset edge is on the left. + * When offsets are equal, the new point is on the edge bisector, with length offset/sin(angle/2), + * but if the offsets are not equal (allowing for this, as bevel modifier has edge weights that may + * lead to different offsets) then meeting point can be found be intersecting offset lines. + */ +static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, + int on_right, float meetco[3]) +{ + float dir1[3], dir2[3], norm_v[3], norm_perp1[3], norm_perp2[3], + off1a[3], off1b[3], off2a[3], off2b[3], isect2[3]; + + /* get direction vectors for two offset lines */ + sub_v3_v3v3(dir1, v->co, BM_edge_other_vert(e1->e, v)->co); + sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co); + + /* get normal to plane where meet point should be */ + cross_v3_v3v3(norm_v, dir2, dir1); + normalize_v3(norm_v); + if (!on_right) + negate_v3(norm_v); + if (is_zero_v3(norm_v)) { + /* 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 */ + if (f) + copy_v3_v3(norm_v, f->no); + else + copy_v3_v3(norm_v, v->no); + cross_v3_v3v3(norm_perp1, dir1, norm_v); + normalize_v3(norm_perp1); + copy_v3_v3(off1a, v->co); + madd_v3_v3fl(off1a, norm_perp1, e1->offset); + copy_v3_v3(meetco, off1a); + } + else { + /* get vectors perp to each edge, perp to norm_v, and pointing into face */ + if (f) { + copy_v3_v3(norm_v, f->no); + } + cross_v3_v3v3(norm_perp1, dir1, norm_v); + cross_v3_v3v3(norm_perp2, dir2, norm_v); + normalize_v3(norm_perp1); + normalize_v3(norm_perp2); + + /* get points that are offset distances from each line, then another point on each line */ + copy_v3_v3(off1a, v->co); + madd_v3_v3fl(off1a, norm_perp1, e1->offset); + add_v3_v3v3(off1b, off1a, dir1); + copy_v3_v3(off2a, v->co); + madd_v3_v3fl(off2a, norm_perp2, e2->offset); + add_v3_v3v3(off2b, off2a, dir2); + + /* intersect the lines; by construction they should be on the same plane and not parallel */ + if (!isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2)) { + BLI_assert(!"offset_meet failure"); + copy_v3_v3(meetco, off1a); /* just to do something */ + } + } +} + +/* Like offset_meet, but here f1 and f2 must not be NULL and give the + * planes in which to run the offset lines. They may not meet exactly, + * but the line intersection routine will find the closest approach point. */ +static void offset_in_two_planes(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, + BMFace *f1, BMFace *f2, float meetco[3]) +{ + float dir1[3], dir2[3], norm_perp1[3], norm_perp2[3], + off1a[3], off1b[3], off2a[3], off2b[3], isect2[3]; + + BLI_assert(f1 != NULL && f2 != NULL); + + /* get direction vectors for two offset lines */ + sub_v3_v3v3(dir1, v->co, BM_edge_other_vert(e1->e, v)->co); + sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co); + + /* get directions into offset planes */ + cross_v3_v3v3(norm_perp1, dir1, f1->no); + normalize_v3(norm_perp1); + cross_v3_v3v3(norm_perp2, dir2, f2->no); + normalize_v3(norm_perp2); + + /* get points that are offset distances from each line, then another point on each line */ + copy_v3_v3(off1a, v->co); + madd_v3_v3fl(off1a, norm_perp1, e1->offset); + add_v3_v3v3(off1b, off1a, dir1); + copy_v3_v3(off2a, v->co); + madd_v3_v3fl(off2a, norm_perp2, e2->offset); + add_v3_v3v3(off2b, off2a, dir2); + + if (angle_v3v3(dir1, dir2) < 100.0f * (float)BEVEL_EPSILON) { + /* lines are parallel; off1a is a good meet point */ + copy_v3_v3(meetco, off1a); + } + else if (!isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2)) { + /* another test says they are parallel */ + copy_v3_v3(meetco, off1a); + } +} + +/* Offset by e->offset in plane with normal plane_no, on left if left==TRUE, + * else on right. If no is NULL, choose an arbitrary plane different + * from eh's direction. */ +static void offset_in_plane(EdgeHalf *e, const float plane_no[3], int left, float r[3]) +{ + float dir[3], no[3]; + BMVert *v; + + v = e->is_rev ? e->e->v1 : e->e->v2; + + sub_v3_v3v3(dir, BM_edge_other_vert(e->e, v)->co, v->co); + normalize_v3(dir); + if (plane_no) { + copy_v3_v3(no, plane_no); + } + else { + zero_v3(no); + if (fabs(dir[0]) < fabs(dir[1])) + no[0] = 1.0f; + else + no[1] = 1.0f; + } + if (left) + cross_v3_v3v3(r, no, dir); + else + cross_v3_v3v3(r, dir, no); + normalize_v3(r); + mul_v3_fl(r, e->offset); +} + +/* Calculate coordinates of a point a distance d from v on e->e and return it in slideco */ +static void slide_dist(EdgeHalf *e, BMVert *v, float d, float slideco[3]) +{ + float dir[3], len; + + 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); + copy_v3_v3(slideco, v->co); + madd_v3_v3fl(slideco, dir, -d); +} + +/* Calculate the point on e where line (co_a, co_b) comes closest to and return it in projco */ +static void project_to_edge(BMEdge *e, const float co_a[3], const float co_b[3], float projco[3]) +{ + float otherco[3]; + + if (!isect_line_line_v3(e->v1->co, e->v2->co, co_a, co_b, projco, otherco)) { + BLI_assert(!"project meet failure"); + copy_v3_v3(projco, e->v1->co); + } +} + +/* return 1 if a and b are in CCW order on the normal side of f, + * and -1 if they are reversed, and 0 if there is no shared face f */ +static int bev_ccw_test(BMEdge *a, BMEdge *b, BMFace *f) +{ + BMLoop *la, *lb; + + if (!f) + return 0; + la = BM_face_edge_share_loop(f, a); + lb = BM_face_edge_share_loop(f, b); + if (!la || !lb) + return 0; + 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 */ + +/* + * calculation of points on the round profile + * r - result, coordinate of point on round profile + * method: + * Inscribe a circle in angle va - v -vb + * such that it touches the arms at offset from v. + * Rotate the center-va segment by (i/n) of the + * angle va - center -vb, and put the endpoint + * of that segment in r. + */ +static void get_point_on_round_profile(float r_co[3], float offset, int k, int count, + const float va[3], const float v[3], const float vb[3]) +{ + float vva[3], vvb[3], angle, center[3], rv[3], axis[3], co[3]; + + sub_v3_v3v3(vva, va, v); + sub_v3_v3v3(vvb, vb, v); + normalize_v3(vva); + normalize_v3(vvb); + angle = angle_normalized_v3v3(vva, vvb); + + add_v3_v3v3(center, vva, vvb); + normalize_v3(center); + mul_v3_fl(center, offset * (1.0f / cosf(0.5f * angle))); + add_v3_v3(center, v); /* coordinates of the center of the inscribed circle */ + + + sub_v3_v3v3(rv, va, center); /* radius vector */ + + + sub_v3_v3v3(co, v, center); + cross_v3_v3v3(axis, rv, co); /* calculate axis */ + + sub_v3_v3v3(vva, va, center); + sub_v3_v3v3(vvb, vb, center); + angle = angle_v3v3(vva, vvb); + + rotate_v3_v3v3fl(co, rv, axis, angle * (float)k / (float)count); + + add_v3_v3(co, center); + copy_v3_v3(r_co, co); +} + +/* + * Find the point (/n) of the way around the round profile for e, + * where start point is va, midarc point is vmid, and end point is vb. + * Return the answer in profileco. + * Method: + * Adjust va and vb (along edge direction) so that they are perpendicular + * to edge at v, then use get_point_on_round_profile, then project + * back onto original va - vmid - vb plane. + * If va, vmid, and vb are all on the same plane, just interpolate between va and vb. + */ +static void get_point_on_round_edge(EdgeHalf *e, int k, + const float va[3], const float vmid[3], const float vb[3], + float r_co[3]) +{ + float vva[3], vvb[3], point[3], dir[3], vaadj[3], vbadj[3], p2[3], pn[3]; + int n = e->seg; + + sub_v3_v3v3(vva, va, vmid); + sub_v3_v3v3(vvb, vb, vmid); + if (e->is_rev) + sub_v3_v3v3(dir, e->e->v1->co, e->e->v2->co); + else + sub_v3_v3v3(dir, e->e->v2->co, e->e->v1->co); + normalize_v3(dir); + if (fabsf(angle_v3v3(vva, vvb) - (float)M_PI) > (float)BEVEL_EPSILON) { + copy_v3_v3(vaadj, va); + madd_v3_v3fl(vaadj, dir, -len_v3(vva) * cosf(angle_v3v3(vva, dir))); + copy_v3_v3(vbadj, vb); + madd_v3_v3fl(vbadj, dir, -len_v3(vvb) * cosf(angle_v3v3(vvb, dir))); + + get_point_on_round_profile(point, e->offset, k, n, vaadj, vmid, vbadj); + + add_v3_v3v3(p2, point, dir); + cross_v3_v3v3(pn, vva, vvb); + if (!isect_line_plane_v3(r_co, point, p2, vmid, pn, 0)) { + /* TODO: track down why this sometimes fails */ + copy_v3_v3(r_co, point); + } + } + else { + /* planar case */ + interp_v3_v3v3(r_co, va, vb, (float)k / (float)n); + } +} + +#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. + * Doesn't make the actual BMVerts */ +static void build_boundary(MemArena *mem_arena, BevVert *bv) +{ + EdgeHalf *efirst, *e; + BoundVert *v; + VMesh *vm; + float co[3]; + const float *no; + float lastd; + + e = efirst = next_bev(bv, NULL); + vm = bv->vmesh; + + BLI_assert(bv->edgecount >= 2); /* since bevel edges incident to 2 faces */ + + if (bv->edgecount == 2 && bv->selcount == 1) { + /* special case: beveled edge meets non-beveled one at valence 2 vert */ + no = e->fprev ? e->fprev->no : (e->fnext ? e->fnext->no : NULL); + offset_in_plane(e, no, TRUE, co); + v = add_new_bound_vert(mem_arena, vm, co); + v->efirst = v->elast = v->ebev = e; + e->leftv = v; + no = e->fnext ? e->fnext->no : (e->fprev ? e->fprev->no : NULL); + offset_in_plane(e, no, FALSE, co); + v = add_new_bound_vert(mem_arena, vm, co); + v->efirst = v->elast = e; + e->rightv = v; + /* make artifical extra point along unbeveled edge, and form triangle */ + slide_dist(e->next, bv->v, e->offset, co); + v = add_new_bound_vert(mem_arena, vm, co); + v->efirst = v->elast = e->next; + vm->mesh_kind = M_POLY; + return; + } + + lastd = e->offset; + vm->boundstart = NULL; + do { + if (e->is_bev) { + /* handle only left side of beveled edge e here: next iteration should do right side */ + if (e->prev->is_bev) { + BLI_assert(e->prev != e); /* see: wire edge special case */ + offset_meet(e->prev, e, bv->v, e->fprev, TRUE, co); + v = add_new_bound_vert(mem_arena, vm, co); + v->efirst = e->prev; + v->elast = v->ebev = e; + e->leftv = v; + e->prev->rightv = v; + } + else { + /* e->prev is not beveled */ + if (e->prev->prev->is_bev) { + BLI_assert(e->prev->prev != e); /* see: edgecount 2, selcount 1 case */ + /* find meet point between e->prev->prev and e and attach e->prev there */ + /* TODO: fix case when one or both faces in following are NULL */ + offset_in_two_planes(e->prev->prev, e, bv->v, + e->prev->prev->fnext, e->fprev, co); + v = add_new_bound_vert(mem_arena, vm, co); + v->efirst = e->prev->prev; + v->elast = v->ebev = e; + e->leftv = v; + e->prev->leftv = v; + e->prev->prev->rightv = v; + } + else { + /* neither e->prev nor e->prev->prev are beveled: make on-edge on e->prev */ + offset_meet(e->prev, e, bv->v, e->fprev, TRUE, co); + v = add_new_bound_vert(mem_arena, vm, co); + v->efirst = e->prev; + v->elast = v->ebev = e; + e->leftv = v; + e->prev->leftv = v; + } + } + lastd = len_v3v3(bv->v->co, v->nv.co); + } + else { + /* e is not beveled */ + if (e->next->is_bev) { + /* next iteration will place e between beveled previous and next edges */ + /* do nothing... */ + } + else if (e->prev->is_bev) { + /* on-edge meet between e->prev and e */ + offset_meet(e->prev, e, bv->v, e->fprev, TRUE, co); + v = add_new_bound_vert(mem_arena, vm, co); + v->efirst = e->prev; + v->elast = e; + e->leftv = v; + e->prev->rightv = v; + } + else { + /* None of e->prev, e, e->next are beveled. + * could either leave alone or add slide points to make + * one polygon around bv->v. For now, we choose latter. + * Could slide to make an even bevel plane but for now will + * just use last distance a meet point moved from bv->v. */ + slide_dist(e, bv->v, lastd, co); + v = add_new_bound_vert(mem_arena, vm, co); + v->efirst = v->elast = e; + e->leftv = v; + } + } + } while ((e = e->next) != efirst); + + BLI_assert(vm->count >= 2); + if (vm->count == 2 && bv->edgecount == 3) { + vm->mesh_kind = M_NONE; + } + else if (bv->selcount == 2) { + vm->mesh_kind = M_QUAD_STRIP; + } + else if (efirst->seg == 1 || bv->selcount == 1) { + if (vm->count == 3 && bv->selcount == 1) { + vm->mesh_kind = M_TRI_FAN; + } + else { + vm->mesh_kind = M_POLY; + } + } + else { + vm->mesh_kind = M_ADJ; + } + /* TODO: if vm->count == 4 and bv->selcount == 4, use M_CROSS pattern */ +} + +/* + * 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 pattern, + * then make the BMVerts and the new faces. */ +static void bevel_build_rings(BMesh *bm, BevVert *bv) +{ + int k, ring, i, n, ns, ns2, nn; + VMesh *vm = bv->vmesh; + BoundVert *v, *vprev, *vnext; + NewVert *nv, *nvprev, *nvnext; + BMVert *bmv, *bmv1, *bmv2, *bmv3, *bmv4; + BMFace *f; + float co[3], coa[3], cob[3], midco[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; + BLI_assert(n > 2 && ns > 1); + /* Make initial rings, going between points on neighbors. + * After this loop, will have coords for all (i, r, k) where + * BoundVert for i has a bevel, 0 <= r <= ns2, 0 <= k <= ns */ + for (ring = 1; ring <= ns2; ring++) { + v = vm->boundstart; + + do { + i = v->index; + if (v->ebev) { + /* get points coords of points a and b, on outer rings + * of prev and next edges, k away from this edge */ + vprev = v->prev; + vnext = v->next; + + if (vprev->ebev) + nvprev = mesh_vert(vm, vprev->index, 0, ns - ring); + else + nvprev = mesh_vert(vm, vprev->index, 0, ns); + copy_v3_v3(coa, nvprev->co); + nv = mesh_vert(vm, i, ring, 0); + copy_v3_v3(nv->co, coa); + nv->v = nvprev->v; + + if (vnext->ebev) + nvnext = mesh_vert(vm, vnext->index, 0, ring); + else + nvnext = mesh_vert(vm, vnext->index, 0, 0); + copy_v3_v3(cob, nvnext->co); + nv = mesh_vert(vm, i, ring, ns); + 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); + + for (k = 1; k < ns; k++) { + get_point_on_round_edge(v->ebev, k, coa, midco, cob, co); + copy_v3_v3(mesh_vert(vm, i, ring, k)->co, co); + } +#endif + } + } while ((v = v->next) != vm->boundstart); + } + + /* Now make sure cross points of rings share coordinates and vertices. + * After this loop, will have BMVerts for all (i, r, k) where + * i is for a BoundVert that is beveled and has either a predecessor or + * successor BoundVert beveled too, and + * for odd ns: 0 <= r <= ns2, 0 <= k <= ns + * for even ns: 0 <= r < ns2, 0 <= k <= ns except k=ns2 */ + v = vm->boundstart; + do { + i = v->index; + if (v->ebev) { + vprev = v->prev; + vnext = v->next; + if (vprev->ebev) { + for (ring = 1; ring <= ns2; ring++) { + for (k = 1; k <= ns2; k++) { + if (ns % 2 == 0 && (k == ns2 || ring == ns2)) + continue; /* center line is special case: do after the rest are done */ + nv = mesh_vert(vm, i, ring, k); + nvprev = mesh_vert(vm, vprev->index, k, ns - ring); + mid_v3_v3v3(co, nv->co, nvprev->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); + } + } + if (!vprev->prev->ebev) { + for (ring = 1; ring <= ns2; ring++) { + for (k = 1; k <= ns2; k++) { + if (ns % 2 == 0 && (k == ns2 || ring == ns2)) + continue; + create_mesh_bmvert(bm, vm, vprev->index, ring, k, bv->v); + } + } + } + if (!vnext->ebev) { + for (ring = 1; ring <= ns2; ring++) { + for (k = ns - ns2; k < ns; k++) { + if (ns % 2 == 0 && (k == ns2 || ring == ns2)) + continue; + create_mesh_bmvert(bm, vm, i, ring, k, bv->v); + } + } + } + } + } + } while ((v = v->next) != vm->boundstart); + + if (ns % 2 == 0) { + /* Do special case center lines. + * This loop makes verts for (i, ns2, k) for 1 <= k <= ns-1, k!=ns2 + * and for (i, r, ns2) for 1 <= r <= ns2-1, + * whenever i is in a sequence of at least two beveled verts */ + v = vm->boundstart; + do { + i = v->index; + if (v->ebev) { + vprev = v->prev; + vnext = v->next; + for (k = 1; k < ns2; k++) { + nv = mesh_vert(vm, i, k, ns2); + if (vprev->ebev) + nvprev = mesh_vert(vm, vprev->index, ns2, ns - k); + if (vnext->ebev) + nvnext = mesh_vert(vm, vnext->index, ns2, k); + if (vprev->ebev && vnext->ebev) { + mid_v3_v3v3v3(co, nvprev->co, nv->co, nvnext->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); + + } + else if (vprev->ebev) { + mid_v3_v3v3(co, nvprev->co, nv->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); + + create_mesh_bmvert(bm, vm, i, ns2, ns - k, bv->v); + } + else if (vnext->ebev) { + mid_v3_v3v3(co, nv->co, nvnext->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); + + create_mesh_bmvert(bm, vm, i, ns2, k, bv->v); + } + } + } + } while ((v = v->next) != vm->boundstart); + + /* center point need to be average of all centers of rings */ + /* TODO: this is wrong if not all verts have ebev: could have + * several disconnected sections of mesh. */ + zero_v3(midco); + nn = 0; + v = vm->boundstart; + do { + i = v->index; + if (v->ebev) { + nv = mesh_vert(vm, i, ns2, ns2); + add_v3_v3(midco, nv->co); + nn++; + } + } while ((v = v->next) != vm->boundstart); + mul_v3_fl(midco, 1.0f / nn); + bmv = BM_vert_create(bm, midco, NULL); + v = vm->boundstart; + do { + i = v->index; + if (v->ebev) { + nv = mesh_vert(vm, i, ns2, ns2); + copy_v3_v3(nv->co, midco); + nv->v = bmv; + } + } while ((v = v->next) != vm->boundstart); + } + + /* Make the ring quads */ + for (ring = 0; ring < ns2; ring++) { + v = vm->boundstart; + do { + i = v->index; + f = boundvert_rep_face(v); + if (v->ebev && (v->prev->ebev || v->next->ebev)) { + for (k = 0; k < ns2 + (ns % 2); k++) { + bmv1 = mesh_vert(vm, i, ring, k)->v; + bmv2 = mesh_vert(vm, i, ring, k + 1)->v; + bmv3 = mesh_vert(vm, i, ring + 1, k + 1)->v; + bmv4 = mesh_vert(vm, i, ring + 1, k)->v; + BLI_assert(bmv1 && bmv2 && bmv3 && bmv4); + if (bmv3 == bmv4 || bmv1 == bmv4) + bmv4 = NULL; + bev_create_quad_tri(bm, bmv1, bmv2, bmv3, bmv4, f); + } + } + else if (v->prev->ebev && v->prev->prev->ebev) { + /* finish off a sequence of beveled edges */ + i = v->prev->index; + f = boundvert_rep_face(v->prev); + for (k = ns2 + (ns % 2); k < ns; k++) { + bmv1 = mesh_vert(vm, i, ring, k)->v; + bmv2 = mesh_vert(vm, i, ring, k + 1)->v; + bmv3 = mesh_vert(vm, i, ring + 1, k + 1)->v; + bmv4 = mesh_vert(vm, i, ring + 1, k)->v; + BLI_assert(bmv1 && bmv2 && bmv3 && bmv4); + if (bmv2 == bmv3) { + bmv3 = bmv4; + bmv4 = NULL; + } + bev_create_quad_tri(bm, bmv1, bmv2, bmv3, bmv4, f); + } + } + } while ((v = v->next) != vm->boundstart); + } + + /* Make center ngon if odd number of segments and fully beveled */ + if (ns % 2 == 1 && vm->count == bv->selcount) { + BMVert **vv = NULL; + BLI_array_declare(vv); + + v = vm->boundstart; + do { + i = v->index; + BLI_assert(v->ebev); + 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); + } + + /* Make 'rest-of-vmesh' polygon if not fully beveled */ + if (vm->count > bv->selcount) { + int j; + BMVert **vv = NULL; + BLI_array_declare(vv); + + v = vm->boundstart; + f = boundvert_rep_face(v); + j = 0; + do { + i = v->index; + if (v->ebev) { + if (!v->prev->ebev) { + for (k = 0; k < ns2; k++) { + bmv1 = mesh_vert(vm, i, ns2, k)->v; + if (!bmv1) + bmv1 = mesh_vert(vm, i, 0, k)->v; + if (!(j > 0 && bmv1 == vv[j - 1])) { + BLI_assert(bmv1 != NULL); + BLI_array_append(vv, bmv1); + j++; + } + } + } + bmv1 = mesh_vert(vm, i, ns2, ns2)->v; + if (!bmv1) + bmv1 = mesh_vert(vm, i, 0, ns2)->v; + if (!(j > 0 && bmv1 == vv[j - 1])) { + BLI_assert(bmv1 != NULL); + BLI_array_append(vv, bmv1); + j++; + } + if (!v->next->ebev) { + for (k = ns - ns2; k < ns; k++) { + bmv1 = mesh_vert(vm, i, ns2, k)->v; + if (!bmv1) + bmv1 = mesh_vert(vm, i, 0, k)->v; + if (!(j > 0 && bmv1 == vv[j - 1])) { + BLI_assert(bmv1 != NULL); + BLI_array_append(vv, bmv1); + j++; + } + } + } + } + else { + BLI_assert(mesh_vert(vm, i, 0, 0)->v != NULL); + BLI_array_append(vv, mesh_vert(vm, i, 0, 0)->v); + j++; + } + } while ((v = v->next) != vm->boundstart); + if (vv[0] == vv[j - 1]) + j--; + bev_create_ngon(bm, vv, j, f); + + BLI_array_free(vv); + } +} + +static BMFace *bevel_build_poly_ex(BMesh *bm, BevVert *bv) +{ + BMFace *f; + int n, k; + VMesh *vm = bv->vmesh; + BoundVert *v; + BMVert **vv = NULL; + BLI_array_declare(vv); + + v = vm->boundstart; + n = 0; + do { + /* accumulate vertices for vertex ngon */ + BLI_array_append(vv, v->nv.v); + n++; + if (v->ebev && v->ebev->seg > 1) { + for (k = 1; k < v->ebev->seg; k++) { + BLI_array_append(vv, mesh_vert(vm, v->index, 0, k)->v); + n++; + } + } + } while ((v = v->next) != vm->boundstart); + if (n > 2) { + f = bev_create_ngon(bm, vv, n, boundvert_rep_face(v)); + } + else { + f = NULL; + } + BLI_array_free(vv); + return f; +} + +static void bevel_build_poly(BMesh *bm, BevVert *bv) +{ + bevel_build_poly_ex(bm, bv); +} + +static void bevel_build_trifan(BMesh *bm, BevVert *bv) +{ + BMFace *f; + BLI_assert(next_bev(bv, NULL)->seg == 1 || bv->selcount == 1); + + f = bevel_build_poly_ex(bm, bv); + + if (f) { + /* we have a polygon which we know starts at the previous vertex, make it into a fan */ + BMLoop *l_fan = BM_FACE_FIRST_LOOP(f)->prev; + BMVert *v_fan = l_fan->v; + + while (f->len > 3) { + BMLoop *l_new; + BMFace *f_new; + BLI_assert(v_fan == l_fan->v); + f_new = BM_face_split(bm, f, l_fan->v, l_fan->next->next->v, &l_new, NULL, FALSE); + + if (f_new->len > f->len) { + f = f_new; + if (l_new->v == v_fan) { l_fan = l_new; } + else if (l_new->next->v == v_fan) { l_fan = l_new->next; } + else if (l_new->prev->v == v_fan) { l_fan = l_new->prev; } + else { BLI_assert(0); } + } + else { + if (l_fan->v == v_fan) { l_fan = l_fan; } + else if (l_fan->next->v == v_fan) { l_fan = l_fan->next; } + else if (l_fan->prev->v == v_fan) { l_fan = l_fan->prev; } + else { BLI_assert(0); } + } + } + } +} + +static void bevel_build_quadstrip(BMesh *bm, BevVert *bv) +{ + BMFace *f; + BLI_assert(bv->selcount == 2); + + f = bevel_build_poly_ex(bm, bv); + + if (f) { + /* we have a polygon which we know starts at this vertex, make it into strips */ + EdgeHalf *eh_a = bv->vmesh->boundstart->elast; + EdgeHalf *eh_b = next_bev(bv, eh_a->next); /* since (selcount == 2) we know this is valid */ + BMLoop *l_a = BM_face_vert_share_loop(f, eh_a->rightv->nv.v); + BMLoop *l_b = BM_face_vert_share_loop(f, eh_b->leftv->nv.v); + int seg_count = bv->vmesh->seg; /* ensure we don't walk past the segments */ + + if (l_a == l_b) { + /* step once around if we hit the same loop */ + l_a = l_a->prev; + l_b = l_b->next; + seg_count--; + } + + BLI_assert(l_a != l_b); + + while (f->len > 4) { + BMLoop *l_new; + BLI_assert(l_a->f == f); + BLI_assert(l_b->f == f); + + BM_face_split(bm, f, l_a->v, l_b->v, &l_new, NULL, FALSE); + if (seg_count-- == 0) { + break; + } + + /* turns out we don't need this, + * because of how BM_face_split works we always get the loop of the next face */ +#if 0 + if (l_new->f->len < l_new->radial_next->f->len) { + l_new = l_new->radial_next; + } +#endif + f = l_new->f; + + /* walk around the new face to get the next verts to split */ + l_a = l_new->prev; + l_b = l_new->next->next; + } + } +} + +/* Given that the boundary is built, now make the actual BMVerts + * for the boundary and the interior of the vertex mesh. */ +static void build_vmesh(MemArena *mem_arena, BMesh *bm, BevVert *bv) +{ + VMesh *vm = bv->vmesh; + 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; + ns2 = ns / 2; + + vm->mesh = (NewVert *)BLI_memarena_alloc(mem_arena, n * (ns2 + 1) * (ns + 1) * sizeof(NewVert)); + + /* special case: two beveled ends welded together */ + weld = (bv->selcount == 2) && (vm->count == 2); + weld1 = weld2 = NULL; /* will hold two BoundVerts involved in weld */ + + /* make (i, 0, 0) mesh verts for all i */ + v = vm->boundstart; + do { + i = v->index; + copy_v3_v3(mesh_vert(vm, i, 0, 0)->co, v->nv.co); + create_mesh_bmvert(bm, vm, i, 0, 0, bv->v); + v->nv.v = mesh_vert(vm, i, 0, 0)->v; + if (weld && v->ebev) { + if (!weld1) + weld1 = v; + else + weld2 = v; + } + } while ((v = v->next) != vm->boundstart); + + /* copy other ends to (i, 0, ns) for all i, and fill in profiles for beveled edges */ + v = vm->boundstart; + do { + 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); + for (k = 1; k < ns; k++) { + get_point_on_round_edge(v->ebev, k, va, midco, vb, co); + copy_v3_v3(mesh_vert(vm, i, 0, k)->co, co); + if (!weld) + create_mesh_bmvert(bm, vm, i, 0, k, bv->v); + } +#endif /* !USE_ALTERNATE_ADJ */ + } + } while ((v = v->next) != vm->boundstart); + + if (weld) { + vm->mesh_kind = M_NONE; + for (k = 1; k < ns; k++) { + va = mesh_vert(vm, weld1->index, 0, k)->co; + vb = mesh_vert(vm, weld2->index, 0, ns - k)->co; + mid_v3_v3v3(co, va, vb); + copy_v3_v3(mesh_vert(vm, weld1->index, 0, k)->co, co); + create_mesh_bmvert(bm, vm, weld1->index, 0, k, bv->v); + } + for (k = 1; k < ns; k++) + copy_mesh_vert(vm, weld2->index, 0, ns - k, weld1->index, 0, k); + } + + switch (vm->mesh_kind) { + case M_NONE: + /* do nothing */ + break; + case M_POLY: + bevel_build_poly(bm, bv); + break; + case M_ADJ: + bevel_build_rings(bm, bv); + break; + case M_TRI_FAN: + bevel_build_trifan(bm, bv); + break; + case M_QUAD_STRIP: + bevel_build_quadstrip(bm, bv); + break; + } +} + +/* take care, this flag isn't cleared before use, it just so happens that its not set */ +#define BM_BEVEL_EDGE_TAG_ENABLE(bme) BM_elem_flag_enable( (bme)->l, BM_ELEM_TAG) +#define BM_BEVEL_EDGE_TAG_DISABLE(bme) BM_elem_flag_disable( (bme)->l, BM_ELEM_TAG) +#define BM_BEVEL_EDGE_TAG_TEST(bme) BM_elem_flag_test( (bme)->l, BM_ELEM_TAG) + +/* + * Construction around the vertex + */ +static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v) +{ + BMEdge *bme; + BevVert *bv; + BMEdge *bme2, *unflagged_bme; + BMFace *f; + BMIter iter, iter2; + EdgeHalf *e; + int i, found_shared_face, ccw_test_sum; + int nsel = 0; + int ntot = 0; + + /* Gather input selected edges. + * Only bevel selected edges that have exactly two incident faces. + */ + + BM_ITER_ELEM (bme, &iter, v, BM_EDGES_OF_VERT) { + if (BM_elem_flag_test(bme, BM_ELEM_TAG)) { + BLI_assert(BM_edge_is_manifold(bme)); + nsel++; + } + ntot++; + } + + if (nsel == 0) { + /* signal this vert isn't being beveled */ + BM_elem_flag_disable(v, BM_ELEM_TAG); + return; + } + + /* avoid calling BM_vert_edge_count since we loop over edges already */ + // ntot = BM_vert_edge_count(v); + // BLI_assert(ntot == BM_vert_edge_count(v)); + + bv = (BevVert *)BLI_memarena_alloc(bp->mem_arena, (sizeof(BevVert))); + bv->v = v; + bv->edgecount = ntot; + bv->selcount = nsel; + bv->edges = (EdgeHalf *)BLI_memarena_alloc(bp->mem_arena, ntot * sizeof(EdgeHalf)); + bv->vmesh = (VMesh *)BLI_memarena_alloc(bp->mem_arena, sizeof(VMesh)); + bv->vmesh->seg = bp->seg; + BLI_ghash_insert(bp->vert_hash, v, bv); + + /* add edges to bv->edges in order that keeps adjacent edges sharing + * a face, if possible */ + i = 0; + bme = v->e; + BM_BEVEL_EDGE_TAG_ENABLE(bme); + e = &bv->edges[0]; + e->e = bme; + for (i = 0; i < ntot; i++) { + if (i > 0) { + /* find an unflagged edge bme2 that shares a face f with previous bme */ + found_shared_face = 0; + unflagged_bme = NULL; + BM_ITER_ELEM (bme2, &iter, v, BM_EDGES_OF_VERT) { + if (BM_BEVEL_EDGE_TAG_TEST(bme2)) + continue; + if (!unflagged_bme) + unflagged_bme = bme2; + BM_ITER_ELEM (f, &iter2, bme2, BM_FACES_OF_EDGE) { + if (BM_face_edge_share_loop(f, bme)) { + found_shared_face = 1; + break; + } + } + if (found_shared_face) + break; + } + e = &bv->edges[i]; + if (found_shared_face) { + e->e = bme2; + e->fprev = f; + bv->edges[i - 1].fnext = f; + } + else { + e->e = unflagged_bme; + } + } + bme = e->e; + BM_BEVEL_EDGE_TAG_ENABLE(bme); + if (BM_elem_flag_test(bme, BM_ELEM_TAG)) { + e->is_bev = TRUE; + e->seg = bp->seg; + } + else { + e->is_bev = FALSE; + e->seg = 0; + } + e->is_rev = (bme->v2 == v); + e->offset = e->is_bev ? bp->offset : 0.0f; + } + /* find wrap-around shared face */ + BM_ITER_ELEM (f, &iter2, bme, BM_FACES_OF_EDGE) { + if (BM_face_edge_share_loop(f, bv->edges[0].e)) { + if (bv->edges[0].fnext == f) + continue; /* if two shared faces, want the other one now */ + bv->edges[ntot - 1].fnext = f; + bv->edges[0].fprev = f; + break; + } + } + + /* do later when we loop over edges */ +#if 0 + /* clear BEVEL_EDGE_TAG now that we are finished with it*/ + for (i = 0; i < ntot; i++) { + BM_BEVEL_EDGE_TAG_DISABLE(bv->edges[i].e); + } +#endif + + /* if edge array doesn't go CCW around vertex from average normal side, + * reverse the array, being careful to reverse face pointers too */ + if (ntot > 1) { + ccw_test_sum = 0; + for (i = 0; i < ntot; i++) + ccw_test_sum += bev_ccw_test(bv->edges[i].e, bv->edges[(i + 1) % ntot].e, + bv->edges[i].fnext); + if (ccw_test_sum < 0) { + for (i = 0; i <= (ntot / 2) - 1; i++) { + SWAP(EdgeHalf, bv->edges[i], bv->edges[ntot - i - 1]); + SWAP(BMFace *, bv->edges[i].fprev, bv->edges[i].fnext); + SWAP(BMFace *, bv->edges[ntot - i - 1].fprev, bv->edges[ntot - i - 1].fnext); + } + if (ntot % 2 == 1) { + i = ntot / 2; + SWAP(BMFace *, bv->edges[i].fprev, bv->edges[i].fnext); + } + } + } + + for (i = 0, e = bv->edges; i < ntot; i++, e++) { + e->next = &bv->edges[(i + 1) % ntot]; + e->prev = &bv->edges[(i + ntot - 1) % ntot]; + BM_BEVEL_EDGE_TAG_DISABLE(e->e); + } + + build_boundary(bp->mem_arena, bv); + build_vmesh(bp->mem_arena, bm, bv); +} + +/* Face f has at least one beveled vertex. Rebuild f */ +static int bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) +{ + BMIter liter; + BMLoop *l, *lprev; + BevVert *bv; + BoundVert *v, *vstart, *vend; + EdgeHalf *e, *eprev; + VMesh *vm; + int i, k; + int do_rebuild = FALSE; + BMVert *bmv; + BMVert **vv = NULL; + BLI_array_staticdeclare(vv, BM_DEFAULT_NGON_STACK_SIZE); + + BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { + if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) { + lprev = l->prev; + bv = find_bevvert(bp, l->v); + e = find_edge_half(bv, l->e); + eprev = find_edge_half(bv, lprev->e); + BLI_assert(e != NULL && eprev != NULL); + vstart = eprev->leftv; + if (e->is_bev) + vend = e->rightv; + else + vend = e->leftv; + v = vstart; + vm = bv->vmesh; + BLI_array_append(vv, v->nv.v); + while (v != vend) { + if (vm->mesh_kind == M_NONE && v->ebev && v->ebev->seg > 1 && v->ebev != e && v->ebev != eprev) { + /* case of 3rd face opposite a beveled edge, with no vmesh */ + i = v->index; + e = v->ebev; + for (k = 1; k < e->seg; k++) { + bmv = mesh_vert(vm, i, 0, k)->v; + BLI_array_append(vv, bmv); + } + } + v = v->prev; + BLI_array_append(vv, v->nv.v); + } + + do_rebuild = TRUE; + } + else { + BLI_array_append(vv, l->v); + } + } + if (do_rebuild) { + BMFace *f_new = bev_create_ngon(bm, vv, BLI_array_count(vv), f); + + /* don't select newly created boundary faces... */ + if (f_new) { + BM_elem_flag_disable(f_new, BM_ELEM_TAG); + } + } + + BLI_array_free(vv); + return do_rebuild; +} + +/* All polygons touching v need rebuilding because beveling v has made new vertices */ +static void bevel_rebuild_existing_polygons(BMesh *bm, BevelParams *bp, BMVert *v) +{ + void *faces_stack[BM_DEFAULT_ITER_STACK_SIZE]; + int faces_len, f_index; + BMFace **faces = BM_iter_as_arrayN(bm, BM_FACES_OF_VERT, v, &faces_len, + faces_stack, BM_DEFAULT_ITER_STACK_SIZE); + + if (LIKELY(faces != NULL)) { + for (f_index = 0; f_index < faces_len; f_index++) { + BMFace *f = faces[f_index]; + if (bev_rebuild_polygon(bm, bp, f)) { + BM_face_kill(bm, f); + } + } + + if (faces != (BMFace **)faces_stack) { + MEM_freeN(faces); + } + } +} + + +/* + * Build the polygons along the selected Edge + */ +static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme) +{ + BevVert *bv1, *bv2; + BMVert *bmv1, *bmv2, *bmv3, *bmv4, *bmv1i, *bmv2i, *bmv3i, *bmv4i; + VMesh *vm1, *vm2; + EdgeHalf *e1, *e2; + BMFace *f1, *f2, *f; + int k, nseg, i1, i2; + + if (!BM_edge_is_manifold(bme)) + return; + + bv1 = find_bevvert(bp, bme->v1); + bv2 = find_bevvert(bp, bme->v2); + + BLI_assert(bv1 && bv2); + + e1 = find_edge_half(bv1, bme); + e2 = find_edge_half(bv2, bme); + + BLI_assert(e1 && e2); + + /* v4 v3 + * \ / + * e->v1 - e->v2 + * / \ + * v1 v2 + */ + nseg = e1->seg; + BLI_assert(nseg > 0 && nseg == e2->seg); + + bmv1 = e1->leftv->nv.v; + bmv4 = e1->rightv->nv.v; + bmv2 = e2->rightv->nv.v; + bmv3 = e2->leftv->nv.v; + + BLI_assert(bmv1 && bmv2 && bmv3 && bmv4); + + f1 = boundvert_rep_face(e1->leftv); + f2 = boundvert_rep_face(e1->rightv); + + if (nseg == 1) { + bev_create_quad_tri(bm, bmv1, bmv2, bmv3, bmv4, f1); + } + else { + i1 = e1->leftv->index; + i2 = e2->leftv->index; + vm1 = bv1->vmesh; + vm2 = bv2->vmesh; + bmv1i = bmv1; + bmv2i = bmv2; + for (k = 1; k <= nseg; k++) { + bmv4i = mesh_vert(vm1, i1, 0, k)->v; + bmv3i = mesh_vert(vm2, i2, 0, nseg - k)->v; + f = (k <= nseg / 2 + (nseg % 2)) ? f1 : f2; + bev_create_quad_tri(bm, bmv1i, bmv2i, bmv3i, bmv4i, f); + bmv1i = bmv4i; + bmv2i = bmv3i; + } + } +} + +/** + * - Currently only bevels BM_ELEM_TAG'd verts and edges. + * + * - Newly created faces are BM_ELEM_TAG'd too, + * the caller needs to ensure this is cleared before calling + * if its going to use this face tag. + * + * \warning all tagged edges _must_ be manifold. + */ +void BM_mesh_bevel(BMesh *bm, const float offset, const float segments) +{ + BMIter iter; + BMVert *v; + BMEdge *e; + BevelParams bp = {NULL}; + + bp.offset = offset; + bp.seg = segments; + + if (bp.offset > 0) { + /* primary alloc */ + bp.vert_hash = BLI_ghash_ptr_new(__func__); + bp.mem_arena = BLI_memarena_new((1 << 16), __func__); + BLI_memarena_use_calloc(bp.mem_arena); + + /* The analysis of the input vertices and execution additional constructions */ + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_TAG)) { + bevel_vert_construct(bm, &bp, v); + } + } + + /* Build polygons for edges */ + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_TAG)) { + bevel_build_edge_polygons(bm, &bp, e); + } + } + + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_TAG)) { + bevel_rebuild_existing_polygons(bm, &bp, v); + } + } + + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_TAG)) { + BLI_assert(find_bevvert(&bp, v) != NULL); + BM_vert_kill(bm, v); + } + } + + /* primary free */ + BLI_ghash_free(bp.vert_hash, NULL, NULL); + BLI_memarena_free(bp.mem_arena); + } +} diff --git a/source/blender/bmesh/tools/bmesh_bevel.h b/source/blender/bmesh/tools/bmesh_bevel.h new file mode 100644 index 00000000000..a80e4f3a4a2 --- /dev/null +++ b/source/blender/bmesh/tools/bmesh_bevel.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): + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BMESH_BEVEL_H__ +#define __BMESH_BEVEL_H__ + +/** \file blender/bmesh/tools/bmesh_bevel.h + * \ingroup bmesh + */ + +void BM_mesh_bevel(BMesh *bm, const float offset, const float segments); + +#endif /* __BMESH_BEVEL_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_decimate.h b/source/blender/bmesh/tools/bmesh_decimate.h index 04dc0cfd2ea..4d382d65659 100644 --- a/source/blender/bmesh/intern/bmesh_decimate.h +++ b/source/blender/bmesh/tools/bmesh_decimate.h @@ -23,7 +23,7 @@ #ifndef __BMESH_DECIMATE_H__ #define __BMESH_DECIMATE_H__ -/** \file blender/bmesh/intern/bmesh_decimate.h +/** \file blender/bmesh/tools/bmesh_decimate.h * \ingroup bmesh */ diff --git a/source/blender/bmesh/intern/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c index 74792d1d558..781001508f2 100644 --- a/source/blender/bmesh/intern/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c @@ -20,7 +20,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/bmesh/intern/bmesh_decimate_collapse.c +/** \file blender/bmesh/tools/bmesh_decimate_collapse.c * \ingroup bmesh * * BMesh decimator that uses an edge collapse method. @@ -39,9 +39,10 @@ #include "BKE_customdata.h" #include "bmesh.h" -#include "bmesh_structure.h" #include "bmesh_decimate.h" /* own include */ +#include "../intern/bmesh_structure.h" + /* defines for testing */ #define USE_CUSTOMDATA #define USE_TRIANGULATE diff --git a/source/blender/bmesh/intern/bmesh_decimate_dissolve.c b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c index d1371a18160..d2a5c580ae6 100644 --- a/source/blender/bmesh/intern/bmesh_decimate_dissolve.c +++ b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c @@ -20,7 +20,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/bmesh/intern/bmesh_decimate_dissolve.c +/** \file blender/bmesh/tools/bmesh_decimate_dissolve.c * \ingroup bmesh * * BMesh decimator that dissolves flat areas into polygons (ngons). @@ -231,8 +231,8 @@ void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const int do_ int vinput_len; int einput_len; - BMVert **vinput_arr = BM_iter_as_arrayN(bm, BM_VERTS_OF_MESH, NULL, &vinput_len); - BMEdge **einput_arr = BM_iter_as_arrayN(bm, BM_EDGES_OF_MESH, NULL, &einput_len); + BMVert **vinput_arr = BM_iter_as_arrayN(bm, BM_VERTS_OF_MESH, NULL, &vinput_len, NULL, 0); + BMEdge **einput_arr = BM_iter_as_arrayN(bm, BM_EDGES_OF_MESH, NULL, &einput_len, NULL, 0); BM_mesh_decimate_dissolve_ex(bm, angle_limit, do_dissolve_boundaries, vinput_arr, vinput_len, diff --git a/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c index 1ec13010d80..acdab2510a4 100644 --- a/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c +++ b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c @@ -20,7 +20,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/bmesh/intern/bmesh_decimate_unsubdivide.c +/** \file blender/bmesh/tools/bmesh_decimate_unsubdivide.c * \ingroup bmesh * * BMesh decimator that uses a grid un-subdivide method. diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp index 374f6385ea7..44e74e320cc 100644 --- a/source/blender/collada/AnimationImporter.cpp +++ b/source/blender/collada/AnimationImporter.cpp @@ -844,7 +844,7 @@ void AnimationImporter::apply_matrix_curves(Object *ob, std::vector<FCurve *>& a * This function returns the aspet ration from the Collada camera. * * Note:COLLADA allows to specify either XFov, or YFov alone. - * In tghat case the aspect ratio can be determined from + * In that case the aspect ratio can be determined from * the viewport aspect ratio (which is 1:1 ?) * XXX: check this: its probably wrong! * If both values are specified, then the aspect ration is simply xfov/yfov diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index 1c4f0974c6d..084f71e0afc 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -552,8 +552,8 @@ bool DocumentImporter::writeVisualScene(const COLLADAFW::VisualScene *visualScen } /** When this method is called, the writer must handle all nodes contained in the -* library nodes. -* \return The writer should return true, if writing succeeded, false otherwise.*/ + * library nodes. + * \return The writer should return true, if writing succeeded, false otherwise.*/ bool DocumentImporter::writeLibraryNodes(const COLLADAFW::LibraryNodes *libraryNodes) { if (mImportStage != General) diff --git a/source/blender/collada/DocumentImporter.h b/source/blender/collada/DocumentImporter.h index e878a5a5b48..d54b8db9f00 100644 --- a/source/blender/collada/DocumentImporter.h +++ b/source/blender/collada/DocumentImporter.h @@ -81,8 +81,8 @@ public: /** * This method will be called if an error in the loading process occurred and the loader cannot * continue to load. The writer should undo all operations that have been performed. - \param errorMessage A message containing informations about the error that occurred. - */ + * \param errorMessage A message containing informations about the error that occurred. + */ void cancel(const COLLADAFW::String& errorMessage); /** This is the method called. The writer hast to prepare to receive data.*/ diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp index 2e0c0f1ea57..aba290f5ce4 100644 --- a/source/blender/collada/ImageExporter.cpp +++ b/source/blender/collada/ImageExporter.cpp @@ -61,7 +61,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies) if (not_yet_exported) { - ImBuf *imbuf = BKE_image_get_ibuf(image, NULL); + ImBuf *imbuf = BKE_image_acquire_ibuf(image, NULL, NULL); if (!imbuf) { fprintf(stderr, "Collada export: image does not exist:\n%s\n", image->name); return; @@ -147,6 +147,8 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies) img.add(mSW); fprintf(stdout, "Collada export: Added image: %s\n", export_file); mImages.push_back(translated_name); + + BKE_image_release_ibuf(image, imbuf, NULL); } } diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index ceb91e5a3ec..6e59ce60c9b 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -267,6 +267,8 @@ set(SRC nodes/COM_MathNode.h nodes/COM_MapValueNode.cpp nodes/COM_MapValueNode.h + nodes/COM_MapRangeNode.cpp + nodes/COM_MapRangeNode.h operations/COM_NormalizeOperation.cpp operations/COM_NormalizeOperation.h @@ -572,6 +574,8 @@ set(SRC operations/COM_SetAlphaOperation.h operations/COM_MapValueOperation.cpp operations/COM_MapValueOperation.h + operations/COM_MapRangeOperation.cpp + operations/COM_MapRangeOperation.h # Distort operation operations/COM_TranslateOperation.h diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp index 2b09c9d5b8c..9c4a32f20c9 100644 --- a/source/blender/compositor/intern/COM_Converter.cpp +++ b/source/blender/compositor/intern/COM_Converter.cpp @@ -83,6 +83,7 @@ #include "COM_LuminanceMatteNode.h" #include "COM_MapUVNode.h" #include "COM_MapValueNode.h" +#include "COM_MapRangeNode.h" #include "COM_MaskNode.h" #include "COM_MathNode.h" #include "COM_MixNode.h" @@ -351,6 +352,9 @@ Node *Converter::convert(bNode *b_node, bool fast) case CMP_NODE_MAP_VALUE: node = new MapValueNode(b_node); break; + case CMP_NODE_MAP_RANGE: + node = new MapRangeNode(b_node); + break; case CMP_NODE_TRANSFORM: node = new TransformNode(b_node); break; diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp index c6e0f6c2cfb..1ec4ac7699b 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp +++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp @@ -247,9 +247,14 @@ void ExecutionSystem::addReadWriteBufferOperations(NodeOperation *operation) */ static void debug_check_node_connections(Node *node) { + /* note: connected inputs are not checked here, + * it would break quite a lot and such inputs are ignored later anyway + */ +#if 0 for (int i = 0; i < node->getNumberOfInputSockets(); ++i) { BLI_assert(!node->getInputSocket(i)->isConnected()); } +#endif for (int i = 0; i < node->getNumberOfOutputSockets(); ++i) { BLI_assert(!node->getOutputSocket(i)->isConnected()); } diff --git a/source/blender/compositor/nodes/COM_BlurNode.cpp b/source/blender/compositor/nodes/COM_BlurNode.cpp index 4f120ea5a6e..6a4987c2075 100644 --- a/source/blender/compositor/nodes/COM_BlurNode.cpp +++ b/source/blender/compositor/nodes/COM_BlurNode.cpp @@ -31,6 +31,7 @@ #include "COM_FastGaussianBlurOperation.h" #include "COM_MathBaseOperation.h" #include "COM_SetValueOperation.h" +#include "COM_GammaCorrectOperation.h" BlurNode::BlurNode(bNode *editorNode) : Node(editorNode) { @@ -48,16 +49,17 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co const float size = ((const bNodeSocketValueFloat *)sock->default_value)->value; CompositorQuality quality = context->getQuality(); - + NodeOperation *input_operation = NULL, *output_operation = NULL; + if (data->filtertype == R_FILTER_FAST_GAUSS) { FastGaussianBlurOperation *operationfgb = new FastGaussianBlurOperation(); operationfgb->setData(data); operationfgb->setbNode(editorNode); - this->getInputSocket(0)->relinkConnections(operationfgb->getInputSocket(0), 0, graph); this->getInputSocket(1)->relinkConnections(operationfgb->getInputSocket(1), 1, graph); - this->getOutputSocket(0)->relinkConnections(operationfgb->getOutputSocket(0)); graph->addOperation(operationfgb); - addPreviewOperation(graph, context, operationfgb->getOutputSocket()); + + input_operation = operationfgb; + output_operation = operationfgb; } else if (editorNode->custom1 & CMP_NODEFLAG_BLUR_VARIABLE_SIZE) { MathAddOperation *clamp = new MathAddOperation(); @@ -93,48 +95,68 @@ void BlurNode::convertToOperations(ExecutionSystem *graph, CompositorContext *co operation->setData(data); operation->setbNode(editorNode); operation->setQuality(quality); - this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph); addLink(graph, operationy->getOutputSocket(), operation->getInputSocket(1)); graph->addOperation(operation); - this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket()); - addPreviewOperation(graph, context, operation->getOutputSocket()); + + output_operation = operation; + input_operation = operation; } else if (!data->bokeh) { GaussianXBlurOperation *operationx = new GaussianXBlurOperation(); operationx->setData(data); operationx->setbNode(editorNode); operationx->setQuality(quality); - this->getInputSocket(0)->relinkConnections(operationx->getInputSocket(0), 0, graph); this->getInputSocket(1)->relinkConnections(operationx->getInputSocket(1), 1, graph); graph->addOperation(operationx); GaussianYBlurOperation *operationy = new GaussianYBlurOperation(); operationy->setData(data); operationy->setbNode(editorNode); operationy->setQuality(quality); - this->getOutputSocket(0)->relinkConnections(operationy->getOutputSocket()); + graph->addOperation(operationy); addLink(graph, operationx->getOutputSocket(), operationy->getInputSocket(0)); addLink(graph, operationx->getInputSocket(1)->getConnection()->getFromSocket(), operationy->getInputSocket(1)); - addPreviewOperation(graph, context, operationy->getOutputSocket()); if (!connectedSizeSocket) { operationx->setSize(size); operationy->setSize(size); } + + input_operation = operationx; + output_operation = operationy; } else { GaussianBokehBlurOperation *operation = new GaussianBokehBlurOperation(); operation->setData(data); operation->setbNode(editorNode); - this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph); this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph); operation->setQuality(quality); graph->addOperation(operation); - this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket()); - addPreviewOperation(graph, context, operation->getOutputSocket()); if (!connectedSizeSocket) { operation->setSize(size); } + + input_operation = operation; + output_operation = operation; + } + + if (data->gamma) { + GammaCorrectOperation *correct = new GammaCorrectOperation(); + GammaUncorrectOperation *inverse = new GammaUncorrectOperation(); + + this->getInputSocket(0)->relinkConnections(correct->getInputSocket(0), 0, graph); + addLink(graph, correct->getOutputSocket(), input_operation->getInputSocket(0)); + addLink(graph, output_operation->getOutputSocket(), inverse->getInputSocket(0)); + this->getOutputSocket()->relinkConnections(inverse->getOutputSocket()); + graph->addOperation(correct); + graph->addOperation(inverse); + + addPreviewOperation(graph, context, inverse->getOutputSocket()); + } + else { + this->getInputSocket(0)->relinkConnections(input_operation->getInputSocket(0), 0, graph); + this->getOutputSocket()->relinkConnections(output_operation->getOutputSocket()); + addPreviewOperation(graph, context, output_operation->getOutputSocket()); } } diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp index 4ebd28d710a..729cb1b70a0 100644 --- a/source/blender/compositor/nodes/COM_ImageNode.cpp +++ b/source/blender/compositor/nodes/COM_ImageNode.cpp @@ -73,7 +73,7 @@ void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c /* force a load, we assume iuser index will be set OK anyway */ if (image && image->type == IMA_TYPE_MULTILAYER) { bool is_multilayer_ok = false; - BKE_image_get_ibuf(image, imageuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(image, imageuser, NULL); if (image->rr) { RenderLayer *rl = (RenderLayer *)BLI_findlink(&image->rr->layers, imageuser->layer); if (rl) { @@ -118,6 +118,7 @@ void ImageNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c } } } + BKE_image_release_ibuf(image, ibuf, NULL); /* without this, multilayer that fail to load will crash blender [#32490] */ if (is_multilayer_ok == false) { diff --git a/source/blender/compositor/nodes/COM_MapRangeNode.cpp b/source/blender/compositor/nodes/COM_MapRangeNode.cpp new file mode 100644 index 00000000000..232be3d41b0 --- /dev/null +++ b/source/blender/compositor/nodes/COM_MapRangeNode.cpp @@ -0,0 +1,54 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Dalai Felinto + * Daniel Salazar + */ + +#include "COM_MapRangeNode.h" + +#include "COM_MapRangeOperation.h" +#include "COM_ExecutionSystem.h" + +MapRangeNode::MapRangeNode(bNode *editorNode) : Node(editorNode) +{ + /* pass */ +} + +void MapRangeNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context) +{ + InputSocket *valueSocket = this->getInputSocket(0); + InputSocket *sourceMinSocket = this->getInputSocket(1); + InputSocket *sourceMaxSocket = this->getInputSocket(2); + InputSocket *destMinSocket = this->getInputSocket(3); + InputSocket *destMaxSocket = this->getInputSocket(4); + OutputSocket *outputSocket = this->getOutputSocket(0); + + MapRangeOperation *operation = new MapRangeOperation(); + + valueSocket->relinkConnections(operation->getInputSocket(0), 0, graph); + sourceMinSocket->relinkConnections(operation->getInputSocket(1), 1, graph); + sourceMaxSocket->relinkConnections(operation->getInputSocket(2), 2, graph); + destMinSocket->relinkConnections(operation->getInputSocket(3), 3, graph); + destMaxSocket->relinkConnections(operation->getInputSocket(4), 4, graph); + outputSocket->relinkConnections(operation->getOutputSocket(0)); + + operation->setUseClamp(this->getbNode()->custom1); + + graph->addOperation(operation); +} diff --git a/source/blender/compositor/nodes/COM_MapRangeNode.h b/source/blender/compositor/nodes/COM_MapRangeNode.h new file mode 100644 index 00000000000..6667720be3d --- /dev/null +++ b/source/blender/compositor/nodes/COM_MapRangeNode.h @@ -0,0 +1,38 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Dalai Felinto + * Daniel Salazar + */ + +#ifndef __COM_MAPRANGENODE_H__ +#define __COM_MAPRANGENODE_H__ + +#include "COM_Node.h" +#include "DNA_node_types.h" +/** + * @brief MapRangeNode + * @ingroup Node + */ +class MapRangeNode : public Node { +public: + MapRangeNode(bNode *editorNode); + void convertToOperations(ExecutionSystem *graph, CompositorContext *context); +}; + +#endif /* __COM_MAPRANGENODE_H__ */ diff --git a/source/blender/compositor/nodes/COM_MuteNode.cpp b/source/blender/compositor/nodes/COM_MuteNode.cpp index 4502dcf469c..de12fff3591 100644 --- a/source/blender/compositor/nodes/COM_MuteNode.cpp +++ b/source/blender/compositor/nodes/COM_MuteNode.cpp @@ -43,6 +43,10 @@ void MuteNode::reconnect(ExecutionSystem *graph, OutputSocket *output) if (input->getDataType() == output->getDataType()) { if (input->isConnected()) { output->relinkConnections(input->getConnection()->getFromSocket(), false); + /* output connections have been redirected, + * remove the input connection to completely unlink the node. + */ + input->unlinkConnections(graph); return; } } diff --git a/source/blender/compositor/nodes/COM_NormalNode.cpp b/source/blender/compositor/nodes/COM_NormalNode.cpp index e00e71e50e9..fbfff8386d0 100644 --- a/source/blender/compositor/nodes/COM_NormalNode.cpp +++ b/source/blender/compositor/nodes/COM_NormalNode.cpp @@ -41,9 +41,14 @@ void NormalNode::convertToOperations(ExecutionSystem *graph, CompositorContext * SetVectorOperation *operationSet = new SetVectorOperation(); bNodeSocket *insock = (bNodeSocket *)editorNode->outputs.first; bNodeSocketValueVector *dval = (bNodeSocketValueVector *)insock->default_value; - operationSet->setX(dval->value[0]); - operationSet->setY(dval->value[1]); - operationSet->setZ(dval->value[2]); + float normal[3]; + + /* animation can break normalization, this restores it */ + normalize_v3_v3(normal, dval->value); + + operationSet->setX(normal[0]); + operationSet->setY(normal[1]); + operationSet->setZ(normal[2]); operationSet->setW(0.0f); outputSocket->relinkConnections(operationSet->getOutputSocket(0)); diff --git a/source/blender/compositor/nodes/COM_OutputFileNode.cpp b/source/blender/compositor/nodes/COM_OutputFileNode.cpp index 921b9e63a73..3b1871b307b 100644 --- a/source/blender/compositor/nodes/COM_OutputFileNode.cpp +++ b/source/blender/compositor/nodes/COM_OutputFileNode.cpp @@ -41,6 +41,12 @@ void OutputFileNode::convertToOperations(ExecutionSystem *graph, CompositorConte * otherwise, it overwrites the output files just * scrubbing through the timeline when the compositor updates. */ + + /* still, need to unlink input sockets to remove the node from the graph completely */ + int num_inputs = getNumberOfInputSockets(); + for (int i = 0; i < num_inputs; ++i) { + getInputSocket(i)->unlinkConnections(graph); + } return; } diff --git a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp index 4bdb2591cb7..9231261986d 100644 --- a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp @@ -230,6 +230,7 @@ FastGaussianBlurValueOperation::FastGaussianBlurValueOperation() : NodeOperation this->m_iirgaus = NULL; this->m_inputprogram = NULL; this->m_sigma = 1.0f; + this->m_overlay = 0; setComplex(true); } @@ -281,7 +282,7 @@ void *FastGaussianBlurValueOperation::initializeTileData(rcti *rect) if (this->m_overlay == FAST_GAUSS_OVERLAY_MIN) { float *src = newBuf->getBuffer(); float *dst = copy->getBuffer(); - for (int i = copy->getWidth() * copy->getHeight() * COM_NUMBER_OF_CHANNELS; i != 0; i--, src++, dst++) { + for (int i = copy->getWidth() * copy->getHeight(); i != 0; i--, src += COM_NUMBER_OF_CHANNELS, dst += COM_NUMBER_OF_CHANNELS) { if (*src < *dst) { *dst = *src; } @@ -290,7 +291,7 @@ void *FastGaussianBlurValueOperation::initializeTileData(rcti *rect) else if (this->m_overlay == FAST_GAUSS_OVERLAY_MAX) { float *src = newBuf->getBuffer(); float *dst = copy->getBuffer(); - for (int i = copy->getWidth() * copy->getHeight() * COM_NUMBER_OF_CHANNELS; i != 0; i--, src++, dst++) { + for (int i = copy->getWidth() * copy->getHeight(); i != 0; i--, src += COM_NUMBER_OF_CHANNELS, dst += COM_NUMBER_OF_CHANNELS) { if (*src > *dst) { *dst = *src; } diff --git a/source/blender/compositor/operations/COM_GammaCorrectOperation.cpp b/source/blender/compositor/operations/COM_GammaCorrectOperation.cpp index af990f4f3e0..8f92dc02a57 100644 --- a/source/blender/compositor/operations/COM_GammaCorrectOperation.cpp +++ b/source/blender/compositor/operations/COM_GammaCorrectOperation.cpp @@ -48,15 +48,13 @@ void GammaCorrectOperation::executePixel(float output[4], float x, float y, Pixe output[0] = inputColor[0] > 0.0f ? inputColor[0] * inputColor[0] : 0.0f; output[1] = inputColor[1] > 0.0f ? inputColor[1] * inputColor[1] : 0.0f; output[2] = inputColor[2] > 0.0f ? inputColor[2] * inputColor[2] : 0.0f; - - inputColor[0] *= inputColor[3]; - inputColor[1] *= inputColor[3]; - inputColor[2] *= inputColor[3]; - - output[0] = inputColor[0]; - output[1] = inputColor[1]; - output[2] = inputColor[2]; output[3] = inputColor[3]; + + if (inputColor[3] > 0.0f) { + output[0] *= inputColor[3]; + output[1] *= inputColor[3]; + output[2] *= inputColor[3]; + } } void GammaCorrectOperation::deinitExecution() @@ -89,15 +87,13 @@ void GammaUncorrectOperation::executePixel(float output[4], float x, float y, Pi output[0] = inputColor[0] > 0.0f ? sqrtf(inputColor[0]) : 0.0f; output[1] = inputColor[1] > 0.0f ? sqrtf(inputColor[1]) : 0.0f; output[2] = inputColor[2] > 0.0f ? sqrtf(inputColor[2]) : 0.0f; - - inputColor[0] *= inputColor[3]; - inputColor[1] *= inputColor[3]; - inputColor[2] *= inputColor[3]; - - output[0] = inputColor[0]; - output[1] = inputColor[1]; - output[2] = inputColor[2]; output[3] = inputColor[3]; + + if (inputColor[3] > 0.0f) { + output[0] *= inputColor[3]; + output[1] *= inputColor[3]; + output[2] *= inputColor[3]; + } } void GammaUncorrectOperation::deinitExecution() diff --git a/source/blender/compositor/operations/COM_ImageOperation.cpp b/source/blender/compositor/operations/COM_ImageOperation.cpp index fb3efbb67ed..d4c35f5afaa 100644 --- a/source/blender/compositor/operations/COM_ImageOperation.cpp +++ b/source/blender/compositor/operations/COM_ImageOperation.cpp @@ -65,8 +65,9 @@ ImBuf *BaseImageOperation::getImBuf() { ImBuf *ibuf; - ibuf = BKE_image_get_ibuf(this->m_image, this->m_imageUser); + ibuf = BKE_image_acquire_ibuf(this->m_image, this->m_imageUser, NULL); if (ibuf == NULL || (ibuf->rect == NULL && ibuf->rect_float == NULL)) { + BKE_image_release_ibuf(this->m_image, ibuf, NULL); return NULL; } @@ -93,6 +94,7 @@ void BaseImageOperation::initExecution() void BaseImageOperation::deinitExecution() { this->m_imageBuffer = NULL; + BKE_image_release_ibuf(this->m_image, this->m_buffer, NULL); } void BaseImageOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) @@ -106,6 +108,8 @@ void BaseImageOperation::determineResolution(unsigned int resolution[2], unsigne resolution[0] = stackbuf->x; resolution[1] = stackbuf->y; } + + IMB_freeImBuf(stackbuf); } void ImageOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp index 0874e2f59be..201dc99eb9e 100644 --- a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp @@ -202,9 +202,9 @@ KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTri INIT_MINMAX2(min, max); - DO_MINMAX2(a->co, min, max); - DO_MINMAX2(b->co, min, max); - DO_MINMAX2(c->co, min, max); + minmax_v2v2_v2(min, max, a->co); + minmax_v2v2_v2(min, max, b->co); + minmax_v2v2_v2(min, max, c->co); rect->xmin = min[0]; rect->ymin = min[1]; diff --git a/source/blender/compositor/operations/COM_MapRangeOperation.cpp b/source/blender/compositor/operations/COM_MapRangeOperation.cpp new file mode 100644 index 00000000000..a18f418e48e --- /dev/null +++ b/source/blender/compositor/operations/COM_MapRangeOperation.cpp @@ -0,0 +1,87 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Dalai Felinto + * Daniel Salazar + */ + +#include "COM_MapRangeOperation.h" + +MapRangeOperation::MapRangeOperation() : NodeOperation() +{ + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VALUE); + this->m_inputOperation = NULL; + this->m_useClamp = FALSE; +} + +void MapRangeOperation::initExecution() +{ + this->m_inputOperation = this->getInputSocketReader(0); + this->m_sourceMinOperation = this->getInputSocketReader(1); + this->m_sourceMaxOperation = this->getInputSocketReader(2); + this->m_destMinOperation = this->getInputSocketReader(3); + this->m_destMaxOperation = this->getInputSocketReader(4); +} + +void MapRangeOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputs[8]; /* includes the 5 inputs + 3 pads */ + float value; + float source_min, source_max; + float dest_min, dest_max; + + this->m_inputOperation->read(inputs, x, y, sampler); + this->m_sourceMinOperation->read(inputs + 1, x, y, sampler); + this->m_sourceMaxOperation->read(inputs + 2, x, y, sampler); + this->m_destMinOperation->read(inputs + 3, x, y, sampler); + this->m_destMaxOperation->read(inputs + 4, x, y, sampler); + + value = inputs[0]; + source_min = inputs[1]; + source_max = inputs[2]; + dest_min = inputs[3]; + dest_max = inputs[4]; + + value = (value - source_min) / (source_max - source_min); + value = dest_min + value * (dest_max - dest_min); + + if (this->m_useClamp) { + if (dest_max > dest_min) { + CLAMP(value, dest_min, dest_max); + } + else { + CLAMP(value, dest_max, dest_min); + } + } + + output[0] = value; +} + +void MapRangeOperation::deinitExecution() +{ + this->m_inputOperation = NULL; + this->m_sourceMinOperation = NULL; + this->m_sourceMaxOperation = NULL; + this->m_destMinOperation = NULL; + this->m_destMaxOperation = NULL; +} diff --git a/source/blender/compositor/operations/COM_MapRangeOperation.h b/source/blender/compositor/operations/COM_MapRangeOperation.h new file mode 100644 index 00000000000..00dfc68168c --- /dev/null +++ b/source/blender/compositor/operations/COM_MapRangeOperation.h @@ -0,0 +1,71 @@ +/* + * Copyright 2012, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Dalai Felinto + * Daniel Salazar + */ + +#ifndef _COM_MapRangeOperation_h +#define _COM_MapRangeOperation_h +#include "COM_NodeOperation.h" +#include "DNA_texture_types.h" + +/** + * this program converts an input color to an output value. + * it assumes we are in sRGB color space. + */ +class MapRangeOperation : public NodeOperation { +private: + /** + * Cached reference to the inputProgram + */ + SocketReader *m_inputOperation; + SocketReader *m_sourceMinOperation; + SocketReader *m_sourceMaxOperation; + SocketReader *m_destMinOperation; + SocketReader *m_destMaxOperation; + + bool m_useClamp; +public: + /** + * Default constructor + */ + MapRangeOperation(); + + /** + * the inner loop of this program + */ + void executePixel(float output[4], float x, float y, PixelSampler sampler); + + /** + * Initialize the execution + */ + void initExecution(); + + /** + * Deinitialize the execution + */ + void deinitExecution(); + + /** + * Clamp the output + */ + void setUseClamp(bool value) { this->m_useClamp = value; } + +}; +#endif diff --git a/source/blender/compositor/operations/COM_PixelateOperation.h b/source/blender/compositor/operations/COM_PixelateOperation.h index b16b21b2ec1..83603a59331 100644 --- a/source/blender/compositor/operations/COM_PixelateOperation.h +++ b/source/blender/compositor/operations/COM_PixelateOperation.h @@ -35,7 +35,7 @@ class PixelateOperation : public NodeOperation { private: /** - * @brief cached refeerence to the input operation + * @brief cached reference to the input operation */ SocketReader *m_inputOperation; public: diff --git a/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp b/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp index f4160a5fbcb..2ca499683d3 100644 --- a/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp +++ b/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp @@ -91,11 +91,11 @@ void RenderLayersBaseProg::doInterpolation(float output[4], float x, float y, Pi break; case COM_PS_BILINEAR: - BLI_bilinear_interpolation(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y); + BLI_bilinear_interpolation_fl(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y); break; case COM_PS_BICUBIC: - BLI_bicubic_interpolation(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y); + BLI_bicubic_interpolation_fl(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y); break; } diff --git a/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp b/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp index 4d4c1199f3e..cc313512316 100644 --- a/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_ViewerBaseOperation.cpp @@ -87,20 +87,16 @@ void ViewerBaseOperation::initImage() /* now we combine the input with ibuf */ this->m_outputBuffer = ibuf->rect_float; - /* needed for display buffer update - * - * no need to lock / reference the image buffer because it's seems - * to be the single place which changes buffers of viewer image - * which is this node - */ + /* needed for display buffer update */ this->m_ibuf = ibuf; if (m_doDepthBuffer) { this->m_depthBuffer = ibuf->zbuf_float; } - BKE_image_release_ibuf(this->m_image, this->m_lock); + BKE_image_release_ibuf(this->m_image, this->m_ibuf, this->m_lock); } + void ViewerBaseOperation:: updateImage(rcti *rect) { IMB_partial_display_buffer_update(this->m_ibuf, this->m_outputBuffer, NULL, getWidth(), 0, 0, diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index f19dbe740bc..fe836204c27 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -1560,6 +1560,8 @@ static int animchannels_setflag_exec(bContext *C, wmOperator *op) /* duplicate of 'ANIM_OT_channels_setting_toggle' for menu title only, weak! */ static void ANIM_OT_channels_setting_enable(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Enable Channel Setting"; ot->idname = "ANIM_OT_channels_setting_enable"; @@ -1575,13 +1577,16 @@ static void ANIM_OT_channels_setting_enable(wmOperatorType *ot) /* props */ /* flag-setting mode */ - RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_ADD, "Mode", ""); + prop = RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_ADD, "Mode", ""); + RNA_def_property_flag(prop, PROP_HIDDEN); /* setting to set */ ot->prop = RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", ""); } /* duplicate of 'ANIM_OT_channels_setting_toggle' for menu title only, weak! */ static void ANIM_OT_channels_setting_disable(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Disable Channel Setting"; ot->idname = "ANIM_OT_channels_setting_disable"; @@ -1597,13 +1602,16 @@ static void ANIM_OT_channels_setting_disable(wmOperatorType *ot) /* props */ /* flag-setting mode */ - RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_CLEAR, "Mode", ""); + prop = RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_CLEAR, "Mode", ""); + RNA_def_property_flag(prop, PROP_HIDDEN); /* internal hack - don't expose */ /* setting to set */ ot->prop = RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", ""); } static void ANIM_OT_channels_setting_toggle(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Toggle Channel Setting"; ot->idname = "ANIM_OT_channels_setting_toggle"; @@ -1619,13 +1627,16 @@ static void ANIM_OT_channels_setting_toggle(wmOperatorType *ot) /* props */ /* flag-setting mode */ - RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_TOGGLE, "Mode", ""); + prop = RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_TOGGLE, "Mode", ""); + RNA_def_property_flag(prop, PROP_HIDDEN); /* internal hack - don't expose */ /* setting to set */ ot->prop = RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", ""); } static void ANIM_OT_channels_editable_toggle(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Toggle Channel Editability"; ot->idname = "ANIM_OT_channels_editable_toggle"; @@ -1642,7 +1653,8 @@ static void ANIM_OT_channels_editable_toggle(wmOperatorType *ot) /* flag-setting mode */ RNA_def_enum(ot->srna, "mode", prop_animchannel_setflag_types, ACHANNEL_SETFLAG_TOGGLE, "Mode", ""); /* setting to set */ - RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, ACHANNEL_SETTING_PROTECT, "Type", ""); + prop = RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, ACHANNEL_SETTING_PROTECT, "Type", ""); + RNA_def_property_flag(prop, PROP_HIDDEN); /* internal hack - don't expose */ } /* ********************** Expand Channels Operator *********************** */ diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c index 8124dd268be..3846a5a2380 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -3569,16 +3569,16 @@ static int armature_subdivide_exec(bContext *C, wmOperator *op) Object *obedit = CTX_data_edit_object(C); bArmature *arm = obedit->data; EditBone *newbone, *tbone; - int numcuts, i; + int cuts, i; /* there may not be a number_cuts property defined (for 'simple' subdivide) */ - numcuts = RNA_int_get(op->ptr, "number_cuts"); + cuts = RNA_int_get(op->ptr, "number_cuts"); /* loop over all editable bones */ // XXX the old code did this in reverse order though! CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) { - for (i = numcuts + 1; i > 1; i--) { + for (i = cuts + 1; i > 1; i--) { /* compute cut ratio first */ float cutratio = 1.0f / (float)i; float cutratioI = 1.0f - cutratio; diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 957dcfbd848..23fed4ce8fc 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -1069,7 +1069,7 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) Nurb *nu = editnurb->nurbs.first; CVKeyIndex *keyIndex; char rna_path[64], orig_rna_path[64]; - AnimData *ad = BKE_animdata_from_id(&cu->id); + AnimData *adt = BKE_animdata_from_id(&cu->id); ListBase curves = {NULL, NULL}; FCurve *fcu, *next; @@ -1089,14 +1089,14 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) char handle_path[64], orig_handle_path[64]; BLI_snprintf(orig_handle_path, sizeof(orig_rna_path), "%s.handle_left", orig_rna_path); BLI_snprintf(handle_path, sizeof(rna_path), "%s.handle_right", rna_path); - fcurve_path_rename(ad, orig_handle_path, handle_path, orig_curves, &curves); + fcurve_path_rename(adt, orig_handle_path, handle_path, orig_curves, &curves); BLI_snprintf(orig_handle_path, sizeof(orig_rna_path), "%s.handle_right", orig_rna_path); BLI_snprintf(handle_path, sizeof(rna_path), "%s.handle_left", rna_path); - fcurve_path_rename(ad, orig_handle_path, handle_path, orig_curves, &curves); + fcurve_path_rename(adt, orig_handle_path, handle_path, orig_curves, &curves); } - fcurve_path_rename(ad, orig_rna_path, rna_path, orig_curves, &curves); + fcurve_path_rename(adt, orig_rna_path, rna_path, orig_curves, &curves); keyIndex->nu_index = nu_index; keyIndex->pt_index = pt_index; @@ -1116,7 +1116,7 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) if (keyIndex) { BLI_snprintf(rna_path, sizeof(rna_path), "splines[%d].points[%d]", nu_index, pt_index); BLI_snprintf(orig_rna_path, sizeof(orig_rna_path), "splines[%d].points[%d]", keyIndex->nu_index, keyIndex->pt_index); - fcurve_path_rename(ad, orig_rna_path, rna_path, orig_curves, &curves); + fcurve_path_rename(adt, orig_rna_path, rna_path, orig_curves, &curves); keyIndex->nu_index = nu_index; keyIndex->pt_index = pt_index; @@ -1140,7 +1140,7 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) char *ch = strchr(fcu->rna_path, '.'); if (ch && (!strncmp(ch, ".bezier_points", 14) || !strncmp(ch, ".points", 7))) - fcurve_remove(ad, orig_curves, fcu); + fcurve_remove(adt, orig_curves, fcu); } } @@ -1156,7 +1156,7 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) if (keyIndex) { BLI_snprintf(rna_path, sizeof(rna_path), "splines[%d]", nu_index); BLI_snprintf(orig_rna_path, sizeof(orig_rna_path), "splines[%d]", keyIndex->nu_index); - fcurve_path_rename(ad, orig_rna_path, rna_path, orig_curves, &curves); + fcurve_path_rename(adt, orig_rna_path, rna_path, orig_curves, &curves); } nu_index++; @@ -1168,7 +1168,7 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) for (fcu = orig_curves->first; fcu; fcu = next) { next = fcu->next; - if (!strncmp(fcu->rna_path, "splines", 7)) fcurve_remove(ad, orig_curves, fcu); + if (!strncmp(fcu->rna_path, "splines", 7)) fcurve_remove(adt, orig_curves, fcu); else BLI_addtail(&curves, fcu); } @@ -1178,14 +1178,14 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) /* return 0 if animation data wasn't changed, 1 otherwise */ int ED_curve_updateAnimPaths(Curve *cu) { - AnimData *ad = BKE_animdata_from_id(&cu->id); + AnimData *adt = BKE_animdata_from_id(&cu->id); if (!curve_is_animated(cu)) return 0; - if (ad->action) - curve_rename_fcurves(cu, &ad->action->curves); + if (adt->action) + curve_rename_fcurves(cu, &adt->action->curves); - curve_rename_fcurves(cu, &ad->drivers); + curve_rename_fcurves(cu, &adt->drivers); return 1; } @@ -3678,10 +3678,12 @@ static int is_u_selected(Nurb *nu, int u) /* what about resolu == 2? */ bp = &nu->bp[u]; for (v = 0; v < nu->pntsv - 1; v++, bp += nu->pntsu) { - if (v) if (bp->f1 & SELECT) return 1; + if ((v != 0) && (bp->f1 & SELECT)) { + return TRUE; + } } - return 0; + return FALSE; } typedef struct NurbSort { @@ -6464,7 +6466,7 @@ Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type bp->vec[0] += fac * grid; fac = (float)b - 1.5f; bp->vec[1] += fac * grid; - if (a == 1 || a == 2) if (b == 1 || b == 2) { + if ((a == 1 || a == 2) && (b == 1 || b == 2)) { bp->vec[2] += grid; } mul_m4_v3(mat, bp->vec); diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index fd87e6752f2..257dfca051f 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -1289,6 +1289,13 @@ static int insert_text_invoke(bContext *C, wmOperator *op, wmEvent *evt) insert_into_textbuf(obedit, ascii); accentcode = 0; } + else if (ascii) { + insert_into_textbuf(obedit, ascii); + accentcode = 0; + } + else { + BLI_assert(0); + } kill_selection(obedit, 1); text_update_edited(C, scene, obedit, 1, FO_EDIT); diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index ed8a1ea8280..e9ca7392752 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -40,8 +40,10 @@ #include "BLI_math.h" #include "BLI_blenlib.h" +#include "BLI_rand.h" #include "BLI_utildefines.h" +#include "DNA_anim_types.h" #include "DNA_curve_types.h" #include "DNA_object_types.h" #include "DNA_node_types.h" @@ -51,14 +53,19 @@ #include "DNA_view3d_types.h" #include "DNA_gpencil_types.h" +#include "BKE_animsys.h" #include "BKE_context.h" #include "BKE_curve.h" +#include "BKE_depsgraph.h" +#include "BKE_fcurve.h" +#include "BKE_global.h" #include "BKE_gpencil.h" #include "BKE_library.h" #include "BKE_object.h" #include "BKE_report.h" #include "BKE_tracking.h" +#include "UI_interface.h" #include "WM_api.h" #include "WM_types.h" @@ -71,6 +78,7 @@ #include "ED_gpencil.h" #include "ED_view3d.h" #include "ED_clip.h" +#include "ED_keyframing.h" #include "gpencil_intern.h" @@ -131,11 +139,11 @@ bGPdata **gpencil_data_get_pointers(const bContext *C, PointerRNA *ptr) return &sseq->gpd; } break; - + case SPACE_IMAGE: /* Image/UV Editor */ { SpaceImage *sima = (SpaceImage *)CTX_wm_space_data(C); - + /* for now, Grease Pencil data is associated with the space... */ /* XXX our convention for everything else is to link to data though... */ if (ptr) RNA_pointer_create(screen_id, &RNA_SpaceImageEditor, sima, ptr); @@ -151,19 +159,19 @@ bGPdata **gpencil_data_get_pointers(const bContext *C, PointerRNA *ptr) if (clip) { if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) { MovieTrackingTrack *track = BKE_tracking_track_get_active(&clip->tracking); - + if (!track) return NULL; - + if (ptr) RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, ptr); - + return &track->gpd; } else { if (ptr) RNA_id_pointer_create(&clip->id, ptr); - + return &clip->gpd; } } @@ -387,6 +395,14 @@ enum { GP_STROKECONVERT_CURVE, }; +/* Defines for possible timing modes */ +enum { + GP_STROKECONVERT_TIMING_NONE = 1, + GP_STROKECONVERT_TIMING_LINEAR = 2, + GP_STROKECONVERT_TIMING_FULL = 3, + GP_STROKECONVERT_TIMING_CUSTOMGAP = 4, +}; + /* RNA enum define */ static EnumPropertyItem prop_gpencil_convertmodes[] = { {GP_STROKECONVERT_PATH, "PATH", 0, "Path", ""}, @@ -394,6 +410,31 @@ static EnumPropertyItem prop_gpencil_convertmodes[] = { {0, NULL, 0, NULL, NULL} }; +static EnumPropertyItem prop_gpencil_convert_timingmodes_restricted[] = { + {GP_STROKECONVERT_TIMING_NONE, "NONE", 0, "No Timing", "Ignore timing"}, + {GP_STROKECONVERT_TIMING_LINEAR, "LINEAR", 0, "Linear", "Simple linear timing"}, + {0, NULL, 0, NULL, NULL}, +}; + +static EnumPropertyItem prop_gpencil_convert_timingmodes[] = { + {GP_STROKECONVERT_TIMING_NONE, "NONE", 0, "No Timing", "Ignore timing"}, + {GP_STROKECONVERT_TIMING_LINEAR, "LINEAR", 0, "Linear", "Simple linear timing"}, + {GP_STROKECONVERT_TIMING_FULL, "FULL", 0, "Original", "Use the original timing, gaps included"}, + {GP_STROKECONVERT_TIMING_CUSTOMGAP, "CUSTOMGAP", 0, "Custom Gaps", + "Use the original timing, but with custom gap lengths (in frames)"}, + {0, NULL, 0, NULL, NULL}, +}; + +static EnumPropertyItem *rna_GPConvert_mode_items(bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), + int *free) +{ + *free = FALSE; + if (RNA_boolean_get(ptr, "use_timing_data")) { + return prop_gpencil_convert_timingmodes; + } + return prop_gpencil_convert_timingmodes_restricted; +} + /* --- */ /* convert the coordinates from the given stroke point into 3d-coordinates @@ -430,7 +471,7 @@ static void gp_strokepoint_convertcoords(bContext *C, bGPDstroke *gps, bGPDspoin mvalf[1] = (float)pt->y / 100.0f * ar->winy; } } - + /* convert screen coordinate to 3d coordinates * - method taken from editview.c - mouse_cursor() */ @@ -440,47 +481,510 @@ static void gp_strokepoint_convertcoords(bContext *C, bGPDstroke *gps, bGPDspoin /* --- */ -/* convert stroke to 3d path */ -static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect) +/* temp struct for gp_stroke_path_animation() */ +typedef struct tGpTimingData { + /* Data set from operator settings */ + int mode; + int frame_range; /* Number of frames evaluated for path animation */ + int start_frame, end_frame; + int realtime; /* A bool, actually, will overwrite end_frame in case of Original or CustomGap timing... */ + float gap_duration, gap_randomness; /* To be used with CustomGap mode*/ + int seed; + + /* Data set from points, used to compute final timing FCurve */ + int num_points, cur_point; + + /* Distances */ + float *dists; + float tot_dist; + + /* Times */ + float *times; /* Note: Gap times will be negative! */ + float tot_time, gap_tot_time; + double inittime; +} tGpTimingData; + +/* init point buffers for timing data */ +static void _gp_timing_data_set_nbr(tGpTimingData *gtd, int nbr) { - bGPDspoint *pt; - Nurb *nu; - BPoint *bp; + float *tmp; + + BLI_assert(nbr > gtd->num_points); + + /* distances */ + tmp = gtd->dists; + gtd->dists = MEM_callocN(sizeof(float) * nbr, __func__); + if (tmp) { + memcpy(gtd->dists, tmp, sizeof(float) * gtd->num_points); + MEM_freeN(tmp); + } + + /* times */ + tmp = gtd->times; + gtd->times = MEM_callocN(sizeof(float) * nbr, __func__); + if (tmp) { + memcpy(gtd->times, tmp, sizeof(float) * gtd->num_points); + MEM_freeN(tmp); + } + + gtd->num_points = nbr; +} + +/* add stroke point to timing buffers */ +static void gp_timing_data_add_point(tGpTimingData *gtd, double stroke_inittime, float time, float delta_dist) +{ + if (time < 0.0f) { + /* This is a gap, negative value! */ + gtd->times[gtd->cur_point] = -(((float)(stroke_inittime - gtd->inittime)) + time); + gtd->tot_time = -gtd->times[gtd->cur_point]; + + gtd->gap_tot_time += gtd->times[gtd->cur_point] - gtd->times[gtd->cur_point - 1]; + } + else { + gtd->times[gtd->cur_point] = (((float)(stroke_inittime - gtd->inittime)) + time); + gtd->tot_time = (gtd->times[gtd->cur_point]); + } + + gtd->tot_dist += delta_dist; + gtd->dists[gtd->cur_point] = gtd->tot_dist; + + gtd->cur_point++; +} + +/* In frames! Binary search for FCurve keys have a threshold of 0.01, so we can't set + * arbitrarily close points - this is esp. important with NoGaps mode! + */ +#define MIN_TIME_DELTA 0.02f + +/* Loop over next points to find the end of the stroke, and compute */ +static int gp_find_end_of_stroke_idx(tGpTimingData *gtd, int idx, int nbr_gaps, int *nbr_done_gaps, + float tot_gaps_time, float delta_time, float *next_delta_time) +{ + int j; + + for (j = idx + 1; j < gtd->num_points; j++) { + if (gtd->times[j] < 0) { + gtd->times[j] = -gtd->times[j]; + if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) { + /* In this mode, gap time between this stroke and the next should be 0 currently... + * So we have to compute its final duration! + */ + if (gtd->gap_randomness > 0.0f) { + /* We want gaps that are in gtd->gap_duration +/- gtd->gap_randomness range, + * and which sum to exactly tot_gaps_time... + */ + int rem_gaps = nbr_gaps - (*nbr_done_gaps); + if (rem_gaps < 2) { + /* Last gap, just give remaining time! */ + *next_delta_time = tot_gaps_time; + } + else { + float delta, min, max; + + /* This code ensures that if the first gaps have been shorter than average gap_duration, + * next gaps will tend to be longer (i.e. try to recover the lateness), and vice-versa! + */ + delta = delta_time - (gtd->gap_duration * (*nbr_done_gaps)); + + /* Clamp min between [-gap_randomness, 0.0], with lower delta giving higher min */ + min = -gtd->gap_randomness - delta; + CLAMP(min, -gtd->gap_randomness, 0.0f); + + /* Clamp max between [0.0, gap_randomness], with lower delta giving higher max */ + max = gtd->gap_randomness - delta; + CLAMP(max, 0.0f, gtd->gap_randomness); + *next_delta_time += gtd->gap_duration + (BLI_frand() * (max - min)) + min; + } + } + else { + *next_delta_time += gtd->gap_duration; + } + } + (*nbr_done_gaps)++; + break; + } + } + + return j - 1; +} + +static void gp_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, int *nbr_gaps, float *tot_gaps_time) +{ + int i; + float delta_time = 0.0f; + + for (i = 0; i < gtd->num_points; i++) { + if (gtd->times[i] < 0 && i) { + (*nbr_gaps)++; + gtd->times[i] = -gtd->times[i] - delta_time; + delta_time += gtd->times[i] - gtd->times[i - 1]; + gtd->times[i] = -gtd->times[i - 1]; /* Temp marker, values *have* to be different! */ + } + else { + gtd->times[i] -= delta_time; + } + } + gtd->tot_time -= delta_time; + + *tot_gaps_time = (float)(*nbr_gaps) * gtd->gap_duration; + gtd->tot_time += *tot_gaps_time; + if (G.debug & G_DEBUG) { + printf("%f, %f, %f, %d\n", gtd->tot_time, delta_time, *tot_gaps_time, *nbr_gaps); + } + if (gtd->gap_randomness > 0.0f) { + BLI_srandom(gtd->seed); + } +} + +static void gp_stroke_path_animation_add_keyframes(ReportList *reports, PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, + Curve *cu, tGpTimingData *gtd, float time_range, + int nbr_gaps, float tot_gaps_time) +{ + /* Use actual recorded timing! */ + float time_start = (float)gtd->start_frame; + + float last_valid_time = 0.0f; + int end_stroke_idx = -1, start_stroke_idx = 0; + float end_stroke_time = 0.0f; + + /* CustomGaps specific */ + float delta_time = 0.0f, next_delta_time = 0.0f; + int nbr_done_gaps = 0; + int i; + float cfra; + + /* This is a bit tricky, as: + * - We can't add arbitrarily close points on FCurve (in time). + * - We *must* have all "caps" points of all strokes in FCurve, as much as possible! + */ + for (i = 0; i < gtd->num_points; i++) { + /* If new stroke... */ + if (i > end_stroke_idx) { + start_stroke_idx = i; + delta_time = next_delta_time; + /* find end of that new stroke */ + end_stroke_idx = gp_find_end_of_stroke_idx(gtd, i, nbr_gaps, &nbr_done_gaps, + tot_gaps_time, delta_time, &next_delta_time); + /* This one should *never* be negative! */ + end_stroke_time = time_start + ((gtd->times[end_stroke_idx] + delta_time) / gtd->tot_time * time_range); + } + + /* Simple proportional stuff... */ + cu->ctime = gtd->dists[i] / gtd->tot_dist * cu->pathlen; + cfra = time_start + ((gtd->times[i] + delta_time) / gtd->tot_time * time_range); + + /* And now, the checks about timing... */ + if (i == start_stroke_idx) { + /* If first point of a stroke, be sure it's enough ahead of last valid keyframe, and + * that the end point of the stroke is far enough! + * In case it is not, we keep the end point... + * Note that with CustomGaps mode, this is here we set the actual gap timing! + */ + if ((end_stroke_time - last_valid_time) > MIN_TIME_DELTA * 2) { + if ((cfra - last_valid_time) < MIN_TIME_DELTA) { + cfra = last_valid_time + MIN_TIME_DELTA; + } + insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); + last_valid_time = cfra; + } + else if (G.debug & G_DEBUG) { + printf("\t Skipping start point %d, too close from end point %d\n", i, end_stroke_idx); + } + } + else if (i == end_stroke_idx) { + /* Always try to insert end point of a curve (should be safe enough, anyway...) */ + if ((cfra - last_valid_time) < MIN_TIME_DELTA) { + cfra = last_valid_time + MIN_TIME_DELTA; + } + insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); + last_valid_time = cfra; + } + else { + /* Else ("middle" point), we only insert it if it's far enough from last keyframe, + * and also far enough from (not yet added!) end_stroke keyframe! + */ + if ((cfra - last_valid_time) > MIN_TIME_DELTA && (end_stroke_time - cfra) > MIN_TIME_DELTA) { + insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); + last_valid_time = cfra; + } + else if (G.debug & G_DEBUG) { + printf("\t Skipping \"middle\" point %d, too close from last added point or end point %d\n", + i, end_stroke_idx); + } + } + } +} - /* create new 'nurb' within the curve */ - nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_path(nurb)"); +static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu, tGpTimingData *gtd) +{ + Scene *scene = CTX_data_scene(C); + bAction *act; + FCurve *fcu; + PointerRNA ptr; + PropertyRNA *prop = NULL; + int nbr_gaps = 0, i; + + if (gtd->mode == GP_STROKECONVERT_TIMING_NONE) + return; + + /* gap_duration and gap_randomness are in frames, but we need seconds!!! */ + gtd->gap_duration = FRA2TIME(gtd->gap_duration); + gtd->gap_randomness = FRA2TIME(gtd->gap_randomness); - nu->pntsu = gps->totpoints; - nu->pntsv = 1; - nu->orderu = gps->totpoints; - nu->flagu = CU_NURB_ENDPOINT; - nu->resolu = 32; + /* Enable path! */ + cu->flag |= CU_PATH; + cu->pathlen = gtd->frame_range; - nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * gps->totpoints, "bpoints"); + /* Get RNA pointer to read/write path time values */ + RNA_id_pointer_create((ID *)cu, &ptr); + prop = RNA_struct_find_property(&ptr, "eval_time"); + + /* Ensure we have an F-Curve to add keyframes to */ + act = verify_adt_action((ID *)cu, TRUE); + fcu = verify_fcurve(act, NULL, &ptr, "eval_time", 0, TRUE); + + if (G.debug & G_DEBUG) { + printf("%s: tot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time); + for (i = 0; i < gtd->num_points; i++) { + printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]); + } + } + + if (gtd->mode == GP_STROKECONVERT_TIMING_LINEAR) { + float cfra; + + /* Linear extrapolation! */ + fcu->extend = FCURVE_EXTRAPOLATE_LINEAR; + + cu->ctime = 0.0f; + cfra = (float)gtd->start_frame; + insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); + + cu->ctime = cu->pathlen; + if (gtd->realtime) { + cfra += (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */ + } + else { + cfra = (float)gtd->end_frame; + } + insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); + } + else { + /* Use actual recorded timing! */ + float time_range; + + /* CustomGaps specific */ + float tot_gaps_time = 0.0f; + + /* Pre-process gaps, in case we don't want to keep their original timing */ + if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) { + gp_stroke_path_animation_preprocess_gaps(gtd, &nbr_gaps, &tot_gaps_time); + } + + if (gtd->realtime) { + time_range = (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */ + } + else { + time_range = (float)(gtd->end_frame - gtd->start_frame); + } + + if (G.debug & G_DEBUG) { + printf("GP Stroke Path Conversion: Starting keying!\n"); + } + + gp_stroke_path_animation_add_keyframes(reports, ptr, prop, fcu, cu, gtd, time_range, + nbr_gaps, tot_gaps_time); + } + + /* As we used INSERTKEY_FAST mode, we need to recompute all curve's handles now */ + calchandles_fcurve(fcu); + + if (G.debug & G_DEBUG) { + printf("%s: \ntot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time); + for (i = 0; i < gtd->num_points; i++) { + printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]); + } + printf("\n\n"); + } + + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + + /* send updates */ + DAG_id_tag_update(&cu->id, 0); +} + +#undef MIN_TIME_DELTA + +#define GAP_DFAC 0.05f +#define WIDTH_CORR_FAC 0.1f +#define BEZT_HANDLE_FAC 0.3f + +/* convert stroke to 3d path */ +static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu, + float minmax_weights[2], float rad_fac, int stitch, tGpTimingData *gtd) +{ + bGPDspoint *pt; + Nurb *nu = (curnu) ? *curnu : NULL; + BPoint *bp, *prev_bp = NULL; + const int do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE); + int i, old_nbp = 0; + + /* create new 'nurb' or extend current one within the curve */ + if (nu) { + old_nbp = nu->pntsu; + + /* If stitch, the first point of this stroke is already present in current nu. + * Else, we have to add to additional points to make the zero-radius link between strokes. + */ + BKE_nurb_points_add(nu, gps->totpoints + (stitch ? -1 : 2)); + } + else { + nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_path(nurb)"); + + nu->pntsu = gps->totpoints; + nu->pntsv = 1; + nu->orderu = 2; /* point-to-point! */ + nu->type = CU_NURBS; + nu->flagu = CU_NURB_ENDPOINT; + nu->resolu = cu->resolu; + nu->resolv = cu->resolv; + nu->knotsu = NULL; + + nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * nu->pntsu, "bpoints"); + + stitch = FALSE; /* Security! */ + } + + if (do_gtd) { + _gp_timing_data_set_nbr(gtd, nu->pntsu); + } + + /* If needed, make the link between both strokes with two zero-radius additional points */ + /* About "zero-radius" point interpolations: + * - If we have at least two points in current curve (most common case), we linearly extrapolate + * the last segment to get the first point (p1) position and timing. + * - If we do not have those (quite odd, but may happen), we linearly interpolate the last point + * with the first point of the current stroke. + * The same goes for the second point, first segment of the current stroke is "negatively" extrapolated + * if it exists, else (if the stroke is a single point), linear interpolation with last curve point... + */ + if (curnu && !stitch && old_nbp) { + float p1[3], p2[3], p[3], next_p[3]; + float delta_time; + + prev_bp = NULL; + if ((old_nbp > 1) && gps->prev && (gps->prev->totpoints > 1)) { + /* Only use last curve segment if previous stroke was not a single-point one! */ + prev_bp = nu->bp + old_nbp - 2; + } + bp = nu->bp + old_nbp - 1; + + /* XXX We do this twice... Not sure it's worth to bother about this! */ + gp_strokepoint_convertcoords(C, gps, gps->points, p, subrect); + if (prev_bp) { + interp_v3_v3v3(p1, prev_bp->vec, bp->vec, 1.0f + GAP_DFAC); + } + else { + interp_v3_v3v3(p1, bp->vec, p, GAP_DFAC); + } + + if (gps->totpoints > 1) { + /* XXX We do this twice... Not sure it's worth to bother about this! */ + gp_strokepoint_convertcoords(C, gps, gps->points + 1, next_p, subrect); + interp_v3_v3v3(p2, p, next_p, -GAP_DFAC); + } + else { + interp_v3_v3v3(p2, p, bp->vec, GAP_DFAC); + } + + /* First point */ + bp++; + copy_v3_v3(bp->vec, p1); + bp->vec[3] = 1.0f; + bp->f1 = SELECT; + minmax_weights[0] = bp->radius = bp->weight = 0.0f; + if (do_gtd) { + if (prev_bp) { + delta_time = gtd->tot_time + (gtd->tot_time - gtd->times[gtd->cur_point - 1]) * GAP_DFAC; + } + else { + delta_time = gtd->tot_time + (((float)(gps->inittime - gtd->inittime)) - gtd->tot_time) * GAP_DFAC; + } + gp_timing_data_add_point(gtd, gtd->inittime, delta_time, len_v3v3((bp - 1)->vec, p1)); + } + + /* Second point */ + bp++; + copy_v3_v3(bp->vec, p2); + bp->vec[3] = 1.0f; + bp->f1 = SELECT; + minmax_weights[0] = bp->radius = bp->weight = 0.0f; + if (do_gtd) { + /* This negative delta_time marks the gap! */ + if (gps->totpoints > 1) { + delta_time = ((gps->points + 1)->time - gps->points->time) * -GAP_DFAC; + } + else { + delta_time = -(((float)(gps->inittime - gtd->inittime)) - gtd->tot_time) * GAP_DFAC; + } + gp_timing_data_add_point(gtd, gps->inittime, delta_time, len_v3v3(p1, p2)); + } + + old_nbp += 2; + } + if (old_nbp && do_gtd) { + prev_bp = nu->bp + old_nbp - 1; + } /* add points */ - for (i = 0, pt = gps->points, bp = nu->bp; i < gps->totpoints; i++, pt++, bp++) { + for (i = (stitch) ? 1 : 0, pt = gps->points + ((stitch) ? 1 : 0), bp = nu->bp + old_nbp; + i < gps->totpoints; + i++, pt++, bp++) + { float p3d[3]; + float width = pt->pressure * gpl->thickness * WIDTH_CORR_FAC; /* get coordinates to add at */ gp_strokepoint_convertcoords(C, gps, pt, p3d, subrect); copy_v3_v3(bp->vec, p3d); + bp->vec[3] = 1.0f; /* set settings */ bp->f1 = SELECT; - bp->radius = bp->weight = pt->pressure * gpl->thickness; + bp->radius = width * rad_fac; + bp->weight = width; + CLAMP(bp->weight, 0.0f, 1.0f); + if (bp->weight < minmax_weights[0]) { + minmax_weights[0] = bp->weight; + } + else if (bp->weight > minmax_weights[1]) { + minmax_weights[1] = bp->weight; + } + + /* Update timing data */ + if (do_gtd) { + gp_timing_data_add_point(gtd, gps->inittime, pt->time, (prev_bp) ? len_v3v3(prev_bp->vec, p3d) : 0.0f); + } + prev_bp = bp; } /* add nurb to curve */ - BLI_addtail(&cu->nurb, nu); + if (!curnu || !*curnu) { + BLI_addtail(&cu->nurb, nu); + } + if (curnu) { + *curnu = nu; + } + + BKE_nurb_knot_calc_u(nu); } static int gp_camera_view_subrect(bContext *C, rctf *subrect) { View3D *v3d = CTX_wm_view3d(C); ARegion *ar = CTX_wm_region(C); - + if (v3d) { RegionView3D *rv3d = ar->regiondata; @@ -491,48 +995,178 @@ static int gp_camera_view_subrect(bContext *C, rctf *subrect) return 1; } } - + return 0; } /* convert stroke to 3d bezier */ -static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect) +static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu, + float minmax_weights[2], float rad_fac, int stitch, tGpTimingData *gtd) { bGPDspoint *pt; - Nurb *nu; - BezTriple *bezt; - int i, tot; + Nurb *nu = (curnu) ? *curnu : NULL; + BezTriple *bezt, *prev_bezt = NULL; + int i, tot, old_nbezt = 0; float p3d_cur[3], p3d_prev[3], p3d_next[3]; + const int do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE); + + /* create new 'nurb' or extend current one within the curve */ + if (nu) { + old_nbezt = nu->pntsu; + /* If we do stitch, first point of current stroke is assumed the same as last point of previous stroke, + * so no need to add it. + * If no stitch, we want to add two additional points to make a "zero-radius" link between both strokes. + */ + BKE_nurb_bezierPoints_add(nu, gps->totpoints + ((stitch) ? -1 : 2)); + } + else { + nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_bezier(nurb)"); + + nu->pntsu = gps->totpoints; + nu->resolu = 12; + nu->resolv = 12; + nu->type = CU_BEZIER; + nu->bezt = (BezTriple *)MEM_callocN(gps->totpoints * sizeof(BezTriple), "bezts"); + + stitch = FALSE; /* Security! */ + } - /* create new 'nurb' within the curve */ - nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_bezier(nurb)"); - - nu->pntsu = gps->totpoints; - nu->resolu = 12; - nu->resolv = 12; - nu->type = CU_BEZIER; - nu->bezt = (BezTriple *)MEM_callocN(gps->totpoints * sizeof(BezTriple), "bezts"); + if (do_gtd) { + _gp_timing_data_set_nbr(gtd, nu->pntsu); + } tot = gps->totpoints; /* get initial coordinates */ pt = gps->points; if (tot) { - gp_strokepoint_convertcoords(C, gps, pt, p3d_cur, subrect); + gp_strokepoint_convertcoords(C, gps, pt, (stitch) ? p3d_prev : p3d_cur, subrect); if (tot > 1) { - gp_strokepoint_convertcoords(C, gps, pt + 1, p3d_next, subrect); + gp_strokepoint_convertcoords(C, gps, pt + 1, (stitch) ? p3d_cur : p3d_next, subrect); + } + if (stitch && tot > 2) { + gp_strokepoint_convertcoords(C, gps, pt + 2, p3d_next, subrect); } } + /* If needed, make the link between both strokes with two zero-radius additional points */ + if (curnu && old_nbezt) { + /* Update last point's second handle */ + if (stitch) { + float h2[3]; + bezt = nu->bezt + old_nbezt - 1; + interp_v3_v3v3(h2, bezt->vec[1], p3d_cur, BEZT_HANDLE_FAC); + copy_v3_v3(bezt->vec[2], h2); + pt++; + } + + /* Create "link points" */ + /* About "zero-radius" point interpolations: + * - If we have at least two points in current curve (most common case), we linearly extrapolate + * the last segment to get the first point (p1) position and timing. + * - If we do not have those (quite odd, but may happen), we linearly interpolate the last point + * with the first point of the current stroke. + * The same goes for the second point, first segment of the current stroke is "negatively" extrapolated + * if it exists, else (if the stroke is a single point), linear interpolation with last curve point... + */ + else { + float h1[3], h2[3], p1[3], p2[3]; + float delta_time; + + prev_bezt = NULL; + if (old_nbezt > 1 && gps->prev && gps->prev->totpoints > 1) { + /* Only use last curve segment if previous stroke was not a single-point one! */ + prev_bezt = nu->bezt + old_nbezt - 2; + } + bezt = nu->bezt + old_nbezt - 1; + if (prev_bezt) { + interp_v3_v3v3(p1, prev_bezt->vec[1], bezt->vec[1], 1.0f + GAP_DFAC); + } + else { + interp_v3_v3v3(p1, bezt->vec[1], p3d_cur, GAP_DFAC); + } + if (tot > 1) { + interp_v3_v3v3(p2, p3d_cur, p3d_next, -GAP_DFAC); + } + else { + interp_v3_v3v3(p2, p3d_cur, bezt->vec[1], GAP_DFAC); + } + + /* Second handle of last point */ + interp_v3_v3v3(h2, bezt->vec[1], p1, BEZT_HANDLE_FAC); + copy_v3_v3(bezt->vec[2], h2); + + /* First point */ + interp_v3_v3v3(h1, p1, bezt->vec[1], BEZT_HANDLE_FAC); + interp_v3_v3v3(h2, p1, p2, BEZT_HANDLE_FAC); + + bezt++; + copy_v3_v3(bezt->vec[0], h1); + copy_v3_v3(bezt->vec[1], p1); + copy_v3_v3(bezt->vec[2], h2); + bezt->h1 = bezt->h2 = HD_FREE; + bezt->f1 = bezt->f2 = bezt->f3 = SELECT; + minmax_weights[0] = bezt->radius = bezt->weight = 0.0f; + + if (do_gtd) { + if (prev_bezt) { + delta_time = gtd->tot_time + (gtd->tot_time - gtd->times[gtd->cur_point - 1]) * GAP_DFAC; + } + else { + delta_time = gtd->tot_time + (((float)(gps->inittime - gtd->inittime)) - gtd->tot_time) * GAP_DFAC; + } + gp_timing_data_add_point(gtd, gtd->inittime, delta_time, len_v3v3((bezt - 1)->vec[1], p1)); + } + + /* Second point */ + interp_v3_v3v3(h1, p2, p1, BEZT_HANDLE_FAC); + interp_v3_v3v3(h2, p2, p3d_cur, BEZT_HANDLE_FAC); + + bezt++; + copy_v3_v3(bezt->vec[0], h1); + copy_v3_v3(bezt->vec[1], p2); + copy_v3_v3(bezt->vec[2], h2); + bezt->h1 = bezt->h2 = HD_FREE; + bezt->f1 = bezt->f2 = bezt->f3 = SELECT; + minmax_weights[0] = bezt->radius = bezt->weight = 0.0f; + + if (do_gtd) { + /* This negative delta_time marks the gap! */ + if (tot > 1) { + delta_time = ((gps->points + 1)->time - gps->points->time) * -GAP_DFAC; + } + else { + delta_time = -(((float)(gps->inittime - gtd->inittime)) - gtd->tot_time) * GAP_DFAC; + } + gp_timing_data_add_point(gtd, gps->inittime, delta_time, len_v3v3(p1, p2)); + } + + old_nbezt += 2; + copy_v3_v3(p3d_prev, p2); + } + } + if (old_nbezt && do_gtd) { + prev_bezt = nu->bezt + old_nbezt - 1; + } + /* add points */ - for (i = 0, bezt = nu->bezt; i < tot; i++, pt++, bezt++) { + for (i = stitch ? 1 : 0, bezt = nu->bezt + old_nbezt; i < tot; i++, pt++, bezt++) { float h1[3], h2[3]; + float width = pt->pressure * gpl->thickness * WIDTH_CORR_FAC; - if (i) interp_v3_v3v3(h1, p3d_cur, p3d_prev, 0.3); - else interp_v3_v3v3(h1, p3d_cur, p3d_next, -0.3); + if (i || old_nbezt) { + interp_v3_v3v3(h1, p3d_cur, p3d_prev, BEZT_HANDLE_FAC); + } + else { + interp_v3_v3v3(h1, p3d_cur, p3d_next, -BEZT_HANDLE_FAC); + } - if (i < tot - 1) interp_v3_v3v3(h2, p3d_cur, p3d_next, 0.3); - else interp_v3_v3v3(h2, p3d_cur, p3d_prev, -0.3); + if (i < tot - 1) { + interp_v3_v3v3(h2, p3d_cur, p3d_next, BEZT_HANDLE_FAC); + } + else { + interp_v3_v3v3(h2, p3d_cur, p3d_prev, -BEZT_HANDLE_FAC); + } copy_v3_v3(bezt->vec[0], h1); copy_v3_v3(bezt->vec[1], p3d_cur); @@ -541,7 +1175,20 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu /* set settings */ bezt->h1 = bezt->h2 = HD_FREE; bezt->f1 = bezt->f2 = bezt->f3 = SELECT; - bezt->radius = bezt->weight = pt->pressure * gpl->thickness * 0.1f; + bezt->radius = width * rad_fac; + bezt->weight = width; + CLAMP(bezt->weight, 0.0f, 1.0f); + if (bezt->weight < minmax_weights[0]) { + minmax_weights[0] = bezt->weight; + } + else if (bezt->weight > minmax_weights[1]) { + minmax_weights[1] = bezt->weight; + } + + /* Update timing data */ + if (do_gtd) { + gp_timing_data_add_point(gtd, gps->inittime, pt->time, prev_bezt ? len_v3v3(prev_bezt->vec[1], p3d_cur) : 0.0f); + } /* shift coord vects */ copy_v3_v3(p3d_prev, p3d_cur); @@ -550,31 +1197,103 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu if (i + 2 < tot) { gp_strokepoint_convertcoords(C, gps, pt + 2, p3d_next, subrect); } + + prev_bezt = bezt; } - + /* must calculate handles or else we crash */ BKE_nurb_handles_calc(nu); - /* add nurb to curve */ - BLI_addtail(&cu->nurb, nu); + if (!curnu || !*curnu) { + BLI_addtail(&cu->nurb, nu); + } + if (curnu) { + *curnu = nu; + } +} + +#undef GAP_DFAC +#undef WIDTH_CORR_FAC +#undef BEZT_HANDLE_FAC + +static void gp_stroke_finalize_curve_endpoints(Curve *cu) +{ + /* start */ + Nurb *nu = cu->nurb.first; + int i = 0; + if (nu->bezt) { + BezTriple *bezt = nu->bezt; + if (bezt) { + bezt[i].weight = bezt[i].radius = 0.0f; + } + } + else if (nu->bp) { + BPoint *bp = nu->bp; + if (bp) { + bp[i].weight = bp[i].radius = 0.0f; + } + } + + /* end */ + nu = cu->nurb.last; + i = nu->pntsu - 1; + if (nu->bezt) { + BezTriple *bezt = nu->bezt; + if (bezt) { + bezt[i].weight = bezt[i].radius = 0.0f; + } + } + else if (nu->bp) { + BPoint *bp = nu->bp; + if (bp) { + bp[i].weight = bp[i].radius = 0.0f; + } + } +} + +static void gp_stroke_norm_curve_weights(Curve *cu, float minmax_weights[2]) +{ + Nurb *nu; + const float delta = minmax_weights[0]; + const float fac = 1.0f / (minmax_weights[1] - delta); + int i; + + for (nu = cu->nurb.first; nu; nu = nu->next) { + if (nu->bezt) { + BezTriple *bezt = nu->bezt; + for (i = 0; i < nu->pntsu; i++, bezt++) { + bezt->weight = (bezt->weight - delta) * fac; + } + } + else if (nu->bp) { + BPoint *bp = nu->bp; + for (i = 0; i < nu->pntsu; i++, bp++) { + bp->weight = (bp->weight - delta) * fac; + } + } + } } /* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */ -static void gp_layer_to_curve(bContext *C, bGPdata *gpd, bGPDlayer *gpl, short mode) +static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bGPDlayer *gpl, int mode, + int norm_weights, float rad_fac, int link_strokes, tGpTimingData *gtd) { Scene *scene = CTX_data_scene(C); bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0); - bGPDstroke *gps; + bGPDstroke *gps, *prev_gps = NULL; Object *ob; Curve *cu; + Nurb *nu = NULL; + Base *base = BASACT, *newbase = NULL; + float minmax_weights[2] = {1.0f, 0.0f}; /* camera framing */ rctf subrect, *subrect_ptr = NULL; - + /* error checking */ if (ELEM3(NULL, gpd, gpl, gpf)) return; - + /* only convert if there are any strokes on this layer's frame to convert */ if (gpf->strokes.first == NULL) return; @@ -583,7 +1302,7 @@ static void gp_layer_to_curve(bContext *C, bGPdata *gpd, bGPDlayer *gpl, short m if (gp_camera_view_subrect(C, &subrect)) { subrect_ptr = &subrect; } - + /* init the curve object (remove rotation and get curve data from it) * - must clear transforms set on object, as those skew our results */ @@ -597,24 +1316,125 @@ static void gp_layer_to_curve(bContext *C, bGPdata *gpd, bGPDlayer *gpl, short m rename_id((ID *)ob, gpl->info); rename_id((ID *)cu, gpl->info); + gtd->inittime = ((bGPDstroke *)gpf->strokes.first)->inittime; + /* add points to curve */ for (gps = gpf->strokes.first; gps; gps = gps->next) { + /* Detect new strokes created because of GP_STROKE_BUFFER_MAX reached, + * and stitch them to previous one. + */ + int stitch = FALSE; + + if (prev_gps) { + bGPDspoint *pt1 = prev_gps->points + prev_gps->totpoints - 1; + bGPDspoint *pt2 = gps->points; + + if ((pt1->x == pt2->x) && (pt1->y == pt2->y)) { + stitch = TRUE; + } + } + + /* Decide whether we connect this stroke to previous one */ + if (!(stitch || link_strokes)) { + nu = NULL; + } + switch (mode) { case GP_STROKECONVERT_PATH: - gp_stroke_to_path(C, gpl, gps, cu, subrect_ptr); + gp_stroke_to_path(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch, gtd); break; case GP_STROKECONVERT_CURVE: - gp_stroke_to_bezier(C, gpl, gps, cu, subrect_ptr); + gp_stroke_to_bezier(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch, gtd); break; default: BLI_assert(!"invalid mode"); break; } + prev_gps = gps; + } + + /* If link_strokes, be sure first and last points have a zero weight/size! */ + if (link_strokes) + gp_stroke_finalize_curve_endpoints(cu); + + /* Update curve's weights, if needed */ + if (norm_weights && ((minmax_weights[0] > 0.0f) || (minmax_weights[1] < 1.0f))) + gp_stroke_norm_curve_weights(cu, minmax_weights); + + /* Create the path animation, if needed */ + gp_stroke_path_animation(C, reports, cu, gtd); + + /* Reset original object as active, else we can't edit operator's settings!!! */ + /* set layers OK */ + newbase = BASACT; + if (base) { + newbase->lay = base->lay; + ob->lay = newbase->lay; + } + + /* restore, BKE_object_add sets active */ + BASACT = base; + if (base) { + base->flag |= SELECT; } } /* --- */ +/* Check a GP layer has valid timing data! Else, most timing options are hidden in the operator. + * op may be NULL. + */ +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; + bGPDspoint *pt; + double base_time, cur_time, prev_time = -1.0; + int i, valid = TRUE; + + do { + base_time = cur_time = gps->inittime; + if (cur_time <= prev_time) { + valid = FALSE; + break; + } + + prev_time = cur_time; + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + cur_time = base_time + (double)pt->time; + /* First point of a stroke should have the same time as stroke's inittime, + * so it's the only case where equality is allowed! + */ + if ((i && cur_time <= prev_time) || (cur_time < prev_time)) { + valid = FALSE; + break; + } + prev_time = cur_time; + } + + if (!valid) { + break; + } + } while ((gps = gps->next)); + + if (op) { + RNA_boolean_set(op->ptr, "use_timing_data", valid); + } + return valid; +} + +/* Check end_frame is always > start frame! */ +static void gp_convert_set_end_frame(struct Main *UNUSED(main), struct Scene *UNUSED(scene), struct PointerRNA *ptr) +{ + int start_frame = RNA_int_get(ptr, "start_frame"); + int end_frame = RNA_int_get(ptr, "end_frame"); + + if (end_frame <= start_frame) { + RNA_int_set(ptr, "end_frame", start_frame + 1); + } +} + static int gp_convert_poll(bContext *C) { bGPdata *gpd = gpencil_data_get_active(C); @@ -627,45 +1447,204 @@ static int gp_convert_poll(bContext *C) static int gp_convert_layer_exec(bContext *C, wmOperator *op) { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_timing_data"); bGPdata *gpd = gpencil_data_get_active(C); bGPDlayer *gpl = gpencil_layer_getactive(gpd); Scene *scene = CTX_data_scene(C); int mode = RNA_enum_get(op->ptr, "type"); - + int norm_weights = RNA_boolean_get(op->ptr, "use_normalize_weights"); + float rad_fac = RNA_float_get(op->ptr, "radius_multiplier"); + int link_strokes = RNA_boolean_get(op->ptr, "use_link_strokes"); + int valid_timing; + tGpTimingData gtd; + /* check if there's data to work with */ if (gpd == NULL) { - BKE_report(op->reports, RPT_ERROR, "No grease pencil data to work on"); + BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data to work on"); return OPERATOR_CANCELLED; } - - gp_layer_to_curve(C, gpd, gpl, mode); - + + if (!RNA_property_is_set(op->ptr, prop) && !gp_convert_check_has_valid_timing(C, gpl, op)) { + BKE_report(op->reports, RPT_WARNING, + "Current Grease Pencil strokes have no valid timing data, most timing options will be hidden!"); + } + valid_timing = RNA_property_boolean_get(op->ptr, prop); + + gtd.mode = RNA_enum_get(op->ptr, "timing_mode"); + /* Check for illegal timing mode! */ + if (!valid_timing && !ELEM(gtd.mode, GP_STROKECONVERT_TIMING_NONE, GP_STROKECONVERT_TIMING_LINEAR)) { + gtd.mode = GP_STROKECONVERT_TIMING_LINEAR; + RNA_enum_set(op->ptr, "timing_mode", gtd.mode); + } + if (!link_strokes) { + gtd.mode = GP_STROKECONVERT_TIMING_NONE; + } + + /* grab all relevant settings */ + gtd.frame_range = RNA_int_get(op->ptr, "frame_range"); + gtd.start_frame = RNA_int_get(op->ptr, "start_frame"); + gtd.realtime = valid_timing ? RNA_boolean_get(op->ptr, "use_realtime") : FALSE; + gtd.end_frame = RNA_int_get(op->ptr, "end_frame"); + gtd.gap_duration = RNA_float_get(op->ptr, "gap_duration"); + gtd.gap_randomness = RNA_float_get(op->ptr, "gap_randomness"); + gtd.gap_randomness = min_ff(gtd.gap_randomness, gtd.gap_duration); + gtd.seed = RNA_int_get(op->ptr, "seed"); + gtd.num_points = gtd.cur_point = 0; + gtd.dists = gtd.times = NULL; + gtd.tot_dist = gtd.tot_time = gtd.gap_tot_time = 0.0f; + gtd.inittime = 0.0; + + /* perform conversion */ + gp_layer_to_curve(C, op->reports, gpd, gpl, mode, norm_weights, rad_fac, link_strokes, >d); + + /* free temp memory */ + if (gtd.dists) { + MEM_freeN(gtd.dists); + gtd.dists = NULL; + } + if (gtd.times) { + MEM_freeN(gtd.times); + gtd.times = NULL; + } + /* notifiers */ WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); - + /* done */ return OPERATOR_FINISHED; } +static int gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop) +{ + const char *prop_id = RNA_property_identifier(prop); + int link_strokes = RNA_boolean_get(ptr, "use_link_strokes"); + int timing_mode = RNA_enum_get(ptr, "timing_mode"); + int realtime = RNA_boolean_get(ptr, "use_realtime"); + float gap_duration = RNA_float_get(ptr, "gap_duration"); + float gap_randomness = RNA_float_get(ptr, "gap_randomness"); + int valid_timing = RNA_boolean_get(ptr, "use_timing_data"); + + /* Always show those props */ + if (strcmp(prop_id, "type") == 0 || + strcmp(prop_id, "use_normalize_weights") == 0 || + strcmp(prop_id, "radius_multiplier") == 0 || + strcmp(prop_id, "use_link_strokes") == 0) + { + return TRUE; + } + + /* Never show this prop */ + if (strcmp(prop_id, "use_timing_data") == 0) + return FALSE; + + if (link_strokes) { + /* Only show when link_stroke is TRUE */ + if (strcmp(prop_id, "timing_mode") == 0) + return TRUE; + + if (timing_mode != GP_STROKECONVERT_TIMING_NONE) { + /* Only show when link_stroke is TRUE and stroke timing is enabled */ + if (strcmp(prop_id, "frame_range") == 0 || + strcmp(prop_id, "start_frame") == 0) + { + return TRUE; + } + + /* Only show if we have valid timing data! */ + if (valid_timing && strcmp(prop_id, "use_realtime") == 0) + return TRUE; + + /* Only show if realtime or valid_timing is FALSE! */ + if ((!realtime || !valid_timing) && strcmp(prop_id, "end_frame") == 0) + return TRUE; + + if (valid_timing && timing_mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) { + /* Only show for custom gaps! */ + if (strcmp(prop_id, "gap_duration") == 0) + return TRUE; + + /* Only show randomness for non-null custom gaps! */ + if (strcmp(prop_id, "gap_randomness") == 0 && (gap_duration > 0.0f)) + return TRUE; + + /* Only show seed for randomize action! */ + if (strcmp(prop_id, "seed") == 0 && (gap_duration > 0.0f) && (gap_randomness > 0.0f)) + return TRUE; + } + } + } + + /* Else, hidden! */ + return FALSE; +} + +static void gp_convert_ui(bContext *C, wmOperator *op) +{ + uiLayout *layout = op->layout; + wmWindowManager *wm = CTX_wm_manager(C); + PointerRNA ptr; + + RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); + + /* Main auto-draw call */ + uiDefAutoButsRNA(layout, &ptr, gp_convert_draw_check_prop, '\0'); +} + void GPENCIL_OT_convert(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Convert Grease Pencil"; ot->idname = "GPENCIL_OT_convert"; - ot->description = "Convert the active Grease Pencil layer to a new Object"; - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + ot->description = "Convert the active Grease Pencil layer to a new Curve Object"; /* callbacks */ ot->invoke = WM_menu_invoke; ot->exec = gp_convert_layer_exec; ot->poll = gp_convert_poll; + ot->ui = gp_convert_ui; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_convertmodes, 0, "Type", ""); + ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_convertmodes, 0, "Type", "Which type of curve to convert to"); + + RNA_def_boolean(ot->srna, "use_normalize_weights", TRUE, "Normalize Weight", + "Normalize weight (set from stroke width)"); + RNA_def_float(ot->srna, "radius_multiplier", 1.0f, 0.0f, 1000.0f, "Radius Fac", + "Multiplier for the points' radii (set from stroke width)", 0.0f, 10.0f); + RNA_def_boolean(ot->srna, "use_link_strokes", TRUE, "Link Strokes", + "Whether to link strokes with zero-radius sections of curves"); + + prop = RNA_def_enum(ot->srna, "timing_mode", prop_gpencil_convert_timingmodes, GP_STROKECONVERT_TIMING_FULL, + "Timing Mode", "How to use timing data stored in strokes"); + RNA_def_enum_funcs(prop, rna_GPConvert_mode_items); + + RNA_def_int(ot->srna, "frame_range", 100, 1, 10000, "Frame Range", + "The duration of evaluation of the path control curve", 1, 1000); + RNA_def_int(ot->srna, "start_frame", 1, 1, 100000, "Start Frame", + "The start frame of the path control curve", 1, 100000); + RNA_def_boolean(ot->srna, "use_realtime", FALSE, "Realtime", + "Whether the path control curve reproduces the drawing in realtime, starting from Start Frame"); + prop = RNA_def_int(ot->srna, "end_frame", 250, 1, 100000, "End Frame", + "The end frame of the path control curve (if Realtime is not set)", 1, 100000); + RNA_def_property_update_runtime(prop, gp_convert_set_end_frame); + + RNA_def_float(ot->srna, "gap_duration", 0.0f, 0.0f, 10000.0f, "Gap Duration", + "Custom Gap mode: (Average) length of gaps, in frames " + "(Note: Realtime value, will be scaled if Realtime is not set)", 0.0f, 1000.0f); + RNA_def_float(ot->srna, "gap_randomness", 0.0f, 0.0f, 10000.0f, "Gap Randomness", + "Custom Gap mode: Number of frames that gap lengths can vary", 0.0f, 1000.0f); + RNA_def_int(ot->srna, "seed", 0, 0, 1000, "Random Seed", + "Custom Gap mode: Random generator seed", 0, 100); + + /* Note: Internal use, this one will always be hidden by UI code... */ + prop = RNA_def_boolean(ot->srna, "use_timing_data", FALSE, "Has Valid Timing", + "Whether the converted Grease Pencil layer has valid timing data (internal use)"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /* ************************************************ */ diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 432292c259d..3fbd4a8f736 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -39,6 +39,8 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#include "PIL_time.h" + #include "BKE_gpencil.h" #include "BKE_context.h" #include "BKE_global.h" @@ -100,6 +102,14 @@ typedef struct tGPsdata { short radius; /* radius of influence for eraser */ short flags; /* flags that can get set during runtime */ + + /* These need to be doubles, as (at least under unix) they are in seconds since epoch, + * float (and its 7 digits precision) is definitively not enough here! + * double, with its 15 digits precision, ensures us millisecond precision for a few centuries at least. + */ + double inittime; /* Used when converting to path */ + double curtime; /* Used when converting to path */ + double ocurtime; /* Used when converting to path */ float imat[4][4]; /* inverted transformation matrix applying when converting coords from screen-space * to region space */ @@ -203,7 +213,7 @@ static void gp_get_3d_reference(tGPsdata *p, float vec[3]) float *fp = give_cursor(p->scene, v3d); /* the reference point used depends on the owner... */ -#if 0 // XXX: disabled for now, since we can't draw relative to the owner yet +#if 0 /* XXX: disabled for now, since we can't draw relative to the owner yet */ if (p->ownerPtr.type == &RNA_Object) { Object *ob = (Object *)p->ownerPtr.data; @@ -251,7 +261,7 @@ static short gp_stroke_filtermval(tGPsdata *p, const int mval[2], int pmval[2]) } /* convert screen-coordinates to buffer-coordinates */ -// XXX this method needs a total overhaul! +/* XXX this method needs a total overhaul! */ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3], float *depth) { bGPdata *gpd = p->gpd; @@ -312,7 +322,7 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3] } /* add current stroke-point to buffer (returns whether point was successfully added) */ -static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) +static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure, double curtime) { bGPdata *gpd = p->gpd; tGPspoint *pt; @@ -327,6 +337,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) /* store settings */ copy_v2_v2_int(&pt->x, mval); pt->pressure = pressure; + pt->time = (float)(curtime - p->inittime); /* increment buffer size */ gpd->sbuffer_size++; @@ -340,6 +351,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) /* store settings */ copy_v2_v2_int(&pt->x, mval); pt->pressure = pressure; + pt->time = (float)(curtime - p->inittime); /* if this is just the second point we've added, increment the buffer size * so that it will be drawn properly... @@ -363,6 +375,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) /* store settings */ copy_v2_v2_int(&pt->x, mval); pt->pressure = pressure; + pt->time = (float)(curtime - p->inittime); /* increment counters */ gpd->sbuffer_size++; @@ -380,10 +393,11 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) /* store settings */ copy_v2_v2_int(&pt->x, mval); pt->pressure = pressure; + pt->time = (float)(curtime - p->inittime); /* if there's stroke for this poly line session add (or replace last) point * to stroke. This allows to draw lines more interactively (see new segment - * during mouse slide, i.e.) + * during mouse slide, e.g.) */ if (gp_stroke_added_check(p)) { bGPDstroke *gps = p->gpf->strokes.last; @@ -412,8 +426,9 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &pt->x, &pts->x, NULL); - /* copy pressure */ + /* copy pressure and time */ pts->pressure = pt->pressure; + pts->time = pt->time; } /* increment counters */ @@ -427,18 +442,11 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) return GP_STROKEADD_INVALID; } - -/* temp struct for gp_stroke_smooth() */ -typedef struct tGpSmoothCo { - int x; - int y; -} tGpSmoothCo; - /* smooth a stroke (in buffer) before storing it */ static void gp_stroke_smooth(tGPsdata *p) { bGPdata *gpd = p->gpd; - tGpSmoothCo *smoothArray, *spc; + tGPspoint *spt, tmp_spt[3]; int i = 0, cmx = gpd->sbuffer_size; /* only smooth if smoothing is enabled, and we're not doing a straight line */ @@ -449,30 +457,28 @@ static void gp_stroke_smooth(tGPsdata *p) if ((cmx <= 2) || (gpd->sbuffer == NULL)) return; - /* create a temporary smoothing coordinates buffer, use to store calculated values to prevent sequential error */ - smoothArray = MEM_callocN(sizeof(tGpSmoothCo) * cmx, "gp_stroke_smooth smoothArray"); + /* Calculate smoothing coordinates using weighted-averages + * WARNING: we do NOT smooth first and last points (to avoid shrinkage) + */ + spt = (tGPspoint *)gpd->sbuffer; - /* first pass: calculate smoothing coordinates using weighted-averages */ - for (i = 0, spc = smoothArray; i < gpd->sbuffer_size; i++, spc++) { - const tGPspoint *pc = (((tGPspoint *)gpd->sbuffer) + i); - const tGPspoint *pb = (i - 1 > 0) ? (pc - 1) : (pc); - const tGPspoint *pa = (i - 2 > 0) ? (pc - 2) : (pb); - const tGPspoint *pd = (i + 1 < cmx) ? (pc + 1) : (pc); + /* This (tmp_spt) small array stores the last two points' original coordinates, + * as we don't want to use already averaged ones! It is used as a cyclic buffer... + */ + tmp_spt[0] = *spt; + for (i = 1, spt++; i < cmx - 1; i++, spt++) { + const tGPspoint *pc = spt; + const tGPspoint *pb = &tmp_spt[(i - 1) % 3]; + const tGPspoint *pa = (i - 1 > 0) ? (&tmp_spt[(i - 2) % 3]) : (pb); + const tGPspoint *pd = pc + 1; const tGPspoint *pe = (i + 2 < cmx) ? (pc + 2) : (pd); - spc->x = (int)(0.1 * pa->x + 0.2 * pb->x + 0.4 * pc->x + 0.2 * pd->x + 0.1 * pe->x); - spc->y = (int)(0.1 * pa->y + 0.2 * pb->y + 0.4 * pc->y + 0.2 * pd->y + 0.1 * pe->y); - } - - /* second pass: apply smoothed coordinates */ - for (i = 0, spc = smoothArray; i < gpd->sbuffer_size; i++, spc++) { - tGPspoint *pc = (((tGPspoint *)gpd->sbuffer) + i); + /* Store current point's original state for the two next points! */ + tmp_spt[i % 3] = *spt; - copy_v2_v2_int(&pc->x, &spc->x); + spt->x = (int)(0.1 * pa->x + 0.2 * pb->x + 0.4 * pc->x + 0.2 * pd->x + 0.1 * pe->x); + spt->y = (int)(0.1 * pa->y + 0.2 * pb->y + 0.4 * pc->y + 0.2 * pd->y + 0.1 * pe->y); } - - /* free temp array */ - MEM_freeN(smoothArray); } /* simplify a stroke (in buffer) before storing it @@ -494,7 +500,7 @@ static void gp_stroke_simplify(tGPsdata *p) /* don't simplify if less than 4 points in buffer */ if ((num_points <= 4) || (old_points == NULL)) return; - + /* clear buffer (but don't free mem yet) so that we can write to it * - firstly set sbuffer to NULL, so a new one is allocated * - secondly, reset flag after, as it gets cleared auto @@ -511,17 +517,21 @@ static void gp_stroke_simplify(tGPsdata *p) co[0] += (float)(old_points[offs].x * sfac); \ co[1] += (float)(old_points[offs].y * sfac); \ pressure += old_points[offs].pressure * sfac; \ + time += old_points[offs].time * sfac; \ } (void)0 + /* XXX Here too, do not lose start and end points! */ + gp_stroke_addpoint(p, &old_points->x, old_points->pressure, p->inittime + (double)old_points->time); for (i = 0, j = 0; i < num_points; i++) { if (i - j == 3) { - float co[2], pressure; + float co[2], pressure, time; int mco[2]; /* initialize values */ - co[0] = 0; - co[1] = 0; - pressure = 0; + co[0] = 0.0f; + co[1] = 0.0f; + pressure = 0.0f; + time = 0.0f; /* using macro, calculate new point */ GP_SIMPLIFY_AVPOINT(j, -0.25f); @@ -534,11 +544,13 @@ static void gp_stroke_simplify(tGPsdata *p) mco[1] = (int)co[1]; /* ignore return values on this... assume to be ok for now */ - gp_stroke_addpoint(p, mco, pressure); + gp_stroke_addpoint(p, mco, pressure, p->inittime + (double)time); j += 2; } } + gp_stroke_addpoint(p, &old_points[num_points - 1].x, old_points[num_points - 1].pressure, + p->inittime + (double)old_points[num_points - 1].time); /* free old buffer */ MEM_freeN(old_points); @@ -573,13 +585,14 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* special case for poly line -- for already added stroke during session * coordinates are getting added to stroke immediately to allow more - * interactive behavior */ + * interactive behavior + */ if (p->paintmode == GP_PAINTMODE_DRAW_POLY) { if (gp_stroke_added_check(p)) { return; } } - + /* allocate memory for a new stroke */ gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke"); @@ -587,13 +600,14 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) gps->totpoints = totelem; gps->thickness = p->gpl->thickness; gps->flag = gpd->sbuffer_sflag; + gps->inittime = p->inittime; /* allocate enough memory for a continuous array for storage points */ gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); - + /* set pointer to first non-initialized point */ pt = gps->points + (gps->totpoints - totelem); - + /* copy points from the buffer to the stroke */ if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) { /* straight lines only -> only endpoints */ @@ -604,8 +618,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); - /* copy pressure */ + /* copy pressure and time */ pt->pressure = ptc->pressure; + pt->time = ptc->time; pt++; } @@ -617,8 +632,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); - /* copy pressure */ + /* copy pressure and time */ pt->pressure = ptc->pressure; + pt->time = ptc->time; } } else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) { @@ -628,8 +644,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); - /* copy pressure */ + /* copy pressure and time */ pt->pressure = ptc->pressure; + pt->time = ptc->time; } else { float *depth_arr = NULL; @@ -701,14 +718,15 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &ptc->x, &pt->x, depth_arr ? depth_arr + i : NULL); - /* copy pressure */ + /* copy pressure and time */ pt->pressure = ptc->pressure; + pt->time = ptc->time; } if (depth_arr) MEM_freeN(depth_arr); } - + /* add stroke to frame */ BLI_addtail(&p->gpf->strokes, gps); gp_stroke_added_enable(p); @@ -721,7 +739,7 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i) { bGPDspoint *pt_tmp = gps->points; bGPDstroke *gsn = NULL; - + /* if stroke only had two points, get rid of stroke */ if (gps->totpoints == 2) { /* free stroke points, then stroke */ @@ -731,7 +749,7 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i) /* nothing left in stroke, so stop */ return 1; } - + /* if last segment, just remove segment from the stroke */ else if (i == gps->totpoints - 2) { /* allocate new points array, and assign most of the old stroke there */ @@ -745,7 +763,7 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i) /* nothing left in stroke, so stop */ return 1; } - + /* if first segment, just remove segment from the stroke */ else if (i == 0) { /* allocate new points array, and assign most of the old stroke there */ @@ -753,13 +771,32 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i) gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); memcpy(gps->points, pt_tmp + 1, sizeof(bGPDspoint) * gps->totpoints); + /* We must adjust timings! + * Each point's timing data is a delta from stroke's inittime, so as we erase the first + * point of the stroke, we have to offset this inittime and all remaining points' delta values. + * This way we get a new stroke with exactly the same timing as if user had started drawing from + * the second point... + */ + { + bGPDspoint *pts; + float delta = pt_tmp[1].time; + int j; + + gps->inittime += (double)delta; + + pts = gps->points; + for (j = 0; j < gps->totpoints; j++, pts++) { + pts->time -= delta; + } + } + /* free temp buffer */ MEM_freeN(pt_tmp); /* no break here, as there might still be stuff to remove in this stroke */ return 0; } - + /* segment occurs in 'middle' of stroke, so split */ else { /* duplicate stroke, and assign 'later' data to that stroke */ @@ -771,6 +808,25 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i) gsn->points = MEM_callocN(sizeof(bGPDspoint) * gsn->totpoints, "gp_stroke_points"); memcpy(gsn->points, pt_tmp + i, sizeof(bGPDspoint) * gsn->totpoints); + /* We must adjust timings of this new stroke! + * Each point's timing data is a delta from stroke's inittime, so as we erase the first + * point of the stroke, we have to offset this inittime and all remaing points' delta values. + * This way we get a new stroke with exactly the same timing as if user had started drawing from + * the second point... + */ + { + bGPDspoint *pts; + float delta = pt_tmp[i].time; + int j; + + gsn->inittime += (double)delta; + + pts = gsn->points; + for (j = 0; j < gsn->totpoints; j++, pts++) { + pts->time -= delta; + } + } + /* adjust existing stroke */ gps->totpoints = i; gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); @@ -792,7 +848,7 @@ static short gp_stroke_eraser_strokeinside(const int mval[], const int UNUSED(mv const float mval_fl[2] = {mval[0], mval[1]}; const float screen_co_a[2] = {x0, y0}; const float screen_co_b[2] = {x1, y1}; - + if (edge_inside_circle(mval_fl, rad, screen_co_a, screen_co_b)) { return TRUE; } @@ -833,7 +889,7 @@ static void gp_point_to_xy(ARegion *ar, View2D *v2d, rctf *subrect, bGPDstroke * /* eraser tool - evaluation per stroke */ -// TODO: this could really do with some optimization (KD-Tree/BVH?) +/* TODO: this could really do with some optimization (KD-Tree/BVH?) */ static void gp_stroke_eraser_dostroke(tGPsdata *p, const int mval[], const int mvalo[], short rad, const rcti *rect, bGPDframe *gpf, bGPDstroke *gps) @@ -852,7 +908,6 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, gp_point_to_xy(p->ar, p->v2d, p->subrect, gps, gps->points, &x0, &y0); /* do boundbox check first */ - if ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) { /* only check if point is inside */ if (((x0 - mval[0]) * (x0 - mval[0]) + (y0 - mval[1]) * (y0 - mval[1])) <= rad * rad) { @@ -870,10 +925,10 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, /* get points to work with */ pt1 = gps->points + i; pt2 = gps->points + i + 1; - + gp_point_to_xy(p->ar, p->v2d, p->subrect, gps, pt1, &x0, &y0); gp_point_to_xy(p->ar, p->v2d, p->subrect, gps, pt2, &x1, &y1); - + /* check that point segment of the boundbox of the eraser stroke */ if (((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) || ((!ELEM(V2D_IS_CLIPPED, x1, y1)) && BLI_rcti_isect_pt(rect, x1, y1))) { @@ -921,11 +976,11 @@ static void gp_session_validatebuffer(tGPsdata *p) /* clear memory of buffer (or allocate it if starting a new session) */ if (gpd->sbuffer) { - //printf("\t\tGP - reset sbuffer\n"); + /* printf("\t\tGP - reset sbuffer\n"); */ memset(gpd->sbuffer, 0, sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX); } else { - //printf("\t\tGP - allocate sbuffer\n"); + /* printf("\t\tGP - allocate sbuffer\n"); */ gpd->sbuffer = MEM_callocN(sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX, "gp_session_strokebuffer"); } @@ -934,6 +989,9 @@ static void gp_session_validatebuffer(tGPsdata *p) /* reset flags */ gpd->sbuffer_sflag = 0; + + /* reset inittime */ + p->inittime = 0.0; } /* (re)init new painting data */ @@ -961,8 +1019,8 @@ static int gp_session_initdata(bContext *C, tGPsdata *p) /* supported views first */ case SPACE_VIEW3D: { - // View3D *v3d = curarea->spacedata.first; - // RegionView3D *rv3d = ar->regiondata; + /* View3D *v3d = curarea->spacedata.first; */ + /* RegionView3D *rv3d = ar->regiondata; */ /* set current area * - must verify that region data is 3D-view (and not something else) @@ -978,10 +1036,10 @@ static int gp_session_initdata(bContext *C, tGPsdata *p) } } break; - + case SPACE_NODE: { - //SpaceNode *snode = curarea->spacedata.first; + /* SpaceNode *snode = curarea->spacedata.first; */ /* set current area */ p->sa = curarea; @@ -1009,7 +1067,7 @@ static int gp_session_initdata(bContext *C, tGPsdata *p) break; case SPACE_IMAGE: { - //SpaceImage *sima = curarea->spacedata.first; + /* SpaceImage *sima = curarea->spacedata.first; */ /* set the current area */ p->sa = curarea; @@ -1074,7 +1132,8 @@ static int gp_session_initdata(bContext *C, tGPsdata *p) if (ED_gpencil_session_active() == 0) { /* initialize undo stack, - * also, existing undo stack would make buffer drawn */ + * also, existing undo stack would make buffer drawn + */ gpencil_undo_init(p->gpd); } @@ -1109,7 +1168,7 @@ static void gp_session_cleanup(tGPsdata *p) /* free stroke buffer */ if (gpd->sbuffer) { - //printf("\t\tGP - free sbuffer\n"); + /* printf("\t\tGP - free sbuffer\n"); */ MEM_freeN(gpd->sbuffer); gpd->sbuffer = NULL; } @@ -1117,6 +1176,7 @@ static void gp_session_cleanup(tGPsdata *p) /* clear flags */ gpd->sbuffer_size = 0; gpd->sbuffer_sflag = 0; + p->inittime = 0.0; } /* init new stroke */ @@ -1261,7 +1321,8 @@ static void gp_paint_strokeend(tGPsdata *p) static void gp_paint_cleanup(tGPsdata *p) { /* p->gpd==NULL happens when stroke failed to initialize, - * for example. when GP is hidden in current space (sergey) */ + * for example when GP is hidden in current space (sergey) + */ if (p->gpd) { /* finish off a stroke */ gp_paint_strokeend(p); @@ -1303,7 +1364,7 @@ static void gpencil_draw_toggle_eraser_cursor(bContext *C, tGPsdata *p, short en else if (enable) { /* enable cursor */ p->erasercursor = WM_paint_cursor_activate(CTX_wm_manager(C), - NULL, // XXX + NULL, /* XXX */ gpencil_draw_eraser, p); } } @@ -1444,16 +1505,26 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p) /* only add current point to buffer if mouse moved (even though we got an event, it might be just noise) */ else if (gp_stroke_filtermval(p, p->mval, p->mvalo)) { /* try to add point */ - short ok = gp_stroke_addpoint(p, p->mval, p->pressure); + short ok = gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime); /* handle errors while adding point */ if ((ok == GP_STROKEADD_FULL) || (ok == GP_STROKEADD_OVERFLOW)) { /* finish off old stroke */ gp_paint_strokeend(p); + /* And start a new one!!! Else, projection errors! */ + gp_paint_initstroke(p, p->paintmode); /* start a new stroke, starting from previous point */ - gp_stroke_addpoint(p, p->mvalo, p->opressure); - gp_stroke_addpoint(p, p->mval, p->pressure); + /* XXX Must manually reset inittime... */ + /* XXX We only need to reuse previous point if overflow! */ + if (ok == GP_STROKEADD_OVERFLOW) { + p->inittime = p->ocurtime; + gp_stroke_addpoint(p, p->mvalo, p->opressure, p->ocurtime); + } + else { + p->inittime = p->curtime; + } + gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime); } else if (ok == GP_STROKEADD_INVALID) { /* the painting operation cannot continue... */ @@ -1469,6 +1540,7 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p) p->mvalo[0] = p->mval[0]; p->mvalo[1] = p->mval[1]; p->opressure = p->pressure; + p->ocurtime = p->curtime; } } @@ -1479,13 +1551,14 @@ static void gpencil_draw_apply_event(wmOperator *op, wmEvent *event) PointerRNA itemptr; float mousef[2]; int tablet = 0; - + /* convert from window-space to area-space mouse coordinates - * NOTE: float to ints conversions, +1 factor is probably used to ensure a bit more accurate rounding... + * NOTE: float to ints conversions, +1 factor is probably used to ensure a bit more accurate rounding... */ p->mval[0] = event->mval[0] + 1; p->mval[1] = event->mval[1] + 1; - + p->curtime = PIL_check_seconds_timer(); + /* handle pressure sensitivity (which is supplied by tablets) */ if (event->customdatatype == EVT_DATA_TABLET) { wmTabletData *wmtab = event->customdata; @@ -1493,8 +1566,8 @@ static void gpencil_draw_apply_event(wmOperator *op, wmEvent *event) tablet = (wmtab->Active != EVT_TABLET_NONE); p->pressure = wmtab->Pressure; - //if (wmtab->Active == EVT_TABLET_ERASER) - // TODO... this should get caught by the keymaps which call drawing in the first place + /* if (wmtab->Active == EVT_TABLET_ERASER) */ + /* TODO... this should get caught by the keymaps which call drawing in the first place */ } else p->pressure = 1.0f; @@ -1515,14 +1588,17 @@ static void gpencil_draw_apply_event(wmOperator *op, wmEvent *event) p->mvalo[0] = p->mval[0]; p->mvalo[1] = p->mval[1]; p->opressure = p->pressure; + p->inittime = p->ocurtime = p->curtime; /* special exception here for too high pressure values on first touch in - * windows for some tablets, then we just skip first touch .. + * windows for some tablets, then we just skip first touch... */ if (tablet && (p->pressure >= 0.99f)) return; } + RNA_float_set(&itemptr, "time", p->curtime - p->inittime); + /* apply the current latest drawing point */ gpencil_draw_apply(op, p); @@ -1537,18 +1613,18 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) { tGPsdata *p = NULL; - //printf("GPencil - Starting Re-Drawing\n"); + /* printf("GPencil - Starting Re-Drawing\n"); */ /* try to initialize context data needed while drawing */ if (!gpencil_draw_init(C, op)) { if (op->customdata) MEM_freeN(op->customdata); - //printf("\tGP - no valid data\n"); + /* printf("\tGP - no valid data\n"); */ return OPERATOR_CANCELLED; } else p = op->customdata; - //printf("\tGP - Start redrawing stroke\n"); + /* printf("\tGP - Start redrawing stroke\n"); */ /* loop over the stroke RNA elements recorded (i.e. progress of mouse movement), * setting the relevant values in context at each step, then applying @@ -1557,20 +1633,21 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) { float mousef[2]; - //printf("\t\tGP - stroke elem\n"); + /* printf("\t\tGP - stroke elem\n"); */ /* get relevant data for this point from stroke */ RNA_float_get_array(&itemptr, "mouse", mousef); p->mval[0] = (int)mousef[0]; p->mval[1] = (int)mousef[1]; p->pressure = RNA_float_get(&itemptr, "pressure"); + p->curtime = (double)RNA_float_get(&itemptr, "time") + p->inittime; if (RNA_boolean_get(&itemptr, "is_start")) { /* if first-run flag isn't set already (i.e. not true first stroke), * then we must terminate the previous one first before continuing */ if ((p->flags & GP_PAINTFLAG_FIRSTRUN) == 0) { - // TODO: both of these ops can set error-status, but we probably don't need to worry + /* TODO: both of these ops can set error-status, but we probably don't need to worry */ gp_paint_strokeend(p); gp_paint_initstroke(p, p->paintmode); } @@ -1583,6 +1660,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) p->mvalo[0] = p->mval[0]; p->mvalo[1] = p->mval[1]; p->opressure = p->pressure; + p->ocurtime = p->curtime; } /* apply this data as necessary now (as per usual) */ @@ -1590,7 +1668,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) } RNA_END; - //printf("\tGP - done\n"); + /* printf("\tGP - done\n"); */ /* cleanup */ gpencil_draw_exit(C, op); @@ -1636,7 +1714,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, wmEvent *event) /* set cursor */ if (p->paintmode == GP_PAINTMODE_ERASER) - WM_cursor_modal(win, BC_CROSSCURSOR); // XXX need a better cursor + WM_cursor_modal(win, BC_CROSSCURSOR); /* XXX need a better cursor */ else WM_cursor_modal(win, BC_PAINTBRUSHCURSOR); @@ -1646,7 +1724,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, wmEvent *event) */ if (event->val == KM_PRESS) { /* hotkey invoked - start drawing */ - //printf("\tGP - set first spot\n"); + /* printf("\tGP - set first spot\n"); */ p->status = GP_STATUS_PAINTING; /* handle the initial drawing - i.e. for just doing a simple dot */ @@ -1654,7 +1732,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, wmEvent *event) } else { /* toolbar invoked - don't start drawing yet... */ - //printf("\tGP - hotkey invoked... waiting for click-drag\n"); + /* printf("\tGP - hotkey invoked... waiting for click-drag\n"); */ } WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); @@ -1673,7 +1751,7 @@ static int gpencil_area_exists(bContext *C, ScrArea *sa_test) static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op) { tGPsdata *p = op->customdata; - + /* we must check that we're still within the area that we're set up to work from * otherwise we could crash (see bug #20586) */ @@ -1681,20 +1759,20 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op) printf("\t\t\tGP - wrong area execution abort!\n"); p->status = GP_STATUS_ERROR; } - - //printf("\t\tGP - start stroke\n"); - + + /* printf("\t\tGP - start stroke\n"); */ + /* we may need to set up paint env again if we're resuming */ /* XXX: watch it with the paintmode! in future, * it'd be nice to allow changing paint-mode when in sketching-sessions */ /* XXX: with tablet events, we may event want to check for eraser here, for nicer tablet support */ - + if (gp_session_initdata(C, p)) gp_paint_initstroke(p, p->paintmode); - + if (p->status != GP_STATUS_ERROR) p->status = GP_STATUS_PAINTING; - + return op->customdata; } @@ -1719,7 +1797,7 @@ static void gpencil_stroke_end(wmOperator *op) static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) { tGPsdata *p = op->customdata; - int estate = OPERATOR_RUNNING_MODAL; /* default exit state - we don't pass on events, GP is used with key-modifiers */ + int estate = OPERATOR_PASS_THROUGH; /* default exit state - pass through to support MMB view nav, etc. */ /* if (event->type == NDOF_MOTION) * return OPERATOR_PASS_THROUGH; @@ -1731,8 +1809,13 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) * the stroke is converted to 3D only after * it is finished. This approach should work * better in tools that immediately apply - * in 3D space. */ - + * in 3D space. + */ + + /* we don't pass on key events, GP is used with key-modifiers - prevents Dkey to insert drivers */ + if (ISKEYBOARD(event->type)) + estate = OPERATOR_RUNNING_MODAL; + //printf("\tGP - handle modal event...\n"); /* exit painting mode (and/or end current stroke) @@ -1740,7 +1823,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) */ if (ELEM4(event->type, RETKEY, PADENTER, ESCKEY, SPACEKEY)) { /* exit() ends the current stroke before cleaning up */ - //printf("\t\tGP - end of paint op + end of stroke\n"); + /* printf("\t\tGP - end of paint op + end of stroke\n"); */ p->status = GP_STATUS_DONE; estate = OPERATOR_FINISHED; } @@ -1764,7 +1847,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) if (sketch) { /* end stroke only, and then wait to resume painting soon */ - //printf("\t\tGP - end stroke only\n"); + /* printf("\t\tGP - end stroke only\n"); */ gpencil_stroke_end(op); /* we've just entered idling state, so this event was processed (but no others yet) */ @@ -1774,7 +1857,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); } else { - //printf("\t\tGP - end of stroke + op\n"); + /* printf("\t\tGP - end of stroke + op\n"); */ p->status = GP_STATUS_DONE; estate = OPERATOR_FINISHED; } @@ -1797,7 +1880,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) /* handle painting mouse-movements? */ if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) || (p->flags & GP_PAINTFLAG_FIRSTRUN)) { /* handle drawing event */ - //printf("\t\tGP - add point\n"); + /* printf("\t\tGP - add point\n"); */ gpencil_draw_apply_event(op, event); /* finish painting operation if anything went wrong just now */ @@ -1807,7 +1890,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) } else { /* event handled, so just tag as running modal */ - //printf("\t\t\t\tGP - add point handled!\n"); + /* printf("\t\t\t\tGP - add point handled!\n"); */ estate = OPERATOR_RUNNING_MODAL; } } @@ -1818,7 +1901,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) /* just resize the brush (local version) * TODO: fix the hardcoded size jumps (set to make a visible difference) and hardcoded keys */ - //printf("\t\tGP - resize eraser\n"); + /* printf("\t\tGP - resize eraser\n"); */ switch (event->type) { case WHEELUPMOUSE: /* larger */ case PADPLUSKEY: diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index 1d461f797d6..39dd8822267 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -56,6 +56,7 @@ struct wmKeyConfig; typedef struct tGPspoint { int x, y; /* x and y coordinates of cursor (in relative to area) */ float pressure; /* pressure of tablet at this point */ + float time; /* Time relative to stroke start (used when converting to path) */ } tGPspoint; diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h index a50b33966c6..9b726cea56c 100644 --- a/source/blender/editors/include/ED_image.h +++ b/source/blender/editors/include/ED_image.h @@ -49,7 +49,7 @@ void ED_space_image_set_mask(struct bContext *C, struct SpaceImage *sim int ED_space_image_color_sample(struct SpaceImage *sima, struct ARegion *ar, int mval[2], float r_col[3]); struct ImBuf *ED_space_image_acquire_buffer(struct SpaceImage *sima, void **lock_r); -void ED_space_image_release_buffer(struct SpaceImage *sima, void *lock); +void ED_space_image_release_buffer(struct SpaceImage *sima, struct ImBuf *ibuf, void *lock); int ED_space_image_has_buffer(struct SpaceImage *sima); void ED_space_image_get_size(struct SpaceImage *sima, int *width, int *height); diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 05e4d8c4a2f..b9811bf0a93 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -153,7 +153,12 @@ int EDBM_select_pick(struct bContext *C, const int mval[2], short extend, short void EDBM_selectmode_set(struct BMEditMesh *em); void EDBM_selectmode_convert(struct BMEditMesh *em, short selectmode_old, short selectmode_new); -void EDBM_deselect_by_material(struct BMEditMesh *em, short index, short select); +/* user access this */ +int EDBM_selectmode_toggle(struct bContext *C, const short selectmode_new, + const int action, const int use_extend, const int use_expand); + + +void EDBM_deselect_by_material(struct BMEditMesh *em, const short index, const short select); void EDBM_select_toggle_all(struct BMEditMesh *em); diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index e400e44e944..10c585aa802 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -593,6 +593,7 @@ DEF_ICON(MOD_REMESH) DEF_ICON(MOD_OCEAN) DEF_ICON(MOD_WARP) DEF_ICON(MOD_SKIN) +DEF_ICON(MOD_TRIANGULATE) #ifndef DEF_ICON_BLANK_SKIP DEF_ICON(BLANK166) DEF_ICON(BLANK167) @@ -606,7 +607,6 @@ DEF_ICON(MOD_SKIN) DEF_ICON(BLANK175) DEF_ICON(BLANK176) DEF_ICON(BLANK177) - DEF_ICON(BLANK177b) #endif /* ANIMATION */ diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 560a5a716c3..264aa895fc5 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -1675,7 +1675,7 @@ void ui_get_but_string(uiBut *but, char *str, size_t maxlen) { if (but->rnaprop && ELEM3(but->type, TEX, IDPOIN, SEARCH_MENU)) { PropertyType type; - char *buf = NULL; + const char *buf = NULL; int buf_len; type = RNA_property_type(but->rnaprop); @@ -1684,11 +1684,22 @@ void ui_get_but_string(uiBut *but, char *str, size_t maxlen) /* RNA string */ buf = RNA_property_string_get_alloc(&but->rnapoin, but->rnaprop, str, maxlen, &buf_len); } + else if (type == PROP_ENUM) { + /* RNA enum */ + int value = RNA_property_enum_get(&but->rnapoin, but->rnaprop); + if (RNA_property_enum_name(but->block->evil_C, &but->rnapoin, but->rnaprop, value, &buf)) { + BLI_strncpy(str, buf, maxlen); + buf = str; + } + } else if (type == PROP_POINTER) { /* RNA pointer */ PointerRNA ptr = RNA_property_pointer_get(&but->rnapoin, but->rnaprop); buf = RNA_struct_name_get_alloc(&ptr, str, maxlen, &buf_len); } + else { + BLI_assert(0); + } if (!buf) { str[0] = '\0'; @@ -1696,7 +1707,7 @@ void ui_get_but_string(uiBut *but, char *str, size_t maxlen) else if (buf && buf != str) { /* string was too long, we have to truncate */ memcpy(str, buf, MIN2(maxlen, (size_t)buf_len + 1)); - MEM_freeN(buf); + MEM_freeN((void *)buf); } } else if (but->type == IDPOIN) { @@ -1839,6 +1850,17 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str) return 0; } + else if (type == PROP_ENUM) { + int value; + if (RNA_property_enum_value(but->block->evil_C, &but->rnapoin, but->rnaprop, str, &value)) { + RNA_property_enum_set(&but->rnapoin, but->rnaprop, value); + return 1; + } + return 0; + } + else { + BLI_assert(0); + } } } else if (but->type == IDPOIN) { diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 540a9cc752b..23d3810e058 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -358,7 +358,7 @@ struct uiBlock { char color_profile; /* color profile for correcting linear colors for display */ - char *display_device; /* display devide name used to display this block, + char *display_device; /* display device name used to display this block, * used by color widgets to transform colors from/to scene linear */ }; diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 52d909a34c0..9759c22f30e 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -68,6 +68,8 @@ #define EM_SEPR_X 6 #define EM_SEPR_Y 6 +// #define USE_OP_RESET_BUT // we may want to make this optional, disable for now. + #define UI_OPERATOR_ERROR_RET(_ot, _opname, return_statement) \ if (ot == NULL) { \ ui_item_disabled(layout, _opname); \ @@ -428,7 +430,7 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, in but->type = NUMSLI; } } - else if (subtype == PROP_DIRECTION) { + else if (subtype == PROP_DIRECTION && !expand) { uiDefButR_prop(block, BUT_NORMAL, 0, name, x, y, UI_UNIT_X * 3, UI_UNIT_Y * 3, ptr, prop, 0, 0, 0, -1, -1, NULL); } else { @@ -1382,6 +1384,12 @@ void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRN but->rnasearchprop = searchprop; but->flag |= UI_ICON_LEFT | UI_TEXT_LEFT; + if (RNA_property_type(prop) == PROP_ENUM) { + /* XXX, this will have a menu string, + * but in this case we just want the text */ + but->str[0] = 0; + } + uiButSetSearchFunc(but, rna_search_cb, but, NULL, NULL); } } @@ -1399,13 +1407,14 @@ void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propna prop = RNA_struct_find_property(ptr, propname); if (!prop) { - RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname); + RNA_warning("property not found: %s.%s", + RNA_struct_identifier(ptr->type), propname); return; } type = RNA_property_type(prop); - if (!ELEM(type, PROP_POINTER, PROP_STRING)) { - RNA_warning("Property %s must be a pointer or string", propname); + if (!ELEM3(type, PROP_POINTER, PROP_STRING, PROP_ENUM)) { + RNA_warning("Property %s must be a pointer, string or enum", propname); return; } @@ -1413,11 +1422,13 @@ void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propna if (!searchprop) { - RNA_warning("search collection property not found: %s.%s", RNA_struct_identifier(ptr->type), searchpropname); + RNA_warning("search collection property not found: %s.%s", + RNA_struct_identifier(searchptr->type), searchpropname); return; } else if (RNA_property_type(searchprop) != PROP_COLLECTION) { - RNA_warning("search collection property is not a collection type: %s.%s", RNA_struct_identifier(ptr->type), searchpropname); + RNA_warning("search collection property is not a collection type: %s.%s", + RNA_struct_identifier(searchptr->type), searchpropname); return; } @@ -2840,10 +2851,12 @@ const char *uiLayoutIntrospect(uiLayout *layout) return str; } +#ifdef USE_OP_RESET_BUT static void ui_layout_operator_buts__reset_cb(bContext *UNUSED(C), void *op_pt, void *UNUSED(arg_dummy2)) { WM_operator_properties_reset((wmOperator *)op_pt); } +#endif /* this function does not initialize the layout, functions can be called on the layout before and after */ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op, @@ -2911,6 +2924,7 @@ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op, } } +#ifdef USE_OP_RESET_BUT /* its possible that reset can do nothing if all have PROP_SKIP_SAVE enabled * but this is not so important if this button is drawn in those cases * (which isn't all that likely anyway) - campbell */ @@ -2925,6 +2939,7 @@ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Reset operator defaults")); uiButSetFunc(but, ui_layout_operator_buts__reset_cb, op, NULL); } +#endif /* set various special settings for buttons */ { diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 9e7e50d69ac..4712e03d454 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -1413,8 +1413,8 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, dir1 &= (UI_TOP | UI_DOWN); } - if (dir2 == 0) if (dir1 == UI_LEFT || dir1 == UI_RIGHT) dir2 = UI_DOWN; - if (dir2 == 0) if (dir1 == UI_TOP || dir1 == UI_DOWN) dir2 = UI_LEFT; + if ((dir2 == 0) && (dir1 == UI_LEFT || dir1 == UI_RIGHT)) dir2 = UI_DOWN; + if ((dir2 == 0) && (dir1 == UI_TOP || dir1 == UI_DOWN)) dir2 = UI_LEFT; /* no space at all? don't change */ if (left || right) { diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 84ae3a8f57d..f872afed486 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -185,7 +185,8 @@ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem) /* fake button, it holds space for search items */ uiDefBut(block, LABEL, 0, "", 10, 15, w, h, NULL, 0, 0, 0, 0, NULL); - but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, w, 19, template.prv_rows, template.prv_cols, ""); + but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, w, 19, + template.prv_rows, template.prv_cols, ""); uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data); } /* list view */ @@ -315,33 +316,68 @@ static const char *template_id_browse_tip(StructRNA *type) if (type) { switch (RNA_type_to_ID_code(type)) { case ID_SCE: return N_("Browse Scene to be linked"); - case ID_OB: return N_("Browse Object to be linked"); - case ID_ME: return N_("Browse Mesh Data to be linked"); - case ID_CU: return N_("Browse Curve Data to be linked"); - case ID_MB: return N_("Browse Metaball Data to be linked"); - case ID_MA: return N_("Browse Material to be linked"); - case ID_TE: return N_("Browse Texture to be linked"); - case ID_IM: return N_("Browse Image to be linked"); - case ID_LT: return N_("Browse Lattice Data to be linked"); - case ID_LA: return N_("Browse Lamp Data to be linked"); - case ID_CA: return N_("Browse Camera Data to be linked"); - case ID_WO: return N_("Browse World Settings to be linked"); + case ID_OB: return N_("Browse Object to be linked"); + case ID_ME: return N_("Browse Mesh Data to be linked"); + case ID_CU: return N_("Browse Curve Data to be linked"); + case ID_MB: return N_("Browse Metaball Data to be linked"); + case ID_MA: return N_("Browse Material to be linked"); + case ID_TE: return N_("Browse Texture to be linked"); + case ID_IM: return N_("Browse Image to be linked"); + case ID_LT: return N_("Browse Lattice Data to be linked"); + case ID_LA: return N_("Browse Lamp Data to be linked"); + case ID_CA: return N_("Browse Camera Data to be linked"); + case ID_WO: return N_("Browse World Settings to be linked"); case ID_SCR: return N_("Choose Screen lay-out"); case ID_TXT: return N_("Browse Text to be linked"); case ID_SPK: return N_("Browse Speaker Data to be linked"); - case ID_SO: return N_("Browse Sound to be linked"); - case ID_AR: return N_("Browse Armature data to be linked"); - case ID_AC: return N_("Browse Action to be linked"); - case ID_NT: return N_("Browse Node Tree to be linked"); - case ID_BR: return N_("Browse Brush to be linked"); - case ID_PA: return N_("Browse Particle System to be linked"); - case ID_GD: return N_("Browse Grease Pencil Data to be linked"); + case ID_SO: return N_("Browse Sound to be linked"); + case ID_AR: return N_("Browse Armature data to be linked"); + case ID_AC: return N_("Browse Action to be linked"); + case ID_NT: return N_("Browse Node Tree to be linked"); + case ID_BR: return N_("Browse Brush to be linked"); + case ID_PA: return N_("Browse Particle System to be linked"); + case ID_GD: return N_("Browse Grease Pencil Data to be linked"); } } return N_("Browse ID data to be linked"); } -static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, short idcode, int flag, const char *newop, const char *openop, const char *unlinkop) +/* Return a type-based i18n context, needed e.g. by "New" button. + * In most languages, this adjective takes different form based on gender of type name... + */ +static const char *template_id_context(StructRNA *type) +{ + if (type) { + switch (RNA_type_to_ID_code(type)) { + case ID_SCE: return BLF_I18NCONTEXT_ID_SCENE; + case ID_OB: return BLF_I18NCONTEXT_ID_OBJECT; + case ID_ME: return BLF_I18NCONTEXT_ID_MESH; + case ID_CU: return BLF_I18NCONTEXT_ID_CURVE; + case ID_MB: return BLF_I18NCONTEXT_ID_METABALL; + case ID_MA: return BLF_I18NCONTEXT_ID_MATERIAL; + case ID_TE: return BLF_I18NCONTEXT_ID_TEXTURE; + case ID_IM: return BLF_I18NCONTEXT_ID_IMAGE; + case ID_LT: return BLF_I18NCONTEXT_ID_LATTICE; + case ID_LA: return BLF_I18NCONTEXT_ID_LAMP; + case ID_CA: return BLF_I18NCONTEXT_ID_CAMERA; + case ID_WO: return BLF_I18NCONTEXT_ID_WORLD; + case ID_SCR: return BLF_I18NCONTEXT_ID_SCREEN; + case ID_TXT: return BLF_I18NCONTEXT_ID_TEXT; + case ID_SPK: return BLF_I18NCONTEXT_ID_SPEAKER; + case ID_SO: return BLF_I18NCONTEXT_ID_SOUND; + case ID_AR: return BLF_I18NCONTEXT_ID_ARMATURE; + case ID_AC: return BLF_I18NCONTEXT_ID_ACTION; + case ID_NT: return BLF_I18NCONTEXT_ID_NODETREE; + case ID_BR: return BLF_I18NCONTEXT_ID_BRUSH; + case ID_PA: return BLF_I18NCONTEXT_ID_PARTICLESETTINGS; + case ID_GD: return BLF_I18NCONTEXT_ID_GPENCIL; + } + } + return BLF_I18NCONTEXT_DEFAULT; +} + +static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, short idcode, int flag, + const char *newop, const char *openop, const char *unlinkop) { uiBut *but; uiBlock *block; @@ -349,6 +385,7 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str // ListBase *lb; // UNUSED ID *id, *idfrom; int editable = RNA_property_editable(&template->ptr, template->prop); + const char *i18n_ctxt = template_id_context(type); idptr = RNA_property_pointer_get(&template->ptr, template->prop); id = idptr.data; @@ -400,19 +437,20 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str //text_idbutton(id, name); name[0] = '\0'; - but = uiDefButR(block, TEX, 0, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, &idptr, "name", -1, 0, 0, -1, -1, RNA_struct_ui_description(type)); + but = uiDefButR(block, TEX, 0, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, + &idptr, "name", -1, 0, 0, -1, -1, RNA_struct_ui_description(type)); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME)); if (user_alert) uiButSetFlag(but, UI_BUT_REDALERT); if (id->lib) { if (id->flag & LIB_INDIRECT) { - but = uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_INDIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, - TIP_("Indirect library datablock, cannot change")); + but = uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_INDIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y, + NULL, 0, 0, 0, 0, TIP_("Indirect library datablock, cannot change")); uiButSetFlag(but, UI_BUT_DISABLED); } else { - but = uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, - TIP_("Direct linked library datablock, click to make local")); + but = uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y, + NULL, 0, 0, 0, 0, TIP_("Direct linked library datablock, click to make local")); if (!id_make_local(id, 1 /* test */) || (idfrom && idfrom->lib)) uiButSetFlag(but, UI_BUT_DISABLED); } @@ -425,7 +463,8 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str BLI_snprintf(numstr, sizeof(numstr), "%d", id->us); - but = uiDefBut(block, BUT, 0, numstr, 0, 0, UI_UNIT_X + ((id->us < 10) ? 0 : 10), UI_UNIT_Y, NULL, 0, 0, 0, 0, + but = uiDefBut(block, BUT, 0, numstr, 0, 0, UI_UNIT_X + ((id->us < 10) ? 0 : 10), UI_UNIT_Y, + NULL, 0, 0, 0, 0, TIP_("Display number of users of this data (click to make a single-user copy)")); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ALONE)); @@ -450,12 +489,39 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str if (flag & UI_ID_ADD_NEW) { int w = id ? UI_UNIT_X : (flag & UI_ID_OPEN) ? UI_UNIT_X * 3 : UI_UNIT_X * 6; + /* i18n markup, does nothing! */ + BLF_I18N_MSGID_MULTI_CTXT("New", BLF_I18NCONTEXT_DEFAULT, + BLF_I18NCONTEXT_ID_SCENE, + BLF_I18NCONTEXT_ID_OBJECT, + BLF_I18NCONTEXT_ID_MESH, + BLF_I18NCONTEXT_ID_CURVE, + BLF_I18NCONTEXT_ID_METABALL, + BLF_I18NCONTEXT_ID_MATERIAL, + BLF_I18NCONTEXT_ID_TEXTURE, + BLF_I18NCONTEXT_ID_IMAGE, + BLF_I18NCONTEXT_ID_LATTICE, + BLF_I18NCONTEXT_ID_LAMP, + BLF_I18NCONTEXT_ID_CAMERA, + BLF_I18NCONTEXT_ID_WORLD, + BLF_I18NCONTEXT_ID_SCREEN, + BLF_I18NCONTEXT_ID_TEXT); + BLF_I18N_MSGID_MULTI_CTXT("New", BLF_I18NCONTEXT_ID_SPEAKER, + BLF_I18NCONTEXT_ID_SOUND, + BLF_I18NCONTEXT_ID_ARMATURE, + BLF_I18NCONTEXT_ID_ACTION, + BLF_I18NCONTEXT_ID_NODETREE, + BLF_I18NCONTEXT_ID_BRUSH, + BLF_I18NCONTEXT_ID_PARTICLESETTINGS, + BLF_I18NCONTEXT_ID_GPENCIL); + if (newop) { - but = uiDefIconTextButO(block, BUT, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN, (id) ? "" : IFACE_("New"), 0, 0, w, UI_UNIT_Y, NULL); + but = uiDefIconTextButO(block, BUT, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN, + (id) ? "" : CTX_IFACE_(i18n_ctxt, "New"), 0, 0, w, UI_UNIT_Y, NULL); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW)); } else { - but = uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, (id) ? "" : IFACE_("New"), 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); + but = uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, (id) ? "" : CTX_IFACE_(i18n_ctxt, "New"), + 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW)); } @@ -467,11 +533,13 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str int w = id ? UI_UNIT_X : (flag & UI_ID_ADD_NEW) ? UI_UNIT_X * 3 : UI_UNIT_X * 6; if (openop) { - but = uiDefIconTextButO(block, BUT, openop, WM_OP_INVOKE_DEFAULT, ICON_FILESEL, (id) ? "" : IFACE_("Open"), 0, 0, w, UI_UNIT_Y, NULL); + but = uiDefIconTextButO(block, BUT, openop, WM_OP_INVOKE_DEFAULT, ICON_FILESEL, (id) ? "" : IFACE_("Open"), + 0, 0, w, UI_UNIT_Y, NULL); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN)); } else { - but = uiDefIconTextBut(block, BUT, 0, ICON_FILESEL, (id) ? "" : IFACE_("Open"), 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); + but = uiDefIconTextBut(block, BUT, 0, ICON_FILESEL, (id) ? "" : IFACE_("Open"), 0, 0, w, UI_UNIT_Y, + NULL, 0, 0, 0, 0, NULL); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN)); } @@ -488,7 +556,8 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str } else { but = uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, - TIP_("Unlink datablock. Shift + Click to set users to zero, data will then not be saved")); + TIP_("Unlink datablock " + "(Shift + Click to set users to zero, data will then not be saved)")); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_DELETE)); if (RNA_property_flag(template->prop) & PROP_NEVER_NULL) @@ -505,7 +574,8 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str uiBlockEndAlign(block); } -static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop, int flag, int prv_rows, int prv_cols) +static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, + const char *openop, const char *unlinkop, int flag, int prv_rows, int prv_cols) { TemplateID *template; PropertyRNA *prop; @@ -545,19 +615,24 @@ static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, const MEM_freeN(template); } -void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop) +void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, + const char *openop, const char *unlinkop) { - ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE, 0, 0); + ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, + UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE, 0, 0); } -void uiTemplateIDBrowse(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop) +void uiTemplateIDBrowse(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, + const char *openop, const char *unlinkop) { ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE | UI_ID_RENAME, 0, 0); } -void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop, int rows, int cols) +void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, + const char *openop, const char *unlinkop, int rows, int cols) { - ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE | UI_ID_PREVIEWS, rows, cols); + ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, + UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE | UI_ID_PREVIEWS, rows, cols); } /************************ ID Chooser Template ***************************/ @@ -567,7 +642,8 @@ void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, const c * - propname: property identifier for property that ID-pointer gets stored to * - proptypename: property identifier for property used to determine the type of ID-pointer that can be used */ -void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *proptypename, const char *text) +void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *proptypename, + const char *text) { PropertyRNA *propID, *propType; uiLayout *row; @@ -614,7 +690,8 @@ void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, co * - propname: property identifier for property that path gets stored to * - root_ptr: struct that path gets built from */ -void uiTemplatePathBuilder(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *UNUSED(root_ptr), const char *text) +void uiTemplatePathBuilder(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *UNUSED(root_ptr), + const char *text) { PropertyRNA *propPath; uiLayout *row; @@ -779,7 +856,7 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, uiBlockBeginAlign(block); /* Softbody not allowed in this situation, enforce! */ if (((md->type != eModifierType_Softbody && md->type != eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) && - (md->type != eModifierType_Surface) ) + (md->type != eModifierType_Surface) ) { uiItemR(row, &ptr, "show_render", 0, "", ICON_NONE); uiItemR(row, &ptr, "show_viewport", 0, "", ICON_NONE); @@ -791,7 +868,8 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, if (ob->type == OB_MESH) { if (modifier_couldBeCage(scene, md) && (index <= lastCageIndex)) { /* -- convert to rna ? */ - but = uiDefIconButBitI(block, TOG, eModifierMode_OnCage, 0, ICON_MESH_DATA, 0, 0, UI_UNIT_X - 2, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0, + but = uiDefIconButBitI(block, TOG, eModifierMode_OnCage, 0, ICON_MESH_DATA, 0, 0, + UI_UNIT_X - 2, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0, TIP_("Apply modifier to editing cage during Edit mode")); if (index < cageIndex) uiButSetFlag(but, UI_BUT_DISABLED); @@ -802,7 +880,8 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, /* place holder button */ uiBlockSetEmboss(block, UI_EMBOSSN); - but = uiDefIconBut(block, BUT, 0, ICON_NONE, 0, 0, UI_UNIT_X - 2, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, NULL); + but = uiDefIconBut(block, BUT, 0, ICON_NONE, 0, 0, UI_UNIT_X - 2, UI_UNIT_Y, + NULL, 0.0, 0.0, 0.0, 0.0, NULL); uiButSetFlag(but, UI_BUT_DISABLED); uiBlockSetEmboss(block, UI_EMBOSS); } @@ -812,7 +891,8 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) { /* add disabled pre-tessellated button, so users could have * message for this modifiers */ - but = uiDefIconButBitI(block, TOG, eModifierMode_ApplyOnSpline, 0, ICON_SURFACE_DATA, 0, 0, UI_UNIT_X - 2, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0, + but = uiDefIconButBitI(block, TOG, eModifierMode_ApplyOnSpline, 0, ICON_SURFACE_DATA, 0, 0, + UI_UNIT_X - 2, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0, TIP_("This modifier could be applied on splines' points only")); uiButSetFlag(but, UI_BUT_DISABLED); } @@ -866,15 +946,20 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT); uiItemEnumO(row, "OBJECT_OT_modifier_apply", IFACE_("Apply"), 0, "apply_as", MODIFIER_APPLY_DATA); - if (modifier_sameTopology(md) && !modifier_nonGeometrical(md)) - uiItemEnumO(row, "OBJECT_OT_modifier_apply", IFACE_("Apply as Shape Key"), 0, "apply_as", MODIFIER_APPLY_SHAPE); + if (modifier_isSameTopology(md) && !modifier_isNonGeometrical(md)) { + uiItemEnumO(row, "OBJECT_OT_modifier_apply", IFACE_("Apply as Shape Key"), 0, + "apply_as", MODIFIER_APPLY_SHAPE); + } } uiBlockClearButLock(block); uiBlockSetButLock(block, ob && ob->id.lib, ERROR_LIBDATA_MESSAGE); - if (!ELEM5(md->type, eModifierType_Fluidsim, eModifierType_Softbody, eModifierType_ParticleSystem, eModifierType_Cloth, eModifierType_Smoke)) + if (!ELEM5(md->type, eModifierType_Fluidsim, eModifierType_Softbody, eModifierType_ParticleSystem, + eModifierType_Cloth, eModifierType_Smoke)) + { uiItemO(row, IFACE_("Copy"), ICON_NONE, "OBJECT_OT_modifier_copy"); + } } /* result is the layout block inside the box, that we return so that modifier settings can be drawn */ @@ -1046,8 +1131,10 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) uiBlockSetEmboss(block, UI_EMBOSSN); /* draw a ghost icon (for proxy) and also a lock beside it, to show that constraint is "proxy locked" */ - uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_GHOST, xco + 244, yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Proxy Protected")); - uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_LOCKED, xco + 262, yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Proxy Protected")); + uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_GHOST, xco + 244, yco, 19, 19, + NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Proxy Protected")); + uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_LOCKED, xco + 262, yco, 19, 19, + NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Proxy Protected")); uiBlockSetEmboss(block, UI_EMBOSS); } @@ -1076,7 +1163,8 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) /* enabled */ uiBlockSetEmboss(block, UI_EMBOSSN); - uiItemR(row, &ptr, "mute", 0, "", (con->flag & CONSTRAINT_OFF) ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF); + uiItemR(row, &ptr, "mute", 0, "", + (con->flag & CONSTRAINT_OFF) ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF); uiBlockSetEmboss(block, UI_EMBOSS); uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT); @@ -1233,14 +1321,22 @@ void uiTemplatePreview(uiLayout *layout, ID *id, int show_buttons, ID *parent, M RNA_pointer_create(id, &RNA_Texture, tex, &texture_ptr); uiLayoutRow(layout, TRUE); - uiDefButS(block, ROW, B_MATPRV, IFACE_("Texture"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, pr_texture, 10, TEX_PR_TEXTURE, 0, 0, ""); - if (GS(parent->name) == ID_MA) - uiDefButS(block, ROW, B_MATPRV, IFACE_("Material"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, ""); - else if (GS(parent->name) == ID_LA) - uiDefButS(block, ROW, B_MATPRV, IFACE_("Lamp"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, ""); - else if (GS(parent->name) == ID_WO) - uiDefButS(block, ROW, B_MATPRV, IFACE_("World"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, ""); - uiDefButS(block, ROW, B_MATPRV, IFACE_("Both"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, pr_texture, 10, TEX_PR_BOTH, 0, 0, ""); + uiDefButS(block, ROW, B_MATPRV, IFACE_("Texture"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, + pr_texture, 10, TEX_PR_TEXTURE, 0, 0, ""); + if (GS(parent->name) == ID_MA) { + uiDefButS(block, ROW, B_MATPRV, IFACE_("Material"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, + pr_texture, 10, TEX_PR_OTHER, 0, 0, ""); + } + else if (GS(parent->name) == ID_LA) { + uiDefButS(block, ROW, B_MATPRV, IFACE_("Lamp"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, + pr_texture, 10, TEX_PR_OTHER, 0, 0, ""); + } + else if (GS(parent->name) == ID_WO) { + uiDefButS(block, ROW, B_MATPRV, IFACE_("World"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, + pr_texture, 10, TEX_PR_OTHER, 0, 0, ""); + } + uiDefButS(block, ROW, B_MATPRV, IFACE_("Both"), 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, + pr_texture, 10, TEX_PR_BOTH, 0, 0, ""); /* Alpha button for texture preview */ if (*pr_texture != TEX_PR_OTHER) { @@ -1330,7 +1426,8 @@ static void colorband_update_cb(bContext *UNUSED(C), void *bt_v, void *coba_v) } /* offset aligns from bottom, standard width 300, height 115 */ -static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand *coba, int xoffs, int yoffs, RNAUpdateCb *cb) +static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand *coba, + int xoffs, int yoffs, RNAUpdateCb *cb) { uiBut *bt; uiLayout *row; @@ -1349,13 +1446,16 @@ static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand /* XXX, todo for later - convert to operator - campbell */ - bt = uiDefBut(block, BUT, 0, "F", 95 + xoffs, line1_y, 20, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Flip colorband")); + bt = uiDefBut(block, BUT, 0, "F", 95 + xoffs, line1_y, 20, UI_UNIT_Y, + NULL, 0, 0, 0, 0, TIP_("Flip colorband")); uiButSetNFunc(bt, colorband_flip_cb, MEM_dupallocN(cb), coba); - uiDefButS(block, NUM, 0, "", 120 + xoffs, line1_y, 80, UI_UNIT_Y, &coba->cur, 0.0, (float)(MAX2(0, coba->tot - 1)), 0, 0, TIP_("Choose active color stop")); + uiDefButS(block, NUM, 0, "", 120 + xoffs, line1_y, 80, UI_UNIT_Y, &coba->cur, 0.0, (float)(MAX2(0, coba->tot - 1)), + 0, 0, TIP_("Choose active color stop")); - bt = uiDefButS(block, MENU, 0, IFACE_("Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4"), - 210 + xoffs, line1_y, 90, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0, TIP_("Set interpolation between color stops")); + bt = uiDefButS(block, MENU, 0, IFACE_("Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4"), + 210 + xoffs, line1_y, 90, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0, + TIP_("Set interpolation between color stops")); uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); uiBlockEndAlign(block); @@ -1391,10 +1491,11 @@ static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand bt = uiDefBut(block, BUT, 0, IFACE_("Add"), xs, butr->ymin + UI_UNIT_Y, 2.0f * unit, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Add a new color stop to the colorband")); uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba); - bt = uiDefBut(block, BUT, 0, IFACE_("Delete"), xs + 2.0f * unit, butr->ymin + UI_UNIT_Y, 1.5f * unit, UI_UNIT_Y, NULL, 0, 0, 0, 0, - TIP_("Delete the active position")); + bt = uiDefBut(block, BUT, 0, IFACE_("Delete"), xs + 2.0f * unit, butr->ymin + UI_UNIT_Y, 1.5f * unit, UI_UNIT_Y, + NULL, 0, 0, 0, 0, TIP_("Delete the active position")); uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba); - bt = uiDefBut(block, BUT, 0, "F", xs + 3.5f * unit, butr->ymin + UI_UNIT_Y, 0.5f * unit, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Flip the color ramp")); + bt = uiDefBut(block, BUT, 0, "F", xs + 3.5f * unit, butr->ymin + UI_UNIT_Y, 0.5f * unit, UI_UNIT_Y, + NULL, 0, 0, 0, 0, TIP_("Flip the color ramp")); uiButSetNFunc(bt, colorband_flip_cb, MEM_dupallocN(cb), coba); uiBlockEndAlign(block); @@ -1406,7 +1507,7 @@ static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand } bt = uiDefButS(block, MENU, 0, IFACE_("Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4"), - xs + 10.0f * unit, butr->ymin + UI_UNIT_Y, unit * 4, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0, + xs + 10.0f * unit, butr->ymin + UI_UNIT_Y, unit * 4, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0, TIP_("Set interpolation between color stops")); uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); @@ -1416,7 +1517,8 @@ static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand uiBlockEndAlign(block); } -static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr, int small, RNAUpdateCb *cb) +static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr, + int small, RNAUpdateCb *cb) { if (small) colorband_buttons_small(layout, block, coba, butr, cb); @@ -1485,7 +1587,8 @@ void uiTemplateHistogram(uiLayout *layout, PointerRNA *ptr, const char *propname hist->height = (hist->height <= UI_UNIT_Y) ? UI_UNIT_Y : hist->height; - bt = uiDefBut(block, HISTOGRAM, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), hist->height, hist, 0, 0, 0, 0, ""); + bt = uiDefBut(block, HISTOGRAM, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), hist->height, hist, + 0, 0, 0, 0, ""); uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); MEM_freeN(cb); @@ -1522,7 +1625,8 @@ void uiTemplateWaveform(uiLayout *layout, PointerRNA *ptr, const char *propname) scopes->wavefrm_height = (scopes->wavefrm_height <= UI_UNIT_Y) ? UI_UNIT_Y : scopes->wavefrm_height; - bt = uiDefBut(block, WAVEFORM, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), scopes->wavefrm_height, scopes, 0, 0, 0, 0, ""); + bt = uiDefBut(block, WAVEFORM, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), scopes->wavefrm_height, scopes, + 0, 0, 0, 0, ""); (void)bt; /* UNUSED */ MEM_freeN(cb); @@ -1559,7 +1663,8 @@ void uiTemplateVectorscope(uiLayout *layout, PointerRNA *ptr, const char *propna scopes->vecscope_height = (scopes->vecscope_height <= UI_UNIT_Y) ? UI_UNIT_Y : scopes->vecscope_height; - bt = uiDefBut(block, VECTORSCOPE, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), scopes->vecscope_height, scopes, 0, 0, 0, 0, ""); + bt = uiDefBut(block, VECTORSCOPE, 0, "", rect.xmin, rect.ymin, BLI_rctf_size_x(&rect), + scopes->vecscope_height, scopes, 0, 0, 0, 0, ""); uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); MEM_freeN(cb); @@ -1658,10 +1763,14 @@ static uiBlock *curvemap_clipping_func(bContext *C, ARegion *ar, void *cumap_v) uiButSetFunc(bt, curvemap_buttons_setclip, cumap, NULL); uiBlockBeginAlign(block); - uiDefButF(block, NUM, 0, IFACE_("Min X "), 0, 4 * UI_UNIT_Y, width, UI_UNIT_Y, &cumap->clipr.xmin, -100.0, cumap->clipr.xmax, 10, 0, ""); - uiDefButF(block, NUM, 0, IFACE_("Min Y "), 0, 3 * UI_UNIT_Y, width, UI_UNIT_Y, &cumap->clipr.ymin, -100.0, cumap->clipr.ymax, 10, 0, ""); - uiDefButF(block, NUM, 0, IFACE_("Max X "), 0, 2 * UI_UNIT_Y, width, UI_UNIT_Y, &cumap->clipr.xmax, cumap->clipr.xmin, 100.0, 10, 0, ""); - uiDefButF(block, NUM, 0, IFACE_("Max Y "), 0, UI_UNIT_Y, width, UI_UNIT_Y, &cumap->clipr.ymax, cumap->clipr.ymin, 100.0, 10, 0, ""); + uiDefButF(block, NUM, 0, IFACE_("Min X "), 0, 4 * UI_UNIT_Y, width, UI_UNIT_Y, + &cumap->clipr.xmin, -100.0, cumap->clipr.xmax, 10, 0, ""); + uiDefButF(block, NUM, 0, IFACE_("Min Y "), 0, 3 * UI_UNIT_Y, width, UI_UNIT_Y, + &cumap->clipr.ymin, -100.0, cumap->clipr.ymax, 10, 0, ""); + uiDefButF(block, NUM, 0, IFACE_("Max X "), 0, 2 * UI_UNIT_Y, width, UI_UNIT_Y, + &cumap->clipr.xmax, cumap->clipr.xmin, 100.0, 10, 0, ""); + uiDefButF(block, NUM, 0, IFACE_("Max Y "), 0, UI_UNIT_Y, width, UI_UNIT_Y, + &cumap->clipr.ymax, cumap->clipr.ymin, 100.0, 10, 0, ""); uiBlockSetDirection(block, UI_RIGHT); @@ -1710,12 +1819,18 @@ static uiBlock *curvemap_tools_func(bContext *C, ARegion *ar, void *cumap_v) block = uiBeginBlock(C, ar, __func__, UI_EMBOSS); uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset View"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 1, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Vector Handle"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 2, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Auto Handle"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 3, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Extend Horizontal"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 4, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Extend Extrapolated"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 5, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset Curve"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset View"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 1, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Vector Handle"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 2, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Auto Handle"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 3, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Extend Horizontal"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 4, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Extend Extrapolated"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 5, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset Curve"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); uiBlockSetDirection(block, UI_RIGHT); uiTextBoundsBlock(block, 50); @@ -1732,10 +1847,14 @@ static uiBlock *curvemap_brush_tools_func(bContext *C, ARegion *ar, void *cumap_ block = uiBeginBlock(C, ar, __func__, UI_EMBOSS); uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset View"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 1, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Vector Handle"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 2, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Auto Handle"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 3, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset Curve"), 0, yco -= UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset View"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 1, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Vector Handle"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 2, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Auto Handle"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 3, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset Curve"), 0, yco -= UI_UNIT_Y, + menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); uiBlockSetDirection(block, UI_RIGHT); uiTextBoundsBlock(block, 50); @@ -1775,7 +1894,8 @@ static void curvemap_buttons_reset(bContext *C, void *cb_v, void *cumap_v) } /* still unsure how this call evolves... we use labeltype for defining what curve-channels to show */ -static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labeltype, int levels, int brush, RNAUpdateCb *cb) +static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labeltype, int levels, + int brush, RNAUpdateCb *cb) { CurveMapping *cumap = ptr->data; CurveMap *cm = &cumap->cm[cumap->cur]; @@ -1956,7 +2076,8 @@ void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, const char *propn #define WHEEL_SIZE 100 /* This template now follows User Preference for type - name is not correct anymore... */ -void uiTemplateColorPicker(uiLayout *layout, PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic) +void uiTemplateColorPicker(uiLayout *layout, PointerRNA *ptr, const char *propname, int value_slider, + int lock, int lock_luminosity, int cubic) { PropertyRNA *prop = RNA_struct_find_property(ptr, propname); uiBlock *block = uiLayoutGetBlock(layout); @@ -1976,16 +2097,20 @@ void uiTemplateColorPicker(uiLayout *layout, PointerRNA *ptr, const char *propna switch (U.color_picker_type) { case USER_CP_CIRCLE: - but = uiDefButR_prop(block, HSVCIRCLE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, -1, 0.0, 0.0, 0, 0, ""); + but = uiDefButR_prop(block, HSVCIRCLE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, + -1, 0.0, 0.0, 0, 0, ""); break; case USER_CP_SQUARE_SV: - but = uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, -1, 0.0, 0.0, UI_GRAD_SV, 0, ""); + but = uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, + -1, 0.0, 0.0, UI_GRAD_SV, 0, ""); break; case USER_CP_SQUARE_HS: - but = uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, -1, 0.0, 0.0, UI_GRAD_HS, 0, ""); + but = uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, + -1, 0.0, 0.0, UI_GRAD_HS, 0, ""); break; case USER_CP_SQUARE_HV: - but = uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, -1, 0.0, 0.0, UI_GRAD_HV, 0, ""); + but = uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, + -1, 0.0, 0.0, UI_GRAD_HV, 0, ""); break; } @@ -2010,19 +2135,23 @@ void uiTemplateColorPicker(uiLayout *layout, PointerRNA *ptr, const char *propna switch (U.color_picker_type) { case USER_CP_CIRCLE: uiItemS(row); - uiDefButR_prop(block, HSVCUBE, 0, "", WHEEL_SIZE + 6, 0, 14, WHEEL_SIZE, ptr, prop, -1, softmin, softmax, UI_GRAD_V_ALT, 0, ""); + uiDefButR_prop(block, HSVCUBE, 0, "", WHEEL_SIZE + 6, 0, 14, WHEEL_SIZE, ptr, prop, + -1, softmin, softmax, UI_GRAD_V_ALT, 0, ""); break; case USER_CP_SQUARE_SV: uiItemS(col); - uiDefButR_prop(block, HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18, ptr, prop, -1, softmin, softmax, UI_GRAD_SV + 3, 0, ""); + uiDefButR_prop(block, HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18, ptr, prop, + -1, softmin, softmax, UI_GRAD_SV + 3, 0, ""); break; case USER_CP_SQUARE_HS: uiItemS(col); - uiDefButR_prop(block, HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18, ptr, prop, -1, softmin, softmax, UI_GRAD_HS + 3, 0, ""); + uiDefButR_prop(block, HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18, ptr, prop, + -1, softmin, softmax, UI_GRAD_HS + 3, 0, ""); break; case USER_CP_SQUARE_HV: uiItemS(col); - uiDefButR_prop(block, HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18, ptr, prop, -1, softmin, softmax, UI_GRAD_HV + 3, 0, ""); + uiDefButR_prop(block, HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18, ptr, prop, + -1, softmin, softmax, UI_GRAD_HV + 3, 0, ""); break; } @@ -2184,7 +2313,8 @@ void uiTemplateGameStates(uiLayout *layout, PointerRNA *ptr, const char *propnam else if (used_prop && RNA_property_boolean_get_index(used_ptr, used_prop, state)) icon = ICON_LAYER_USED; - but = uiDefIconButR_prop(block, ICONTOG, 0, icon, 0, 0, UI_UNIT_X / 2, UI_UNIT_Y / 2, ptr, prop, state, 0, 0, -1, -1, sca_state_name_get(ob, state)); + but = uiDefIconButR_prop(block, ICONTOG, 0, icon, 0, 0, UI_UNIT_X / 2, UI_UNIT_Y / 2, ptr, prop, + state, 0, 0, -1, -1, sca_state_name_get(ob, state)); uiButSetFunc(but, handle_layer_buttons, but, SET_INT_IN_POINTER(state)); but->type = TOG; } @@ -2232,7 +2362,8 @@ static int list_item_icon_get(bContext *C, PointerRNA *itemptr, int rnaicon, int return rnaicon; } -static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *itemptr, int i, int rnaicon, PointerRNA *activeptr, PropertyRNA *activeprop, const char *prop_list_id) +static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *itemptr, int i, + int rnaicon, PointerRNA *activeptr, PropertyRNA *activeprop, const char *prop_list_id) { uiBlock *block = uiLayoutGetBlock(layout); uiBut *but; @@ -2246,7 +2377,8 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe /* list item behind label & other buttons */ sub = uiLayoutRow(overlap, FALSE); - but = uiDefButR_prop(block, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, activeptr, activeprop, 0, 0, i, 0, 0, ""); + but = uiDefButR_prop(block, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, activeptr, activeprop, + 0, 0, i, 0, 0, ""); uiButSetFlag(but, UI_BUT_NO_TOOLTIP); sub = uiLayoutRow(overlap, FALSE); @@ -2263,7 +2395,8 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe if (itemptr->type == &RNA_MeshTexturePolyLayer || itemptr->type == &RNA_MeshLoopColorLayer) { uiItemL(sub, name, icon); uiBlockSetEmboss(block, UI_EMBOSSN); - uiDefIconButR(block, TOG, 0, ICON_SCENE, 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "active_render", 0, 0, 0, 0, 0, NULL); + uiDefIconButR(block, TOG, 0, ICON_SCENE, 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "active_render", + 0, 0, 0, 0, 0, NULL); uiBlockSetEmboss(block, UI_EMBOSS); } else if (RNA_struct_is_a(itemptr->type, &RNA_MaterialTextureSlot)) { @@ -2356,7 +2489,8 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe uiItemL(sub, name_final, icon); if (dynamicPaint_surfaceHasColorPreview(surface)) { uiBlockSetEmboss(block, UI_EMBOSSN); - uiDefIconButR(block, OPTION, 0, (surface->flags & MOD_DPAINT_PREVIEW) ? ICON_RESTRICT_VIEW_OFF : ICON_RESTRICT_VIEW_ON, + uiDefIconButR(block, OPTION, 0, + (surface->flags & MOD_DPAINT_PREVIEW) ? ICON_RESTRICT_VIEW_OFF : ICON_RESTRICT_VIEW_ON, 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "show_preview", 0, 0, 0, 0, 0, NULL); uiBlockSetEmboss(block, UI_EMBOSS); } @@ -2445,7 +2579,8 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe } } -void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *activeptr, const char *activepropname, const char *prop_list, int rows, int maxrows, int listtype) +void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *activeptr, + const char *activepropname, const char *prop_list, int rows, int maxrows, int listtype) { PropertyRNA *prop = NULL, *activeprop; PropertyType type, activetype; @@ -2521,7 +2656,8 @@ void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char * row = uiLayoutRow(col, FALSE); icon = list_item_icon_get(C, &itemptr, rnaicon, 1); - but = uiDefIconButR_prop(block, LISTROW, 0, icon, 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, activeptr, activeprop, 0, 0, i, 0, 0, ""); + but = uiDefIconButR_prop(block, LISTROW, 0, icon, 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, activeptr, + activeprop, 0, 0, i, 0, 0, ""); uiButSetFlag(but, UI_BUT_NO_TOOLTIP); @@ -2563,7 +2699,8 @@ void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char * /* next/prev button */ BLI_snprintf(numstr, sizeof(numstr), "%d :", i); - but = uiDefIconTextButR_prop(block, NUM, 0, 0, numstr, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, activeptr, activeprop, 0, 0, 0, 0, 0, ""); + but = uiDefIconTextButR_prop(block, NUM, 0, 0, numstr, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, activeptr, + activeprop, 0, 0, 0, 0, 0, ""); if (i == 0) uiButSetFlag(but, UI_BUT_DISABLED); } @@ -2620,7 +2757,8 @@ void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char * /* add scrollbar */ if (len > items) { col = uiLayoutColumn(row, FALSE); - uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * items, &pa->list_scroll, 0, len - items, items, 0, ""); + uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * items, &pa->list_scroll, + 0, len - items, items, 0, ""); } } } @@ -2767,19 +2905,19 @@ void uiTemplateRunningJobs(uiLayout *layout, bContext *C) ui_abs = uiLayoutAbsolute(layout, FALSE); (void)ui_abs; /* UNUSED */ - uiDefIconBut(block, BUT, handle_event, ICON_PANEL_CLOSE, - 0, UI_UNIT_Y * 0.1, UI_UNIT_X * 0.8, UI_UNIT_Y * 0.8, NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop this job")); + uiDefIconBut(block, BUT, handle_event, ICON_PANEL_CLOSE, 0, UI_UNIT_Y * 0.1, UI_UNIT_X * 0.8, UI_UNIT_Y * 0.8, + NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop this job")); uiDefBut(block, PROGRESSBAR, 0, WM_jobs_name(wm, owner), UI_UNIT_X, 0, 100, UI_UNIT_Y, NULL, 0.0f, 0.0f, WM_jobs_progress(wm, owner), 0, TIP_("Progress")); uiLayoutRow(layout, FALSE); } if (WM_jobs_test(wm, screen, WM_JOB_TYPE_SCREENCAST)) - uiDefIconTextBut(block, BUT, B_STOPCAST, ICON_CANCEL, IFACE_("Capture"), 0, 0, 85, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, - TIP_("Stop screencast")); + uiDefIconTextBut(block, BUT, B_STOPCAST, ICON_CANCEL, IFACE_("Capture"), 0, 0, 85, UI_UNIT_Y, + NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop screencast")); if (screen->animtimer) - uiDefIconTextBut(block, BUT, B_STOPANIM, ICON_CANCEL, IFACE_("Anim Player"), 0, 0, 100, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, - TIP_("Stop animation playback")); + uiDefIconTextBut(block, BUT, B_STOPANIM, ICON_CANCEL, IFACE_("Anim Player"), 0, 0, 100, UI_UNIT_Y, + NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop animation playback")); } /************************* Reports for Last Operator Template **************************/ @@ -2818,7 +2956,8 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C) rgb_float_to_uchar(but->col, rti->col); but->col[3] = 255; - but = uiDefBut(block, ROUNDBOX, 0, "", UI_UNIT_X + 10, 0, UI_UNIT_X + width, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); + but = uiDefBut(block, ROUNDBOX, 0, "", UI_UNIT_X + 10, 0, UI_UNIT_X + width, UI_UNIT_Y, + NULL, 0.0f, 0.0f, 0, 0, ""); but->col[0] = but->col[1] = but->col[2] = FTOCHAR(rti->grayscale); but->col[3] = 255; @@ -2839,14 +2978,15 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C) uiBlockSetEmboss(block, UI_EMBOSSN); if (reports->list.first != reports->list.last) - uiDefIconButO(block, BUT, "UI_OT_reports_to_textblock", WM_OP_INVOKE_REGION_WIN, icon, 2, 0, - UI_UNIT_X, UI_UNIT_Y, TIP_("Click to see the remaining reports in text block: 'Recent Reports'")); + uiDefIconButO(block, BUT, "UI_OT_reports_to_textblock", WM_OP_INVOKE_REGION_WIN, icon, 2, 0, UI_UNIT_X, + UI_UNIT_Y, TIP_("Click to see the remaining reports in text block: 'Recent Reports'")); else uiDefIconBut(block, LABEL, 0, icon, 2, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); uiBlockSetEmboss(block, UI_EMBOSS); - uiDefBut(block, LABEL, 0, report->message, UI_UNIT_X + 10, 0, UI_UNIT_X + width, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); + uiDefBut(block, LABEL, 0, report->message, UI_UNIT_X + 10, 0, UI_UNIT_X + width, UI_UNIT_Y, + NULL, 0.0f, 0.0f, 0, 0, ""); } /********************************* Keymap *************************************/ diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index bef8fff4ae3..c43fc4bc4e4 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -2648,6 +2648,11 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat } +static void widget_normal(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int UNUSED(roundboxalign)) +{ + ui_draw_but_NORMAL(but, wcol, rect); +} + static void widget_icon_has_anim(uiBut *UNUSED(but), uiWidgetColors *wcol, rcti *rect, int state, int UNUSED(roundboxalign)) { if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_REDALERT)) { @@ -3055,6 +3060,7 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type) break; case UI_WTYPE_NORMAL: + wt.custom = widget_normal; break; case UI_WTYPE_SCROLL: @@ -3294,7 +3300,7 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct break; case BUT_NORMAL: - ui_draw_but_NORMAL(but, &tui->wcol_regular, rect); + wt = widget_type(UI_WTYPE_NORMAL); break; case BUT_IMAGE: diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c index 70b359d3e28..65d70e231a4 100644 --- a/source/blender/editors/mesh/editmesh_add.c +++ b/source/blender/editors/mesh/editmesh_add.c @@ -108,8 +108,8 @@ static int add_primitive_plane_exec(bContext *C, wmOperator *op) obedit = make_prim_init(C, "Plane", &dia, mat, &state, loc, rot, layer); em = BMEdit_FromObject(obedit); - if (!EDBM_op_call_and_selectf(em, op, "vertout", - "create_grid xsegments=%i ysegments=%i size=%f mat=%m4", 1, 1, dia, mat)) + if (!EDBM_op_call_and_selectf(em, op, "verts.out", + "create_grid x_segments=%i y_segments=%i size=%f mat=%m4", 1, 1, dia, mat)) { return OPERATOR_CANCELLED; } @@ -149,7 +149,7 @@ static int add_primitive_cube_exec(bContext *C, wmOperator *op) obedit = make_prim_init(C, "Cube", &dia, mat, &state, loc, rot, layer); em = BMEdit_FromObject(obedit); - if (!EDBM_op_call_and_selectf(em, op, "vertout", "create_cube mat=%m4 size=%f", mat, dia * 2.0f)) { + if (!EDBM_op_call_and_selectf(em, op, "verts.out", "create_cube mat=%m4 size=%f", mat, dia * 2.0f)) { return OPERATOR_CANCELLED; } @@ -198,7 +198,7 @@ static int add_primitive_circle_exec(bContext *C, wmOperator *op) obedit = make_prim_init(C, "Circle", &dia, mat, &state, loc, rot, layer); em = BMEdit_FromObject(obedit); - if (!EDBM_op_call_and_selectf(em, op, "vertout", + if (!EDBM_op_call_and_selectf(em, op, "verts.out", "create_circle segments=%i diameter=%f cap_ends=%b cap_tris=%b mat=%m4", RNA_int_get(op->ptr, "vertices"), RNA_float_get(op->ptr, "radius") * dia, cap_end, cap_tri, mat)) @@ -253,7 +253,7 @@ static int add_primitive_cylinder_exec(bContext *C, wmOperator *op) em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf( - em, op, "vertout", + em, op, "verts.out", "create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%b cap_tris=%b depth=%f mat=%m4", RNA_int_get(op->ptr, "vertices"), RNA_float_get(op->ptr, "radius") * dia, @@ -313,7 +313,7 @@ static int add_primitive_cone_exec(bContext *C, wmOperator *op) em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf( - em, op, "vertout", + em, op, "verts.out", "create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%b cap_tris=%b depth=%f mat=%m4", RNA_int_get(op->ptr, "vertices"), RNA_float_get(op->ptr, "radius1") * dia, RNA_float_get(op->ptr, "radius2") * dia, cap_end, cap_tri, RNA_float_get(op->ptr, "depth") * dia, mat)) @@ -368,8 +368,8 @@ static int add_primitive_grid_exec(bContext *C, wmOperator *op) obedit = make_prim_init(C, "Grid", &dia, mat, &state, loc, rot, layer); em = BMEdit_FromObject(obedit); - if (!EDBM_op_call_and_selectf(em, op, "vertout", - "create_grid xsegments=%i ysegments=%i size=%f mat=%m4", + if (!EDBM_op_call_and_selectf(em, op, "verts.out", + "create_grid x_segments=%i y_segments=%i size=%f mat=%m4", RNA_int_get(op->ptr, "x_subdivisions"), RNA_int_get(op->ptr, "y_subdivisions"), RNA_float_get(op->ptr, "size") * dia, mat)) @@ -420,14 +420,14 @@ static int add_primitive_monkey_exec(bContext *C, wmOperator *op) if (!view_aligned) rot[0] += (float)M_PI / 2.0f; - obedit = make_prim_init(C, "Monkey", &dia, mat, &state, loc, rot, layer); + obedit = make_prim_init(C, "Suzanne", &dia, mat, &state, loc, rot, layer); mat[0][0] *= dia; mat[1][1] *= dia; mat[2][2] *= dia; em = BMEdit_FromObject(obedit); - if (!EDBM_op_call_and_selectf(em, op, "vertout", "create_monkey mat=%m4", mat)) { + if (!EDBM_op_call_and_selectf(em, op, "verts.out", "create_monkey mat=%m4", mat)) { return OPERATOR_CANCELLED; } @@ -466,8 +466,8 @@ static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op) obedit = make_prim_init(C, "Sphere", &dia, mat, &state, loc, rot, layer); em = BMEdit_FromObject(obedit); - if (!EDBM_op_call_and_selectf(em, op, "vertout", - "create_uvsphere segments=%i revolutions=%i diameter=%f mat=%m4", + if (!EDBM_op_call_and_selectf(em, op, "verts.out", + "create_uvsphere u_segments=%i v_segments=%i diameter=%f mat=%m4", RNA_int_get(op->ptr, "segments"), RNA_int_get(op->ptr, "ring_count"), RNA_float_get(op->ptr, "size") * dia, mat)) { @@ -518,7 +518,7 @@ static int add_primitive_icosphere_exec(bContext *C, wmOperator *op) em = BMEdit_FromObject(obedit); if (!EDBM_op_call_and_selectf( - em, op, "vertout", + em, op, "verts.out", "create_icosphere subdivisions=%i diameter=%f mat=%m4", RNA_int_get(op->ptr, "subdivisions"), RNA_float_get(op->ptr, "size") * dia, mat)) diff --git a/source/blender/editors/mesh/editmesh_bvh.c b/source/blender/editors/mesh/editmesh_bvh.c index 3f7100c5417..289dc37b3e4 100644 --- a/source/blender/editors/mesh/editmesh_bvh.c +++ b/source/blender/editors/mesh/editmesh_bvh.c @@ -157,13 +157,13 @@ BMBVHTree *BMBVH_NewBVH(BMEditMesh *em, int flag, Scene *scene, Object *obedit) if (flag & BMBVH_RESPECT_SELECT) { - /* note, the arrays wont allign now! take care */ + /* note, the arrays wont align now! take care */ if (!BM_elem_flag_test(em->looptris[i][0]->f, BM_ELEM_SELECT)) { continue; } } else if (flag & BMBVH_RESPECT_HIDDEN) { - /* note, the arrays wont allign now! take care */ + /* note, the arrays wont align now! take care */ if (BM_elem_flag_test(em->looptris[i][0]->f, BM_ELEM_HIDDEN)) { continue; } diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index f6f226ec614..9e0c85a2f17 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -1828,7 +1828,7 @@ static void remerge_faces(KnifeTool_OpData *kcd) BMO_op_initf(bm, &bmop, "beautify_fill faces=%ff constrain_edges=%fe", FACE_NEW, BOUNDARY); BMO_op_exec(bm, &bmop); - BMO_slot_buffer_flag_enable(bm, &bmop, "geomout", BM_FACE, FACE_NEW); + BMO_slot_buffer_flag_enable(bm, &bmop, "geom.out", BM_FACE, FACE_NEW); BMO_op_finish(bm, &bmop); @@ -2578,8 +2578,8 @@ static void knife_make_chain_cut(KnifeTool_OpData *kcd, BMFace *f, ListBase *cha int nco = BLI_countlist(chain) - 1; float (*cos)[3] = NULL; KnifeVert **kverts; - BLI_array_fixedstack_declare(cos, BM_NGON_STACK_SIZE, nco, __func__); - BLI_array_fixedstack_declare(kverts, BM_NGON_STACK_SIZE, nco, __func__); + BLI_array_fixedstack_declare(cos, BM_DEFAULT_NGON_STACK_SIZE, nco, __func__); + BLI_array_fixedstack_declare(kverts, BM_DEFAULT_NGON_STACK_SIZE, nco, __func__); kfe = ((Ref *)chain->first)->ref; v1 = kfe->v1->v ? kfe->v1->v : kfe->v2->v; diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 851a72f5631..d4b73dd1b64 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -311,7 +311,8 @@ static void ringsel_find_edge(RingSelOpData *lcd, int cuts) static void ringsel_finish(bContext *C, wmOperator *op) { RingSelOpData *lcd = op->customdata; - int cuts = RNA_int_get(op->ptr, "number_cuts"); + const int cuts = RNA_int_get(op->ptr, "number_cuts"); + const float smoothness = 0.292f * RNA_float_get(op->ptr, "smoothness"); if (lcd->eed) { BMEditMesh *em = lcd->em; @@ -323,7 +324,7 @@ static void ringsel_finish(bContext *C, wmOperator *op) * Note though that it will break edgeslide in this specific case. * See [#31939]. */ BM_mesh_esubdivide(em->bm, BM_ELEM_SELECT, - 0.0f, 0.0f, 0.0f, + smoothness, 0.0f, 0.0f, cuts, SUBDIV_SELECT_LOOPCUT, SUBD_PATH, 0, TRUE, 0); @@ -417,6 +418,7 @@ static int ringcut_cancel(bContext *C, wmOperator *op) static int ringcut_invoke(bContext *C, wmOperator *op, wmEvent *evt) { + ScrArea *sa = CTX_wm_area(C); Object *obedit = CTX_data_edit_object(C); RingSelOpData *lcd; BMEdge *edge; @@ -442,13 +444,17 @@ static int ringcut_invoke(bContext *C, wmOperator *op, wmEvent *evt) lcd->eed = edge; ringsel_find_edge(lcd, 1); } - ED_area_headerprint(CTX_wm_area(C), "Select a ring to be cut, use mouse-wheel or page-up/down for number of cuts"); + ED_area_headerprint(sa, + "Select a ring to be cut, " + "use mouse-wheel or page-up/down for number of cuts, " + "Hold Alt for smooth"); return OPERATOR_RUNNING_MODAL; } static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event) { + float smoothness = RNA_float_get(op->ptr, "smoothness"); int cuts = RNA_int_get(op->ptr, "number_cuts"); RingSelOpData *lcd = op->customdata; int show_cuts = 0; @@ -495,11 +501,17 @@ static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event) case WHEELUPMOUSE: /* change number of cuts */ if (event->val == KM_RELEASE) break; - - cuts++; - RNA_int_set(op->ptr, "number_cuts", cuts); - ringsel_find_edge(lcd, cuts); - show_cuts = TRUE; + if (event->alt == 0) { + cuts++; + RNA_int_set(op->ptr, "number_cuts", cuts); + ringsel_find_edge(lcd, cuts); + show_cuts = TRUE; + } + else { + smoothness = min_ff(smoothness + 0.05f, 4.0f); + RNA_float_set(op->ptr, "smoothness", smoothness); + show_cuts = TRUE; + } ED_region_tag_redraw(lcd->ar); break; @@ -509,10 +521,17 @@ static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event) if (event->val == KM_RELEASE) break; - cuts = max_ii(cuts - 1, 0); - RNA_int_set(op->ptr, "number_cuts", cuts); - ringsel_find_edge(lcd, cuts); - show_cuts = TRUE; + if (event->alt == 0) { + cuts = max_ii(cuts - 1, 0); + RNA_int_set(op->ptr, "number_cuts", cuts); + ringsel_find_edge(lcd, cuts); + show_cuts = TRUE; + } + else { + smoothness = max_ff(smoothness - 0.05f, 0.0f); + RNA_float_set(op->ptr, "smoothness", smoothness); + show_cuts = TRUE; + } ED_region_tag_redraw(lcd->ar); break; @@ -556,7 +575,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event) if (show_cuts) { char buf[64]; - BLI_snprintf(buf, sizeof(buf), "Number of Cuts: %d", cuts); + BLI_snprintf(buf, sizeof(buf), "Number of Cuts: %d, Smooth: %.2f (Alt)", cuts, smoothness); ED_area_headerprint(CTX_wm_area(C), buf); } @@ -608,4 +627,7 @@ void MESH_OT_loopcut(wmOperatorType *ot) prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, INT_MAX, "Number of Cuts", "", 1, 10); /* avoid re-using last var because it can cause _very_ high poly meshes and annoy users (or worse crash) */ RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + prop = RNA_def_float(ot->srna, "smoothness", 0.0f, 0.0f, FLT_MAX, "Smoothness", "Smoothness factor", 0.0f, 4.0f); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index 6379bdbc0ca..d3a4c951e06 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -489,7 +489,7 @@ static void edbm_tagged_loop_pairs_do_fill_faces(BMesh *bm, UnorderedLoopPair *u } /* face should never exist */ - BLI_assert(BM_face_exists(bm, f_verts, f_verts[3] ? 4 : 3, &f) == FALSE); + BLI_assert(BM_face_exists(f_verts, f_verts[3] ? 4 : 3, &f) == FALSE); f = BM_face_create_quad_tri_v(bm, f_verts, f_verts[3] ? 4 : 3, f_example, FALSE); diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 0bdb5032a30..453c29f004f 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -56,6 +56,7 @@ #include "ED_mesh.h" #include "ED_screen.h" +#include "ED_util.h" #include "ED_uvedit.h" #include "ED_object.h" #include "ED_view3d.h" @@ -69,6 +70,7 @@ #include "mesh_intern.h" +#include "UI_resources.h" /* ****************************** MIRROR **************** */ @@ -731,7 +733,7 @@ static int similar_face_select_exec(bContext *C, wmOperator *op) EDBM_flag_disable_all(em, BM_ELEM_SELECT); /* select the output */ - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "faceout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_ALL, BM_ELEM_SELECT, TRUE); /* finish the operator */ if (!EDBM_op_finish(em, &bmop, op, TRUE)) { @@ -772,7 +774,7 @@ static int similar_edge_select_exec(bContext *C, wmOperator *op) EDBM_flag_disable_all(em, BM_ELEM_SELECT); /* select the output */ - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "edgeout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_ALL, BM_ELEM_SELECT, TRUE); EDBM_selectmode_flush(em); /* finish the operator */ @@ -816,7 +818,7 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) EDBM_flag_disable_all(em, BM_ELEM_SELECT); /* select the output */ - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "vertout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "verts.out", BM_ALL, BM_ELEM_SELECT, TRUE); /* finish the operator */ if (!EDBM_op_finish(em, &bmop, op, TRUE)) { @@ -916,6 +918,74 @@ void MESH_OT_select_similar(wmOperatorType *ot) RNA_def_float(ot->srna, "threshold", 0.0, 0.0, 1.0, "Threshold", "", 0.0, 1.0); } + +/* **************** Mode Select *************** */ + +static int edbm_select_mode_exec(bContext *C, wmOperator *op) +{ + const int type = RNA_enum_get(op->ptr, "type"); + const int action = RNA_enum_get(op->ptr, "action"); + const int use_extend = RNA_boolean_get(op->ptr, "use_extend"); + const int use_expand = RNA_boolean_get(op->ptr, "use_expand"); + + if (EDBM_selectmode_toggle(C, type, action, use_extend, use_expand)) { + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +static int edbm_select_mode_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + // RNA_enum_set(op->ptr, "type"); /* type must be set already */ + RNA_boolean_set(op->ptr, "use_extend", event->shift); + RNA_boolean_set(op->ptr, "use_expand", event->ctrl); + return edbm_select_mode_exec(C, op); +} + +void MESH_OT_select_mode(wmOperatorType *ot) +{ + PropertyRNA *prop; + + static EnumPropertyItem elem_items[] = { + {SCE_SELECT_VERTEX, "VERT", ICON_VERTEXSEL, "Vertices", ""}, + {SCE_SELECT_EDGE, "EDGE", ICON_EDGESEL, "Edges", ""}, + {SCE_SELECT_FACE, "FACE", ICON_FACESEL, "Faces", ""}, + {0, NULL, 0, NULL, NULL}, + }; + + static EnumPropertyItem actions_items[] = { + {0, "DISABLE", 0, "Disable", "Disable selected markers"}, + {1, "ENABLE", 0, "Enable", "Enable selected markers"}, + {2, "TOGGLE", 0, "Toggle", "Toggle disabled flag for selected markers"}, + {0, NULL, 0, NULL, NULL} + }; + + /* identifiers */ + ot->name = "Select Mode"; + ot->idname = "MESH_OT_select_mode"; + ot->description = "Change selection mode"; + + /* api callbacks */ + ot->invoke = edbm_select_mode_invoke; + ot->exec = edbm_select_mode_exec; + ot->poll = ED_operator_editmesh; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + prop = RNA_def_boolean(ot->srna, "use_extend", FALSE, "Extend", ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "use_expand", FALSE, "Expand", ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + ot->prop = prop = RNA_def_enum(ot->srna, "type", elem_items, 0, "Type", ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + RNA_def_enum(ot->srna, "action", actions_items, 2, "Action", "Selection action to execute"); +} + /* ***************************************************** */ /* **************** LOOP SELECTS *************** */ @@ -1014,7 +1084,7 @@ void MESH_OT_loop_multi_select(wmOperatorType *ot) /* ***************** loop select (non modal) ************** */ -static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short ring) +static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short deselect, short toggle, short ring) { ViewContext vc; BMEditMesh *em; @@ -1033,14 +1103,20 @@ static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short ring) eed = EDBM_edge_find_nearest(&vc, &dist); if (eed) { - if (extend == 0) { + if (extend == 0 && deselect == 0 && toggle == 0) { EDBM_flag_disable_all(em, BM_ELEM_SELECT); } - if (BM_elem_flag_test(eed, BM_ELEM_SELECT) == 0) { + if (extend) { + select = TRUE; + } + else if (deselect) { + select = FALSE; + } + else if (BM_elem_flag_test(eed, BM_ELEM_SELECT) == 0) { select = TRUE; } - else if (extend) { + else if (toggle) { select = FALSE; } @@ -1133,6 +1209,8 @@ static int edbm_select_loop_invoke(bContext *C, wmOperator *op, wmEvent *event) view3d_operator_needs_opengl(C); mouse_mesh_loop(C, event->mval, RNA_boolean_get(op->ptr, "extend"), + RNA_boolean_get(op->ptr, "deselect"), + RNA_boolean_get(op->ptr, "toggle"), RNA_boolean_get(op->ptr, "ring")); /* cannot do tweaks for as long this keymap is after transform map */ @@ -1155,6 +1233,8 @@ void MESH_OT_loop_select(wmOperatorType *ot) /* properties */ RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", "Extend the selection"); + RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from the selection"); + RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Select", "Toggle the selection"); RNA_def_boolean(ot->srna, "ring", 0, "Select Ring", "Select ring"); } @@ -1173,6 +1253,8 @@ void MESH_OT_edgering_select(wmOperatorType *ot) ot->flag = OPTYPE_UNDO; RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection"); + RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Remove from the selection"); + RNA_def_boolean(ot->srna, "toggle", 0, "Toggle Select", "Toggle the selection"); RNA_def_boolean(ot->srna, "ring", 1, "Select Ring", "Select ring"); } @@ -1882,58 +1964,148 @@ void EDBM_selectmode_convert(BMEditMesh *em, short selectmode_old, short selectm BMFace *efa; BMIter iter; + /* first tag-to-select, then select --- this avoids a feedback loop */ + /* have to find out what the selectionmode was previously */ if (selectmode_old == SCE_SELECT_VERTEX) { if (selectmode_new == SCE_SELECT_EDGE) { - /* select all edges associated with every selected vertex */ - eed = BM_iter_new(&iter, em->bm, BM_EDGES_OF_MESH, NULL); - for (; eed; eed = BM_iter_step(&iter)) { - if ((BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) || - BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))) - { + /* select all edges associated with every selected vert */ + BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { + BM_elem_flag_set(eed, BM_ELEM_TAG, BM_edge_is_any_vert_flag_test(eed, BM_ELEM_SELECT)); + } + + BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(eed, BM_ELEM_TAG)) { BM_edge_select_set(em->bm, eed, TRUE); } } } else if (selectmode_new == SCE_SELECT_FACE) { - BMIter liter; - BMLoop *l; - - /* select all faces associated with every selected vertex */ - efa = BM_iter_new(&iter, em->bm, BM_FACES_OF_MESH, NULL); - for (; efa; efa = BM_iter_step(&iter)) { - l = BM_iter_new(&liter, em->bm, BM_LOOPS_OF_FACE, efa); - for (; l; l = BM_iter_step(&liter)) { - if (BM_elem_flag_test(l->v, BM_ELEM_SELECT)) { - BM_face_select_set(em->bm, efa, TRUE); - break; - } + /* select all faces associated with every selected vert */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_elem_flag_set(efa, BM_ELEM_TAG, BM_face_is_any_vert_flag_test(efa, BM_ELEM_SELECT)); + } + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { + BM_face_select_set(em->bm, efa, TRUE); } } } } else if (selectmode_old == SCE_SELECT_EDGE) { if (selectmode_new == SCE_SELECT_FACE) { - BMIter liter; - BMLoop *l; - - /* select all faces associated with every selected vertex */ - efa = BM_iter_new(&iter, em->bm, BM_FACES_OF_MESH, NULL); - for (; efa; efa = BM_iter_step(&iter)) { - l = BM_iter_new(&liter, em->bm, BM_LOOPS_OF_FACE, efa); - for (; l; l = BM_iter_step(&liter)) { - if (BM_elem_flag_test(l->v, BM_ELEM_SELECT)) { - BM_face_select_set(em->bm, efa, TRUE); - break; - } + /* select all faces associated with every selected edge */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_elem_flag_set(efa, BM_ELEM_TAG, BM_face_is_any_edge_flag_test(efa, BM_ELEM_SELECT)); + } + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { + BM_face_select_set(em->bm, efa, TRUE); } } } } } +/* user facing function, does notification and undo push */ +int EDBM_selectmode_toggle(bContext *C, const short selectmode_new, + const int action, const int use_extend, const int use_expand) +{ + ToolSettings *ts = CTX_data_tool_settings(C); + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = NULL; + int ret = FALSE; + + if (obedit && obedit->type == OB_MESH) { + em = BMEdit_FromObject(obedit); + } + + if (em == NULL) { + return ret; + } -void EDBM_deselect_by_material(BMEditMesh *em, short index, short select) + switch (action) { + case -1: + /* already set */ + break; + case 0: /* disable */ + /* check we have something to do */ + if ((em->selectmode & selectmode_new) == 0) { + return FALSE; + } + em->selectmode &= ~selectmode_new; + break; + case 1: /* enable */ + /* check we have something to do */ + if ((em->selectmode & selectmode_new) != 0) { + return FALSE; + } + em->selectmode |= selectmode_new; + break; + case 2: /* toggle */ + /* can't disable this flag if its the only one set */ + if (em->selectmode == selectmode_new) { + return FALSE; + } + em->selectmode ^= selectmode_new; + break; + default: + BLI_assert(0); + } + + switch (selectmode_new) { + case SCE_SELECT_VERTEX: + if (use_extend == 0 || em->selectmode == 0) + em->selectmode = SCE_SELECT_VERTEX; + ts->selectmode = em->selectmode; + EDBM_selectmode_set(em); + ret = TRUE; + break; + case SCE_SELECT_EDGE: + if (use_extend == 0 || em->selectmode == 0) { + if (use_expand) { + const short selmode_max = highest_order_bit_s(ts->selectmode); + if (selmode_max == SCE_SELECT_VERTEX) { + EDBM_selectmode_convert(em, selmode_max, SCE_SELECT_EDGE); + } + } + em->selectmode = SCE_SELECT_EDGE; + } + ts->selectmode = em->selectmode; + EDBM_selectmode_set(em); + ret = TRUE; + break; + case SCE_SELECT_FACE: + if (use_extend == 0 || em->selectmode == 0) { + if (use_expand) { + const short selmode_max = highest_order_bit_s(ts->selectmode); + if (ELEM(selmode_max, SCE_SELECT_VERTEX, SCE_SELECT_EDGE)) { + EDBM_selectmode_convert(em, selmode_max, SCE_SELECT_FACE); + } + } + + em->selectmode = SCE_SELECT_FACE; + } + ts->selectmode = em->selectmode; + EDBM_selectmode_set(em); + ret = TRUE; + break; + default: + BLI_assert(0); + break; + } + + if (ret == TRUE) { + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL); + } + + return ret; +} + +void EDBM_deselect_by_material(BMEditMesh *em, const short index, const short select) { BMIter iter; BMFace *efa; @@ -2079,6 +2251,8 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent * return OPERATOR_CANCELLED; if (limit) { + /* grr, shouldn't need to alloc BMO flags here */ + BM_mesh_elem_toolflags_ensure(bm); /* hflag no-seam --> bmo-tag */ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { /* BMESH_TODO, don't use 'BM_ELEM_SELECT' here, its a HFLAG only! */ @@ -2171,6 +2345,8 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) } if (limit) { + /* grr, shouldn't need to alloc BMO flags here */ + BM_mesh_elem_toolflags_ensure(bm); BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { /* BMESH_TODO, don't use 'BM_ELEM_SELECT' here, its a HFLAG only! */ BMO_elem_flag_set(bm, e, BM_ELEM_SELECT, !BM_elem_flag_test(e, BM_ELEM_SEAM)); @@ -2191,6 +2367,10 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op) } } BMW_end(&walker); + + if (limit) { + BM_mesh_elem_toolflags_clear(bm); + } } else { BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) { @@ -2336,6 +2516,9 @@ static void walker_deselect_nth(BMEditMesh *em, int nth, int offset, BMHeader *h break; } + /* grr, shouldn't need to alloc BMO flags here */ + BM_mesh_elem_toolflags_ensure(bm); + /* Walker restrictions uses BMO flags, not header flags, * so transfer BM_ELEM_SELECT from HFlags onto a BMO flag layer. */ BMO_push(bm, NULL); diff --git a/source/blender/editors/mesh/editmesh_slide.c b/source/blender/editors/mesh/editmesh_slide.c index 5d77dd88c91..e5889955fc7 100644 --- a/source/blender/editors/mesh/editmesh_slide.c +++ b/source/blender/editors/mesh/editmesh_slide.c @@ -741,10 +741,10 @@ static int edbm_vertex_slide_exec_ex(bContext *C, wmOperator *op, const int do_u BMO_op_exec(bm, &bmop); /* Deselect the input edges */ - BMO_slot_buffer_hflag_disable(bm, &bmop, "edge", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_disable(bm, bmop.slots_in, "edge", BM_ALL, BM_ELEM_SELECT, TRUE); /* Select the output vert */ - BMO_slot_buffer_hflag_enable(bm, &bmop, "vertout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "verts.out", BM_ALL, BM_ELEM_SELECT, TRUE); /* Flush the select buffers */ EDBM_selectmode_flush(em); diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 0c5c756a0fc..9bc926598db 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -72,6 +72,7 @@ #include "RE_render_ext.h" #include "UI_interface.h" +#include "UI_resources.h" #include "mesh_intern.h" @@ -242,7 +243,7 @@ static short edbm_extrude_discrete_faces(BMEditMesh *em, wmOperator *op, const c BMO_op_exec(em->bm, &bmop); - BMO_ITER (f, &siter, em->bm, &bmop, "faceout", BM_FACE) { + BMO_ITER (f, &siter, bmop.slots_out, "faces.out", BM_FACE) { BM_face_select_set(em->bm, f, TRUE); /* set face vertex normals to face normal */ @@ -269,7 +270,7 @@ static short edbm_extrude_edges_indiv(BMEditMesh *em, wmOperator *op, const char EDBM_flag_disable_all(em, BM_ELEM_SELECT); BMO_op_exec(em->bm, &bmop); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "geomout", BM_VERT | BM_EDGE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_VERT | BM_EDGE, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return 0; @@ -286,10 +287,10 @@ static short edbm_extrude_verts_indiv(BMEditMesh *em, wmOperator *op, const char EDBM_op_init(em, &bmop, op, "extrude_vert_indiv verts=%hv", hflag); /* deselect original verts */ - BMO_slot_buffer_hflag_disable(em->bm, &bmop, "verts", BM_VERT, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_in, "verts", BM_VERT, BM_ELEM_SELECT, TRUE); BMO_op_exec(em->bm, &bmop); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "vertout", BM_VERT, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "verts.out", BM_VERT, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return 0; @@ -308,9 +309,12 @@ static short edbm_extrude_edge(Object *obedit, BMEditMesh *em, const char hflag, BMFace *f; ModifierData *md; BMElem *ele; + BMOpSlot *slot_edges_exclude; BMO_op_init(bm, &extop, BMO_FLAG_DEFAULTS, "extrude_face_region"); - BMO_slot_buffer_from_enabled_hflag(bm, &extop, "edgefacein", BM_VERT | BM_EDGE | BM_FACE, hflag); + BMO_slot_buffer_from_enabled_hflag(bm, &extop, extop.slots_in, "geom", BM_VERT | BM_EDGE | BM_FACE, hflag); + + slot_edges_exclude = BMO_slot_get(extop.slots_in, "edges_exclude"); /* If a mirror modifier with clipping is on, we need to adjust some * of the cases above to handle edges on the line of symmetry. @@ -350,21 +354,21 @@ static short edbm_extrude_edge(Object *obedit, BMEditMesh *em, const char hflag, if ((fabsf(co1[0]) < mmd->tolerance) && (fabsf(co2[0]) < mmd->tolerance)) { - BMO_slot_map_ptr_insert(bm, &extop, "exclude", edge, NULL); + BMO_slot_map_ptr_insert(&extop, slot_edges_exclude, edge, NULL); } } if (mmd->flag & MOD_MIR_AXIS_Y) { if ((fabsf(co1[1]) < mmd->tolerance) && (fabsf(co2[1]) < mmd->tolerance)) { - BMO_slot_map_ptr_insert(bm, &extop, "exclude", edge, NULL); + BMO_slot_map_ptr_insert(&extop, slot_edges_exclude, edge, NULL); } } if (mmd->flag & MOD_MIR_AXIS_Z) { if ((fabsf(co1[2]) < mmd->tolerance) && (fabsf(co2[2]) < mmd->tolerance)) { - BMO_slot_map_ptr_insert(bm, &extop, "exclude", edge, NULL); + BMO_slot_map_ptr_insert(&extop, slot_edges_exclude, edge, NULL); } } } @@ -379,7 +383,7 @@ static short edbm_extrude_edge(Object *obedit, BMEditMesh *em, const char hflag, zero_v3(nor); - BMO_ITER (ele, &siter, bm, &extop, "geomout", BM_ALL) { + BMO_ITER (ele, &siter, extop.slots_out, "geom.out", BM_ALL) { BM_elem_select_set(bm, ele, TRUE); if (ele->head.htype == BM_FACE) { @@ -449,7 +453,7 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op) for (a = 0; a < steps; a++) { edbm_extrude_edge(obedit, em, BM_ELEM_SELECT, nor); - //BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, "extrude_face_region edgefacein=%hef", BM_ELEM_SELECT); + //BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, "extrude_face_region geom=%hef", BM_ELEM_SELECT); BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, "translate vec=%v verts=%hv", (float *)dvec, BM_ELEM_SELECT); @@ -915,7 +919,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent EDBM_op_init(vc.em, &bmop, op, "create_vert co=%v", min); BMO_op_exec(vc.em->bm, &bmop); - BMO_ITER (v1, &oiter, vc.em->bm, &bmop, "newvertout", BM_VERT) { + BMO_ITER (v1, &oiter, bmop.slots_out, "vert.out", BM_VERT) { BM_vert_select_set(vc.em->bm, v1, TRUE); } @@ -1110,8 +1114,8 @@ static int edbm_add_edge_face_exec(bContext *C, wmOperator *op) } BMO_op_exec(em->bm, &bmop); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "faceout", BM_FACE, BM_ELEM_SELECT, TRUE); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "edgeout", BM_EDGE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; @@ -1261,7 +1265,7 @@ static int edbm_vert_connect(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } BMO_op_exec(bm, &bmop); - len = BMO_slot_get(&bmop, "edgeout")->len; + len = BMO_slot_get(bmop.slots_out, "edges.out")->len; if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; } @@ -1301,7 +1305,7 @@ static int edbm_edge_split_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } BMO_op_exec(bm, &bmop); - len = BMO_slot_get(&bmop, "edgeout")->len; + len = BMO_slot_get(bmop.slots_out, "edges.out")->len; if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; } @@ -1339,7 +1343,7 @@ static int edbm_duplicate_exec(bContext *C, wmOperator *op) BMO_op_exec(em->bm, &bmop); EDBM_flag_disable_all(em, BM_ELEM_SELECT); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "newout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; @@ -1405,8 +1409,8 @@ void MESH_OT_flip_normals(wmOperatorType *ot) } static const EnumPropertyItem direction_items[] = { - {DIRECTION_CW, "CW", 0, "Clockwise", ""}, - {DIRECTION_CCW, "CCW", 0, "Counter Clockwise", ""}, + {FALSE, "CW", 0, "Clockwise", ""}, + {TRUE, "CCW", 0, "Counter Clockwise", ""}, {0, NULL, 0, NULL, NULL} }; @@ -1418,7 +1422,7 @@ static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op) BMOperator bmop; BMEdge *eed; BMIter iter; - const int do_ccw = RNA_enum_get(op->ptr, "direction") == 1; + const int use_ccw = RNA_boolean_get(op->ptr, "use_ccw"); int tot = 0; if (em->bm->totedgesel == 0) { @@ -1448,17 +1452,17 @@ static int edbm_edge_rotate_selected_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_ERROR, "Could not find any selected edges that can be rotated"); return OPERATOR_CANCELLED; } - - EDBM_op_init(em, &bmop, op, "rotate_edges edges=%he ccw=%b", BM_ELEM_TAG, do_ccw); + + EDBM_op_init(em, &bmop, op, "rotate_edges edges=%he use_ccw=%b", BM_ELEM_TAG, use_ccw); /* avoids leaving old verts selected which can be a problem running multiple times, * since this means the edges become selected around the face which then attempt to rotate */ - BMO_slot_buffer_hflag_disable(em->bm, &bmop, "edges", BM_EDGE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_in, "edges", BM_EDGE, BM_ELEM_SELECT, TRUE); BMO_op_exec(em->bm, &bmop); /* edges may rotate into hidden vertices, if this does _not_ run we get an ilogical state */ - BMO_slot_buffer_hflag_disable(em->bm, &bmop, "edgeout", BM_EDGE, BM_ELEM_HIDDEN, TRUE); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "edgeout", BM_EDGE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_HIDDEN, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, TRUE); EDBM_selectmode_flush(em); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { @@ -1485,7 +1489,7 @@ void MESH_OT_edge_rotate(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* props */ - RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "Direction", "Direction to rotate edge around"); + RNA_def_boolean(ot->srna, "use_ccw", FALSE, "Counter Clockwise", ""); } @@ -1553,7 +1557,7 @@ static int edbm_normals_make_consistent_exec(bContext *C, wmOperator *op) /* doflip has to do with bmesh_rationalize_normals, it's an internal * thing */ - if (!EDBM_op_callf(em, op, "recalc_face_normals faces=%hf do_flip=%b", BM_ELEM_SELECT, TRUE)) + if (!EDBM_op_callf(em, op, "recalc_face_normals faces=%hf use_flip=%b", BM_ELEM_SELECT, TRUE)) return OPERATOR_CANCELLED; if (RNA_boolean_get(op->ptr, "inside")) @@ -1590,7 +1594,7 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op) ModifierData *md; int mirrx = FALSE, mirry = FALSE, mirrz = FALSE; int i, repeat; - float clipdist = 0.0f; + float clip_dist = 0.0f; int xaxis = RNA_boolean_get(op->ptr, "xaxis"); int yaxis = RNA_boolean_get(op->ptr, "yaxis"); @@ -1616,7 +1620,7 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op) if (mmd->flag & MOD_MIR_AXIS_Z) mirrz = TRUE; - clipdist = mmd->tolerance; + clip_dist = mmd->tolerance; } } } @@ -1627,9 +1631,9 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op) for (i = 0; i < repeat; i++) { if (!EDBM_op_callf(em, op, - "smooth_vert verts=%hv mirror_clip_x=%b mirror_clip_y=%b mirror_clip_z=%b clipdist=%f " + "smooth_vert verts=%hv mirror_clip_x=%b mirror_clip_y=%b mirror_clip_z=%b clip_dist=%f " "use_axis_x=%b use_axis_y=%b use_axis_z=%b", - BM_ELEM_SELECT, mirrx, mirry, mirrz, clipdist, xaxis, yaxis, zaxis)) + BM_ELEM_SELECT, mirrx, mirry, mirrz, clip_dist, xaxis, yaxis, zaxis)) { return OPERATOR_CANCELLED; } @@ -1670,7 +1674,7 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); - int usex = TRUE, usey = TRUE, usez = TRUE, volume_preservation = TRUE; + int usex = TRUE, usey = TRUE, usez = TRUE, preserve_volume = TRUE; int i, repeat; float lambda; float lambda_border; @@ -1698,14 +1702,14 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op) usex = RNA_boolean_get(op->ptr, "use_x"); usey = RNA_boolean_get(op->ptr, "use_y"); usez = RNA_boolean_get(op->ptr, "use_z"); - volume_preservation = RNA_boolean_get(op->ptr, "volume_preservation"); + preserve_volume = RNA_boolean_get(op->ptr, "preserve_volume"); if (!repeat) repeat = 1; for (i = 0; i < repeat; i++) { if (!EDBM_op_callf(em, op, - "smooth_laplacian_vert verts=%hv lambda=%f lambda_border=%f use_x=%b use_y=%b use_z=%b volume_preservation=%b", - BM_ELEM_SELECT, lambda, lambda_border, usex, usey, usez, volume_preservation)) + "smooth_laplacian_vert verts=%hv lambda=%f lambda_border=%f use_x=%b use_y=%b use_z=%b preserve_volume=%b", + BM_ELEM_SELECT, lambda, lambda_border, usex, usey, usez, preserve_volume)) { return OPERATOR_CANCELLED; } @@ -1745,7 +1749,7 @@ void MESH_OT_vertices_smooth_laplacian(wmOperatorType *ot) RNA_def_boolean(ot->srna, "use_x", 1, "Smooth X Axis", "Smooth object along X axis"); RNA_def_boolean(ot->srna, "use_y", 1, "Smooth Y Axis", "Smooth object along Y axis"); RNA_def_boolean(ot->srna, "use_z", 1, "Smooth Z Axis", "Smooth object along Z axis"); - RNA_def_boolean(ot->srna, "volume_preservation", 1, "Preserve Volume", "Apply volume preservation after smooth"); + RNA_def_boolean(ot->srna, "preserve_volume", 1, "Preserve Volume", "Apply volume preservation after smooth"); } /********************** Smooth/Solid Operators *************************/ @@ -1828,10 +1832,10 @@ static int edbm_rotate_uvs_exec(bContext *C, wmOperator *op) BMOperator bmop; /* get the direction from RNA */ - int dir = RNA_enum_get(op->ptr, "direction"); + const int use_ccw = RNA_boolean_get(op->ptr, "use_ccw"); /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ - EDBM_op_init(em, &bmop, op, "rotate_uvs faces=%hf dir=%i", BM_ELEM_SELECT, dir); + EDBM_op_init(em, &bmop, op, "rotate_uvs faces=%hf use_ccw=%b", BM_ELEM_SELECT, use_ccw); /* execute the operator */ BMO_op_exec(em->bm, &bmop); @@ -1877,10 +1881,10 @@ static int edbm_rotate_colors_exec(bContext *C, wmOperator *op) BMOperator bmop; /* get the direction from RNA */ - int dir = RNA_enum_get(op->ptr, "direction"); + const int use_ccw = RNA_boolean_get(op->ptr, "use_ccw"); /* initialize the bmop using EDBM api, which does various ui error reporting and other stuff */ - EDBM_op_init(em, &bmop, op, "rotate_colors faces=%hf dir=%i", BM_ELEM_SELECT, dir); + EDBM_op_init(em, &bmop, op, "rotate_colors faces=%hf use_ccw=%b", BM_ELEM_SELECT, use_ccw); /* execute the operator */ BMO_op_exec(em->bm, &bmop); @@ -1936,7 +1940,7 @@ void MESH_OT_uvs_rotate(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* props */ - RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CW, "Direction", "Direction to rotate UVs around"); + RNA_def_boolean(ot->srna, "use_ccw", FALSE, "Counter Clockwise", ""); } //void MESH_OT_uvs_mirror(wmOperatorType *ot) @@ -1973,7 +1977,7 @@ void MESH_OT_colors_rotate(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* props */ - RNA_def_enum(ot->srna, "direction", direction_items, DIRECTION_CCW, "Direction", "Direction to rotate edge around"); + RNA_def_boolean(ot->srna, "use_ccw", FALSE, "Counter Clockwise", ""); } void MESH_OT_colors_reverse(wmOperatorType *ot) @@ -2174,7 +2178,7 @@ void MESH_OT_merge(wmOperatorType *ot) /* properties */ ot->prop = RNA_def_enum(ot->srna, "type", merge_type_items, 3, "Type", "Merge method to use"); RNA_def_enum_funcs(ot->prop, merge_type_itemf); - RNA_def_boolean(ot->srna, "uvs", 1, "UVs", "Move UVs according to merge"); + RNA_def_boolean(ot->srna, "uvs", 0, "UVs", "Move UVs according to merge"); } @@ -2183,7 +2187,7 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op) Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); BMOperator bmop; - const float mergedist = RNA_float_get(op->ptr, "mergedist"); + const float threshold = RNA_float_get(op->ptr, "threshold"); int use_unselected = RNA_boolean_get(op->ptr, "use_unselected"); int totvert_orig = em->bm->totvert; int count; @@ -2191,7 +2195,7 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op) if (use_unselected) { EDBM_op_init(em, &bmop, op, "automerge verts=%hv dist=%f", - BM_ELEM_SELECT, mergedist); + BM_ELEM_SELECT, threshold); BMO_op_exec(em->bm, &bmop); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { @@ -2201,10 +2205,10 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op) else { EDBM_op_init(em, &bmop, op, "find_doubles verts=%hv dist=%f", - BM_ELEM_SELECT, mergedist); + BM_ELEM_SELECT, threshold); BMO_op_exec(em->bm, &bmop); - if (!EDBM_op_callf(em, op, "weld_verts targetmap=%s", &bmop, "targetmapout")) { + if (!EDBM_op_callf(em, op, "weld_verts targetmap=%S", &bmop, "targetmap.out")) { BMO_op_finish(em->bm, &bmop); return OPERATOR_CANCELLED; } @@ -2236,8 +2240,7 @@ void MESH_OT_remove_doubles(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_float(ot->srna, "mergedist", 0.0001f, 0.000001f, 50.0f, - "Merge Distance", + RNA_def_float(ot->srna, "threshold", 0.0001f, 0.000001f, 50.0f, "Merge Distance", "Minimum distance between elements to merge", 0.00001, 10.0); RNA_def_boolean(ot->srna, "use_unselected", 0, "Unselected", "Merge selected to other unselected vertices"); } @@ -2314,7 +2317,7 @@ static int edbm_select_vertex_path_exec(bContext *C, wmOperator *op) /* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */ /* select the output */ - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "vertout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "verts.out", BM_ALL, BM_ELEM_SELECT, TRUE); /* finish the operator */ if (!EDBM_op_finish(em, &bmop, op, TRUE)) { @@ -2439,7 +2442,7 @@ static int edbm_blend_from_shape_exec(bContext *C, wmOperator *op) totshape = CustomData_number_of_layers(&em->bm->vdata, CD_SHAPEKEY); if (totshape == 0 || shape < 0 || shape >= totshape) return OPERATOR_CANCELLED; - + /* get shape key - needed for finding reference shape (for add mode only) */ if (key) { kb = BLI_findlink(&key->block, shape); @@ -2506,6 +2509,22 @@ static EnumPropertyItem *shape_itemf(bContext *C, PointerRNA *UNUSED(ptr), Prop return item; } +static void edbm_blend_from_shape_ui(bContext *C, wmOperator *op) +{ + uiLayout *layout = op->layout; + PointerRNA ptr; + Object *obedit = CTX_data_edit_object(C); + Mesh *me = obedit->data; + PointerRNA ptr_key; + + RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr); + RNA_id_pointer_create((ID *)me->key, &ptr_key); + + uiItemPointerR(layout, &ptr, "shape", &ptr_key, "key_blocks", "", ICON_SHAPEKEY_DATA); + uiItemR(layout, &ptr, "blend", 0, NULL, ICON_NONE); + uiItemR(layout, &ptr, "add", 0, NULL, ICON_NONE); +} + void MESH_OT_blend_from_shape(wmOperatorType *ot) { PropertyRNA *prop; @@ -2518,7 +2537,8 @@ void MESH_OT_blend_from_shape(wmOperatorType *ot) /* api callbacks */ ot->exec = edbm_blend_from_shape_exec; - ot->invoke = WM_operator_props_popup; +// ot->invoke = WM_operator_props_popup_call; /* disable because search popup closes too easily */ + ot->ui = edbm_blend_from_shape_ui; ot->poll = ED_operator_editmesh; /* flags */ @@ -2631,13 +2651,13 @@ static int edbm_solidify_exec(bContext *C, wmOperator *op) /* deselect only the faces in the region to be solidified (leave wire * edges and loose verts selected, as there will be no corresponding * geometry selected below) */ - BMO_slot_buffer_hflag_disable(bm, &bmop, "geom", BM_FACE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_disable(bm, bmop.slots_in, "geom", BM_FACE, BM_ELEM_SELECT, TRUE); /* run the solidify operator */ BMO_op_exec(bm, &bmop); /* select the newly generated faces */ - BMO_slot_buffer_hflag_enable(bm, &bmop, "geomout", BM_FACE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; @@ -2869,6 +2889,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) float isect = 0.0f; int len = 0, isected, i; short numcuts = 1, mode = RNA_int_get(op->ptr, "type"); + BMOpSlot *slot_edgepercents; /* allocd vars */ float (*screen_vert_coords)[2], (*sco)[2], (*mouse_path)[2]; @@ -2923,6 +2944,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) } /* store percentage of edge cut for KNIFE_EXACT here.*/ + slot_edgepercents = BMO_slot_get(bmop.slots_in, "edgepercents"); for (be = BM_iter_new(&iter, bm, BM_EDGES_OF_MESH, NULL); be; be = BM_iter_step(&iter)) { int is_cut = FALSE; if (BM_elem_flag_test(be, BM_ELEM_SELECT)) { @@ -2935,9 +2957,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) if (isect != 0.0f) { if (mode != KNIFE_MULTICUT && mode != KNIFE_MIDPOINT) { - BMO_slot_map_float_insert(bm, &bmop, - "edgepercents", - be, isect); + BMO_slot_map_float_insert(&bmop, slot_edgepercents, be, isect); } } } @@ -2952,16 +2972,16 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) MEM_freeN(mouse_path); - BMO_slot_buffer_from_enabled_flag(bm, &bmop, "edges", BM_EDGE, ELE_EDGE_CUT); + BMO_slot_buffer_from_enabled_flag(bm, &bmop, bmop.slots_in, "edges", BM_EDGE, ELE_EDGE_CUT); if (mode == KNIFE_MIDPOINT) numcuts = 1; - BMO_slot_int_set(&bmop, "numcuts", numcuts); + BMO_slot_int_set(bmop.slots_in, "cuts", numcuts); - BMO_slot_int_set(&bmop, "quadcornertype", SUBD_STRAIGHT_CUT); - BMO_slot_bool_set(&bmop, "use_singleedge", FALSE); - BMO_slot_bool_set(&bmop, "use_gridfill", FALSE); + BMO_slot_int_set(bmop.slots_in, "quad_corner_type", SUBD_STRAIGHT_CUT); + BMO_slot_bool_set(bmop.slots_in, "use_singleedge", FALSE); + BMO_slot_bool_set(bmop.slots_in, "use_gridfill", FALSE); - BMO_slot_float_set(&bmop, "radius", 0); + BMO_slot_float_set(bmop.slots_in, "radius", 0); BMO_op_exec(bm, &bmop); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { @@ -3007,6 +3027,8 @@ static int mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh BMesh *bm_new; bm_new = BM_mesh_create(&bm_mesh_allocsize_default); + BM_mesh_elem_toolflags_ensure(bm_new); /* needed for 'duplicate' bmo */ + CustomData_copy(&bm_old->vdata, &bm_new->vdata, CD_MASK_BMESH, CD_CALLOC, 0); CustomData_copy(&bm_old->edata, &bm_new->edata, CD_MASK_BMESH, CD_CALLOC, 0); CustomData_copy(&bm_old->ldata, &bm_new->ldata, CD_MASK_BMESH, CD_CALLOC, 0); @@ -3302,7 +3324,7 @@ static int edbm_fill_exec(bContext *C, wmOperator *op) BMO_op_exec(em->bm, &bmop); /* select new geometry */ - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "geomout", BM_FACE | BM_EDGE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_FACE | BM_EDGE, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; @@ -3574,7 +3596,7 @@ static int edbm_split_exec(bContext *C, wmOperator *op) EDBM_op_init(em, &bmop, op, "split geom=%hvef use_only_faces=%b", BM_ELEM_SELECT, FALSE); BMO_op_exec(em->bm, &bmop); BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, FALSE); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "geomout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; } @@ -3629,14 +3651,14 @@ static int edbm_spin_exec(bContext *C, wmOperator *op) mul_m3_v3(imat, axis); if (!EDBM_op_init(em, &spinop, op, - "spin geom=%hvef cent=%v axis=%v dvec=%v steps=%i ang=%f do_dupli=%b", + "spin geom=%hvef cent=%v axis=%v dvec=%v steps=%i angle=%f use_duplicate=%b", BM_ELEM_SELECT, cent, axis, d, steps, degr, dupli)) { return OPERATOR_CANCELLED; } BMO_op_exec(bm, &spinop); EDBM_flag_disable_all(em, BM_ELEM_SELECT); - BMO_slot_buffer_hflag_enable(bm, &spinop, "lastout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(bm, spinop.slots_out, "geom_last.out", BM_ALL, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &spinop, op, TRUE)) { return OPERATOR_CANCELLED; } @@ -3753,14 +3775,14 @@ static int edbm_screw_exec(bContext *C, wmOperator *op) negate_v3(dvec); if (!EDBM_op_init(em, &spinop, op, - "spin geom=%hvef cent=%v axis=%v dvec=%v steps=%i ang=%f do_dupli=%b", + "spin geom=%hvef cent=%v axis=%v dvec=%v steps=%i angle=%f use_duplicate=%b", BM_ELEM_SELECT, cent, axis, dvec, turns * steps, 360.0f * turns, FALSE)) { return OPERATOR_CANCELLED; } BMO_op_exec(bm, &spinop); EDBM_flag_disable_all(em, BM_ELEM_SELECT); - BMO_slot_buffer_hflag_enable(bm, &spinop, "lastout", BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(bm, spinop.slots_out, "geom_last.out", BM_ALL, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &spinop, op, TRUE)) { return OPERATOR_CANCELLED; } @@ -4756,11 +4778,20 @@ static int edbm_bevel_calc(bContext *C, wmOperator *op) if (!EDBM_op_init(em, &bmop, op, "bevel geom=%hev offset=%f segments=%i", BM_ELEM_SELECT, offset, segments)) - { - return 0; - } - + { + return 0; + } + BMO_op_exec(em->bm, &bmop); + + if (offset != 0.0f) { + /* not essential, but we may have some loose geometry that + * won't get bevel'd and better not leave it selected */ + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, TRUE); + } + + /* no need to de-select existing geometry */ if (!EDBM_op_finish(em, &bmop, op, TRUE)) return 0; #else @@ -5094,7 +5125,7 @@ static int edbm_bridge_edge_loops_exec(bContext *C, wmOperator *op) /* when merge is used the edges are joined and remain selected */ if (use_merge == FALSE) { EDBM_flag_disable_all(em, BM_ELEM_SELECT); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "faceout", BM_FACE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, TRUE); } if (!EDBM_op_finish(em, &bmop, op, TRUE)) { @@ -5267,11 +5298,11 @@ static int edbm_inset_calc(bContext *C, wmOperator *op) if (use_select_inset) { /* deselect original faces/verts */ EDBM_flag_disable_all(em, BM_ELEM_SELECT); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "faceout", BM_FACE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, TRUE); } else { BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE, BM_ELEM_SELECT, FALSE); - BMO_slot_buffer_hflag_disable(em->bm, &bmop, "faceout", BM_FACE, BM_ELEM_SELECT, FALSE); + BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, FALSE); /* re-select faces so the verts and edges get selected too */ BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, TRUE, BM_ELEM_SELECT); } @@ -5528,7 +5559,7 @@ static int edbm_wireframe_exec(bContext *C, wmOperator *op) if (use_replace) { BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, FALSE); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "faces", BM_FACE, BM_ELEM_TAG, FALSE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_in, "faces", BM_FACE, BM_ELEM_TAG, FALSE); BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, "delete geom=%hvef context=%i", @@ -5536,7 +5567,7 @@ static int edbm_wireframe_exec(bContext *C, wmOperator *op) } BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, FALSE); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "faceout", BM_FACE, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, TRUE); if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; @@ -5599,8 +5630,8 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op) /* Delete unused vertices, edges, and faces */ if (RNA_boolean_get(op->ptr, "delete_unused")) { - if (!EDBM_op_callf(em, op, "delete geom=%s context=%i", - &bmop, "unused_geom", DEL_ONLYTAGGED)) + if (!EDBM_op_callf(em, op, "delete geom=%S context=%i", + &bmop, "geom_unused.out", DEL_ONLYTAGGED)) { EDBM_op_finish(em, &bmop, op, TRUE); return OPERATOR_CANCELLED; @@ -5609,8 +5640,8 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op) /* Delete hole edges/faces */ if (RNA_boolean_get(op->ptr, "make_holes")) { - if (!EDBM_op_callf(em, op, "delete geom=%s context=%i", - &bmop, "holes_geom", DEL_ONLYTAGGED)) + if (!EDBM_op_callf(em, op, "delete geom=%S context=%i", + &bmop, "geom_holes.out", DEL_ONLYTAGGED)) { EDBM_op_finish(em, &bmop, op, TRUE); return OPERATOR_CANCELLED; @@ -5619,8 +5650,8 @@ static int edbm_convex_hull_exec(bContext *C, wmOperator *op) /* Merge adjacent triangles */ if (RNA_boolean_get(op->ptr, "join_triangles")) { - if (!EDBM_op_callf(em, op, "join_triangles faces=%s limit=%f", - &bmop, "geomout", + if (!EDBM_op_callf(em, op, "join_triangles faces=%S limit=%f", + &bmop, "geom.out", RNA_float_get(op->ptr, "limit"))) { EDBM_op_finish(em, &bmop, op, TRUE); diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index ef3d8db4156..22c71d5d3ca 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -263,7 +263,7 @@ int EDBM_op_callf(BMEditMesh *em, wmOperator *op, const char *fmt, ...) return EDBM_op_finish(em, &bmop, op, TRUE); } -int EDBM_op_call_and_selectf(BMEditMesh *em, wmOperator *op, const char *selectslot, const char *fmt, ...) +int EDBM_op_call_and_selectf(BMEditMesh *em, wmOperator *op, const char *select_slot_out, const char *fmt, ...) { BMesh *bm = em->bm; BMOperator bmop; @@ -285,7 +285,7 @@ int EDBM_op_call_and_selectf(BMEditMesh *em, wmOperator *op, const char *selects BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, FALSE); - BMO_slot_buffer_hflag_enable(em->bm, &bmop, selectslot, BM_ALL, BM_ELEM_SELECT, TRUE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, select_slot_out, BM_ALL, BM_ELEM_SELECT, TRUE); va_end(list); return EDBM_op_finish(em, &bmop, op, TRUE); @@ -494,11 +494,11 @@ void EDBM_select_more(BMEditMesh *em) int use_faces = em->selectmode == SCE_SELECT_FACE; BMO_op_initf(em->bm, &bmop, BMO_FLAG_DEFAULTS, - "region_extend geom=%hvef constrict=%b use_faces=%b", + "region_extend geom=%hvef use_constrict=%b use_faces=%b", BM_ELEM_SELECT, FALSE, use_faces); BMO_op_exec(em->bm, &bmop); /* don't flush selection in edge/vertex mode */ - BMO_slot_buffer_hflag_enable(em->bm, &bmop, "geomout", BM_ALL, BM_ELEM_SELECT, use_faces ? TRUE : FALSE); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL, BM_ELEM_SELECT, use_faces ? TRUE : FALSE); BMO_op_finish(em->bm, &bmop); EDBM_select_flush(em); @@ -510,11 +510,11 @@ void EDBM_select_less(BMEditMesh *em) int use_faces = em->selectmode == SCE_SELECT_FACE; BMO_op_initf(em->bm, &bmop, BMO_FLAG_DEFAULTS, - "region_extend geom=%hvef constrict=%b use_faces=%b", + "region_extend geom=%hvef use_constrict=%b use_faces=%b", BM_ELEM_SELECT, TRUE, use_faces); BMO_op_exec(em->bm, &bmop); /* don't flush selection in edge/vertex mode */ - BMO_slot_buffer_hflag_disable(em->bm, &bmop, "geomout", BM_ALL, BM_ELEM_SELECT, use_faces ? TRUE : FALSE); + BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "geom.out", BM_ALL, BM_ELEM_SELECT, use_faces ? TRUE : FALSE); BMO_op_finish(em->bm, &bmop); EDBM_selectmode_flush(em); diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 82b785e5785..8e63bd74ece 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -129,6 +129,7 @@ void MESH_OT_faces_select_linked_flat(struct wmOperatorType *ot); void MESH_OT_edges_select_sharp(struct wmOperatorType *ot); void MESH_OT_select_shortest_path(struct wmOperatorType *ot); void MESH_OT_select_similar(struct wmOperatorType *ot); +void MESH_OT_select_mode(struct wmOperatorType *ot); void MESH_OT_select_random(struct wmOperatorType *ot); void MESH_OT_loop_multi_select(struct wmOperatorType *ot); void MESH_OT_mark_seam(struct wmOperatorType *ot); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index d319fdcca26..a413a60412c 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -129,6 +129,7 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_edge_face_add); WM_operatortype_append(MESH_OT_select_shortest_path); WM_operatortype_append(MESH_OT_select_similar); + WM_operatortype_append(MESH_OT_select_mode); WM_operatortype_append(MESH_OT_loop_multi_select); WM_operatortype_append(MESH_OT_mark_seam); WM_operatortype_append(MESH_OT_mark_sharp); @@ -277,13 +278,21 @@ void ED_keymap_mesh(wmKeyConfig *keyconf) /* standard mouse selection goes via space_view3d */ kmi = WM_keymap_add_item(keymap, "MESH_OT_loop_select", SELECTMOUSE, KM_PRESS, KM_ALT, 0); RNA_boolean_set(kmi->ptr, "extend", FALSE); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + RNA_boolean_set(kmi->ptr, "toggle", FALSE); kmi = WM_keymap_add_item(keymap, "MESH_OT_loop_select", SELECTMOUSE, KM_PRESS, KM_SHIFT | KM_ALT, 0); - RNA_boolean_set(kmi->ptr, "extend", TRUE); + RNA_boolean_set(kmi->ptr, "extend", FALSE); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + RNA_boolean_set(kmi->ptr, "toggle", TRUE); kmi = WM_keymap_add_item(keymap, "MESH_OT_edgering_select", SELECTMOUSE, KM_PRESS, KM_ALT | KM_CTRL, 0); RNA_boolean_set(kmi->ptr, "extend", FALSE); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + RNA_boolean_set(kmi->ptr, "toggle", FALSE); kmi = WM_keymap_add_item(keymap, "MESH_OT_edgering_select", SELECTMOUSE, KM_PRESS, KM_SHIFT | KM_ALT | KM_CTRL, 0); - RNA_boolean_set(kmi->ptr, "extend", TRUE); + RNA_boolean_set(kmi->ptr, "extend", FALSE); + RNA_boolean_set(kmi->ptr, "deselect", FALSE); + RNA_boolean_set(kmi->ptr, "toggle", TRUE); WM_keymap_add_item(keymap, "MESH_OT_select_shortest_path", SELECTMOUSE, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index ee3c66b6eac..e144c38a350 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -114,7 +114,7 @@ typedef struct { } MultiresBakeRender; typedef void (*MPassKnownData)(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data, - const int face_index, const int lvl, const float st[2], + 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); @@ -133,6 +133,7 @@ typedef struct { DerivedMesh *lores_dm, *hires_dm; int lvl; void *bake_data; + ImBuf *ibuf; MPassKnownData pass_data; } MResolvePixelData; @@ -257,7 +258,7 @@ static void flush_pixel(const MResolvePixelData *data, const int x, const int y) /* sequence end */ data->pass_data(data->lores_dm, data->hires_dm, data->bake_data, - data->face_index, data->lvl, st, to_tang, x, y); + data->ibuf, data->face_index, data->lvl, st, to_tang, x, y); } static void set_rast_triangle(const MBakeRast *bake_rast, const int x, const int y) @@ -368,7 +369,7 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, MPassKnownData MInitBakeData initBakeData, MApplyBakeData applyBakeData, MFreeBakeData freeBakeData) { DerivedMesh *dm = bkr->lores_dm; - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); const int lvl = bkr->lvl; const int tot_face = dm->getNumTessFaces(dm); MVert *mvert = dm->getVertArray(dm); @@ -414,6 +415,7 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, MPassKnownData continue; data.face_index = f; + data.ibuf = ibuf; /* might support other forms of diagonal splits later on such as * split by shortest diagonal.*/ @@ -449,32 +451,8 @@ static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, MPassKnownData if (freeBakeData) freeBakeData(data.bake_data); } -} - -static void interp_bilinear_quad_data(float data[4][3], float u, float v, float res[3]) -{ - float vec[3]; - - copy_v3_v3(res, data[0]); - mul_v3_fl(res, (1 - u) * (1 - v)); - copy_v3_v3(vec, data[1]); - mul_v3_fl(vec, u * (1 - v)); add_v3_v3(res, vec); - copy_v3_v3(vec, data[2]); - mul_v3_fl(vec, u * v); add_v3_v3(res, vec); - copy_v3_v3(vec, data[3]); - mul_v3_fl(vec, (1 - u) * v); add_v3_v3(res, vec); -} -static void interp_barycentric_tri_data(float data[3][3], float u, float v, float res[3]) -{ - float vec[3]; - - copy_v3_v3(res, data[0]); - mul_v3_fl(res, u); - copy_v3_v3(vec, data[1]); - mul_v3_fl(vec, v); add_v3_v3(res, vec); - copy_v3_v3(vec, data[2]); - mul_v3_fl(vec, 1.0f - u - v); add_v3_v3(res, vec); + BKE_image_release_ibuf(ima, ibuf, NULL); } /* mode = 0: interpolate normals, @@ -507,7 +485,7 @@ static void interp_bilinear_grid(CCGKey *key, CCGElem *grid, float crn_x, float copy_v3_v3(data[3], CCG_grid_elem_co(key, grid, x0, y1)); } - interp_bilinear_quad_data(data, u, v, res); + interp_bilinear_quad_v3(data, u, v, res); } static void get_ccgdm_data(DerivedMesh *lodm, DerivedMesh *hidm, @@ -579,7 +557,7 @@ static void interp_bilinear_mface(DerivedMesh *dm, MFace *mface, const float u, dm->getVertCo(dm, mface->v4, data[3]); } - interp_bilinear_quad_data(data, u, v, res); + interp_bilinear_quad_v3(data, u, v, res); } /* mode = 0: interpolate normals, @@ -599,13 +577,13 @@ static void interp_barycentric_mface(DerivedMesh *dm, MFace *mface, const float dm->getVertCo(dm, mface->v3, data[2]); } - interp_barycentric_tri_data(data, u, v, res); + interp_barycentric_tri_v3(data, u, v, res); } static void *init_heights_data(MultiresBakeRender *bkr, Image *ima) { MHeightBakeData *height_data; - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); DerivedMesh *lodm = bkr->lores_dm; height_data = MEM_callocN(sizeof(MHeightBakeData), "MultiresBake heightData"); @@ -635,6 +613,8 @@ static void *init_heights_data(MultiresBakeRender *bkr, Image *ima) height_data->orig_index_mf_to_mpoly = lodm->getTessFaceDataArray(lodm, CD_ORIGINDEX); height_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX); + BKE_image_release_ibuf(ima, ibuf, NULL); + return (void *)height_data; } @@ -661,7 +641,7 @@ static void free_normal_data(void *bake_data) static void apply_heights_data(void *bake_data) { MHeightBakeData *height_data = (MHeightBakeData *)bake_data; - ImBuf *ibuf = BKE_image_get_ibuf(height_data->ima, NULL); + 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; @@ -693,6 +673,8 @@ static void apply_heights_data(void *bake_data) } ibuf->userflags = IB_RECT_INVALID | IB_DISPLAY_BUFFER_INVALID; + + BKE_image_release_ibuf(height_data->ima, ibuf, NULL); } static void free_heights_data(void *bake_data) @@ -713,13 +695,11 @@ static void free_heights_data(void *bake_data) * mesh to make texture smoother) let's call this point p0 and n. * - height wound be dot(n, p1-p0) */ static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data, - const int face_index, const int lvl, const float st[2], + 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; - Image *ima = mtface[face_index].tpage; - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); MHeightBakeData *height_data = (MHeightBakeData *)bake_data; float uv[2], *st0, *st1, *st2, *st3; int pixel = ibuf->x * y + x; @@ -790,13 +770,11 @@ static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, * - 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, - const int face_index, const int lvl, const float st[2], + 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; - Image *ima = mtface[face_index].tpage; - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); MNormalBakeData *normal_data = (MNormalBakeData *)bake_data; float uv[2], *st0, *st1, *st2, *st3; int pixel = ibuf->x * y + x; @@ -879,7 +857,7 @@ static void bake_images(MultiresBakeRender *bkr) for (link = bkr->image.first; link; link = link->next) { Image *ima = (Image *)link->data; - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + 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"); @@ -895,6 +873,8 @@ static void bake_images(MultiresBakeRender *bkr) } } + BKE_image_release_ibuf(ima, ibuf, NULL); + ima->id.flag |= LIB_DOIT; } } @@ -905,7 +885,7 @@ static void finish_images(MultiresBakeRender *bkr) for (link = bkr->image.first; link; link = link->next) { Image *ima = (Image *)link->data; - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (ibuf->x <= 0 || ibuf->y <= 0) continue; @@ -926,6 +906,8 @@ static void finish_images(MultiresBakeRender *bkr) MEM_freeN(ibuf->userdata); ibuf->userdata = NULL; } + + BKE_image_release_ibuf(ima, ibuf, NULL); } } @@ -1000,7 +982,7 @@ static int multiresbake_check(bContext *C, wmOperator *op) ok = 0; } else { - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (!ibuf) { BKE_report(op->reports, RPT_ERROR, "Baking should happen to image with image buffer"); @@ -1017,6 +999,8 @@ static int multiresbake_check(bContext *C, wmOperator *op) if (!ok) BKE_report(op->reports, RPT_ERROR, "Baking to unsupported image type"); } + + BKE_image_release_ibuf(ima, ibuf, NULL); } } } @@ -1087,10 +1071,12 @@ static void clear_images(MTFace *mtface, int totface) Image *ima = mtface[a].tpage; if ((ima->id.flag & LIB_DOIT) == 0) { - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); IMB_rectfill(ibuf, (ibuf->planes == R_IMF_PLANES_RGBA) ? vec_alpha : vec_solid); ima->id.flag |= LIB_DOIT; + + BKE_image_release_ibuf(ima, ibuf, NULL); } } @@ -1384,7 +1370,7 @@ static void finish_bake_internal(BakeRender *bkr) /* force OpenGL reload and mipmap recalc */ for (ima = G.main->image.first; ima; ima = ima->id.next) { - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); /* some of the images could have been changed during bake, * so recreate mipmaps regardless bake result status @@ -1409,6 +1395,8 @@ static void finish_bake_internal(BakeRender *bkr) ibuf->userdata = NULL; } } + + BKE_image_release_ibuf(ima, ibuf, NULL); } } diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index c0c2195592b..d39e34824b9 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -550,7 +550,8 @@ static int editmode_toggle_poll(bContext *C) if (ELEM(NULL, ob, ob->data) || ((ID *)ob->data)->lib) return 0; - if (ob->restrictflag & OB_RESTRICT_VIEW) + /* if hidden but in edit mode, we still display */ + if ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT)) return 0; return (ob->type == OB_MESH || ob->type == OB_ARMATURE || @@ -1380,7 +1381,7 @@ static void UNUSED_FUNCTION(image_aspect) (Scene * scene, View3D * v3d) if (ma->mtex[b] && ma->mtex[b]->tex) { tex = ma->mtex[b]->tex; if (tex->type == TEX_IMAGE && tex->ima) { - ImBuf *ibuf = BKE_image_get_ibuf(tex->ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, NULL, NULL); /* texturespace */ space = 1.0; @@ -1402,6 +1403,8 @@ static void UNUSED_FUNCTION(image_aspect) (Scene * scene, View3D * v3d) done = TRUE; DAG_id_tag_update(&ob->id, OB_RECALC_OB); + + BKE_image_release_ibuf(tex->ima, ibuf, NULL); } } if (done) break; diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 3d2c4f95624..7d3d6861418 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -555,7 +555,7 @@ static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, M Key *key = me->key; KeyBlock *kb; - if (!modifier_sameTopology(md) || mti->type == eModifierTypeType_NonGeometrical) { + if (!modifier_isSameTopology(md) || mti->type == eModifierTypeType_NonGeometrical) { BKE_report(reports, RPT_ERROR, "Only deforming modifiers can be applied to shapes"); return 0; } @@ -688,6 +688,13 @@ int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, Modi BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data"); return 0; } + else if ((ob->mode & OB_MODE_SCULPT) && + (find_multires_modifier_before(scene, md)) && + (modifier_isSameTopology(md) == FALSE)) + { + BKE_report(reports, RPT_ERROR, "Constructive modifier cannot be applied to multi-res data in sculpt mode"); + return 0; + } if (md != ob->modifiers.first) BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected"); @@ -1000,7 +1007,7 @@ static int modifier_apply_exec(bContext *C, wmOperator *op) Object *ob = ED_object_active_context(C); ModifierData *md = edit_modifier_property_get(op, ob, 0); int apply_as = RNA_enum_get(op->ptr, "apply_as"); - + if (!ob || !md || !ED_object_modifier_apply(op->reports, scene, ob, md, apply_as)) { return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 58c6959d6f0..e7f09b4055a 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1225,7 +1225,7 @@ static unsigned int move_to_layer_init(bContext *C, wmOperator *op) return lay; } -static int move_to_layer_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int move_to_layer_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { View3D *v3d = CTX_wm_view3d(C); if (v3d && v3d->localvd) { @@ -1233,7 +1233,7 @@ static int move_to_layer_invoke(bContext *C, wmOperator *op, wmEvent *event) } else { move_to_layer_init(C, op); - return WM_operator_props_popup(C, op, event); + return WM_operator_props_dialog_popup(C, op, 260, 30); } } diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 05524af34f0..e56ca20dfcc 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -845,25 +845,26 @@ void ED_vgroup_vert_remove(Object *ob, bDeformGroup *dg, int vertnum) static float get_vert_def_nr(Object *ob, const int def_nr, const int vertnum) { MDeformVert *dv = NULL; - BMVert *eve; - Mesh *me; /* get the deform vertices corresponding to the vertnum */ if (ob->type == OB_MESH) { - me = ob->data; + Mesh *me = ob->data; if (me->edit_btmesh) { - eve = BM_vert_at_index(me->edit_btmesh->bm, vertnum); + /* warning, this lookup is _not_ fast */ + BMVert *eve = BM_vert_at_index(me->edit_btmesh->bm, vertnum); if (!eve) { return 0.0f; } dv = CustomData_bmesh_get(&me->edit_btmesh->bm->vdata, eve->head.data, CD_MDEFORMVERT); } else { - if (vertnum >= me->totvert) { - return 0.0f; + if (me->dvert) { + if (vertnum >= me->totvert) { + return 0.0f; + } + dv = &me->dvert[vertnum]; } - dv = &me->dvert[vertnum]; } } else if (ob->type == OB_LATTICE) { diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 82e47312222..9121e4e55b5 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -404,6 +404,7 @@ static int key_test_depth(PEData *data, const float co[3], const int screen_co[2 { View3D *v3d= data->vc.v3d; GLfloat u[3]; + ViewDepths *vd = data->vc.rv3d->depths; float depth; /* nothing to do */ @@ -430,12 +431,15 @@ static int key_test_depth(PEData *data, const float co[3], const int screen_co[2 /* view3d_validate_backbuf(&data->vc); */ glReadPixels(screen_co[0], screen_co[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth); #else /* faster to use depths, these are calculated in PE_set_view3d_data */ - { - ViewDepths *vd = data->vc.rv3d->depths; - assert(vd && vd->depths); + + /* check if screen_co is within bounds because brush_cut uses out of screen coords */ + if(screen_co[0] >= 0 && screen_co[0] < vd->w && screen_co[1] >= 0 && screen_co[1] < vd->h) { + BLI_assert(vd && vd->depths); /* we know its not clipped */ depth = vd->depths[screen_co[1] * vd->w + screen_co[0]]; } + else + return 0; #endif if (u[2] - 0.00001f > depth) @@ -2439,7 +2443,8 @@ void PARTICLE_OT_remove_doubles(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; /* properties */ - RNA_def_float(ot->srna, "threshold", 0.0002f, 0.0f, FLT_MAX, "Threshold", "Threshold distance withing which particles are removed", 0.00001f, 0.1f); + RNA_def_float(ot->srna, "threshold", 0.0002f, 0.0f, FLT_MAX, + "Merge Distance", "Threshold distance withing which particles are removed", 0.00001f, 0.1f); } diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index 7cd153d9564..5304c64c2a9 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -446,7 +446,7 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid for (fobj=fobjects->first; fobj; fobj=fobj->next) { Object *ob = fobj->object; FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); - float active= (float)(fluidmd->fss->flag & OB_FLUIDSIM_ACTIVE); + float active= (float) ((fluidmd->fss->flag & OB_FLUIDSIM_ACTIVE) > 0 ? 1 : 0); float rot_d[3] = {0.f, 0.f, 0.f}, old_rot[3] = {0.f, 0.f, 0.f}; if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE)) @@ -467,6 +467,8 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid set_channel(fobj->Scale, timeAtFrame, ob->size, i, CHANNEL_VEC); set_channel(fobj->Active, timeAtFrame, &active, i, CHANNEL_FLOAT); set_channel(fobj->InitialVelocity, timeAtFrame, &fluidmd->fss->iniVelx, i, CHANNEL_VEC); + + // printf("Active: %f, Frame: %f\n", active, timeAtFrame); if (fluidmd->fss->type == OB_FLUIDSIM_CONTROL) { set_channel(fobj->AttractforceStrength, timeAtFrame, &fluidmd->fss->attractforceStrength, i, CHANNEL_FLOAT); @@ -962,8 +964,8 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain, shor /* ******** prepare output file paths ******** */ outStringsChanged = fluid_init_filepaths(fsDomain, targetDir, targetFile, debugStrBuffer); - channels->length = scene->r.efra; - channels->aniFrameTime = (double)(domainSettings->animEnd - domainSettings->animStart) / (double)noFrames; + channels->length = scene->r.efra; // DG TODO: why using endframe and not "noFrames" here? .. because "noFrames" is buggy too? (not using sfra) + channels->aniFrameTime = (double)((double)domainSettings->animEnd - (double)domainSettings->animStart) / (double)noFrames; /* ******** initialize and allocate animation channels ******** */ fluid_init_all_channels(C, fsDomain, domainSettings, channels, fobjects); diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 4b177629f72..7b67f63c646 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -375,7 +375,7 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec /* make jobs timer to send notifier */ *(rj->do_update) = TRUE; } - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); } static void render_startjob(void *rjv, short *stop, short *do_update, float *progress) diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 4dc08d2687a..4364ec712fd 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -287,7 +287,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) } } - BKE_image_release_ibuf(oglrender->ima, lock); + BKE_image_release_ibuf(oglrender->ima, ibuf, lock); } static int screen_opengl_render_init(bContext *C, wmOperator *op) @@ -612,7 +612,7 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op) IMB_freeImBuf(ibuf); } - BKE_image_release_ibuf(oglrender->ima, lock); + BKE_image_release_ibuf(oglrender->ima, ibuf, lock); /* movie stats prints have no line break */ printf("\n"); diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 2f9b6231858..73a250ec6a9 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -934,13 +934,15 @@ static void icon_preview_startjob(void *customdata, short *stop, short *do_updat /* elubie: this needs to be changed: here image is always loaded if not * already there. Very expensive for large images. Need to find a way to * only get existing ibuf */ - ibuf = BKE_image_get_ibuf(ima, &iuser); + ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); if (ibuf == NULL || ibuf->rect == NULL) return; icon_copy_rect(ibuf, sp->sizex, sp->sizey, sp->pr_rect); *do_update = TRUE; + + BKE_image_release_ibuf(ima, ibuf, NULL); } else if (idtype == ID_BR) { Brush *br = (Brush *)id; diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index 5155f1001ab..3f438c5948e 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -250,6 +250,24 @@ static void material_changed(Main *bmain, Material *ma) } } +static void lamp_changed(Main *bmain, Lamp *la) +{ + Object *ob; + Material *ma; + + /* icons */ + BKE_icon_changed(BKE_icon_getid(&la->id)); + + /* glsl */ + for (ob = bmain->object.first; ob; ob = ob->id.next) + if (ob->data == la && ob->gpulamp.first) + GPU_lamp_free(ob); + + for (ma = bmain->mat.first; ma; ma = ma->id.next) + if (ma->gpumaterial.first) + GPU_material_free(ma); +} + static void texture_changed(Main *bmain, Tex *tex) { Material *ma; @@ -282,16 +300,14 @@ static void texture_changed(Main *bmain, Tex *tex) /* find lamps */ for (la = bmain->lamp.first; la; la = la->id.next) { if (mtex_use_tex(la->mtex, MAX_MTEX, tex)) { - /* pass */ + lamp_changed(bmain, la); } else if (la->nodetree && nodes_use_tex(la->nodetree, tex)) { - /* pass */ + lamp_changed(bmain, la); } else { continue; } - - BKE_icon_changed(BKE_icon_getid(&la->id)); } /* find worlds */ @@ -320,24 +336,6 @@ static void texture_changed(Main *bmain, Tex *tex) } } -static void lamp_changed(Main *bmain, Lamp *la) -{ - Object *ob; - Material *ma; - - /* icons */ - BKE_icon_changed(BKE_icon_getid(&la->id)); - - /* glsl */ - for (ob = bmain->object.first; ob; ob = ob->id.next) - if (ob->data == la && ob->gpulamp.first) - GPU_lamp_free(ob); - - for (ma = bmain->mat.first; ma; ma = ma->id.next) - if (ma->gpumaterial.first) - GPU_material_free(ma); -} - static void world_changed(Main *bmain, World *wo) { Material *ma; diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 6a9c24d2913..67d4af916aa 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -293,29 +293,35 @@ int ED_operator_console_active(bContext *C) return ed_spacetype_test(C, SPACE_CONSOLE); } +static int ed_object_hidden(Object *ob) +{ + /* if hidden but in edit mode, we still display, can happen with animation */ + return ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT)); +} + int ED_operator_object_active(bContext *C) { Object *ob = ED_object_active_context(C); - return ((ob != NULL) && !(ob->restrictflag & OB_RESTRICT_VIEW)); + return ((ob != NULL) && !ed_object_hidden(ob)); } int ED_operator_object_active_editable(bContext *C) { Object *ob = ED_object_active_context(C); - return ((ob != NULL) && !(ob->id.lib) && !(ob->restrictflag & OB_RESTRICT_VIEW)); + return ((ob != NULL) && !(ob->id.lib) && !ed_object_hidden(ob)); } int ED_operator_object_active_editable_mesh(bContext *C) { Object *ob = ED_object_active_context(C); - return ((ob != NULL) && !(ob->id.lib) && !(ob->restrictflag & OB_RESTRICT_VIEW) && + return ((ob != NULL) && !(ob->id.lib) && !ed_object_hidden(ob) && (ob->type == OB_MESH) && !(((ID *)ob->data)->lib)); } int ED_operator_object_active_editable_font(bContext *C) { Object *ob = ED_object_active_context(C); - return ((ob != NULL) && !(ob->id.lib) && !(ob->restrictflag & OB_RESTRICT_VIEW) && + return ((ob != NULL) && !(ob->id.lib) && !ed_object_hidden(ob) && (ob->type == OB_FONT)); } diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index d980703dce5..ae5d6ed6152 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -35,6 +35,7 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLI_math.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -52,6 +53,8 @@ #include "BKE_writeavi.h" #include "GPU_compatibility.h" +#include "GPU_primitives.h" +#include "BIF_glutil.h" #include "RNA_access.h" #include "RNA_define.h" @@ -278,6 +281,7 @@ void SCREEN_OT_screenshot(wmOperatorType *ot) typedef struct ScreenshotJob { Main *bmain; Scene *scene; + wmWindowManager *wm; unsigned int *dumprect; int x, y, dumpsx, dumpsy; short *stop; @@ -395,6 +399,54 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float BKE_report(&sj->reports, RPT_INFO, "Screencast job stopped"); } +/* Helper callback for drawing the cursor itself */ +static void screencast_draw_cursor(bContext *UNUSED(C), int x, int y, void *UNUSED(p_ptr)) +{ + + glPushMatrix(); + + glTranslatef((float)x, (float)y, 0.0f); + + + glEnable(GL_LINE_SMOOTH); + glEnable(GL_BLEND); + + gpuCurrentColor4ub(0, 0, 0, 32); + gpuSingleArc(0, 0, 0, 2*M_PI, 20, 20, 40); + + gpuCurrentColor4ub(255, 255, 255, 128); + gpuSingleArc(0, 0, 0, 2*M_PI, 20, 20, 40); + + glDisable(GL_BLEND); + glDisable(GL_LINE_SMOOTH); + + glPopMatrix(); +} + +/* Turn brush cursor in 3D view on/off */ +static void screencast_cursor_toggle(wmWindowManager *wm, short enable) +{ + static void *cursor = NULL; + + if (cursor && !enable) { + /* clear cursor */ + WM_paint_cursor_end(wm, cursor); + cursor = NULL; + } + else if (enable) { + /* enable cursor */ + cursor = WM_paint_cursor_activate(wm, NULL, screencast_draw_cursor, NULL); + } +} + +static void screenshot_endjob(void *sjv) +{ + ScreenshotJob *sj = sjv; + + screencast_cursor_toggle(sj->wm, 0); +} + + static int screencast_exec(bContext *C, wmOperator *op) { bScreen *screen = CTX_wm_screen(C); @@ -418,15 +470,18 @@ static int screencast_exec(bContext *C, wmOperator *op) } sj->bmain = CTX_data_main(C); sj->scene = CTX_data_scene(C); - + sj->wm = CTX_wm_manager(C); + BKE_reports_init(&sj->reports, RPT_PRINT); /* setup job */ WM_jobs_customdata_set(wm_job, sj, screenshot_freejob); WM_jobs_timer(wm_job, 0.1, 0, NC_SCREEN | ND_SCREENCAST); - WM_jobs_callbacks(wm_job, screenshot_startjob, NULL, screenshot_updatejob, NULL); + WM_jobs_callbacks(wm_job, screenshot_startjob, NULL, screenshot_updatejob, screenshot_endjob); + + WM_jobs_start(sj->wm, wm_job); - WM_jobs_start(CTX_wm_manager(C), wm_job); + screencast_cursor_toggle(sj->wm, 1); WM_event_add_notifier(C, NC_SCREEN | ND_SCREENCAST, screen); diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 3cf4c947c26..80d49387df7 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -501,7 +501,7 @@ static void image_undo_restore(bContext *C, ListBase *lb) ima = BLI_findstring(&bmain->image, tile->idname, offsetof(ID, name)); } - ibuf = BKE_image_get_ibuf(ima, NULL); + ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (ima && ibuf && strcmp(tile->ibufname, ibuf->name) != 0) { /* current ImBuf filename was changed, probably current frame @@ -509,19 +509,27 @@ static void image_undo_restore(bContext *C, ListBase *lb) * full image user (which isn't so obvious, btw) try to find ImBuf with * matched file name in list of already loaded images */ + BKE_image_release_ibuf(ima, ibuf, NULL); + ibuf = BLI_findstring(&ima->ibufs, tile->ibufname, offsetof(ImBuf, name)); } - if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) + if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) { + BKE_image_release_ibuf(ima, ibuf, NULL); continue; + } - if (ima->gen_type != tile->gen_type || ima->source != tile->source) + if (ima->gen_type != tile->gen_type || ima->source != tile->source) { + BKE_image_release_ibuf(ima, ibuf, NULL); continue; + } use_float = ibuf->rect_float ? 1 : 0; - if (use_float != tile->use_float) + if (use_float != tile->use_float) { + BKE_image_release_ibuf(ima, ibuf, NULL); continue; + } undo_copy_tile(tile, tmpibuf, ibuf, 1); @@ -531,6 +539,8 @@ static void image_undo_restore(bContext *C, ListBase *lb) if (ibuf->mipmap[0]) ibuf->userflags |= IB_MIPMAP_INVALID; /* force mipmap recreatiom */ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + + BKE_image_release_ibuf(ima, ibuf, NULL); } IMB_freeImBuf(tmpibuf); @@ -1050,11 +1060,11 @@ static int pixel_bounds_uv( INIT_MINMAX2(min_uv, max_uv); - DO_MINMAX2(uv1, min_uv, max_uv); - DO_MINMAX2(uv2, min_uv, max_uv); - DO_MINMAX2(uv3, min_uv, max_uv); + minmax_v2v2_v2(min_uv, max_uv, uv1); + minmax_v2v2_v2(min_uv, max_uv, uv2); + minmax_v2v2_v2(min_uv, max_uv, uv3); if (is_quad) - DO_MINMAX2(uv4, min_uv, max_uv); + minmax_v2v2_v2(min_uv, max_uv, uv4); bounds_px->xmin = (int)(ibuf_x * min_uv[0]); bounds_px->ymin = (int)(ibuf_y * min_uv[1]); @@ -1080,7 +1090,7 @@ static int pixel_bounds_array(float (*uv)[2], rcti *bounds_px, const int ibuf_x, INIT_MINMAX2(min_uv, max_uv); while (tot--) { - DO_MINMAX2((*uv), min_uv, max_uv); + minmax_v2v2_v2(min_uv, max_uv, (*uv)); uv++; } @@ -1399,8 +1409,8 @@ static float project_paint_uvpixel_mask( Image *other_tpage = project_paint_face_image(ps, ps->dm_mtface_stencil, face_index); const MTFace *tf_other = ps->dm_mtface_stencil + face_index; - if (other_tpage && (ibuf_other = BKE_image_get_ibuf(other_tpage, NULL))) { - /* BKE_image_get_ibuf - TODO - this may be slow */ + if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) { + /* BKE_image_acquire_ibuf - TODO - this may be slow */ unsigned char rgba_ub[4]; float rgba_f[4]; @@ -1412,7 +1422,9 @@ static float project_paint_uvpixel_mask( else { /* from char to float */ mask = ((rgba_ub[0] + rgba_ub[1] + rgba_ub[2]) / (256 * 3.0f)) * (rgba_ub[3] / 256.0f); } - + + BKE_image_release_ibuf(other_tpage, ibuf_other, NULL); + if (!ps->do_layer_stencil_inv) /* matching the gimps layer mask black/white rules, white==full opacity */ mask = (1.0f - mask); @@ -1580,8 +1592,8 @@ static ProjPixel *project_paint_uvpixel_init( Image *other_tpage = project_paint_face_image(ps, ps->dm_mtface_clone, face_index); const MTFace *tf_other = ps->dm_mtface_clone + face_index; - if (other_tpage && (ibuf_other = BKE_image_get_ibuf(other_tpage, NULL))) { - /* BKE_image_get_ibuf - TODO - this may be slow */ + if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) { + /* BKE_image_acquire_ibuf - TODO - this may be slow */ if (ibuf->rect_float) { if (ibuf_other->rect_float) { /* from float to float */ @@ -1603,6 +1615,8 @@ static ProjPixel *project_paint_uvpixel_init( project_face_pixel(tf_other, ibuf_other, w, side, ((ProjPixelClone *)projPixel)->clonepx.ch, NULL); } } + + BKE_image_release_ibuf(other_tpage, ibuf_other, NULL); } else { if (ibuf->rect_float) { @@ -2927,7 +2941,7 @@ static void project_paint_delayed_face_init(ProjPaintState *ps, const MFace *mf, fidx = mf->v4 ? 3 : 2; do { vCoSS = ps->screenCoords[*(&mf->v1 + fidx)]; - DO_MINMAX2(vCoSS, min, max); + minmax_v2v2_v2(min, max, vCoSS); } while (fidx--); project_paint_bucket_bounds(ps, min, max, bucketMin, bucketMax); @@ -3192,7 +3206,7 @@ static void project_paint_begin(ProjPaintState *ps) /* screen space, not clamped */ projScreenCo[0] = (float)(ps->winx / 2.0f) + (ps->winx / 2.0f) * projScreenCo[0]; projScreenCo[1] = (float)(ps->winy / 2.0f) + (ps->winy / 2.0f) * projScreenCo[1]; - DO_MINMAX2(projScreenCo, ps->screenMin, ps->screenMax); + minmax_v2v2_v2(ps->screenMin, ps->screenMax, projScreenCo); } } else { @@ -3207,7 +3221,7 @@ static void project_paint_begin(ProjPaintState *ps) projScreenCo[0] = (float)(ps->winx / 2.0f) + (ps->winx / 2.0f) * projScreenCo[0] / projScreenCo[3]; projScreenCo[1] = (float)(ps->winy / 2.0f) + (ps->winy / 2.0f) * projScreenCo[1] / projScreenCo[3]; projScreenCo[2] = projScreenCo[2] / projScreenCo[3]; /* Use the depth for bucket point occlusion */ - DO_MINMAX2(projScreenCo, ps->screenMin, ps->screenMax); + minmax_v2v2_v2(ps->screenMin, ps->screenMax, projScreenCo); } else { /* TODO - deal with cases where 1 side of a face goes behind the view ? @@ -3409,7 +3423,7 @@ static void project_paint_begin(ProjPaintState *ps) image_index = BLI_linklist_index(image_LinkList, tpage); - if (image_index == -1 && BKE_image_get_ibuf(tpage, NULL)) { /* MemArena dosnt have an append func */ + if (image_index == -1 && BKE_image_has_ibuf(tpage, NULL)) { /* MemArena dosnt have an append func */ BLI_linklist_append(&image_LinkList, tpage); image_index = ps->image_tot; ps->image_tot++; @@ -3432,7 +3446,7 @@ static void project_paint_begin(ProjPaintState *ps) for (node = image_LinkList, i = 0; node; node = node->next, i++, projIma++) { projIma->ima = node->link; projIma->touch = 0; - projIma->ibuf = BKE_image_get_ibuf(projIma->ima, NULL); + projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, NULL, NULL); projIma->partRedrawRect = BLI_memarena_alloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED); memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED); } @@ -3459,6 +3473,7 @@ static void project_paint_begin_clone(ProjPaintState *ps, int mouse[2]) static void project_paint_end(ProjPaintState *ps) { int a; + ProjPaintImage *projIma; /* build undo data from original pixel colors */ if (U.uiflag & USER_GLOBALUNDO) { @@ -3546,7 +3561,14 @@ static void project_paint_end(ProjPaintState *ps) if (tmpibuf_float) IMB_freeImBuf(tmpibuf_float); } /* done calculating undo data */ - + + /* dereference used image buffers */ + for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) { + BKE_image_release_ibuf(projIma->ima, projIma->ibuf, NULL); + } + + BKE_image_release_ibuf(ps->reproject_image, ps->reproject_ibuf, NULL); + MEM_freeN(ps->screenCoords); MEM_freeN(ps->bucketRect); MEM_freeN(ps->bucketFaces); @@ -4673,7 +4695,7 @@ static int texpaint_break_stroke(float *prevuv, float *fwuv, float *bkuv, float static int imapaint_canvas_set(ImagePaintState *s, Image *ima) { - ImBuf *ibuf = BKE_image_get_ibuf(ima, s->sima ? &s->sima->iuser : NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL); /* verify that we can paint and set canvas */ if (ima == NULL) { @@ -4696,10 +4718,12 @@ static int imapaint_canvas_set(ImagePaintState *s, Image *ima) /* set clone canvas */ if (s->tool == PAINT_TOOL_CLONE) { ima = s->brush->clone.image; - ibuf = BKE_image_get_ibuf(ima, s->sima ? &s->sima->iuser : NULL); + ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL); - if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) + if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) { + BKE_image_release_ibuf(ima, ibuf, NULL); return 0; + } s->clonecanvas = ibuf; @@ -4714,13 +4738,15 @@ static int imapaint_canvas_set(ImagePaintState *s, Image *ima) return 1; } -static void imapaint_canvas_free(ImagePaintState *UNUSED(s)) +static void imapaint_canvas_free(ImagePaintState *s) { + BKE_image_release_ibuf(s->image, s->canvas, NULL); + BKE_image_release_ibuf(s->brush->clone.image, s->clonecanvas, NULL); } static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter, Image *image, short texpaint, float *uv, double time, int update, float pressure) { - ImBuf *ibuf = BKE_image_get_ibuf(image, s->sima ? &s->sima->iuser : NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(image, s->sima ? &s->sima->iuser : NULL, NULL); float pos[2]; int is_data; @@ -4740,9 +4766,13 @@ static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter, if (BKE_brush_painter_paint(painter, imapaint_paint_op, pos, time, pressure, s, is_data == FALSE)) { if (update) imapaint_image_update(s->scene, s->sima, image, ibuf, texpaint); + BKE_image_release_ibuf(image, ibuf, NULL); return 1; } - else return 0; + else { + BKE_image_release_ibuf(image, ibuf, NULL); + return 0; + } } static int imapaint_paint_stroke(ViewContext *vc, ImagePaintState *s, BrushPainter *painter, short texpaint, const int prevmval[2], const int mval[2], double time, float pressure) @@ -4760,7 +4790,7 @@ static int imapaint_paint_stroke(ViewContext *vc, ImagePaintState *s, BrushPaint ImBuf *ibuf; newimage = imapaint_face_image(s, newfaceindex); - ibuf = BKE_image_get_ibuf(newimage, s->sima ? &s->sima->iuser : NULL); + ibuf = BKE_image_acquire_ibuf(newimage, s->sima ? &s->sima->iuser : NULL, NULL); if (ibuf && ibuf->rect) imapaint_pick_uv(s->scene, s->ob, newfaceindex, mval, newuv); @@ -4768,6 +4798,8 @@ static int imapaint_paint_stroke(ViewContext *vc, ImagePaintState *s, BrushPaint newimage = NULL; newuv[0] = newuv[1] = 0.0f; } + + BKE_image_release_ibuf(newimage, ibuf, NULL); } else newuv[0] = newuv[1] = 0.0f; @@ -5891,7 +5923,7 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op) } ps.reproject_image = image; - ps.reproject_ibuf = BKE_image_get_ibuf(image, NULL); + ps.reproject_ibuf = BKE_image_acquire_ibuf(image, NULL, NULL); if (ps.reproject_ibuf == NULL || ps.reproject_ibuf->rect == NULL) { BKE_report(op->reports, RPT_ERROR, "Image data could not be found"); diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c index 0e82d8651f3..abfefba02b9 100644 --- a/source/blender/editors/space_buttons/buttons_texture.c +++ b/source/blender/editors/space_buttons/buttons_texture.c @@ -248,7 +248,7 @@ static void buttons_texture_users_from_context(ListBase *users, const bContext * void buttons_texture_context_compute(const bContext *C, SpaceButs *sbuts) { - /* gatheravailable texture users in context. runs on every draw of + /* gather available texture users in context. runs on every draw of * properties editor, before the buttons are created. */ ButsContextTexture *ct = sbuts->texuser; Scene *scene = CTX_data_scene(C); diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index 157dc3282b9..a7ba2b7dbdb 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -1322,7 +1322,7 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip, BKE_tracking_undistort_v2(tracking, pos, tpos); - DO_MINMAX2(tpos, min, max); + minmax_v2v2_v2(min, max, tpos); } copy_v2_v2(pos, min); @@ -1535,7 +1535,7 @@ void clip_draw_grease_pencil(bContext *C, int onlyv2d) if (onlyv2d) { /* if manual calibration is used then grease pencil data is already - * drawed in draw_distortion */ + * drawn in draw_distortion */ if ((sc->flag & SC_MANUAL_CALIBRATION) == 0 || sc->mode != SC_MODE_DISTORTION) { gpuPushMatrix(); gpuMultMatrix(sc->unistabmat); diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 20ccdf74890..ac6bb785e72 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -349,7 +349,7 @@ static int selected_boundbox(SpaceClip *sc, float min[2], float max[2]) mul_v3_m4v3(pos, sc->stabmat, pos); - DO_MINMAX2(pos, min, max); + minmax_v2v2_v2(min, max, pos); ok = TRUE; } diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 1620ea9cb1f..5f0e4db9dd7 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -1030,17 +1030,14 @@ static void clip_refresh(const bContext *C, ScrArea *sa) static void movieclip_main_area_set_view2d(const bContext *C, ARegion *ar) { SpaceClip *sc = CTX_wm_space_clip(C); - MovieClip *clip = ED_space_clip_get_clip(sc); - float x1, y1, w, h; + float x1, y1, w, h, aspx, aspy; int width, height, winx, winy; ED_space_clip_get_size(sc, &width, &height); + ED_space_clip_get_aspect(sc, &aspx, &aspy); - w = width; - h = height; - - if (clip) - h *= clip->aspy / clip->aspx / clip->tracking.camera.pixel_aspect; + w = width * aspx; + h = height * aspy; winx = BLI_rcti_size_x(&ar->winrct) + 1; winy = BLI_rcti_size_y(&ar->winrct) + 1; diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c index d3ae5373a18..bb46135545c 100644 --- a/source/blender/editors/space_console/console_ops.c +++ b/source/blender/editors/space_console/console_ops.c @@ -157,10 +157,9 @@ static ConsoleLine *console_lb_add__internal(ListBase *lb, ConsoleLine *from) ConsoleLine *ci = MEM_callocN(sizeof(ConsoleLine), "ConsoleLine Add"); if (from) { - ci->line = BLI_strdup(from->line); - ci->len = strlen(ci->line); - ci->len_alloc = ci->len; - + BLI_assert(strlen(from->line) == from->len); + ci->line = BLI_strdupn(from->line, from->len); + ci->len = ci->len_alloc = from->len; ci->cursor = from->cursor; ci->type = from->type; } @@ -174,10 +173,8 @@ static ConsoleLine *console_lb_add__internal(ListBase *lb, ConsoleLine *from) return ci; } -static ConsoleLine *console_history_add(const bContext *C, ConsoleLine *from) +static ConsoleLine *console_history_add(SpaceConsole *sc, ConsoleLine *from) { - SpaceConsole *sc = CTX_wm_space_console(C); - return console_lb_add__internal(&sc->history, from); } @@ -217,7 +214,7 @@ ConsoleLine *console_history_verify(const bContext *C) SpaceConsole *sc = CTX_wm_space_console(C); ConsoleLine *ci = sc->history.last; if (ci == NULL) - ci = console_history_add(C, NULL); + ci = console_history_add(sc, NULL); return ci; } @@ -623,8 +620,9 @@ static int console_clear_line_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } - console_history_add(C, ci); - console_history_add(C, NULL); + console_history_add(sc, ci); + console_history_add(sc, NULL); + console_select_offset(sc, -ci->len); console_textview_update_rect(sc, ar); @@ -727,7 +725,7 @@ static int console_history_cycle_exec(bContext *C, wmOperator *op) while ((cl = console_history_find(sc, ci->line, ci))) console_history_free(sc, cl); - console_history_add(C, (ConsoleLine *)sc->history.last); + console_history_add(sc, (ConsoleLine *)sc->history.last); } ci = sc->history.last; diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index 8bb57a32090..483348db18e 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -714,7 +714,17 @@ static void graph_panel_drivers(const bContext *C, Panel *pa) row = uiLayoutRow(box, TRUE); uiItemL(row, IFACE_("Value:"), ICON_NONE); - BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", dvar->curval); + if ((dvar->type == DVAR_TYPE_ROT_DIFF) || + (dvar->type == DVAR_TYPE_TRANSFORM_CHAN && + dvar->targets[0].transChan >= DTAR_TRANSCHAN_ROTX && + dvar->targets[0].transChan < DTAR_TRANSCHAN_SCALEX)) + { + BLI_snprintf(valBuf, sizeof(valBuf), "%.3f (%4.1f°)", dvar->curval, RAD2DEGF(dvar->curval)); + } + else { + BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", dvar->curval); + } + uiItemL(row, valBuf, ICON_NONE); } } diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index ae7a718ab5b..0a3db59096a 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -593,7 +593,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char if (ima->source == IMA_SRC_VIEWER) { ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock); image_info(scene, iuser, ima, ibuf, str); - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); uiItemL(layout, ima->id.name + 2, ICON_NONE); uiItemL(layout, str, ICON_NONE); @@ -663,7 +663,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char if (compact == 0) { ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock); image_info(scene, iuser, ima, ibuf, str); - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); uiItemL(layout, str, ICON_NONE); } } @@ -722,7 +722,6 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char split = uiLayoutSplit(layout, 0.0f, FALSE); col = uiLayoutColumn(split, TRUE); - uiLayoutSetEnabled(col, 0); uiItemR(col, &imaptr, "generated_width", 0, "X", ICON_NONE); uiItemR(col, &imaptr, "generated_height", 0, "Y", ICON_NONE); diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index f418deeb1c9..9f67da768c5 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -661,7 +661,7 @@ static unsigned char *get_alpha_clone_image(const bContext *C, Scene *scene, int if (!brush || !brush->clone.image) return NULL; - ibuf = BKE_image_get_ibuf(brush->clone.image, NULL); + ibuf = BKE_image_acquire_ibuf(brush->clone.image, NULL, NULL); if (!ibuf) return NULL; @@ -669,6 +669,7 @@ static unsigned char *get_alpha_clone_image(const bContext *C, Scene *scene, int display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); if (!display_buffer) { + BKE_image_release_ibuf(brush->clone.image, ibuf, NULL); IMB_display_buffer_release(cache_handle); return NULL; @@ -678,8 +679,10 @@ static unsigned char *get_alpha_clone_image(const bContext *C, Scene *scene, int IMB_display_buffer_release(cache_handle); - if (!rect) + if (!rect) { + BKE_image_release_ibuf(brush->clone.image, ibuf, NULL); return NULL; + } *width = ibuf->x; *height = ibuf->y; @@ -693,6 +696,8 @@ static unsigned char *get_alpha_clone_image(const bContext *C, Scene *scene, int cp += 4; } + BKE_image_release_ibuf(brush->clone.image, ibuf, NULL); + return rect; } @@ -807,7 +812,7 @@ void draw_image_main(const bContext *C, ARegion *ar) } #endif - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); if (show_viewer) { BLI_unlock_thread(LOCK_DRAW_IMAGE); diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c index 4ca2f8888f8..c4e2230e7a7 100644 --- a/source/blender/editors/space_image/image_edit.c +++ b/source/blender/editors/space_image/image_edit.c @@ -117,8 +117,12 @@ ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **lock_r) #endif ibuf = BKE_image_acquire_ibuf(sima->image, &sima->iuser, lock_r); - if (ibuf && (ibuf->rect || ibuf->rect_float)) - return ibuf; + if (ibuf) { + if (ibuf->rect || ibuf->rect_float) + return ibuf; + + BKE_image_release_ibuf(sima->image, ibuf, NULL); + } } else *lock_r = NULL; @@ -126,10 +130,10 @@ ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **lock_r) return NULL; } -void ED_space_image_release_buffer(SpaceImage *sima, void *lock) +void ED_space_image_release_buffer(SpaceImage *sima, ImBuf *ibuf, void *lock) { if (sima && sima->image) - BKE_image_release_ibuf(sima->image, lock); + BKE_image_release_ibuf(sima->image, ibuf, lock); } int ED_space_image_has_buffer(SpaceImage *sima) @@ -140,7 +144,7 @@ int ED_space_image_has_buffer(SpaceImage *sima) ibuf = ED_space_image_acquire_buffer(sima, &lock); has_buffer = (ibuf != NULL); - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); return has_buffer; } @@ -175,7 +179,7 @@ void ED_space_image_get_size(SpaceImage *sima, int *width, int *height) *height = IMG_SIZE_FALLBACK; } - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); } void ED_space_image_get_size_fl(SpaceImage *sima, float size[2]) diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index ce3c6e1fd26..d4f24babff6 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -167,7 +167,7 @@ static int space_image_file_exists_poll(bContext *C) ret = TRUE; } } - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); return ret; } @@ -1188,7 +1188,7 @@ static int save_image_options_init(SaveImageOptions *simopts, SpaceImage *sima, BKE_color_managed_view_settings_copy(&simopts->im_format.view_settings, &scene->view_settings); } - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); return (ibuf != NULL); } @@ -1328,7 +1328,7 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI IMB_freeImBuf(colormanaged_ibuf); } - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); } static void image_save_as_free(wmOperator *op) @@ -1743,17 +1743,14 @@ void IMAGE_OT_new(wmOperatorType *ot) static int image_invert_poll(bContext *C) { Image *ima = CTX_data_edit_image(C); - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); - - if (ibuf != NULL) - return 1; - return 0; + + return BKE_image_has_ibuf(ima, NULL); } static int image_invert_exec(bContext *C, wmOperator *op) { Image *ima = CTX_data_edit_image(C); - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); /* flags indicate if this channel should be inverted */ const short r = RNA_boolean_get(op->ptr, "invert_r"); @@ -1792,6 +1789,7 @@ static int image_invert_exec(bContext *C, wmOperator *op) } } else { + BKE_image_release_ibuf(ima, ibuf, NULL); return OPERATOR_CANCELLED; } @@ -1800,6 +1798,9 @@ static int image_invert_exec(bContext *C, wmOperator *op) ibuf->userflags |= IB_MIPMAP_INVALID; WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima); + + BKE_image_release_ibuf(ima, ibuf, NULL); + return OPERATOR_FINISHED; } @@ -1848,7 +1849,7 @@ static int image_pack_exec(bContext *C, wmOperator *op) { struct Main *bmain = CTX_data_main(C); Image *ima = CTX_data_edit_image(C); - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); int as_png = RNA_boolean_get(op->ptr, "as_png"); if (!image_pack_test(C, op)) @@ -1865,30 +1866,38 @@ static int image_pack_exec(bContext *C, wmOperator *op) ima->packedfile = newPackedFile(op->reports, ima->name, ID_BLEND_PATH(bmain, &ima->id)); WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima); - + + BKE_image_release_ibuf(ima, ibuf, NULL); + return OPERATOR_FINISHED; } static int image_pack_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { Image *ima = CTX_data_edit_image(C); - ImBuf *ibuf = BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf; uiPopupMenu *pup; uiLayout *layout; int as_png = RNA_boolean_get(op->ptr, "as_png"); if (!image_pack_test(C, op)) return OPERATOR_CANCELLED; - + + ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); + if (!as_png && (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))) { pup = uiPupMenuBegin(C, "OK", ICON_QUESTION); layout = uiPupMenuLayout(pup); uiItemBooleanO(layout, "Can't pack edited image from disk. Pack as internal PNG?", ICON_NONE, op->idname, "as_png", 1); uiPupMenuEnd(C, pup); + BKE_image_release_ibuf(ima, ibuf, NULL); + return OPERATOR_CANCELLED; } + BKE_image_release_ibuf(ima, ibuf, NULL); + return image_pack_exec(C, op); } @@ -2032,7 +2041,7 @@ int ED_space_image_color_sample(SpaceImage *sima, ARegion *ar, int mval[2], floa int ret = FALSE; if (ibuf == NULL) { - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); return FALSE; } @@ -2058,7 +2067,7 @@ int ED_space_image_color_sample(SpaceImage *sima, ARegion *ar, int mval[2], floa } } - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); return ret; } @@ -2074,7 +2083,7 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event) CurveMapping *curve_mapping = scene->view_settings.curve_mapping; if (ibuf == NULL) { - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); info->draw = 0; return; } @@ -2175,7 +2184,7 @@ static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->draw = 0; } - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); ED_area_tag_redraw(CTX_wm_area(C)); } @@ -2266,12 +2275,12 @@ static int image_sample_line_exec(bContext *C, wmOperator *op) float x1f, y1f, x2f, y2f; if (ibuf == NULL) { - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); return OPERATOR_CANCELLED; } /* hmmmm */ if (ibuf->channels < 3) { - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); return OPERATOR_CANCELLED; } @@ -2288,7 +2297,7 @@ static int image_sample_line_exec(bContext *C, wmOperator *op) /* reset y zoom */ hist->ymax = 1.0f; - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); ED_area_tag_redraw(CTX_wm_area(C)); @@ -2383,11 +2392,13 @@ static int image_record_composite_apply(bContext *C, wmOperator *op) ED_area_tag_redraw(CTX_wm_area(C)); - ibuf = BKE_image_get_ibuf(sima->image, &sima->iuser); + ibuf = BKE_image_acquire_ibuf(sima->image, &sima->iuser, NULL); /* save memory in flipbooks */ if (ibuf) imb_freerectfloatImBuf(ibuf); - + + BKE_image_release_ibuf(sima->image, ibuf, NULL); + scene->r.cfra++; return (scene->r.cfra <= rcd->efra); diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index f0b3e70f359..7eff00d3882 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -779,7 +779,7 @@ static void image_scope_area_draw(const bContext *C, ARegion *ar) } scopes_update(&sima->scopes, ibuf, &scene->view_settings, &scene->display_settings); } - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); ED_region_panels(C, ar, 1, NULL, -1); } diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c index 131908bc9db..48b5eaf7b44 100644 --- a/source/blender/editors/space_info/info_ops.c +++ b/source/blender/editors/space_info/info_ops.c @@ -87,10 +87,14 @@ static int pack_all_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) // first check for dirty images for (ima = bmain->image.first; ima; ima = ima->id.next) { if (ima->ibufs.first) { /* XXX FIX */ - ibuf = BKE_image_get_ibuf(ima, NULL); + ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); - if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) + if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) { + BKE_image_release_ibuf(ima, ibuf, NULL); break; + } + + BKE_image_release_ibuf(ima, ibuf, NULL); } } diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index e5cc6bf4bc7..bd6639c6575 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -400,29 +400,15 @@ static void node_buts_curvecol(uiLayout *layout, bContext *UNUSED(C), PointerRNA uiTemplateCurveMapping(layout, ptr, "mapping", 'c', 0, 0); } -static void node_normal_cb(bContext *C, void *ntree_v, void *node_v) -{ - Main *bmain = CTX_data_main(C); - - ED_node_generic_update(bmain, ntree_v, node_v); - WM_event_add_notifier(C, NC_NODE|NA_EDITED, ntree_v); -} - static void node_buts_normal(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiBlock *block= uiLayoutAbsoluteBlock(layout); - bNodeTree *ntree= ptr->id.data; - bNode *node= ptr->data; - rctf *butr= &node->butr; + bNodeTree *ntree = (bNodeTree*)ptr->id.data; + bNode *node = (bNode*)ptr->data; bNodeSocket *sock= node->outputs.first; /* first socket stores normal */ - float *nor= ((bNodeSocketValueVector*)sock->default_value)->value; - uiBut *bt; - - bt= uiDefButF(block, BUT_NORMAL, B_NODE_EXEC, "", - (int)butr->xmin, (int)butr->xmin, - (short)BLI_rctf_size_x(butr), (short)BLI_rctf_size_x(butr), - nor, 0.0f, 1.0f, 0, 0, ""); - uiButSetFunc(bt, node_normal_cb, ntree, node); + PointerRNA sockptr; + + RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &sockptr); + uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE); } #if 0 /* not used in 2.5x yet */ static void node_browse_tex_cb(bContext *C, void *ntree_v, void *node_v) @@ -1486,9 +1472,10 @@ static void node_shader_buts_script_details(uiLayout *layout, bContext *C, Point node_shader_buts_script(layout, C, ptr); - /* not implemented yet +#if 0 /* not implemented yet */ if (RNA_enum_get(ptr, "mode") == NODE_SCRIPT_EXTERNAL) - uiItemR(layout, ptr, "use_auto_update", 0, NULL, ICON_NONE);*/ + uiItemR(layout, ptr, "use_auto_update", 0, NULL, ICON_NONE); +#endif } /* only once called */ @@ -1888,6 +1875,14 @@ static void node_composit_buts_double_edge_mask(uiLayout *layout, bContext *UNUS uiItemR(col, ptr, "edge_mode", 0, "", ICON_NONE); } +static void node_composit_buts_map_range(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiLayout *col; + + col = uiLayoutColumn(layout, TRUE); + uiItemR(col, ptr, "use_clamp", 0, NULL, ICON_NONE); +} + static void node_composit_buts_map_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiLayout *sub, *col; @@ -2826,6 +2821,9 @@ static void node_composit_set_butfunc(bNodeType *ntype) case CMP_NODE_MAP_VALUE: ntype->uifunc= node_composit_buts_map_value; break; + case CMP_NODE_MAP_RANGE: + ntype->uifunc = node_composit_buts_map_range; + break; case CMP_NODE_TIME: ntype->uifunc= node_buts_time; break; @@ -3303,7 +3301,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode) gpuPopMatrix(); } - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); } } @@ -3316,7 +3314,7 @@ static void draw_nodespace_back_tex(ScrArea *sa, SpaceNode *snode) if (snode->flag & SNODE_BACKDRAW) { Image *ima= BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); - ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (ibuf) { int x, y; float zoom = 1.0; @@ -3352,6 +3350,8 @@ static void draw_nodespace_back_tex(ScrArea *sa, SpaceNode *snode) gpuPopMatrix(); gpuMatrixMode(GL_MODELVIEW); gpuPopMatrix(); + + BKE_image_release_ibuf(ima, ibuf, NULL); } } } diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c index 5f8b5db7766..4dd9c89375d 100644 --- a/source/blender/editors/space_node/node_group.c +++ b/source/blender/editors/space_node/node_group.c @@ -29,13 +29,18 @@ * \ingroup spnode */ +#include <stdlib.h> + #include "MEM_guardedalloc.h" #include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_anim_types.h" -#include "BLI_blenlib.h" +#include "BLI_listbase.h" +#include "BLI_string.h" +#include "BLI_rect.h" +#include "BLI_math.h" #include "BKE_action.h" #include "BKE_animsys.h" @@ -865,7 +870,7 @@ static void node_get_selected_minmax(bNodeTree *ntree, bNode *gnode, float *min, if (node == gnode) continue; if (node->flag & NODE_SELECT) { - DO_MINMAX2((&node->locx), min, max); + minmax_v2v2_v2(min, max, &node->locx); } } } diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c index ccf5c4b540f..f386657c460 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.c @@ -241,7 +241,7 @@ static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event) ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); if (ibuf == NULL) { - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); return OPERATOR_CANCELLED; } @@ -255,7 +255,7 @@ static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event) nvm->ymin = -(ar->winy / 2) - (ibuf->y * (0.5f * snode->zoom)) + pad; nvm->ymax = (ar->winy / 2) + (ibuf->y * (0.5f * snode->zoom)) - pad; - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); /* add modal handler */ WM_event_add_modal_handler(C, op); @@ -330,6 +330,12 @@ typedef struct ImageSampleInfo { unsigned char col[4]; float colf[4]; + + int z; + float zf; + + int *zp; + float *zfp; int draw; int color_manage; @@ -343,8 +349,7 @@ static void sample_draw(const bContext *C, ARegion *ar, void *arg_info) if (info->draw) { ED_image_draw_info(scene, ar, info->color_manage, FALSE, info->channels, info->x, info->y, info->col, info->colf, - NULL, NULL /* zbuf - unused for nodes */ - ); + info->zp, info->zfp); } } @@ -398,7 +403,7 @@ int ED_space_node_color_sample(SpaceNode *snode, ARegion *ar, int mval[2], float } } - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); return ret; } @@ -443,6 +448,9 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->draw = 1; info->channels = ibuf->channels; + info->zp = NULL; + info->zfp = NULL; + if (ibuf->rect) { cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x); @@ -468,6 +476,15 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event) info->color_manage = TRUE; } + + if (ibuf->zbuf) { + info->z = ibuf->zbuf[y * ibuf->x + x]; + info->zp = &info->z; + } + if (ibuf->zbuf_float) { + info->zf = ibuf->zbuf_float[y * ibuf->x + x]; + info->zfp = &info->zf; + } ED_node_sample_set(info->colf); } @@ -476,7 +493,7 @@ static void sample_apply(bContext *C, wmOperator *op, wmEvent *event) ED_node_sample_set(NULL); } - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); ED_area_tag_redraw(CTX_wm_area(C)); } diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 324d9e3e6fe..6cda8660c5b 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -1046,6 +1046,8 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto UI_icon_draw(x, y, ICON_MOD_WARP); break; case eModifierType_Skin: UI_icon_draw(x, y, ICON_MOD_SKIN); break; + case eModifierType_Triangulate: + UI_icon_draw(x, y, ICON_MOD_TRIANGULATE); break; /* Default */ case eModifierType_None: diff --git a/source/blender/editors/space_sequencer/SConscript b/source/blender/editors/space_sequencer/SConscript index 0b429ae750b..bc72786fc5f 100644 --- a/source/blender/editors/space_sequencer/SConscript +++ b/source/blender/editors/space_sequencer/SConscript @@ -3,7 +3,7 @@ Import ('env') sources = env.Glob('*.c') -incs = '../include ../../blenlib ../../blenkernel ../../blenfont ../../makesdna ../../imbuf' +incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' incs += ' ../../makesrna ../../blenloader ../../blenfont' incs += ' #/intern/audaspace/intern' diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index dd57566ff91..7f0ae1d7680 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -837,6 +837,7 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int int rectx, recty; float render_size = 0.0; float proxy_size = 100.0; + short is_break = G.is_break; render_size = sseq->render_size; if (render_size == 0) { @@ -855,6 +856,11 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int context = BKE_sequencer_new_render_data(bmain, scene, rectx, recty, proxy_size); + /* sequencer could start rendering, in this case we need to be sure it wouldn't be canceled + * by Esc pressed somewhere in the past + */ + G.is_break = FALSE; + if (special_seq_update) ibuf = BKE_sequencer_give_ibuf_direct(context, cfra + frame_ofs, special_seq_update); else if (!U.prefetchframes) // XXX || (G.f & G_PLAYANIM) == 0) { @@ -862,6 +868,9 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int else ibuf = BKE_sequencer_give_ibuf_threaded(context, cfra + frame_ofs, sseq->chanshown); + /* restore state so real rendering would be canceled (if needed) */ + G.is_break = is_break; + return ibuf; } diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 7270516aa51..00d4a943626 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -1686,7 +1686,7 @@ static int sequencer_delete_invoke(bContext *C, wmOperator *op, wmEvent *event) if (ar->regiontype == RGN_TYPE_WINDOW) { /* bounding box of 30 pixels is used for markers shortcuts, - * prevent conflict with markers shortcurts here + * prevent conflict with markers shortcuts here */ if (event->mval[1] <= 30) return OPERATOR_PASS_THROUGH; diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index f546c90c82c..1f806b78dc8 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -196,10 +196,6 @@ static void text_operatortypes(void) WM_operatortype_append(TEXT_OT_unindent); WM_operatortype_append(TEXT_OT_indent); - WM_operatortype_append(TEXT_OT_markers_clear); - WM_operatortype_append(TEXT_OT_next_marker); - WM_operatortype_append(TEXT_OT_previous_marker); - WM_operatortype_append(TEXT_OT_select_line); WM_operatortype_append(TEXT_OT_select_all); WM_operatortype_append(TEXT_OT_select_word); @@ -227,7 +223,6 @@ static void text_operatortypes(void) WM_operatortype_append(TEXT_OT_find_set_selected); WM_operatortype_append(TEXT_OT_replace); WM_operatortype_append(TEXT_OT_replace_set_selected); - WM_operatortype_append(TEXT_OT_mark_all); WM_operatortype_append(TEXT_OT_to_3d_object); diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c index d352e9f7b41..1818c4a5b31 100644 --- a/source/blender/editors/space_text/text_draw.c +++ b/source/blender/editors/space_text/text_draw.c @@ -764,7 +764,7 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w buffer[len] = '\0'; text_font_draw(st, ox, y, buffer); - y -= st->lheight; + y -= st->lheight + TXT_LINE_SPACING; x = basex; lines++; start = end; mstart = mend; @@ -1172,40 +1172,6 @@ int text_get_total_lines(SpaceText *st, ARegion *ar) return drawcache->total_lines; } -/* Move pointer to first visible line (top) */ -static TextLine *first_visible_line(SpaceText *st, ARegion *ar, int *wrap_top) -{ - Text *text = st->text; - TextLine *pline = text->lines.first; - int i = st->top, lineno = 0; - - text_update_drawcache(st, ar); - - if (wrap_top) *wrap_top = 0; - - if (st->wordwrap) { - while (i > 0 && pline) { - int lines = text_get_visible_lines_no(st, lineno); - - if (i - lines < 0) { - if (wrap_top) *wrap_top = i; - break; - } - else { - pline = pline->next; - i -= lines; - lineno++; - } - } - } - else { - for (i = st->top; pline->next && i > 0; i--) - pline = pline->next; - } - - return pline; -} - /************************ draw scrollbar *****************************/ static void calc_text_rcts(SpaceText *st, ARegion *ar, rcti *scroll, rcti *back) @@ -1343,94 +1309,6 @@ static void draw_textscroll(SpaceText *st, rcti *scroll, rcti *back) glDisable(GL_BLEND); } -/************************** draw markers **************************/ - -static void draw_markers(SpaceText *st, ARegion *ar) -{ - Text *text = st->text; - TextMarker *marker, *next; - TextLine *top, *line; - int offl, offc, i, x1, x2, y1, y2, x, y; - int topi, topy; - - /* Move pointer to first visible line (top) */ - top = first_visible_line(st, ar, NULL); - topi = BLI_findindex(&text->lines, top); - - topy = txt_get_span(text->lines.first, top); - - for (marker = text->markers.first; marker; marker = next) { - next = marker->next; - - /* invisible line (before top) */ - if (marker->lineno < topi) continue; - - line = BLI_findlink(&text->lines, marker->lineno); - - /* Remove broken markers */ - if (marker->end > line->len || marker->start > marker->end) { - BLI_freelinkN(&text->markers, marker); - continue; - } - - wrap_offset(st, ar, line, marker->start, &offl, &offc); - y1 = txt_get_span(top, line) - st->top + offl + topy; - x1 = text_get_char_pos(st, line->line, marker->start) - st->left + offc; - - wrap_offset(st, ar, line, marker->end, &offl, &offc); - y2 = txt_get_span(top, line) - st->top + offl + topy; - x2 = text_get_char_pos(st, line->line, marker->end) - st->left + offc; - - /* invisible part of line (before top, after last visible line) */ - if (y2 < 0 || y1 > st->top + st->viewlines) continue; - - gpuCurrentColor3ubv(marker->color); - x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; - y = ar->winy - 3; - - gpuImmediateFormat_V2(); - - if (y1 == y2) { - y -= y1 * st->lheight; - gpuBegin(GL_LINE_LOOP); - gpuVertex2i(x + x2 * st->cwidth + 1, y); - gpuVertex2i(x + x1 * st->cwidth - 2, y); - gpuVertex2i(x + x1 * st->cwidth - 2, y - st->lheight); - gpuVertex2i(x + x2 * st->cwidth + 1, y - st->lheight); - gpuEnd(); - } - else { - y -= y1 * st->lheight; - gpuBegin(GL_LINE_STRIP); - gpuVertex2i(ar->winx, y); - gpuVertex2i(x + x1 * st->cwidth - 2, y); - gpuVertex2i(x + x1 * st->cwidth - 2, y - st->lheight); - gpuVertex2i(ar->winx, y - st->lheight); - gpuEnd(); - y -= st->lheight; - - for (i = y1 + 1; i < y2; i++) { - gpuBegin(GL_LINES); - gpuVertex2i(x, y); - gpuVertex2i(ar->winx, y); - gpuVertex2i(x, y - st->lheight); - gpuVertex2i(ar->winx, y - st->lheight); - gpuEnd(); - y -= st->lheight; - } - - gpuBegin(GL_LINE_STRIP); - gpuVertex2i(x, y); - gpuVertex2i(x + x2 * st->cwidth + 1, y); - gpuVertex2i(x + x2 * st->cwidth + 1, y - st->lheight); - gpuVertex2i(x, y - st->lheight); - gpuEnd(); - } - - gpuImmediateUnformat(); - } -} - /*********************** draw documentation *******************************/ static void draw_documentation(SpaceText *st, ARegion *ar) @@ -1610,6 +1488,7 @@ static void draw_cursor(SpaceText *st, ARegion *ar) Text *text = st->text; int vcurl, vcurc, vsell, vselc, hidden = 0; int x, y, w, i; + int lheight = st->lheight + TXT_LINE_SPACING; /* Draw the selection */ if (text->curl != text->sell || text->curc != text->selc) { @@ -1630,11 +1509,11 @@ static void draw_cursor(SpaceText *st, ARegion *ar) y = ar->winy - 2; if (vcurl == vsell) { - y -= vcurl * st->lheight; + y -= vcurl * lheight; if (vcurc < vselc) - gpuSingleFilledRecti(x + vcurc * st->cwidth - 1, y, x + vselc * st->cwidth, y - st->lheight); + gpuSingleFilledRecti(x + vcurc * st->cwidth - 1, y, x + vselc * st->cwidth, y - st->lheight + TXT_LINE_SPACING); else - gpuSingleFilledRecti(x + vselc * st->cwidth - 1, y, x + vcurc * st->cwidth, y - st->lheight); + gpuSingleFilledRecti(x + vselc * st->cwidth - 1, y, x + vcurc * st->cwidth, y - st->lheight + TXT_LINE_SPACING); } else { int froml, fromc, tol, toc; @@ -1648,12 +1527,13 @@ static void draw_cursor(SpaceText *st, ARegion *ar) fromc = vselc; toc = vcurc; } - y -= froml * st->lheight; + y -= froml * lheight; gpuSingleFilledRecti(x + fromc * st->cwidth - 1, y, ar->winx, y - st->lheight); y -= st->lheight; + for (i = froml + 1; i < tol; i++) for (i = froml + 1; i < tol; i++) { - gpuSingleFilledRecti(x - 4, y, ar->winx, y - st->lheight); + gpuSingleFilledRecti(x - 4, y, ar->winx, y - st->lheight + TXT_LINE_SPACING); y -= st->lheight; } @@ -1681,12 +1561,12 @@ static void draw_cursor(SpaceText *st, ARegion *ar) wrap_offset_in_line(st, ar, text->sell, text->selc, &offl, &offc); - y1 = ar->winy - 2 - (vsell - offl) * st->lheight; - y2 = y1 - st->lheight * visible_lines + 1; + y1 = ar->winy - 2 - (vsell - offl) * lheight; + y2 = y1 - lheight * visible_lines + 1; } else { - y1 = ar->winy - 2 - vsell * st->lheight; - y2 = y1 - st->lheight + 1; + y1 = ar->winy - 2 - vsell * lheight; + y2 = y1 - lheight + 1; } if (!(y1 < 0 || y2 > ar->winy)) { /* check we need to draw */ @@ -1696,7 +1576,7 @@ static void draw_cursor(SpaceText *st, ARegion *ar) gpuCurrentColor4x(CPACK_WHITE, 0.125f); glEnable(GL_BLEND); - gpuSingleFilledRecti(x1 - 4, y1, x2, y2); + gpuSingleFilledRecti(x1 - 4, y1, x2, y2 + TXT_LINE_SPACING); glDisable(GL_BLEND); } } @@ -1705,20 +1585,21 @@ static void draw_cursor(SpaceText *st, ARegion *ar) /* Draw the cursor itself (we draw the sel. cursor as this is the leading edge) */ x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; x += vselc * st->cwidth; - y = ar->winy - 2 - vsell * st->lheight; + y = ar->winy - 2 - vsell * lheight; if (st->overwrite) { char ch = text->sell->line[text->selc]; + y += TXT_LINE_SPACING; w = st->cwidth; if (ch == '\t') w *= st->tabnumber - (vselc + st->left) % st->tabnumber; UI_ThemeColor(TH_HILITE); - gpuSingleFilledRecti(x, y - st->lheight - 1, x + w, y - st->lheight + 1); + gpuSingleFilledRecti(x, y - lheight - 1, x + w, y - lheight + 1); } else { UI_ThemeColor(TH_HILITE); - gpuSingleFilledRecti(x - 1, y, x + 1, y - st->lheight); + gpuSingleFilledRecti(x - 1, y, x + 1, y - lheight + TXT_LINE_SPACING); } } } @@ -1833,8 +1714,8 @@ static void draw_brackets(SpaceText *st, ARegion *ar) if (viewc >= 0) { viewl = txt_get_span(text->lines.first, startl) - st->top + offl; - text_font_draw_character(st, x + viewc * st->cwidth, y - viewl * st->lheight, ch); - text_font_draw_character(st, x + viewc * st->cwidth + 1, y - viewl * st->lheight, ch); + text_font_draw_character(st, x + viewc * st->cwidth, y - viewl * (st->lheight + TXT_LINE_SPACING), ch); + text_font_draw_character(st, x + viewc * st->cwidth + 1, y - viewl * (st->lheight + TXT_LINE_SPACING), ch); } /* draw closing bracket */ @@ -1845,8 +1726,8 @@ static void draw_brackets(SpaceText *st, ARegion *ar) if (viewc >= 0) { viewl = txt_get_span(text->lines.first, endl) - st->top + offl; - text_font_draw_character(st, x + viewc * st->cwidth, y - viewl * st->lheight, ch); - text_font_draw_character(st, x + viewc * st->cwidth + 1, y - viewl * st->lheight, ch); + text_font_draw_character(st, x + viewc * st->cwidth, y - viewl * (st->lheight + TXT_LINE_SPACING), ch); + text_font_draw_character(st, x + viewc * st->cwidth + 1, y - viewl * (st->lheight + TXT_LINE_SPACING), ch); } } @@ -1862,7 +1743,7 @@ void draw_text_main(SpaceText *st, ARegion *ar) int wraplinecount = 0, wrap_skip = 0; int margin_column_x; - if (st->lheight) st->viewlines = (int)ar->winy / st->lheight; + if (st->lheight) st->viewlines = (int)ar->winy / (st->lheight + TXT_LINE_SPACING); else st->viewlines = 0; /* if no text, nothing to do */ @@ -1955,14 +1836,14 @@ void draw_text_main(SpaceText *st, ARegion *ar) if (st->wordwrap) { /* draw word wrapped text */ int lines = text_draw_wrapped(st, tmp->line, x, y, winx - x, tmp->format, wrap_skip); - y -= lines * st->lheight; + y -= lines * (st->lheight + TXT_LINE_SPACING); } else { /* draw unwrapped text */ text_draw(st, tmp->line, st->left, ar->winx / st->cwidth, 1, x, y, tmp->format); - y -= st->lheight; + y -= st->lheight + TXT_LINE_SPACING; } - + wrap_skip = 0; } @@ -1987,7 +1868,6 @@ void draw_text_main(SpaceText *st, ARegion *ar) /* draw other stuff */ draw_brackets(st, ar); - draw_markers(st, ar); gpuTranslate(GLA_PIXEL_OFS, GLA_PIXEL_OFS, 0.0f); /* XXX scroll requires exact pixel space */ draw_textscroll(st, &scroll, &back); draw_documentation(st, ar); diff --git a/source/blender/editors/space_text/text_intern.h b/source/blender/editors/space_text/text_intern.h index 4f973e7076b..ea61644cee9 100644 --- a/source/blender/editors/space_text/text_intern.h +++ b/source/blender/editors/space_text/text_intern.h @@ -57,6 +57,7 @@ void text_update_cursor_moved(struct bContext *C); #define TXT_OFFSET 15 #define TXT_SCROLL_WIDTH 20 #define TXT_SCROLL_SPACE 2 +#define TXT_LINE_SPACING 4 /* space between lines */ #define TEXTXLOC (st->cwidth * st->linenrs_tot) @@ -68,9 +69,6 @@ void text_update_cursor_moved(struct bContext *C); #define TOOL_SUGG_LIST 0x01 #define TOOL_DOCUMENT 0x02 -#define TMARK_GRP_CUSTOM 0x00010000 /* Lower 2 bytes used for Python groups */ -#define TMARK_GRP_FINDALL 0x00020000 - typedef struct FlattenString { char fixedbuf[256]; int fixedaccum[256]; @@ -129,10 +127,6 @@ void TEXT_OT_indent(struct wmOperatorType *ot); void TEXT_OT_line_break(struct wmOperatorType *ot); void TEXT_OT_insert(struct wmOperatorType *ot); -void TEXT_OT_markers_clear(struct wmOperatorType *ot); -void TEXT_OT_next_marker(struct wmOperatorType *ot); -void TEXT_OT_previous_marker(struct wmOperatorType *ot); - void TEXT_OT_select_line(struct wmOperatorType *ot); void TEXT_OT_select_all(struct wmOperatorType *ot); void TEXT_OT_select_word(struct wmOperatorType *ot); @@ -157,7 +151,6 @@ void TEXT_OT_find(struct wmOperatorType *ot); void TEXT_OT_find_set_selected(struct wmOperatorType *ot); void TEXT_OT_replace(struct wmOperatorType *ot); void TEXT_OT_replace_set_selected(struct wmOperatorType *ot); -void TEXT_OT_mark_all(struct wmOperatorType *ot); void TEXT_OT_to_3d_object(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 1be50a54b68..cd6d8719544 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -1135,7 +1135,8 @@ static int text_convert_whitespace_exec(bContext *C, wmOperator *op) tmp = text->lines.first; - //first convert to all space, this make it a lot easier to convert to tabs because there is no mixtures of ' ' && '\t' + /* first convert to all space, this make it a lot easier to convert to tabs + * because there is no mixtures of ' ' && '\t' */ while (tmp) { text_check_line = tmp->line; number = flatten_string(st, &fs, text_check_line) + 1; @@ -1376,104 +1377,6 @@ void TEXT_OT_move_lines(wmOperatorType *ot) RNA_def_enum(ot->srna, "direction", direction_items, 1, "Direction", ""); } -/******************* previous marker operator *********************/ - -static int text_previous_marker_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Text *text = CTX_data_edit_text(C); - TextMarker *mrk; - int lineno; - - lineno = txt_get_span(text->lines.first, text->curl); - mrk = text->markers.last; - while (mrk && (mrk->lineno > lineno || (mrk->lineno == lineno && mrk->end > text->curc))) - mrk = mrk->prev; - if (!mrk) mrk = text->markers.last; - if (mrk) { - txt_move_to(text, mrk->lineno, mrk->start, 0); - txt_move_to(text, mrk->lineno, mrk->end, 1); - } - - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - - return OPERATOR_FINISHED; -} - -void TEXT_OT_previous_marker(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Previous Marker"; - ot->idname = "TEXT_OT_previous_marker"; - ot->description = "Move to previous marker"; - - /* api callbacks */ - ot->exec = text_previous_marker_exec; - ot->poll = text_edit_poll; -} - -/******************* next marker operator *********************/ - -static int text_next_marker_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Text *text = CTX_data_edit_text(C); - TextMarker *mrk; - int lineno; - - lineno = txt_get_span(text->lines.first, text->curl); - mrk = text->markers.first; - while (mrk && (mrk->lineno < lineno || (mrk->lineno == lineno && mrk->start <= text->curc))) - mrk = mrk->next; - if (!mrk) mrk = text->markers.first; - if (mrk) { - txt_move_to(text, mrk->lineno, mrk->start, 0); - txt_move_to(text, mrk->lineno, mrk->end, 1); - } - - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - - return OPERATOR_FINISHED; -} - -void TEXT_OT_next_marker(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Next Marker"; - ot->idname = "TEXT_OT_next_marker"; - ot->description = "Move to next marker"; - - /* api callbacks */ - ot->exec = text_next_marker_exec; - ot->poll = text_edit_poll; -} - -/******************* clear all markers operator *********************/ - -static int text_clear_all_markers_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Text *text = CTX_data_edit_text(C); - - txt_clear_markers(text, 0, 0); - - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - - return OPERATOR_FINISHED; -} - -void TEXT_OT_markers_clear(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Clear All Markers"; - ot->idname = "TEXT_OT_markers_clear"; - ot->description = "Clear all markers"; - - /* api callbacks */ - ot->exec = text_clear_all_markers_exec; - ot->poll = text_edit_poll; -} - /************************ move operator ************************/ static EnumPropertyItem move_type_items[] = { @@ -1664,16 +1567,15 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, short sel) Text *text = st->text; TextLine **linep; int *charp; - int oldl, oldc, i, j, max, start, end, endj, chop, loop; + int oldc, i, j, max, start, end, endj, chop, loop; char ch; text_update_character_width(st); - if (sel) linep = &text->sell, charp = &text->selc; - else linep = &text->curl, charp = &text->curc; + if (sel) { linep = &text->sell; charp = &text->selc; } + else { linep = &text->curl; charp = &text->curc; } oldc = *charp; - oldl = txt_get_span(text->lines.first, *linep); max = wrap_width(st, ar); @@ -1724,7 +1626,6 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, short sel) } if (!sel) txt_pop_sel(text); - txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, oldl, oldc, oldl, *charp); } static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, short sel) @@ -1732,16 +1633,15 @@ static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, short sel) Text *text = st->text; TextLine **linep; int *charp; - int oldl, oldc, i, j, max, start, end, endj, chop, loop; + int oldc, i, j, max, start, end, endj, chop, loop; char ch; text_update_character_width(st); - if (sel) linep = &text->sell, charp = &text->selc; - else linep = &text->curl, charp = &text->curc; + if (sel) { linep = &text->sell; charp = &text->selc; } + else { linep = &text->curl; charp = &text->curc; } oldc = *charp; - oldl = txt_get_span(text->lines.first, *linep); max = wrap_width(st, ar); @@ -1790,7 +1690,6 @@ static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, short sel) } if (!sel) txt_pop_sel(text); - txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, oldl, oldc, oldl, *charp); } static void txt_wrap_move_up(SpaceText *st, ARegion *ar, short sel) @@ -1798,22 +1697,17 @@ static void txt_wrap_move_up(SpaceText *st, ARegion *ar, short sel) Text *text = st->text; TextLine **linep; int *charp; - int oldl, oldc, offl, offc, col, newl; + int offl, offc, col; text_update_character_width(st); - if (sel) linep = &text->sell, charp = &text->selc; - else linep = &text->curl, charp = &text->curc; - - /* store previous position */ - oldc = *charp; - newl = oldl = txt_get_span(text->lines.first, *linep); + if (sel) { linep = &text->sell; charp = &text->selc; } + else { linep = &text->curl; charp = &text->curc; } wrap_offset_in_line(st, ar, *linep, *charp, &offl, &offc); col = text_get_char_pos(st, (*linep)->line, *charp) + offc; if (offl) { *charp = text_get_cursor_rel(st, ar, *linep, offl - 1, col); - newl = BLI_findindex(&text->lines, linep); } else { if ((*linep)->prev) { @@ -1822,13 +1716,11 @@ static void txt_wrap_move_up(SpaceText *st, ARegion *ar, short sel) *linep = (*linep)->prev; visible_lines = text_get_visible_lines(st, ar, (*linep)->line); *charp = text_get_cursor_rel(st, ar, *linep, visible_lines - 1, col); - newl--; } else *charp = 0; } if (!sel) txt_pop_sel(text); - txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, oldl, oldc, newl, *charp); } static void txt_wrap_move_down(SpaceText *st, ARegion *ar, short sel) @@ -1836,35 +1728,28 @@ static void txt_wrap_move_down(SpaceText *st, ARegion *ar, short sel) Text *text = st->text; TextLine **linep; int *charp; - int oldl, oldc, offl, offc, col, newl, visible_lines; + int offl, offc, col, visible_lines; text_update_character_width(st); - if (sel) linep = &text->sell, charp = &text->selc; - else linep = &text->curl, charp = &text->curc; - - /* store previous position */ - oldc = *charp; - newl = oldl = txt_get_span(text->lines.first, *linep); + if (sel) { linep = &text->sell; charp = &text->selc; } + else { linep = &text->curl; charp = &text->curc; } wrap_offset_in_line(st, ar, *linep, *charp, &offl, &offc); col = text_get_char_pos(st, (*linep)->line, *charp) + offc; visible_lines = text_get_visible_lines(st, ar, (*linep)->line); if (offl < visible_lines - 1) { *charp = text_get_cursor_rel(st, ar, *linep, offl + 1, col); - newl = BLI_findindex(&text->lines, linep); } else { if ((*linep)->next) { *linep = (*linep)->next; *charp = text_get_cursor_rel(st, ar, *linep, 0, col); - newl++; } else *charp = (*linep)->len; } if (!sel) txt_pop_sel(text); - txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, oldl, oldc, newl, *charp); } /* Moves the cursor vertically by the specified number of lines. @@ -1876,12 +1761,10 @@ static void txt_wrap_move_down(SpaceText *st, ARegion *ar, short sel) static void cursor_skip(SpaceText *st, ARegion *ar, Text *text, int lines, int sel) { TextLine **linep; - int oldl, oldc, *charp; + int *charp; - if (sel) linep = &text->sell, charp = &text->selc; - else linep = &text->curl, charp = &text->curc; - oldl = txt_get_span(text->lines.first, *linep); - oldc = *charp; + if (sel) { linep = &text->sell; charp = &text->selc; } + else { linep = &text->curl; charp = &text->curc; } if (st && ar && st->wordwrap) { int rell, relc; @@ -1904,7 +1787,6 @@ static void cursor_skip(SpaceText *st, ARegion *ar, Text *text, int lines, int s if (*charp > (*linep)->len) *charp = (*linep)->len; if (!sel) txt_pop_sel(text); - txt_undo_add_toop(text, sel ? UNDO_STO : UNDO_CTO, oldl, oldc, txt_get_span(text->lines.first, *linep), *charp); } static int text_move_cursor(bContext *C, int type, int select) @@ -2222,10 +2104,10 @@ static void text_scroll_apply(bContext *C, wmOperator *op, wmEvent *event) if (!tsc->scrollbar) { txtdelta[0] = -tsc->delta[0] / st->cwidth; - txtdelta[1] = tsc->delta[1] / st->lheight; + txtdelta[1] = tsc->delta[1] / (st->lheight + TXT_LINE_SPACING); tsc->delta[0] %= st->cwidth; - tsc->delta[1] %= st->lheight; + tsc->delta[1] %= (st->lheight + TXT_LINE_SPACING); } else { txtdelta[1] = -tsc->delta[1] * st->pix_per_line; @@ -2611,7 +2493,7 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in if (linep && charp != -1) { if (sel) { text->sell = linep; text->selc = charp; } - else { text->curl = linep; text->curc = charp; } + else { text->curl = linep; text->curc = charp; } } } @@ -2619,7 +2501,7 @@ static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, int { Text *text = st->text; text_update_character_width(st); - y = (ar->winy - 2 - y) / st->lheight; + y = (ar->winy - 2 - y) / (st->lheight + TXT_LINE_SPACING); if (st->showlinenrs) x -= TXT_OFFSET + TEXTXLOC; else x -= TXT_OFFSET; @@ -2636,7 +2518,7 @@ static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, int int w; if (sel) { linep = &text->sell; charp = &text->selc; } - else { linep = &text->curl; charp = &text->curc; } + else { linep = &text->curl; charp = &text->curc; } y -= txt_get_span(text->lines.first, *linep) - st->top; @@ -2696,7 +2578,6 @@ static void text_cursor_set_exit(bContext *C, wmOperator *op) SpaceText *st = CTX_wm_space_text(C); Text *text = st->text; SetSelection *ssel = op->customdata; - int linep2, charp2; char *buffer; if (txt_has_sel(text)) { @@ -2705,12 +2586,6 @@ static void text_cursor_set_exit(bContext *C, wmOperator *op) MEM_freeN(buffer); } - linep2 = txt_get_span(st->text->lines.first, st->text->sell); - charp2 = st->text->selc; - - if (ssel->sell != linep2 || ssel->selc != charp2) - txt_undo_add_toop(st->text, UNDO_STO, ssel->sell, ssel->selc, linep2, charp2); - text_update_cursor_moved(C); WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text); @@ -2786,19 +2661,12 @@ void TEXT_OT_selection_set(wmOperatorType *ot) static int text_cursor_set_exec(bContext *C, wmOperator *op) { SpaceText *st = CTX_wm_space_text(C); - Text *text = st->text; ARegion *ar = CTX_wm_region(C); int x = RNA_int_get(op->ptr, "x"); int y = RNA_int_get(op->ptr, "y"); - int oldl, oldc; - - oldl = txt_get_span(text->lines.first, text->curl); - oldc = text->curc; text_cursor_set_to_pos(st, ar, x, y, 0); - txt_undo_add_toop(text, UNDO_CTO, oldl, oldc, txt_get_span(text->lines.first, text->curl), text->curc); - text_update_cursor_moved(C); WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text); @@ -2990,14 +2858,13 @@ void TEXT_OT_insert(wmOperatorType *ot) /* mode */ #define TEXT_FIND 0 #define TEXT_REPLACE 1 -#define TEXT_MARK_ALL 2 static int text_find_and_replace(bContext *C, wmOperator *op, short mode) { Main *bmain = CTX_data_main(C); SpaceText *st = CTX_wm_space_text(C); - Text *start = NULL, *text = st->text; - int flags, first = 1; + Text *text = st->text; + int flags; int found = 0; char *tmp; @@ -3006,79 +2873,48 @@ static int text_find_and_replace(bContext *C, wmOperator *op, short mode) flags = st->flags; if (flags & ST_FIND_ALL) - flags ^= ST_FIND_WRAP; - - do { - int proceed = 0; + flags &= ~ST_FIND_WRAP; - if (first) { - if (text->markers.first) - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + /* Replace current */ + if (mode != TEXT_FIND && txt_has_sel(text)) { + tmp = txt_sel_to_buf(text); - txt_clear_markers(text, TMARK_GRP_FINDALL, 0); - } + if (flags & ST_MATCH_CASE) found = strcmp(st->findstr, tmp) == 0; + else found = BLI_strcasecmp(st->findstr, tmp) == 0; - first = 0; - - /* Replace current */ - if (mode != TEXT_FIND && txt_has_sel(text)) { - tmp = txt_sel_to_buf(text); - - if (flags & ST_MATCH_CASE) proceed = strcmp(st->findstr, tmp) == 0; - else proceed = BLI_strcasecmp(st->findstr, tmp) == 0; - - if (proceed) { - if (mode == TEXT_REPLACE) { - txt_insert_buf(text, st->replacestr); - if (text->curl && text->curl->format) { - MEM_freeN(text->curl->format); - text->curl->format = NULL; - } - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); - text_drawcache_tag_update(CTX_wm_space_text(C), 1); - } - else if (mode == TEXT_MARK_ALL) { - unsigned char color[4]; - UI_GetThemeColor4ubv(TH_SHADE2, color); - - if (txt_find_marker(text, text->curl, text->selc, TMARK_GRP_FINDALL, 0)) { - if (tmp) MEM_freeN(tmp), tmp = NULL; - break; - } - - txt_add_marker(text, text->curl, text->curc, text->selc, color, TMARK_GRP_FINDALL, TMARK_EDITALL); - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + if (found) { + if (mode == TEXT_REPLACE) { + txt_insert_buf(text, st->replacestr); + if (text->curl && text->curl->format) { + MEM_freeN(text->curl->format); + text->curl->format = NULL; } + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text); + text_drawcache_tag_update(CTX_wm_space_text(C), 1); } - MEM_freeN(tmp); - tmp = NULL; } + MEM_freeN(tmp); + tmp = NULL; + } - /* Find next */ - if (txt_find_string(text, st->findstr, flags & ST_FIND_WRAP, flags & ST_MATCH_CASE)) { - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text); - } - else if (flags & ST_FIND_ALL) { - if (text == start) break; - if (!start) start = text; - if (text->id.next) - text = st->text = text->id.next; - else - text = st->text = bmain->text.first; - txt_move_toline(text, 0, 0); - text_update_cursor_moved(C); - WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text); - first = 1; - } - else { - if (!found && !proceed) BKE_reportf(op->reports, RPT_ERROR, "Text not found: %s", st->findstr); - break; - } - found = 1; - } while (mode == TEXT_MARK_ALL); + /* Find next */ + if (txt_find_string(text, st->findstr, flags & ST_FIND_WRAP, flags & ST_MATCH_CASE)) { + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text); + } + else if (flags & ST_FIND_ALL) { + if (text->id.next) + text = st->text = text->id.next; + else + text = st->text = bmain->text.first; + txt_move_toline(text, 0, 0); + text_update_cursor_moved(C); + WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text); + } + else { + if (!found) BKE_reportf(op->reports, RPT_ERROR, "Text not found: %s", st->findstr); + } return OPERATOR_FINISHED; } @@ -3119,25 +2955,6 @@ void TEXT_OT_replace(wmOperatorType *ot) ot->poll = text_space_edit_poll; } -/******************* mark all operator *********************/ - -static int text_mark_all_exec(bContext *C, wmOperator *op) -{ - return text_find_and_replace(C, op, TEXT_MARK_ALL); -} - -void TEXT_OT_mark_all(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Mark All"; - ot->idname = "TEXT_OT_mark_all"; - ot->description = "Mark all specified text"; - - /* api callbacks */ - ot->exec = text_mark_all_exec; - ot->poll = text_space_edit_poll; -} - /******************* find set selected *********************/ static int text_find_set_selected_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/space_text/text_python.c b/source/blender/editors/space_text/text_python.c index 966afe22e42..4c9b4b900cc 100644 --- a/source/blender/editors/space_text/text_python.c +++ b/source/blender/editors/space_text/text_python.c @@ -359,177 +359,3 @@ static short UNUSED_FUNCTION(do_texttools) (SpaceText * st, char ascii, unsigned return swallow; } - -static short UNUSED_FUNCTION(do_textmarkers) (SpaceText * st, char ascii, unsigned short evnt, short val) -{ - Text *text; - TextMarker *marker, *mrk, *nxt; - int c, s, draw = 0, swallow = 0; - int qual = 0; // XXX - - text = st->text; - if (!text || text->id.lib || text->curl != text->sell) return 0; - - marker = txt_find_marker(text, text->sell, text->selc, 0, 0); - if (marker && (marker->start > text->curc || marker->end < text->curc)) - marker = NULL; - - if (!marker) { - /* Find the next temporary marker */ - if (evnt == TABKEY) { - int lineno = txt_get_span(text->lines.first, text->curl); - mrk = text->markers.first; - while (mrk) { - if (!marker && (mrk->flags & TMARK_TEMP)) marker = mrk; - if ((mrk->flags & TMARK_TEMP) && (mrk->lineno > lineno || (mrk->lineno == lineno && mrk->end > text->curc))) { - marker = mrk; - break; - } - mrk = mrk->next; - } - if (marker) { - txt_move_to(text, marker->lineno, marker->start, 0); - txt_move_to(text, marker->lineno, marker->end, 1); - // XXX text_update_cursor_moved(C); - // XXX WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text); - evnt = ascii = val = 0; - draw = 1; - swallow = 1; - } - } - else if (evnt == ESCKEY) { - if (txt_clear_markers(text, 0, TMARK_TEMP)) swallow = 1; - else if (txt_clear_markers(text, 0, 0)) swallow = 1; - else return 0; - evnt = ascii = val = 0; - draw = 1; - } - if (!swallow) return 0; - } - - if (ascii) { - if (marker->flags & TMARK_EDITALL) { - c = text->curc - marker->start; - s = text->selc - marker->start; - if (s < 0 || s > marker->end - marker->start) return 0; - - mrk = txt_next_marker(text, marker); - while (mrk) { - nxt = txt_next_marker(text, mrk); /* mrk may become invalid */ - txt_move_to(text, mrk->lineno, mrk->start + c, 0); - if (s != c) txt_move_to(text, mrk->lineno, mrk->start + s, 1); - if (st->overwrite) { - if (txt_replace_char(text, ascii)) - text_update_line_edited(st->text->curl); - } - else { - if (txt_add_char(text, ascii)) { - text_update_line_edited(st->text->curl); - } - } - - if (mrk == marker || mrk == nxt) break; - mrk = nxt; - } - swallow = 1; - draw = 1; - } - } - else if (val) { - switch (evnt) { - case BACKSPACEKEY: - if (marker->flags & TMARK_EDITALL) { - c = text->curc - marker->start; - s = text->selc - marker->start; - if (s < 0 || s > marker->end - marker->start) return 0; - - mrk = txt_next_marker(text, marker); - while (mrk) { - nxt = txt_next_marker(text, mrk); /* mrk may become invalid */ - txt_move_to(text, mrk->lineno, mrk->start + c, 0); - if (s != c) txt_move_to(text, mrk->lineno, mrk->start + s, 1); - txt_backspace_char(text); - text_update_line_edited(st->text->curl); - if (mrk == marker || mrk == nxt) break; - mrk = nxt; - } - swallow = 1; - draw = 1; - } - break; - case DELKEY: - if (marker->flags & TMARK_EDITALL) { - c = text->curc - marker->start; - s = text->selc - marker->start; - if (s < 0 || s > marker->end - marker->start) return 0; - - mrk = txt_next_marker(text, marker); - while (mrk) { - nxt = txt_next_marker(text, mrk); /* mrk may become invalid */ - txt_move_to(text, mrk->lineno, mrk->start + c, 0); - if (s != c) txt_move_to(text, mrk->lineno, mrk->start + s, 1); - txt_delete_char(text); - text_update_line_edited(st->text->curl); - if (mrk == marker || mrk == nxt) break; - mrk = nxt; - } - swallow = 1; - draw = 1; - } - break; - case TABKEY: - if (qual & LR_SHIFTKEY) { - nxt = marker->prev; - if (!nxt) nxt = text->markers.last; - } - else { - nxt = marker->next; - if (!nxt) nxt = text->markers.first; - } - if (marker->flags & TMARK_TEMP) { - if (nxt == marker) nxt = NULL; - BLI_freelinkN(&text->markers, marker); - } - mrk = nxt; - if (mrk) { - txt_move_to(text, mrk->lineno, mrk->start, 0); - txt_move_to(text, mrk->lineno, mrk->end, 1); - // XXX text_update_cursor_moved(C); - // XXX WM_event_add_notifier(C, NC_TEXT|ND_CURSOR, text); - } - swallow = 1; - draw = 1; - break; - - /* Events that should clear markers */ - case UKEY: if (!(qual & LR_ALTKEY)) break; - case ZKEY: if (evnt == ZKEY && !(qual & LR_CTRLKEY)) break; - case RETKEY: - case ESCKEY: - if (marker->flags & (TMARK_EDITALL | TMARK_TEMP)) - txt_clear_markers(text, marker->group, 0); - else - BLI_freelinkN(&text->markers, marker); - swallow = 1; - draw = 1; - break; - case RIGHTMOUSE: /* Marker context menu? */ - case LEFTMOUSE: - break; - case FKEY: /* Allow find */ - if (qual & LR_SHIFTKEY) swallow = 1; - break; - - default: - if (qual != 0 && qual != LR_SHIFTKEY) - swallow = 1; /* Swallow all other shortcut events */ - } - } - - if (draw) { - // XXX redraw_alltext(); - } - - return swallow; -} - diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index 20d5e8ee69c..5d442aff84d 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -741,7 +741,7 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl) BKE_bproperty_set_valstr(prop, string); characters = strlen(string); - if (!BKE_image_get_ibuf(mtpoly->tpage, NULL)) + if (!BKE_image_has_ibuf(mtpoly->tpage, NULL)) characters = 0; if (!mf_smooth) { diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 8cb4d1ff308..7cd432db661 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -462,7 +462,7 @@ void drawaxes(float size, char drawtype) static void draw_empty_image(Object *ob, const short dflag, const unsigned char ob_wire_col[4]) { Image *ima = (Image *)ob->data; - ImBuf *ibuf = ima ? BKE_image_get_ibuf(ima, NULL) : NULL; + ImBuf *ibuf = ima ? BKE_image_acquire_ibuf(ima, NULL, NULL) : NULL; float scale, ofs_x, ofs_y, sca_x, sca_y; int ima_x, ima_y; @@ -547,6 +547,8 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char /* Reset GL settings */ gpuMatrixMode(GL_MODELVIEW); gpuPopMatrix(); + + BKE_image_release_ibuf(ima, ibuf, NULL); } /* circle for object centers, special_color is for library or ob users */ @@ -3551,9 +3553,12 @@ static int drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, B return 0; } -/* returns 1 when nothing was drawn */ -static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, - const short dt, const short dflag, const unsigned char ob_wire_col[4]) +/** + * Only called by #drawDispList + * \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]) { Object *ob = base->object; ListBase *lb = NULL; @@ -3561,20 +3566,9 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas Curve *cu; const short render_only = (v3d->flag2 & V3D_RENDER_OVERRIDE); const short solid = (dt > OB_WIRE); - int retval = 0; - - /* backface culling */ - if (v3d->flag2 & V3D_BACKFACE_CULLING) { - /* not all displists use same in/out normal direction convention */ - glEnable(GL_CULL_FACE); - glCullFace((ob->type == OB_MBALL) ? GL_BACK : GL_FRONT); - } if (drawCurveDerivedMesh(scene, v3d, rv3d, base, dt) == 0) { - if (v3d->flag2 & V3D_BACKFACE_CULLING) - glDisable(GL_CULL_FACE); - - return 0; + return FALSE; } switch (ob->type) { @@ -3586,7 +3580,9 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas if (solid) { dl = lb->first; - if (dl == NULL) return 1; + if (dl == NULL) { + return TRUE; + } if (dl->nors == NULL) BKE_displist_normals_add(lb); index3_nors_incr = 0; @@ -3620,9 +3616,11 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas } else { if (!render_only || (render_only && BKE_displist_has_faces(lb))) { + int retval; draw_index_wire = 0; retval = drawDispListwire(lb); draw_index_wire = 1; + return retval; } } break; @@ -3632,7 +3630,9 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas if (solid) { dl = lb->first; - if (dl == NULL) return 1; + if (dl == NULL) { + return TRUE; + } if (dl->nors == NULL) BKE_displist_normals_add(lb); @@ -3648,7 +3648,7 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas } } else { - retval = drawDispListwire(lb); + return drawDispListwire(lb); } break; case OB_MBALL: @@ -3656,7 +3656,9 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas if (BKE_mball_is_basis(ob)) { lb = &ob->disp; if (lb->first == NULL) BKE_displist_make_mball(scene, ob); - if (lb->first == NULL) return 1; + if (lb->first == NULL) { + return TRUE; + } if (solid) { @@ -3673,14 +3675,31 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas } else { /* MetaBalls use DL_INDEX4 type of DispList */ - retval = drawDispListwire(lb); + return drawDispListwire(lb); } } break; } - - if (v3d->flag2 & V3D_BACKFACE_CULLING) + + 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]) +{ + int retval; + + /* backface culling */ + if (v3d->flag2 & V3D_BACKFACE_CULLING) { + /* not all displists use same in/out normal direction convention */ + glEnable(GL_CULL_FACE); + glCullFace((base->object->type == OB_MBALL) ? GL_BACK : GL_FRONT); + } + + retval = drawDispList_nobackface(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); + + if (v3d->flag2 & V3D_BACKFACE_CULLING) { glDisable(GL_CULL_FACE); + } return retval; } diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 88b100c6c13..26eebd16fba 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -946,7 +946,7 @@ static void view3d_buttons_area_listener(ARegion *ar, wmNotifier *wmn) ED_region_tag_redraw(ar); break; case NC_GPENCIL: - if (wmn->data == ND_DATA) + if (wmn->data == ND_DATA || wmn->action == NA_EDITED) ED_region_tag_redraw(ar); break; } @@ -1120,16 +1120,21 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes return 1; } else if (CTX_data_equals(member, "active_base")) { - if (scene->basact && (scene->basact->lay & lay)) - if ((scene->basact->object->restrictflag & OB_RESTRICT_VIEW) == 0) + if (scene->basact && (scene->basact->lay & lay)) { + Object *ob = scene->basact->object; + /* if hidden but in edit mode, we still display, can happen with animation */ + if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0 || (ob->mode & OB_MODE_EDIT)) CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, scene->basact); + } return 1; } else if (CTX_data_equals(member, "active_object")) { - if (scene->basact && (scene->basact->lay & lay)) - if ((scene->basact->object->restrictflag & OB_RESTRICT_VIEW) == 0) + if (scene->basact && (scene->basact->lay & lay)) { + Object *ob = scene->basact->object; + if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0 || (ob->mode & OB_MODE_EDIT)) CTX_data_id_pointer_set(result, &scene->basact->object->id); + } return 1; } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 2c85dc62edb..10480a3872a 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -97,6 +97,16 @@ #include "view3d_intern.h" /* own include */ +/* handy utility for drawing shapes in the viewport for arbitrary code. + * could add lines and points too */ +// #define DEBUG_DRAW +#ifdef DEBUG_DRAW +static void bl_debug_draw(void); +/* add these locally when using these functions for testing */ +extern void bl_debug_draw_quad_clear(void); +extern void bl_debug_draw_quad_add(const float v0[3], const float v1[3], const float v2[3], const float v3[3]); +extern void bl_debug_draw_edge_add(const float v0[3], const float v1[3]); +#endif static void star_stuff_init_func(void) { @@ -1271,7 +1281,7 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) hmargin = 0.035f * (x2 - x1); vmargin = 0.035f * (y2 - y1); - uiDrawBox(GL_LINE_LOOP, x1 + hmargin, y1+vmargin, x2 - hmargin, y2 - vmargin, 2.0f); + uiDrawBox(GL_LINE_LOOP, x1 + hmargin, y1 + vmargin, x2 - hmargin, y2 - vmargin, 2.0f); } if (ca && (ca->flag & CAM_SHOWSENSOR)) { /* determine sensor fit, and get sensor x/y, for auto fit we @@ -1464,8 +1474,8 @@ ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax, ibuf = IMB_allocImBuf((xmaxc - xminc + 1), (ymaxc - yminc + 1), 32, IB_rect); - view3d_validate_backbuf(vc); - + view3d_validate_backbuf(vc); + glReadPixels(vc->ar->winrct.xmin + xminc, vc->ar->winrct.ymin + yminc, (xmaxc - xminc + 1), @@ -1613,7 +1623,8 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, ibuf = NULL; /* frame is out of range, dont show */ } else { - ibuf = BKE_image_get_ibuf(ima, &bgpic->iuser); + ibuf = BKE_image_acquire_ibuf(ima, &bgpic->iuser, NULL); + freeibuf = ibuf; } image_aspect[0] = ima->aspx; @@ -3036,9 +3047,10 @@ static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const v3d->zbuf = FALSE; /* enables anti-aliasing for 3D view drawing */ - if (U.ogl_multisamples) - if (!(U.gameflags & USER_DISABLE_AA)) - glEnable(GL_MULTISAMPLE_ARB); + if (U.ogl_multisamples != USER_MULTISAMPLE_NONE) { + // if (!(U.gameflags & USER_DISABLE_AA)) + glEnable(GL_MULTISAMPLE_ARB); + } /* needs to be done always, gridview is adjusted in drawgrid() now */ @@ -3153,9 +3165,10 @@ static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const BIF_draw_manipulator(C); /* Disable back anti-aliasing */ - if (U.ogl_multisamples) - if (!(U.gameflags & USER_DISABLE_AA)) - glDisable(GL_MULTISAMPLE_ARB); + if (U.ogl_multisamples != USER_MULTISAMPLE_NONE) { + // if (!(U.gameflags & USER_DISABLE_AA)) + glDisable(GL_MULTISAMPLE_ARB); + } if (v3d->zbuf) { @@ -3257,6 +3270,9 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar) /* draw viewport using opengl */ if (v3d->drawtype != OB_RENDER || !view3d_main_area_do_render_draw(C) || draw_border) { view3d_main_area_draw_objects(C, ar, &grid_unit); +#ifdef DEBUG_DRAW + bl_debug_draw(); +#endif ED_region_pixelspace(ar); } @@ -3269,3 +3285,57 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar) v3d->flag |= V3D_INVALID_BACKBUF; } +#ifdef DEBUG_DRAW +/* debug drawing */ +#define _DEBUG_DRAW_QUAD_TOT 1024 +static float _bl_debug_draw_quads[_DEBUG_DRAW_QUAD_TOT][4][3]; +static int _bl_debug_draw_quads_tot = 0; + +void bl_debug_draw_quad_clear(void) +{ + _bl_debug_draw_quads_tot = 0; +} +void bl_debug_draw_quad_add(const float v0[3], const float v1[3], const float v2[3], const float v3[3]) +{ + if (_bl_debug_draw_quads_tot >= _DEBUG_DRAW_QUAD_TOT) { + printf("%s: max quad count hit %d!", __func__, _bl_debug_draw_quads_tot); + } + else { + float *pt = &_bl_debug_draw_quads[_bl_debug_draw_quads_tot][0][0]; + copy_v3_v3(pt, v0); pt += 3; + copy_v3_v3(pt, v1); pt += 3; + copy_v3_v3(pt, v2); pt += 3; + copy_v3_v3(pt, v3); pt += 3; + _bl_debug_draw_quads_tot++; + } +} +void bl_debug_draw_edge_add(const float v0[3], const float v1[3]) +{ + if (_bl_debug_draw_quads_tot >= _DEBUG_DRAW_QUAD_TOT) { + printf("%s: max edge count hit %d!", __func__, _bl_debug_draw_quads_tot); + } + else { + float *pt = &_bl_debug_draw_quads[_bl_debug_draw_quads_tot][0][0]; + copy_v3_v3(pt, v0); pt += 3; + copy_v3_v3(pt, v1); pt += 3; + copy_v3_v3(pt, v0); pt += 3; + copy_v3_v3(pt, v1); pt += 3; + _bl_debug_draw_quads_tot++; + } +} +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 ++) { + 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(); + } +} +#endif diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index d8fcc7e12e7..79bf003a563 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -310,21 +310,14 @@ static char *view3d_modeselect_pup(Scene *scene) return (string); } - static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event) { wmWindow *win = CTX_wm_window(C); - ToolSettings *ts = CTX_data_tool_settings(C); ScrArea *sa = CTX_wm_area(C); View3D *v3d = sa->spacedata.first; - Object *obedit = CTX_data_edit_object(C); - BMEditMesh *em = NULL; - int ctrl = win->eventstate->ctrl, shift = win->eventstate->shift; + const int ctrl = win->eventstate->ctrl, shift = win->eventstate->shift; PointerRNA props_ptr; - - if (obedit && obedit->type == OB_MESH) { - em = BMEdit_FromObject(obedit); - } + /* watch it: if sa->win does not exist, check that when calling direct drawing routines */ switch (event) { @@ -336,42 +329,17 @@ static void do_view3d_header_buttons(bContext *C, void *UNUSED(arg), int event) break; case B_SEL_VERT: - if (em) { - if (shift == 0 || em->selectmode == 0) - em->selectmode = SCE_SELECT_VERTEX; - ts->selectmode = em->selectmode; - EDBM_selectmode_set(em); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + if (EDBM_selectmode_toggle(C, SCE_SELECT_VERTEX, -1, shift, ctrl)) { ED_undo_push(C, "Selectmode Set: Vertex"); } break; case B_SEL_EDGE: - if (em) { - if (shift == 0 || em->selectmode == 0) { - if ((em->selectmode ^ SCE_SELECT_EDGE) == SCE_SELECT_VERTEX) { - if (ctrl) EDBM_selectmode_convert(em, SCE_SELECT_VERTEX, SCE_SELECT_EDGE); - } - em->selectmode = SCE_SELECT_EDGE; - } - ts->selectmode = em->selectmode; - EDBM_selectmode_set(em); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + if (EDBM_selectmode_toggle(C, SCE_SELECT_EDGE, -1, shift, ctrl)) { ED_undo_push(C, "Selectmode Set: Edge"); } break; case B_SEL_FACE: - if (em) { - if (shift == 0 || em->selectmode == 0) { - if (((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_VERTEX) || - ((ts->selectmode ^ SCE_SELECT_FACE) == SCE_SELECT_EDGE)) - { - if (ctrl) EDBM_selectmode_convert(em, (ts->selectmode ^ SCE_SELECT_FACE), SCE_SELECT_FACE); - } - em->selectmode = SCE_SELECT_FACE; - } - ts->selectmode = em->selectmode; - EDBM_selectmode_set(em); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + if (EDBM_selectmode_toggle(C, SCE_SELECT_FACE, -1, shift, ctrl)) { ED_undo_push(C, "Selectmode Set: Face"); } break; @@ -430,9 +398,15 @@ void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C) row = uiLayoutRow(layout, TRUE); block = uiLayoutGetBlock(row); - uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL, 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Vertex select - Shift-Click for multiple modes"); - uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_SEL_EDGE, ICON_EDGESEL, 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Edge select - Shift-Click for multiple modes"); - uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL, 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Face select - Shift-Click for multiple modes"); + uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL, + 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, + "Vertex select - Shift-Click for multiple modes"); + uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_SEL_EDGE, ICON_EDGESEL, + 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, + "Edge select - Shift-Click for multiple modes, Ctrl-Click expands selection"); + uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL, + 0, 0, UI_UNIT_X, UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, + "Face select - Shift-Click for multiple modes, Ctrl-Click expands selection"); } } diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index a9dcbdc1687..1a4d345705b 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -1066,11 +1066,11 @@ static EnumPropertyItem *object_select_menu_enum_itemf(bContext *C, PointerRNA * static int object_select_menu_exec(bContext *C, wmOperator *op) { int name_index = RNA_enum_get(op->ptr, "name"); - short extend = RNA_boolean_get(op->ptr, "extend"); + short toggle = RNA_boolean_get(op->ptr, "toggle"); short changed = 0; const char *name = object_mouse_select_menu_data[name_index].idname; - if (!extend) { + if (!toggle) { CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { if (base->flag & SELECT) { @@ -1127,7 +1127,7 @@ void VIEW3D_OT_select_menu(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN); ot->prop = prop; - RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first"); + RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "Toggle selection instead of deselecting everything first"); } static void deselectall_except(Scene *scene, Base *b) /* deselect all except b */ @@ -1143,7 +1143,7 @@ static void deselectall_except(Scene *scene, Base *b) /* deselect all except b } } -static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int *buffer, int hits, const int mval[2], short extend) +static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int *buffer, int hits, const int mval[2], short toggle) { short baseCount = 0; short ok; @@ -1209,7 +1209,7 @@ static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int PointerRNA ptr; WM_operator_properties_create(&ptr, "VIEW3D_OT_select_menu"); - RNA_boolean_set(&ptr, "extend", extend); + RNA_boolean_set(&ptr, "toggle", toggle); WM_operator_name_call(C, "VIEW3D_OT_select_menu", WM_OP_INVOKE_DEFAULT, &ptr); WM_operator_properties_free(&ptr); } @@ -1442,7 +1442,7 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese /* note; shift+alt goes to group-flush-selecting */ if (enumerate) { - basact = object_mouse_select_menu(C, &vc, NULL, 0, mval, extend); + basact = object_mouse_select_menu(C, &vc, NULL, 0, mval, toggle); } else { base = startbase; @@ -1482,7 +1482,7 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese /* note; shift+alt goes to group-flush-selecting */ if (has_bones == 0 && enumerate) { - basact = object_mouse_select_menu(C, &vc, buffer, hits, mval, extend); + basact = object_mouse_select_menu(C, &vc, buffer, hits, mval, toggle); } else { basact = mouse_select_eval_buffer(&vc, buffer, hits, mval, startbase, has_bones); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 1c50e833c6d..e69f0695697 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -3209,11 +3209,21 @@ static void headerResize(TransInfo *t, float vec[3], char *str) (void)spos; } -#define SIGN(a) (a<-FLT_EPSILON ? 1 : a>FLT_EPSILON ? 2 : 3) -#define VECSIGNFLIP(a, b) ((SIGN(a[0]) & SIGN(b[0])) == 0 || (SIGN(a[1]) & SIGN(b[1])) == 0 || (SIGN(a[2]) & SIGN(b[2])) == 0) +/* FLT_EPSILON is too small [#29633], 0.0000001f starts to flip */ +#define TX_FLIP_EPS 0.00001f +BLI_INLINE int tx_sign(const float a) +{ + return (a < -TX_FLIP_EPS ? 1 : a > TX_FLIP_EPS ? 2 : 3); +} +BLI_INLINE int tx_vec_sign_flip(const float a[3], const float b[3]) +{ + return ((tx_sign(a[0]) & tx_sign(b[0])) == 0 || + (tx_sign(a[1]) & tx_sign(b[1])) == 0 || + (tx_sign(a[2]) & tx_sign(b[2])) == 0); +} /* smat is reference matrix, only scaled */ -static void TransMat3ToSize(float mat[][3], float smat[][3], float *size) +static void TransMat3ToSize(float mat[][3], float smat[][3], float size[3]) { float vec[3]; @@ -3225,9 +3235,9 @@ static void TransMat3ToSize(float mat[][3], float smat[][3], float *size) size[2] = normalize_v3(vec); /* first tried with dotproduct... but the sign flip is crucial */ - if (VECSIGNFLIP(mat[0], smat[0]) ) size[0] = -size[0]; - if (VECSIGNFLIP(mat[1], smat[1]) ) size[1] = -size[1]; - if (VECSIGNFLIP(mat[2], smat[2]) ) size[2] = -size[2]; + if (tx_vec_sign_flip(mat[0], smat[0]) ) size[0] = -size[0]; + if (tx_vec_sign_flip(mat[1], smat[1]) ) size[1] = -size[1]; + if (tx_vec_sign_flip(mat[2], smat[2]) ) size[2] = -size[2]; } diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 8e8b909270b..58d8a06415a 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -151,8 +151,8 @@ static void postConstraintChecks(TransInfo *t, float vec[3], float pvec[3]) if (hasNumInput(&t->num)) { applyNumInput(&t->num, vec); - removeAspectRatio(t, vec); constraintNumInput(t, vec); + removeAspectRatio(t, vec); } /* autovalues is operator param, use that directly but not if snapping is forced */ diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 9bbd3f59cbf..5b79b69f7ec 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -2486,7 +2486,7 @@ int clipUVTransform(TransInfo *t, float *vec, int resize) max[0] = aspx; max[1] = aspy; for (a = 0, td = t->data; a < t->total; a++, td++) { - DO_MINMAX2(td->loc, min, max); + minmax_v2v2_v2(min, max, td->loc); } if (resize) { diff --git a/source/blender/editors/uvedit/uvedit_buttons.c b/source/blender/editors/uvedit/uvedit_buttons.c index fa39a52444b..1c32c01b8f0 100644 --- a/source/blender/editors/uvedit/uvedit_buttons.c +++ b/source/blender/editors/uvedit/uvedit_buttons.c @@ -94,14 +94,19 @@ static int uvedit_center(Scene *scene, BMEditMesh *em, Image *ima, float center[ return tot; } -static void uvedit_translate(Scene *scene, BMEditMesh *em, Image *UNUSED(ima), float delta[2]) +static void uvedit_translate(Scene *scene, BMEditMesh *em, Image *ima, float delta[2]) { BMFace *f; BMLoop *l; BMIter iter, liter; MLoopUV *luv; + MTexPoly *tf; BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) { + tf = CustomData_bmesh_get(&em->bm->pdata, f->head.data, CD_MTEXPOLY); + if (!uvedit_face_visible_test(scene, ima, f, tf)) + continue; + BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); if (uvedit_uv_select_test(em, scene, l)) { diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index d3d85c19487..c6db7d4896a 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -616,7 +616,7 @@ int ED_uvedit_minmax(Scene *scene, Image *ima, Object *obedit, float r_min[2], f 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); - DO_MINMAX2(luv->uv, r_min, r_max); + minmax_v2v2_v2(r_min, r_max, luv->uv); sel = 1; } } @@ -1327,7 +1327,7 @@ static void weld_align_uv(bContext *C, int tool) 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); - DO_MINMAX2(luv->uv, min, max); + minmax_v2v2_v2(min, max, luv->uv); } } } @@ -1553,7 +1553,170 @@ static void UV_OT_align(wmOperatorType *ot) /* properties */ RNA_def_enum(ot->srna, "axis", axis_items, 'a', "Axis", "Axis to align UV locations on"); } +/* ******************** weld near operator **************** */ +typedef struct UVvert { + MLoopUV *uv_loop; + int weld; +} UVvert; + +static int remove_doubles_exec(bContext *C, wmOperator *op) +{ + const float threshold = RNA_float_get(op->ptr, "threshold"); + const int use_unselected = RNA_boolean_get(op->ptr, "use_unselected"); + + SpaceImage *sima; + Scene *scene; + Object *obedit; + Image *ima; + BMEditMesh *em; + MTexPoly *tf; + int uv_a_index; + int uv_b_index; + float *uv_a; + float *uv_b; + + BMIter iter, liter; + BMFace *efa; + BMLoop *l; + + 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) { + UVvert *vert_arr = NULL; + BLI_array_declare(vert_arr); + MLoopUV **loop_arr = NULL; + BLI_array_declare(loop_arr); + + /* 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); + 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); + UVvert vert; + vert.uv_loop = luv; + vert.weld = FALSE; + BLI_array_append(vert_arr, vert); + } + + } + } + + for (uv_a_index = 0; uv_a_index < BLI_array_count(vert_arr); uv_a_index++) { + if (vert_arr[uv_a_index].weld == FALSE) { + float uv_min[2]; + float uv_max[2]; + + BLI_array_empty(loop_arr); + BLI_array_append(loop_arr, vert_arr[uv_a_index].uv_loop); + + uv_a = vert_arr[uv_a_index].uv_loop->uv; + + copy_v2_v2(uv_max, uv_a); + copy_v2_v2(uv_min, uv_a); + + vert_arr[uv_a_index].weld = TRUE; + for (uv_b_index = uv_a_index + 1; uv_b_index < BLI_array_count(vert_arr); uv_b_index++) { + uv_b = vert_arr[uv_b_index].uv_loop->uv; + if ((vert_arr[uv_b_index].weld == FALSE) && + (len_manhattan_v2v2(uv_a, uv_b) < threshold)) + { + minmax_v2v2_v2(uv_max, uv_min, uv_b); + BLI_array_append(loop_arr, vert_arr[uv_b_index].uv_loop); + vert_arr[uv_b_index].weld = TRUE; + } + } + if (BLI_array_count(loop_arr)) { + float uv_mid[2]; + mid_v2_v2v2(uv_mid, uv_min, uv_max); + for (uv_b_index = 0; uv_b_index < BLI_array_count(loop_arr); uv_b_index++) { + copy_v2_v2(loop_arr[uv_b_index]->uv, uv_mid); + } + } + } + } + + BLI_array_free(vert_arr); + BLI_array_free(loop_arr); + } + else { + /* selected -> unselected + * + * No need to use 'UVvert' here */ + MLoopUV **loop_arr = NULL; + BLI_array_declare(loop_arr); + MLoopUV **loop_arr_unselected = NULL; + 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); + 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); + if (uvedit_uv_select_test(em, scene, l)) { + BLI_array_append(loop_arr, luv); + } + else { + BLI_array_append(loop_arr_unselected, luv); + } + } + } + + for (uv_a_index = 0; uv_a_index < BLI_array_count(loop_arr); uv_a_index++) { + float dist_best = FLT_MAX, dist; + float *uv_best = NULL; + + uv_a = loop_arr[uv_a_index]->uv; + for (uv_b_index = 0; uv_b_index < BLI_array_count(loop_arr_unselected); uv_b_index++) { + uv_b = loop_arr_unselected[uv_b_index]->uv; + dist = len_manhattan_v2v2(uv_a, uv_b); + if ((dist < threshold) && (dist < dist_best)) { + uv_best = uv_b; + dist_best = dist; + } + } + if (uv_best) { + copy_v2_v2(uv_a, uv_best); + } + } + + BLI_array_free(loop_arr); + BLI_array_free(loop_arr_unselected); + } + + uvedit_live_unwrap_update(sima, scene, obedit); + DAG_id_tag_update(obedit->data, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + + return OPERATOR_FINISHED; +} + +static void UV_OT_remove_doubles(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Remove Doubles UV"; + ot->description = "Selected UV vertices that are within a radius of each other are welded together"; + ot->idname = "UV_OT_remove_doubles"; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* api callbacks */ + ot->exec = remove_doubles_exec; + ot->poll = ED_operator_uvedit; + + RNA_def_float(ot->srna, "threshold", 0.02f, 0.0f, 10.0f, + "Merge Distance", "Maximum distance between welded vertices", 0.0f, 1.0f); + RNA_def_boolean(ot->srna, "use_unselected", 0, "Unselected", "Merge selected to other unselected vertices"); +} /* ******************** weld operator **************** */ static int weld_exec(bContext *C, wmOperator *UNUSED(op)) @@ -3776,6 +3939,7 @@ void ED_operatortypes_uvedit(void) WM_operatortype_append(UV_OT_seams_from_islands); WM_operatortype_append(UV_OT_mark_seam); WM_operatortype_append(UV_OT_weld); + WM_operatortype_append(UV_OT_remove_doubles); WM_operatortype_append(UV_OT_pin); WM_operatortype_append(UV_OT_average_islands_scale); diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c index 5b6125b558b..8703234122a 100644 --- a/source/blender/editors/uvedit/uvedit_parametrizer.c +++ b/source/blender/editors/uvedit/uvedit_parametrizer.c @@ -450,7 +450,7 @@ static void p_chart_uv_bbox(PChart *chart, float minv[2], float maxv[2]) INIT_MINMAX2(minv, maxv); for (v = chart->verts; v; v = v->nextlink) { - DO_MINMAX2(v->uv, minv, maxv); + minmax_v2v2_v2(minv, maxv, v->uv); } } @@ -3891,9 +3891,9 @@ static void p_smooth(PChart *chart) INIT_MINMAX2(fmin, fmax); - DO_MINMAX2(e1->vert->uv, fmin, fmax); - DO_MINMAX2(e2->vert->uv, fmin, fmax); - DO_MINMAX2(e3->vert->uv, fmin, fmax); + minmax_v2v2_v2(fmin, fmax, e1->vert->uv); + minmax_v2v2_v2(fmin, fmax, e2->vert->uv); + minmax_v2v2_v2(fmin, fmax, e3->vert->uv); bx1 = (int)((fmin[0] - minv[0]) * invmedian); by1 = (int)((fmin[1] - minv[1]) * invmedian); diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c index 4f6aa224586..cd260c4ea77 100644 --- a/source/blender/editors/uvedit/uvedit_smart_stitch.c +++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c @@ -1444,18 +1444,22 @@ static int stitch_modal(bContext *C, wmOperator *op, wmEvent *event) } case PADENTER: case RETKEY: - if (stitch_process_data(stitch_state, scene, 1)) { - stitch_exit(C, op, 1); - return OPERATOR_FINISHED; + if (event->val == KM_PRESS) { + if (stitch_process_data(stitch_state, scene, 1)) { + stitch_exit(C, op, 1); + return OPERATOR_FINISHED; + } + else { + return stitch_cancel(C, op); + } } else { - return stitch_cancel(C, op); + return OPERATOR_PASS_THROUGH; } - /* Increase limit */ case PADPLUSKEY: case WHEELUPMOUSE: - if (event->alt) { + if (event->val == KM_PRESS && event->alt) { stitch_state->limit_dist += 0.01f; if (!stitch_process_data(stitch_state, scene, 0)) { return stitch_cancel(C, op); @@ -1468,7 +1472,7 @@ static int stitch_modal(bContext *C, wmOperator *op, wmEvent *event) /* Decrease limit */ case PADMINUS: case WHEELDOWNMOUSE: - if (event->alt) { + if (event->val == KM_PRESS && event->alt) { stitch_state->limit_dist -= 0.01f; stitch_state->limit_dist = MAX2(0.01f, stitch_state->limit_dist); if (!stitch_process_data(stitch_state, scene, 0)) { diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index f615902eedf..efe9d1fedfe 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -1089,7 +1089,7 @@ static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOper BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV); - DO_MINMAX2(luv->uv, min, max); + minmax_v2v2_v2(min, max, luv->uv); } } @@ -1414,7 +1414,7 @@ static void uv_map_mirror(BMEditMesh *em, BMFace *efa, MTexPoly *UNUSED(tf)) BMIter liter; MLoopUV *luv; float **uvs = NULL; - BLI_array_fixedstack_declare(uvs, BM_NGON_STACK_SIZE, efa->len, __func__); + BLI_array_fixedstack_declare(uvs, BM_DEFAULT_NGON_STACK_SIZE, efa->len, __func__); float dx; int i, mi; diff --git a/source/blender/gpu/SConscript b/source/blender/gpu/SConscript index f7ed9effc7a..9b8a86eac15 100644 --- a/source/blender/gpu/SConscript +++ b/source/blender/gpu/SConscript @@ -27,7 +27,6 @@ sources.extend(( os.path.join(env['DATA_SOURCES'], "gpu_shader_vertex.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_frag.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_vert.glsl.c"), - os.path.join(env['DATA_SOURCES'], "gpu_shader_material.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_vsm_store_frag.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_vsm_store_vert.glsl.c"), )) diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 53a51c9c9fd..b89f0196794 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -327,7 +327,7 @@ static void gpu_make_repbind(Image *ima) { ImBuf *ibuf; - ibuf = BKE_image_get_ibuf(ima, NULL); + ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (ibuf==NULL) return; @@ -342,6 +342,8 @@ static void gpu_make_repbind(Image *ima) if (ima->totbind>1) ima->repbind= MEM_callocN(sizeof(int)*ima->totbind, "repbind"); + + BKE_image_release_ibuf(ima, ibuf, NULL); } static void reset_default_alphablend_state(void); @@ -586,7 +588,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int return 0; /* check if we have a valid image buffer */ - ibuf= BKE_image_get_ibuf(ima, iuser); + ibuf= BKE_image_acquire_ibuf(ima, iuser, NULL); if (ibuf==NULL) return 0; @@ -682,6 +684,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int /* enable opengl drawing with textures */ #include REAL_GL_MODE glBindTexture(GL_TEXTURE_2D, *bind); + BKE_image_release_ibuf(ima, ibuf, NULL); return *bind; } @@ -743,6 +746,8 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int if (srgb_frect) MEM_freeN(srgb_frect); + BKE_image_release_ibuf(ima, ibuf, NULL); + return *bind; } @@ -997,7 +1002,7 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h) { ImBuf *ibuf; - ibuf = BKE_image_get_ibuf(ima, NULL); + ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); if (ima->repbind || (GPU_get_mipmap() && !GTS.gpu_mipmap) || !ima->bindcode || !ibuf || (!is_power_of_2_i(ibuf->x) || !is_power_of_2_i(ibuf->y)) || @@ -1031,6 +1036,7 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h) ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; } + BKE_image_release_ibuf(ima, ibuf, NULL); return; } @@ -1065,6 +1071,8 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h) ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; } } + + BKE_image_release_ibuf(ima, ibuf, NULL); } #include REAL_GL_MODE diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 1005a60d8b1..ace97215d8d 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -1187,13 +1187,14 @@ static void do_material_tex(GPUShadeInput *shi) // resolve texture resolution if ( (mtex->texflag & MTEX_BUMP_TEXTURESPACE) || found_deriv_map ) { - ImBuf *ibuf= BKE_image_get_ibuf(tex->ima, &tex->iuser); + ImBuf *ibuf= BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); ima_x= 512.0f; ima_y= 512.f; // prevent calling textureSize, glsl 1.3 only if (ibuf) { ima_x= ibuf->x; ima_y= ibuf->y; aspect = ((float) ima_y) / ima_x; } + BKE_image_release_ibuf(tex->ima, ibuf, NULL); } // The negate on norfac is done because the diff --git a/source/blender/gpu/shaders/gpu_shader_vertex.glsl b/source/blender/gpu/shaders/gpu_shader_vertex.glsl index a86431bdd7a..574455e42b3 100644 --- a/source/blender/gpu/shaders/gpu_shader_vertex.glsl +++ b/source/blender/gpu/shaders/gpu_shader_vertex.glsl @@ -10,3 +10,11 @@ void main() varnormal = normalize(gl_NormalMatrix * gl_Normal); gl_Position = gl_ProjectionMatrix * co; + // Setting gl_ClipVertex is necessary to get glClipPlane working on NVIDIA graphic cards. + // gl_ClipVertex works only on NVIDIA graphic cards so we have to check with + // __GLSL_CG_DATA_TYPES if a NVIDIA graphic card is used (Cg support). + // gl_ClipVerte is supported up to GLSL 1.20. + #ifdef __GLSL_CG_DATA_TYPES + gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; + #endif + diff --git a/source/blender/ikplugin/intern/ikplugin_api.c b/source/blender/ikplugin/intern/ikplugin_api.c index 9a0878f24ce..efe07b2c48c 100644 --- a/source/blender/ikplugin/intern/ikplugin_api.c +++ b/source/blender/ikplugin/intern/ikplugin_api.c @@ -79,14 +79,14 @@ static IKPlugin ikplugin_tab[] = { itasc_update_param, itasc_test_constraint, }, - #endif +#endif { NULL } }; static IKPlugin *get_plugin(bPose *pose) { - if (!pose || pose->iksolver < 0 || pose->iksolver >= (sizeof(ikplugin_tab) / sizeof(IKPlugin))) + if (!pose || pose->iksolver < 0 || pose->iksolver > (sizeof(ikplugin_tab)/sizeof(IKPlugin) - 2)) return NULL; return &ikplugin_tab[pose->iksolver]; diff --git a/source/blender/ikplugin/intern/iksolver_plugin.c b/source/blender/ikplugin/intern/iksolver_plugin.c index af15333ece5..ca81f4c915a 100644 --- a/source/blender/ikplugin/intern/iksolver_plugin.c +++ b/source/blender/ikplugin/intern/iksolver_plugin.c @@ -379,6 +379,7 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree) copy_v3_v3(goalpos, goal[3]); copy_m3_m4(goalrot, goal); + normalize_m3(goalrot); /* same for pole vector target */ if (data->poletar) { @@ -433,7 +434,7 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree) iktarget = iktree[target->tip]; - if (data->weight != 0.0f) { + if ((data->flag & CONSTRAINT_IK_POS) && data->weight != 0.0f) { if (poleconstrain) IK_SolverSetPoleVectorConstraint(solver, iktarget, goalpos, polepos, data->poleangle, (poleangledata == data)); diff --git a/source/blender/imbuf/intern/cineon/cineon_dpx.c b/source/blender/imbuf/intern/cineon/cineon_dpx.c index d20c6dec9d3..c8bc3f8ebb8 100644 --- a/source/blender/imbuf/intern/cineon/cineon_dpx.c +++ b/source/blender/imbuf/intern/cineon/cineon_dpx.c @@ -139,9 +139,19 @@ static int imb_save_dpx_cineon(ImBuf *ibuf, const char *filename, int use_cineon if (ibuf->rect_float != 0 && bitspersample != 8) { /* don't use the float buffer to save 8 bpp picture to prevent color banding (there's no dithering algorithm behing the logImageSetDataRGBA function) */ - IMB_flipy(ibuf); - rvalue = (logImageSetDataRGBA(logImage, ibuf->rect_float, 1) == 0); - IMB_flipy(ibuf); + + fbuf = (float *)MEM_mallocN(ibuf->x * ibuf->y * 4 * sizeof(float), "fbuf in imb_save_dpx_cineon"); + + for (y = 0; y < ibuf->y; y++) { + float *dst_ptr = fbuf + 4 * ((ibuf->y - y - 1) * ibuf->x); + float *src_ptr = ibuf->rect_float + 4 * (y * ibuf->x); + + memcpy(dst_ptr, src_ptr, 4 * ibuf->x * sizeof(float)); + } + + rvalue = (logImageSetDataRGBA(logImage, fbuf, 1) == 0); + + MEM_freeN(fbuf); } else { if (ibuf->rect == 0) diff --git a/source/blender/imbuf/intern/cineon/cineonlib.c b/source/blender/imbuf/intern/cineon/cineonlib.c index 9926d8c8562..3049a5be514 100644 --- a/source/blender/imbuf/intern/cineon/cineonlib.c +++ b/source/blender/imbuf/intern/cineon/cineonlib.c @@ -188,7 +188,7 @@ LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t } else { if (verbose) printf("Cineon: Bad magic number %lu in \"%s\".\n", - (uintptr_t)header.fileHeader.magic_num, byteStuff); + (unsigned long)header.fileHeader.magic_num, byteStuff); logImageClose(cineon); return 0; } diff --git a/source/blender/imbuf/intern/cineon/dpxlib.c b/source/blender/imbuf/intern/cineon/dpxlib.c index aedce52a7bf..4c9b5e620dd 100644 --- a/source/blender/imbuf/intern/cineon/dpxlib.c +++ b/source/blender/imbuf/intern/cineon/dpxlib.c @@ -457,7 +457,7 @@ LogImageFile *dpxCreate(const char *filename, int width, int height, int bitsPer } /* Header should be rounded to next 8k block - 6044 = 8092 - sizeof(DpxMainHeader) */ + * 6044 = 8092 - sizeof(DpxMainHeader) */ memset(&pad, 0, 6044); if (fwrite(&pad, 6044, 1, dpx->file) == 0) { if (verbose) printf("DPX: Couldn't write image header\n"); diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index b9774a9f7b0..1c68a466ade 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -164,7 +164,7 @@ typedef struct ColormanageProcessor { * but they holds indexes of all transformations and color spaces, not * their names. * - * This helps avoid extra colorsmace / display / view lookup without + * This helps avoid extra colorspace / display / view lookup without * requiring to pass all variables which affects on display buffer * to color management cache system and keeps calls small and nice. */ @@ -2465,7 +2465,8 @@ ColormanageProcessor *IMB_colormanagement_display_processor_new(const ColorManag } display_space = display_transform_get_colorspace(applied_view_settings, display_settings); - cm_processor->is_data_result = display_space->is_data; + if (display_space) + cm_processor->is_data_result = display_space->is_data; cm_processor->processor = create_display_buffer_processor(applied_view_settings->view_transform, display_settings->display_device, applied_view_settings->exposure, applied_view_settings->gamma); diff --git a/source/blender/imbuf/intern/dds/BlockDXT.h b/source/blender/imbuf/intern/dds/BlockDXT.h index 0291816cd03..7e5a1e504b8 100644 --- a/source/blender/imbuf/intern/dds/BlockDXT.h +++ b/source/blender/imbuf/intern/dds/BlockDXT.h @@ -147,7 +147,7 @@ struct BlockDXT3 struct AlphaBlockDXT5 { // uint64 unions do not compile on all platforms - /* +#if 0 union { struct { uint64 alpha0 : 8; // 8 @@ -171,7 +171,7 @@ struct AlphaBlockDXT5 }; uint64 u; }; - */ +#endif uint64 u; uint8 alpha0() const { return u & 0xffLL; } uint8 alpha1() const { return (u >> 8) & 0xffLL; } diff --git a/source/blender/imbuf/intern/dds/SConscript b/source/blender/imbuf/intern/dds/SConscript index d5a613f5981..475d21135aa 100644 --- a/source/blender/imbuf/intern/dds/SConscript +++ b/source/blender/imbuf/intern/dds/SConscript @@ -3,16 +3,17 @@ Import ('env') source_files = ['dds_api.cpp', 'DirectDrawSurface.cpp', 'Stream.cpp', 'BlockDXT.cpp', 'ColorBlock.cpp', 'Image.cpp', 'FlipDXT.cpp'] -incs = ['.', - '../../', - '../..', +incs = [ + '.', '..', + '../..', '../../../makesdna', '../../../blenkernel', '../../../blenlib', 'intern/include', '#/intern/guardedalloc', - '#/intern/utfconv'] + '#/intern/utfconv' + ] defs = ['WITH_DDS'] diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c index 57fbce710a1..a185c4ee3e0 100644 --- a/source/blender/imbuf/intern/imageprocess.c +++ b/source/blender/imbuf/intern/imageprocess.c @@ -43,6 +43,7 @@ #include "BLI_utildefines.h" #include "BLI_threads.h" #include "BLI_listbase.h" +#include "BLI_math.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -95,132 +96,15 @@ static void pixel_from_buffer(struct ImBuf *ibuf, unsigned char **outI, float ** *outF = ibuf->rect_float + offset; } -/************************************************************************** - * INTERPOLATIONS - * - * Reference and docs: - * http://wiki.blender.org/index.php/User:Damiles#Interpolations_Algorithms - ***************************************************************************/ - -/* BICUBIC Interpolation functions - * More info: http://wiki.blender.org/index.php/User:Damiles#Bicubic_pixel_interpolation - * function assumes out to be zero'ed, only does RGBA */ - -static float P(float k) -{ - float p1, p2, p3, p4; - p1 = MAX2(k + 2.0f, 0); - p2 = MAX2(k + 1.0f, 0); - p3 = MAX2(k, 0); - p4 = MAX2(k - 1.0f, 0); - return (float)(1.0f / 6.0f) * (p1 * p1 * p1 - 4.0f * p2 * p2 * p2 + 6.0f * p3 * p3 * p3 - 4.0f * p4 * p4 * p4); -} - - -#if 0 -/* older, slower function, works the same as above */ -static float P(float k) -{ - return (float)(1.0f / 6.0f) * (pow(MAX2(k + 2.0f, 0), 3.0f) - 4.0f * pow(MAX2(k + 1.0f, 0), 3.0f) + 6.0f * pow(MAX2(k, 0), 3.0f) - 4.0f * pow(MAX2(k - 1.0f, 0), 3.0f)); -} -#endif +/* BICUBIC Interpolation */ void bicubic_interpolation_color(struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) { - int i, j, n, m, x1, y1; - unsigned char *dataI; - float a, b, w, wx, wy[4], outR, outG, outB, outA, *dataF; - - /* sample area entirely outside image? */ - if (ceil(u) < 0 || floor(u) > in->x - 1 || ceil(v) < 0 || floor(v) > in->y - 1) { - return; - } - - /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ - - i = (int)floor(u); - j = (int)floor(v); - a = u - i; - b = v - j; - - outR = outG = outB = outA = 0.0f; - -/* Optimized and not so easy to read */ - - /* avoid calling multiple times */ - wy[0] = P(b - (-1)); - wy[1] = P(b - 0); - wy[2] = P(b - 1); - wy[3] = P(b - 2); - - for (n = -1; n <= 2; n++) { - x1 = i + n; - CLAMP(x1, 0, in->x - 1); - wx = P(n - a); - for (m = -1; m <= 2; m++) { - y1 = j + m; - CLAMP(y1, 0, in->y - 1); - /* normally we could do this */ - /* w = P(n-a) * P(b-m); */ - /* except that would call P() 16 times per pixel therefor pow() 64 times, better precalc these */ - w = wx * wy[m + 1]; - - if (outF) { - dataF = in->rect_float + in->x * y1 * 4 + 4 * x1; - outR += dataF[0] * w; - outG += dataF[1] * w; - outB += dataF[2] * w; - outA += dataF[3] * w; - } - if (outI) { - dataI = (unsigned char *)in->rect + in->x * y1 * 4 + 4 * x1; - outR += dataI[0] * w; - outG += dataI[1] * w; - outB += dataI[2] * w; - outA += dataI[3] * w; - } - } - } - -/* Done with optimized part */ - -#if 0 - /* older, slower function, works the same as above */ - for (n = -1; n <= 2; n++) { - for (m = -1; m <= 2; m++) { - x1 = i + n; - y1 = j + m; - if (x1 > 0 && x1 < in->x && y1 > 0 && y1 < in->y) { - if (do_float) { - dataF = in->rect_float + in->x * y1 * 4 + 4 * x1; - outR += dataF[0] * P(n - a) * P(b - m); - outG += dataF[1] * P(n - a) * P(b - m); - outB += dataF[2] * P(n - a) * P(b - m); - outA += dataF[3] * P(n - a) * P(b - m); - } - if (do_rect) { - dataI = (unsigned char *)in->rect + in->x * y1 * 4 + 4 * x1; - outR += dataI[0] * P(n - a) * P(b - m); - outG += dataI[1] * P(n - a) * P(b - m); - outB += dataI[2] * P(n - a) * P(b - m); - outA += dataI[3] * P(n - a) * P(b - m); - } - } - } - } -#endif - - if (outI) { - outI[0] = (int)outR; - outI[1] = (int)outG; - outI[2] = (int)outB; - outI[3] = (int)outA; - } if (outF) { - outF[0] = outR; - outF[1] = outG; - outF[2] = outB; - outF[3] = outA; + BLI_bicubic_interpolation_fl(in->rect_float, outF, in->x, in->y, 4, u, v); + } + else { + BLI_bicubic_interpolation_char((unsigned char*) in->rect, outI, in->x, in->y, 4, u, v); } } @@ -239,77 +123,14 @@ void bicubic_interpolation(ImBuf *in, ImBuf *out, float u, float v, int xout, in bicubic_interpolation_color(in, outI, outF, u, v); } -/* function assumes out to be zero'ed, only does RGBA */ /* BILINEAR INTERPOLATION */ void bilinear_interpolation_color(struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) { - float *row1, *row2, *row3, *row4, a, b; - unsigned char *row1I, *row2I, *row3I, *row4I; - float a_b, ma_b, a_mb, ma_mb; - float empty[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - unsigned char emptyI[4] = {0, 0, 0, 0}; - int y1, y2, x1, x2; - - - /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ - - x1 = (int)floor(u); - x2 = (int)ceil(u); - y1 = (int)floor(v); - y2 = (int)ceil(v); - - /* sample area entirely outside image? */ - if (x2 < 0 || x1 > in->x - 1 || y2 < 0 || y1 > in->y - 1) { - return; - } - if (outF) { - /* sample including outside of edges of image */ - if (x1 < 0 || y1 < 0) row1 = empty; - else row1 = in->rect_float + in->x * y1 * 4 + 4 * x1; - - if (x1 < 0 || y2 > in->y - 1) row2 = empty; - else row2 = in->rect_float + in->x * y2 * 4 + 4 * x1; - - if (x2 > in->x - 1 || y1 < 0) row3 = empty; - else row3 = in->rect_float + in->x * y1 * 4 + 4 * x2; - - if (x2 > in->x - 1 || y2 > in->y - 1) row4 = empty; - else row4 = in->rect_float + in->x * y2 * 4 + 4 * x2; - - a = u - floorf(u); - b = v - floorf(v); - a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b); - - outF[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; - outF[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; - outF[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; - outF[3] = ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3]; + BLI_bilinear_interpolation_fl(in->rect_float, outF, in->x, in->y, 4, u, v); } - if (outI) { - /* sample including outside of edges of image */ - if (x1 < 0 || y1 < 0) row1I = emptyI; - else row1I = (unsigned char *)in->rect + in->x * y1 * 4 + 4 * x1; - - if (x1 < 0 || y2 > in->y - 1) row2I = emptyI; - else row2I = (unsigned char *)in->rect + in->x * y2 * 4 + 4 * x1; - - if (x2 > in->x - 1 || y1 < 0) row3I = emptyI; - else row3I = (unsigned char *)in->rect + in->x * y1 * 4 + 4 * x2; - - if (x2 > in->x - 1 || y2 > in->y - 1) row4I = emptyI; - else row4I = (unsigned char *)in->rect + in->x * y2 * 4 + 4 * x2; - - a = u - floorf(u); - b = v - floorf(v); - a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b); - - /* need to add 0.5 to avoid rounding down (causes darken with the smear brush) - * tested with white images and this should not wrap back to zero */ - outI[0] = (ma_mb * row1I[0] + a_mb * row3I[0] + ma_b * row2I[0] + a_b * row4I[0]) + 0.5f; - outI[1] = (ma_mb * row1I[1] + a_mb * row3I[1] + ma_b * row2I[1] + a_b * row4I[1]) + 0.5f; - outI[2] = (ma_mb * row1I[2] + a_mb * row3I[2] + ma_b * row2I[2] + a_b * row4I[2]) + 0.5f; - outI[3] = (ma_mb * row1I[3] + a_mb * row3I[3] + ma_b * row2I[3] + a_b * row4I[3]) + 0.5f; + else { + BLI_bilinear_interpolation_char((unsigned char*) in->rect, outI, in->x, in->y, 4, u, v); } } diff --git a/source/blender/imbuf/intern/jp2.c b/source/blender/imbuf/intern/jp2.c index d94f6368298..3a2bf99c75c 100644 --- a/source/blender/imbuf/intern/jp2.c +++ b/source/blender/imbuf/intern/jp2.c @@ -387,8 +387,8 @@ BLI_INLINE int DOWNSAMPLE_FLOAT_TO_16BIT(const float _val) /* * 2048x1080 (2K) at 24 fps or 48 fps, or 4096x2160 (4K) at 24 fps; 3x12 bits per pixel, XYZ color space * - * - In 2K, for Scope (2.39:1) presentation 2048x858 pixels of the imager is used - * - In 2K, for Flat (1.85:1) presentation 1998x1080 pixels of the imager is used + * - In 2K, for Scope (2.39:1) presentation 2048x858 pixels of the image is used + * - In 2K, for Flat (1.85:1) presentation 1998x1080 pixels of the image is used */ /* ****************************** COPIED FROM image_to_j2k.c */ diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c index d96a01d7093..758617bdd48 100644 --- a/source/blender/imbuf/intern/jpeg.c +++ b/source/blender/imbuf/intern/jpeg.c @@ -348,25 +348,12 @@ static ImBuf *ibJpegImageFromCinfo(struct jpeg_decompress_struct *cinfo, int fla g = *buffer++; b = *buffer++; k = *buffer++; - - k = 255 - k; - r -= k; - if (r & 0xffffff00) { - if (r < 0) r = 0; - else r = 255; - } - g -= k; - if (g & 0xffffff00) { - if (g < 0) g = 0; - else g = 255; - } - b -= k; - if (b & 0xffffff00) { - if (b < 0) b = 0; - else b = 255; - } - - rect[3] = 255 - k; + + r = (r * k) / 255; + g = (g * k) / 255; + b = (b * k) / 255; + + rect[3] = 255; rect[2] = b; rect[1] = g; rect[0] = r; diff --git a/source/blender/imbuf/intern/openexr/CMakeLists.txt b/source/blender/imbuf/intern/openexr/CMakeLists.txt index d5cb8e8a3b6..6c428afe535 100644 --- a/source/blender/imbuf/intern/openexr/CMakeLists.txt +++ b/source/blender/imbuf/intern/openexr/CMakeLists.txt @@ -52,4 +52,6 @@ if(WITH_IMAGE_OPENEXR) add_definitions(-DWITH_OPENEXR) endif() +message(STATUS "EXR ${INC_SYS}") + blender_add_lib(bf_imbuf_openexr "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 60c6e184070..da7b31cc2ba 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -72,21 +72,6 @@ _CRTIMP void __cdecl _invalid_parameter_noinfo(void) #include <iostream> -#if defined(_WIN32) && !defined(FREE_WINDOWS) -#include <half.h> -#include <Iex/Iex.h> -#include <IlmImf/ImfVersion.h> -#include <IlmImf/ImfArray.h> -#include <IlmImf/ImfIO.h> -#include <IlmImf/ImfChannelList.h> -#include <IlmImf/ImfPixelType.h> -#include <IlmImf/ImfInputFile.h> -#include <IlmImf/ImfOutputFile.h> -#include <IlmImf/ImfCompression.h> -#include <IlmImf/ImfCompressionAttribute.h> -#include <IlmImf/ImfStringAttribute.h> -#include <Imath/ImathBox.h> -#else #include <half.h> #include <Iex.h> #include <ImfVersion.h> @@ -100,7 +85,6 @@ _CRTIMP void __cdecl _invalid_parameter_noinfo(void) #include <ImfCompression.h> #include <ImfCompressionAttribute.h> #include <ImfStringAttribute.h> -#endif using namespace Imf; using namespace Imath; @@ -881,7 +865,7 @@ void IMB_exr_close(void *handle) /* get a substring from the end of the name, separated by '.' */ static int imb_exr_split_token(const char *str, const char *end, const char **token) { - int maxlen = end - str; + ptrdiff_t maxlen = end - str; int len = 0; while (len < maxlen && *(end - len - 1) != '.') { len++; @@ -1183,7 +1167,7 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char frameBuffer.insert(exr_rgba_channelname(file, "B"), Slice(Imf::FLOAT, (char *) (first + 2), xstride, ystride)); - /* 1.0 is fill value, this still neesd to be assigned even when (is_alpha == 0) */ + /* 1.0 is fill value, this still needs to be assigned even when (is_alpha == 0) */ frameBuffer.insert(exr_rgba_channelname(file, "A"), Slice(Imf::FLOAT, (char *) (first + 3), xstride, ystride, 1, 1, 1.0f)); diff --git a/source/blender/imbuf/intern/openexr/openexr_multi.h b/source/blender/imbuf/intern/openexr/openexr_multi.h index 78071975c72..376d2401b1c 100644 --- a/source/blender/imbuf/intern/openexr/openexr_multi.h +++ b/source/blender/imbuf/intern/openexr/openexr_multi.h @@ -35,10 +35,10 @@ /* experiment with more advanced exr api */ -/* Note: as for now openexr only supports 32 chars in channel names. - * This api also supports max 8 channels per pass now. easy to fix! */ -#define EXR_LAY_MAXNAME 51 -#define EXR_PASS_MAXNAME 11 +/* XXX layer+pass name max 64? */ +/* This api also supports max 8 channels per pass now. easy to fix! */ +#define EXR_LAY_MAXNAME 64 +#define EXR_PASS_MAXNAME 64 #define EXR_TOT_MAXNAME 64 #define EXR_PASS_MAXCHAN 8 diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c index b9525ccccf1..1e701b8d615 100644 --- a/source/blender/imbuf/intern/scaling.c +++ b/source/blender/imbuf/intern/scaling.c @@ -1467,10 +1467,10 @@ struct ImBuf *IMB_scaleImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int return ibuf; } - if (newx < ibuf->x) if (newx) scaledownx(ibuf, newx); - if (newy < ibuf->y) if (newy) scaledowny(ibuf, newy); - if (newx > ibuf->x) if (newx) scaleupx(ibuf, newx); - if (newy > ibuf->y) if (newy) scaleupy(ibuf, newy); + if (newx && (newx < ibuf->x)) scaledownx(ibuf, newx); + if (newy && (newy < ibuf->y)) scaledowny(ibuf, newy); + if (newx && (newx > ibuf->x)) scaleupx(ibuf, newx); + if (newy && (newy > ibuf->y)) scaleupy(ibuf, newy); return(ibuf); } diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c index fe138a71a4a..42fb0c79b62 100644 --- a/source/blender/imbuf/intern/util.c +++ b/source/blender/imbuf/intern/util.c @@ -228,16 +228,27 @@ static int isqtime(const char *name) #ifdef WITH_FFMPEG +#ifdef _MSC_VER +#define va_copy(dst, src) ((dst) = (src)) +#endif + /* BLI_vsnprintf in ffmpeg_log_callback() causes invalid warning */ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmissing-format-attribute" +#ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wmissing-format-attribute" +#endif static char ffmpeg_last_error[1024]; static void ffmpeg_log_callback(void *ptr, int level, const char *format, va_list arg) { if (ELEM(level, AV_LOG_FATAL, AV_LOG_ERROR)) { - size_t n = BLI_vsnprintf(ffmpeg_last_error, sizeof(ffmpeg_last_error), format, arg); + size_t n; + va_list arg2; + + va_copy(arg2, arg); + + n = BLI_vsnprintf(ffmpeg_last_error, sizeof(ffmpeg_last_error), format, arg2); /* strip trailing \n */ ffmpeg_last_error[n - 1] = '\0'; @@ -249,7 +260,9 @@ static void ffmpeg_log_callback(void *ptr, int level, const char *format, va_lis } } -#pragma GCC diagnostic pop +#ifdef __GNUC__ +# pragma GCC diagnostic pop +#endif void IMB_ffmpeg_init(void) { diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index d8d1ad78451..f227af78dab 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -372,7 +372,7 @@ typedef enum ePose_Flags { /* bPose->iksolver and bPose->ikparam->iksolver */ typedef enum ePose_IKSolverType { - IKSOLVER_LEGACY = 0, + IKSOLVER_STANDARD = 0, IKSOLVER_ITASC = 1 } ePose_IKSolverType; diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index 100968e7257..b64fc08a47a 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -41,6 +41,7 @@ typedef struct bGPDspoint { float x, y, z; /* co-ordinates of point (usually 2d, but can be 3d as well) */ float pressure; /* pressure of input device (from 0 to 1) at this point */ + float time; /* seconds since start of stroke */ } bGPDspoint; /* Grease-Pencil Annotations - 'Stroke' @@ -49,12 +50,14 @@ typedef struct bGPDspoint { */ typedef struct bGPDstroke { struct bGPDstroke *next, *prev; - bGPDspoint *points; /* array of data-points for stroke */ + void *pad; /* keep 4 pointers at the beginning, padding for 'inittime' is tricky 64/32bit */ int totpoints; /* number of data-points in array */ short thickness; /* thickness of stroke (currently not used) */ short flag; /* various settings about this stroke */ + + double inittime; /* Init time of stroke */ } bGPDstroke; /* bGPDstroke->flag */ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 2c896e4893f..3875a0d5799 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -76,6 +76,7 @@ typedef enum ModifierType { eModifierType_Remesh = 41, eModifierType_Skin = 42, eModifierType_LaplacianSmooth = 43, + eModifierType_Triangulate = 44, NUM_MODIFIER_TYPES } ModifierType; @@ -1114,11 +1115,23 @@ enum { MOD_SKIN_SMOOTH_SHADING = 1 }; +/* Triangulate modifier */ + +typedef struct TriangulateModifierData { + ModifierData modifier; + int flag; + int pad; +} TriangulateModifierData; + +enum { + MOD_TRIANGULATE_BEAUTY = (1 << 0), +}; + /* Smooth modifier flags */ #define MOD_LAPLACIANSMOOTH_X (1<<1) #define MOD_LAPLACIANSMOOTH_Y (1<<2) #define MOD_LAPLACIANSMOOTH_Z (1<<3) -#define MOD_LAPLACIANSMOOTH_VOLUME_PRESERVATION (1<<4) +#define MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME (1 << 4) typedef struct LaplacianSmoothModifierData { ModifierData modifier; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 9dc4480fc35..a5af4234503 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1200,7 +1200,8 @@ typedef struct Scene { #define R_NO_OVERWRITE 0x400000 /* skip existing files */ #define R_TOUCH 0x800000 /* touch files before rendering */ #define R_SIMPLIFY 0x1000000 -#define R_PERSISTENT_DATA 0x2000000 /* keep data around for re-render */ +#define R_EDGE_FRS 0x2000000 /* R_EDGE reserved for Freestyle */ +#define R_PERSISTENT_DATA 0x4000000 /* keep data around for re-render */ /* seq_flag */ #define R_SEQ_GL_PREV 1 @@ -1453,9 +1454,9 @@ typedef struct Scene { /* Paint.flags */ typedef enum { - PAINT_SHOW_BRUSH = (1<<0), - PAINT_FAST_NAVIGATE = (1<<1), - PAINT_SHOW_BRUSH_ON_SURFACE = (1<<2), + PAINT_SHOW_BRUSH = (1 << 0), + PAINT_FAST_NAVIGATE = (1 << 1), + PAINT_SHOW_BRUSH_ON_SURFACE = (1 << 2), } PaintFlags; /* Sculpt.flags */ diff --git a/source/blender/makesdna/DNA_text_types.h b/source/blender/makesdna/DNA_text_types.h index cf26dae402d..6ce883905d4 100644 --- a/source/blender/makesdna/DNA_text_types.h +++ b/source/blender/makesdna/DNA_text_types.h @@ -44,15 +44,6 @@ typedef struct TextLine { int len, blen; /* blen unused */ } TextLine; -typedef struct TextMarker { - struct TextMarker *next, *prev; - - int lineno, start, end, pad1; /* line number and start/end character indices */ - - int group, flags; /* see BKE_text.h for flag defines */ - unsigned char color[4], pad[4]; /* draw color of the marker */ -} TextMarker; - typedef struct Text { ID id; @@ -63,7 +54,6 @@ typedef struct Text { ListBase lines; TextLine *curl, *sell; int curc, selc; - ListBase markers; char *undo_buf; int undo_pos, undo_len; @@ -78,7 +68,6 @@ typedef struct Text { /* text flags */ #define TXT_ISDIRTY 0x0001 -#define TXT_DEPRECATED 0x0004 /* deprecated ISTMP flag */ #define TXT_ISMEM 0x0004 #define TXT_ISEXT 0x0008 #define TXT_ISSCRIPT 0x0010 /* used by space handler scriptlinks */ diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index 9c80d30bca4..12819303b26 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -163,7 +163,7 @@ typedef struct MovieTrackingSettings { /* ** reconstruction settings ** */ int keyframe1 DNA_DEPRECATED, - keyframe2 DNA_DEPRECATED; /* two keyframes for reconstrution initialization + keyframe2 DNA_DEPRECATED; /* two keyframes for reconstruction initialization * were moved to per-tracking object settings */ @@ -228,7 +228,7 @@ typedef struct MovieTrackingObject { MovieTrackingReconstruction reconstruction; /* reconstruction data for this object */ /* reconstruction options */ - int keyframe1, keyframe2; /* two keyframes for reconstrution initialization */ + int keyframe1, keyframe2; /* two keyframes for reconstruction initialization */ } MovieTrackingObject; typedef struct MovieTrackingStats { diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 69e67461a56..2e2f65dbec7 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -600,7 +600,7 @@ typedef enum eOpenGL_RenderingOptions { /* backwards compatibilty in do_versions! */ USER_DISABLE_MIPMAP = (1 << 2), USER_DISABLE_VBO = (1 << 3), - USER_DISABLE_AA = (1 << 4), + /* USER_DISABLE_AA = (1 << 4), */ /* DEPRECATED */ } eOpenGL_RenderingOptions; /* wm draw method */ diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 5f667db4425..2b68cc8bdc1 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -148,6 +148,7 @@ extern StructRNA RNA_CompositorNodeLevels; extern StructRNA RNA_CompositorNodeLumaMatte; extern StructRNA RNA_CompositorNodeMapUV; extern StructRNA RNA_CompositorNodeMapValue; +extern StructRNA RNA_CompositorNodeMapRange; extern StructRNA RNA_CompositorNodeMath; extern StructRNA RNA_CompositorNodeMask; extern StructRNA RNA_CompositorNodeMixRGB; @@ -525,7 +526,6 @@ extern StructRNA RNA_TextBox; extern StructRNA RNA_TextCharacterFormat; extern StructRNA RNA_TextCurve; extern StructRNA RNA_TextLine; -extern StructRNA RNA_TextMarker; extern StructRNA RNA_Texture; extern StructRNA RNA_TextureNode; extern StructRNA RNA_TextureNodeBricks; @@ -1053,6 +1053,11 @@ __attribute__ ((format(printf, 1, 2))) #endif ; +/* Equals test (skips pointers and collections) */ + +int RNA_property_equals(struct PointerRNA *a, struct PointerRNA *b, struct PropertyRNA *prop); +int RNA_struct_equals(struct PointerRNA *a, struct PointerRNA *b); + #ifdef __cplusplus } #endif diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 7a3bb230a78..9b1a947941c 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -1223,6 +1223,89 @@ static char *rna_def_property_lookup_int_func(FILE *f, StructRNA *srna, Property return func; } +static char *rna_def_property_lookup_string_func(FILE *f, StructRNA *srna, PropertyRNA *prop, PropertyDefRNA *dp, + const char *manualfunc, const char *item_type) +{ + char *func; + StructRNA *item_srna, *item_name_base; + PropertyRNA *item_name_prop; + const int namebuflen = 1024; + + if (prop->flag & PROP_IDPROPERTY && manualfunc == NULL) + return NULL; + + if (!manualfunc) { + if (!dp->dnastructname || !dp->dnaname) + return NULL; + + /* only supported for collection items with name properties */ + item_srna = rna_find_struct(item_type); + if (item_srna && item_srna->nameproperty) { + item_name_prop = item_srna->nameproperty; + item_name_base = item_srna; + while (item_name_base->base && item_name_base->base->nameproperty == item_name_prop) + item_name_base = item_name_base->base; + } + else + return NULL; + } + + func = rna_alloc_function_name(srna->identifier, rna_safe_id(prop->identifier), "lookup_string"); + + fprintf(f, "int %s(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)\n", func); + fprintf(f, "{\n"); + + if (manualfunc) { + fprintf(f, " return %s(ptr, key, r_ptr);\n", manualfunc); + fprintf(f, "}\n\n"); + return func; + } + + /* XXX extern declaration could be avoid by including RNA_blender.h, but this has lots of unknown + * DNA types in functions, leading to conflicting function signatures. + */ + fprintf(f, " extern int %s_%s_length(PointerRNA *);\n", item_name_base->identifier, rna_safe_id(item_name_prop->identifier)); + fprintf(f, " extern void %s_%s_get(PointerRNA *, char *);\n\n", item_name_base->identifier, rna_safe_id(item_name_prop->identifier)); + + fprintf(f, " int found= 0;\n"); + fprintf(f, " CollectionPropertyIterator iter;\n"); + fprintf(f, " char namebuf[%d];\n", namebuflen); + fprintf(f, " char *name;\n\n"); + + fprintf(f, " %s_%s_begin(&iter, ptr);\n\n", srna->identifier, rna_safe_id(prop->identifier)); + + fprintf(f, " while (iter.valid) {\n"); + fprintf(f, " int namelen = %s_%s_length(&iter.ptr);\n", item_name_base->identifier, rna_safe_id(item_name_prop->identifier)); + fprintf(f, " if (namelen < %d) {\n", namebuflen); + fprintf(f, " %s_%s_get(&iter.ptr, namebuf);\n", item_name_base->identifier, rna_safe_id(item_name_prop->identifier)); + fprintf(f, " if (strcmp(namebuf, key) == 0) {\n"); + fprintf(f, " found = 1;\n"); + fprintf(f, " *r_ptr = iter.ptr;\n"); + fprintf(f, " break;\n"); + fprintf(f, " }\n"); + fprintf(f, " }\n"); + fprintf(f, " else {\n"); + fprintf(f, " name = MEM_mallocN(namelen+1, \"name string\");\n"); + fprintf(f, " %s_%s_get(&iter.ptr, name);\n", item_name_base->identifier, rna_safe_id(item_name_prop->identifier)); + fprintf(f, " if (strcmp(name, key) == 0) {\n"); + fprintf(f, " MEM_freeN(name);\n\n"); + fprintf(f, " found = 1;\n"); + fprintf(f, " *r_ptr = iter.ptr;\n"); + fprintf(f, " break;\n"); + fprintf(f, " }\n"); + fprintf(f, " else\n"); + fprintf(f, " MEM_freeN(name);\n"); + fprintf(f, " }\n"); + fprintf(f, " %s_%s_next(&iter);\n", srna->identifier, rna_safe_id(prop->identifier)); + fprintf(f, " }\n"); + fprintf(f, " %s_%s_end(&iter);\n\n", srna->identifier, rna_safe_id(prop->identifier)); + + fprintf(f, " return found;\n"); + fprintf(f, "}\n\n"); + + return func; +} + static char *rna_def_property_next_func(FILE *f, StructRNA *srna, PropertyRNA *prop, PropertyDefRNA *UNUSED(dp), const char *manualfunc) { @@ -1403,6 +1486,7 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp) { CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop; const char *nextfunc = (const char *)cprop->next; + const char *item_type = (const char *)cprop->item_type; if (dp->dnatype && strcmp(dp->dnatype, "ListBase") == 0) { /* pass */ @@ -1426,6 +1510,8 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp) cprop->end = (void *)rna_def_property_end_func(f, srna, prop, dp, (const char *)cprop->end); cprop->lookupint = (void *)rna_def_property_lookup_int_func(f, srna, prop, dp, (const char *)cprop->lookupint, nextfunc); + cprop->lookupstring = (void *)rna_def_property_lookup_string_func(f, srna, prop, dp, + (const char *)cprop->lookupstring, item_type); if (!(prop->flag & PROP_IDPROPERTY)) { if (!cprop->begin) { @@ -3171,6 +3257,8 @@ static void rna_generate(BlenderRNA *brna, FILE *f, const char *filename, const fprintf(f, "#include <string.h>\n\n"); fprintf(f, "#include <stddef.h>\n\n"); + fprintf(f, "#include \"MEM_guardedalloc.h\"\n\n"); + fprintf(f, "#include \"DNA_ID.h\"\n"); fprintf(f, "#include \"DNA_scene_types.h\"\n"); diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 69332dcd250..07febfb85f4 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -1224,10 +1224,10 @@ void RNA_property_enum_items_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA if (prop->translation_context) nitem[i].name = BLF_pgettext(prop->translation_context, nitem[i].name); else - nitem[i].name = BLF_gettext(nitem[i].name); + nitem[i].name = BLF_pgettext(NULL, nitem[i].name); } if (nitem[i].description) - nitem[i].description = BLF_gettext(nitem[i].description); + nitem[i].description = BLF_pgettext(NULL, nitem[i].description); } *item = nitem; @@ -2551,7 +2551,10 @@ PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop) pprop = (PointerPropertyRNA *)prop; /* for groups, data is idprop itself */ - return rna_pointer_inherit_refine(ptr, pprop->type, idprop); + if (pprop->typef) + return rna_pointer_inherit_refine(ptr, pprop->typef(ptr), idprop); + else + return rna_pointer_inherit_refine(ptr, pprop->type, idprop); } else if (pprop->get) { return pprop->get(ptr); @@ -5718,7 +5721,7 @@ int RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, i /* get the length of the array to work with */ len = RNA_property_array_length(ptr, prop); - fromlen = RNA_property_array_length(ptr, prop); + fromlen = RNA_property_array_length(fromptr, prop); if (len != fromlen) return 0; @@ -5832,3 +5835,142 @@ void _RNA_warning(const char *format, ...) } #endif } + +int RNA_property_equals(PointerRNA *a, PointerRNA *b, PropertyRNA *prop) +{ + /* get the length of the array to work with */ + int len = RNA_property_array_length(a, prop); + int fromlen = RNA_property_array_length(b, prop); + + if (len != fromlen) + return 0; + + /* get and set the default values as appropriate for the various types */ + switch (RNA_property_type(prop)) { + case PROP_BOOLEAN: { + if (len) { + int fixed_a[16], fixed_b[16]; + int *array_a, *array_b; + int equals; + + array_a = (len > 16)? MEM_callocN(sizeof(int) * len, "RNA equals"): fixed_a; + array_b = (len > 16)? MEM_callocN(sizeof(int) * len, "RNA equals"): fixed_b; + + RNA_property_boolean_get_array(a, prop, array_a); + RNA_property_boolean_get_array(b, prop, array_b); + + equals = memcmp(array_a, array_b, sizeof(int) * len) == 0; + + if (array_a != fixed_a) MEM_freeN(array_a); + if (array_b != fixed_b) MEM_freeN(array_b); + + return equals; + } + else { + int value = RNA_property_boolean_get(a, prop); + return value == RNA_property_boolean_get(b, prop); + } + } + + case PROP_INT: { + if (len) { + int fixed_a[16], fixed_b[16]; + int *array_a, *array_b; + int equals; + + array_a = (len > 16)? MEM_callocN(sizeof(int) * len, "RNA equals"): fixed_a; + array_b = (len > 16)? MEM_callocN(sizeof(int) * len, "RNA equals"): fixed_b; + + RNA_property_int_get_array(a, prop, array_a); + RNA_property_int_get_array(b, prop, array_b); + + equals = memcmp(array_a, array_b, sizeof(int) * len) == 0; + + if (array_a != fixed_a) MEM_freeN(array_a); + if (array_b != fixed_b) MEM_freeN(array_b); + + return equals; + } + else { + int value = RNA_property_int_get(a, prop); + return value == RNA_property_int_get(b, prop); + } + } + + case PROP_FLOAT: { + if (len) { + float fixed_a[16], fixed_b[16]; + float *array_a, *array_b; + int equals; + + array_a = (len > 16)? MEM_callocN(sizeof(float) * len, "RNA equals"): fixed_a; + array_b = (len > 16)? MEM_callocN(sizeof(float) * len, "RNA equals"): fixed_b; + + RNA_property_float_get_array(a, prop, array_a); + RNA_property_float_get_array(b, prop, array_b); + + equals = memcmp(array_a, array_b, sizeof(float) * len) == 0; + + if (array_a != fixed_a) MEM_freeN(array_a); + if (array_b != fixed_b) MEM_freeN(array_b); + + return equals; + } + else { + float value = RNA_property_float_get(a, prop); + return value == RNA_property_float_get(b, prop); + } + } + + case PROP_ENUM: { + int value = RNA_property_enum_get(a, prop); + return value == RNA_property_enum_get(b, prop); + } + + 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); + char *value_b = RNA_property_string_get_alloc(b, prop, fixed_b, sizeof(fixed_b), &len_b); + int equals = strcmp(value_a, value_b) == 0; + + if (value_a != fixed_a) MEM_freeN(value_a); + if (value_b != fixed_b) MEM_freeN(value_b); + + return equals; + } + + default: + break; + } + + return 1; +} + +int RNA_struct_equals(PointerRNA *a, PointerRNA *b) +{ + CollectionPropertyIterator iter; + CollectionPropertyRNA *citerprop; + PropertyRNA *iterprop; + int equals = 1; + + if (a->type != b->type) + return 0; + + iterprop = RNA_struct_iterator_property(a->type); + citerprop = (CollectionPropertyRNA *)rna_ensure_property(iterprop); + + RNA_property_collection_begin(a, iterprop, &iter); + for (; iter.valid; RNA_property_collection_next(&iter)) { + PropertyRNA *prop = iter.ptr.data; + + if (!RNA_property_equals(a, b, prop)) { + equals = 0; + break; + } + } + RNA_property_collection_end(&iter); + + return equals; +} + diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c index b1fdfccd0be..b653289e44d 100644 --- a/source/blender/makesrna/intern/rna_actuator.c +++ b/source/blender/makesrna/intern/rna_actuator.c @@ -973,13 +973,13 @@ static void rna_def_sound_actuator(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.0, 1.0, 1, 2); RNA_def_property_range(prop, 0.0, 2.0); RNA_def_property_ui_text(prop, "Volume", "Initial volume of the sound"); - RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND); RNA_def_property_update(prop, NC_LOGIC, NULL); prop = RNA_def_property(srna, "pitch", PROP_FLOAT, PROP_NONE); RNA_def_property_ui_range(prop, -12.0, 12.0, 1, 2); RNA_def_property_ui_text(prop, "Pitch", "Pitch of the sound"); - RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND); RNA_def_property_update(prop, NC_LOGIC, NULL); /* floats - 3D Parameters */ diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 7b6b629ca82..30a9bfd81f6 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -614,7 +614,7 @@ static void rna_def_constraint_kinematic(BlenderRNA *brna) RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update"); prop = RNA_def_property(srna, "iterations", PROP_INT, PROP_NONE); - RNA_def_property_range(prop, 1, 10000); + RNA_def_property_range(prop, 0, 10000); RNA_def_property_ui_text(prop, "Iterations", "Maximum number of solving iterations"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c index 1e1a8c82b8e..21aed20ccc3 100644 --- a/source/blender/makesrna/intern/rna_curve.c +++ b/source/blender/makesrna/intern/rna_curve.c @@ -1424,7 +1424,7 @@ static void rna_def_curve(BlenderRNA *brna) prop = RNA_def_property(srna, "use_map_taper", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CU_MAP_TAPER); - RNA_def_property_ui_text(prop, "Map Taper", "Map effect of taper object on actually bevelled curve"); + RNA_def_property_ui_text(prop, "Map Taper", "Map effect of taper object on actually beveled curve"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); /* texture space */ diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index f8af2427827..9fedbee41ff 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -113,7 +113,7 @@ static void rna_Image_fields_update(Main *UNUSED(bmain), Scene *UNUSED(scene), P BKE_image_signal(ima, NULL, IMA_SIGNAL_FREE); } - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); } static void rna_Image_free_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) @@ -187,8 +187,12 @@ static EnumPropertyItem *rna_Image_source_itemf(bContext *UNUSED(C), PointerRNA static int rna_Image_file_format_get(PointerRNA *ptr) { Image *image = (Image *)ptr->data; - ImBuf *ibuf = BKE_image_get_ibuf(image, NULL); - return BKE_ftype_to_imtype(ibuf ? ibuf->ftype : 0); + ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL); + int imtype = BKE_ftype_to_imtype(ibuf ? ibuf->ftype : 0); + + BKE_image_release_ibuf(image, ibuf, NULL); + + return imtype; } static void rna_Image_file_format_set(PointerRNA *ptr, int value) @@ -199,12 +203,13 @@ static void rna_Image_file_format_set(PointerRNA *ptr, int value) int ftype = BKE_imtype_to_ftype(value); #if 0 - ibuf = BKE_image_get_ibuf(image, NULL); + ibuf = BKE_image_acquire_ibuf(image, NULL, NULL); if (ibuf) ibuf->ftype = ftype; #endif /* to be safe change all buffer file types */ + /* TODO: this is never threadsafe */ for (ibuf = image->ibufs.first; ibuf; ibuf = ibuf->next) { ibuf->ftype = ftype; } @@ -237,7 +242,7 @@ static void rna_Image_size_get(PointerRNA *ptr, int *values) values[1] = 0; } - BKE_image_release_ibuf(im, lock); + BKE_image_release_ibuf(im, ibuf, lock); } static void rna_Image_resolution_get(PointerRNA *ptr, float *values) @@ -256,7 +261,7 @@ static void rna_Image_resolution_get(PointerRNA *ptr, float *values) values[1] = 0; } - BKE_image_release_ibuf(im, lock); + BKE_image_release_ibuf(im, ibuf, lock); } static void rna_Image_resolution_set(PointerRNA *ptr, const float *values) @@ -271,7 +276,7 @@ static void rna_Image_resolution_set(PointerRNA *ptr, const float *values) ibuf->ppm[1] = values[1]; } - BKE_image_release_ibuf(im, lock); + BKE_image_release_ibuf(im, ibuf, lock); } static int rna_Image_depth_get(PointerRNA *ptr) @@ -290,7 +295,7 @@ static int rna_Image_depth_get(PointerRNA *ptr) else planes = ibuf->planes; - BKE_image_release_ibuf(im, lock); + BKE_image_release_ibuf(im, ibuf, lock); return planes; } @@ -317,7 +322,7 @@ static int rna_Image_pixels_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY else length[0] = 0; - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); return length[0]; } @@ -343,7 +348,7 @@ static void rna_Image_pixels_get(PointerRNA *ptr, float *values) } } - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); } static void rna_Image_pixels_set(PointerRNA *ptr, const float *values) @@ -369,7 +374,7 @@ static void rna_Image_pixels_set(PointerRNA *ptr, const float *values) ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID; } - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); } #else diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c index 4d951b54c26..3c04fcc89ec 100644 --- a/source/blender/makesrna/intern/rna_image_api.c +++ b/source/blender/makesrna/intern/rna_image_api.c @@ -98,7 +98,7 @@ static void rna_Image_save_render(Image *image, bContext *C, ReportList *reports IMB_freeImBuf(write_ibuf); } - BKE_image_release_ibuf(image, lock); + BKE_image_release_ibuf(image, ibuf, lock); } else { BKE_report(reports, RPT_ERROR, "Scene not in context, could not get save parameters"); @@ -107,7 +107,7 @@ static void rna_Image_save_render(Image *image, bContext *C, ReportList *reports static void rna_Image_save(Image *image, ReportList *reports) { - ImBuf *ibuf = BKE_image_get_ibuf(image, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL); if (ibuf) { char filename[FILE_MAX]; BLI_strncpy(filename, image->name, sizeof(filename)); @@ -135,11 +135,13 @@ static void rna_Image_save(Image *image, ReportList *reports) else { BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2); } + + BKE_image_release_ibuf(image, ibuf, NULL); } static void rna_Image_pack(Image *image, ReportList *reports, int as_png) { - ImBuf *ibuf = BKE_image_get_ibuf(image, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL); if (!as_png && (ibuf && (ibuf->userflags & IB_BITMAPDIRTY))) { BKE_report(reports, RPT_ERROR, "Cannot pack edited image from disk, only as internal PNG"); @@ -152,6 +154,8 @@ static void rna_Image_pack(Image *image, ReportList *reports, int as_png) image->packedfile = newPackedFile(reports, image->name, ID_BLEND_PATH(G.main, &image->id)); } } + + BKE_image_release_ibuf(image, ibuf, NULL); } static void rna_Image_unpack(Image *image, ReportList *reports, int method) @@ -176,7 +180,7 @@ static void rna_Image_reload(Image *image) static void rna_Image_update(Image *image, ReportList *reports) { - ImBuf *ibuf = BKE_image_get_ibuf(image, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, NULL); if (ibuf == NULL) { BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2); @@ -187,6 +191,8 @@ static void rna_Image_update(Image *image, ReportList *reports) IMB_rect_from_float(ibuf); ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + + BKE_image_release_ibuf(image, ibuf, NULL); } static void rna_Image_scale(Image *image, ReportList *reports, int width, int height) @@ -205,10 +211,11 @@ static int rna_Image_gl_load(Image *image, ReportList *reports, int filter, int if (*bind) return error; - ibuf = BKE_image_get_ibuf(image, NULL); + ibuf = BKE_image_acquire_ibuf(image, NULL, NULL); if (ibuf == NULL || ibuf->rect == NULL) { BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2); + BKE_image_release_ibuf(image, ibuf, NULL); return (int)GL_INVALID_OPERATION; } @@ -237,6 +244,8 @@ static int rna_Image_gl_load(Image *image, ReportList *reports, int filter, int image->bindcode = 0; } + BKE_image_release_ibuf(image, ibuf, NULL); + return error; } diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c index 9d63e0e687d..af39500442d 100644 --- a/source/blender/makesrna/intern/rna_lamp.c +++ b/source/blender/makesrna/intern/rna_lamp.c @@ -421,7 +421,7 @@ static void rna_def_lamp(BlenderRNA *brna) /* textures */ rna_def_mtex_common(brna, srna, "rna_Lamp_mtex_begin", "rna_Lamp_active_texture_get", - "rna_Lamp_active_texture_set", NULL, "LampTextureSlot", "LampTextureSlots", "rna_Lamp_update"); + "rna_Lamp_active_texture_set", NULL, "LampTextureSlot", "LampTextureSlots", "rna_Lamp_draw_update"); } static void rna_def_lamp_falloff(StructRNA *srna) diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index a381dd489c7..9d90601c075 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -78,6 +78,7 @@ EnumPropertyItem modifier_type_items[] = { {eModifierType_Skin, "SKIN", ICON_MOD_SKIN, "Skin", ""}, {eModifierType_Solidify, "SOLIDIFY", ICON_MOD_SOLIDIFY, "Solidify", ""}, {eModifierType_Subsurf, "SUBSURF", ICON_MOD_SUBSURF, "Subdivision Surface", ""}, + {eModifierType_Triangulate, "TRIANGULATE", ICON_MOD_TRIANGULATE, "Triangulate", ""}, {0, "", 0, N_("Deform"), ""}, {eModifierType_Armature, "ARMATURE", ICON_MOD_ARMATURE, "Armature", ""}, {eModifierType_Cast, "CAST", ICON_MOD_CAST, "Cast", ""}, @@ -213,6 +214,8 @@ static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr) return &RNA_SkinModifier; case eModifierType_LaplacianSmooth: return &RNA_LaplacianSmoothModifier; + case eModifierType_Triangulate: + return &RNA_TriangulateModifier; default: return &RNA_Modifier; } @@ -1814,7 +1817,7 @@ static void rna_def_modifier_laplaciansmooth(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Modifier_update"); prop = RNA_def_property(srna, "use_volume_preserve", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_LAPLACIANSMOOTH_VOLUME_PRESERVATION); + 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"); @@ -3361,6 +3364,22 @@ static void rna_def_modifier_skin(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Modifier_update"); } +static void rna_def_modifier_triangulate(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "TriangulateModifier", "Modifier"); + RNA_def_struct_ui_text(srna, "Triangulate Modifier", "Triangulate Mesh"); + RNA_def_struct_sdna(srna, "TriangulateModifierData"); + RNA_def_struct_ui_icon(srna, ICON_MOD_TRIANGULATE); + + prop = RNA_def_property(srna, "use_beauty", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_TRIANGULATE_BEAUTY); + RNA_def_property_ui_text(prop, "Beauty Subdivide", "Subdivide across shortest diagonal"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); +} + void RNA_def_modifier(BlenderRNA *brna) { StructRNA *srna; @@ -3468,6 +3487,7 @@ void RNA_def_modifier(BlenderRNA *brna) rna_def_modifier_remesh(brna); rna_def_modifier_skin(brna); rna_def_modifier_laplaciansmooth(brna); + rna_def_modifier_triangulate(brna); } #endif diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 33a41ff6f6e..1da9a450c2c 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -1140,7 +1140,7 @@ static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *p bNode *node = (bNode *)ptr->data; RenderEngineType *engine_type = RE_engines_find(scene->r.engine); - if(engine_type && engine_type->update_script_node) { + if (engine_type && engine_type->update_script_node) { /* auto update node */ RenderEngine *engine = RE_engine_create(engine_type); engine_type->update_script_node(engine, ntree, node); @@ -2199,6 +2199,16 @@ static void def_cmp_map_value(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } +static void def_cmp_map_range(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "use_clamp", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "custom1", 1); + RNA_def_property_ui_text(prop, "Clamp", "Clamp result of the node to 0..1 range"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); +} + static void def_cmp_vector_blur(StructRNA *srna) { PropertyRNA *prop; @@ -4641,18 +4651,22 @@ static void rna_def_node(BlenderRNA *brna) prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_SELECT); RNA_def_property_ui_text(prop, "Select", ""); + RNA_def_property_update(prop, NC_NODE | NA_SELECTED, NULL); prop = RNA_def_property(srna, "show_options", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_OPTIONS); RNA_def_property_ui_text(prop, "Show Options", ""); + RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL); prop = RNA_def_property(srna, "show_preview", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_PREVIEW); RNA_def_property_ui_text(prop, "Show Preview", ""); + RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL); prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_HIDDEN); RNA_def_property_ui_text(prop, "Hide", ""); + RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, NULL); prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_MUTED); diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/makesrna/intern/rna_nodetree_types.h index fbbcbae6c12..14cdbc6cf7d 100644 --- a/source/blender/makesrna/intern/rna_nodetree_types.h +++ b/source/blender/makesrna/intern/rna_nodetree_types.h @@ -114,6 +114,7 @@ DefNode( CompositorNode, CMP_NODE_ALPHAOVER, def_cmp_alpha_over, "ALPHA DefNode( CompositorNode, CMP_NODE_BLUR, def_cmp_blur, "BLUR", Blur, "Blur", "" ) DefNode( CompositorNode, CMP_NODE_FILTER, def_cmp_filter, "FILTER", Filter, "Filter", "" ) DefNode( CompositorNode, CMP_NODE_MAP_VALUE, def_cmp_map_value, "MAP_VALUE", MapValue, "Map Value", "" ) +DefNode( CompositorNode, CMP_NODE_MAP_RANGE, def_cmp_map_range, "MAP_RANGE", MapRange, "Map Range", "" ) DefNode( CompositorNode, CMP_NODE_TIME, def_time, "TIME", Time, "Time", "" ) DefNode( CompositorNode, CMP_NODE_VECBLUR, def_cmp_vector_blur, "VECBLUR", VecBlur, "Vector Blur", "" ) DefNode( CompositorNode, CMP_NODE_SEPRGBA, 0, "SEPRGBA", SepRGBA, "Separate RGBA", "" ) diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index d436e4719ea..a669cb2558a 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -1643,21 +1643,23 @@ static void rna_def_object_game_settings(BlenderRNA *brna) RNA_def_property_range(prop, 0.0, 1000.0); RNA_def_property_ui_text(prop, "Velocity Max", "Clamp velocity to this maximum speed"); + /* Character physics */ prop = RNA_def_property(srna, "step_height", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "step_height"); - RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_range(prop, 0.01, 1.0); RNA_def_property_ui_text(prop, "Step Height", "Maximum height of steps the character can run over"); prop = RNA_def_property(srna, "jump_speed", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "jump_speed"); RNA_def_property_range(prop, 0.0, 1000.0); - RNA_def_property_ui_text(prop, "Jump Force", "Upward velocity applied to the character when jumping (with the Motion actuator)"); + RNA_def_property_ui_text(prop, "Jump Force", "Upward velocity applied to the character when jumping"); prop = RNA_def_property(srna, "fall_speed", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "fall_speed"); RNA_def_property_range(prop, 0.0, 1000.0); RNA_def_property_ui_text(prop, "Fall Speed Max", "Maximum speed at which the character will fall"); + /* Collision Masks */ prop = RNA_def_property(srna, "collision_group", PROP_BOOLEAN, PROP_LAYER_MEMBER); RNA_def_property_boolean_sdna(prop, NULL, "col_group", 1); RNA_def_property_array(prop, OB_MAX_COL_MASKS); diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index 412aad20a41..5c90fb8787c 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -675,7 +675,7 @@ static void rna_def_bone_group(BlenderRNA *brna) } static EnumPropertyItem prop_iksolver_items[] = { - {IKSOLVER_LEGACY, "LEGACY", 0, "Legacy", "Original IK solver"}, + {IKSOLVER_STANDARD, "LEGACY", 0, "Standard", "Original IK solver"}, {IKSOLVER_ITASC, "ITASC", 0, "iTaSC", "Multi constraint, stateful IK solver"}, {0, NULL, 0, NULL, NULL} }; @@ -1126,7 +1126,7 @@ static void rna_def_pose_itasc(BlenderRNA *brna) prop = RNA_def_property(srna, "iterations", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "numiter"); - RNA_def_property_range(prop, 1.f, 1000.f); + RNA_def_property_range(prop, 0, 1000); RNA_def_property_ui_text(prop, "Iterations", "Maximum number of iterations for convergence in case of reiteration"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Itasc_update"); @@ -1221,8 +1221,7 @@ static void rna_def_pose_ikparam(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "iksolver"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_enum_items(prop, prop_iksolver_items); - RNA_def_property_ui_text(prop, "IK Solver", - "IK solver for which these parameters are defined, 0 for Legacy, 1 for iTaSC"); + RNA_def_property_ui_text(prop, "IK Solver", "IK solver for which these parameters are defined"); } /* pose.bone_groups */ @@ -1285,8 +1284,7 @@ static void rna_def_pose(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "iksolver"); RNA_def_property_enum_funcs(prop, NULL, "rna_Pose_ik_solver_set", NULL); RNA_def_property_enum_items(prop, prop_iksolver_items); - RNA_def_property_ui_text(prop, "IK Solver", - "Selection of IK solver for IK chain, current choice is 0 for Legacy, 1 for iTaSC"); + RNA_def_property_ui_text(prop, "IK Solver", "Selection of IK solver for IK chain"); RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_ik_solver_update"); prop = RNA_def_property(srna, "ik_param", PROP_POINTER, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 0ba15193985..5529c3a375e 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1123,6 +1123,12 @@ static void rna_SceneRenderLayer_name_set(PointerRNA *ptr, const char *value) } } +static char *rna_SceneRenderLayer_path(PointerRNA *ptr) +{ + SceneRenderLayer *srl = (SceneRenderLayer*)ptr->data; + return BLI_sprintfN("render.layers[\"%s\"]", srl->name); +} + static int rna_RenderSettings_multiple_engines_get(PointerRNA *UNUSED(ptr)) { return (BLI_countlist(&R_engines) > 1); @@ -2788,6 +2794,7 @@ static void rna_def_scene_render_layer(BlenderRNA *brna) srna = RNA_def_struct(brna, "SceneRenderLayer", NULL); RNA_def_struct_ui_text(srna, "Scene Render Layer", "Render layer"); RNA_def_struct_ui_icon(srna, ICON_RENDERLAYERS); + RNA_def_struct_path_func(srna, "rna_SceneRenderLayer_path"); rna_def_render_layer_common(srna, 1); } @@ -3144,7 +3151,7 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Volume", "Audio volume"); - RNA_def_property_translation_context(prop, "Audio"); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); #endif @@ -3967,6 +3974,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop = RNA_def_property(srna, "use_sequencer_gl_preview", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "seq_flag", R_SEQ_GL_PREV); RNA_def_property_ui_text(prop, "Sequencer OpenGL", ""); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SceneSequencer_update"); #if 0 /* see R_SEQ_GL_REND comment */ prop = RNA_def_property(srna, "use_sequencer_gl_render", PROP_BOOLEAN, PROP_NONE); @@ -4565,7 +4573,7 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "audio.volume"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Volume", "Audio volume"); - RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND); RNA_def_property_update(prop, NC_SCENE, NULL); RNA_def_property_float_funcs(prop, NULL, "rna_Scene_volume_set", NULL); diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index c2fa64698e4..18a9b9683f8 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -1875,7 +1875,7 @@ static void rna_def_sound(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "volume"); RNA_def_property_range(prop, 0.0f, 100.0f); RNA_def_property_ui_text(prop, "Volume", "Playback volume of the sound"); - RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND); RNA_def_property_float_funcs(prop, NULL, "rna_Sequence_volume_set", NULL); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); @@ -1883,7 +1883,7 @@ static void rna_def_sound(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "pitch"); RNA_def_property_range(prop, 0.1f, 10.0f); RNA_def_property_ui_text(prop, "Pitch", "Playback pitch of the sound"); - RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND); RNA_def_property_float_funcs(prop, NULL, "rna_Sequence_pitch_set", NULL); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 962a92223eb..caa81dafa0e 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -598,7 +598,7 @@ static EnumPropertyItem *rna_SpaceImageEditor_draw_channels_itemf(bContext *UNUS alpha = ibuf && (ibuf->channels == 4); zbuf = ibuf && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1)); - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); if (alpha && zbuf) return draw_channels_items; @@ -678,7 +678,7 @@ static void rna_SpaceImageEditor_scopes_update(Main *UNUSED(bmain), Scene *scene scopes_update(&sima->scopes, ibuf, &scene->view_settings, &scene->display_settings); WM_main_add_notifier(NC_IMAGE, sima->image); } - ED_space_image_release_buffer(sima, lock); + ED_space_image_release_buffer(sima, ibuf, lock); } /* Space Text Editor */ diff --git a/source/blender/makesrna/intern/rna_speaker.c b/source/blender/makesrna/intern/rna_speaker.c index a160aaf94e2..139582104ee 100644 --- a/source/blender/makesrna/intern/rna_speaker.c +++ b/source/blender/makesrna/intern/rna_speaker.c @@ -152,7 +152,7 @@ static void rna_def_speaker(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "volume"); RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Volume", "How loud the sound is"); - RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND); /* RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_volume_set", NULL); */ /* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */ @@ -160,7 +160,7 @@ static void rna_def_speaker(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "pitch"); RNA_def_property_range(prop, 0.1f, 10.0f); RNA_def_property_ui_text(prop, "Pitch", "Playback pitch of the sound"); - RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_AUDIO); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_SOUND); /* RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_pitch_set", NULL); */ /* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */ diff --git a/source/blender/makesrna/intern/rna_text.c b/source/blender/makesrna/intern/rna_text.c index e46373b250c..b1637ef4c8a 100644 --- a/source/blender/makesrna/intern/rna_text.c +++ b/source/blender/makesrna/intern/rna_text.c @@ -129,49 +129,6 @@ static void rna_def_text_line(BlenderRNA *brna) RNA_def_property_update(prop, NC_TEXT | NA_EDITED, NULL); } -static void rna_def_text_marker(BlenderRNA *brna) -{ - StructRNA *srna; - PropertyRNA *prop; - - srna = RNA_def_struct(brna, "TextMarker", NULL); - RNA_def_struct_ui_text(srna, "Text Marker", "Marker highlighting a portion of text in a Text datablock"); - - prop = RNA_def_property(srna, "line", PROP_INT, PROP_UNSIGNED); - RNA_def_property_int_sdna(prop, NULL, "lineno"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Line", "Line in which the marker is located"); - - prop = RNA_def_property(srna, "character_index_start", PROP_INT, PROP_UNSIGNED); - RNA_def_property_int_sdna(prop, NULL, "start"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Start", "Start position of the marker in the line"); - - prop = RNA_def_property(srna, "character_index_end", PROP_INT, PROP_UNSIGNED); - RNA_def_property_int_sdna(prop, NULL, "end"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "End", "Start position of the marker in the line"); - - prop = RNA_def_property(srna, "group", PROP_INT, PROP_UNSIGNED); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_range(prop, 0, (int)0xFFFF); - RNA_def_property_ui_text(prop, "Group", ""); - - prop = RNA_def_property(srna, "is_temporary", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flags", TMARK_TEMP); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Temporary", "Marker is temporary"); - - prop = RNA_def_property(srna, "use_edit_all", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flags", TMARK_EDITALL); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Edit All", "Edit all markers of the same group as one"); - - prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA); - RNA_def_property_range(prop, 0.0f, 1.0f); - RNA_def_property_ui_text(prop, "Color", "Color to display the marker with"); -} - static void rna_def_text(BlenderRNA *brna) { StructRNA *srna; @@ -241,17 +198,12 @@ static void rna_def_text(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Selection End Character", "Index of character after end of selection in the selection end line"); - prop = RNA_def_property(srna, "markers", PROP_COLLECTION, PROP_NONE); - RNA_def_property_struct_type(prop, "TextMarker"); - RNA_def_property_ui_text(prop, "Markers", "Text markers highlighting part of the text"); - RNA_api_text(srna); } void RNA_def_text(BlenderRNA *brna) { rna_def_text_line(brna); - rna_def_text_marker(brna); rna_def_text(brna); } diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c index e77c5d13a6b..e67985f68c5 100644 --- a/source/blender/makesrna/intern/rna_texture.c +++ b/source/blender/makesrna/intern/rna_texture.c @@ -233,6 +233,7 @@ void rna_TextureSlot_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRN break; case ID_LA: WM_main_add_notifier(NC_LAMP | ND_LIGHTING, id); + WM_main_add_notifier(NC_LAMP | ND_LIGHTING_DRAW, id); break; case ID_BR: WM_main_add_notifier(NC_BRUSH, id); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 3e9f5b44a3d..7be34c398ae 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -3019,11 +3019,11 @@ static void rna_def_userdef_system(BlenderRNA *brna) }; static EnumPropertyItem multi_sample_levels[] = { - {USER_MULTISAMPLE_NONE, "MULTISAMPLE_NONE", 0, "No MultiSample", "Do not use OpenGL MultiSample"}, - {USER_MULTISAMPLE_2, "MULTISAMPLE_2", 0, "MultiSample: 2", "Use 2x OpenGL MultiSample (requires restart)"}, - {USER_MULTISAMPLE_4, "MULTISAMPLE_4", 0, "MultiSample: 4", "Use 4x OpenGL MultiSample (requires restart)"}, - {USER_MULTISAMPLE_8, "MULTISAMPLE_8", 0, "MultiSample: 8", "Use 8x OpenGL MultiSample (requires restart)"}, - {USER_MULTISAMPLE_16, "MULTISAMPLE_16", 0, "MultiSample: 16", "Use 16x OpenGL MultiSample (requires restart)"}, + {USER_MULTISAMPLE_NONE, "NONE", 0, "No MultiSample", "Do not use OpenGL MultiSample"}, + {USER_MULTISAMPLE_2, "2", 0, "MultiSample: 2", "Use 2x OpenGL MultiSample (requires restart)"}, + {USER_MULTISAMPLE_4, "4", 0, "MultiSample: 4", "Use 4x OpenGL MultiSample (requires restart)"}, + {USER_MULTISAMPLE_8, "8", 0, "MultiSample: 8", "Use 8x OpenGL MultiSample (requires restart)"}, + {USER_MULTISAMPLE_16, "16", 0, "MultiSample: 16", "Use 16x OpenGL MultiSample (requires restart)"}, {0, NULL, 0, NULL, NULL} }; @@ -3236,10 +3236,12 @@ static void rna_def_userdef_system(BlenderRNA *brna) /* this isn't essential but nice to check if VBO draws any differently */ RNA_def_property_update(prop, NC_WINDOW, NULL); +#if 0 prop = RNA_def_property(srna, "use_antialiasing", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "gameflags", USER_DISABLE_AA); RNA_def_property_ui_text(prop, "Anti-aliasing", "Use anti-aliasing for the 3D view (may impact redraw performance)"); +#endif prop = RNA_def_property(srna, "anisotropic_filter", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "anisotropic_filter"); @@ -3322,7 +3324,7 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_userdef_text_update"); /* Full scene anti-aliasing */ - prop = RNA_def_property(srna, "ogl_multisamples", PROP_ENUM, PROP_NONE); + prop = RNA_def_property(srna, "multi_sample", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "ogl_multisamples"); RNA_def_property_enum_items(prop, multi_sample_levels); RNA_def_property_ui_text(prop, "MultiSample", "Enable OpenGL multi-sampling, only for systems that support it, requires restart"); diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index e5f44644f7a..f83410e7cc1 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -555,7 +555,7 @@ static void rna_Window_screen_set(PointerRNA *ptr, PointerRNA value) if (value.data == NULL) return; - /* exception: can't set screens inside of area/region handers */ + /* exception: can't set screens inside of area/region handlers */ win->newscreen = value.data; } @@ -563,8 +563,8 @@ static void rna_Window_screen_update(bContext *C, PointerRNA *ptr) { wmWindow *win = (wmWindow *)ptr->data; - /* exception: can't set screens inside of area/region handers, and must - * use context so notifier gets to the right window */ + /* exception: can't set screens inside of area/region handlers, + * and must use context so notifier gets to the right window */ if (win->newscreen) { WM_event_add_notifier(C, NC_SCREEN | ND_SCREENBROWSE, win->newscreen); win->newscreen = NULL; diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index 3a7066ff41a..cf3bb05849a 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -94,6 +94,7 @@ set(SRC intern/MOD_weightvgedit.c intern/MOD_weightvgmix.c intern/MOD_weightvgproximity.c + intern/MOD_triangulate.c MOD_modifiertypes.h intern/MOD_boolean_util.h diff --git a/source/blender/modifiers/MOD_modifiertypes.h b/source/blender/modifiers/MOD_modifiertypes.h index a4817ff775d..290ba193567 100644 --- a/source/blender/modifiers/MOD_modifiertypes.h +++ b/source/blender/modifiers/MOD_modifiertypes.h @@ -76,6 +76,7 @@ extern ModifierTypeInfo modifierType_DynamicPaint; extern ModifierTypeInfo modifierType_Remesh; extern ModifierTypeInfo modifierType_Skin; extern ModifierTypeInfo modifierType_LaplacianSmooth; +extern ModifierTypeInfo modifierType_Triangulate; /* MOD_util.c */ void modifier_type_init(ModifierTypeInfo *types[]); diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c index 7219038b087..7ab3a5df531 100644 --- a/source/blender/modifiers/intern/MOD_armature.c +++ b/source/blender/modifiers/intern/MOD_armature.c @@ -58,7 +58,7 @@ static void initData(ModifierData *md) { ArmatureModifierData *amd = (ArmatureModifierData *) md; - amd->deformflag = ARM_DEF_ENVELOPE | ARM_DEF_VGROUP; + amd->deformflag = ARM_DEF_VGROUP; } static void copyData(ModifierData *md, ModifierData *target) diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index b9dd37ac50c..d4463098f07 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -178,14 +178,14 @@ static int *find_doubles_index_map(BMesh *bm, BMOperator *dupe_op, amd->merge_dist, dupe_op, "geom"); BMO_op_exec(bm, &find_op); - + i = 0; - BMO_ITER (ele, &oiter, bm, dupe_op, "geom", BM_ALL) { + BMO_ITER (ele, &oiter, dupe_op->slots_in, "geom", BM_ALL) { BM_elem_index_set(ele, i); /* set_dirty */ i++; } - BMO_ITER (ele, &oiter, bm, dupe_op, "newout", BM_ALL) { + BMO_ITER (ele, &oiter, dupe_op->slots_out, "geom.out", BM_ALL) { BM_elem_index_set(ele, i); /* set_dirty */ i++; } @@ -197,7 +197,7 @@ static int *find_doubles_index_map(BMesh *bm, BMOperator *dupe_op, index_map = MEM_callocN(sizeof(int) * (*index_map_length), "index_map"); /*element type argument doesn't do anything here*/ - BMO_ITER (v, &oiter, bm, &find_op, "targetmapout", 0) { + BMO_ITER (v, &oiter, find_op.slots_out, "targetmap.out", 0) { v2 = BMO_iter_map_value_p(&oiter); index_map[BM_elem_index_get(v)] = BM_elem_index_get(v2) + 1; @@ -218,9 +218,10 @@ static int *find_doubles_index_map(BMesh *bm, BMOperator *dupe_op, static void bm_merge_dm_transform(BMesh *bm, DerivedMesh *dm, float mat[4][4], const ArrayModifierData *amd, BMOperator *dupe_op, - const char *dupe_slot_name, + BMOpSlot dupe_op_slot_args[BMO_OP_MAX_SLOTS], const char *dupe_slot_name, BMOperator *weld_op) { + const int is_input = (dupe_op->slots_in == dupe_op_slot_args); BMVert *v, *v2, *v3; BMIter iter; @@ -234,14 +235,27 @@ static void bm_merge_dm_transform(BMesh *bm, DerivedMesh *dm, float mat[4][4], BMOIter oiter; BMOperator find_op; + BMOpSlot *slot_targetmap; BMO_op_initf(bm, &find_op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), - "find_doubles verts=%Hv dist=%f keep_verts=%s", + is_input ? /* ugh */ + "find_doubles verts=%Hv dist=%f keep_verts=%s" : + "find_doubles verts=%Hv dist=%f keep_verts=%S", BM_ELEM_TAG, amd->merge_dist, dupe_op, dupe_slot_name); /* append the dupe's geom to the findop input verts */ - BMO_slot_buffer_append(&find_op, "verts", dupe_op, dupe_slot_name); + if (is_input) { + BMO_slot_buffer_append(&find_op, slots_in, "verts", + dupe_op, slots_in, dupe_slot_name); + } + else if (dupe_op->slots_out == dupe_op_slot_args) { + BMO_slot_buffer_append(&find_op, slots_in, "verts", + dupe_op, slots_out, dupe_slot_name); + } + else { + BLI_assert(0); + } /* transform and tag verts */ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { @@ -253,15 +267,17 @@ static void bm_merge_dm_transform(BMesh *bm, DerivedMesh *dm, float mat[4][4], BMO_op_exec(bm, &find_op); + slot_targetmap = BMO_slot_get(weld_op->slots_in, "targetmap"); + /* add new merge targets to weld operator */ - BMO_ITER (v, &oiter, bm, &find_op, "targetmapout", 0) { + BMO_ITER (v, &oiter, find_op.slots_out, "targetmap.out", 0) { v2 = BMO_iter_map_value_p(&oiter); /* check in case the target vertex (v2) is already marked * for merging */ - while ((v3 = BMO_slot_map_ptr_get(bm, weld_op, "targetmap", v2))) { + while ((v3 = BMO_slot_map_ptr_get(slot_targetmap, v2))) { v2 = v3; } - BMO_slot_map_ptr_insert(bm, weld_op, "targetmap", v, v2); + BMO_slot_map_ptr_insert(weld_op, slot_targetmap, v, v2); } BMO_op_finish(bm, &find_op); @@ -286,6 +302,7 @@ static void merge_first_last(BMesh *bm, BMOperator find_op; BMOIter oiter; BMVert *v, *v2; + BMOpSlot *slot_targetmap; BMO_op_initf(bm, &find_op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "find_doubles verts=%s dist=%f keep_verts=%s", @@ -293,14 +310,16 @@ static void merge_first_last(BMesh *bm, dupe_first, "geom"); /* append the last dupe's geom to the findop input verts */ - BMO_slot_buffer_append(&find_op, "verts", dupe_last, "newout"); + BMO_slot_buffer_append(&find_op, slots_in, "verts", + dupe_last, slots_out, "geom.out"); BMO_op_exec(bm, &find_op); /* add new merge targets to weld operator */ - BMO_ITER (v, &oiter, bm, &find_op, "targetmapout", 0) { + slot_targetmap = BMO_slot_get(weld_op->slots_in, "targetmap"); + BMO_ITER (v, &oiter, find_op.slots_out, "targetmap.out", 0) { v2 = BMO_iter_map_value_p(&oiter); - BMO_slot_map_ptr_insert(bm, weld_op, "targetmap", v, v2); + BMO_slot_map_ptr_insert(weld_op, slot_targetmap, v, v2); } BMO_op_finish(bm, &find_op); @@ -325,6 +344,7 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, int *indexMap = NULL; DerivedMesh *start_cap = NULL, *end_cap = NULL; MVert *src_mvert; + BMOpSlot *slot_targetmap = NULL; /* for weldop */ /* need to avoid infinite recursion here */ if (amd->start_cap && amd->start_cap != ob) @@ -408,13 +428,17 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, * cleaner way to do this. One possibility: a "mirror" BMOp would * certainly help by compressing it all into one top-level BMOp that * executes a lot of second-level BMOps. */ + BM_mesh_elem_toolflags_ensure(bm); BMO_push(bm, NULL); bmesh_edit_begin(bm, 0); - if (amd->flags & MOD_ARR_MERGE) + if (amd->flags & MOD_ARR_MERGE) { BMO_op_init(bm, &weld_op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "weld_verts"); + slot_targetmap = BMO_slot_get(weld_op.slots_in, "targetmap"); + } + BMO_op_initf(bm, &dupe_op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "duplicate geom=%avef"); first_dupe_op = dupe_op; @@ -422,18 +446,18 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, for (j = 0; j < count - 1; j++) { BMVert *v, *v2, *v3; BMOpSlot *geom_slot; - BMOpSlot *newout_slot; + BMOpSlot *geom_out_slot; BMOIter oiter; if (j != 0) { BMO_op_initf(bm, &dupe_op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), - "duplicate geom=%s", &old_dupe_op, "newout"); + "duplicate geom=%S", &old_dupe_op, "geom.out"); } BMO_op_exec(bm, &dupe_op); - geom_slot = BMO_slot_get(&dupe_op, "geom"); - newout_slot = BMO_slot_get(&dupe_op, "newout"); + geom_slot = BMO_slot_get(dupe_op.slots_in, "geom"); + geom_out_slot = BMO_slot_get(dupe_op.slots_out, "geom.out"); if ((amd->flags & MOD_ARR_MERGEFINAL) && j == 0) { int first_geom_bytes = sizeof(BMVert *) * geom_slot->len; @@ -445,7 +469,7 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, } /* apply transformation matrix */ - BMO_ITER (v, &oiter, bm, &dupe_op, "newout", BM_VERT) { + BMO_ITER (v, &oiter, dupe_op.slots_out, "geom.out", BM_VERT) { mul_m4_v3(offset, v->co); } @@ -464,17 +488,17 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, for (i = 0; i < index_len; i++) { if (!indexMap[i]) continue; - /* merge v (from 'newout') into v2 (from old 'geom') */ - v = _E(newout_slot, i - geom_slot->len); + /* merge v (from 'geom.out') into v2 (from old 'geom') */ + v = _E(geom_out_slot, i - geom_slot->len); v2 = _E(geom_slot, indexMap[i] - 1); /* check in case the target vertex (v2) is already marked * for merging */ - while ((v3 = BMO_slot_map_ptr_get(bm, &weld_op, "targetmap", v2))) { + while ((v3 = BMO_slot_map_ptr_get(slot_targetmap, v2))) { v2 = v3; } - BMO_slot_map_ptr_insert(bm, &weld_op, "targetmap", v, v2); + BMO_slot_map_ptr_insert(&weld_op, slot_targetmap, v, v2); } #undef _E @@ -510,14 +534,15 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, float startoffset[4][4]; invert_m4_m4(startoffset, offset); bm_merge_dm_transform(bm, start_cap, startoffset, amd, - &first_dupe_op, "geom", &weld_op); + &first_dupe_op, first_dupe_op.slots_in, "geom", &weld_op); } if (end_cap) { float endoffset[4][4]; mult_m4_m4m4(endoffset, offset, final_offset); bm_merge_dm_transform(bm, end_cap, endoffset, amd, - &dupe_op, count == 1 ? "geom" : "newout", &weld_op); + &dupe_op, (count == 1) ? dupe_op.slots_in : dupe_op.slots_out, + (count == 1) ? "geom" : "geom.out", &weld_op); } } /* done capping */ diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c index 3e3bcb73491..59befe4db05 100644 --- a/source/blender/modifiers/intern/MOD_bevel.c +++ b/source/blender/modifiers/intern/MOD_bevel.c @@ -92,20 +92,15 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) #ifdef USE_BM_BEVEL_OP_AS_MOD -#define EDGE_MARK 1 - /* BMESH_TODO * - * this bevel calls the operator which is missing many of the options - * which the bevel modifier in trunk has. + * this bevel calls the new bevel code (added since 2.64) + * which is missing many of the options which the bevel modifier from 2.4x has. * - no vertex bevel * - no weight bevel * * These will need to be added to the bmesh operator. - * - campbell - * - * note: this code is very close to MOD_edgesplit.c. - * note: if 0'd code from trunk included below. + * - campbell */ static DerivedMesh *applyModifier(ModifierData *md, struct Object *UNUSED(ob), DerivedMesh *dm, @@ -116,22 +111,20 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Object *UNUSED(ob), BMIter iter; BMEdge *e; BevelModifierData *bmd = (BevelModifierData *) md; - float threshold = cos((bmd->bevel_angle + 0.00001f) * M_PI / 180.0f); + const float threshold = cosf((bmd->bevel_angle + 0.00001f) * (float)M_PI / 180.0f); + const int segments = 16; /* XXX */ bm = DM_to_bmesh(dm); - BM_mesh_normals_update(bm, FALSE); - BMO_push(bm, NULL); - if (bmd->lim_flags & BME_BEVEL_ANGLE) { BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { /* check for 1 edge having 2 face users */ - BMLoop *l1, *l2; - if ((l1 = e->l) && - (l2 = e->l->radial_next) != l1) - { - if (dot_v3v3(l1->f->no, l2->f->no) < threshold) { - BMO_elem_flag_enable(bm, e, EDGE_MARK); + BMLoop *l_a, *l_b; + if (BM_edge_loop_pair(e, &l_a, &l_b)) { + if (dot_v3v3(l_a->f->no, l_b->f->no) < threshold) { + BM_elem_flag_enable(e, BM_ELEM_TAG); + BM_elem_flag_enable(e->v1, BM_ELEM_TAG); + BM_elem_flag_enable(e->v2, BM_ELEM_TAG); } } } @@ -139,18 +132,23 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Object *UNUSED(ob), else { /* crummy, is there a way just to operator on all? - campbell */ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - BMO_elem_flag_enable(bm, e, EDGE_MARK); + if (BM_edge_is_manifold(e)) { + BM_elem_flag_enable(e, BM_ELEM_TAG); + BM_elem_flag_enable(e->v1, BM_ELEM_TAG); + BM_elem_flag_enable(e->v2, BM_ELEM_TAG); + } } } - BMO_op_callf(bm, BMO_FLAG_DEFAULTS, - "bevel geom=%fe percent=%f use_even=%b use_dist=%b", - EDGE_MARK, bmd->value, (bmd->flags & BME_BEVEL_EVEN) != 0, (bmd->flags & BME_BEVEL_DIST) != 0); - BMO_pop(bm); + BM_mesh_bevel(bm, bmd->value, segments); result = CDDM_from_bmesh(bm, TRUE); + + BLI_assert(bm->toolflagpool == NULL); /* make sure we never alloc'd this */ BM_mesh_free(bm); + CDDM_calc_normals(result); + return result; } diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c index dc29e59d549..3f8eaa438c9 100644 --- a/source/blender/modifiers/intern/MOD_decimate.c +++ b/source/blender/modifiers/intern/MOD_decimate.c @@ -186,6 +186,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, /* update for display only */ dmd->face_count = bm->totface; result = CDDM_from_bmesh(bm, FALSE); + BLI_assert(bm->toolflagpool == NULL); /* make sure we never alloc'd this */ BM_mesh_free(bm); #ifdef USE_TIMEIT diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c index 21717d07fef..ec81c5ce699 100644 --- a/source/blender/modifiers/intern/MOD_edgesplit.c +++ b/source/blender/modifiers/intern/MOD_edgesplit.c @@ -67,8 +67,7 @@ static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd, Obj float threshold = cosf((emd->split_angle + 0.00001f) * (float)M_PI / 180.0f); bm = DM_to_bmesh(dm); - - BMO_push(bm, NULL); + BM_mesh_elem_toolflags_ensure(bm); if (emd->flags & MOD_EDGESPLIT_FROMANGLE) { BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { @@ -103,8 +102,6 @@ static DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd, Obj BMO_op_callf(bm, BMO_FLAG_DEFAULTS, "split_edges edges=%fe", EDGE_MARK); - - BMO_pop(bm); /* BM_mesh_validate(bm); */ /* for troubleshooting */ diff --git a/source/blender/modifiers/intern/MOD_fluidsim_util.c b/source/blender/modifiers/intern/MOD_fluidsim_util.c index 47523286229..13d409dc941 100644 --- a/source/blender/modifiers/intern/MOD_fluidsim_util.c +++ b/source/blender/modifiers/intern/MOD_fluidsim_util.c @@ -426,7 +426,11 @@ static DerivedMesh *fluidsim_read_cache(Object *ob, DerivedMesh *orgdm, FluidsimModifierData *fluidmd, int framenr, int useRenderParams) { int displaymode = 0; - int curFrame = framenr - 1 /*scene->r.sfra*/; /* start with 0 at start frame */ + + int curFrame = framenr /* - 1 */ /*scene->r.sfra*/; /* start with 0 at start frame */ + /* why start with 0 as start frame?? Animations + time are frozen for frame 0 anyway. (See physics_fluid.c for that. - DG */ + /* If we start with frame 0, we need to remap all animation channels, too, because they will all be 1 frame late if using frame-1! - DG */ + char targetFile[FILE_MAX]; FluidsimSettings *fss = fluidmd->fss; DerivedMesh *dm = NULL; diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c index 6f6589d4d14..266226040a3 100644 --- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c +++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c @@ -199,7 +199,7 @@ static void init_data(ModifierData *md) smd->lambda = 0.00001f; smd->lambda_border = 0.00005f; smd->repeat = 1; - smd->flag = MOD_LAPLACIANSMOOTH_X | MOD_LAPLACIANSMOOTH_Y | MOD_LAPLACIANSMOOTH_Z | MOD_LAPLACIANSMOOTH_VOLUME_PRESERVATION; + smd->flag = MOD_LAPLACIANSMOOTH_X | MOD_LAPLACIANSMOOTH_Y | MOD_LAPLACIANSMOOTH_Z | MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME; smd->defgrp_name[0] = '\0'; } @@ -511,7 +511,7 @@ static void validate_solution(LaplacianSystem *sys, short flag) float leni, lene; float vini, vend; float *vi1, *vi2, ve1[3], ve2[3]; - if (flag & MOD_LAPLACIANSMOOTH_VOLUME_PRESERVATION) { + if (flag & MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME) { vini = compute_volume(sys->vertexCos, sys->mfaces, sys->numFaces); } for (i = 0; i < sys->numEdges; i++) { @@ -545,7 +545,7 @@ static void validate_solution(LaplacianSystem *sys, short flag) } } } - if (flag & MOD_LAPLACIANSMOOTH_VOLUME_PRESERVATION) { + if (flag & MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME) { vend = compute_volume(sys->vertexCos, sys->mfaces, sys->numFaces); volume_preservation(sys, vini, vend, flag); } diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 38ec0e8bb4c..9f702957fa5 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -249,14 +249,14 @@ static int build_hull(SkinOutput *so, Frame **frames, int totframe) } /* Apply face attributes to hull output */ - BMO_ITER (f, &oiter, bm, &op, "geomout", BM_FACE) { + BMO_ITER (f, &oiter, op.slots_out, "geom.out", BM_FACE) { if (so->smd->flag & MOD_SKIN_SMOOTH_SHADING) BM_elem_flag_enable(f, BM_ELEM_SMOOTH); f->mat_nr = so->mat_nr; } /* Mark interior frames */ - BMO_ITER (v, &oiter, bm, &op, "interior_geom", BM_VERT) { + BMO_ITER (v, &oiter, op.slots_out, "geom_interior.out", BM_VERT) { for (i = 0; i < totframe; i++) { Frame *frame = frames[i]; @@ -309,7 +309,7 @@ static int build_hull(SkinOutput *so, Frame **frames, int totframe) /* Check if removing triangles above will create wire triangles, * mark them too */ - BMO_ITER (e, &oiter, bm, &op, "geomout", BM_EDGE) { + BMO_ITER (e, &oiter, op.slots_out, "geom.out", BM_EDGE) { int is_wire = TRUE; BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) { if (!BM_elem_flag_test(f, BM_ELEM_TAG)) { @@ -537,6 +537,7 @@ static int connection_node_mat(float mat[3][3], int v, const MeshElemMap *emap, /* Get axis and angle to rotate frame by */ angle = angle_normalized_v3v3(ine[0], oute[0]) / 2.0f; cross_v3_v3v3(axis, ine[0], oute[0]); + normalize_v3(axis); /* Build frame matrix (don't care about X axis here) */ copy_v3_v3(mat[0], ine[0]); @@ -1079,17 +1080,20 @@ static BMFace *collapse_face_corners(BMesh *bm, BMFace *f, int n, BMOperator op; BMIter iter; int i; + BMOpSlot *slot_targetmap; shortest_edge = BM_face_find_shortest_loop(f)->e; BMO_op_initf(bm, &op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "weld_verts"); + slot_targetmap = BMO_slot_get(op.slots_in, "targetmap"); + /* Note: could probably calculate merges in one go to be * faster */ v_safe = shortest_edge->v1; v_merge = shortest_edge->v2; mid_v3_v3v3(v_safe->co, v_safe->co, v_merge->co); - BMO_slot_map_ptr_insert(bm, &op, "targetmap", v_merge, v_safe); + BMO_slot_map_ptr_insert(&op, slot_targetmap, v_merge, v_safe); BMO_op_exec(bm, &op); BMO_op_finish(bm, &op); @@ -1215,6 +1219,7 @@ static void skin_fix_hole_no_good_verts(BMesh *bm, Frame *frame, BMFace *split_f BMOIter oiter; BMOperator op; int i, best_order[4]; + BMOpSlot *slot_targetmap; BLI_assert(split_face->len >= 3); @@ -1228,7 +1233,7 @@ static void skin_fix_hole_no_good_verts(BMesh *bm, Frame *frame, BMFace *split_f /* Update split face (should only be one new face created * during extrusion) */ split_face = NULL; - BMO_ITER (f, &oiter, bm, &op, "faceout", BM_FACE) { + BMO_ITER (f, &oiter, op.slots_out, "faces.out", BM_FACE) { BLI_assert(!split_face); split_face = f; } @@ -1246,7 +1251,7 @@ static void skin_fix_hole_no_good_verts(BMesh *bm, Frame *frame, BMFace *split_f BM_elem_flag_enable(longest_edge, BM_ELEM_TAG); BMO_op_callf(bm, BMO_FLAG_DEFAULTS, - "subdivide_edges edges=%he numcuts=%i quadcornertype=%i", + "subdivide_edges edges=%he cuts=%i quad_corner_type=%i", BM_ELEM_TAG, 1, SUBD_STRAIGHT_CUT); } else if (split_face->len > 4) { @@ -1280,8 +1285,9 @@ static void skin_fix_hole_no_good_verts(BMesh *bm, Frame *frame, BMFace *split_f BM_face_kill(bm, split_face); BMO_op_init(bm, &op, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), "weld_verts"); + slot_targetmap = BMO_slot_get(op.slots_in, "targetmap"); for (i = 0; i < 4; i++) { - BMO_slot_map_ptr_insert(bm, &op, "targetmap", + BMO_slot_map_ptr_insert(&op, slot_targetmap, verts[i], frame->verts[best_order[i]]); } BMO_op_exec(bm, &op); diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c new file mode 100644 index 00000000000..645fd5eb2cf --- /dev/null +++ b/source/blender/modifiers/intern/MOD_triangulate.c @@ -0,0 +1,144 @@ +/* + * ***** 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): Antony Riakiotakis + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +/** \file blender/modifiers/intern/MOD_triangulate.c + * \ingroup modifiers + */ + +#include "DNA_object_types.h" + +#include "BLI_utildefines.h" + +#include "BKE_cdderivedmesh.h" +#include "BKE_modifier.h" +#include "BKE_tessmesh.h" + +/* triangulation modifier, directly calls the bmesh operator */ + +static DerivedMesh *triangulate_dm(DerivedMesh *dm, const int flag) +{ + DerivedMesh *result; + BMesh *bm; + int total_edges, i; + MEdge *me; + + bm = DM_to_bmesh(dm); + + BM_mesh_elem_toolflags_ensure(bm); + BMO_push(bm, NULL); + + BMO_op_callf(bm, BMO_FLAG_DEFAULTS, + "triangulate faces=%af use_beauty=%b", + (flag & MOD_TRIANGULATE_BEAUTY)); + BMO_pop(bm); + + result = CDDM_from_bmesh(bm, FALSE); + BM_mesh_free(bm); + + total_edges = result->getNumEdges(result); + me = CDDM_get_edges(result); + + /* force drawing of all edges (seems to be omitted in CDDM_from_bmesh) */ + for (i = 0; i < total_edges; i++, me++) + me->flag |= ME_EDGEDRAW | ME_EDGERENDER; + + CDDM_calc_normals(result); + + return result; +} + + +static void initData(ModifierData *md) +{ + TriangulateModifierData *tmd = (TriangulateModifierData *)md; + + /* Enable in editmode by default */ + md->mode |= eModifierMode_Editmode; + tmd->flag = MOD_TRIANGULATE_BEAUTY; +} + + +static void copyData(ModifierData *md, ModifierData *target) +{ + TriangulateModifierData *smd = (TriangulateModifierData *) md; + TriangulateModifierData *tsmd = (TriangulateModifierData *) target; + + *tsmd = *smd; +} + +static DerivedMesh *applyModifierEM(ModifierData *md, + Object *UNUSED(ob), + struct BMEditMesh *UNUSED(em), + DerivedMesh *dm) +{ + TriangulateModifierData *tmd = (TriangulateModifierData *)md; + DerivedMesh *result; + if (!(result = triangulate_dm(dm, tmd->flag))) { + return dm; + } + + return result; +} + +static DerivedMesh *applyModifier(ModifierData *md, + Object *UNUSED(ob), + DerivedMesh *dm, + ModifierApplyFlag UNUSED(flag)) +{ + TriangulateModifierData *tmd = (TriangulateModifierData *)md; + DerivedMesh *result; + if (!(result = triangulate_dm(dm, tmd->flag))) { + return dm; + } + + return result; +} + +ModifierTypeInfo modifierType_Triangulate = { + /* name */ "Triangulate", + /* structName */ "TriangulateModifierData", + /* structSize */ sizeof(TriangulateModifierData), + /* type */ eModifierTypeType_Constructive, + /* flags */ eModifierTypeFlag_AcceptsMesh | + eModifierTypeFlag_SupportsEditmode | + eModifierTypeFlag_SupportsMapping | + eModifierTypeFlag_EnableInEditmode | + eModifierTypeFlag_AcceptsCVs, + + /* copyData */ copyData, + /* deformVerts */ NULL, + /* deformMatrices */ NULL, + /* deformVertsEM */ NULL, + /* deformMatricesEM */ NULL, + /* applyModifier */ applyModifier, + /* applyModifierEM */ applyModifierEM, + /* initData */ initData, + /* requiredDataMask */ NULL, //requiredDataMask, + /* freeData */ NULL, + /* isDisabled */ NULL, + /* updateDepgraph */ NULL, + /* dependsOnTime */ NULL, + /* dependsOnNormals */ NULL, + /* foreachObjectLink */ NULL, + /* foreachIDLink */ NULL, +}; diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c index 3b769a30994..a27d5e5e03b 100644 --- a/source/blender/modifiers/intern/MOD_util.c +++ b/source/blender/modifiers/intern/MOD_util.c @@ -278,5 +278,6 @@ void modifier_type_init(ModifierTypeInfo *types[]) INIT_TYPE(Remesh); INIT_TYPE(Skin); INIT_TYPE(LaplacianSmooth); + INIT_TYPE(Triangulate); #undef INIT_TYPE } diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 7dca4d07b24..141a3680df2 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -84,6 +84,7 @@ set(SRC composite/nodes/node_composite_lummaMatte.c composite/nodes/node_composite_mapUV.c composite/nodes/node_composite_mapValue.c + composite/nodes/node_composite_mapRange.c composite/nodes/node_composite_math.c composite/nodes/node_composite_mask.c composite/nodes/node_composite_mixrgb.c @@ -122,7 +123,6 @@ set(SRC composite/nodes/node_composite_pixelate.c composite/node_composite_tree.c - composite/node_composite_util.c shader/nodes/node_shader_camera.c shader/nodes/node_shader_common.c @@ -222,7 +222,6 @@ set(SRC intern/node_common.c intern/node_socket.c - composite/node_composite_util.h shader/node_shader_util.h texture/node_texture_util.h @@ -235,6 +234,13 @@ 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 diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h index ee67ac88085..eecc1e46827 100644 --- a/source/blender/nodes/NOD_composite.h +++ b/source/blender/nodes/NOD_composite.h @@ -72,6 +72,7 @@ void register_node_type_cmp_huecorrect(struct bNodeTreeType *ttype); void register_node_type_cmp_normal(struct bNodeTreeType *ttype); void register_node_type_cmp_curve_vec(struct bNodeTreeType *ttype); void register_node_type_cmp_map_value(struct bNodeTreeType *ttype); +void register_node_type_cmp_map_range(struct bNodeTreeType *ttype); void register_node_type_cmp_normalize(struct bNodeTreeType *ttype); void register_node_type_cmp_filter(struct bNodeTreeType *ttype); diff --git a/source/blender/nodes/composite/nodes/node_composite_colorbalance.c b/source/blender/nodes/composite/nodes/node_composite_colorbalance.c index e9d26ebebbc..df49e537788 100644 --- a/source/blender/nodes/composite/nodes/node_composite_colorbalance.c +++ b/source/blender/nodes/composite/nodes/node_composite_colorbalance.c @@ -49,14 +49,14 @@ static bNodeSocketTemplate cmp_node_colorbalance_out[] = { #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 + * 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) { diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index 150382c1f8f..88d78df190f 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -173,9 +173,10 @@ static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node) Image *ima= (Image *)node->id; if (ima) { ImageUser *iuser= node->storage; + ImBuf *ibuf; /* make sure ima->type is correct */ - BKE_image_get_ibuf(ima, iuser); + ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); if (ima->rr) { RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer); @@ -191,6 +192,8 @@ static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node) } else cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE|RRES_OUT_ALPHA|RRES_OUT_Z); + + BKE_image_release_ibuf(ima, ibuf, NULL); } else cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE|RRES_OUT_ALPHA); @@ -312,7 +315,7 @@ float *node_composit_get_float_buffer(RenderData *rd, ImBuf *ibuf, int *alloc) } /* note: this function is used for multilayer too, to ensure uniform - * handling with BKE_image_get_ibuf() */ + * handling with BKE_image_acquire_ibuf() */ static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *iuser) { ImBuf *ibuf; @@ -322,7 +325,7 @@ static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *i float *rect; int alloc= FALSE; - ibuf= BKE_image_get_ibuf(ima, iuser); + ibuf= BKE_image_acquire_ibuf(ima, iuser, NULL); if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) { return NULL; } @@ -374,12 +377,15 @@ static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *i } } #endif + + BKE_image_release_ibuf(ima, ibuf, NULL); + return stackbuf; } static CompBuf *node_composit_get_zimage(bNode *node, RenderData *rd) { - ImBuf *ibuf= BKE_image_get_ibuf((Image *)node->id, node->storage); + ImBuf *ibuf= BKE_image_acquire_ibuf((Image *)node->id, node->storage, NULL); CompBuf *zbuf= NULL; if (ibuf && ibuf->zbuf_float) { @@ -391,6 +397,9 @@ static CompBuf *node_composit_get_zimage(bNode *node, RenderData *rd) zbuf->rect= ibuf->zbuf_float; } } + + BKE_image_release_ibuf((Image *)node->id, ibuf, NULL); + return zbuf; } @@ -418,13 +427,14 @@ static void node_composit_exec_image(void *data, bNode *node, bNodeStack **UNUSE 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) - BKE_image_get_ibuf(ima, iuser); + 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); @@ -505,6 +515,8 @@ static void node_composit_exec_image(void *data, bNode *node, bNodeStack **UNUSE generate_preview(data, node, stackbuf); } } + + BKE_image_release_ibuf(ima, ibuf, NULL); } } diff --git a/source/blender/nodes/composite/nodes/node_composite_mapRange.c b/source/blender/nodes/composite/nodes/node_composite_mapRange.c new file mode 100644 index 00000000000..f96e133b19f --- /dev/null +++ b/source/blender/nodes/composite/nodes/node_composite_mapRange.c @@ -0,0 +1,58 @@ +/* + * ***** 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/nodes/node_composite_mapRange.c + * \ingroup cmpnodes + */ + + +#include "node_composite_util.h" + +/* **************** MAP VALUE ******************** */ +static bNodeSocketTemplate cmp_node_map_range_in[] = { + { SOCK_FLOAT, 1, N_("Value"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, + { SOCK_FLOAT, 1, N_("From Min"), 0.0f, 1.0f, 1.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + { SOCK_FLOAT, 1, N_("From Max"), 1.0f, 1.0f, 1.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + { SOCK_FLOAT, 1, N_("To Min"), 0.0f, 1.0f, 1.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + { SOCK_FLOAT, 1, N_("To Max"), 1.0f, 1.0f, 1.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE}, + { -1, 0, "" } +}; +static bNodeSocketTemplate cmp_node_map_range_out[] = { + { SOCK_FLOAT, 0, N_("Value")}, + { -1, 0, "" } +}; + +void register_node_type_cmp_map_range(bNodeTreeType *ttype) +{ + static bNodeType ntype; + + node_type_base(ttype, &ntype, CMP_NODE_MAP_RANGE, "Map Range", NODE_CLASS_OP_VECTOR, NODE_OPTIONS); + node_type_socket_templates(&ntype, cmp_node_map_range_in, cmp_node_map_range_out); + node_type_size(&ntype, 120, 60, 150); + + nodeRegisterType(ttype, &ntype); +} diff --git a/source/blender/nodes/composite/nodes/node_composite_normal.c b/source/blender/nodes/composite/nodes/node_composite_normal.c index 93fd7ca1c1b..d104e8f03e6 100644 --- a/source/blender/nodes/composite/nodes/node_composite_normal.c +++ b/source/blender/nodes/composite/nodes/node_composite_normal.c @@ -40,7 +40,7 @@ static bNodeSocketTemplate cmp_node_normal_in[] = { }; static bNodeSocketTemplate cmp_node_normal_out[] = { - { SOCK_VECTOR, 0, N_("Normal")}, + { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION}, { SOCK_FLOAT, 0, N_("Dot")}, { -1, 0, "" } }; diff --git a/source/blender/nodes/composite/nodes/node_composite_splitViewer.c b/source/blender/nodes/composite/nodes/node_composite_splitViewer.c index 73cf039c6df..41fb0e822ed 100644 --- a/source/blender/nodes/composite/nodes/node_composite_splitViewer.c +++ b/source/blender/nodes/composite/nodes/node_composite_splitViewer.c @@ -77,7 +77,7 @@ static void node_composit_exec_splitviewer(void *data, bNode *node, bNodeStack * ibuf= BKE_image_acquire_ibuf(ima, node->storage, &lock); if (ibuf==NULL) { printf("node_composit_exec_viewer error\n"); - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); return; } @@ -128,7 +128,7 @@ static void node_composit_exec_splitviewer(void *data, bNode *node, bNodeStack * 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, lock); + BKE_image_release_ibuf(ima, ibuf, lock); generate_preview(data, node, cbuf); free_compbuf(cbuf); diff --git a/source/blender/nodes/composite/nodes/node_composite_viewer.c b/source/blender/nodes/composite/nodes/node_composite_viewer.c index 938f75cf3f5..1c27cc21b06 100644 --- a/source/blender/nodes/composite/nodes/node_composite_viewer.c +++ b/source/blender/nodes/composite/nodes/node_composite_viewer.c @@ -62,7 +62,7 @@ static void node_composit_exec_viewer(void *data, bNode *node, bNodeStack **in, ibuf = BKE_image_acquire_ibuf(ima, node->storage, &lock); if (ibuf == NULL) { printf("node_composit_exec_viewer error\n"); - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); return; } @@ -112,7 +112,7 @@ static void node_composit_exec_viewer(void *data, bNode *node, bNodeStack **in, free_compbuf(zbuf); } - BKE_image_release_ibuf(ima, lock); + BKE_image_release_ibuf(ima, ibuf, lock); generate_preview(data, node, cbuf); free_compbuf(cbuf); diff --git a/source/blender/nodes/shader/nodes/node_shader_normal_map.c b/source/blender/nodes/shader/nodes/node_shader_normal_map.c index ee83699abdb..6a4eb9d81df 100644 --- a/source/blender/nodes/shader/nodes/node_shader_normal_map.c +++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.c @@ -31,7 +31,7 @@ static bNodeSocketTemplate sh_node_normal_map_in[] = { { SOCK_FLOAT, 1, N_("Strength"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 10.0f}, - { SOCK_RGBA, 0, N_("Color"), 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f}, + { SOCK_RGBA, 1, N_("Color"), 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f}, { -1, 0, "" } }; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c index abe8e0190c8..d2d0870e2ed 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c @@ -75,12 +75,13 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, GPUNod ret = GPU_stack_link(mat, "node_tex_environment", in, out, GPU_image(ima, iuser, isdata)); if (ret) { - ImBuf *ibuf = BKE_image_get_ibuf(ima, iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 && GPU_material_do_color_management(mat)) { GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link); } + BKE_image_release_ibuf(ima, ibuf, NULL); } return ret; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c index 9b17f76bd47..49b38434246 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c @@ -75,12 +75,13 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, GPUNodeStack ret = GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, isdata)); if (ret) { - ImBuf *ibuf = BKE_image_get_ibuf(ima, iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 && GPU_material_do_color_management(mat)) { GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link); } + BKE_image_release_ibuf(ima, ibuf, NULL); } return ret; diff --git a/source/blender/nodes/shader/nodes/node_shader_texture.c b/source/blender/nodes/shader/nodes/node_shader_texture.c index 6d1b3ff6dba..b77c7d07407 100644 --- a/source/blender/nodes/shader/nodes/node_shader_texture.c +++ b/source/blender/nodes/shader/nodes/node_shader_texture.c @@ -128,12 +128,13 @@ static int gpu_shader_texture(GPUMaterial *mat, bNode *node, GPUNodeStack *in, G int ret = GPU_stack_link(mat, "texture_image", in, out, texlink); if (ret) { - ImBuf *ibuf = BKE_image_get_ibuf(tex->ima, &tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) ==0 && GPU_material_do_color_management(mat)) { GPU_link(mat, "srgb_to_linearrgb", out[1].link, &out[1].link); } + BKE_image_release_ibuf(tex->ima, ibuf, NULL); } return ret; diff --git a/source/blender/nodes/texture/nodes/node_texture_image.c b/source/blender/nodes/texture/nodes/node_texture_image.c index f3fdaf0bb64..2ef1669a266 100644 --- a/source/blender/nodes/texture/nodes/node_texture_image.c +++ b/source/blender/nodes/texture/nodes/node_texture_image.c @@ -46,7 +46,7 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **UNUSED(i ImageUser *iuser= (ImageUser *)node->storage; if ( ima ) { - ImBuf *ibuf = BKE_image_get_ibuf(ima, iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); if ( ibuf ) { float xsize, ysize; float xoff, yoff; @@ -77,6 +77,8 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **UNUSED(i result = ibuf->rect_float + py*ibuf->x*4 + px*4; copy_v4_v4(out, result); + + BKE_image_release_ibuf(ima, ibuf, NULL); } } } diff --git a/source/blender/python/bmesh/bmesh_py_ops.c b/source/blender/python/bmesh/bmesh_py_ops.c index fb5b94249e6..2b82826eb04 100644 --- a/source/blender/python/bmesh/bmesh_py_ops.c +++ b/source/blender/python/bmesh/bmesh_py_ops.c @@ -90,6 +90,7 @@ static PyObject *bpy_bmesh_op_repr(BPy_BMeshOpFunc *self) static PyObject *pyrna_op_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject *kw) { + PyObject *ret; BPy_BMesh *py_bm; BMesh *bm; @@ -122,7 +123,7 @@ static PyObject *pyrna_op_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject * Py_ssize_t pos = 0; while (PyDict_Next(kw, &pos, &key, &value)) { const char *slot_name = _PyUnicode_AsString(key); - BMOpSlot *slot = BMO_slot_get(&bmop, slot_name); + BMOpSlot *slot = BMO_slot_get(bmop.slots_in, slot_name); if (slot == NULL) { PyErr_Format(PyExc_TypeError, @@ -146,7 +147,7 @@ static PyObject *pyrna_op_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject * return NULL; } else { - slot->data.i = param; + BMO_SLOT_AS_BOOL(slot) = param; } break; @@ -169,7 +170,7 @@ static PyObject *pyrna_op_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject * return NULL; } else { - slot->data.i = (int)param; + BMO_SLOT_AS_INT(slot) = (int)param; } break; } @@ -183,7 +184,7 @@ static PyObject *pyrna_op_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject * return NULL; } else { - slot->data.f = param; + BMO_SLOT_AS_FLOAT(slot) = param; } break; } @@ -210,13 +211,13 @@ static PyObject *pyrna_op_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject * return NULL; } - BMO_slot_mat_set(&bmop, slot_name, ((MatrixObject *)value)->matrix, size); + BMO_slot_mat_set(&bmop, bmop.slots_in, slot_name, ((MatrixObject *)value)->matrix, size); break; } case BMO_OP_SLOT_VEC: { /* passing slot name here is a bit non-descriptive */ - if (mathutils_array_parse(slot->data.vec, 3, 3, value, slot_name) == -1) { + if (mathutils_array_parse(BMO_SLOT_AS_VECTOR(slot), 3, 3, value, slot_name) == -1) { return NULL; } break; @@ -243,15 +244,15 @@ static PyObject *pyrna_op_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject * if (BPy_BMVertSeq_Check(value)) { BPY_BM_GENERIC_MESH_TEST("verts"); - BMO_slot_buffer_from_all(bm, &bmop, slot_name, BM_VERT); + BMO_slot_buffer_from_all(bm, &bmop, bmop.slots_in, slot_name, BM_VERT); } else if (BPy_BMEdgeSeq_Check(value)) { BPY_BM_GENERIC_MESH_TEST("edges"); - BMO_slot_buffer_from_all(bm, &bmop, slot_name, BM_EDGE); + BMO_slot_buffer_from_all(bm, &bmop, bmop.slots_in, slot_name, BM_EDGE); } else if (BPy_BMFaceSeq_Check(value)) { BPY_BM_GENERIC_MESH_TEST("faces"); - BMO_slot_buffer_from_all(bm, &bmop, slot_name, BM_FACE); + BMO_slot_buffer_from_all(bm, &bmop, bmop.slots_in, slot_name, BM_FACE); } else if (BPy_BMElemSeq_Check(value)) { BMIter iter; @@ -266,11 +267,11 @@ static PyObject *pyrna_op_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject * /* calls bpy_bmelemseq_length() */ tot = Py_TYPE(value)->tp_as_sequence->sq_length((PyObject *)self); - BMO_slot_buffer_alloc(&bmop, slot_name, tot); + BMO_slot_buffer_alloc(&bmop, bmop.slots_in, slot_name, tot); i = 0; BM_ITER_BPY_BM_SEQ (ele, &iter, ((BPy_BMElemSeq *)value)) { - ((void **)slot->data.buf)[i] = (void *)ele; + slot->data.buf[i] = ele; i++; } } @@ -288,7 +289,7 @@ static PyObject *pyrna_op_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject * return NULL; } - BMO_slot_buffer_alloc(&bmop, slot_name, elem_array_len); + BMO_slot_buffer_alloc(&bmop, bmop.slots_in, slot_name, elem_array_len); memcpy(slot->data.buf, elem_array, sizeof(void *) * elem_array_len); PyMem_FREE(elem_array); } @@ -316,13 +317,104 @@ static PyObject *pyrna_op_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject * } BMO_op_exec(bm, &bmop); - BMO_op_finish(bm, &bmop); - if (bpy_bm_op_as_py_error(bm) == -1) { - return NULL; + /* from here until the end of the function, no returns, just set 'ret' */ + if (UNLIKELY(bpy_bm_op_as_py_error(bm) == -1)) { + ret = NULL; /* exception raised above */ } + else if (bmop.slots_out[0].slot_name == NULL) { + ret = (Py_INCREF(Py_None), Py_None); + } + else { + /* build return value */ + int i; + ret = PyDict_New(); - Py_RETURN_NONE; + for (i = 0; bmop.slots_out[i].slot_name; i++) { + // BMOpDefine *op_def = opdefines[bmop.type]; + // BMOSlotType *slot_type = op_def->slot_types_out[i]; + BMOpSlot *slot = &bmop.slots_out[i]; + PyObject *item = NULL; + + /* keep switch in same order as above */ + switch (slot->slot_type) { + case BMO_OP_SLOT_BOOL: + item = PyBool_FromLong((BMO_SLOT_AS_BOOL(slot))); + break; + case BMO_OP_SLOT_INT: + item = PyLong_FromLong(BMO_SLOT_AS_INT(slot)); + break; + case BMO_OP_SLOT_FLT: + item = PyFloat_FromDouble((double)BMO_SLOT_AS_FLOAT(slot)); + break; + case BMO_OP_SLOT_MAT: + item = Matrix_CreatePyObject((float *)BMO_SLOT_AS_MATRIX(slot), 4, 4, Py_NEW, NULL); + break; + case BMO_OP_SLOT_VEC: + item = Vector_CreatePyObject(BMO_SLOT_AS_VECTOR(slot), slot->len, Py_NEW, NULL); + break; + case BMO_OP_SLOT_ELEMENT_BUF: + { + const int size = slot->len; + void **buffer = BMO_SLOT_AS_BUFFER(slot); + int j; + + item = PyList_New(size); + for (j = 0; j < size; j++) { + BMHeader *ele = buffer[i]; + PyList_SET_ITEM(item, j, ele ? BPy_BMElem_CreatePyObject(bm, ele) : (Py_INCREF(Py_None), Py_None)); + } + break; + } + case BMO_OP_SLOT_MAPPING: + { + GHash *slot_hash = BMO_SLOT_AS_GHASH(slot); + GHashIterator *hash_iter; + item = PyDict_New(); + + for (hash_iter = BLI_ghashIterator_new(slot_hash); + !BLI_ghashIterator_isDone(hash_iter); + BLI_ghashIterator_step(hash_iter) ) + { + BMHeader *ele_key = BLI_ghashIterator_getKey(hash_iter); + BMHeader **ele_val = BLI_ghashIterator_getValue(hash_iter); + + PyObject *py_key = ele_key ? BPy_BMElem_CreatePyObject(bm, ele_key) : (Py_INCREF(Py_None), Py_None); + PyObject *py_val = *ele_val ? BPy_BMElem_CreatePyObject(bm, *ele_val) : (Py_INCREF(Py_None), Py_None); + + PyDict_SetItem(ret, py_key, py_val); + Py_DECREF(py_key); + Py_DECREF(py_val); + } + BLI_ghashIterator_free(hash_iter); + break; + } + } + BLI_assert(item != NULL); + if (item == NULL) { + item = (Py_INCREF(Py_None), Py_None); + } + +#if 1 + /* temp code, strip off '.out' while we keep this convention */ + { + char slot_name_strip[MAX_SLOTNAME]; + char *ch = strchr(slot->slot_name, '.'); /* can't fail! */ + int tot = ch - slot->slot_name; + BLI_assert(ch != NULL); + memcpy(slot_name_strip, slot->slot_name, tot); + slot_name_strip[tot] = '\0'; + PyDict_SetItemString(ret, slot_name_strip, item); + } +#else + PyDict_SetItemString(ret, slot->slot_name, item); +#endif + Py_DECREF(item); + } + } + + BMO_op_finish(bm, &bmop); + return ret; } @@ -413,17 +505,17 @@ static PyObject *bpy_bmesh_fmod_getattro(PyObject *UNUSED(self), PyObject *pynam { const unsigned int tot = bmesh_total_ops; unsigned int i; - const char *name = _PyUnicode_AsString(pyname); + const char *opname = _PyUnicode_AsString(pyname); for (i = 0; i < tot; i++) { - if (strcmp(opdefines[i]->name, name) == 0) { - return bpy_bmesh_op_CreatePyObject(opdefines[i]->name); + if (strcmp(opdefines[i]->opname, opname) == 0) { + return bpy_bmesh_op_CreatePyObject(opdefines[i]->opname); } } PyErr_Format(PyExc_AttributeError, "BMeshOpsModule: operator \"%.200s\" doesn't exist", - name); + opname); return NULL; } @@ -436,7 +528,7 @@ static PyObject *bpy_bmesh_fmod_dir(PyObject *UNUSED(self)) ret = PyList_New(bmesh_total_ops); for (i = 0; i < tot; i++) { - PyList_SET_ITEM(ret, i, PyUnicode_FromString(opdefines[i]->name)); + PyList_SET_ITEM(ret, i, PyUnicode_FromString(opdefines[i]->opname)); } return ret; diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index 2cae10101d1..ee4528df50d 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -801,34 +801,92 @@ static PyObject *bpy_bmesh_to_mesh(BPy_BMesh *self, PyObject *args) Py_RETURN_NONE; } -/* note: rna_Object_to_mesh() also has apply_modifiers arg that works the same way */ PyDoc_STRVAR(bpy_bmesh_from_object_doc, -".. method:: from_object(mesh, apply_modifiers=True)\n" +".. method:: from_object(object, scene, deform=True, render=False, cage=False)\n" "\n" -" Initialize this bmesh from existing object datablock.\n" +" Initialize this bmesh from existing object datablock (currently only meshes are supported).\n" "\n" " :arg object: The object data to load.\n" " :type object: :class:`Object`\n" -" :arg apply_modifiers: Use the final display mesh rather then the deformed cage.\n" -" :type apply_modifiers: boolean\n" +" :arg deform: Apply deformation modifiers.\n" +" :type deform: boolean\n" +" :arg render: Use render settings.\n" +" :type render: boolean\n" +" :arg cage: Get the mesh as a deformed cage.\n" +" :type cage: boolean\n" ); static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args) { PyObject *py_object; + PyObject *py_scene; Object *ob; + struct Scene *scene; BMesh *bm; - int apply_modifiers = TRUE; + int use_deform = TRUE; + int use_render = FALSE; + int use_cage = FALSE; DerivedMesh *dm; + const int mask = CD_MASK_BMESH; BPY_BM_CHECK_OBJ(self); - if (!PyArg_ParseTuple(args, "O|i:from_object", &py_object, &apply_modifiers) || - !(ob = PyC_RNA_AsPointer(py_object, "Object"))) + if (!PyArg_ParseTuple(args, "OO|iii:from_object", &py_object, &py_scene, &use_render, &use_cage) || + !(ob = PyC_RNA_AsPointer(py_object, "Object")) || + !(scene = PyC_RNA_AsPointer(py_scene, "Scene"))) { return NULL; } - dm = apply_modifiers ? ob->derivedFinal : ob->derivedDeform; + if (ob->type != OB_MESH) { + PyErr_SetString(PyExc_ValueError, + "from_object(...): currently only mesh objects are supported"); + return NULL; + } + + /* Write the display mesh into the dummy mesh */ + if (use_deform) { + if (use_render) { + if (use_cage) { + PyErr_SetString(PyExc_ValueError, + "from_object(...): cage arg is unsupported when (render=True)"); + return NULL; + } + else { + dm = mesh_create_derived_render(scene, ob, mask); + } + } + else { + if (use_cage) { + dm = mesh_get_derived_deform(scene, ob, mask); /* ob->derivedDeform */ + } + else { + dm = mesh_get_derived_final(scene, ob, mask); /* ob->derivedFinal */ + } + } + } + else { + /* !use_deform */ + if (use_render) { + if (use_cage) { + PyErr_SetString(PyExc_ValueError, + "from_object(...): cage arg is unsupported when (render=True)"); + return NULL; + } + else { + dm = mesh_create_derived_no_deform_render(scene, ob, NULL, mask); + } + } + else { + if (use_cage) { + PyErr_SetString(PyExc_ValueError, + "from_object(...): cage arg is unsupported when (deform=False, render=False)"); + return NULL; + } + else { + dm = mesh_create_derived_no_deform(scene, ob, NULL, mask); + } + } + } if (dm == NULL) { PyErr_Format(PyExc_ValueError, @@ -840,6 +898,8 @@ static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args) DM_to_bmesh_ex(dm, bm); + dm->release(dm); + Py_RETURN_NONE; } @@ -1790,7 +1850,7 @@ static PyObject *bpy_bmfaceseq_new(BPy_BMElemSeq *self, PyObject *args) } /* check if the face exists */ - if (BM_face_exists(bm, vert_array, vert_seq_len, NULL)) { + if (BM_face_exists(vert_array, vert_seq_len, NULL)) { PyErr_SetString(PyExc_ValueError, "faces.new(verts): face already exists"); goto cleanup; @@ -2012,7 +2072,7 @@ static PyObject *bpy_bmfaceseq_get__method(BPy_BMElemSeq *self, PyObject *args) return NULL; } - if (BM_face_exists(bm, vert_array, vert_seq_len, &f)) { + if (BM_face_exists(vert_array, vert_seq_len, &f)) { ret = BPy_BMFace_CreatePyObject(bm, f); } else { @@ -3306,6 +3366,7 @@ PyObject *BPy_BMElem_CreatePyObject(BMesh *bm, BMHeader *ele) case BM_LOOP: return BPy_BMLoop_CreatePyObject(bm, (BMLoop *)ele); default: + BLI_assert(0); PyErr_SetString(PyExc_SystemError, "internal error"); return NULL; } diff --git a/source/blender/python/bmesh/bmesh_py_types_customdata.c b/source/blender/python/bmesh/bmesh_py_types_customdata.c index 1fea12d105c..14132d08fe6 100644 --- a/source/blender/python/bmesh/bmesh_py_types_customdata.c +++ b/source/blender/python/bmesh/bmesh_py_types_customdata.c @@ -981,7 +981,7 @@ PyObject *BPy_BMLayerItem_GetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer) } case CD_PROP_INT: { - ret = PyLong_FromSsize_t((Py_ssize_t)(*(int *)value)); + ret = PyLong_FromLong(*(int *)value); break; } case CD_PROP_STR: @@ -1060,7 +1060,7 @@ int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObj } case CD_PROP_INT: { - int tmp_val = PyLong_AsSsize_t(py_value); + int tmp_val = PyLong_AsLong(py_value); if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) { PyErr_Format(PyExc_TypeError, "expected an int, not a %.200s", Py_TYPE(py_value)->tp_name); ret = -1; diff --git a/source/blender/python/bmesh/bmesh_py_types_meshdata.c b/source/blender/python/bmesh/bmesh_py_types_meshdata.c index 8316d33ea38..b0870578f5a 100644 --- a/source/blender/python/bmesh/bmesh_py_types_meshdata.c +++ b/source/blender/python/bmesh/bmesh_py_types_meshdata.c @@ -527,7 +527,7 @@ static PyObject *bpy_bmdeformvert_keys(BPy_BMDeformVert *self) ret = PyList_New(self->data->totweight); for (i = 0; i < self->data->totweight; i++, dw++) { - PyList_SET_ITEM(ret, i, PyLong_FromSsize_t(dw->def_nr)); + PyList_SET_ITEM(ret, i, PyLong_FromLong(dw->def_nr)); } return ret; @@ -576,7 +576,7 @@ static PyObject *bpy_bmdeformvert_items(BPy_BMDeformVert *self) for (i = 0; i < self->data->totweight; i++, dw++) { item = PyTuple_New(2); - PyTuple_SET_ITEM(item, 0, PyLong_FromSsize_t(dw->def_nr)); + PyTuple_SET_ITEM(item, 0, PyLong_FromLong(dw->def_nr)); PyTuple_SET_ITEM(item, 1, PyFloat_FromDouble(dw->weight)); PyList_SET_ITEM(ret, i, item); diff --git a/source/blender/python/generic/bgl.c b/source/blender/python/generic/bgl.c index a10bfef2a8d..22b9c1a2208 100644 --- a/source/blender/python/generic/bgl.c +++ b/source/blender/python/generic/bgl.c @@ -613,15 +613,15 @@ static PyObject *Buffer_repr(Buffer *self) } -BGL_Wrap(2, Accum, void, (GLenum, GLfloat)) -BGL_Wrap(1, ActiveTexture, void, (GLenum)) -BGL_Wrap(2, AlphaFunc, void, (GLenum, GLclampf)) +BGL_Wrap(2, Accum, void, (GLenum, GLfloat)) +BGL_Wrap(1, ActiveTexture, void, (GLenum)) +BGL_Wrap(2, AlphaFunc, void, (GLenum, GLclampf)) BGL_Wrap(3, AreTexturesResident, GLboolean, (GLsizei, GLuintP, GLbooleanP)) BGL_Wrap(2, AttachShader, void, (GLuint, GLuint)) -BGL_Wrap(1, Begin, void, (GLenum)) -BGL_Wrap(2, BindTexture, void, (GLenum, GLuint)) -BGL_Wrap(7, Bitmap, void, (GLsizei, GLsizei, GLfloat, - GLfloat, GLfloat, GLfloat, GLubyteP)) +BGL_Wrap(1, Begin, void, (GLenum)) +BGL_Wrap(2, BindTexture, void, (GLenum, GLuint)) +BGL_Wrap(7, Bitmap, void, (GLsizei, GLsizei, GLfloat, + GLfloat, GLfloat, GLfloat, GLubyteP)) BGL_Wrap(2, BlendFunc, void, (GLenum, GLenum)) BGL_Wrap(1, CallList, void, (GLuint)) BGL_Wrap(3, CallLists, void, (GLsizei, GLenum, GLvoidP)) @@ -675,7 +675,7 @@ BGL_Wrap(1, CullFace, void, (GLenum)) BGL_Wrap(2, DeleteLists, void, (GLuint, GLsizei)) BGL_Wrap(1, DeleteProgram, void, (GLuint)) BGL_Wrap(1, DeleteShader, void, (GLuint)) -BGL_Wrap(2, DeleteTextures, void, (GLsizei, GLuintP)) +BGL_Wrap(2, DeleteTextures, void, (GLsizei, GLuintP)) BGL_Wrap(1, DepthFunc, void, (GLenum)) BGL_Wrap(1, DepthMask, void, (GLboolean)) BGL_Wrap(2, DepthRange, void, (GLclampd, GLclampd)) @@ -773,7 +773,7 @@ BGL_Wrap(3, Lighti, void, (GLenum, GLenum, GLint)) BGL_Wrap(3, Lightiv, void, (GLenum, GLenum, GLintP)) BGL_Wrap(2, LineStipple, void, (GLint, GLushort)) BGL_Wrap(1, LineWidth, void, (GLfloat)) -BGL_Wrap(1, LinkProgram, void, (GLuint)) +BGL_Wrap(1, LinkProgram, void, (GLuint)) BGL_Wrap(1, ListBase, void, (GLuint)) BGL_Wrap(1, LoadIdentity, void, (void)) BGL_Wrap(1, LoadMatrixd, void, (GLdoubleP)) @@ -1907,9 +1907,9 @@ PyObject *BPyInit_bgl(void) return submodule; } -static PyObject *Method_ShaderSource (PyObject *UNUSED(self), PyObject *args) +static PyObject *Method_ShaderSource(PyObject *UNUSED(self), PyObject *args) { - int shader; + unsigned int shader; char *source; if (!PyArg_ParseTuple(args, "Is", &shader, &source)) diff --git a/source/blender/python/generic/bpy_internal_import.c b/source/blender/python/generic/bpy_internal_import.c index ad97ceb68d4..8d146bedb48 100644 --- a/source/blender/python/generic/bpy_internal_import.c +++ b/source/blender/python/generic/bpy_internal_import.c @@ -59,6 +59,19 @@ static PyMethodDef bpy_reload_meth; static PyObject *imp_reload_orig = NULL; /* 'builtins' is most likely PyEval_GetBuiltins() */ + +/** + * \note to the discerning developer, yes - this is nasty + * monkey-patching our own import into Python's builtin 'imp' module. + * + * However Python's alternative is to use import hooks, + * which are implemented in a way that we can't use our own importer as a + * fall-back (instead we must try and fail - raise an exception evert time). + * Since importing from blenders text-blocks is not the common case + * I prefer to use Pythons import by default and fall-back to + * Blenders - which we can only do by intercepting import calls I'm afraid. + * - Campbell + */ void bpy_import_init(PyObject *builtins) { PyObject *item; diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index 529b2e708ad..53112d46098 100644 --- a/source/blender/python/generic/idprop_py_api.c +++ b/source/blender/python/generic/idprop_py_api.c @@ -249,7 +249,7 @@ static int BPy_IDGroup_SetName(BPy_IDProperty *self, PyObject *value, void *UNUS #if 0 static PyObject *BPy_IDGroup_GetType(BPy_IDProperty *self) { - return PyLong_FromSsize_t(self->prop->type); + return PyLong_FromLong(self->prop->type); } #endif @@ -351,7 +351,7 @@ const char *BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty prop = IDP_New(IDP_DOUBLE, &val, name); } else if (PyLong_Check(ob)) { - val.i = (int) PyLong_AsSsize_t(ob); + val.i = (int)PyLong_AsLong(ob); prop = IDP_New(IDP_INT, &val, name); } else if (PyUnicode_Check(ob)) { @@ -409,7 +409,7 @@ const char *BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty prop = IDP_New(IDP_ARRAY, &val, name); for (i = 0; i < val.array.len; i++) { item = PySequence_Fast_GET_ITEM(ob_seq_fast, i); - ((int *)IDP_Array(prop))[i] = (int)PyLong_AsSsize_t(item); + ((int *)IDP_Array(prop))[i] = (int)PyLong_AsLong(item); } break; case IDP_IDPARRAY: @@ -1072,7 +1072,7 @@ static int BPy_IDArray_SetItem(BPy_IDArray *self, int index, PyObject *value) ((double *)IDP_Array(self->prop))[index] = d; break; case IDP_INT: - i = PyLong_AsSsize_t(value); + i = PyLong_AsLong(value); if (i == -1 && PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "expected an int type"); return -1; diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index b8537a1359f..f62fdaf09db 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -83,13 +83,13 @@ int PyC_AsArray(void *array, PyObject *value, const Py_ssize_t length, /* could use is_double for 'long int' but no use now */ int *array_int = array; for (i = 0; i < length; i++) { - array_int[i] = PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value_fast, i)); + array_int[i] = PyLong_AsLong(PySequence_Fast_GET_ITEM(value_fast, i)); } } else if (type == &PyBool_Type) { int *array_bool = array; for (i = 0; i < length; i++) { - array_bool[i] = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value_fast, i)) != 0); + array_bool[i] = (PyLong_AsLong(PySequence_Fast_GET_ITEM(value_fast, i)) != 0); } } else { @@ -567,7 +567,7 @@ void PyC_RunQuicky(const char *filepath, int n, ...) ret = PyObject_CallFunction(calcsize, (char *)"s", format); if (ret) { - sizes[i] = PyLong_AsSsize_t(ret); + sizes[i] = PyLong_AsLong(ret); Py_DECREF(ret); ret = PyObject_CallFunction(unpack, (char *)"sy#", format, (char *)ptr, sizes[i]); } diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index a8aa7269b72..b1eeff8b3ae 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -195,12 +195,12 @@ PyDoc_STRVAR(bpy_app_debug_value_doc, ); static PyObject *bpy_app_debug_value_get(PyObject *UNUSED(self), void *UNUSED(closure)) { - return PyLong_FromSsize_t(G.debug_value); + return PyLong_FromLong(G.debug_value); } static int bpy_app_debug_value_set(PyObject *UNUSED(self), PyObject *value, void *UNUSED(closure)) { - int param = PyLong_AsSsize_t(value); + int param = PyLong_AsLong(value); if (param == -1 && PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "bpy.app.debug_value can only be set to a whole number"); diff --git a/source/blender/python/intern/bpy_intern_string.c b/source/blender/python/intern/bpy_intern_string.c index 7c8291d62d3..70ea57bb33f 100644 --- a/source/blender/python/intern/bpy_intern_string.c +++ b/source/blender/python/intern/bpy_intern_string.c @@ -38,6 +38,8 @@ PyObject *bpy_intern_str_bl_rna; PyObject *bpy_intern_str_order; PyObject *bpy_intern_str_attr; PyObject *bpy_intern_str___slots__; +PyObject *bpy_intern_str___name__; +PyObject *bpy_intern_str___doc__; void bpy_intern_string_init(void) { @@ -47,6 +49,8 @@ void bpy_intern_string_init(void) bpy_intern_str_order = PyUnicode_FromString("order"); bpy_intern_str_attr = PyUnicode_FromString("attr"); bpy_intern_str___slots__ = PyUnicode_FromString("__slots__"); + bpy_intern_str___name__ = PyUnicode_FromString("__name__"); + bpy_intern_str___doc__ = PyUnicode_FromString("__doc__"); } void bpy_intern_string_exit(void) @@ -57,4 +61,6 @@ void bpy_intern_string_exit(void) Py_DECREF(bpy_intern_str_order); Py_DECREF(bpy_intern_str_attr); Py_DECREF(bpy_intern_str___slots__); + Py_DECREF(bpy_intern_str___name__); + Py_DECREF(bpy_intern_str___doc__); } diff --git a/source/blender/python/intern/bpy_intern_string.h b/source/blender/python/intern/bpy_intern_string.h index dc7af735743..0b7ca2cd47b 100644 --- a/source/blender/python/intern/bpy_intern_string.h +++ b/source/blender/python/intern/bpy_intern_string.h @@ -33,3 +33,5 @@ extern PyObject *bpy_intern_str_bl_rna; extern PyObject *bpy_intern_str_order; extern PyObject *bpy_intern_str_attr; extern PyObject *bpy_intern_str___slots__; +extern PyObject *bpy_intern_str___name__; +extern PyObject *bpy_intern_str___doc__; diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index eaaced416fe..a0df8988068 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -1344,7 +1344,7 @@ PyObject *pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) ret = PyBool_FromLong(RNA_property_boolean_get(ptr, prop)); break; case PROP_INT: - ret = PyLong_FromSsize_t((Py_ssize_t)RNA_property_int_get(ptr, prop)); + ret = PyLong_FromLong(RNA_property_int_get(ptr, prop)); break; case PROP_FLOAT: ret = PyFloat_FromDouble(RNA_property_float_get(ptr, prop)); @@ -2371,7 +2371,7 @@ static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, Po RNA_property_int_get_array(ptr, prop, values); for (count = start; count < stop; count++) - PyTuple_SET_ITEM(tuple, count - start, PyLong_FromSsize_t(values[count])); + PyTuple_SET_ITEM(tuple, count - start, PyLong_FromLong(values[count])); if (values != values_stack) { PyMem_FREE(values); @@ -4077,7 +4077,7 @@ static PyObject *pyrna_prop_collection_items(BPy_PropertyRNA *self) } else { /* a bit strange but better then returning an empty list */ - PyTuple_SET_ITEM(item, 0, PyLong_FromSsize_t(i)); + PyTuple_SET_ITEM(item, 0, PyLong_FromLong(i)); } PyTuple_SET_ITEM(item, 1, pyrna_struct_CreatePyObject(&itemptr)); @@ -4256,7 +4256,7 @@ static PyObject *pyrna_prop_collection_find(BPy_PropertyRNA *self, PyObject *key } RNA_PROP_END; - return PyLong_FromSsize_t(index); + return PyLong_FromLong(index); } static void foreach_attr_type(BPy_PropertyRNA *self, const char *attr, @@ -4463,13 +4463,13 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set) switch (raw_type) { case PROP_RAW_CHAR: - item = PyLong_FromSsize_t((Py_ssize_t) ((char *)array)[i]); + item = PyLong_FromLong((long) ((char *)array)[i]); break; case PROP_RAW_SHORT: - item = PyLong_FromSsize_t((Py_ssize_t) ((short *)array)[i]); + item = PyLong_FromLong((long) ((short *)array)[i]); break; case PROP_RAW_INT: - item = PyLong_FromSsize_t((Py_ssize_t) ((int *)array)[i]); + item = PyLong_FromLong((long) ((int *)array)[i]); break; case PROP_RAW_FLOAT: item = PyFloat_FromDouble((double) ((float *)array)[i]); @@ -4756,7 +4756,7 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat case PROP_INT: ret = PyTuple_New(len); for (a = 0; a < len; a++) - PyTuple_SET_ITEM(ret, a, PyLong_FromSsize_t((Py_ssize_t)((int *)data)[a])); + PyTuple_SET_ITEM(ret, a, PyLong_FromLong(((int *)data)[a])); break; case PROP_FLOAT: switch (RNA_property_subtype(prop)) { @@ -4797,7 +4797,7 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat ret = PyBool_FromLong(*(int *)data); break; case PROP_INT: - ret = PyLong_FromSsize_t((Py_ssize_t)*(int *)data); + ret = PyLong_FromLong(*(int *)data); break; case PROP_FLOAT: ret = PyFloat_FromDouble(*(float *)data); @@ -6883,8 +6883,8 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v /* Sneaky workaround to use the class name as the bl_idname */ #define BPY_REPLACEMENT_STRING(rna_attr, py_attr) \ - if (strcmp(identifier, rna_attr) == 0) { \ - item = PyObject_GetAttrString(py_class, py_attr); \ + (strcmp(identifier, rna_attr) == 0) { \ + item = PyObject_GetAttr(py_class, py_attr); \ if (item && item != Py_None) { \ if (pyrna_py_to_prop(dummyptr, prop, NULL, \ item, "validating class:") != 0) \ @@ -6894,11 +6894,10 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v } \ } \ Py_XDECREF(item); \ - } (void)0 - + } /* intendionally allow else here */ - BPY_REPLACEMENT_STRING("bl_idname", "__name__"); - BPY_REPLACEMENT_STRING("bl_description", "__doc__"); + if BPY_REPLACEMENT_STRING("bl_idname", bpy_intern_str___name__) + else if BPY_REPLACEMENT_STRING("bl_description", bpy_intern_str___doc__) #undef BPY_REPLACEMENT_STRING @@ -6912,10 +6911,11 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v PyErr_Clear(); } else { - Py_DECREF(item); /* no need to keep a ref, the class owns it */ - - if (pyrna_py_to_prop(dummyptr, prop, NULL, item, "validating class:") != 0) + if (pyrna_py_to_prop(dummyptr, prop, NULL, item, "validating class:") != 0) { + Py_DECREF(item); return -1; + } + Py_DECREF(item); } } diff --git a/source/blender/python/intern/bpy_rna_array.c b/source/blender/python/intern/bpy_rna_array.c index e66d8f05309..62c0ced9eab 100644 --- a/source/blender/python/intern/bpy_rna_array.c +++ b/source/blender/python/intern/bpy_rna_array.c @@ -507,7 +507,7 @@ static void py_to_float(PyObject *py, char *data) static void py_to_int(PyObject *py, char *data) { - *(int *)data = (int)PyLong_AsSsize_t(py); + *(int *)data = (int)PyLong_AsLong(py); } static void py_to_bool(PyObject *py, char *data) @@ -609,7 +609,7 @@ PyObject *pyrna_array_index(PointerRNA *ptr, PropertyRNA *prop, int index) item = PyBool_FromLong(RNA_property_boolean_get_index(ptr, prop, index)); break; case PROP_INT: - item = PyLong_FromSsize_t(RNA_property_int_get_index(ptr, prop, index)); + item = PyLong_FromLong(RNA_property_int_get_index(ptr, prop, index)); break; default: PyErr_SetString(PyExc_TypeError, "not an array type"); @@ -766,7 +766,7 @@ int pyrna_array_contains_py(PointerRNA *ptr, PropertyRNA *prop, PyObject *value) case PROP_BOOLEAN: case PROP_INT: { - int value_i = PyLong_AsSsize_t(value); + int value_i = PyLong_AsLong(value); if (value_i == -1 && PyErr_Occurred()) { PyErr_Clear(); return 0; diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c index 19be2b6a62e..e98af997507 100644 --- a/source/blender/python/mathutils/mathutils_Vector.c +++ b/source/blender/python/mathutils/mathutils_Vector.c @@ -2784,7 +2784,7 @@ static struct PyMethodDef Vector_methods[] = { /* Note * Py_TPFLAGS_CHECKTYPES allows us to avoid casting all types to Vector when coercing * but this means for eg that - * (vec * mat) and (mat * vec) both get sent to Vector_mul and it neesd to sort out the order + * (vec * mat) and (mat * vec) both get sent to Vector_mul and it needs to sort out the order */ PyDoc_STRVAR(vector_doc, diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index 1331c287d7c..d2ffc3a0e26 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -60,6 +60,7 @@ struct Scene; #define RE_ENGINE_PREVIEW 2 #define RE_ENGINE_DO_DRAW 4 #define RE_ENGINE_DO_UPDATE 8 +#define RE_ENGINE_RENDERING 16 extern ListBase R_engines; diff --git a/source/blender/render/intern/include/initrender.h b/source/blender/render/intern/include/initrender.h index 43ab9552194..73dc29c8feb 100644 --- a/source/blender/render/intern/include/initrender.h +++ b/source/blender/render/intern/include/initrender.h @@ -40,8 +40,9 @@ struct Object; void free_sample_tables(Render *re); void make_sample_tables(Render *re); -void initparts(Render *re, int do_crop); -void freeparts(Render *re); +void RE_parts_clamp(Render *re); +void RE_parts_init(Render *re, int do_crop); +void RE_parts_free(Render *re); #endif /* __INITRENDER_H__ */ diff --git a/source/blender/render/intern/raytrace/rayobject_internal.h b/source/blender/render/intern/raytrace/rayobject_internal.h index 92ac39909a8..aa8ab8c3da4 100644 --- a/source/blender/render/intern/raytrace/rayobject_internal.h +++ b/source/blender/render/intern/raytrace/rayobject_internal.h @@ -92,7 +92,7 @@ int RE_rayobjectcontrol_test_break(RayObjectControl *c); * eg.: on render code) * * 0 means it's reserved and has it own meaning inside each ray acceleration structure - * (this way each structure can use the allign offset to determine if a node represents a + * (this way each structure can use the align offset to determine if a node represents a * RayObject primitive, which can be used to save memory) */ diff --git a/source/blender/render/intern/raytrace/rayobject_octree.cpp b/source/blender/render/intern/raytrace/rayobject_octree.cpp index 77e9dc9d8fd..afb8fe6c3b5 100644 --- a/source/blender/render/intern/raytrace/rayobject_octree.cpp +++ b/source/blender/render/intern/raytrace/rayobject_octree.cpp @@ -1026,7 +1026,7 @@ static int RE_rayobject_octree_intersect(RayObject *tree, Isect *is) labdao = ddalabda; - /* traversing ocree nodes need careful detection of smallest values, with proper + /* traversing octree nodes need careful detection of smallest values, with proper * exceptions for equal labdas */ eqval = (labdax == labday); if (labday == labdaz) eqval += 2; diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp index bae65c492f4..4195b103811 100644 --- a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp +++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp @@ -435,7 +435,7 @@ int rtbuild_heuristic_object_split(RTBuilder *b, int nchilds) /* * Helper code * PARTITION code / used on mean-split - * basicly this a std::nth_element (like on C++ STL algorithm) + * basically this a std::nth_element (like on C++ STL algorithm) */ #if 0 static void split_leafs(RTBuilder *b, int *nth, int partitions, int split_axis) diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 759b0737c01..d6e6171047e 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -125,7 +125,9 @@ #define FLT_EPSILON10 1.19209290e-06F /* could enable at some point but for now there are far too many conversions */ -#pragma GCC diagnostic ignored "-Wdouble-promotion" +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wdouble-promotion" +#endif /* ------------------------------------------------------------------------- */ diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c index 28f70211a9c..c3126e57b53 100644 --- a/source/blender/render/intern/source/envmap.c +++ b/source/blender/render/intern/source/envmap.c @@ -687,11 +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_get_ibuf(env->ima, NULL); + ImBuf *ibuf_ima = BKE_image_acquire_ibuf(env->ima, NULL, NULL); if (ibuf_ima) envmap_split_ima(env, ibuf_ima); else env->ok = 0; + BKE_image_release_ibuf(env->ima, ibuf_ima, NULL); } } } diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index d771cf2253d..6fdf11ba48c 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -316,6 +316,7 @@ int RE_engine_render(Render *re, int do_all) { RenderEngineType *type = RE_engines_find(re->r.engine); RenderEngine *engine; + int persistent_data = re->r.mode & R_PERSISTENT_DATA; /* verify if we can render */ if (!type->render) @@ -349,11 +350,17 @@ int RE_engine_render(Render *re, int do_all) re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0; /* render */ - if(!re->engine) - re->engine = RE_engine_create(type); - engine = re->engine; + if (!engine) { + engine = RE_engine_create(type); + + if (persistent_data) + re->engine = engine; + } + + engine->flag |= RE_ENGINE_RENDERING; + /* TODO: actually link to a parent which shouldn't happen */ engine->re = re; @@ -369,7 +376,7 @@ int RE_engine_render(Render *re, int do_all) if ((re->r.scemode & (R_NO_FRAME_UPDATE | R_PREVIEWBUTS)) == 0) BKE_scene_update_for_newframe(re->main, re->scene, re->lay); - initparts(re, FALSE); + RE_parts_init(re, FALSE); engine->tile_x = re->partx; engine->tile_y = re->party; @@ -382,8 +389,15 @@ int RE_engine_render(Render *re, int do_all) if (type->render) type->render(engine, re->scene); - if(!(re->r.mode & R_PERSISTENT_DATA)) { - RE_engine_free(re->engine); + engine->tile_x = 0; + engine->tile_y = 0; + engine->flag &= ~RE_ENGINE_RENDERING; + + render_result_free_list(&engine->fullresult, engine->fullresult.first); + + /* re->engine becomes zero if user changed active render engine during render */ + if (!persistent_data || !re->engine) { + RE_engine_free(engine); re->engine = NULL; } @@ -393,11 +407,7 @@ int RE_engine_render(Render *re, int do_all) BLI_rw_mutex_unlock(&re->resultmutex); } - engine->tile_x = 0; - engine->tile_y = 0; - freeparts(re); - - render_result_free_list(&engine->fullresult, engine->fullresult.first); + RE_parts_free(re); if (BKE_reports_contain(re->reports, RPT_ERROR)) G.is_break = TRUE; diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c index db1454fd82f..cd06839b004 100644 --- a/source/blender/render/intern/source/imagetexture.c +++ b/source/blender/render/intern/source/imagetexture.c @@ -124,13 +124,16 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul /* hack for icon render */ if (ima->ibufs.first==NULL && (R.r.scemode & R_NO_IMAGE_LOAD)) return retval; - - ibuf= BKE_image_get_ibuf(ima, &tex->iuser); + + ibuf= BKE_image_acquire_ibuf(ima, &tex->iuser, NULL); ima->flag|= IMA_USED_FOR_RENDER; } - if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) + if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); return retval; + } /* setup mapping */ if (tex->imaflag & TEX_IMAROT) { @@ -155,11 +158,17 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul /* pass */ } else { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); return retval; } } if ( (tex->flag & TEX_CHECKER_EVEN)==0) { - if ((xs+ys) & 1) return retval; + if ((xs+ys) & 1) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); + return retval; + } } /* scale around center, (0.5, 0.5) */ if (tex->checkerdist<1.0f) { @@ -173,11 +182,15 @@ 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); 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); return retval; } } @@ -287,6 +300,9 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul texres->tb*= fx; } + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); + BRICONTRGB; return retval; @@ -1056,10 +1072,14 @@ 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_get_ibuf(ima, &tex->iuser); + ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL); } - if ((ibuf == NULL) || ((ibuf->rect == NULL) && (ibuf->rect_float == NULL))) return retval; + if ((ibuf == NULL) || ((ibuf->rect == NULL) && (ibuf->rect_float == NULL))) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); + return retval; + } if (ima) { ima->flag |= IMA_USED_FOR_RENDER; @@ -1172,8 +1192,16 @@ 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) return retval; - if ((tex->flag & TEX_CHECKER_EVEN) == 0 && (xs + ys) & 1) return retval; + if ((tex->flag & TEX_CHECKER_ODD) == 0 && ((xs + ys) & 1) == 0) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); + return retval; + } + if ((tex->flag & TEX_CHECKER_EVEN) == 0 && (xs + ys) & 1) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); + return retval; + } fx -= xs; fy -= ys; } @@ -1189,10 +1217,18 @@ 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) return retval; + 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); + 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) return retval; + 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); + return retval; + } } else { if (tex->extend == TEX_EXTEND) { @@ -1413,6 +1449,9 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex texres->tb *= fx; } + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); + BRICONTRGB; return retval; @@ -1449,12 +1488,15 @@ 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_get_ibuf(ima, &tex->iuser); + ibuf= BKE_image_acquire_ibuf(ima, &tex->iuser, NULL); ima->flag|= IMA_USED_FOR_RENDER; } - if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) + if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); return retval; + } /* mipmap test */ image_mipmap_test(tex, ibuf); @@ -1565,11 +1607,15 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const /* pass */ } else { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); return retval; } } if ( (tex->flag & TEX_CHECKER_EVEN)==0) { if ((xs + ys) & 1) { + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); return retval; } } @@ -1605,11 +1651,15 @@ 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); 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); return retval; } } @@ -1804,6 +1854,9 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const mul_v3_fl(&texres->tr, 1.0f / texres->ta); } + if (ima) + BKE_image_release_ibuf(ima, ibuf, NULL); + BRICONTRGB; return retval; @@ -1812,7 +1865,7 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const void image_sample(Image *ima, float fx, float fy, float dx, float dy, float result[4]) { TexResult texres; - ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL); if (UNLIKELY(ibuf == NULL)) { zero_v4(result); @@ -1830,6 +1883,8 @@ void image_sample(Image *ima, float fx, float fy, float dx, float dy, float resu ibuf->rect-= (ibuf->x*ibuf->y); ima->flag|= IMA_USED_FOR_RENDER; + + BKE_image_release_ibuf(ima, ibuf, NULL); } void ibuf_sample(ImBuf *ibuf, float fx, float fy, float dx, float dy, float result[4]) diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c index b2cf8db7995..3ea74abbcc2 100644 --- a/source/blender/render/intern/source/initrender.c +++ b/source/blender/render/intern/source/initrender.c @@ -525,7 +525,7 @@ void RE_GetCameraWindow(struct Render *re, struct Object *camera, int frame, flo /* ~~~~~~~~~~~~~~~~ part (tile) calculus ~~~~~~~~~~~~~~~~~~~~~~ */ -void freeparts(Render *re) +void RE_parts_free(Render *re) { RenderPart *part = re->parts.first; @@ -537,12 +537,19 @@ void freeparts(Render *re) BLI_freelistN(&re->parts); } -void initparts(Render *re, int do_crop) +void RE_parts_clamp(Render *re) +{ + /* part size */ + re->partx = min_ii(re->r.tilex, re->rectx); + re->party = min_ii(re->r.tiley, re->recty); +} + +void RE_parts_init(Render *re, int do_crop) { int nr, xd, yd, partx, party, xparts, yparts; int xminb, xmaxb, yminb, ymaxb; - freeparts(re); + RE_parts_free(re); /* this is render info for caller, is not reset when parts are freed! */ re->i.totpart = 0; @@ -555,13 +562,10 @@ void initparts(Render *re, int do_crop) xmaxb = re->disprect.xmax; ymaxb = re->disprect.ymax; - /* part size */ - partx = min_ii(re->r.tilex, re->rectx); - party = min_ii(re->r.tiley, re->recty); - - re->partx = partx; - re->party = party; - + RE_parts_clamp(re); + + partx = re->partx; + party = re->party; /* part count */ xparts = (re->rectx + partx - 1) / partx; yparts = (re->recty + party - 1) / party; diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 85cafa07759..6b5b9716f3b 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -63,6 +63,7 @@ #include "BLI_string.h" #include "BLI_path_util.h" #include "BLI_fileops.h" +#include "BLI_threads.h" #include "BLI_rand.h" #include "BLI_callbacks.h" @@ -432,7 +433,10 @@ void RE_FreePersistentData(void) /* render engines can be kept around for quick re-render, this clears all */ for (re = RenderGlobal.renderlist.first; re; re = re->next) { if (re->engine) { - RE_engine_free(re->engine); + /* if engine is currently rendering, just tag it to be freed when render is finished */ + if (!(re->engine->flag & RE_ENGINE_RENDERING)) + RE_engine_free(re->engine); + re->engine = NULL; } } @@ -689,7 +693,7 @@ static void *do_part_thread(void *pa_v) /* calculus for how much 1 pixel rendered should rotate the 3d geometry */ /* is not that simple, needs to be corrected for errors of larger viewplane sizes */ -/* called in initrender.c, initparts() and convertblender.c, for speedvectors */ +/* called in initrender.c, RE_parts_init() and convertblender.c, for speedvectors */ float panorama_pixel_rot(Render *re) { float psize, phi, xfac; @@ -832,7 +836,7 @@ static void threaded_tile_processor(Render *re) /* warning; no return here without closing exr file */ - initparts(re, TRUE); + RE_parts_init(re, TRUE); if (re->result->do_exr_tile) render_result_exr_file_begin(re); @@ -924,7 +928,7 @@ static void threaded_tile_processor(Render *re) g_break = 0; BLI_end_threads(&threads); - freeparts(re); + RE_parts_free(re); re->viewplane = viewplane; /* restore viewplane, modified by pano render */ } @@ -943,6 +947,7 @@ static void do_render_3d(Render *re) return; /* internal */ + RE_parts_clamp(re); // re->cfra= cfra; /* <- unused! */ re->scene->r.subframe = re->mblur_offs + re->field_offs; diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index c507d6595e0..e6daa5f9094 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -1233,11 +1233,13 @@ int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int os rgbnor = multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output); if (mtex->mapto & (MAP_COL+MAP_COLSPEC+MAP_COLMIR)) { - ImBuf *ibuf = BKE_image_get_ibuf(tex->ima, &tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); /* 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); } } else { @@ -1264,11 +1266,13 @@ int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int os rgbnor= multitex(tex, texvec_l, dxt_l, dyt_l, osatex, texres, thread, which_output); { - ImBuf *ibuf = BKE_image_get_ibuf(tex->ima, &tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); /* 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); } } @@ -1723,11 +1727,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_get_ibuf(tex->ima, &tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); if (ibuf) { du = 1.f/(float)ibuf->x; dv = 1.f/(float)ibuf->y; } + BKE_image_release_ibuf(tex->ima, ibuf, NULL); } else if (shi->osatex) { /* we have derivatives, can compute proper du/dv */ @@ -1900,12 +1905,13 @@ 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_get_ibuf(tex->ima, &tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL); if (ibuf) { dimx = ibuf->x; dimy = ibuf->y; aspect = ((float) dimy) / dimx; } + BKE_image_release_ibuf(tex->ima, ibuf, NULL); } if (found_deriv_map) { @@ -2396,11 +2402,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_get_ibuf(ima, &tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL); /* 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); } if (mtex->mapto & MAP_COL) { @@ -2928,11 +2936,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_get_ibuf(ima, &mtex->tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &mtex->tex->iuser, NULL); /* 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); } fact= texres.tin*mtex->colfac; @@ -3147,11 +3157,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_get_ibuf(ima, &tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL); /* 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); } if (mtex->mapto & WOMAP_HORIZ) { @@ -3361,11 +3373,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_get_ibuf(ima, &tex->iuser); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &tex->iuser, NULL); /* 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); } /* lamp colors were premultiplied with this */ diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 9fe2620747c..3431c3ff5de 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -2506,21 +2506,26 @@ static int get_next_bake_face(BakeShade *bs) if (tface && tface->tpage) { Image *ima= tface->tpage; - ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, 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}; if (ibuf==NULL) continue; - if (ibuf->rect==NULL && ibuf->rect_float==NULL) + 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)) + 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; } @@ -2548,6 +2553,9 @@ static int get_next_bake_face(BakeShade *bs) v++; BLI_unlock_thread(LOCK_CUSTOM1); + + BKE_image_release_ibuf(ima, ibuf, NULL); + return 1; } } @@ -2571,8 +2579,10 @@ static void shade_tface(BakeShade *bs) /* check valid zspan */ if (ima!=bs->ima) { + BKE_image_release_ibuf(bs->ima, bs->ibuf, NULL); + bs->ima= ima; - bs->ibuf= BKE_image_get_ibuf(ima, NULL); + 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); @@ -2638,7 +2648,9 @@ static void *do_bake_thread(void *bs_v) *bs->do_update= TRUE; } bs->ready= 1; - + + BKE_image_release_ibuf(bs->ima, bs->ibuf, NULL); + return NULL; } @@ -2689,12 +2701,13 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up /* baker uses this flag to detect if image was initialized */ for (ima= G.main->image.first; ima; ima= ima->id.next) { - ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + 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); @@ -2747,7 +2760,7 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up /* filter and refresh images */ for (ima= G.main->image.first; ima; ima= ima->id.next) { if ((ima->id.flag & LIB_DOIT)==0) { - ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, NULL); if (ima->flag & IMA_USED_FOR_RENDER) result= BAKE_RESULT_FEEDBACK_LOOP; @@ -2758,6 +2771,7 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up RE_bake_ibuf_filter(ibuf, (char *)ibuf->userdata, re->r.bake_filter); ibuf->userflags |= IB_BITMAPDIRTY; + BKE_image_release_ibuf(ima, ibuf, NULL); } } diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index 7a7602dcce2..44daaf516e1 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -1179,30 +1179,36 @@ HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Mater /* -------------------------- operations on entire database ----------------------- */ /* ugly function for halos in panorama */ -static int panotestclip(Render *re, int do_pano, float *v) +static int panotestclip(Render *re, int do_pano, float v[4]) { - /* to be used for halos en infos */ - float abs4; - short c=0; - int xparts = (re->rectx + re->partx - 1) / re->partx; + /* part size (ensure we run RE_parts_clamp first) */ + BLI_assert(re->partx == min_ii(re->r.tilex, re->rectx)); + BLI_assert(re->party == min_ii(re->r.tiley, re->recty)); if (do_pano == FALSE) { return testclip(v); } + else { + /* to be used for halos en infos */ + float abs4; + short c = 0; + + int xparts = (re->rectx + re->partx - 1) / re->partx; - abs4= fabs(v[3]); + abs4= fabsf(v[3]); - if (v[2]< -abs4) c=16; /* this used to be " if (v[2]<0) ", see clippz() */ - else if (v[2]> abs4) c+= 32; + if (v[2]< -abs4) c=16; /* this used to be " if (v[2]<0) ", see clippz() */ + else if (v[2]> abs4) c+= 32; - if ( v[1]>abs4) c+=4; - else if ( v[1]< -abs4) c+=8; + if ( v[1]>abs4) c+=4; + else if ( v[1]< -abs4) c+=8; - abs4*= xparts; - if ( v[0]>abs4) c+=2; - else if ( v[0]< -abs4) c+=1; + abs4*= xparts; + if ( v[0]>abs4) c+=2; + else if ( v[0]< -abs4) c+=1; - return c; + return c; + } } /** diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index 77602edf955..597196f464b 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -58,7 +58,9 @@ #include "shading.h" /* own include */ /* could enable at some point but for now there are far too many conversions */ -#pragma GCC diagnostic ignored "-Wdouble-promotion" +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wdouble-promotion" +#endif /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ diff --git a/source/blender/render/intern/source/sunsky.c b/source/blender/render/intern/source/sunsky.c index e4a42fcd675..e812b99287c 100644 --- a/source/blender/render/intern/source/sunsky.c +++ b/source/blender/render/intern/source/sunsky.c @@ -118,8 +118,8 @@ static void DirectionToThetaPhi(float *toSun, float *theta, float *phi) /** * PerezFunction: - * compute perez function value based on input paramters - * */ + * compute perez function value based on input parameters + */ static float PerezFunction(struct SunSky *sunsky, const float *lam, float theta, float gamma, float lvz) { float den, num; diff --git a/source/blender/render/intern/source/voxeldata.c b/source/blender/render/intern/source/voxeldata.c index 42849a01971..77d6644479a 100644 --- a/source/blender/render/intern/source/voxeldata.c +++ b/source/blender/render/intern/source/voxeldata.c @@ -157,10 +157,10 @@ static void load_frame_image_sequence(VoxelData *vd, Tex *tex) /* find the first valid ibuf and use it to initialize the resolution of the data set */ /* need to do this in advance so we know how much memory to allocate */ - ibuf = BKE_image_get_ibuf(ima, &iuser); + ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); while (!ibuf && (iuser.framenr < iuser.frames)) { iuser.framenr++; - ibuf = BKE_image_get_ibuf(ima, &iuser); + ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); } if (!ibuf) return; if (!ibuf->rect_float) IMB_float_from_rect(ibuf); @@ -175,7 +175,8 @@ static void load_frame_image_sequence(VoxelData *vd, Tex *tex) /* get a new ibuf for each frame */ if (z > 0) { iuser.framenr++; - ibuf = BKE_image_get_ibuf(ima, &iuser); + BKE_image_release_ibuf(ima, ibuf, NULL); + ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL); if (!ibuf) break; if (!ibuf->rect_float) IMB_float_from_rect(ibuf); } @@ -191,7 +192,9 @@ static void load_frame_image_sequence(VoxelData *vd, Tex *tex) BKE_image_free_anim_ibufs(ima, iuser.framenr); } - + + BKE_image_release_ibuf(ima, ibuf, NULL); + vd->ok = 1; return; } diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index 62bf9ac2005..c52fb84a7f8 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -77,7 +77,9 @@ #include "zbuf.h" /* could enable at some point but for now there are far too many conversions */ -#pragma GCC diagnostic ignored "-Wdouble-promotion" +#ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wdouble-promotion" +#endif /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */ diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 9a3b8513810..ecb70a5740e 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -181,6 +181,7 @@ int WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const char imt /* poll callback, context checks */ int WM_operator_winactive (struct bContext *C); /* invoke callback, exec + redo popup */ +int WM_operator_props_popup_call(struct bContext *C, struct wmOperator *op, struct wmEvent *event); int WM_operator_props_popup (struct bContext *C, struct wmOperator *op, struct wmEvent *event); int WM_operator_props_dialog_popup (struct bContext *C, struct wmOperator *op, int width, int height); int WM_operator_redo_popup (struct bContext *C, struct wmOperator *op); diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index ad19df3aaf6..97808d75dbe 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -718,14 +718,14 @@ static int wm_automatic_draw_method(wmWindow *win) if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE)) return USER_DRAW_OVERLAP; /* also Intel drivers are slow */ - /* 2.64 BCon3 period, let's try if intel now works... +#if 0 /* 2.64 BCon3 period, let's try if intel now works... */ else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_UNIX, GPU_DRIVER_ANY)) return USER_DRAW_OVERLAP; else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_ANY)) return USER_DRAW_OVERLAP_FLIP; else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_MAC, GPU_DRIVER_ANY)) return USER_DRAW_OVERLAP_FLIP; - */ +#endif /* Windows software driver darkens color on each redraw */ else if (GPU_type_matches(GPU_DEVICE_SOFTWARE, GPU_OS_WIN, GPU_DRIVER_SOFTWARE)) return USER_DRAW_OVERLAP_FLIP; @@ -760,6 +760,15 @@ void wm_draw_update(bContext *C) GPU_free_unused_buffers(); for (win = wm->windows.first; win; win = win->next) { + int state = GHOST_GetWindowState(win->ghostwin);; + + if (state == GHOST_kWindowStateMinimized) { + /* do not update minimized windows, it gives issues on intel drivers (see [#33223]) + * anyway, it seems logical to skip update for invisile windows + */ + continue; + } + if (win->drawmethod != U.wmdrawmethod) { wm_draw_window_clear(win); win->drawmethod = U.wmdrawmethod; diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 551f9157dfe..4066c8d7f5a 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -341,7 +341,7 @@ static int wm_handler_ui_call(bContext *C, wmEventHandler *handler, wmEvent *eve int retval; /* UI code doesn't handle return values - it just always returns break. - to make the DBL_CLICK conversion work, we just don't send this to UI */ + * to make the DBL_CLICK conversion work, we just don't send this to UI */ if (event->val == KM_DBL_CLICK) return WM_HANDLER_CONTINUE; @@ -1280,74 +1280,6 @@ int WM_userdef_event_map(int kmitype) return kmitype; } -static void wm_eventemulation(wmEvent *event) -{ - /* Store last mmb event value to make emulation work when modifier keys are released first. */ - static int mmb_emulated = 0; /* this should be in a data structure somwhere */ - - /* middlemouse emulation */ - if (U.flag & USER_TWOBUTTONMOUSE) { - if (event->type == LEFTMOUSE) { - - if (event->val == KM_PRESS && event->alt) { - event->type = MIDDLEMOUSE; - event->alt = 0; - mmb_emulated = 1; - } - else if (event->val == KM_RELEASE) { - /* only send middle-mouse release if emulated */ - if (mmb_emulated) { - event->type = MIDDLEMOUSE; - event->alt = 0; - } - mmb_emulated = 0; - } - } - - } - -#ifdef __APPLE__ - - /* rightmouse emulation */ - if (U.flag & USER_TWOBUTTONMOUSE) { - if (event->type == LEFTMOUSE) { - - if (event->val == KM_PRESS && event->oskey) { - event->type = RIGHTMOUSE; - event->oskey = 0; - mmb_emulated = 1; - } - else if (event->val == KM_RELEASE) { - if (mmb_emulated) { - event->oskey = RIGHTMOUSE; - event->alt = 0; - } - mmb_emulated = 0; - } - } - - } -#endif - - /* numpad emulation */ - if (U.flag & USER_NONUMPAD) { - switch (event->type) { - case ZEROKEY: event->type = PAD0; break; - case ONEKEY: event->type = PAD1; break; - case TWOKEY: event->type = PAD2; break; - case THREEKEY: event->type = PAD3; break; - case FOURKEY: event->type = PAD4; break; - case FIVEKEY: event->type = PAD5; break; - case SIXKEY: event->type = PAD6; break; - case SEVENKEY: event->type = PAD7; break; - case EIGHTKEY: event->type = PAD8; break; - case NINEKEY: event->type = PAD9; break; - case MINUSKEY: event->type = PADMINUS; break; - case EQUALKEY: event->type = PADPLUSKEY; break; - case BACKSLASHKEY: event->type = PADSLASHKEY; break; - } - } -} static int wm_eventmatch(wmEvent *winevent, wmKeyMapItem *kmi) { @@ -1357,9 +1289,9 @@ static int wm_eventmatch(wmEvent *winevent, wmKeyMapItem *kmi) /* the matching rules */ if (kmitype == KM_TEXTINPUT) - if (winevent->val == KM_PRESS) { // prevent double clicks + if (winevent->val == KM_PRESS) { /* prevent double clicks */ /* NOT using ISTEXTINPUT anymore because (at least on Windows) some key codes above 255 - could have printable ascii keys - BUG [#30479] */ + * could have printable ascii keys - BUG [#30479] */ if (ISKEYBOARD(winevent->type) && (winevent->ascii || winevent->utf8_buf[0])) return 1; } @@ -1379,7 +1311,8 @@ static int wm_eventmatch(wmEvent *winevent, wmKeyMapItem *kmi) if (kmi->oskey != KM_ANY) if (winevent->oskey != kmi->oskey && !(winevent->oskey & kmi->oskey)) return 0; - if (winevent->keymodifier != kmi->keymodifier) return 0; + if (kmi->keymodifier) + if (winevent->keymodifier != kmi->keymodifier) return 0; return 1; @@ -1619,8 +1552,8 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa if (handler->op->reports->list.first) { /* FIXME, temp setting window, this is really bad! - * only have because lib linking errors need to be seen by users :( - * it can be removed without breaking anything but then no linking errors - campbell */ + * only have because lib linking errors need to be seen by users :( + * it can be removed without breaking anything but then no linking errors - campbell */ wmWindow *win_prev = CTX_wm_window(C); ScrArea *area_prev = CTX_wm_area(C); ARegion *ar_prev = CTX_wm_region(C); @@ -2114,8 +2047,6 @@ void wm_event_do_handlers(bContext *C) } #endif - wm_eventemulation(event); - CTX_wm_window_set(C, win); /* we let modal handlers get active area/region, also wm_paintcursor_test needs it */ @@ -2617,6 +2548,75 @@ static int convert_key(GHOST_TKey key) } } +static void wm_eventemulation(wmEvent *event) +{ + /* Store last mmb event value to make emulation work when modifier keys are released first. */ + static int mmb_emulated = 0; /* this should be in a data structure somwhere */ + + /* middlemouse emulation */ + if (U.flag & USER_TWOBUTTONMOUSE) { + if (event->type == LEFTMOUSE) { + + if (event->val == KM_PRESS && event->alt) { + event->type = MIDDLEMOUSE; + event->alt = 0; + mmb_emulated = 1; + } + else if (event->val == KM_RELEASE) { + /* only send middle-mouse release if emulated */ + if (mmb_emulated) { + event->type = MIDDLEMOUSE; + event->alt = 0; + } + mmb_emulated = 0; + } + } + + } + +#ifdef __APPLE__ + + /* rightmouse emulation */ + if (U.flag & USER_TWOBUTTONMOUSE) { + if (event->type == LEFTMOUSE) { + + if (event->val == KM_PRESS && event->oskey) { + event->type = RIGHTMOUSE; + event->oskey = 0; + mmb_emulated = 1; + } + else if (event->val == KM_RELEASE) { + if (mmb_emulated) { + event->oskey = RIGHTMOUSE; + event->alt = 0; + } + mmb_emulated = 0; + } + } + + } +#endif + + /* numpad emulation */ + if (U.flag & USER_NONUMPAD) { + switch (event->type) { + case ZEROKEY: event->type = PAD0; break; + case ONEKEY: event->type = PAD1; break; + case TWOKEY: event->type = PAD2; break; + case THREEKEY: event->type = PAD3; break; + case FOURKEY: event->type = PAD4; break; + case FIVEKEY: event->type = PAD5; break; + case SIXKEY: event->type = PAD6; break; + case SEVENKEY: event->type = PAD7; break; + case EIGHTKEY: event->type = PAD8; break; + case NINEKEY: event->type = PAD9; break; + case MINUSKEY: event->type = PADMINUS; break; + case EQUALKEY: event->type = PADPLUSKEY; break; + case BACKSLASHKEY: event->type = PADSLASHKEY; break; + } + } +} + /* adds customdata to event */ static void update_tablet_data(wmWindow *win, wmEvent *event) { @@ -2826,6 +2826,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U else event.type = MIDDLEMOUSE; + wm_eventemulation(&event); + /* copy previous state to prev event state (two old!) */ evt->prevval = evt->val; evt->prevtype = evt->type; @@ -2891,6 +2893,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U memcpy(event.utf8_buf, kd->utf8_buf, sizeof(event.utf8_buf)); /* might be not null terminated*/ event.val = (type == GHOST_kEventKeyDown) ? KM_PRESS : KM_RELEASE; + wm_eventemulation(&event); + /* copy previous state to prev event state (two old!) */ evt->prevval = evt->val; evt->prevtype = evt->type; diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c index f5c83d48cb9..7481c01d72b 100644 --- a/source/blender/windowmanager/intern/wm_jobs.c +++ b/source/blender/windowmanager/intern/wm_jobs.c @@ -405,9 +405,11 @@ void WM_jobs_kill_all(wmWindowManager *wm) /* wait until every job ended, except for one owner (used in undo to keep screen job alive) */ void WM_jobs_kill_all_except(wmWindowManager *wm, void *owner) { - wmJob *wm_job; + wmJob *wm_job, *next_job; - for (wm_job = wm->jobs.first; wm_job; wm_job = wm_job->next) { + for (wm_job = wm->jobs.first; wm_job; wm_job = next_job) { + next_job = wm_job->next; + if (wm_job->owner != owner) wm_jobs_kill_job(wm, wm_job); } diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 7aa2b403897..4fe1e3b64ab 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -101,11 +101,8 @@ static int wm_keymap_item_equals_result(wmKeyMapItem *a, wmKeyMapItem *b) if (strcmp(a->idname, b->idname) != 0) return 0; - if (!((a->ptr == NULL && b->ptr == NULL) || - (a->ptr && b->ptr && IDP_EqualsProperties(a->ptr->data, b->ptr->data)))) - { + if (!RNA_struct_equals(a->ptr, b->ptr)) return 0; - } if ((a->flag & KMI_INACTIVE) != (b->flag & KMI_INACTIVE)) return 0; @@ -545,7 +542,7 @@ static wmKeyMap *wm_keymap_patch_update(ListBase *lb, wmKeyMap *defaultmap, wmKe /* copy new keymap from an existing one */ if (usermap && !(usermap->flag & KEYMAP_DIFF)) { - /* for compatibiltiy with old user preferences with non-diff + /* for compatibility with old user preferences with non-diff * keymaps we override the original entirely */ wmKeyMapItem *kmi, *orig_kmi; diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 962eb55996d..69b2d5326a4 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -625,7 +625,7 @@ void WM_operator_properties_sanitize(PointerRNA *ptr, const short no_context) /** set all props to their default, * \param do_update Only update un-initialized props. * - * \note, theres nothing spesific to operators here. + * \note, theres nothing specific to operators here. * this could be made a general function. */ int WM_operator_properties_default(PointerRNA *ptr, const int do_update) @@ -1187,6 +1187,8 @@ static void wm_operator_ui_popup_ok(struct bContext *C, void *arg, int retval) if (op && retval > 0) WM_operator_call(C, op); + + MEM_freeN(data); } int WM_operator_ui_popup(bContext *C, wmOperator *op, int width, int height) @@ -1200,8 +1202,11 @@ int WM_operator_ui_popup(bContext *C, wmOperator *op, int width, int height) return OPERATOR_RUNNING_MODAL; } -/* operator menu needs undo, for redo callback */ -int WM_operator_props_popup(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +/** + * For use by #WM_operator_props_popup_call, #WM_operator_props_popup only. + * + * \note operator menu needs undo flag enabled , for redo callback */ +static int wm_operator_props_popup_ex(bContext *C, wmOperator *op, const int do_call) { if ((op->type->flag & OPTYPE_REGISTER) == 0) { @@ -1209,15 +1214,34 @@ int WM_operator_props_popup(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) "Operator '%s' does not have register enabled, incorrect invoke function", op->type->idname); return OPERATOR_CANCELLED; } - + ED_undo_push_op(C, op); + wm_operator_register(C, op); uiPupBlock(C, wm_block_create_redo, op); + if (do_call) { + WM_operator_repeat(C, op); + } + return OPERATOR_RUNNING_MODAL; } +/* Same as WM_operator_props_popup but call the operator first, + * This way - the button values correspond to the result of the operator. + * Without this, first access to a button will make the result jump, + * see [#32452] */ +int WM_operator_props_popup_call(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +{ + return wm_operator_props_popup_ex(C, op, TRUE); +} + +int WM_operator_props_popup(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +{ + return wm_operator_props_popup_ex(C, op, FALSE); +} + int WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width, int height) { wmOpPopUp *data = MEM_callocN(sizeof(wmOpPopUp), "WM_operator_props_dialog_popup"); @@ -1281,6 +1305,31 @@ static void WM_OT_debug_menu(wmOperatorType *ot) RNA_def_int(ot->srna, "debug_value", 0, SHRT_MIN, SHRT_MAX, "Debug Value", "", -10000, 10000); } +/* ***************** Operator defaults ************************* */ +static int wm_operator_defaults_exec(bContext *C, wmOperator *op) +{ + PointerRNA ptr = CTX_data_pointer_get_type(C, "active_operator", &RNA_Operator); + + if (!ptr.data) { + BKE_report(op->reports, RPT_ERROR, "No operator in context"); + return OPERATOR_CANCELLED; + } + + WM_operator_properties_reset((wmOperator *)ptr.data); + return OPERATOR_FINISHED; +} + +/* used by operator preset menu. pre-2.65 this was a 'Reset' button */ +static void WM_OT_operator_defaults(wmOperatorType *ot) +{ + ot->name = "Restore Defaults"; + ot->idname = "WM_OT_operator_defaults"; + ot->description = "Set the active operator to its default values"; + + ot->exec = wm_operator_defaults_exec; + + ot->flag = OPTYPE_INTERNAL; +} /* ***************** Splash Screen ************************* */ @@ -1402,7 +1451,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-264"); + uiItemStringO(col, IFACE_("Release Log"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/development/release-logs/blender-265"); 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"); @@ -3766,6 +3815,7 @@ void wm_operatortype_init(void) WM_operatortype_append(WM_OT_memory_statistics); WM_operatortype_append(WM_OT_dependency_relations); WM_operatortype_append(WM_OT_debug_menu); + WM_operatortype_append(WM_OT_operator_defaults); WM_operatortype_append(WM_OT_splash); WM_operatortype_append(WM_OT_search_menu); WM_operatortype_append(WM_OT_call_menu); diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index b323f9d70a8..41f6a7e5ab0 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -61,6 +61,7 @@ #include "BKE_blender.h" #include "BKE_global.h" +#include "BKE_image.h" #include "GPU_colors.h" #include "GPU_compatibility.h" @@ -76,6 +77,9 @@ #include "WM_api.h" /* only for WM_main_playanim */ +struct PlayState; +static void playanim_window_zoom(const struct PlayState *ps, const float zoom_offset); + typedef struct PlayState { /* playback state */ @@ -86,7 +90,6 @@ typedef struct PlayState { short pingpong; short noskip; short sstep; - short pause; short wait2; short stopped; short go; @@ -134,6 +137,7 @@ typedef enum eWS_Qual { WS_QUAL_ALT = (WS_QUAL_LALT | WS_QUAL_RALT), WS_QUAL_LCTRL = (1 << 4), WS_QUAL_RCTRL = (1 << 5), + WS_QUAL_CTRL = (WS_QUAL_LCTRL | WS_QUAL_RCTRL), WS_QUAL_LMOUSE = (1 << 16), WS_QUAL_MMOUSE = (1 << 17), WS_QUAL_RMOUSE = (1 << 18), @@ -181,27 +185,12 @@ static void playanim_event_qual_update(void) /* Alt */ GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyLeftAlt, &val); - if (val) g_WS.qual |= WS_QUAL_LCTRL; - else g_WS.qual &= ~WS_QUAL_LCTRL; + if (val) g_WS.qual |= WS_QUAL_LALT; + else g_WS.qual &= ~WS_QUAL_LALT; GHOST_GetModifierKeyState(g_WS.ghost_system, GHOST_kModifierKeyRightAlt, &val); - if (val) g_WS.qual |= WS_QUAL_RCTRL; - else g_WS.qual &= ~WS_QUAL_RCTRL; - - /* LMB */ - GHOST_GetButtonState(g_WS.ghost_system, GHOST_kButtonMaskLeft, &val); - if (val) g_WS.qual |= WS_QUAL_LMOUSE; - else g_WS.qual &= ~WS_QUAL_LMOUSE; - - /* MMB */ - GHOST_GetButtonState(g_WS.ghost_system, GHOST_kButtonMaskMiddle, &val); - if (val) g_WS.qual |= WS_QUAL_MMOUSE; - else g_WS.qual &= ~WS_QUAL_MMOUSE; - - /* RMB */ - GHOST_GetButtonState(g_WS.ghost_system, GHOST_kButtonMaskRight, &val); - if (val) g_WS.qual |= WS_QUAL_RMOUSE; - else g_WS.qual &= ~WS_QUAL_RMOUSE; + if (val) g_WS.qual |= WS_QUAL_RALT; + else g_WS.qual &= ~WS_QUAL_RALT; } typedef struct PlayAnimPict { @@ -236,7 +225,7 @@ static void playanim_toscreen(PlayAnimPict *picture, struct ImBuf *ibuf, int fon { if (ibuf == NULL) { - printf("no ibuf !\n"); + printf("%s: no ibuf for picture '%s'\n", __func__, picture ? picture->name : "<NIL>"); return; } if (ibuf->rect == NULL && ibuf->rect_float) { @@ -434,6 +423,11 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) ps->stopped = FALSE; } + if (ps->wait2) { + pupdate_time(); + ptottime = 0; + } + switch (type) { case GHOST_kEventKeyDown: case GHOST_kEventKeyUp: @@ -448,33 +442,42 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) case GHOST_kKeyP: if (val) ps->pingpong = !ps->pingpong; break; + case GHOST_kKey1: case GHOST_kKeyNumpad1: if (val) swaptime = ps->fstep / 60.0; break; + case GHOST_kKey2: case GHOST_kKeyNumpad2: if (val) swaptime = ps->fstep / 50.0; break; + case GHOST_kKey3: case GHOST_kKeyNumpad3: if (val) swaptime = ps->fstep / 30.0; break; + case GHOST_kKey4: case GHOST_kKeyNumpad4: if (g_WS.qual & WS_QUAL_SHIFT) swaptime = ps->fstep / 24.0; else swaptime = ps->fstep / 25.0; break; + case GHOST_kKey5: case GHOST_kKeyNumpad5: if (val) swaptime = ps->fstep / 20.0; break; + case GHOST_kKey6: case GHOST_kKeyNumpad6: if (val) swaptime = ps->fstep / 15.0; break; + case GHOST_kKey7: case GHOST_kKeyNumpad7: if (val) swaptime = ps->fstep / 12.0; break; + case GHOST_kKey8: case GHOST_kKeyNumpad8: if (val) swaptime = ps->fstep / 10.0; break; + case GHOST_kKey9: case GHOST_kKeyNumpad9: if (val) swaptime = ps->fstep / 6.0; break; @@ -541,28 +544,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) } } break; - case GHOST_kKeyEqual: - if (val) { - if (g_WS.qual & WS_QUAL_SHIFT) { - ps->pause++; - printf("pause:%d\n", ps->pause); - } - else { - swaptime /= 1.1; - } - } - break; - case GHOST_kKeyMinus: - if (val) { - if (g_WS.qual & WS_QUAL_SHIFT) { - ps->pause--; - printf("pause:%d\n", ps->pause); - } - else { - swaptime *= 1.1; - } - } - break; + case GHOST_kKey0: case GHOST_kKeyNumpad0: if (val) { if (ps->once) { @@ -581,6 +563,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) ps->wait2 = ps->sstep = FALSE; } break; + case GHOST_kKeyPeriod: case GHOST_kKeyNumpadPeriod: if (val) { if (ps->sstep) ps->wait2 = FALSE; @@ -590,29 +573,28 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) } } break; + case GHOST_kKeyEqual: case GHOST_kKeyNumpadPlus: + { if (val == 0) break; - zoomx += 2.0f; - zoomy += 2.0f; - /* no break??? - is this intentional? - campbell XXX25 */ + if (g_WS.qual & WS_QUAL_CTRL) { + playanim_window_zoom(ps, 1.0f); + } + else { + swaptime /= 1.1; + } + break; + } + case GHOST_kKeyMinus: case GHOST_kKeyNumpadMinus: { - int sizex, sizey; - /* int ofsx, ofsy; */ /* UNUSED */ - if (val == 0) break; - if (zoomx > 1.0f) zoomx -= 1.0f; - if (zoomy > 1.0f) zoomy -= 1.0f; - // playanim_window_get_position(&ofsx, &ofsy); - playanim_window_get_size(&sizex, &sizey); - /* ofsx += sizex / 2; */ /* UNUSED */ - /* ofsy += sizey / 2; */ /* UNUSED */ - sizex = zoomx * ps->ibufx; - sizey = zoomy * ps->ibufy; - /* ofsx -= sizex / 2; */ /* UNUSED */ - /* ofsy -= sizey / 2; */ /* UNUSED */ - // window_set_position(g_WS.ghost_window,sizex,sizey); - GHOST_SetClientSize(g_WS.ghost_window, sizex, sizey); + if (g_WS.qual & WS_QUAL_CTRL) { + playanim_window_zoom(ps, -1.0f); + } + else { + swaptime *= 1.1; + } break; } case GHOST_kKeyEsc: @@ -623,6 +605,44 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) } break; } + case GHOST_kEventButtonDown: + case GHOST_kEventButtonUp: + { + GHOST_TEventButtonData *bd = GHOST_GetEventData(evt); + int cx, cy, sizex, sizey, inside_window; + + GHOST_GetCursorPosition(g_WS.ghost_system, &cx, &cy); + GHOST_ScreenToClient(g_WS.ghost_window, cx, cy, &cx, &cy); + playanim_window_get_size(&sizex, &sizey); + + inside_window = (cx >= 0 && cx < sizex && cy >= 0 && cy <= sizey); + + if (bd->button == GHOST_kButtonMaskLeft) { + if (type == GHOST_kEventButtonDown) { + if (inside_window) + g_WS.qual |= WS_QUAL_LMOUSE; + } + else + g_WS.qual &= ~WS_QUAL_LMOUSE; + } + else if (bd->button == GHOST_kButtonMaskMiddle) { + if (type == GHOST_kEventButtonDown) { + if (inside_window) + g_WS.qual |= WS_QUAL_MMOUSE; + } + else + g_WS.qual &= ~WS_QUAL_MMOUSE; + } + else if (bd->button == GHOST_kButtonMaskRight) { + if (type == GHOST_kEventButtonDown) { + if (inside_window) + g_WS.qual |= WS_QUAL_RMOUSE; + } + else + g_WS.qual &= ~WS_QUAL_RMOUSE; + } + break; + } case GHOST_kEventCursorMove: { if (g_WS.qual & WS_QUAL_LMOUSE) { @@ -654,6 +674,11 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) } break; } + case GHOST_kEventWindowActivate: + case GHOST_kEventWindowDeactivate: { + g_WS.qual &= ~WS_QUAL_MOUSE; + break; + } case GHOST_kEventWindowSize: case GHOST_kEventWindowMove: { @@ -718,6 +743,25 @@ static void playanim_window_open(const char *title, int posx, int posy, int size FALSE /* no stereo */, FALSE); } +static void playanim_window_zoom(const PlayState *ps, const float zoom_offset) +{ + int sizex, sizey; + /* int ofsx, ofsy; */ /* UNUSED */ + + if (zoomx + zoom_offset > 0.0f) zoomx += zoom_offset; + if (zoomy + zoom_offset > 0.0f) zoomy += zoom_offset; + + // playanim_window_get_position(&ofsx, &ofsy); + playanim_window_get_size(&sizex, &sizey); + /* ofsx += sizex / 2; */ /* UNUSED */ + /* ofsy += sizey / 2; */ /* UNUSED */ + sizex = zoomx * ps->ibufx; + sizey = zoomy * ps->ibufy; + /* ofsx -= sizex / 2; */ /* UNUSED */ + /* ofsy -= sizey / 2; */ /* UNUSED */ + // window_set_position(g_WS.ghost_window,sizex,sizey); + GHOST_SetClientSize(g_WS.ghost_window, sizex, sizey); +} void WM_main_playanim(int argc, const char **argv) { @@ -738,13 +782,12 @@ void WM_main_playanim(int argc, const char **argv) /* ps.doubleb = TRUE;*/ /* UNUSED */ ps.go = TRUE; ps.direction = TRUE; - ps.next = TRUE; + ps.next = 1; ps.once = FALSE; ps.turbo = FALSE; ps.pingpong = FALSE; ps.noskip = FALSE; ps.sstep = FALSE; - ps.pause = FALSE; ps.wait2 = FALSE; ps.stopped = FALSE; ps.picture = NULL; @@ -941,6 +984,7 @@ void WM_main_playanim(int argc, const char **argv) if (ptottime > 0.0) ptottime = 0.0; while (ps.picture) { + int hasevent; #ifndef USE_IMB_CACHE if (ibuf != NULL && ibuf->ftype == 0) IMB_freeImBuf(ibuf); #endif @@ -994,19 +1038,22 @@ void WM_main_playanim(int argc, const char **argv) ps.next = ps.direction; - { - int hasevent = GHOST_ProcessEvents(g_WS.ghost_system, 0); + while ((hasevent = GHOST_ProcessEvents(g_WS.ghost_system, 0) || ps.wait2 != 0)) { if (hasevent) { GHOST_DispatchEvents(g_WS.ghost_system); } - } - - /* XXX25 - we should not have to do this, but it makes scrubbing functional! */ - if (g_WS.qual & WS_QUAL_LMOUSE) { - ps.next = 0; - } - else { - ps.sstep = 0; + if (ps.wait2) { + if (hasevent) { + if (ibuf) { + while (pupdate_time()) PIL_sleep_ms(1); + ptottime -= swaptime; + playanim_toscreen(ps.picture, ibuf, ps.fontid, ps.fstep); + } + } + } + if (!ps.go) { + break; + } } ps.wait2 = ps.sstep; @@ -1084,6 +1131,7 @@ void WM_main_playanim(int argc, const char **argv) /* we still miss freeing a lot!, * but many areas could skip initialization too for anim play */ IMB_exit(); + BKE_images_exit(); BLF_exit(); #endif GHOST_DisposeWindow(g_WS.ghost_system, g_WS.ghost_window); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 1da6328d7c8..6864624e163 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -333,8 +333,14 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win) static void wm_window_add_ghostwindow(const char *title, wmWindow *win) { GHOST_WindowHandle ghostwin; + static int multisamples = -1; int scr_w, scr_h, posy; + /* force setting multisamples only once, it requires restart - and you cannot + * mix it, either all windows have it, or none (tested in OSX opengl) */ + if (multisamples == -1) + multisamples = U.ogl_multisamples; + wm_get_screensize(&scr_w, &scr_h); posy = (scr_h - win->posy - win->sizey); @@ -345,7 +351,7 @@ static void wm_window_add_ghostwindow(const char *title, wmWindow *win) (GHOST_TWindowState)win->windowstate, GHOST_kDrawingContextTypeOpenGL, 0 /* no stereo */, - U.ogl_multisamples /* AA */); + multisamples /* AA */); if (ghostwin) { /* needed so we can detect the graphics card below */ @@ -748,6 +754,11 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr state = GHOST_GetWindowState(win->ghostwin); win->windowstate = state; + /* stop screencast if resize */ + if (type == GHOST_kEventWindowSize) { + WM_jobs_stop(CTX_wm_manager(C), win->screen, NULL); + } + /* win32: gives undefined window size when minimized */ if (state != GHOST_kWindowStateMinimized) { GHOST_RectangleHandle client_rect; diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index 62baa328654..8b52bd6a228 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -287,9 +287,9 @@ enum { /* for event checks */ /* only used for KM_TEXTINPUT, so assume that we want all user-inputtable ascii codes included */ - /* UNUSED - see wm_eventmatch - BUG [#30479] -#define ISTEXTINPUT(event) (event >= ' ' && event <= 255) - */ + /* UNUSED - see wm_eventmatch - BUG [#30479] */ +// #define ISTEXTINPUT(event) (event >= ' ' && event <= 255) + /* test whether the event is a key on the keyboard */ #define ISKEYBOARD(event) (event >= ' ' && event <= 320) diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt index 3c537c3d64b..90bf913bbf2 100644 --- a/source/blenderplayer/CMakeLists.txt +++ b/source/blenderplayer/CMakeLists.txt @@ -60,7 +60,7 @@ elseif(APPLE) add_executable(blenderplayer ${EXETYPE} bad_level_call_stubs/stubs.c) # setup Info.plist execute_process(COMMAND date "+%Y-%m-%d" OUTPUT_VARIABLE BLENDER_DATE OUTPUT_STRIP_TRAILING_WHITESPACE) - set(PLAYER_SOURCEDIR ${CMAKE_SOURCE_DIR}/source/darwin/blenderplayer.app) + set(PLAYER_SOURCEDIR ${CMAKE_SOURCE_DIR}/release/darwin/blenderplayer.app) set(PLAYER_SOURCEINFO ${PLAYER_SOURCEDIR}/Contents/Info.plist) set_target_properties(blenderplayer PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${PLAYER_SOURCEINFO} @@ -199,6 +199,10 @@ endif() list(APPEND BLENDER_SORTED_LIBS bf_intern_guardedalloc_cpp) endif() + if(WITH_INTERNATIONAL) + list(APPEND BLENDER_SORTED_LIBS bf_intern_locale) + endif() + foreach(SORTLIB ${BLENDER_SORTED_LIBS}) set(REMLIB ${SORTLIB}) foreach(SEARCHLIB ${BLENDER_LINK_LIBS}) diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 201c89c820d..6ed8bd4a0c8 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -471,20 +471,6 @@ elseif(WIN32) DESTINATION ${TARGETDIR} ) - if(WITH_INTERNATIONAL AND (NOT WITH_MINGW64)) - install( - FILES ${LIBDIR}/gettext/lib/gnu_gettext.dll - DESTINATION ${TARGETDIR} - ) - - if(NOT CMAKE_CL_64) - install( - FILES ${LIBDIR}/iconv/lib/iconv.dll - DESTINATION ${TARGETDIR} - ) - endif() - endif() - if(WITH_PYTHON) set_lib_path(PYLIB "python") install( @@ -532,7 +518,7 @@ elseif(WIN32) endif() if(CMAKE_CL_64) - # gettext and png are statically linked on win64 + # png is statically linked on win64 install( FILES ${LIBDIR}/zlib/lib/zlib.dll DESTINATION ${TARGETDIR} @@ -634,18 +620,7 @@ elseif(WIN32) install( # x86 builds can run on x64 Windows, so this is required at all times FILES ${LIBDIR}/thumbhandler/lib/BlendThumb64.dll DESTINATION ${TARGETDIR} - ) - - if(WITH_OPENIMAGEIO) - if(NOT MINGW) - set(OIIOBIN ${LIBDIR}/openimageio) - install( - FILES - ${OIIOBIN}/bin/OpenImageIO.dll - DESTINATION ${TARGETDIR} - ) - endif() - endif() + ) if(WITH_OPENCOLORIO) set(OCIOBIN ${LIBDIR}/opencolorio/bin) @@ -683,7 +658,7 @@ elseif(APPLE) ) endmacro() - set(OSX_APP_SOURCEDIR ${CMAKE_SOURCE_DIR}/source/darwin/blender.app) + set(OSX_APP_SOURCEDIR ${CMAKE_SOURCE_DIR}/release/darwin/blender.app) # setup Info.plist execute_process(COMMAND date "+%Y-%m-%d" OUTPUT_VARIABLE BLENDER_DATE OUTPUT_STRIP_TRAILING_WHITESPACE) @@ -742,7 +717,7 @@ elseif(APPLE) # install blenderplayer bundle - copy of blender.app above. re-using macros et al # note we are using OSX Bundle as base and copying Blender dummy bundle on top of it if(WITH_GAMEENGINE AND WITH_PLAYER) - set(OSX_APP_PLAYER_SOURCEDIR ${CMAKE_SOURCE_DIR}/source/darwin/blenderplayer.app) + set(OSX_APP_PLAYER_SOURCEDIR ${CMAKE_SOURCE_DIR}/release/darwin/blenderplayer.app) set(PLAYER_SOURCEINFO ${OSX_APP_PLAYER_SOURCEDIR}/Contents/Info.plist) set(PLAYER_TARGETDIR_VER ${TARGETDIR}/blenderplayer.app/Contents/MacOS/${BLENDER_VERSION}) @@ -989,6 +964,10 @@ endif() list_insert_after(BLENDER_SORTED_LIBS "cycles_kernel" "cycles_kernel_osl") endif() + if(WITH_INTERNATIONAL) + list(APPEND BLENDER_SORTED_LIBS bf_intern_locale) + endif() + foreach(SORTLIB ${BLENDER_SORTED_LIBS}) set(REMLIB ${SORTLIB}) foreach(SEARCHLIB ${BLENDER_LINK_LIBS}) diff --git a/source/creator/blender.map b/source/creator/blender.map new file mode 100644 index 00000000000..dc7bc3151e8 --- /dev/null +++ b/source/creator/blender.map @@ -0,0 +1,11 @@ + +/* on Linux we exclude LLVM symbols, they conflict with Mesa llvmpipe */ + +{ +global: + *; +local: + *llvm*; + *LLVM*; +}; + diff --git a/source/creator/creator.c b/source/creator/creator.c index 86a9e411ef7..37327d95628 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -1080,7 +1080,9 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle) "\n\t\t-p <sx> <sy>\tOpen with lower left corner at <sx>, <sy>" "\n\t\t-m\t\tRead from disk (Don't buffer)" "\n\t\t-f <fps> <fps-base>\t\tSpecify FPS to start with" - "\n\t\t-j <frame>\tSet frame step to <frame>"; + "\n\t\t-j <frame>\tSet frame step to <frame>" + "\n\t\t-s <frame>\tPlay from <frame>" + "\n\t\t-j <frame>\tPlay until <frame>"; static char game_doc[] = "Game Engine specific options" "\n\t-g fixedtime\t\tRun on 50 hertz without dropping frames" @@ -1273,6 +1275,7 @@ int main(int argc, const char **argv) initglobals(); /* blender.c */ IMB_init(); + BKE_images_init(); #ifdef WITH_FFMPEG IMB_ffmpeg_init(); diff --git a/source/darwin/blender.app/Contents/Info.plist b/source/darwin/blender.app/Contents/Info.plist deleted file mode 100644 index 064ffe5bc3f..00000000000 --- a/source/darwin/blender.app/Contents/Info.plist +++ /dev/null @@ -1,54 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>CFBundleDocumentTypes</key> - <array> - <dict> - <key>CFBundleTypeExtensions</key> - <array> - <string>blend</string> - </array> - <key>CFBundleTypeIconFile</key> - <string>blender file icon.icns</string> - <key>CFBundleTypeName</key> - <string>Blender File</string> - <key>CFBundleTypeOSTypes</key> - <array> - <string>BLND</string> - </array> - <key>CFBundleTypeRole</key> - <string>Editor</string> - <key>LSIsAppleDefaultForType</key> - <true/> - </dict> - </array> - <key>CFBundleExecutable</key> - <string>blender</string> - <key>CFBundleGetInfoString</key> - <string>${MACOSX_BUNDLE_LONG_VERSION_STRING}, Blender Foundation</string> - <key>CFBundleIconFile</key> - <string>blender icon.icns</string> - <key>CFBundleIdentifier</key> - <string>org.blenderfoundation.blender</string> - <key>CFBundleInfoDictionaryVersion</key> - <string>6.0</string> - <key>CFBundleName</key> - <string>Blender</string> - <key>CFBundlePackageType</key> - <string>APPL</string> - <key>CFBundleShortVersionString</key> - <string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string> - <key>CFBundleSignature</key> - <string>????</string> - <key>CFBundleVersion</key> - <string>${MACOSX_BUNDLE_LONG_VERSION_STRING}, Blender Foundation</string> - <key>LSEnvironment</key> - <dict> - <key>OMP_NUM_THREADS</key> - <string>4</string> - </dict> - <key>NSPrincipalClass</key> - <string>NSApplication</string> -</dict> -</plist> diff --git a/source/darwin/blender.app/Contents/MacOS/blender b/source/darwin/blender.app/Contents/MacOS/blender deleted file mode 100644 index 5e05e74a307..00000000000 --- a/source/darwin/blender.app/Contents/MacOS/blender +++ /dev/null @@ -1 +0,0 @@ -placeholder
diff --git a/source/darwin/blender.app/Contents/PkgInfo b/source/darwin/blender.app/Contents/PkgInfo deleted file mode 100644 index bd04210fb49..00000000000 --- a/source/darwin/blender.app/Contents/PkgInfo +++ /dev/null @@ -1 +0,0 @@ -APPL????
\ No newline at end of file diff --git a/source/darwin/blender.app/Contents/Resources/blender file icon.icns b/source/darwin/blender.app/Contents/Resources/blender file icon.icns Binary files differdeleted file mode 100644 index 9065f1b359c..00000000000 --- a/source/darwin/blender.app/Contents/Resources/blender file icon.icns +++ /dev/null diff --git a/source/darwin/blender.app/Contents/Resources/blender icon.icns b/source/darwin/blender.app/Contents/Resources/blender icon.icns Binary files differdeleted file mode 100644 index 5eef94afde9..00000000000 --- a/source/darwin/blender.app/Contents/Resources/blender icon.icns +++ /dev/null diff --git a/source/darwin/blenderplayer.app/Contents/Info.plist b/source/darwin/blenderplayer.app/Contents/Info.plist deleted file mode 100644 index c7b9ceb568e..00000000000 --- a/source/darwin/blenderplayer.app/Contents/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>CFBundleInfoDictionaryVersion</key> - <string>6.0</string> - <key>CFBundleExecutable</key> - <string>blenderplayer</string> - <key>CFBundlePackageType</key> - <string>APPL</string> - <key>CFBundleSignature</key> - <string>????</string> - <key>CFBundleIconFile</key> - <string>blender player icon.icns</string> - <key>CFBundleName</key> - <string>BlenderPlayer</string> - <key>CFBundleIdentifier</key> - <string>org.blenderfoundation.blenderplayer</string> - <key>CFBundleVersion</key> - <string>${MACOSX_BUNDLE_LONG_VERSION_STRING}, Blender Foundation</string> - <key>CFBundleShortVersionString</key> - <string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string> - <key>CFBundleGetInfoString</key> - <string>${MACOSX_BUNDLE_LONG_VERSION_STRING}, Blender Foundation</string> - <key>CFBundleDocumentTypes</key> - <array> - <dict> - <key>CFBundleTypeIconFile</key> - <string>blender file icon.icns</string> - <key>CFBundleTypeName</key> - <string>Blender File</string> - <key>CFBundleTypeOSTypes</key> - <array> - <string>BLND</string> - </array> - <key>CFBundleTypeExtensions</key> - <array> - <string>blend</string> - </array> - <key>CFBundleTypeRole</key> - <string>Viewer</string> - <key>LSIsAppleDefaultForType</key> - <false/> - </dict> - </array> - <key>NSPrincipalClass</key> - <string>NSApplication</string> -</dict> -</plist> diff --git a/source/darwin/blenderplayer.app/Contents/MacOS/blenderplayer b/source/darwin/blenderplayer.app/Contents/MacOS/blenderplayer deleted file mode 100644 index 5e05e74a307..00000000000 --- a/source/darwin/blenderplayer.app/Contents/MacOS/blenderplayer +++ /dev/null @@ -1 +0,0 @@ -placeholder
diff --git a/source/darwin/blenderplayer.app/Contents/PkgInfo b/source/darwin/blenderplayer.app/Contents/PkgInfo deleted file mode 100644 index bd04210fb49..00000000000 --- a/source/darwin/blenderplayer.app/Contents/PkgInfo +++ /dev/null @@ -1 +0,0 @@ -APPL????
\ No newline at end of file diff --git a/source/darwin/blenderplayer.app/Contents/Resources/blender file icon.icns b/source/darwin/blenderplayer.app/Contents/Resources/blender file icon.icns Binary files differdeleted file mode 100644 index 9065f1b359c..00000000000 --- a/source/darwin/blenderplayer.app/Contents/Resources/blender file icon.icns +++ /dev/null diff --git a/source/darwin/blenderplayer.app/Contents/Resources/blender player icon.icns b/source/darwin/blenderplayer.app/Contents/Resources/blender player icon.icns Binary files differdeleted file mode 100644 index 5eef94afde9..00000000000 --- a/source/darwin/blenderplayer.app/Contents/Resources/blender player icon.icns +++ /dev/null diff --git a/source/darwin/set_simulation_threads.app/Contents/Info.plist b/source/darwin/set_simulation_threads.app/Contents/Info.plist deleted file mode 100644 index eb80955e5a6..00000000000 --- a/source/darwin/set_simulation_threads.app/Contents/Info.plist +++ /dev/null @@ -1,44 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>CFBundleAllowMixedLocalizations</key> - <true/> - <key>CFBundleDevelopmentRegion</key> - <string>English</string> - <key>CFBundleExecutable</key> - <string>applet</string> - <key>CFBundleIconFile</key> - <string>applet</string> - <key>CFBundleInfoDictionaryVersion</key> - <string>6.0</string> - <key>CFBundleName</key> - <string>set_simulation_threads</string> - <key>CFBundlePackageType</key> - <string>APPL</string> - <key>CFBundleSignature</key> - <string>aplt</string> - <key>LSMinimumSystemVersionByArchitecture</key> - <dict> - <key>x86_64</key> - <string>10.6</string> - </dict> - <key>LSRequiresCarbon</key> - <true/> - <key>WindowState</key> - <dict> - <key>dividerCollapsed</key> - <false/> - <key>eventLogLevel</key> - <integer>-1</integer> - <key>name</key> - <string>ScriptWindowState</string> - <key>positionOfDivider</key> - <real>493</real> - <key>savedFrame</key> - <string>698 332 1163 846 0 0 1920 1178 </string> - <key>selectedTabView</key> - <string>result</string> - </dict> -</dict> -</plist> diff --git a/source/darwin/set_simulation_threads.app/Contents/MacOS/applet b/source/darwin/set_simulation_threads.app/Contents/MacOS/applet Binary files differdeleted file mode 100755 index 0079f4b19d4..00000000000 --- a/source/darwin/set_simulation_threads.app/Contents/MacOS/applet +++ /dev/null diff --git a/source/darwin/set_simulation_threads.app/Contents/PkgInfo b/source/darwin/set_simulation_threads.app/Contents/PkgInfo deleted file mode 100644 index 3253614c402..00000000000 --- a/source/darwin/set_simulation_threads.app/Contents/PkgInfo +++ /dev/null @@ -1 +0,0 @@ -APPLaplt
\ No newline at end of file diff --git a/source/darwin/set_simulation_threads.app/Contents/Resources/Scripts/main.scpt b/source/darwin/set_simulation_threads.app/Contents/Resources/Scripts/main.scpt Binary files differdeleted file mode 100644 index fa562578a80..00000000000 --- a/source/darwin/set_simulation_threads.app/Contents/Resources/Scripts/main.scpt +++ /dev/null diff --git a/source/darwin/set_simulation_threads.app/Contents/Resources/applet.icns b/source/darwin/set_simulation_threads.app/Contents/Resources/applet.icns Binary files differdeleted file mode 100644 index fcc1f09273d..00000000000 --- a/source/darwin/set_simulation_threads.app/Contents/Resources/applet.icns +++ /dev/null diff --git a/source/darwin/set_simulation_threads.app/Contents/Resources/applet.rsrc b/source/darwin/set_simulation_threads.app/Contents/Resources/applet.rsrc Binary files differdeleted file mode 100644 index 540621d0b9e..00000000000 --- a/source/darwin/set_simulation_threads.app/Contents/Resources/applet.rsrc +++ /dev/null diff --git a/source/darwin/set_simulation_threads.app/Contents/Resources/description.rtfd/TXT.rtf b/source/darwin/set_simulation_threads.app/Contents/Resources/description.rtfd/TXT.rtf deleted file mode 100644 index 0d0a60c08b5..00000000000 --- a/source/darwin/set_simulation_threads.app/Contents/Resources/description.rtfd/TXT.rtf +++ /dev/null @@ -1,4 +0,0 @@ -{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf230 -{\fonttbl} -{\colortbl;\red255\green255\blue255;} -}
\ No newline at end of file diff --git a/source/tests/bl_rst_completeness.py b/source/tests/bl_rst_completeness.py new file mode 100644 index 00000000000..e9e2779bda8 --- /dev/null +++ b/source/tests/bl_rst_completeness.py @@ -0,0 +1,159 @@ +# ##### 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. +# +# ##### END GPL LICENSE BLOCK ##### + +# <pep8 compliant> + +# run this script in the game engine. +# or on the command line with... +# ./blender.bin --background -noaudio --python source/tests/bl_rst_completeness.py + +# Paste this into the bge and run on an always actuator. +''' +filepath = "/dsk/data/src/blender/blender/source/tests/bl_rst_completeness.py" +exec(compile(open(filepath).read(), filepath, 'exec')) +''' + +import os + +THIS_DIR = os.path.dirname(__file__) +RST_DIR = os.path.normpath(os.path.join(THIS_DIR, "..", "..", "doc", "python_api", "rst")) + +import sys +sys.path.append(THIS_DIR) + +import rst_to_doctree_mini + +try: + import bge +except: + bge = None + +# (file, module) +modules = ( + ("bge.constraints.rst", "bge.constraints", False), + ("bge.events.rst", "bge.events", False), + ("bge.logic.rst", "bge.logic", False), + ("bge.render.rst", "bge.render", False), + ("bge.texture.rst", "bge.texture", False), + ("bge.types.rst", "bge.types", False), + + ("bgl.rst", "bgl", True), + ("gpu.rst", "gpu", False), +) + +def is_directive_pydata(filepath, directive): + if directive.type in {"function", "method", "class", "attribute", "data"}: + return True + elif directive.type in {"module", "note", "warning", "code-block", "hlist", "seealso"}: + return False + elif directive.type in {"literalinclude"}: # TODO + return False + else: + print(directive_to_str(filepath, directive), end=" ") + print("unknown directive type %r" % directive.type) + return False + + +def directive_to_str(filepath, directive): + return "%s:%d:%d:" % (filepath, directive.line + 1, directive.indent) + + +def directive_members_dict(filepath, directive_members): + return {directive.value_strip: directive for directive in directive_members + if is_directive_pydata(filepath, directive)} + + +def module_validate(filepath, mod, mod_name, doctree, partial_ok): + # RST member missing from MODULE ??? + for directive in doctree: + # print(directive.type) + if is_directive_pydata(filepath, directive): + attr = directive.value_strip + has_attr = hasattr(mod, attr) + ok = False + if not has_attr: + # so we can have glNormal docs cover glNormal3f + if partial_ok: + for s in dir(mod): + if s.startswith(attr): + ok = True + break + + if not ok: + print(directive_to_str(filepath, directive), end=" ") + print("rst contains non existing member %r" % attr) + + # if its a class, scan down the class... + # print(directive.type) + if has_attr: + if directive.type == "class": + cls = getattr(mod, attr) + # print("directive: ", directive) + for directive_child in directive.members: + # print("directive_child: ", directive_child) + if is_directive_pydata(filepath, directive_child): + attr_child = directive_child.value_strip + if attr_child not in cls.__dict__: + attr_id = "%s.%s" % (attr, attr_child) + 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): + if attr.startswith("_"): + continue + + directive = doctree_dict.get(attr) + if directive is None: + print("module contains undocumented member %r from %r" % ("%s.%s" % (mod_name, attr), filepath)) + else: + if directive.type == "class": + directive_dict = directive_members_dict(filepath, directive.members) + cls = getattr(mod, attr) + for attr_child in cls.__dict__.keys(): + if attr_child.startswith("_"): + continue + if attr_child not in directive_dict: + attr_id = "%s.%s.%s" % (mod_name, attr, attr_child), filepath + print("module contains undocumented member %r from %r" % attr_id) + + +def main(): + + if bge is None: + print("Skipping BGE modules!") + + for filename, modname, partial_ok in modules: + if bge is None and modname.startswith("bge"): + continue + + filepath = os.path.join(RST_DIR, filename) + if not os.path.exists(filepath): + raise Exception("%r not found" % filepath) + + doctree = rst_to_doctree_mini.parse_rst_py(filepath) + __import__(modname) + mod = sys.modules[modname] + + module_validate(filepath, mod, modname, doctree, partial_ok) + + +if __name__ == "__main__": + main() diff --git a/source/tests/rst_to_doctree_mini.py b/source/tests/rst_to_doctree_mini.py new file mode 100644 index 00000000000..181037299cf --- /dev/null +++ b/source/tests/rst_to_doctree_mini.py @@ -0,0 +1,91 @@ +# ##### 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. +# +# ##### END GPL LICENSE BLOCK ##### + +# <pep8 compliant> + +# Module with function to extract a doctree from an reStructuredText file. +# Named 'Mini' because we only parse the minimum data needed to check +# Python classes, methods and attributes match up to those in existing modules. +# (To test for documentation completeness) + +# note: literalinclude's are not followed. +# could be nice to add but not really needed either right now. + +import collections + +Directive = collections.namedtuple('Directive', + ("type", + "value", + "value_strip", + "line", + "indent", + "members")) + + +def parse_rst_py(filepath): + import re + + # Get the prefix assuming the line is lstrip()'d + # ..foo:: bar + # --> + # ("foo", "bar") + re_prefix = re.compile(r"^\.\.\s([a-zA-Z09\-]+)::\s*(.*)\s*$") + + tree = collections.defaultdict(list) + indent_map = {} + indent_prev = 0 + f = open(filepath, encoding="utf-8") + indent_lists = [] + for i, line in enumerate(f): + line_strip = line.lstrip() + # ^\.\.\s[a-zA-Z09\-]+::.*$ + #if line.startswith(".. "): + march = re_prefix.match(line_strip) + + if march: + directive, value = march.group(1, 2) + indent = len(line) - len(line_strip) + value_strip = value.replace("(", " ").split() + value_strip = value_strip[0] if value_strip else "" + + item = Directive(type=directive, + value=value, + value_strip=value_strip, + line=i, + indent=indent, + members=[]) + + tree[indent].append(item) + if indent_prev < indent: + indent_map[indent] = indent_prev + if indent > 0: + tree[indent_map[indent]][-1].members.append(item) + indent_prev = indent + f.close() + + return tree[0] + + +if __name__ == "__main__": + # not intended use, but may as well print rst files passed as a test. + import sys + for arg in sys.argv: + if arg.lower().endswith((".txt", ".rst")): + items = parse_rst_py(arg) + for i in items: + print(i) |