diff options
author | Lukas Tönne <lukas.toenne@gmail.com> | 2015-05-04 18:00:40 +0300 |
---|---|---|
committer | Lukas Tönne <lukas.toenne@gmail.com> | 2015-05-04 18:14:25 +0300 |
commit | bf7e8b42fa269c310e456fa55263ff2d9849804e (patch) | |
tree | 571b8177bc7d854c865126e8c11b680577b0d98c /source | |
parent | 20e960215a80a41fd7e9782d009531d8d9f827cd (diff) | |
parent | 1227e5c3d1ee20e9af57984a261b1d51d48c0263 (diff) |
Merge branch 'master' into strand_editmode
Conflicts:
source/blender/bmesh/bmesh_class.h
source/blender/bmesh/intern/bmesh_mesh_conv.h
Diffstat (limited to 'source')
362 files changed, 7610 insertions, 3671 deletions
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c index c65a0825a49..215d2484c18 100644 --- a/source/blender/blenfont/intern/blf_glyph.c +++ b/source/blender/blenfont/intern/blf_glyph.c @@ -199,7 +199,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c) GlyphBLF *g; FT_Error err; FT_Bitmap bitmap, tempbitmap; - int sharp = (U.text_render & USER_TEXT_DISABLE_AA); + const bool is_sharp = (U.text_render & USER_TEXT_DISABLE_AA) != 0; int flags = FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP; FT_BBox bbox; unsigned int key; @@ -224,7 +224,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c) if (font->flags & BLF_HINTING) flags &= ~FT_LOAD_NO_HINTING; - if (sharp) + if (is_sharp) err = FT_Load_Glyph(font->face, (FT_UInt)index, FT_LOAD_TARGET_MONO); else err = FT_Load_Glyph(font->face, (FT_UInt)index, flags); @@ -237,7 +237,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c) /* get the glyph. */ slot = font->face->glyph; - if (sharp) { + if (is_sharp) { err = FT_Render_Glyph(slot, FT_RENDER_MODE_MONO); /* Convert result from 1 bit per pixel to 8 bit per pixel */ @@ -266,7 +266,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c) g->height = (int)bitmap.rows; if (g->width && g->height) { - if (sharp) { + if (is_sharp) { /* Font buffer uses only 0 or 1 values, Blender expects full 0..255 range */ int i; for (i = 0; i < (g->width * g->height); i++) { diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 0789335de6a..80332c08fc2 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -42,7 +42,7 @@ extern "C" { * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 274 -#define BLENDER_SUBVERSION 4 +#define BLENDER_SUBVERSION 5 /* Several breakages with 270, e.g. constraint deg vs rad */ #define BLENDER_MINVERSION 270 #define BLENDER_MINSUBVERSION 5 @@ -87,7 +87,7 @@ void BKE_userdef_free(void); void BKE_userdef_state(void); /* set this callback when a UI is running */ -void set_blender_test_break_cb(void (*func)(void)); +void BKE_blender_callback_test_break_set(void (*func)(void)); int blender_test_break(void); #define BKE_UNDO_STR_MAX 64 diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index ec3c0447269..9de13ce9240 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -90,6 +90,7 @@ void BKE_curve_translate(struct Curve *cu, float offset[3], const bool do_keys); void BKE_curve_material_index_remove(struct Curve *cu, int index); void BKE_curve_material_index_clear(struct Curve *cu); int BKE_curve_material_index_validate(struct Curve *cu); +void BKE_curve_material_remap(struct Curve *cu, const unsigned int *remap, unsigned int remap_len); ListBase *BKE_curve_nurbs_get(struct Curve *cu); diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 935a922b3ec..22ddae88b28 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -126,10 +126,11 @@ enum { G_DEBUG_FREESTYLE = (1 << 7), /* freestyle messages */ G_DEBUG_DEPSGRAPH = (1 << 8), /* depsgraph messages */ G_DEBUG_SIMDATA = (1 << 9), /* sim debug data display */ + G_DEBUG_GPU_MEM = (1 << 10), /* gpu memory in status bar */ }; #define G_DEBUG_ALL (G_DEBUG | G_DEBUG_FFMPEG | G_DEBUG_PYTHON | G_DEBUG_EVENTS | G_DEBUG_WM | G_DEBUG_JOBS | \ - G_DEBUG_FREESTYLE | G_DEBUG_DEPSGRAPH) + G_DEBUG_FREESTYLE | G_DEBUG_DEPSGRAPH | G_DEBUG_GPU_MEM) /* G.fileflags */ diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index ad191968a40..155f26d9bd9 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -46,6 +46,7 @@ struct ImageFormatData; struct ImagePool; struct Main; struct ReportList; +struct RenderResult; #define IMA_MAX_SPACE 64 @@ -58,10 +59,11 @@ void BKE_image_free_buffers(struct Image *image); /* call from library */ void BKE_image_free(struct Image *image); -void BKE_imbuf_stamp_info(struct Scene *scene, struct Object *camera, struct ImBuf *ibuf); +void BKE_render_result_stamp_info(struct Scene *scene, struct Object *camera, struct RenderResult *rr); +void BKE_imbuf_stamp_info(struct RenderResult *rr, struct ImBuf *ibuf); void BKE_image_stamp_buf(struct Scene *scene, struct Object *camera, unsigned char *rect, float *rectf, int width, int height, int channels); bool BKE_imbuf_alpha_test(struct ImBuf *ibuf); -int BKE_imbuf_write_stamp(struct Scene *scene, struct Object *camera, struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf); +int BKE_imbuf_write_stamp(struct Scene *scene, struct RenderResult *rr, struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf); void BKE_imbuf_write_prepare(struct ImBuf *ibuf, struct ImageFormatData *imf); int BKE_imbuf_write(struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf); int BKE_imbuf_write_as(struct ImBuf *ibuf, const char *name, struct ImageFormatData *imf, const bool is_copy); @@ -175,7 +177,7 @@ struct Image *BKE_image_load_exists(const char *filepath); struct Image *BKE_image_add_generated( struct Main *bmain, unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, const float color[4], const bool stereo3d); /* adds image from imbuf, owns imbuf */ -struct Image *BKE_image_add_from_imbuf(struct ImBuf *ibuf); +struct Image *BKE_image_add_from_imbuf(struct ImBuf *ibuf, const char *name); /* for reload, refresh, pack */ void BKE_image_init_imageuser(struct Image *ima, struct ImageUser *iuser); diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index e88a4e88209..6ecc955e26c 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -107,8 +107,9 @@ void BKE_library_make_local(struct Main *bmain, struct Library *lib, bool untagg struct ID *BKE_libblock_find_name_ex(struct Main *bmain, const short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); struct ID *BKE_libblock_find_name(const short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -void set_free_windowmanager_cb(void (*func)(struct bContext *, struct wmWindowManager *)); -void set_free_notifier_reference_cb(void (*func)(const void *)); +void BKE_library_callback_free_window_manager_set(void (*func)(struct bContext *, struct wmWindowManager *)); +void BKE_library_callback_free_notifier_reference_set(void (*func)(const void *)); +void BKE_library_callback_free_editor_id_reference_set(void (*func)(const struct ID *)); /* use when "" is given to new_id() */ #define ID_FALLBACK_NAME N_("Untitled") diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index 56393727d28..0cfa1aeecb5 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -50,6 +50,7 @@ void BKE_material_free_ex(struct Material *ma, bool do_id_user); void test_object_materials(struct Main *bmain, struct ID *id); void BKE_material_resize_object(struct Object *ob, const short totcol, bool do_id_user); void init_material(struct Material *ma); +void BKE_material_remap_object(struct Object *ob, const unsigned int *remap); struct Material *BKE_material_add(struct Main *bmain, const char *name); struct Material *BKE_material_copy(struct Material *ma); struct Material *localize_material(struct Material *ma); diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index c0d8902eb71..ebf4384d5a7 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -108,6 +108,7 @@ void BKE_mesh_to_curve_nurblist(struct DerivedMesh *dm, struct ListBase *nurblis void BKE_mesh_to_curve(struct Scene *scene, struct Object *ob); void BKE_mesh_material_index_remove(struct Mesh *me, short index); void BKE_mesh_material_index_clear(struct Mesh *me); +void BKE_mesh_material_remap(struct Mesh *me, const unsigned int *remap, unsigned int remap_len); void BKE_mesh_smooth_flag_set(struct Object *meshOb, int enableSmooth); const char *BKE_mesh_cmp(struct Mesh *me1, struct Mesh *me2, float thresh); diff --git a/source/blender/blenkernel/BKE_mesh_mapping.h b/source/blender/blenkernel/BKE_mesh_mapping.h index da44c989146..dcf5d2ed78d 100644 --- a/source/blender/blenkernel/BKE_mesh_mapping.h +++ b/source/blender/blenkernel/BKE_mesh_mapping.h @@ -102,7 +102,7 @@ typedef struct MeshElemMap { /* mapping */ UvVertMap *BKE_mesh_uv_vert_map_create( struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv, - unsigned int totpoly, unsigned int totvert, int selected, float *limit); + unsigned int totpoly, unsigned int totvert, int selected, float *limit, bool use_winding); UvMapVert *BKE_mesh_uv_vert_map_get_vert(UvVertMap *vmap, unsigned int v); void BKE_mesh_uv_vert_map_free(UvVertMap *vmap); diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 0ddc9b0b256..0e0c779c033 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -33,6 +33,8 @@ extern "C" { #endif +#include "BLI_compiler_attrs.h" + struct Base; struct EvaluationContext; struct Scene; @@ -82,9 +84,18 @@ bool BKE_object_is_in_editmode(struct Object *ob); bool BKE_object_is_in_editmode_vgroup(struct Object *ob); bool BKE_object_is_in_wpaint_select_vert(struct Object *ob); -struct Object *BKE_object_add_only_object(struct Main *bmain, int type, const char *name); -struct Object *BKE_object_add(struct Main *bmain, struct Scene *scene, int type); -void *BKE_object_obdata_add_from_type(struct Main *bmain, int type); +struct Object *BKE_object_add_only_object( + struct Main *bmain, + int type, const char *name) + ATTR_NONNULL(1) ATTR_RETURNS_NONNULL; +struct Object *BKE_object_add( + struct Main *bmain, struct Scene *scene, + int type, const char *name) + ATTR_NONNULL(1, 2) ATTR_RETURNS_NONNULL; +void *BKE_object_obdata_add_from_type( + struct Main *bmain, + int type, const char *name) + ATTR_NONNULL(1); void BKE_object_lod_add(struct Object *ob); void BKE_object_lod_sort(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_packedFile.h b/source/blender/blenkernel/BKE_packedFile.h index 8fab44121de..a2397922061 100644 --- a/source/blender/blenkernel/BKE_packedFile.h +++ b/source/blender/blenkernel/BKE_packedFile.h @@ -48,7 +48,7 @@ struct PackedFile *dupPackedFile(const struct PackedFile *pf_src); struct PackedFile *newPackedFile(struct ReportList *reports, const char *filename, const char *relabase); struct PackedFile *newPackedFileMemory(void *mem, int memlen); -void packAll(struct Main *bmain, struct ReportList *reports); +void packAll(struct Main *bmain, struct ReportList *reports, bool verbose); void packLibraries(struct Main *bmain, struct ReportList *reports); /* unpack */ diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 03ad1765f8d..1df633cc966 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -104,8 +104,9 @@ bool BKE_pbvh_bmesh_node_raycast_detail( /* for orthographic cameras, project the far away ray segment points to the root node so * we can have better precision. */ -void BKE_pbvh_raycast_project_ray_root(PBVH *bvh, bool original, float ray_start[3], - float ray_end[3], float ray_normal[3]); +void BKE_pbvh_raycast_project_ray_root( + PBVH *bvh, bool original, + float ray_start[3], float ray_end[3], float ray_normal[3]); /* Drawing */ diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 79778d504a5..75a5e919bad 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -127,8 +127,8 @@ struct SceneRenderView *BKE_scene_add_render_view(struct Scene *sce, const char bool BKE_scene_remove_render_view(struct Scene *scene, struct SceneRenderView *srv); /* render profile */ -int get_render_subsurf_level(const struct RenderData *r, int level); -int get_render_child_particle_number(const struct RenderData *r, int num); +int get_render_subsurf_level(const struct RenderData *r, int level, bool for_render); +int get_render_child_particle_number(const struct RenderData *r, int num, bool for_render); int get_render_shadow_samples(const struct RenderData *r, int samples); float get_render_aosss_error(const struct RenderData *r, float error); diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 43499933d16..c584051708b 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -273,6 +273,9 @@ void BKE_spacedata_freelist(ListBase *lb); void BKE_spacedata_copylist(ListBase *lb1, ListBase *lb2); void BKE_spacedata_draw_locks(int set); +void BKE_spacedata_callback_id_unref_set(void (*func)(struct SpaceLink *sl, const struct ID *)); +void BKE_spacedata_id_unref(struct SpaceLink *sl, const struct ID *id); + /* area/regions */ struct ARegion *BKE_area_region_copy(struct SpaceType *st, struct ARegion *ar); void BKE_area_region_free(struct SpaceType *st, struct ARegion *ar); @@ -280,6 +283,7 @@ void BKE_screen_area_free(struct ScrArea *sa); struct ARegion *BKE_area_find_region_type(struct ScrArea *sa, int type); struct ARegion *BKE_area_find_region_active_win(struct ScrArea *sa); +struct ARegion *BKE_area_find_region_xy(struct ScrArea *sa, const int regiontype, int x, int y); struct ScrArea *BKE_screen_find_area_from_space(struct bScreen *sc, struct SpaceLink *sl) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2); struct ScrArea *BKE_screen_find_big_area(struct bScreen *sc, const int spacetype, const short min); struct ScrArea *BKE_screen_find_area_xy(struct bScreen *sc, const int spacetype, int x, int y); diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index ef997446c6c..ea56c084fb5 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -136,6 +136,21 @@ struct MovieTrackingPlaneTrack *BKE_tracking_plane_track_get_active(struct Movie void BKE_tracking_plane_tracks_deselect_all(struct ListBase *plane_tracks_base); +bool BKE_tracking_plane_track_has_point_track(struct MovieTrackingPlaneTrack *plane_track, + struct MovieTrackingTrack *track); +bool BKE_tracking_plane_track_remove_point_track(struct MovieTrackingPlaneTrack *plane_track, + struct MovieTrackingTrack *track); + +void BKE_tracking_plane_tracks_remove_point_track(struct MovieTracking *tracking, + struct MovieTrackingTrack *track); + +void BKE_tracking_plane_track_replace_point_track(struct MovieTrackingPlaneTrack *plane_track, + struct MovieTrackingTrack *old_track, + struct MovieTrackingTrack *new_track); +void BKE_tracking_plane_tracks_replace_point_track(struct MovieTracking *tracking, + struct MovieTrackingTrack *old_track, + struct MovieTrackingTrack *new_track); + /* **** Plane Marker **** */ struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_insert(struct MovieTrackingPlaneTrack *plane_track, struct MovieTrackingPlaneMarker *plane_marker); diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 2085fefdb93..37bd9c5db5c 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -623,7 +623,7 @@ int BKE_write_file_userdef(const char *filepath, ReportList *reports) static void (*blender_test_break_cb)(void) = NULL; -void set_blender_test_break_cb(void (*func)(void)) +void BKE_blender_callback_test_break_set(void (*func)(void)) { blender_test_break_cb = func; } diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 5fcdc9c2e78..30ceaea89b8 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -4422,9 +4422,6 @@ void BKE_curve_material_index_remove(Curve *cu, int index) for (nu = cu->nurb.first; nu; nu = nu->next) { if (nu->mat_nr && nu->mat_nr >= index) { nu->mat_nr--; - if (curvetype == OB_CURVE) { - nu->charidx--; - } } } } @@ -4446,9 +4443,6 @@ void BKE_curve_material_index_clear(Curve *cu) for (nu = cu->nurb.first; nu; nu = nu->next) { nu->mat_nr = 0; - if (curvetype == OB_CURVE) { - nu->charidx = 0; - } } } } @@ -4475,9 +4469,6 @@ int BKE_curve_material_index_validate(Curve *cu) for (nu = cu->nurb.first; nu; nu = nu->next) { if (nu->mat_nr > max_idx) { nu->mat_nr = 0; - if (curvetype == OB_CURVE) { - nu->charidx = 0; - } is_valid = false; } } @@ -4492,6 +4483,54 @@ int BKE_curve_material_index_validate(Curve *cu) } } +void BKE_curve_material_remap(Curve *cu, const unsigned int *remap, unsigned int remap_len) +{ + const int curvetype = BKE_curve_type_get(cu); + const short remap_len_short = (short)remap_len; + +#define MAT_NR_REMAP(n) \ + if (n < remap_len_short) { \ + BLI_assert(n >= 0 && remap[n] < remap_len_short); \ + n = remap[n]; \ + } ((void)0) + + if (curvetype == OB_FONT) { + struct CharInfo *strinfo; + int charinfo_len, i; + + if (cu->editfont) { + EditFont *ef = cu->editfont; + strinfo = ef->textbufinfo; + charinfo_len = ef->len; + } + else { + strinfo = cu->strinfo; + charinfo_len = cu->len_wchar; + } + + for (i = 0; i <= charinfo_len; i++) { + if (strinfo[i].mat_nr > 0) { + strinfo[i].mat_nr -= 1; + MAT_NR_REMAP(strinfo[i].mat_nr); + strinfo[i].mat_nr += 1; + } + } + } + else { + Nurb *nu; + ListBase *nurbs = BKE_curve_editNurbs_get(cu); + + if (nurbs) { + for (nu = nurbs->first; nu; nu = nu->next) { + MAT_NR_REMAP(nu->mat_nr); + } + } + } + +#undef MAT_NR_REMAP + +} + void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *tb, struct rctf *r_rect) { r_rect->xmin = cu->xof + tb->x; diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index a09c42e9178..5169559d80b 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -883,12 +883,16 @@ Image *BKE_image_add_generated(Main *bmain, unsigned int width, unsigned int hei /* Create an image image from ibuf. The refcount of ibuf is increased, * caller should take care to drop its reference by calling * IMB_freeImBuf if needed. */ -Image *BKE_image_add_from_imbuf(ImBuf *ibuf) +Image *BKE_image_add_from_imbuf(ImBuf *ibuf, const char *name) { /* on save, type is changed to FILE in editsima.c */ Image *ima; - ima = image_alloc(G.main, BLI_path_basename(ibuf->name), IMA_SRC_FILE, IMA_TYPE_IMAGE); + if (name == NULL) { + name = BLI_path_basename(ibuf->name); + } + + ima = image_alloc(G.main, name, IMA_SRC_FILE, IMA_TYPE_IMAGE); if (ima) { BLI_strncpy(ima->name, ibuf->name, FILE_MAX); @@ -2028,26 +2032,45 @@ void BKE_image_stamp_buf( #undef BUFF_MARGIN_Y } -void BKE_imbuf_stamp_info(Scene *scene, Object *camera, struct ImBuf *ibuf) +void BKE_render_result_stamp_info(Scene *scene, Object *camera, struct RenderResult *rr) { - struct StampData stamp_data; + struct StampData *stamp_data; - if (!ibuf) return; + if (!(scene && scene->r.stamp & R_STAMP_ALL)) + return; - /* fill all the data values, no prefix */ - stampdata(scene, camera, &stamp_data, 0); + if (!rr->stamp_data) { + stamp_data = MEM_callocN(sizeof(StampData), "RenderResult.stamp_data"); + } + else { + stamp_data = rr->stamp_data; + } - if (stamp_data.file[0]) IMB_metadata_change_field(ibuf, "File", stamp_data.file); - if (stamp_data.note[0]) IMB_metadata_change_field(ibuf, "Note", stamp_data.note); - if (stamp_data.date[0]) IMB_metadata_change_field(ibuf, "Date", stamp_data.date); - if (stamp_data.marker[0]) IMB_metadata_change_field(ibuf, "Marker", stamp_data.marker); - if (stamp_data.time[0]) IMB_metadata_change_field(ibuf, "Time", stamp_data.time); - if (stamp_data.frame[0]) IMB_metadata_change_field(ibuf, "Frame", stamp_data.frame); - if (stamp_data.camera[0]) IMB_metadata_change_field(ibuf, "Camera", stamp_data.camera); - if (stamp_data.cameralens[0]) IMB_metadata_change_field(ibuf, "Lens", stamp_data.cameralens); - if (stamp_data.scene[0]) IMB_metadata_change_field(ibuf, "Scene", stamp_data.scene); - if (stamp_data.strip[0]) IMB_metadata_change_field(ibuf, "Strip", stamp_data.strip); - if (stamp_data.rendertime[0]) IMB_metadata_change_field(ibuf, "RenderTime", stamp_data.rendertime); + stampdata(scene, camera, stamp_data, 0); + + if (!rr->stamp_data) { + rr->stamp_data = stamp_data; + } +} + + +void BKE_imbuf_stamp_info(RenderResult *rr, struct ImBuf *ibuf) +{ + struct StampData *stamp_data = rr->stamp_data; + + if (!ibuf || !stamp_data) return; + + if (stamp_data->file[0]) IMB_metadata_change_field(ibuf, "File", stamp_data->file); + if (stamp_data->note[0]) IMB_metadata_change_field(ibuf, "Note", stamp_data->note); + if (stamp_data->date[0]) IMB_metadata_change_field(ibuf, "Date", stamp_data->date); + if (stamp_data->marker[0]) IMB_metadata_change_field(ibuf, "Marker", stamp_data->marker); + if (stamp_data->time[0]) IMB_metadata_change_field(ibuf, "Time", stamp_data->time); + if (stamp_data->frame[0]) IMB_metadata_change_field(ibuf, "Frame", stamp_data->frame); + if (stamp_data->camera[0]) IMB_metadata_change_field(ibuf, "Camera", stamp_data->camera); + if (stamp_data->cameralens[0]) IMB_metadata_change_field(ibuf, "Lens", stamp_data->cameralens); + if (stamp_data->scene[0]) IMB_metadata_change_field(ibuf, "Scene", stamp_data->scene); + if (stamp_data->strip[0]) IMB_metadata_change_field(ibuf, "Strip", stamp_data->strip); + if (stamp_data->rendertime[0]) IMB_metadata_change_field(ibuf, "RenderTime", stamp_data->rendertime); } bool BKE_imbuf_alpha_test(ImBuf *ibuf) @@ -2242,15 +2265,14 @@ int BKE_imbuf_write_as(ImBuf *ibuf, const char *name, ImageFormatData *imf, return ok; } -int BKE_imbuf_write_stamp(Scene *scene, struct Object *camera, ImBuf *ibuf, const char *name, struct ImageFormatData *imf) +int BKE_imbuf_write_stamp(Scene *scene, struct RenderResult *rr, ImBuf *ibuf, const char *name, struct ImageFormatData *imf) { if (scene && scene->r.stamp & R_STAMP_ALL) - BKE_imbuf_stamp_info(scene, camera, ibuf); + BKE_imbuf_stamp_info(rr, ibuf); return BKE_imbuf_write(ibuf, name, imf); } - static void do_makepicstring( char *string, const char *base, const char *relbase, int frame, const char imtype, const ImageFormatData *im_format, const short use_ext, const short use_frames, @@ -3504,6 +3526,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ { Render *re; RenderResult rres; + RenderView *rv; float *rectf, *rectz; unsigned int *rect; float dither; @@ -3535,7 +3558,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ } else if (ima->renders[ima->render_slot]) { rres = *(ima->renders[ima->render_slot]); - rres.have_combined = RE_RenderViewGetRectf(&rres, actview) != NULL; + rres.have_combined = ((RenderView *)rres.views.first)->rectf != NULL; } else memset(&rres, 0, sizeof(RenderResult)); @@ -3550,12 +3573,26 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ if (from_render) { BLI_lock_thread(LOCK_VIEWER); *lock_r = re; + rv = NULL; + } + else { + rv = BLI_findlink(&rres.views, actview); + if (rv == NULL) + rv = rres.views.first; } /* this gives active layer, composite or sequence result */ - rect = (unsigned int *)rres.rect32; - rectf = rres.rectf; - rectz = rres.rectz; + if (rv == NULL) { + rect = (unsigned int *)rres.rect32; + rectf = rres.rectf; + rectz = rres.rectz; + } + else { + rect = (unsigned int *)rv->rect32; + rectf = rv->rectf; + rectz = rv->rectz; + } + dither = iuser->scene->r.dither_intensity; /* combined layer gets added as first layer */ @@ -3586,6 +3623,15 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **lock_ if (rpass) { channels = rpass->channels; rectf = rpass->rect; + + if (!rectf) { + /* Happens when Save Buffers is enabled. + * Use display buffer stored in the render layer. + */ + rect = (unsigned int *) rl->display_buffer; + byte_buffer_in_display_space = true; + } + dither = 0.0f; /* don't dither passes */ } diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 2cee08a821b..42856e82062 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -865,18 +865,24 @@ static void BKE_library_free(Library *lib) static void (*free_windowmanager_cb)(bContext *, wmWindowManager *) = NULL; -void set_free_windowmanager_cb(void (*func)(bContext *C, wmWindowManager *) ) +void BKE_library_callback_free_window_manager_set(void (*func)(bContext *C, wmWindowManager *) ) { free_windowmanager_cb = func; } static void (*free_notifier_reference_cb)(const void *) = NULL; -void set_free_notifier_reference_cb(void (*func)(const void *) ) +void BKE_library_callback_free_notifier_reference_set(void (*func)(const void *) ) { free_notifier_reference_cb = func; } +static void (*free_editor_id_reference_cb)(const ID *) = NULL; + +void BKE_library_callback_free_editor_id_reference_set(void (*func)(const ID *)) +{ + free_editor_id_reference_cb = func; +} static void animdata_dtar_clear_cb(ID *UNUSED(id), AnimData *adt, void *userdata) { @@ -1034,8 +1040,13 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, bool do_id_user) /* avoid notifying on removed data */ BKE_main_lock(bmain); - if (free_notifier_reference_cb) + if (free_notifier_reference_cb) { free_notifier_reference_cb(id); + } + + if (free_editor_id_reference_cb) { + free_editor_id_reference_cb(id); + } BLI_remlink(lb, id); diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c index 387d093051e..13ec970c65c 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.c +++ b/source/blender/blenkernel/intern/mask_rasterize.c @@ -1360,6 +1360,9 @@ float BKE_maskrasterize_handle_sample(MaskRasterHandle *mr_handle, const float x case PROP_SHARP: value_layer = value_layer * value_layer; break; + case PROP_INVSQUARE: + value_layer = value_layer * (2.0f - value_layer); + break; case PROP_LIN: default: /* nothing */ diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index b5b7f3d06aa..eaaf1319167 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -53,6 +53,7 @@ #include "BLI_listbase.h" #include "BLI_utildefines.h" #include "BLI_string.h" +#include "BLI_array_utils.h" #include "BKE_animsys.h" #include "BKE_displist.h" @@ -66,6 +67,8 @@ #include "BKE_scene.h" #include "BKE_node.h" #include "BKE_curve.h" +#include "BKE_editmesh.h" +#include "BKE_font.h" #include "GPU_material.h" @@ -806,9 +809,13 @@ void assign_material_id(ID *id, Material *ma, short act) if (act > MAXMAT) return; if (act < 1) act = 1; + /* this is needed for Python overrides, + * we just have to take care that the UI can't do this */ +#if 0 /* prevent crashing when using accidentally */ BLI_assert(id->lib == NULL); if (id->lib) return; +#endif /* test arraylens */ @@ -918,6 +925,35 @@ void assign_material(Object *ob, Material *ma, short act, int assign_type) test_object_materials(G.main, ob->data); } + +void BKE_material_remap_object(Object *ob, const unsigned int *remap) +{ + Material ***matar = give_matarar(ob); + const short *totcol_p = give_totcolp(ob); + + BLI_array_permute(ob->mat, ob->totcol, remap); + + if (ob->matbits) { + BLI_array_permute(ob->matbits, ob->totcol, remap); + } + + if (matar) { + BLI_array_permute(*matar, *totcol_p, remap); + } + + if (ob->type == OB_MESH) { + BKE_mesh_material_remap(ob->data, remap, ob->totcol); + } + else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { + BKE_curve_material_remap(ob->data, remap, ob->totcol); + } + else { + /* add support for this object data! */ + BLI_assert(matar == NULL); + } +} + + /* XXX - this calls many more update calls per object then are needed, could be optimized */ void assign_matarar(struct Object *ob, struct Material ***matar, short totcol) { diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index eec2b108ca3..e66a4d48fc8 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -1265,7 +1265,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase, dl = dispbase->first; while (dl) { - int smooth = dl->rt & CU_SMOOTH ? 1 : 0; + const bool is_smooth = (dl->rt & CU_SMOOTH) != 0; if (dl->type == DL_SEGM) { startvert = vertcount; @@ -1344,7 +1344,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase, } } - if (smooth) mpoly->flag |= ME_SMOOTH; + if (is_smooth) mpoly->flag |= ME_SMOOTH; mpoly++; mloop += 3; index += 3; @@ -1423,7 +1423,7 @@ int BKE_mesh_nurbs_displist_to_mdata(Object *ob, ListBase *dispbase, } } - if (smooth) mpoly->flag |= ME_SMOOTH; + if (is_smooth) mpoly->flag |= ME_SMOOTH; mpoly++; mloop += 4; @@ -1773,6 +1773,36 @@ void BKE_mesh_material_index_clear(Mesh *me) } } +void BKE_mesh_material_remap(Mesh *me, const unsigned int *remap, unsigned int remap_len) +{ + const short remap_len_short = (short)remap_len; + +#define MAT_NR_REMAP(n) \ + if (n < remap_len_short) { \ + BLI_assert(n >= 0 && remap[n] < remap_len_short); \ + n = remap[n]; \ + } ((void)0) + + if (me->edit_btmesh) { + BMEditMesh *em = me->edit_btmesh; + BMIter iter; + BMFace *efa; + + BM_ITER_MESH(efa, &iter, em->bm, BM_FACES_OF_MESH) { + MAT_NR_REMAP(efa->mat_nr); + } + } + else { + int i; + for (i = 0; i < me->totpoly; i++) { + MAT_NR_REMAP(me->mpoly[i].mat_nr); + } + } + +#undef MAT_NR_REMAP + +} + void BKE_mesh_smooth_flag_set(Object *meshOb, int enableSmooth) { Mesh *me = meshOb->data; @@ -1890,6 +1920,7 @@ void BKE_mesh_transform(Mesh *me, float mat[4][4], bool do_keys) { int i; MVert *mvert = me->mvert; + float (*lnors)[3] = CustomData_get_layer(&me->ldata, CD_NORMAL); for (i = 0; i < me->totvert; i++, mvert++) mul_m4_v3(mat, mvert->co); @@ -1904,7 +1935,17 @@ void BKE_mesh_transform(Mesh *me, float mat[4][4], bool do_keys) } } - /* don't update normals, caller can do this explicitly */ + /* don't update normals, caller can do this explicitly. + * We do update loop normals though, those may not be auto-generated (see e.g. STL import script)! */ + if (lnors) { + float m3[3][3]; + + copy_m3_m4(m3, mat); + normalize_m3(m3); + for (i = 0; i < me->totloop; i++, lnors++) { + mul_m3_v3(m3, *lnors); + } + } } void BKE_mesh_translate(Mesh *me, const float offset[3], const bool do_keys) diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c index ebdbd3aac8a..e4a85eb399b 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.c +++ b/source/blender/blenkernel/intern/mesh_mapping.c @@ -55,7 +55,7 @@ * but for now this replaces it because its unused. */ UvVertMap *BKE_mesh_uv_vert_map_create(struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv, - unsigned int totpoly, unsigned int totvert, int selected, float *limit) + unsigned int totpoly, unsigned int totvert, int selected, float *limit, bool use_winding) { UvVertMap *vmap; UvMapVert *buf; @@ -109,7 +109,10 @@ UvVertMap *BKE_mesh_uv_vert_map_create(struct MPoly *mpoly, struct MLoop *mloop, buf++; } - winding[a] = cross_poly_v2((const float (*)[2])tf_uv, (unsigned int)nverts) > 0; + if (use_winding) + winding[a] = cross_poly_v2((const float (*)[2])tf_uv, (unsigned int)nverts) > 0; + else + winding[a] = 0; } } @@ -177,8 +180,6 @@ void BKE_mesh_uv_vert_map_free(UvVertMap *vmap) } /** - - * Generates a map where the key is the vertex and the value is a list * of polys or loops that use that vertex as a corner. The lists are allocated * from one memory pool. @@ -251,9 +252,10 @@ void BKE_mesh_vert_loop_map_create(MeshElemMap **r_map, int **r_mem, mesh_vert_poly_or_loop_map_create(r_map, r_mem, mpoly, mloop, totvert, totpoly, totloop, true); } -/* Generates a map where the key is the vertex and the value is a list - * of edges that use that vertex as an endpoint. The lists are allocated - * from one memory pool. */ +/** + * Generates a map where the key is the vertex and the value is a list of edges that use that vertex as an endpoint. + * The lists are allocated from one memory pool. + */ void BKE_mesh_vert_edge_map_create(MeshElemMap **r_map, int **r_mem, const MEdge *medge, int totvert, int totedge) { @@ -293,6 +295,10 @@ void BKE_mesh_vert_edge_map_create(MeshElemMap **r_map, int **r_mem, *r_mem = indices; } +/** + * Generates a map where the key is the edge and the value is a list of polygons that use that edge. + * The lists are allocated from one memory pool. + */ void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, int **r_mem, const MEdge *UNUSED(medge), const int totedge, const MPoly *mpoly, const int totpoly, @@ -400,7 +406,8 @@ void BKE_mesh_origindex_map_create(MeshElemMap **r_map, int **r_mem, * Used currently for UVs and 'smooth groups'. * \{ */ -/** Callback deciding whether the given poly/loop/edge define an island boundary or not. +/** + * Callback deciding whether the given poly/loop/edge define an island boundary or not. */ typedef bool (*MeshRemap_CheckIslandBoundary)( const struct MPoly *mpoly, const struct MLoop *mloop, const struct MEdge *medge, @@ -583,8 +590,7 @@ static void poly_edge_loop_islands_calc( } static bool poly_is_island_boundary_smooth_cb( - const MPoly *mp, const MLoop *UNUSED(ml), const MEdge *me, - const int nbr_egde_users) + const MPoly *mp, const MLoop *UNUSED(ml), const MEdge *me, const int nbr_egde_users) { /* Edge is sharp if its poly is sharp, or edge itself is sharp, or edge is not used by exactly two polygons. */ return (!(mp->flag & ME_SMOOTH) || (me->flag & ME_SHARP) || (nbr_egde_users != 2)); @@ -681,7 +687,6 @@ void BKE_mesh_loop_islands_add( const size_t curr_num_islands = (size_t)island_store->islands_num; int i = item_num; - island_store->items_to_islands_num = item_num; while (i--) { island_store->items_to_islands[items_indices[i]] = curr_island_idx; } @@ -716,17 +721,21 @@ void BKE_mesh_loop_islands_add( * not sure we want that at all! */ static bool mesh_check_island_boundary_uv( - const MPoly *UNUSED(mp), const MLoop *UNUSED(ml), const MEdge *me, - const int UNUSED(nbr_egde_users)) + const MPoly *UNUSED(mp), const MLoop *UNUSED(ml), const MEdge *me, const int UNUSED(nbr_egde_users)) { /* Edge is UV boundary if tagged as seam. */ return (me->flag & ME_SEAM) != 0; } /** - * \note all this could be optimized... - * Not sure it would be worth the more complex code, though, those loops - * are supposed to be really quick to do... + * Calculate UV islands. + * + * \note Currently we only consider edges tagges as seams as UV boundaries. This has the advantages of simplicity, + * and being valid/common to all UV maps. However, it means actual UV islands whithout matching UV seams + * will not be handled correctly... + * + * \note All this could be optimized... + * Not sure it would be worth the more complex code, though, those loops are supposed to be really quick to do... */ bool BKE_mesh_calc_islands_loop_poly_uv( MVert *UNUSED(verts), const int UNUSED(totvert), diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c index aca72614094..f3e2f395002 100644 --- a/source/blender/blenkernel/intern/mesh_remap.c +++ b/source/blender/blenkernel/intern/mesh_remap.c @@ -977,6 +977,8 @@ void BKE_mesh_remap_calc_loops_from_dm( float (*poly_nors_dst)[3] = NULL; float (*loop_nors_dst)[3] = NULL; + float (*poly_cents_src)[3] = NULL; + MeshElemMap *vert_to_loop_map_src = NULL; int *vert_to_loop_map_src_buff = NULL; MeshElemMap *vert_to_poly_map_src = NULL; @@ -1012,6 +1014,8 @@ void BKE_mesh_remap_calc_loops_from_dm( int *indices_interp = NULL; float *weights_interp = NULL; + MLoop *ml_src, *ml_dst; + MPoly *mp_src, *mp_dst; int tindex, pidx_dst, lidx_dst, plidx_dst, pidx_src, lidx_src, plidx_src; IslandResult **islands_res; @@ -1089,11 +1093,13 @@ void BKE_mesh_remap_calc_loops_from_dm( edges_src, num_edges_src, polys_src, num_polys_src, loops_src, num_loops_src); if (use_from_vert) { loop_to_poly_map_src = MEM_mallocN(sizeof(*loop_to_poly_map_src) * (size_t)num_loops_src, __func__); - for (pidx_src = 0; pidx_src < num_polys_src; pidx_src++) { - MPoly *mp = &polys_src[pidx_src]; - for (plidx_src = 0, lidx_src = mp->loopstart; plidx_src < mp->totloop; plidx_src++, lidx_src++) { + poly_cents_src = MEM_mallocN(sizeof(*poly_cents_src) * (size_t)num_polys_src, __func__); + for (pidx_src = 0, mp_src = polys_src; pidx_src < num_polys_src; pidx_src++, mp_src++) { + ml_src = &loops_src[mp_src->loopstart]; + for (plidx_src = 0, lidx_src = mp_src->loopstart; plidx_src < mp_src->totloop; plidx_src++, lidx_src++) { loop_to_poly_map_src[lidx_src] = pidx_src; } + BKE_mesh_calc_poly_center(mp_src, ml_src, verts_src, poly_cents_src[pidx_src]); } } @@ -1155,10 +1161,13 @@ void BKE_mesh_remap_calc_loops_from_dm( int num_verts_active = 0; BLI_BITMAP_SET_ALL(verts_active, false, (size_t)num_verts_src); for (i = 0; i < isld->count; i++) { - MPoly *mp_src = &polys_src[isld->indices[i]]; + mp_src = &polys_src[isld->indices[i]]; for (lidx_src = mp_src->loopstart; lidx_src < mp_src->loopstart + mp_src->totloop; lidx_src++) { - BLI_BITMAP_ENABLE(verts_active, loops_src[lidx_src].v); - num_verts_active++; + const unsigned int vidx_src = loops_src[lidx_src].v; + if (!BLI_BITMAP_TEST(verts_active, vidx_src)) { + BLI_BITMAP_ENABLE(verts_active, loops_src[lidx_src].v); + num_verts_active++; + } } } /* verts 'ownership' is transfered to treedata here, which will handle its freeing. */ @@ -1199,13 +1208,13 @@ void BKE_mesh_remap_calc_loops_from_dm( int num_faces_active = 0; BLI_BITMAP_SET_ALL(faces_active, false, (size_t)num_faces_src); for (i = 0; i < num_faces_src; i++) { - MPoly *mp_src = &polys_src[tessface_to_poly_map_src[i]]; + mp_src = &polys_src[tessface_to_poly_map_src[i]]; if (island_store.items_to_islands[mp_src->loopstart] == tindex) { BLI_BITMAP_ENABLE(faces_active, i); num_faces_active++; } } - /* verts 'ownership' is transfered to treedata here, which will handle its freeing. */ + /* verts and faces 'ownership' is transfered to treedata here, which will handle its freeing. */ bvhtree_from_mesh_faces_ex( &treedata[tindex], verts_src, verts_allocated_src, faces_src, num_faces_src, faces_allocated_src, @@ -1233,10 +1242,14 @@ void BKE_mesh_remap_calc_loops_from_dm( islands_res[tindex] = MEM_mallocN(sizeof(**islands_res) * islands_res_buff_size, __func__); } - for (pidx_dst = 0; pidx_dst < numpolys_dst; pidx_dst++) { - MPoly *mp_dst = &polys_dst[pidx_dst]; + for (pidx_dst = 0, mp_dst = polys_dst; pidx_dst < numpolys_dst; pidx_dst++, mp_dst++) { float (*pnor_dst)[3] = &poly_nors_dst[pidx_dst]; + /* Only in use_from_vert case, we may need polys' centers as fallback in case we cannot decide which + * corner to use from normals only. */ + float pcent_dst[3]; + bool pcent_dst_valid = false; + if ((size_t)mp_dst->totloop > islands_res_buff_size) { islands_res_buff_size = (size_t)mp_dst->totloop; for (tindex = 0; tindex < num_trees; tindex++) { @@ -1246,8 +1259,8 @@ void BKE_mesh_remap_calc_loops_from_dm( for (tindex = 0; tindex < num_trees; tindex++) { BVHTreeFromMesh *tdata = &treedata[tindex]; - MLoop *ml_dst = &loops_dst[mp_dst->loopstart]; + ml_dst = &loops_dst[mp_dst->loopstart]; for (plidx_dst = 0; plidx_dst < mp_dst->totloop; plidx_dst++, ml_dst++) { if (use_from_vert) { float tmp_co[3]; @@ -1263,6 +1276,7 @@ void BKE_mesh_remap_calc_loops_from_dm( float (*nor_dst)[3]; float (*nors_src)[3]; float best_nor_dot = -2.0f; + float best_sqdist_fallback = FLT_MAX; int best_index_src = -1; if (mode == MREMAP_MODE_LOOP_NEAREST_LOOPNOR) { @@ -1279,16 +1293,50 @@ void BKE_mesh_remap_calc_loops_from_dm( for (i = vert_to_refelem_map_src[nearest.index].count; i--;) { const int index_src = vert_to_refelem_map_src[nearest.index].indices[i]; const float dot = dot_v3v3(nors_src[index_src], *nor_dst); - if (dot > best_nor_dot) { - best_nor_dot = dot; - best_index_src = index_src; + + pidx_src = (mode == MREMAP_MODE_LOOP_NEAREST_LOOPNOR) ? + loop_to_poly_map_src[index_src] : index_src; + /* WARNING! This is not the *real* lidx_src in case of POLYNOR, we only use it + * to check we stay on current island (all loops from a given poly are + * on same island!). */ + lidx_src = (mode == MREMAP_MODE_LOOP_NEAREST_LOOPNOR) ? + index_src : polys_src[pidx_src].loopstart; + + /* A same vert may be at the boundary of several islands! Hence, we have to ensure + * poly/loop we are currently considering *belongs* to current island! */ + if (island_store.items_to_islands[lidx_src] != tindex) { + continue; + } + + if (dot > best_nor_dot - 1e-6f) { + /* We need something as fallback decision in case dest normal matches several + * source normals (see T44522), using distance between polys' centers here. */ + float *pcent_src; + float sqdist; + + mp_src = &polys_src[pidx_src]; + ml_src = &loops_src[mp_src->loopstart]; + + if (!pcent_dst_valid) { + BKE_mesh_calc_poly_center( + mp_dst, &loops_dst[mp_dst->loopstart], verts_dst, pcent_dst); + pcent_dst_valid = true; + } + pcent_src = poly_cents_src[pidx_src]; + sqdist = len_squared_v3v3(pcent_dst, pcent_src); + + if ((dot > best_nor_dot + 1e-6f) || (sqdist < best_sqdist_fallback)) { + best_nor_dot = dot; + best_sqdist_fallback = sqdist; + best_index_src = index_src; + } } } if (mode == MREMAP_MODE_LOOP_NEAREST_POLYNOR) { /* Our best_index_src is a poly one for now! * Have to find its loop matching our closest vertex. */ - MPoly *mp_src = &polys_src[best_index_src]; - MLoop *ml_src = &loops_src[mp_src->loopstart]; + mp_src = &polys_src[best_index_src]; + ml_src = &loops_src[mp_src->loopstart]; for (plidx_src = 0; plidx_src < mp_src->totloop; plidx_src++, ml_src++) { if ((int)ml_src->v == nearest.index) { best_index_src = plidx_src + mp_src->loopstart; @@ -1296,7 +1344,8 @@ void BKE_mesh_remap_calc_loops_from_dm( } } } - islands_res[tindex][plidx_dst].factor = hit_dist ? (1.0f / (hit_dist * best_nor_dot)) : 1e18f; + best_nor_dot = (best_nor_dot + 1.0f) * 0.5f; + islands_res[tindex][plidx_dst].factor = hit_dist ? (1.0f / hit_dist * best_nor_dot) : 1e18f; islands_res[tindex][plidx_dst].hit_dist = hit_dist; islands_res[tindex][plidx_dst].index_src = best_index_src; } @@ -1488,12 +1537,11 @@ void BKE_mesh_remap_calc_loops_from_dm( if (last_valid_pidx_isld_src != -1) { /* Find a new valid loop in that new poly (nearest one for now). * Note we could be much more subtle here, again that's for later... */ - MPoly *mp_src; - MLoop *ml_src, *ml_dst = &loops_dst[lidx_dst]; int j; float best_dist_sq = FLT_MAX; float tmp_co[3]; + ml_dst = &loops_dst[lidx_dst]; copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co); /* We do our transform here, since we may do several raycast/nearest queries. */ @@ -1532,10 +1580,10 @@ void BKE_mesh_remap_calc_loops_from_dm( /* Else, we use source poly, indices stored in islands_res are those of polygons. */ pidx_src = isld_res->index_src; if (pidx_src >= 0) { - MPoly *mp_src = &polys_src[pidx_src]; float *hit_co = isld_res->hit_point; int best_loop_index_src; + mp_src = &polys_src[pidx_src]; /* If prev and curr poly are the same, no need to do anything more!!! */ if (!ELEM(pidx_src_prev, -1, pidx_src) && isld_steps_src) { int pidx_isld_src, pidx_isld_src_prev; @@ -1575,11 +1623,11 @@ void BKE_mesh_remap_calc_loops_from_dm( if (last_valid_pidx_isld_src != -1) { /* Find a new valid loop in that new poly (nearest point on poly for now). * Note we could be much more subtle here, again that's for later... */ - MLoop *ml_dst = &loops_dst[lidx_dst]; float best_dist_sq = FLT_MAX; float tmp_co[3]; int j; + ml_dst = &loops_dst[lidx_dst]; copy_v3_v3(tmp_co, verts_dst[ml_dst->v].co); /* We do our transform here, since we may do several raycast/nearest queries. */ @@ -1710,6 +1758,9 @@ void BKE_mesh_remap_calc_loops_from_dm( if (loop_to_poly_map_src) { MEM_freeN(loop_to_poly_map_src); } + if (poly_cents_src) { + MEM_freeN(poly_cents_src); + } if (vcos_interp) { MEM_freeN(vcos_interp); } diff --git a/source/blender/blenkernel/intern/modifiers_bmesh.c b/source/blender/blenkernel/intern/modifiers_bmesh.c index 645567eea67..18f3db6bd15 100644 --- a/source/blender/blenkernel/intern/modifiers_bmesh.c +++ b/source/blender/blenkernel/intern/modifiers_bmesh.c @@ -37,8 +37,9 @@ #include "BKE_editmesh.h" /* Static function for alloc */ -static BMFace *bm_face_create_from_mpoly(MPoly *mp, MLoop *ml, - BMesh *bm, BMVert **vtable, BMEdge **etable) +static BMFace *bm_face_create_from_mpoly( + MPoly *mp, MLoop *ml, + BMesh *bm, BMVert **vtable, BMEdge **etable) { BMVert **verts = BLI_array_alloca(verts, mp->totloop); BMEdge **edges = BLI_array_alloca(edges, mp->totloop); diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 4ac96405fbf..e4bf05c2b5b 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -340,13 +340,13 @@ static int multires_get_level(Object *ob, MultiresModifierData *mmd, bool render, bool ignore_simplify) { if (render) - return (mmd->modifier.scene) ? get_render_subsurf_level(&mmd->modifier.scene->r, mmd->renderlvl) : mmd->renderlvl; + return (mmd->modifier.scene) ? get_render_subsurf_level(&mmd->modifier.scene->r, mmd->renderlvl, true) : mmd->renderlvl; else if (ob->mode == OB_MODE_SCULPT) return mmd->sculptlvl; else if (ignore_simplify) return mmd->lvl; else - return (mmd->modifier.scene) ? get_render_subsurf_level(&mmd->modifier.scene->r, mmd->lvl) : mmd->lvl; + return (mmd->modifier.scene) ? get_render_subsurf_level(&mmd->modifier.scene->r, mmd->lvl, false) : mmd->lvl; } void multires_set_tot_level(Object *ob, MultiresModifierData *mmd, int lvl) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 304275d2b1a..99c5e22d51a 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -808,34 +808,11 @@ void BKE_object_unlink(Object *ob) } } } - else if (sl->spacetype == SPACE_OUTLINER) { - SpaceOops *so = (SpaceOops *)sl; - - if (so->treestore) { - TreeStoreElem *tselem; - BLI_mempool_iter iter; - BLI_mempool_iternew(so->treestore, &iter); - while ((tselem = BLI_mempool_iterstep(&iter))) { - if (tselem->id == (ID *)ob) tselem->id = NULL; - } - } - } - else if (sl->spacetype == SPACE_BUTS) { - SpaceButs *sbuts = (SpaceButs *)sl; - - if (sbuts->pinid == (ID *)ob) { - sbuts->flag &= ~SB_PIN_CONTEXT; - sbuts->pinid = NULL; - } - } - else if (sl->spacetype == SPACE_NODE) { - SpaceNode *snode = (SpaceNode *)sl; - - if (snode->from == (ID *)ob) { - snode->flag &= ~SNODE_PIN; - snode->from = NULL; - } +#if 0 + else if (ELEM(sl->spacetype, SPACE_OUTLINER, SPACE_BUTS, SPACE_NODE)) { + /* now handled by WM_main_remove_editor_id_reference */ } +#endif } sa = sa->next; @@ -938,26 +915,6 @@ bool BKE_object_exists_check(Object *obtest) /* *************************************************** */ -void *BKE_object_obdata_add_from_type(Main *bmain, int type) -{ - switch (type) { - case OB_MESH: return BKE_mesh_add(bmain, "Mesh"); - case OB_CURVE: return BKE_curve_add(bmain, "Curve", OB_CURVE); - case OB_SURF: return BKE_curve_add(bmain, "Surf", OB_SURF); - case OB_FONT: return BKE_curve_add(bmain, "Text", OB_FONT); - case OB_MBALL: return BKE_mball_add(bmain, "Meta"); - case OB_CAMERA: return BKE_camera_add(bmain, "Camera"); - case OB_LAMP: return BKE_lamp_add(bmain, "Lamp"); - case OB_LATTICE: return BKE_lattice_add(bmain, "Lattice"); - case OB_ARMATURE: return BKE_armature_add(bmain, "Armature"); - case OB_SPEAKER: return BKE_speaker_add(bmain, "Speaker"); - case OB_EMPTY: return NULL; - default: - printf("BKE_object_obdata_add_from_type: Internal error, bad type: %d\n", type); - return NULL; - } -} - static const char *get_obdata_defname(int type) { switch (type) { @@ -978,6 +935,30 @@ static const char *get_obdata_defname(int type) } } +void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name) +{ + if (name == NULL) { + name = get_obdata_defname(type); + } + + switch (type) { + case OB_MESH: return BKE_mesh_add(bmain, name); + case OB_CURVE: return BKE_curve_add(bmain, name, OB_CURVE); + case OB_SURF: return BKE_curve_add(bmain, name, OB_SURF); + case OB_FONT: return BKE_curve_add(bmain, name, OB_FONT); + case OB_MBALL: return BKE_mball_add(bmain, name); + case OB_CAMERA: return BKE_camera_add(bmain, name); + case OB_LAMP: return BKE_lamp_add(bmain, name); + case OB_LATTICE: return BKE_lattice_add(bmain, name); + case OB_ARMATURE: return BKE_armature_add(bmain, name); + case OB_SPEAKER: return BKE_speaker_add(bmain, name); + case OB_EMPTY: return NULL; + default: + printf("%s: Internal error, bad type: %d\n", __func__, type); + return NULL; + } +} + /* more general add: creates minimum required data, but without vertices etc. */ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name) { @@ -1063,16 +1044,16 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name) /* general add: to scene, with layer from area and default name */ /* creates minimum required data, but without vertices etc. */ -Object *BKE_object_add(Main *bmain, Scene *scene, int type) +Object *BKE_object_add( + Main *bmain, Scene *scene, + int type, const char *name) { Object *ob; Base *base; - char name[MAX_ID_NAME]; - BLI_strncpy(name, get_obdata_defname(type), sizeof(name)); ob = BKE_object_add_only_object(bmain, type, name); - ob->data = BKE_object_obdata_add_from_type(bmain, type); + ob->data = BKE_object_obdata_add_from_type(bmain, type, name); ob->lay = scene->lay; @@ -1770,8 +1751,7 @@ void BKE_object_make_proxy(Object *ob, Object *target, Object *gob) mul_m4_m4m4(ob->obmat, gob->obmat, target->obmat); if (gob->dup_group) { /* should always be true */ float tvec[3]; - copy_v3_v3(tvec, gob->dup_group->dupli_ofs); - mul_mat3_m4_v3(ob->obmat, tvec); + mul_v3_mat3_m4v3(tvec, ob->obmat, gob->dup_group->dupli_ofs); sub_v3_v3(ob->obmat[3], tvec); } BKE_object_apply_mat4(ob, ob->obmat, false, true); diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index b89b5ab4bbc..1a178fb2bdf 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -738,8 +738,8 @@ static void set_height_normalize_factor(struct Ocean *oc) for (i = 0; i < oc->_M; ++i) { for (j = 0; j < oc->_N; ++j) { - if (max_h < fabsf(oc->_disp_y[i * oc->_N + j])) { - max_h = fabsf(oc->_disp_y[i * oc->_N + j]); + if (max_h < fabs(oc->_disp_y[i * oc->_N + j])) { + max_h = fabs(oc->_disp_y[i * oc->_N + j]); } } } diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 61e39d0ad47..68212521617 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -224,7 +224,7 @@ PackedFile *newPackedFile(ReportList *reports, const char *filename, const char } /* no libraries for now */ -void packAll(Main *bmain, ReportList *reports) +void packAll(Main *bmain, ReportList *reports, bool verbose) { Image *ima; VFont *vfont; @@ -237,7 +237,7 @@ void packAll(Main *bmain, ReportList *reports) BKE_image_packfiles(reports, ima, ID_BLEND_PATH(bmain, &ima->id)); tot ++; } - else if (BKE_image_is_animated(ima)) { + else if (BKE_image_is_animated(ima) && verbose) { BKE_reportf(reports, RPT_WARNING, "Image '%s' skipped, movies and image sequences not supported", ima->id.name + 2); } @@ -258,10 +258,10 @@ void packAll(Main *bmain, ReportList *reports) } } - if (tot == 0) - BKE_report(reports, RPT_INFO, "No new files have been packed"); - else + if (tot > 0) BKE_reportf(reports, RPT_INFO, "Packed %d files", tot); + else if (verbose) + BKE_report(reports, RPT_INFO, "No new files have been packed"); } diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index 1429d3b1cdc..4a2540e385b 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -668,6 +668,8 @@ static void exec_distribute_parent(TaskPool *UNUSED(pool), void *taskdata, int U ParticleSystem *psys= task->ctx->sim.psys; ParticleData *pa; int p; + + BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP * task->begin); pa= psys->particles + task->begin; switch (psys->part->from) { diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 5a263e24fc4..4bc46a476a5 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -297,7 +297,7 @@ int psys_get_child_number(Scene *scene, ParticleSystem *psys) else nbr= psys->part->child_nbr; - return get_render_child_particle_number(&scene->r, nbr); + return get_render_child_particle_number(&scene->r, nbr, psys->renderdata != NULL); } int psys_get_tot_child(Scene *scene, ParticleSystem *psys) @@ -559,17 +559,24 @@ static void initialize_all_particles(ParticleSimulationData *sim) ParticleSystem *psys = sim->psys; PARTICLE_P; + LOOP_PARTICLES { + initialize_particle(sim, pa); + } +} + +static void free_unexisting_particles(ParticleSimulationData *sim) +{ + ParticleSystem *psys = sim->psys; + PARTICLE_P; + psys->totunexist = 0; LOOP_PARTICLES { - if ((pa->flag & PARS_UNEXIST)==0) - initialize_particle(sim, pa); - - if (pa->flag & PARS_UNEXIST) + if (pa->flag & PARS_UNEXIST) { psys->totunexist++; + } } - /* Free unexisting particles. */ if (psys->totpart && psys->totunexist == psys->totpart) { if (psys->particles->boid) MEM_freeN(psys->particles->boid); @@ -3790,6 +3797,7 @@ static void system_step(ParticleSimulationData *sim, float cfra) initialize_all_particles(sim); /* reset only just created particles (on startframe all particles are recreated) */ reset_all_particles(sim, 0.0, cfra, oldtotpart); + free_unexisting_particles(sim); if (psys->fluid_springs) { MEM_freeN(psys->fluid_springs); @@ -4136,6 +4144,7 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) { PARTICLE_P; float disp = psys_get_current_display_percentage(psys); + bool free_unexisting = false; /* Particles without dynamics haven't been reset yet because they don't use pointcache */ if (psys->recalc & PSYS_RECALC_RESET) @@ -4145,6 +4154,7 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) free_keyed_keys(psys); distribute_particles(&sim, part->from); initialize_all_particles(&sim); + free_unexisting = true; /* flag for possible explode modifiers after this system */ sim.psmd->flag |= eParticleSystemFlag_Pars; @@ -4163,6 +4173,10 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) pa->flag &= ~PARS_NO_DISP; } + /* free unexisting after reseting particles */ + if (free_unexisting) + free_unexisting_particles(&sim); + if (part->phystype == PART_PHYS_KEYED) { psys_count_keyed_targets(&sim); set_keyed_keys(&sim); diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index fdda72e4f7d..bcbf3b8e77b 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -1612,7 +1612,9 @@ bool BKE_pbvh_node_raycast( return hit; } -void BKE_pbvh_raycast_project_ray_root (PBVH *bvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3]) +void BKE_pbvh_raycast_project_ray_root( + PBVH *bvh, bool original, + float ray_start[3], float ray_end[3], float ray_normal[3]) { if (bvh->nodes) { float rootmin_start, rootmin_end; diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index 5977243a21c..02b8cdba05b 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -667,8 +667,9 @@ static bool check_mask(EdgeQueueContext *eq_ctx, BMVert *v) return (BM_ELEM_CD_GET_FLOAT(v, eq_ctx->cd_vert_mask_offset) < 1.0f); } -static void edge_queue_insert(EdgeQueueContext *eq_ctx, BMEdge *e, - float priority) +static void edge_queue_insert( + EdgeQueueContext *eq_ctx, BMEdge *e, + float priority) { BMVert **pair; @@ -694,8 +695,9 @@ static void edge_queue_insert(EdgeQueueContext *eq_ctx, BMEdge *e, } } -static void long_edge_queue_edge_add(EdgeQueueContext *eq_ctx, - BMEdge *e) +static void long_edge_queue_edge_add( + EdgeQueueContext *eq_ctx, + BMEdge *e) { #ifdef USE_EDGEQUEUE_TAG if (EDGE_QUEUE_TEST(e) == false) @@ -765,8 +767,9 @@ static void long_edge_queue_edge_add_recursive( } #endif /* USE_EDGEQUEUE_EVEN_SUBDIV */ -static void short_edge_queue_edge_add(EdgeQueueContext *eq_ctx, - BMEdge *e) +static void short_edge_queue_edge_add( + EdgeQueueContext *eq_ctx, + BMEdge *e) { #ifdef USE_EDGEQUEUE_TAG if (EDGE_QUEUE_TEST(e) == false) @@ -779,8 +782,9 @@ static void short_edge_queue_edge_add(EdgeQueueContext *eq_ctx, } } -static void long_edge_queue_face_add(EdgeQueueContext *eq_ctx, - BMFace *f) +static void long_edge_queue_face_add( + EdgeQueueContext *eq_ctx, + BMFace *f) { if (edge_queue_tri_in_sphere(eq_ctx->q, f)) { BMLoop *l_iter; @@ -795,7 +799,7 @@ static void long_edge_queue_face_add(EdgeQueueContext *eq_ctx, if (len_sq > eq_ctx->q->limit_len_squared) { long_edge_queue_edge_add_recursive( eq_ctx, l_iter->radial_next, l_iter, - len_sq, eq_ctx->q->limit_len_squared); + len_sq, eq_ctx->q->limit_len); } #else long_edge_queue_edge_add(eq_ctx, l_iter->e); @@ -805,8 +809,9 @@ static void long_edge_queue_face_add(EdgeQueueContext *eq_ctx, } } -static void short_edge_queue_face_add(EdgeQueueContext *eq_ctx, - BMFace *f) +static void short_edge_queue_face_add( + EdgeQueueContext *eq_ctx, + BMFace *f) { if (edge_queue_tri_in_sphere(eq_ctx->q, f)) { BMLoop *l_iter; @@ -829,9 +834,10 @@ static void short_edge_queue_face_add(EdgeQueueContext *eq_ctx, * * The highest priority (lowest number) is given to the longest edge. */ -static void long_edge_queue_create(EdgeQueueContext *eq_ctx, - PBVH *bvh, const float center[3], - float radius) +static void long_edge_queue_create( + EdgeQueueContext *eq_ctx, + PBVH *bvh, const float center[3], + float radius) { int n; @@ -877,9 +883,10 @@ static void long_edge_queue_create(EdgeQueueContext *eq_ctx, * * The highest priority (lowest number) is given to the shortest edge. */ -static void short_edge_queue_create(EdgeQueueContext *eq_ctx, - PBVH *bvh, const float center[3], - float radius) +static void short_edge_queue_create( + EdgeQueueContext *eq_ctx, + PBVH *bvh, const float center[3], + float radius) { int n; @@ -920,8 +927,9 @@ static void bm_edges_from_tri(BMesh *bm, BMVert *v_tri[3], BMEdge *e_tri[3]) e_tri[2] = BM_edge_create(bm, v_tri[2], v_tri[0], NULL, BM_CREATE_NO_DOUBLE); } -static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, PBVH *bvh, - BMEdge *e, BLI_Buffer *edge_loops) +static void pbvh_bmesh_split_edge( + EdgeQueueContext *eq_ctx, PBVH *bvh, + BMEdge *e, BLI_Buffer *edge_loops) { BMVert *v_new; float co_mid[3], no_mid[3]; @@ -1037,16 +1045,12 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, PBVH *bvh, BM_edge_kill(bvh->bm, e); } -static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx, PBVH *bvh, - BLI_Buffer *edge_loops) +static bool pbvh_bmesh_subdivide_long_edges( + EdgeQueueContext *eq_ctx, PBVH *bvh, + BLI_Buffer *edge_loops) { bool any_subdivided = false; -#ifdef USE_EDGEQUEUE_TAG_VERIFY - pbvh_bmesh_edge_tag_verify(bvh); -#endif - - while (!BLI_heap_is_empty(eq_ctx->q->heap)) { BMVert **pair = BLI_heap_popmin(eq_ctx->q->heap); BMVert *v1 = pair[0], *v2 = pair[1]; @@ -1295,9 +1299,10 @@ static bool pbvh_bmesh_collapse_short_edges( /************************* Called from pbvh.c *************************/ -bool pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3], - const float ray_normal[3], float *dist, - bool use_original) +bool pbvh_bmesh_node_raycast( + PBVHNode *node, const float ray_start[3], + const float ray_normal[3], float *dist, + bool use_original) { bool hit = false; @@ -1433,8 +1438,9 @@ static void pbvh_bmesh_node_layers_reset(PBVH *bvh) /* Build a PBVH from a BMesh */ -void BKE_pbvh_build_bmesh(PBVH *bvh, BMesh *bm, bool smooth_shading, BMLog *log, - const int cd_vert_node_offset, const int cd_face_node_offset) +void BKE_pbvh_build_bmesh( + PBVH *bvh, BMesh *bm, bool smooth_shading, BMLog *log, + const int cd_vert_node_offset, const int cd_face_node_offset) { BMIter iter; BMFace *f; @@ -1474,8 +1480,9 @@ void BKE_pbvh_build_bmesh(PBVH *bvh, BMesh *bm, bool smooth_shading, BMLog *log, } /* Collapse short edges, subdivide long edges */ -bool BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode, - const float center[3], float radius) +bool BKE_pbvh_bmesh_update_topology( + PBVH *bvh, PBVHTopologyUpdateMode mode, + const float center[3], float radius) { /* 2 is enough for edge faces - manifold edge */ BLI_buffer_declare_static(BMLoop *, edge_loops, BLI_BUFFER_NOP, 2); diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h index 6b3ef8eb5da..a2b08a1f6d3 100644 --- a/source/blender/blenkernel/intern/pbvh_intern.h +++ b/source/blender/blenkernel/intern/pbvh_intern.h @@ -175,9 +175,10 @@ void BB_expand_with_bb(BB *bb, BB *bb2); void BBC_update_centroid(BBC *bbc); int BB_widest_axis(const BB *bb); void pbvh_grow_nodes(PBVH *bvh, int totnode); -bool ray_face_intersection(const float ray_start[3], const float ray_normal[3], - const float *t0, const float *t1, const float *t2, - const float *t3, float *fdist); +bool ray_face_intersection( + const float ray_start[3], const float ray_normal[3], + const float *t0, const float *t1, const float *t2, + const float *t3, float *fdist); void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag); /* pbvh_bmesh.c */ diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 07e2a186444..575a42ed690 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -75,6 +75,7 @@ #include "BKE_idprop.h" #include "BKE_image.h" #include "BKE_library.h" +#include "BKE_linestyle.h" #include "BKE_main.h" #include "BKE_mask.h" #include "BKE_node.h" @@ -82,6 +83,7 @@ #include "BKE_paint.h" #include "BKE_rigidbody.h" #include "BKE_scene.h" +#include "BKE_screen.h" #include "BKE_sequencer.h" #include "BKE_sound.h" #include "BKE_unit.h" @@ -154,6 +156,7 @@ Scene *BKE_scene_copy(Scene *sce, int type) { Scene *scen; SceneRenderLayer *srl, *new_srl; + FreestyleLineSet *lineset; ToolSettings *ts; Base *base, *obase; @@ -237,6 +240,14 @@ Scene *BKE_scene_copy(Scene *sce, int type) new_srl = scen->r.layers.first; for (srl = sce->r.layers.first; srl; srl = srl->next) { BKE_freestyle_config_copy(&new_srl->freestyleConfig, &srl->freestyleConfig); + if (type == SCE_COPY_FULL) { + for (lineset = new_srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) { + if (lineset->linestyle) { + id_us_plus((ID *)lineset->linestyle); + lineset->linestyle = BKE_linestyle_copy(G.main, lineset->linestyle); + } + } + } new_srl = new_srl->next; } } @@ -680,7 +691,7 @@ Scene *BKE_scene_add(Main *bmain, const char *name) sce->gm.recastData.cellsize = 0.3f; sce->gm.recastData.cellheight = 0.2f; - sce->gm.recastData.agentmaxslope = M_PI / 2; + sce->gm.recastData.agentmaxslope = M_PI_4; sce->gm.recastData.agentmaxclimb = 0.9f; sce->gm.recastData.agentheight = 2.0f; sce->gm.recastData.agentradius = 0.6f; @@ -798,33 +809,6 @@ Scene *BKE_scene_set_name(Main *bmain, const char *name) return NULL; } -static void scene_unlink_space_node(SpaceNode *snode, Scene *sce) -{ - if (snode->id == &sce->id) { - /* nasty DNA logic for SpaceNode: - * ideally should be handled by editor code, but would be bad level call - */ - bNodeTreePath *path, *path_next; - for (path = snode->treepath.first; path; path = path_next) { - path_next = path->next; - MEM_freeN(path); - } - BLI_listbase_clear(&snode->treepath); - - snode->id = NULL; - snode->from = NULL; - snode->nodetree = NULL; - snode->edittree = NULL; - } -} - -static void scene_unlink_space_buts(SpaceButs *sbuts, Scene *sce) -{ - if (sbuts->pinid == &sce->id) { - sbuts->pinid = NULL; - } -} - void BKE_scene_unlink(Main *bmain, Scene *sce, Scene *newsce) { Scene *sce1; @@ -849,24 +833,11 @@ void BKE_scene_unlink(Main *bmain, Scene *sce, Scene *newsce) /* all screens */ for (screen = bmain->screen.first; screen; screen = screen->id.next) { - ScrArea *area; - - if (screen->scene == sce) + if (screen->scene == sce) { screen->scene = newsce; - - for (area = screen->areabase.first; area; area = area->next) { - SpaceLink *space_link; - for (space_link = area->spacedata.first; space_link; space_link = space_link->next) { - switch (space_link->spacetype) { - case SPACE_NODE: - scene_unlink_space_node((SpaceNode *)space_link, sce); - break; - case SPACE_BUTS: - scene_unlink_space_buts((SpaceButs *)space_link, sce); - break; - } - } } + + /* editors are handled by WM_main_remove_editor_id_reference */ } BKE_libblock_free(bmain, sce); @@ -1968,20 +1939,30 @@ bool BKE_scene_remove_render_view(Scene *scene, SceneRenderView *srv) /* render simplification */ -int get_render_subsurf_level(const RenderData *r, int lvl) +int get_render_subsurf_level(const RenderData *r, int lvl, bool for_render) { - if (r->mode & R_SIMPLIFY) - return min_ii(r->simplify_subsurf, lvl); - else + if (r->mode & R_SIMPLIFY) { + if (for_render) + return min_ii(r->simplify_subsurf_render, lvl); + else + return min_ii(r->simplify_subsurf, lvl); + } + else { return lvl; + } } -int get_render_child_particle_number(const RenderData *r, int num) +int get_render_child_particle_number(const RenderData *r, int num, bool for_render) { - if (r->mode & R_SIMPLIFY) - return (int)(r->simplify_particles * num); - else + if (r->mode & R_SIMPLIFY) { + if (for_render) + return (int)(r->simplify_particles_render * num); + else + return (int)(r->simplify_particles * num); + } + else { return num; + } } int get_render_shadow_samples(const RenderData *r, int samples) diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 3c43bfa2920..840e1f99f84 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -272,6 +272,19 @@ void BKE_spacedata_draw_locks(int set) } } +static void (*spacedata_id_unref_cb)(struct SpaceLink *sl, const struct ID *id) = NULL; + +void BKE_spacedata_callback_id_unref_set(void (*func)(struct SpaceLink *sl, const struct ID *)) +{ + spacedata_id_unref_cb = func; +} + +void BKE_spacedata_id_unref(struct SpaceLink *sl, const struct ID *id) +{ + if (spacedata_id_unref_cb) { + spacedata_id_unref_cb(sl, id); + } +} /* not region itself */ void BKE_area_region_free(SpaceType *st, ARegion *ar) @@ -405,6 +418,23 @@ ARegion *BKE_area_find_region_active_win(ScrArea *sa) return NULL; } +ARegion *BKE_area_find_region_xy(ScrArea *sa, const int regiontype, int x, int y) +{ + ARegion *ar_found = NULL; + if (sa) { + ARegion *ar; + for (ar = sa->regionbase.first; ar; ar = ar->next) { + if ((regiontype == RGN_TYPE_ANY) || (ar->regiontype == regiontype)) { + if (BLI_rcti_isect_pt(&ar->winrct, x, y)) { + ar_found = ar; + break; + } + } + } + } + return ar_found; +} + /** * \note, ideally we can get the area from the context, * there are a few places however where this isn't practical. diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 535dcd6ba4d..bb48023de56 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -2423,6 +2423,7 @@ static ImBuf *input_preprocess(const SeqRenderData *context, Sequence *seq, floa IMB_rectcpy(i, ibuf, t.xofs, t.yofs, c.left, c.bottom, sx, sy); sequencer_imbuf_assign_spaces(scene, i); + IMB_metadata_copy(i, ibuf); IMB_freeImBuf(ibuf); ibuf = i; @@ -2474,6 +2475,7 @@ static ImBuf *input_preprocess(const SeqRenderData *context, Sequence *seq, floa ImBuf *ibuf_new = BKE_sequence_modifier_apply_stack(context, seq, ibuf, cfra); if (ibuf_new != ibuf) { + IMB_metadata_copy(ibuf_new, ibuf); IMB_freeImBuf(ibuf); ibuf = ibuf_new; } @@ -2496,6 +2498,7 @@ static ImBuf *copy_from_ibuf_still(const SeqRenderData *context, Sequence *seq, if (ibuf) { rval = IMB_dupImBuf(ibuf); + IMB_metadata_copy(rval, ibuf); IMB_freeImBuf(ibuf); } @@ -2509,9 +2512,11 @@ static void copy_to_ibuf_still(const SeqRenderData *context, Sequence *seq, floa /* we have to store a copy, since the passed ibuf * could be preprocessed afterwards (thereby silently * changing the cached image... */ - ibuf = IMB_dupImBuf(ibuf); + ImBuf *oibuf = ibuf; + ibuf = IMB_dupImBuf(oibuf); if (ibuf) { + IMB_metadata_copy(ibuf, oibuf); sequencer_imbuf_assign_spaces(context->scene, ibuf); } @@ -2721,7 +2726,7 @@ static ImBuf *seq_render_image_strip(const SeqRenderData *context, Sequence *seq BLI_path_abs(name, G.main->name); } - flag = IB_rect; + flag = IB_rect | IB_metadata; if (seq->alpha_mode == SEQ_ALPHA_PREMUL) flag |= IB_alphamode_premul; @@ -3583,6 +3588,8 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context, ListBase *seq out = seq_render_strip_stack_apply_effect(context, seq, cfra, ibuf1, ibuf2); + IMB_metadata_copy(out, ibuf2); + IMB_freeImBuf(ibuf1); IMB_freeImBuf(ibuf2); } @@ -4640,7 +4647,7 @@ static size_t sequencer_rna_path_prefix(char str[SEQ_RNAPATH_MAXSTR], const char char name_esc[SEQ_NAME_MAXSTR * 2]; BLI_strescape(name_esc, name, sizeof(name_esc)); - return BLI_snprintf(str, SEQ_RNAPATH_MAXSTR, "sequence_editor.sequences_all[\"%s\"]", name_esc); + return BLI_snprintf_rlen(str, SEQ_RNAPATH_MAXSTR, "sequence_editor.sequences_all[\"%s\"]", name_esc); } /* XXX - hackish function needed for transforming strips! TODO - have some better solution */ @@ -4974,7 +4981,7 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad sound = BKE_sound_new_file(bmain, seq_load->path); /* handles relative paths */ - if (sound == NULL || sound->playback_handle == NULL) { + if (sound->playback_handle == NULL) { #if 0 if (op) BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 6a831d23aea..30c17773f7d 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -66,7 +66,7 @@ static int sound_cfra; bSound *BKE_sound_new_file(struct Main *bmain, const char *filename) { - bSound *sound = NULL; + bSound *sound; char str[FILE_MAX]; const char *path; @@ -89,11 +89,6 @@ bSound *BKE_sound_new_file(struct Main *bmain, const char *filename) BKE_sound_load(bmain, sound); - if (!sound->playback_handle) { - BKE_libblock_free(bmain, sound); - sound = NULL; - } - return sound; } @@ -246,12 +241,6 @@ bSound *BKE_sound_new_buffer(struct Main *bmain, bSound *source) sound_load(bmain, sound); - if (!sound->playback_handle) - { - BKE_libblock_free(bmain, sound); - sound = NULL; - } - return sound; } @@ -272,12 +261,6 @@ bSound *BKE_sound_new_limiter(struct Main *bmain, bSound *source, float start, f sound_load(bmain, sound); - if (!sound->playback_handle) - { - BKE_libblock_free(bmain, sound); - sound = NULL; - } - return sound; } #endif diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index a4e0eaaa324..2b05a6c8fc5 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -300,7 +300,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, float uv[3] = {0.0f, 0.0f, 0.0f}; /* only first 2 values are written into */ limit[0] = limit[1] = STD_UV_CONNECT_LIMIT; - vmap = BKE_mesh_uv_vert_map_create(mpoly, mloop, mloopuv, totface, totvert, 0, limit); + vmap = BKE_mesh_uv_vert_map_create(mpoly, mloop, mloopuv, totface, totvert, 0, limit, false); if (!vmap) return 0; @@ -3828,7 +3828,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( /* note: editmode calculation can only run once per * modifier stack evaluation (uses freed cache) [#36299] */ if (flags & SUBSURF_FOR_EDIT_MODE) { - int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels) : smd->levels; + int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels, false) : smd->levels; smd->emCache = _getSubSurf(smd->emCache, levels, 3, useSimple | useAging | CCG_CALC_NORMALS); ss_sync_from_derivedmesh(smd->emCache, dm, vertCos, useSimple); @@ -3840,7 +3840,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( else if (flags & SUBSURF_USE_RENDER_PARAMS) { /* Do not use cache in render mode. */ CCGSubSurf *ss; - int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->renderLevels) : smd->renderLevels; + int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->renderLevels, true) : smd->renderLevels; if (levels == 0) return dm; @@ -3856,7 +3856,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( } else { int useIncremental = (smd->flags & eSubsurfModifierFlag_Incremental); - int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels) : smd->levels; + int levels = (smd->modifier.scene) ? get_render_subsurf_level(&smd->modifier.scene->r, smd->levels, false) : smd->levels; CCGSubSurf *ss; /* It is quite possible there is a much better place to do this. It diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 9f441b45db9..1966d5af7d1 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -473,6 +473,7 @@ Text *BKE_text_copy(Main *bmain, Text *ta) BLI_listbase_clear(&tan->lines); tan->curl = tan->sell = NULL; + tan->compiled = NULL; tan->nlines = ta->nlines; @@ -651,7 +652,7 @@ void BKE_text_unlink(Main *bmain, Text *text) } } - /* Freestyle (while looping oer the scene) */ + /* Freestyle (while looping over the scene) */ for (srl = sce->r.layers.first; srl; srl = srl->next) { for (module = srl->freestyleConfig.modules.first; module; module = module->next) { if (module->script == text) diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 83db0639468..e3f04296f50 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1302,6 +1302,95 @@ void BKE_tracking_plane_tracks_deselect_all(ListBase *plane_tracks_base) } } +bool BKE_tracking_plane_track_has_point_track(MovieTrackingPlaneTrack *plane_track, + MovieTrackingTrack *track) +{ + int i; + for (i = 0; i < plane_track->point_tracksnr; i++) { + if (plane_track->point_tracks[i] == track) { + return true; + } + } + return false; +} + +bool BKE_tracking_plane_track_remove_point_track(MovieTrackingPlaneTrack *plane_track, + MovieTrackingTrack *track) +{ + int i, track_index; + MovieTrackingTrack **new_point_tracks; + + if (plane_track->point_tracksnr <= 4) { + return false; + } + + new_point_tracks = MEM_mallocN(sizeof(*new_point_tracks) * (plane_track->point_tracksnr - 1), + "new point tracks array"); + + for (i = 0, track_index = 0; i < plane_track->point_tracksnr; i++) { + if (plane_track->point_tracks[i] != track) { + new_point_tracks[track_index++] = plane_track->point_tracks[i]; + } + } + + MEM_freeN(plane_track->point_tracks); + plane_track->point_tracks = new_point_tracks; + plane_track->point_tracksnr--; + + return true; +} + +void BKE_tracking_plane_tracks_remove_point_track(MovieTracking *tracking, + MovieTrackingTrack *track) +{ + MovieTrackingPlaneTrack *plane_track, *next_plane_track; + ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking); + for (plane_track = plane_tracks_base->first; + plane_track; + plane_track = next_plane_track) + { + next_plane_track = plane_track->next; + if (BKE_tracking_plane_track_has_point_track(plane_track, track)) { + if (!BKE_tracking_plane_track_remove_point_track(plane_track, track)) { + /* Delete planes with less than 3 point tracks in it. */ + BKE_tracking_plane_track_free(plane_track); + BLI_freelinkN(plane_tracks_base, plane_track); + } + } + } +} + +void BKE_tracking_plane_track_replace_point_track(MovieTrackingPlaneTrack *plane_track, + MovieTrackingTrack *old_track, + MovieTrackingTrack *new_track) +{ + int i; + for (i = 0; i < plane_track->point_tracksnr; i++) { + if (plane_track->point_tracks[i] == old_track) { + plane_track->point_tracks[i] = new_track; + break; + } + } +} + +void BKE_tracking_plane_tracks_replace_point_track(MovieTracking *tracking, + MovieTrackingTrack *old_track, + MovieTrackingTrack *new_track) +{ + MovieTrackingPlaneTrack *plane_track; + ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking); + for (plane_track = plane_tracks_base->first; + plane_track; + plane_track = plane_track->next) + { + if (BKE_tracking_plane_track_has_point_track(plane_track, old_track)) { + BKE_tracking_plane_track_replace_point_track(plane_track, + old_track, + new_track); + } + } +} + /*********************** Plane Marker *************************/ MovieTrackingPlaneMarker *BKE_tracking_plane_marker_insert(MovieTrackingPlaneTrack *plane_track, diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c index 4cb3f2ca493..76261bddfbc 100644 --- a/source/blender/blenkernel/intern/tracking_auto.c +++ b/source/blender/blenkernel/intern/tracking_auto.c @@ -534,19 +534,9 @@ void BKE_autotrack_context_finish(AutoTrackContext *context) if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) { int track; for (track = 0; track < context->num_tracks; ++track) { - MovieTrackingTrack *old_track; - bool do_update = false; - int j; - - old_track = context->options[track].track; - for (j = 0; j < plane_track->point_tracksnr; j++) { - if (plane_track->point_tracks[j] == old_track) { - do_update = true; - break; - } - } - - if (do_update) { + if (BKE_tracking_plane_track_has_point_track(plane_track, + context->options[track].track)) + { BKE_tracking_track_plane_from_existing_motion( plane_track, context->first_frame); diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c index 5a2c77b5619..0d83695d2f1 100644 --- a/source/blender/blenkernel/intern/unit.c +++ b/source/blender/blenkernel/intern/unit.c @@ -370,12 +370,7 @@ static size_t unit_as_string(char *str, int len_max, double value, int prec, bUn value_conv = value / unit->scalar; /* Convert to a string */ - { - len = BLI_snprintf(str, len_max, "%.*f", prec, value_conv); - - if (len >= len_max) - len = len_max; - } + len = BLI_snprintf_rlen(str, len_max, "%.*f", prec, value_conv); /* Add unit prefix and strip zeros */ diff --git a/source/blender/blenlib/BLI_array_utils.h b/source/blender/blenlib/BLI_array_utils.h index 0dd1439e58c..ff7976dc701 100644 --- a/source/blender/blenlib/BLI_array_utils.h +++ b/source/blender/blenlib/BLI_array_utils.h @@ -34,6 +34,14 @@ void _bli_array_wrap(void *arr, unsigned int arr_len, size_t arr_stride, int dir #define BLI_array_wrap(arr, arr_len, dir) \ _bli_array_wrap(arr, arr_len, sizeof(*(arr)), dir) +void _bli_array_permute( + void *arr, const unsigned int arr_len, const size_t arr_stride, + const unsigned int *index, void *arr_temp); +#define BLI_array_permute(arr, arr_len, order) \ + _bli_array_permute(arr, arr_len, sizeof(*(arr)), order, NULL) +#define BLI_array_permute_ex(arr, arr_len, index, arr_temp) \ + _bli_array_permute(arr, arr_len, sizeof(*(arr)), order, arr_temp) + int _bli_array_findindex(const void *arr, unsigned int arr_len, size_t arr_stride, const void *p); #define BLI_array_findindex(arr, arr_len, p) \ _bli_array_findindex(arr, arr_len, sizeof(*(arr)), p) diff --git a/source/blender/blenlib/BLI_compiler_typecheck.h b/source/blender/blenlib/BLI_compiler_typecheck.h index 652c4a954b9..b9fb3ebf47a 100644 --- a/source/blender/blenlib/BLI_compiler_typecheck.h +++ b/source/blender/blenlib/BLI_compiler_typecheck.h @@ -381,4 +381,303 @@ # define CHECK_TYPE_ANY(...) (void)0 #endif + +/** + * GENERIC_TYPE_ANY: handy macro to reuse a single expression for multiple types, eg: + * + * \code{.c} + * _Generic(value, + * GENERIC_TYPE_ANY(result_a, Foo *, Bar *, Baz *), + * GENERIC_TYPE_ANY(result_b, Spam *, Spaz *, Spot *), + * ) + * \endcode + * + * excuse ridiculously long generated args. + * \code{.py} + * for i in range(63): + * args = [(chr(ord('a') + (c % 26)) + (chr(ord('0') + (c // 26)))) for c in range(i + 1)] + * print("#define _VA_GENERIC_TYPE_ANY%d(r, %s) \\" % (i + 2, ", ".join(args))) + * print(" %s: r " % (": r, ".join(args))) + * \endcode + */ +#define _VA_GENERIC_TYPE_ANY2(r, a0) \ + a0: r +#define _VA_GENERIC_TYPE_ANY3(r, a0, b0) \ + a0: r, b0: r +#define _VA_GENERIC_TYPE_ANY4(r, a0, b0, c0) \ + a0: r, b0: r, c0: r +#define _VA_GENERIC_TYPE_ANY5(r, a0, b0, c0, d0) \ + a0: r, b0: r, c0: r, d0: r +#define _VA_GENERIC_TYPE_ANY6(r, a0, b0, c0, d0, e0) \ + a0: r, b0: r, c0: r, d0: r, e0: r +#define _VA_GENERIC_TYPE_ANY7(r, a0, b0, c0, d0, e0, f0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r +#define _VA_GENERIC_TYPE_ANY8(r, a0, b0, c0, d0, e0, f0, g0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r +#define _VA_GENERIC_TYPE_ANY9(r, a0, b0, c0, d0, e0, f0, g0, h0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r +#define _VA_GENERIC_TYPE_ANY10(r, a0, b0, c0, d0, e0, f0, g0, h0, i0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r +#define _VA_GENERIC_TYPE_ANY11(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r +#define _VA_GENERIC_TYPE_ANY12(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r +#define _VA_GENERIC_TYPE_ANY13(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r +#define _VA_GENERIC_TYPE_ANY14(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r +#define _VA_GENERIC_TYPE_ANY15(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r +#define _VA_GENERIC_TYPE_ANY16(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r +#define _VA_GENERIC_TYPE_ANY17(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r +#define _VA_GENERIC_TYPE_ANY18(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r +#define _VA_GENERIC_TYPE_ANY19(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r +#define _VA_GENERIC_TYPE_ANY20(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r +#define _VA_GENERIC_TYPE_ANY21(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r +#define _VA_GENERIC_TYPE_ANY22(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r +#define _VA_GENERIC_TYPE_ANY23(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r +#define _VA_GENERIC_TYPE_ANY24(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r +#define _VA_GENERIC_TYPE_ANY25(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r +#define _VA_GENERIC_TYPE_ANY26(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r +#define _VA_GENERIC_TYPE_ANY27(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r +#define _VA_GENERIC_TYPE_ANY28(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r +#define _VA_GENERIC_TYPE_ANY29(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r +#define _VA_GENERIC_TYPE_ANY30(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r +#define _VA_GENERIC_TYPE_ANY31(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r +#define _VA_GENERIC_TYPE_ANY32(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r +#define _VA_GENERIC_TYPE_ANY33(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r +#define _VA_GENERIC_TYPE_ANY34(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r +#define _VA_GENERIC_TYPE_ANY35(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r +#define _VA_GENERIC_TYPE_ANY36(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r +#define _VA_GENERIC_TYPE_ANY37(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r +#define _VA_GENERIC_TYPE_ANY38(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r +#define _VA_GENERIC_TYPE_ANY39(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r +#define _VA_GENERIC_TYPE_ANY40(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r +#define _VA_GENERIC_TYPE_ANY41(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r +#define _VA_GENERIC_TYPE_ANY42(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r +#define _VA_GENERIC_TYPE_ANY43(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r +#define _VA_GENERIC_TYPE_ANY44(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r +#define _VA_GENERIC_TYPE_ANY45(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r +#define _VA_GENERIC_TYPE_ANY46(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r +#define _VA_GENERIC_TYPE_ANY47(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r +#define _VA_GENERIC_TYPE_ANY48(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r +#define _VA_GENERIC_TYPE_ANY49(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r +#define _VA_GENERIC_TYPE_ANY50(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r +#define _VA_GENERIC_TYPE_ANY51(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r +#define _VA_GENERIC_TYPE_ANY52(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r +#define _VA_GENERIC_TYPE_ANY53(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1, z1) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r, z1: r +#define _VA_GENERIC_TYPE_ANY54(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1, z1, a2) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r, z1: r, a2: r +#define _VA_GENERIC_TYPE_ANY55(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1, z1, a2, b2) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r, z1: r, a2: r, b2: r +#define _VA_GENERIC_TYPE_ANY56(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1, z1, a2, b2, c2) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r +#define _VA_GENERIC_TYPE_ANY57(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1, z1, a2, b2, c2, d2) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r +#define _VA_GENERIC_TYPE_ANY58(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1, z1, a2, b2, c2, d2, e2) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r +#define _VA_GENERIC_TYPE_ANY59(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1, z1, a2, b2, c2, d2, e2, f2) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r, f2: r +#define _VA_GENERIC_TYPE_ANY60(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1, z1, a2, b2, c2, d2, e2, f2, g2) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r, f2: r, g2: r +#define _VA_GENERIC_TYPE_ANY61(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1, z1, a2, b2, c2, d2, e2, f2, g2, h2) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r, f2: r, g2: r, h2: r +#define _VA_GENERIC_TYPE_ANY62(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1, z1, a2, b2, c2, d2, e2, f2, g2, h2, i2) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r, f2: r, g2: r, h2: r, i2: r +#define _VA_GENERIC_TYPE_ANY63(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1, z1, a2, b2, c2, d2, e2, f2, g2, h2, i2, j2) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r, f2: r, g2: r, h2: r, i2: r, j2: r +#define _VA_GENERIC_TYPE_ANY64(r, a0, b0, c0, d0, e0, f0, g0, h0, i0, j0, k0, l0, m0, n0, o0, p0, q0, r0, s0, t0, \ + u0, v0, w0, x0, y0, z0, a1, b1, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, n1, o1, p1, q1, r1, s1, t1, u1, v1, \ + w1, x1, y1, z1, a2, b2, c2, d2, e2, f2, g2, h2, i2, j2, k2) \ + a0: r, b0: r, c0: r, d0: r, e0: r, f0: r, g0: r, h0: r, i0: r, j0: r, k0: r, l0: r, m0: r, n0: r, o0: r, p0: r, \ + q0: r, r0: r, s0: r, t0: r, u0: r, v0: r, w0: r, x0: r, y0: r, z0: r, a1: r, b1: r, c1: r, d1: r, e1: r, f1: r, \ + g1: r, h1: r, i1: r, j1: r, k1: r, l1: r, m1: r, n1: r, o1: r, p1: r, q1: r, r1: r, s1: r, t1: r, u1: r, v1: r, \ + w1: r, x1: r, y1: r, z1: r, a2: r, b2: r, c2: r, d2: r, e2: r, f2: r, g2: r, h2: r, i2: r, j2: r, k2: r + +# define GENERIC_TYPE_ANY(...) VA_NARGS_CALL_OVERLOAD(_VA_GENERIC_TYPE_ANY, __VA_ARGS__) + #endif /* __BLI_COMPILER_TYPECHECK_H__ */ diff --git a/source/blender/blenlib/BLI_linklist_stack.h b/source/blender/blenlib/BLI_linklist_stack.h index 9ac233a8fa4..a4b8f77bfa6 100644 --- a/source/blender/blenlib/BLI_linklist_stack.h +++ b/source/blender/blenlib/BLI_linklist_stack.h @@ -168,6 +168,16 @@ #define BLI_SMALLSTACK_IS_EMPTY(var) \ ((_BLI_SMALLSTACK_CAST(var) _##var##_stack) == NULL) +/* fill in a lookup table */ +#define BLI_SMALLSTACK_AS_TABLE(var, data) \ +{ \ + LinkNode *_##var##_iter; \ + unsigned int i; \ + for (_##var##_iter = _##var##_stack, i = 0; _##var##_iter; _##var##_iter = _##var##_iter->next, i++) { \ + (data)[i] = _BLI_SMALLSTACK_CAST(var) (_##var##_iter->link); \ + } \ +} ((void)0) + /* loop over stack members last-added-first */ #define BLI_SMALLSTACK_ITER_BEGIN(var, item) \ { \ diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h index daa7db8e3cf..79a2d57c966 100644 --- a/source/blender/blenlib/BLI_math_base.h +++ b/source/blender/blenlib/BLI_math_base.h @@ -214,9 +214,7 @@ MINLINE int iroundf(float a); MINLINE int divide_round_i(int a, int b); MINLINE int mod_i(int i, int n); -MINLINE unsigned int highest_order_bit_i(unsigned int n); -MINLINE unsigned short highest_order_bit_s(unsigned short n); - +int pow_i(int base, int exp); double double_round(double x, int ndigits); #ifdef BLI_MATH_GCC_WARN_PRAGMA diff --git a/source/blender/blenlib/BLI_math_bits.h b/source/blender/blenlib/BLI_math_bits.h new file mode 100644 index 00000000000..876c0d92e31 --- /dev/null +++ b/source/blender/blenlib/BLI_math_bits.h @@ -0,0 +1,51 @@ +/* + * ***** 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 ***** + * */ + +#ifndef __BLI_MATH_BITS_H__ +#define __BLI_MATH_BITS_H__ + +/** \file BLI_math_bits.h + * \ingroup bli + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "BLI_math_inline.h" + +MINLINE unsigned int highest_order_bit_i(unsigned int n); +MINLINE unsigned short highest_order_bit_s(unsigned short n); + +#ifdef __GNUC__ +# define count_bits_i(i) __builtin_popcount(i) +#else +MINLINE int count_bits_i(unsigned int n); +#endif + +#if BLI_MATH_DO_INLINE +#include "intern/math_bits_inline.c" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __BLI_MATH_BITS_H__ */ diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h index 45972d03175..f7eeb1ec7a1 100644 --- a/source/blender/blenlib/BLI_math_matrix.h +++ b/source/blender/blenlib/BLI_math_matrix.h @@ -106,6 +106,7 @@ void mul_v2_m4v3(float r[2], float M[4][4], const float v[3]); void mul_v2_m2v2(float r[2], float M[2][2], const float v[2]); void mul_m2v2(float M[2][2], float v[2]); void mul_mat3_m4_v3(float M[4][4], float r[3]); +void mul_v3_mat3_m4v3(float r[3], float M[4][4], const float v[3]); void mul_m4_v4(float M[4][4], float r[4]); void mul_v4_m4v4(float r[4], float M[4][4], const float v[4]); void mul_project_m4_v3(float M[4][4], float vec[3]); diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 9c8a9f54379..82a2b9c9ab2 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -314,6 +314,7 @@ double len_squared_vn(const float *array, const int size) ATTR_WARN_UNUSED_RESUL float normalize_vn_vn(float *array_tar, const float *array_src, const int size); float normalize_vn(float *array_tar, const int size); void range_vn_i(int *array_tar, const int size, const int start); +void range_vn_u(unsigned int *array_tar, const int size, const unsigned int start); void range_vn_fl(float *array_tar, const int size, const float start, const float step); void negate_vn(float *array_tar, const int size); void negate_vn_vn(float *array_tar, const float *array_src, const int size); diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h index c4853e37398..e6c1cc8b4b6 100644 --- a/source/blender/blenlib/BLI_string.h +++ b/source/blender/blenlib/BLI_string.h @@ -59,8 +59,10 @@ char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict char *BLI_replacestrN(const char *__restrict str, const char *__restrict substr_old, const char *__restrict substr_new) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC; size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...) ATTR_NONNULL(1, 3) ATTR_PRINTF_FORMAT(3, 4); +size_t BLI_snprintf_rlen(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...) ATTR_NONNULL(1, 3) ATTR_PRINTF_FORMAT(3, 4); size_t BLI_vsnprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format, va_list arg) ATTR_PRINTF_FORMAT(3, 0); +size_t BLI_vsnprintf_rlen(char *__restrict buffer, size_t maxncpy, const char *__restrict format, va_list arg) ATTR_PRINTF_FORMAT(3, 0); char *BLI_sprintfN(const char *__restrict format, ...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1, 2); diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index 2ddc8faa8b1..8f2f906ed17 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -435,7 +435,7 @@ extern "C" { } (void)0 /* assuming a static array */ -#if defined(__GNUC__) && !defined(__cplusplus) +#if defined(__GNUC__) && !defined(__cplusplus) && !defined(__clang__) # define ARRAY_SIZE(arr) \ ((sizeof(struct {int isnt_array : ((const void *)&(arr) == &(arr)[0]);}) * 0) + \ (sizeof(arr) / sizeof(*(arr)))) @@ -493,8 +493,11 @@ extern "C" { #define OFFSETOF_STRUCT(_struct, _member) \ ((((char *)&((_struct)->_member)) - ((char *)(_struct))) + sizeof((_struct)->_member)) -/* memcpy, skipping the first part of a struct, - * ensures 'struct_dst' isn't const and that the offset can be computed at compile time */ +/** + * memcpy helper, skipping the first part of a struct, + * ensures 'struct_dst' isn't const and the offset can be computed at compile time. + * This isn't inclusive, the value of \a member isn't copied. + */ #define MEMCPY_STRUCT_OFS(struct_dst, struct_src, member) { \ CHECK_TYPE_NONCONST(struct_dst); \ ((void)(struct_dst == struct_src), \ @@ -503,6 +506,13 @@ extern "C" { sizeof(*(struct_dst)) - OFFSETOF_STRUCT(struct_dst, member))); \ } (void)0 +#define MEMSET_STRUCT_OFS(struct_var, value, member) { \ + CHECK_TYPE_NONCONST(struct_var); \ + memset((char *)(struct_var) + OFFSETOF_STRUCT(struct_var, member), \ + value, \ + sizeof(*(struct_var)) - OFFSETOF_STRUCT(struct_var, member)); \ +} (void)0 + /* Warning-free macros for storing ints in pointers. Use these _only_ * for storing an int in a pointer, not a pointer in an int (64bit)! */ #define SET_INT_IN_POINTER(i) ((void *)(intptr_t)(i)) diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 73bd4869566..797bdaa2ae4 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -75,6 +75,7 @@ set(SRC intern/listbase.c intern/math_base.c intern/math_base_inline.c + intern/math_bits_inline.c intern/math_color.c intern/math_color_blend_inline.c intern/math_color_inline.c @@ -209,6 +210,7 @@ endif() # no need to compile object files for inline headers. set_source_files_properties( intern/math_base_inline.c + intern/math_bits_inline.c intern/math_color_blend_inline.c intern/math_color_inline.c intern/math_geom_inline.c diff --git a/source/blender/blenlib/intern/array_utils.c b/source/blender/blenlib/intern/array_utils.c index 173effbc434..6c5dc5a7f1e 100644 --- a/source/blender/blenlib/intern/array_utils.c +++ b/source/blender/blenlib/intern/array_utils.c @@ -25,23 +25,28 @@ #include <string.h> #include <stdlib.h> +#include "MEM_guardedalloc.h" + #include "BLI_array_utils.h" #include "BLI_sys_types.h" #include "BLI_utildefines.h" #include "BLI_alloca.h" +#include "BLI_strict_flags.h" + void _bli_array_reverse(void *arr_v, unsigned int arr_len, size_t arr_stride) { - const unsigned int arr_half_stride = (arr_len / 2) * arr_stride; + const unsigned int arr_stride_uint = (unsigned int)arr_stride; + const unsigned int arr_half_stride = (arr_len / 2) * arr_stride_uint; unsigned int i, i_end; char *arr = arr_v; char *buf = BLI_array_alloca(buf, arr_stride); - for (i = 0, i_end = (arr_len - 1) * arr_stride; + for (i = 0, i_end = (arr_len - 1) * arr_stride_uint; i < arr_half_stride; - i += arr_stride, i_end -= arr_stride) + i += arr_stride_uint, i_end -= arr_stride_uint) { memcpy(buf, &arr[i], arr_stride); memcpy(&arr[i], &arr[i_end], arr_stride); @@ -69,6 +74,36 @@ void _bli_array_wrap(void *arr_v, unsigned int arr_len, size_t arr_stride, int d } } +void _bli_array_permute( + void *arr_v, const unsigned int arr_len, const size_t arr_stride, + const unsigned int *order, void *arr_temp) +{ + const size_t len = arr_len * arr_stride; + const unsigned int arr_stride_uint = (unsigned int)arr_stride; + void *arr_orig; + unsigned int i; + + if (arr_temp == NULL) { + arr_orig = MEM_mallocN(len, __func__); + } + else { + arr_orig = arr_temp; + } + + memcpy(arr_orig, arr_v, len); + + for (i = 0; i < arr_len; i++) { + BLI_assert(order[i] < arr_len); + memcpy(POINTER_OFFSET(arr_v, arr_stride_uint * i), + POINTER_OFFSET(arr_orig, arr_stride_uint * order[i]), + arr_stride); + } + + if (arr_temp == NULL) { + MEM_freeN(arr_orig); + } +} + /** * \note Not efficient, use for error checks/asserts. */ diff --git a/source/blender/blenlib/intern/convexhull2d.c b/source/blender/blenlib/intern/convexhull2d.c index 5f64088f433..f77beac1982 100644 --- a/source/blender/blenlib/intern/convexhull2d.c +++ b/source/blender/blenlib/intern/convexhull2d.c @@ -239,7 +239,7 @@ int BLI_convexhull_2d(const float (*points)[2], const int n, int r_points[]) * * Intended to be used with #BLI_convexhull_2d * - * \param points Orded hull points + * \param points Ordered hull points * (result of #BLI_convexhull_2d mapped to a contiguous array). * * \note we could return the index of the best edge too if its needed. diff --git a/source/blender/blenlib/intern/math_base.c b/source/blender/blenlib/intern/math_base.c index cddfde371f5..0a1e9e8a8a1 100644 --- a/source/blender/blenlib/intern/math_base.c +++ b/source/blender/blenlib/intern/math_base.c @@ -31,6 +31,21 @@ #include "BLI_strict_flags.h" +int pow_i(int base, int exp) +{ + int result = 1; + BLI_assert(exp >= 0); + while (exp) { + if (exp & 1) { + result *= base; + } + exp >>= 1; + base *= base; + } + + return result; +} + /* from python 3.1 floatobject.c * ndigits must be between 0 and 21 */ double double_round(double x, int ndigits) diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c index f5713824296..facee8b0a89 100644 --- a/source/blender/blenlib/intern/math_base_inline.c +++ b/source/blender/blenlib/intern/math_base_inline.c @@ -198,25 +198,6 @@ MINLINE int mod_i(int i, int n) return (i % n + n) % n; } -MINLINE unsigned int highest_order_bit_i(unsigned int n) -{ - n |= (n >> 1); - 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 (unsigned short)(n - (n >> 1)); -} - MINLINE float min_ff(float a, float b) { return (a < b) ? a : b; diff --git a/source/blender/blenlib/intern/math_bits_inline.c b/source/blender/blenlib/intern/math_bits_inline.c new file mode 100644 index 00000000000..11ee6e7fa5b --- /dev/null +++ b/source/blender/blenlib/intern/math_bits_inline.c @@ -0,0 +1,59 @@ +/* + * ***** 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 ***** + * */ + +/** \file blender/blenlib/intern/math_bits_inline.c + * \ingroup bli + */ + +#ifndef __MATH_BITS_INLINE_C__ +#define __MATH_BITS_INLINE_C__ + +#include "BLI_math_bits.h" + +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 (unsigned short)(n - (n >> 1)); +} + +#ifndef __GNUC__ +MINLINE int count_bits_i(unsigned int i) +{ + /* variable-precision SWAR algorithm. */ + i = i - ((i >> 1) & 0x55555555); + i = (i & 0x33333333) + ((i >> 2) & 0x33333333); + return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24; +} +#endif + +#endif /* __MATH_BITS_INLINE_C__ */ diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index 1b4bbafdb04..a9afed7a63d 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -504,6 +504,16 @@ void mul_mat3_m4_v3(float mat[4][4], float vec[3]) vec[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2]; } +void mul_v3_mat3_m4v3(float r[3], float mat[4][4], const float vec[3]) +{ + const float x = vec[0]; + const float y = vec[1]; + + r[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2]; + r[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2]; + r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2]; +} + void mul_project_m4_v3(float mat[4][4], float vec[3]) { const float w = mul_project_m4_v3_zfac(mat, vec); @@ -1149,7 +1159,7 @@ bool is_orthogonal_m3(float m[3][3]) for (i = 0; i < 3; i++) { for (j = 0; j < i; j++) { - if (fabsf(dot_v3v3(m[i], m[j])) > 1.5f * FLT_EPSILON) + if (fabsf(dot_v3v3(m[i], m[j])) > 1e-5f) return false; } } @@ -1163,7 +1173,7 @@ bool is_orthogonal_m4(float m[4][4]) for (i = 0; i < 4; i++) { for (j = 0; j < i; j++) { - if (fabsf(dot_v4v4(m[i], m[j])) > 1.5f * FLT_EPSILON) + if (fabsf(dot_v4v4(m[i], m[j])) > 1e-5f) return false; } @@ -1178,7 +1188,7 @@ bool is_orthonormal_m3(float m[3][3]) int i; for (i = 0; i < 3; i++) - if (fabsf(dot_v3v3(m[i], m[i]) - 1) > 1.5f * FLT_EPSILON) + if (fabsf(dot_v3v3(m[i], m[i]) - 1) > 1e-5f) return false; return true; @@ -1193,7 +1203,7 @@ bool is_orthonormal_m4(float m[4][4]) int i; for (i = 0; i < 4; i++) - if (fabsf(dot_v4v4(m[i], m[i]) - 1) > 1.5f * FLT_EPSILON) + if (fabsf(dot_v4v4(m[i], m[i]) - 1) > 1e-5f) return false; return true; @@ -1465,39 +1475,14 @@ float mat4_to_scale(float mat[4][4]) void mat3_to_rot_size(float rot[3][3], float size[3], float mat3[3][3]) { - float mat3_n[3][3]; /* mat3 -> normalized, 3x3 */ - float imat3_n[3][3]; /* mat3 -> normalized & inverted, 3x3 */ - - /* rotation & scale are linked, we need to create the mat's - * for these together since they are related. */ - - /* so scale doesn't interfere with rotation [#24291] */ - /* note: this is a workaround for negative matrix not working for rotation conversion, FIXME */ - normalize_m3_m3(mat3_n, mat3); - if (is_negative_m3(mat3)) { - negate_m3(mat3_n); - } - - /* rotation */ /* keep rot as a 3x3 matrix, the caller can convert into a quat or euler */ - copy_m3_m3(rot, mat3_n); - - /* scale */ - /* note: mat4_to_size(ob->size, mat) fails for negative scale */ - invert_m3_m3(imat3_n, mat3_n); - - /* better not edit mat3 */ -#if 0 - mul_m3_m3m3(mat3, imat3_n, mat3); - - size[0] = mat3[0][0]; - size[1] = mat3[1][1]; - size[2] = mat3[2][2]; -#else - size[0] = dot_m3_v3_row_x(imat3_n, mat3[0]); - size[1] = dot_m3_v3_row_y(imat3_n, mat3[1]); - size[2] = dot_m3_v3_row_z(imat3_n, mat3[2]); -#endif + size[0] = normalize_v3_v3(rot[0], mat3[0]); + size[1] = normalize_v3_v3(rot[1], mat3[1]); + size[2] = normalize_v3_v3(rot[2], mat3[2]); + if (UNLIKELY(is_negative_m3(rot))) { + negate_m3(rot); + negate_v3(size); + } } void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], float wmat[4][4]) @@ -2251,7 +2236,7 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4]) void pseudoinverse_m4_m4(float Ainv[4][4], float A_[4][4], float epsilon) { - /* compute moon-penrose pseudo inverse of matrix, singular values + /* compute Moore-Penrose pseudo inverse of matrix, singular values * below epsilon are ignored for stability (truncated SVD) */ float A[4][4], V[4][4], W[4], Wm[4][4], U[4][4]; int i; diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index 1f0d68b09b2..5f039e89e89 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -1616,7 +1616,7 @@ void eulO_to_gimbal_axis(float gmat[3][3], const float eul[3], const short order void mat4_to_dquat(DualQuat *dq, float basemat[4][4], float mat[4][4]) { - float *t, *q, dscale[3], scale[3], basequat[4]; + float *t, *q, dscale[3], scale[3], basequat[4], mat3[3][3]; float baseRS[4][4], baseinv[4][4], baseR[4][4], baseRinv[4][4]; float R[4][4], S[4][4]; @@ -1629,7 +1629,9 @@ void mat4_to_dquat(DualQuat *dq, float basemat[4][4], float mat[4][4]) dscale[1] = scale[1] - 1.0f; dscale[2] = scale[2] - 1.0f; - if ((determinant_m4(mat) < 0.0f) || len_v3(dscale) > 1e-4f) { + copy_m3_m4(mat3, mat); + + if (!is_orthonormal_m3(mat3) || (determinant_m4(mat) < 0.0f) || len_v3(dscale) > 1e-4f) { /* extract R and S */ float tmp[4][4]; diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c index e9909cef29d..8f536bfe75c 100644 --- a/source/blender/blenlib/intern/math_vector.c +++ b/source/blender/blenlib/intern/math_vector.c @@ -897,6 +897,16 @@ void range_vn_i(int *array_tar, const int size, const int start) } } +void range_vn_u(unsigned int *array_tar, const int size, const unsigned int start) +{ + unsigned int *array_pt = array_tar + (size - 1); + unsigned int j = start + (unsigned int)(size - 1); + int i = size; + while (i--) { + *(array_pt--) = j--; + } +} + void range_vn_fl(float *array_tar, const int size, const float start, const float step) { float *array_pt = array_tar + (size - 1); diff --git a/source/blender/blenlib/intern/polyfill2d.c b/source/blender/blenlib/intern/polyfill2d.c index 3aadbe5f1df..629bed10191 100644 --- a/source/blender/blenlib/intern/polyfill2d.c +++ b/source/blender/blenlib/intern/polyfill2d.c @@ -179,7 +179,7 @@ BLI_INLINE eSign signum_enum(float a) * alternative version of #area_tri_signed_v2 * needed because of float precision issues * - * \note removes / 2 since its not needed since we only need ths sign. + * \note removes / 2 since its not needed since we only need the sign. */ BLI_INLINE float area_tri_signed_v2_alt_2x(const float v1[2], const float v2[2], const float v3[2]) { diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index cc5a90dbc39..e41e52a7c6e 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -231,6 +231,30 @@ size_t BLI_vsnprintf(char *__restrict buffer, size_t maxncpy, const char *__rest } /** + * A version of #BLI_vsnprintf that returns ``strlen(buffer)`` + */ +size_t BLI_vsnprintf_rlen(char *__restrict buffer, size_t maxncpy, const char *__restrict format, va_list arg) +{ + size_t n; + + BLI_assert(buffer != NULL); + BLI_assert(maxncpy > 0); + BLI_assert(format != NULL); + + n = (size_t)vsnprintf(buffer, maxncpy, format, arg); + + if (n != -1 && n < maxncpy) { + /* pass */ + } + else { + n = maxncpy - 1; + } + buffer[n] = '\0'; + + return n; +} + +/** * Portable replacement for #snprintf */ size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...) @@ -250,6 +274,25 @@ size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict } /** + * A version of #BLI_snprintf that returns ``strlen(dst)`` + */ +size_t BLI_snprintf_rlen(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...) +{ + size_t n; + va_list arg; + +#ifdef DEBUG_STRSIZE + memset(dst, 0xff, sizeof(*dst) * maxncpy); +#endif + + va_start(arg, format); + n = BLI_vsnprintf_rlen(dst, maxncpy, format, arg); + va_end(arg); + + return n; +} + +/** * Print formatted string into a newly #MEM_mallocN'd string * and return it. */ diff --git a/source/blender/blenlib/intern/timecode.c b/source/blender/blenlib/intern/timecode.c index 0c8834008b6..7b98d7830ee 100644 --- a/source/blender/blenlib/intern/timecode.c +++ b/source/blender/blenlib/intern/timecode.c @@ -113,22 +113,22 @@ size_t BLI_timecode_string_from_time( if (power <= 0) { /* include "frames" in display */ if (hours) { - rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%02d+%02d", neg, hours, minutes, seconds, frames); + rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d+%02d", neg, hours, minutes, seconds, frames); } else if (minutes) { - rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d+%02d", neg, minutes, seconds, frames); + rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d+%02d", neg, minutes, seconds, frames); } else { - rlen = BLI_snprintf(str, maxncpy, "%s%d+%02d", neg, seconds, frames); + rlen = BLI_snprintf_rlen(str, maxncpy, "%s%d+%02d", neg, seconds, frames); } } else { /* don't include 'frames' in display */ if (hours) { - rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%02d", neg, hours, minutes, seconds); + rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d", neg, hours, minutes, seconds); } else { - rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d", neg, minutes, seconds); + rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d", neg, minutes, seconds); } } break; @@ -137,10 +137,10 @@ size_t BLI_timecode_string_from_time( { /* reduced SMPTE format that always shows minutes, seconds, frames. Hours only shown as needed. */ if (hours) { - rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames); + rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames); } else { - rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%02d", neg, minutes, seconds, frames); + rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d", neg, minutes, seconds, frames); } break; } @@ -156,10 +156,10 @@ size_t BLI_timecode_string_from_time( const int s_pad = ms_dp + 3; if (hours) { - rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%0*.*f", neg, hours, minutes, s_pad, ms_dp, time); + rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%0*.*f", neg, hours, minutes, s_pad, ms_dp, time); } else { - rlen = BLI_snprintf(str, maxncpy, "%s%02d:%0*.*f", neg, minutes, s_pad, ms_dp, time); + rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%0*.*f", neg, minutes, s_pad, ms_dp, time); } break; } @@ -168,10 +168,10 @@ size_t BLI_timecode_string_from_time( /* only show the original seconds display */ /* round to whole numbers if power is >= 1 (i.e. scale is coarse) */ if (power <= 0) { - rlen = BLI_snprintf(str, maxncpy, "%.*f", 1 - power, time_seconds); + rlen = BLI_snprintf_rlen(str, maxncpy, "%.*f", 1 - power, time_seconds); } else { - rlen = BLI_snprintf(str, maxncpy, "%d", iroundf(time_seconds)); + rlen = BLI_snprintf_rlen(str, maxncpy, "%d", iroundf(time_seconds)); } break; } @@ -179,7 +179,7 @@ size_t BLI_timecode_string_from_time( default: { /* full SMPTE format */ - rlen = BLI_snprintf(str, maxncpy, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames); + rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames); break; } } @@ -208,10 +208,10 @@ size_t BLI_timecode_string_from_time_simple( /* round to whole numbers if power is >= 1 (i.e. scale is coarse) */ if (power <= 0) { - rlen = BLI_snprintf(str, maxncpy, "%.*f", 1 - power, time_seconds); + rlen = BLI_snprintf_rlen(str, maxncpy, "%.*f", 1 - power, time_seconds); } else { - rlen = BLI_snprintf(str, maxncpy, "%d", iroundf(time_seconds)); + rlen = BLI_snprintf_rlen(str, maxncpy, "%d", iroundf(time_seconds)); } return rlen; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 1b9cc0063a6..c9952926913 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2639,7 +2639,7 @@ static void lib_verify_nodetree(Main *main, int UNUSED(open)) * New file versions already have input/output nodes with duplicate links, * in that case just remove the invalid links. */ - int create_io_nodes = (ntree->flag & NTREE_DO_VERSIONS_CUSTOMNODES_GROUP_CREATE_INTERFACE); + const bool create_io_nodes = (ntree->flag & NTREE_DO_VERSIONS_CUSTOMNODES_GROUP_CREATE_INTERFACE) != 0; float input_locx = 1000000.0f, input_locy = 0.0f; float output_locx = -1000000.0f, output_locy = 0.0f; @@ -3532,7 +3532,7 @@ static void direct_link_curve(FileData *fd, Curve *cu) nu->bp = newdataadr(fd, nu->bp); nu->knotsu = newdataadr(fd, nu->knotsu); nu->knotsv = newdataadr(fd, nu->knotsv); - if (cu->vfont == NULL) nu->charidx= nu->mat_nr; + if (cu->vfont == NULL) nu->charidx = 0; if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) { switch_endian_knots(nu); @@ -5829,6 +5829,12 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm) win->lastcursor = 0; win->modalcursor = 0; win->stereo3d_format = newdataadr(fd, win->stereo3d_format); + + /* multiview always fallback to anaglyph at file opening + * otherwise quadbuffer saved files can break Blender */ + if (win->stereo3d_format) { + win->stereo3d_format->display_mode = S3D_DISPLAY_ANAGLYPH; + } } BLI_listbase_clear(&wm->timers); @@ -5979,6 +5985,9 @@ static void lib_link_screen(FileData *fd, Main *main) else if (sl->spacetype == SPACE_BUTS) { SpaceButs *sbuts = (SpaceButs *)sl; sbuts->pinid = newlibadr(fd, sc->id.lib, sbuts->pinid); + if (sbuts->pinid == NULL) { + sbuts->flag &= ~SB_PIN_CONTEXT; + } } else if (sl->spacetype == SPACE_FILE) { ; @@ -6308,6 +6317,9 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc else if (sl->spacetype == SPACE_BUTS) { SpaceButs *sbuts = (SpaceButs *)sl; sbuts->pinid = restore_pointer_by_name(newmain, sbuts->pinid, USER_IGNORE); + if (sbuts->pinid == NULL) { + sbuts->flag &= ~SB_PIN_CONTEXT; + } /* TODO: restore path pointers: T40046 * (complicated because this contains data pointers too, not just ID)*/ @@ -7085,7 +7097,7 @@ static void direct_link_moviePlaneTracks(FileData *fd, ListBase *plane_tracks_ba int i; plane_track->point_tracks = newdataadr(fd, plane_track->point_tracks); - + test_pointer_array(fd, (void**)&plane_track->point_tracks); for (i = 0; i < plane_track->point_tracksnr; i++) { plane_track->point_tracks[i] = newdataadr(fd, plane_track->point_tracks[i]); } @@ -7809,12 +7821,12 @@ static void do_versions(FileData *fd, Library *lib, Main *main) if (G.debug & G_DEBUG) { char build_commit_datetime[32]; time_t temp_time = main->build_commit_timestamp; - struct tm *tm = gmtime(&temp_time); + struct tm *tm = (temp_time) ? gmtime(&temp_time) : NULL; if (LIKELY(tm)) { strftime(build_commit_datetime, sizeof(build_commit_datetime), "%Y-%m-%d %H:%M", tm); } else { - BLI_strncpy(build_commit_datetime, "date-unknown", sizeof(build_commit_datetime)); + BLI_strncpy(build_commit_datetime, "unknown", sizeof(build_commit_datetime)); } printf("read file %s\n Version %d sub %d date %s hash %s\n", @@ -9245,7 +9257,6 @@ static void give_base_to_groups(Main *mainvar, Scene *scene) /* assign the group */ ob->dup_group = group; ob->transflag |= OB_DUPLIGROUP; - rename_id(&ob->id, group->id.name + 2); copy_v3_v3(ob->loc, scene->cursor); } } diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index c8862870b92..df985448ccd 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -799,4 +799,36 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } } } + + if (!MAIN_VERSION_ATLEAST(main, 274, 6)) { + bScreen *screen; + + if (!DNA_struct_elem_find(fd->filesdna, "FileSelectParams", "int", "thumbnail_size")) { + for (screen = main->screen.first; screen; screen = screen->id.next) { + ScrArea *sa; + + for (sa = screen->areabase.first; sa; sa = sa->next) { + SpaceLink *sl; + + for (sl = sa->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_FILE) { + SpaceFile *sfile = (SpaceFile *)sl; + + if (sfile->params) { + sfile->params->thumbnail_size = 128; + } + } + } + } + } + } + + if (!DNA_struct_elem_find(fd->filesdna, "RenderData", "short", "simplify_subsurf_render")) { + Scene *scene; + for (scene = main->scene.first; scene != NULL; scene = scene->id.next) { + scene->r.simplify_subsurf_render = scene->r.simplify_subsurf; + scene->r.simplify_particles_render = scene->r.simplify_particles; + } + } + } } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 12c4f4922dc..285c50a4049 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1903,26 +1903,35 @@ static void write_grid_paint_mask(WriteData *wd, int count, GridPaintMask *grid_ static void write_customdata(WriteData *wd, ID *id, int count, CustomData *data, int partial_type, int partial_count) { - CustomData data_tmp; int i; - /* This copy will automatically ignore/remove layers set as NO_COPY (and TEMPORARY). */ - CustomData_copy(data, &data_tmp, CD_MASK_EVERYTHING, CD_REFERENCE, count); + int nofree_buff[128]; + int *nofree; /* write external customdata (not for undo) */ - if (data_tmp.external && !wd->current) - CustomData_external_write(&data_tmp, id, CD_MASK_MESH, count, 0); + if (data->external && !wd->current) + CustomData_external_write(data, id, CD_MASK_MESH, count, 0); - for (i = 0; i < data_tmp.totlayer; i++) - data_tmp.layers[i].flag &= ~CD_FLAG_NOFREE; + if (data->totlayer > ARRAY_SIZE(nofree_buff)) { + nofree = MEM_mallocN(sizeof(*nofree) * (size_t)data->totlayer, __func__); + } + else { + nofree = nofree_buff; + } - writestruct_at_address(wd, DATA, "CustomDataLayer", data_tmp.maxlayer, data->layers, data_tmp.layers); + for (i = 0; i < data->totlayer; i++) { + nofree[i] = (data->layers[i].flag & CD_FLAG_NOFREE); + data->layers[i].flag &= ~CD_FLAG_NOFREE; + } + + writestruct(wd, DATA, "CustomDataLayer", data->maxlayer, data->layers); - for (i = 0; i < data_tmp.totlayer; i++) - data_tmp.layers[i].flag |= CD_FLAG_NOFREE; + for (i = 0; i < data->totlayer; i++) { + data->layers[i].flag |= nofree[i]; + } - for (i = 0; i < data_tmp.totlayer; i++) { - CustomDataLayer *layer= &data_tmp.layers[i]; + for (i = 0; i < data->totlayer; i++) { + CustomDataLayer *layer= &data->layers[i]; const char *structname; int structnum, datasize; @@ -1958,10 +1967,12 @@ static void write_customdata(WriteData *wd, ID *id, int count, CustomData *data, } } - if (data_tmp.external) - writestruct_at_address(wd, DATA, "CustomDataExternal", 1, data->external, data_tmp.external); + if (data->external) + writestruct(wd, DATA, "CustomDataExternal", 1, data->external); - CustomData_free(&data_tmp, count); + if (nofree != nofree_buff) { + MEM_freeN(nofree); + } } static void write_meshes(WriteData *wd, ListBase *idbase) @@ -1978,23 +1989,32 @@ static void write_meshes(WriteData *wd, ListBase *idbase) if (mesh->id.us>0 || wd->current) { /* write LibData */ if (!save_for_old_blender) { - -#ifdef USE_BMESH_SAVE_WITHOUT_MFACE /* write a copy of the mesh, don't modify in place because it is * not thread safe for threaded renders that are reading this */ Mesh *old_mesh = mesh; Mesh copy_mesh = *mesh; mesh = ©_mesh; +#ifdef USE_BMESH_SAVE_WITHOUT_MFACE /* cache only - don't write */ mesh->mface = NULL; mesh->totface = 0; memset(&mesh->fdata, 0, sizeof(mesh->fdata)); +#endif /* USE_BMESH_SAVE_WITHOUT_MFACE */ + + /* Bummer! We need to do the copy *before* writing mesh's struct itself, + * because we eliminate NO_COPY & TEMPORARY layers here, which means + * **number of layers (data.totlayer) may be smaller!** + * If we do not do that, we can get crash by buffer-overflow on reading, see T44461. */ + CustomData_copy(&old_mesh->vdata, &mesh->vdata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totvert); + CustomData_copy(&old_mesh->edata, &mesh->edata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totedge); +#ifndef USE_BMESH_SAVE_WITHOUT_MFACE /* Do not copy org fdata in this case!!! */ + CustomData_copy(&old_mesh->fdata, &mesh->fdata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totface); +#endif + CustomData_copy(&old_mesh->ldata, &mesh->ldata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totloop); + CustomData_copy(&old_mesh->pdata, &mesh->pdata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totpoly); writestruct_at_address(wd, ID_ME, "Mesh", 1, old_mesh, mesh); -#else - writestruct(wd, ID_ME, "Mesh", 1, mesh); -#endif /* USE_BMESH_SAVE_WITHOUT_MFACE */ /* direct data */ if (mesh->id.properties) IDP_WriteProperty(mesh->id.properties, wd); @@ -2010,11 +2030,16 @@ static void write_meshes(WriteData *wd, ListBase *idbase) write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, -1, 0); write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, -1, 0); -#ifdef USE_BMESH_SAVE_WITHOUT_MFACE + CustomData_free(&mesh->vdata, mesh->totvert); + CustomData_free(&mesh->edata, mesh->totedge); +#ifndef USE_BMESH_SAVE_WITHOUT_MFACE + CustomData_free(&mesh->fdata, mesh->totface); +#endif + CustomData_free(&mesh->ldata, mesh->totloop); + CustomData_free(&mesh->pdata, mesh->totpoly); + /* restore pointer */ mesh = old_mesh; -#endif /* USE_BMESH_SAVE_WITHOUT_MFACE */ - } else { @@ -2041,6 +2066,10 @@ static void write_meshes(WriteData *wd, ListBase *idbase) BKE_mesh_update_customdata_pointers(mesh, false); + /* See comment above. Note that loop/poly data are ignored here, and face ones are already handled. */ + CustomData_copy(&old_mesh->vdata, &mesh->vdata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totvert); + CustomData_copy(&old_mesh->edata, &mesh->edata, CD_MASK_EVERYTHING, CD_REFERENCE, mesh->totedge); + writestruct_at_address(wd, ID_ME, "Mesh", 1, old_mesh, mesh); /* direct data */ @@ -2059,6 +2088,8 @@ static void write_meshes(WriteData *wd, ListBase *idbase) write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, -1, 0); #endif + CustomData_free(&mesh->vdata, mesh->totvert); + CustomData_free(&mesh->edata, mesh->totedge); CustomData_free(&mesh->fdata, mesh->totface); /* restore pointer */ diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h index 75de216898b..058fec548a3 100644 --- a/source/blender/bmesh/bmesh_class.h +++ b/source/blender/bmesh/bmesh_class.h @@ -256,12 +256,29 @@ enum { #define BM_ALL (BM_VERT | BM_EDGE | BM_LOOP | BM_FACE) #define BM_ALL_NOLOOP (BM_VERT | BM_EDGE | BM_FACE) +/* args for _Generic */ +#define _BM_GENERIC_TYPE_ELEM_NONCONST \ + void *, BMVert *, BMEdge *, BMLoop *, BMFace *, \ + BMElem *, BMElemF *, BMHeader * + +#define _BM_GENERIC_TYPE_ELEM_CONST \ + const void *, const BMVert *, const BMEdge *, const BMLoop *, const BMFace *, \ + const BMElem *, const BMElemF *, const BMHeader *, \ + void * const, BMVert * const, BMEdge * const, BMLoop * const, BMFace * const, \ + BMElem * const, BMElemF * const, BMHeader * const + +#define BM_CHECK_TYPE_ELEM_CONST(ele) \ + CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPES_CONST) + +#define BM_CHECK_TYPE_ELEM_NONCONST(ele) \ + CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST) + #define BM_CHECK_TYPE_ELEM(ele) \ - CHECK_TYPE_ANY(ele, void *, BMFace *, BMEdge *, BMVert *, BMLoop *, BMElem *, BMElemF *, BMHeader *) + CHECK_TYPE_ANY(ele, _BM_GENERIC_TYPE_ELEM_NONCONST, _BM_GENERIC_TYPE_ELEM_CONST) #ifndef __cplusplus #define BM_CHECK_TYPE_ELEM_ASSIGN(ele) \ - (BM_CHECK_TYPE_ELEM(ele), CHECK_TYPE_NONCONST(ele)), ele + (BM_CHECK_TYPE_ELEM(ele)), ele #else /* for C++: cast the lhs to a void*, * because C++ does not allow implicit void* casting of the rhs @@ -305,8 +322,17 @@ typedef bool (*BMElemFilterFunc)(BMElem *, void *user_data); #define BM_ELEM_CD_GET_INT(ele, offset) \ (assert(offset != -1), *((int *)((char *)(ele)->head.data + (offset)))) +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) +#define BM_ELEM_CD_GET_VOID_P(ele, offset) \ + (assert(offset != -1), \ + _Generic(ele, \ + GENERIC_TYPE_ANY( POINTER_OFFSET((ele)->head.data, offset), _BM_GENERIC_TYPE_ELEM_NONCONST), \ + GENERIC_TYPE_ANY((const void *)POINTER_OFFSET((ele)->head.data, offset), _BM_GENERIC_TYPE_ELEM_CONST)) \ + ) +#else #define BM_ELEM_CD_GET_VOID_P(ele, offset) \ (assert(offset != -1), (void *)((char *)(ele)->head.data + (offset))) +#endif #define BM_ELEM_CD_SET_FLOAT(ele, offset, f) { CHECK_TYPE_NONCONST(ele); \ assert(offset != -1); *((float *)((char *)(ele)->head.data + (offset))) = (f); } (void)0 diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index e0348fea636..fb7f936318b 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -47,8 +47,9 @@ #define SELECT 1 /* prototypes */ -static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, - const BMLoop *source_loop, BMLoop *target_loop); +static void bm_loop_attrs_copy( + BMesh *source_mesh, BMesh *target_mesh, + const BMLoop *source_loop, BMLoop *target_loop); /** * \brief Make Quad/Triangle @@ -64,9 +65,10 @@ static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, * of the vertices in the vertex array. */ -BMFace *BM_face_create_quad_tri(BMesh *bm, - BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, - const BMFace *f_example, const eBMCreateFlag create_flag) +BMFace *BM_face_create_quad_tri( + BMesh *bm, + BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, + const BMFace *f_example, const eBMCreateFlag create_flag) { BMVert *vtar[4] = {v1, v2, v3, v4}; return BM_face_create_verts(bm, vtar, v4 ? 4 : 3, f_example, create_flag, true); @@ -81,8 +83,9 @@ BMFace *BM_face_create_quad_tri(BMesh *bm, * this is done since the face may not be completely surrounded by faces, * this way: a quad with 2 connected quads on either side will still get all 4 loops updated */ -void BM_face_copy_shared(BMesh *bm, BMFace *f, - BMElemFilterFunc filter_fn, void *user_data) +void BM_face_copy_shared( + BMesh *bm, BMFace *f, + BMElemFilterFunc filter_fn, void *user_data) { BMLoop *l_first; BMLoop *l_iter; @@ -132,155 +135,113 @@ void BM_face_copy_shared(BMesh *bm, BMFace *f, } /** - * \brief Make NGon - * - * Makes an ngon from an unordered list of edges. \a v1 and \a v2 - * must be the verts defining edges[0], - * and define the winding of the new face. - * - * \a edges are not required to be ordered, simply to to form - * a single closed loop as a whole. + * Given an array of edges, + * order them using the winding defined by \a v1 & \a v2 + * into \a edges_sort & \a verts_sort. * - * \note While this function will work fine when the edges - * are already sorted, if the edges are always going to be sorted, - * #BM_face_create should be considered over this function as it - * avoids some unnecessary work. + * All arrays must be \a len long. */ -BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len, - const BMFace *f_example, const eBMCreateFlag create_flag) +static bool bm_edges_sort_winding( + BMVert *v1, BMVert *v2, + BMEdge **edges, const int len, + BMEdge **edges_sort, BMVert **verts_sort) { - BMEdge **edges_sort = BLI_array_alloca(edges_sort, len); - BMVert **verts_sort = BLI_array_alloca(verts_sort, len + 1); - int esort_index = 0; - int vsort_index = 0; - - BMFace *f = NULL; - BMEdge *e; - BMVert *v, *ev1, *ev2; + BMEdge *e_iter, *e_first; + BMVert *v_iter; int i; - bool is_v1_found, is_reverse; - - /* this code is hideous, yeek. I'll have to think about ways of - * cleaning it up. basically, it now combines the old BM_face_create_ngon - * _and_ the old bmesh_mf functions, so its kindof smashed together - * - joeedh */ - - BLI_assert(len && v1 && v2 && edges && bm); - - /* put edges in correct order */ + /* all flags _must_ be cleared on exit! */ for (i = 0; i < len; i++) { BM_ELEM_API_FLAG_ENABLE(edges[i], _FLAG_MF); + BM_ELEM_API_FLAG_ENABLE(edges[i]->v1, _FLAG_MV); + BM_ELEM_API_FLAG_ENABLE(edges[i]->v2, _FLAG_MV); } - ev1 = edges[0]->v1; - ev2 = edges[0]->v2; - - BLI_assert(ELEM(v1, ev1, ev2) && ELEM(v2, ev1, ev2)); - - if (v1 == ev2) { - /* Swapping here improves performance and consistency of face - * structure in the special case that the edges are already in - * the correct order and winding */ - SWAP(BMVert *, ev1, ev2); - } - - verts_sort[vsort_index++] = ev1; - v = ev2; - e = edges[0]; + /* find first edge */ + i = 0; + v_iter = v1; + e_iter = e_first = v1->e; do { - BMEdge *e2 = e; - - /* vertex array is (len + 1) */ - if (UNLIKELY(vsort_index > len)) { - goto err; /* vertex in loop twice */ + if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF) && + (BM_edge_other_vert(e_iter, v_iter) == v2)) + { + i = 1; + break; } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first); + if (i == 0) { + goto error; + } - verts_sort[vsort_index++] = v; - edges_sort[esort_index++] = e; - - /* we only flag the verts to check if they are in the face more than once */ - BM_ELEM_API_FLAG_ENABLE(v, _FLAG_MV); - - do { - e2 = bmesh_disk_edge_next(e2, v); - if (e2 != e && BM_ELEM_API_FLAG_TEST(e2, _FLAG_MF)) { - v = BM_edge_other_vert(e2, v); - break; + i = 0; + do { + /* entering loop will always succeed */ + if (BM_ELEM_API_FLAG_TEST(e_iter, _FLAG_MF)) { + if (UNLIKELY(BM_ELEM_API_FLAG_TEST(v_iter, _FLAG_MV) == false)) { + /* vert is in loop multiple times */ + goto error; } - } while (e2 != e); - if (UNLIKELY(e2 == e)) { - goto err; /* the edges do not form a closed loop */ - } + BM_ELEM_API_FLAG_DISABLE(e_iter, _FLAG_MF); + edges_sort[i] = e_iter; - e = e2; - } while (e != edges[0]); + BM_ELEM_API_FLAG_DISABLE(v_iter, _FLAG_MV); + verts_sort[i] = v_iter; - if (UNLIKELY(esort_index != len)) { - goto err; /* we didn't use all edges in forming the boundary loop */ - } + i += 1; - /* ok, edges are in correct order, now ensure they are going - * in the correct direction */ - is_v1_found = is_reverse = false; - for (i = 0; i < len; i++) { - if (BM_vert_in_edge(edges_sort[i], v1)) { - /* see if v1 and v2 are in the same edge */ - if (BM_vert_in_edge(edges_sort[i], v2)) { - /* if v1 is shared by the *next* edge, then the winding - * is incorrect */ - if (BM_vert_in_edge(edges_sort[(i + 1) % len], v1)) { - is_reverse = true; - break; + /* walk onto the next vertex */ + v_iter = BM_edge_other_vert(e_iter, v_iter); + if (i == len) { + if (UNLIKELY(v_iter != verts_sort[0])) { + goto error; } + break; } - is_v1_found = true; + e_first = e_iter; } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v_iter)) != e_first); - if ((is_v1_found == false) && BM_vert_in_edge(edges_sort[i], v2)) { - is_reverse = true; - break; - } - } - - if (is_reverse) { - for (i = 0; i < len / 2; i++) { - v = verts_sort[i]; - verts_sort[i] = verts_sort[len - i - 1]; - verts_sort[len - i - 1] = v; - } + if (i == len) { + return true; } +error: for (i = 0; i < len; i++) { - edges_sort[i] = BM_edge_exists(verts_sort[i], verts_sort[(i + 1) % len]); - if (UNLIKELY(edges_sort[i] == NULL)) { - goto err; - } - - /* check if vert is in face more than once. if the flag is disabled. we've already visited */ - if (UNLIKELY(!BM_ELEM_API_FLAG_TEST(verts_sort[i], _FLAG_MV))) { - goto err; - } - BM_ELEM_API_FLAG_DISABLE(verts_sort[i], _FLAG_MV); + BM_ELEM_API_FLAG_DISABLE(edges[i], _FLAG_MF); + BM_ELEM_API_FLAG_DISABLE(edges[i]->v1, _FLAG_MV); + BM_ELEM_API_FLAG_DISABLE(edges[i]->v2, _FLAG_MV); } - f = BM_face_create(bm, verts_sort, edges_sort, len, f_example, create_flag); + return false; +} - /* clean up flags */ - for (i = 0; i < len; i++) { - BM_ELEM_API_FLAG_DISABLE(edges_sort[i], _FLAG_MF); - } +/** + * \brief Make NGon + * + * Makes an ngon from an unordered list of edges. + * Verts \a v1 and \a v2 define the winding of the new face. + * + * \a edges are not required to be ordered, simply to to form + * a single closed loop as a whole. + * + * \note While this function will work fine when the edges + * are already sorted, if the edges are always going to be sorted, + * #BM_face_create should be considered over this function as it + * avoids some unnecessary work. + */ +BMFace *BM_face_create_ngon( + BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len, + const BMFace *f_example, const eBMCreateFlag create_flag) +{ + BMEdge **edges_sort = BLI_array_alloca(edges_sort, len); + BMVert **verts_sort = BLI_array_alloca(verts_sort, len); - return f; + BLI_assert(len && v1 && v2 && edges && bm); -err: - for (i = 0; i < len; i++) { - BM_ELEM_API_FLAG_DISABLE(edges[i], _FLAG_MF); - } - for (i = 0; i < vsort_index; i++) { - BM_ELEM_API_FLAG_DISABLE(verts_sort[i], _FLAG_MV); + if (bm_edges_sort_winding(v1, v2, edges, len, edges_sort, verts_sort)) { + return BM_face_create(bm, verts_sort, edges_sort, len, f_example, create_flag); } return NULL; @@ -294,9 +255,10 @@ err: * - Optionally create edges between vertices. * - Uses verts so no need to find edges (handy when you only have verts) */ -BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len, - const BMFace *f_example, const eBMCreateFlag create_flag, - const bool calc_winding, const bool create_edges) +BMFace *BM_face_create_ngon_verts( + BMesh *bm, BMVert **vert_arr, const int len, + const BMFace *f_example, const eBMCreateFlag create_flag, + const bool calc_winding, const bool create_edges) { BMEdge **edge_arr = BLI_array_alloca(edge_arr, len); unsigned int winding[2] = {0, 0}; @@ -375,8 +337,9 @@ BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len, * * \note Since this is a vcloud there is no direction. */ -BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, - const BMFace *f_example, const eBMCreateFlag create_flag) +BMFace *BM_face_create_ngon_vcloud( + BMesh *bm, BMVert **vert_arr, int len, + const BMFace *f_example, const eBMCreateFlag create_flag) { struct SortIntByFloat *vang = BLI_array_alloca(vang, len); BMVert **vert_arr_map = BLI_array_alloca(vert_arr_map, len); @@ -497,8 +460,9 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, /*************************************************************/ -static void bm_vert_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, - const BMVert *source_vertex, BMVert *target_vertex) +static void bm_vert_attrs_copy( + BMesh *source_mesh, BMesh *target_mesh, + const BMVert *source_vertex, BMVert *target_vertex) { if ((source_mesh == target_mesh) && (source_vertex == target_vertex)) { BLI_assert(!"BMVert: source and targer match"); @@ -510,8 +474,9 @@ static void bm_vert_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, source_vertex->head.data, &target_vertex->head.data); } -static void bm_edge_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, - const BMEdge *source_edge, BMEdge *target_edge) +static void bm_edge_attrs_copy( + BMesh *source_mesh, BMesh *target_mesh, + const BMEdge *source_edge, BMEdge *target_edge) { if ((source_mesh == target_mesh) && (source_edge == target_edge)) { BLI_assert(!"BMEdge: source and targer match"); @@ -522,8 +487,9 @@ static void bm_edge_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, source_edge->head.data, &target_edge->head.data); } -static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, - const BMLoop *source_loop, BMLoop *target_loop) +static void bm_loop_attrs_copy( + BMesh *source_mesh, BMesh *target_mesh, + const BMLoop *source_loop, BMLoop *target_loop) { if ((source_mesh == target_mesh) && (source_loop == target_loop)) { BLI_assert(!"BMLoop: source and targer match"); @@ -534,8 +500,9 @@ static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, source_loop->head.data, &target_loop->head.data); } -static void bm_face_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, - const BMFace *source_face, BMFace *target_face) +static void bm_face_attrs_copy( + BMesh *source_mesh, BMesh *target_mesh, + const BMFace *source_face, BMFace *target_face) { if ((source_mesh == target_mesh) && (source_face == target_face)) { BLI_assert(!"BMFace: source and targer match"); @@ -555,8 +522,9 @@ static void bm_face_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, * Copies attributes, e.g. customdata, header flags, etc, from one element * to another of the same type. */ -void BM_elem_attrs_copy_ex(BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v, - const char hflag_mask) +void BM_elem_attrs_copy_ex( + BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v, + const char hflag_mask) { const BMHeader *ele_src = ele_src_v; BMHeader *ele_dst = ele_dst_v; @@ -621,9 +589,10 @@ void BM_elem_select_copy(BMesh *bm_dst, BMesh *UNUSED(bm_src), void *ele_dst_v, } /* helper function for 'BM_mesh_copy' */ -static BMFace *bm_mesh_copy_new_face(BMesh *bm_new, BMesh *bm_old, - BMVert **vtable, BMEdge **etable, - BMFace *f) +static BMFace *bm_mesh_copy_new_face( + BMesh *bm_new, BMesh *bm_old, + BMVert **vtable, BMEdge **etable, + BMFace *f) { BMLoop **loops = BLI_array_alloca(loops, f->len); BMVert **verts = BLI_array_alloca(verts, f->len); diff --git a/source/blender/bmesh/intern/bmesh_construct.h b/source/blender/bmesh/intern/bmesh_construct.h index 12d3a4bd474..0e3ca75681a 100644 --- a/source/blender/bmesh/intern/bmesh_construct.h +++ b/source/blender/bmesh/intern/bmesh_construct.h @@ -29,23 +29,29 @@ struct BMAllocTemplate; -BMFace *BM_face_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, - const BMFace *f_example, const eBMCreateFlag create_flag); +BMFace *BM_face_create_quad_tri( + BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, + const BMFace *f_example, const eBMCreateFlag create_flag); -void BM_face_copy_shared(BMesh *bm, BMFace *f, - BMElemFilterFunc filter_fn, void *user_data); +void BM_face_copy_shared( + BMesh *bm, BMFace *f, + BMElemFilterFunc filter_fn, void *user_data); -BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len, - const BMFace *f_example, const eBMCreateFlag create_flag); -BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len, - const BMFace *f_example, const eBMCreateFlag create_flag, - const bool calc_winding, const bool create_edges); +BMFace *BM_face_create_ngon( + BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len, + const BMFace *f_example, const eBMCreateFlag create_flag); +BMFace *BM_face_create_ngon_verts( + BMesh *bm, BMVert **vert_arr, const int len, + const BMFace *f_example, const eBMCreateFlag create_flag, + const bool calc_winding, const bool create_edges); -BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, - const BMFace *f_example, const eBMCreateFlag create_flag); +BMFace *BM_face_create_ngon_vcloud( + BMesh *bm, BMVert **vert_arr, int len, + const BMFace *f_example, const eBMCreateFlag create_flag); -void BM_elem_attrs_copy_ex(BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v, - const char hflag_mask); +void BM_elem_attrs_copy_ex( + BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v, + const char hflag_mask); void BM_elem_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v); void BM_elem_select_copy(BMesh *bm_dst, BMesh *bm_src, void *ele_dst_v, const void *ele_src_v); diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 7b54fcbffde..2a69edd47b0 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -31,7 +31,7 @@ #include "BLI_math_vector.h" #include "BLI_array.h" #include "BLI_alloca.h" -#include "BLI_smallhash.h" +#include "BLI_linklist_stack.h" #include "BLI_stackdefines.h" #include "BLF_translation.h" @@ -57,8 +57,9 @@ /** * \brief Main function for creating a new vertex. */ -BMVert *BM_vert_create(BMesh *bm, const float co[3], - const BMVert *v_example, const eBMCreateFlag create_flag) +BMVert *BM_vert_create( + BMesh *bm, const float co[3], + const BMVert *v_example, const eBMCreateFlag create_flag) { BMVert *v = BLI_mempool_alloc(bm->vpool); @@ -141,8 +142,9 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], * \note Duplicate edges are supported by the API however users should _never_ see them. * so unless you need a unique edge or know the edge won't exist, you should call with \a no_double = true */ -BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, - const BMEdge *e_example, const eBMCreateFlag create_flag) +BMEdge *BM_edge_create( + BMesh *bm, BMVert *v1, BMVert *v2, + const BMEdge *e_example, const eBMCreateFlag create_flag) { BMEdge *e; @@ -204,8 +206,9 @@ BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, return e; } -static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f, - const BMLoop *l_example, const eBMCreateFlag create_flag) +static BMLoop *bm_loop_create( + BMesh *bm, BMVert *v, BMEdge *e, BMFace *f, + const BMLoop *l_example, const eBMCreateFlag create_flag) { BMLoop *l = NULL; @@ -254,8 +257,9 @@ static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f, return l; } -static BMLoop *bm_face_boundary_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte, - const eBMCreateFlag create_flag) +static BMLoop *bm_face_boundary_add( + BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte, + const eBMCreateFlag create_flag) { #ifdef USE_BMESH_HOLES BMLoopList *lst = BLI_mempool_calloc(bm->looplistpool); @@ -276,8 +280,9 @@ static BMLoop *bm_face_boundary_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge return l; } -BMFace *BM_face_copy(BMesh *bm_dst, BMesh *bm_src, BMFace *f, - const bool copy_verts, const bool copy_edges) +BMFace *BM_face_copy( + BMesh *bm_dst, BMesh *bm_src, BMFace *f, + const bool copy_verts, const bool copy_edges) { BMVert **verts = BLI_array_alloca(verts, f->len); BMEdge **edges = BLI_array_alloca(edges, f->len); @@ -400,8 +405,9 @@ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm) * \param len Length of the face * \param create_flag Options for creating the face */ -BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, - const BMFace *f_example, const eBMCreateFlag create_flag) +BMFace *BM_face_create( + BMesh *bm, BMVert **verts, BMEdge **edges, const int len, + const BMFace *f_example, const eBMCreateFlag create_flag) { BMFace *f = NULL; BMLoop *l, *startl, *lastl; @@ -474,8 +480,9 @@ BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, /** * Wrapper for #BM_face_create when you don't have an edge array */ -BMFace *BM_face_create_verts(BMesh *bm, BMVert **vert_arr, const int len, - const BMFace *f_example, const eBMCreateFlag create_flag, const bool create_edges) +BMFace *BM_face_create_verts( + BMesh *bm, BMVert **vert_arr, const int len, + const BMFace *f_example, const eBMCreateFlag create_flag, const bool create_edges) { BMEdge **edge_arr = BLI_array_alloca(edge_arr, len); int i, i_prev = len - 1; @@ -1046,8 +1053,9 @@ static bool disk_is_flagged(BMVert *v, const char api_flag) return false; } - if (bmesh_radial_length(l) == 1) + if (BM_edge_is_boundary(l->e)) { return false; + } do { if (!BM_ELEM_API_FLAG_TEST(l->f, api_flag)) @@ -1327,14 +1335,14 @@ static BMFace *bm_face_create__sfme(BMesh *bm, BMFace *f_example) * * \return A BMFace pointer */ -BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMLoop *l_v1, BMLoop *l_v2, - BMLoop **r_l, +BMFace *bmesh_sfme( + BMesh *bm, BMFace *f, BMLoop *l_v1, BMLoop *l_v2, + BMLoop **r_l, #ifdef USE_BMESH_HOLES - ListBase *holes, + ListBase *holes, #endif - BMEdge *e_example, - const bool no_double - ) + BMEdge *e_example, + const bool no_double) { #ifdef USE_BMESH_HOLES BMLoopList *lst, *lst2; @@ -1501,14 +1509,7 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) bmesh_disk_edge_remove(e_new, tv); bmesh_disk_edge_remove(e_new, v_new); - /* remove e from tv's disk cycle */ - bmesh_disk_edge_remove(e, tv); - - /* swap out tv for v_new in e */ - bmesh_edge_swapverts(e, tv, v_new); - - /* add e to v_new's disk cycle */ - bmesh_disk_edge_append(e, v_new); + bmesh_disk_vert_replace(e, v_new, tv); /* add e_new to v_new's disk cycle */ bmesh_disk_edge_append(e_new, v_new); @@ -1673,13 +1674,14 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) * faces with just 2 edges. It is up to the caller to decide what to do with * these faces. */ -BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, - const bool do_del, const bool check_edge_double) +BMEdge *bmesh_jekv( + BMesh *bm, BMEdge *e_kill, BMVert *v_kill, + const bool do_del, const bool check_edge_double) { BMEdge *e_old; BMVert *v_old, *tv; BMLoop *l_kill; - int len, radlen = 0, i; + int radlen = 0, i; bool halt = false; #ifndef NDEBUG bool edok; @@ -1690,10 +1692,8 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, if (BM_vert_in_edge(e_kill, v_kill) == 0) { return NULL; } - - len = bmesh_disk_count(v_kill); - if (len == 2) { + if (bmesh_disk_count_ex(v_kill, 3) == 2) { #ifndef NDEBUG int valence1, valence2; BMLoop *l; @@ -1720,12 +1720,8 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, e_splice = BM_edge_exists(tv, v_old); } - /* remove e_old from v_kill's disk cycle */ - bmesh_disk_edge_remove(e_old, v_kill); - /* relink e_old->v_kill to be e_old->tv */ - bmesh_edge_swapverts(e_old, v_kill, tv); - /* append e_old to tv's disk cycle */ - bmesh_disk_edge_append(e_old, tv); + bmesh_disk_vert_replace(e_old, tv, v_kill); + /* remove e_kill from tv's disk cycle */ bmesh_disk_edge_remove(e_kill, tv); @@ -1809,7 +1805,7 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, if (check_edge_double) { if (e_splice) { /* removes e_splice */ - BM_edge_splice(bm, e_splice, e_old); + BM_edge_splice(bm, e_old, e_splice); } } @@ -1983,27 +1979,38 @@ bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b) BLI_assert(BM_edge_exists(v_a, v_b) == false); if (v_a->e && v_b->e) { - SmallHash visit; BMEdge *e, *e_first; - BLI_smallhash_init(&visit); +#define VERT_VISIT _FLAG_WALK + /* tag 'v_a' */ e = e_first = v_a->e; do { BMVert *v_other = BM_edge_other_vert(e, v_a); - BLI_smallhash_insert(&visit, (uintptr_t)v_other, NULL); + BLI_assert(!BM_ELEM_API_FLAG_TEST(v_other, VERT_VISIT)); + BM_ELEM_API_FLAG_ENABLE(v_other, VERT_VISIT); } while ((e = BM_DISK_EDGE_NEXT(e, v_a)) != e_first); + /* check 'v_b' connects to 'v_a' edges */ e = e_first = v_b->e; do { BMVert *v_other = BM_edge_other_vert(e, v_b); - if (BLI_smallhash_haskey(&visit, (uintptr_t)v_other)) { + if (BM_ELEM_API_FLAG_TEST(v_other, VERT_VISIT)) { is_double = true; break; } } while ((e = BM_DISK_EDGE_NEXT(e, v_b)) != e_first); - BLI_smallhash_release(&visit); + /* cleanup */ + e = e_first = v_a->e; + do { + BMVert *v_other = BM_edge_other_vert(e, v_a); + BLI_assert(BM_ELEM_API_FLAG_TEST(v_other, VERT_VISIT)); + BM_ELEM_API_FLAG_DISABLE(v_other, VERT_VISIT); + } while ((e = BM_DISK_EDGE_NEXT(e, v_a)) != e_first); + +#undef VERT_VISIT + } return is_double; @@ -2012,7 +2019,8 @@ bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b) /** * \brief Splice Vert * - * Merges two verts into one (\a v into \a vtarget). + * Merges two verts into one + * (\a v_src into \a v_dst, removing \a v_src). * * \return Success * @@ -2020,49 +2028,42 @@ bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b) * where \a v and \a vtarget are connected by an edge * (assert checks for this case). */ -bool BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target) +bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src) { BMEdge *e; /* verts already spliced */ - if (v == v_target) { + if (v_src == v_dst) { return false; } - BLI_assert(BM_vert_pair_share_face_check(v, v_target) == false); + BLI_assert(BM_vert_pair_share_face_check(v_src, v_dst) == false); - /* move all the edges from v's disk to vtarget's disk */ - while ((e = v->e)) { - - /* loop */ - BMLoop *l_first; - if ((l_first = e->l)) { - BMLoop *l_iter = l_first; - do { - if (l_iter->v == v) { - l_iter->v = v_target; - } - /* else if (l_iter->prev->v == v) {...} - * (this case will be handled by a different edge) */ - } while ((l_iter = l_iter->radial_next) != l_first); - } - - /* disk */ - bmesh_disk_edge_remove(e, v); - bmesh_edge_swapverts(e, v, v_target); - bmesh_disk_edge_append(e, v_target); + /* move all the edges from 'v_src' disk to 'v_dst' */ + while ((e = v_src->e)) { + bmesh_edge_vert_swap(e, v_dst, v_src); BLI_assert(e->v1 != e->v2); } - BM_CHECK_ELEMENT(v); - BM_CHECK_ELEMENT(v_target); + BM_CHECK_ELEMENT(v_src); + BM_CHECK_ELEMENT(v_dst); - /* v is unused now, and can be killed */ - BM_vert_kill(bm, v); + /* 'v_src' is unused now, and can be killed */ + BM_vert_kill(bm, v_src); return true; } + +/** \name BM_vert_separate, bmesh_vert_separate and friends + * \{ */ + +/* BM_edge_face_count(e) >= 1 */ +BLI_INLINE bool bm_edge_supports_separate(const BMEdge *e) +{ + return (e->l && e->l->radial_next != e->l); +} + /** * \brief Separate Vert * @@ -2074,167 +2075,252 @@ bool BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target) * * \return Success */ -void bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, - const bool copy_select) +void bmesh_vert_separate( + BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, + const bool copy_select) { - const int v_edgetot = BM_vert_face_count(v); - BMEdge **stack = BLI_array_alloca(stack, v_edgetot); - STACK_DECLARE(stack); + int v_edges_num = 0; - SmallHash visithash; - BMVert **verts = NULL; - BMIter eiter, liter; - BMLoop *l; - BMEdge *e; - int i, maxindex; - BMLoop *l_new; + /* Detailed notes on array use since this is stack memory, we have to be careful */ - BLI_smallhash_init_ex(&visithash, v_edgetot); + /* newly created vertices, only use when 'r_vout' is set + * (total size will be number of fans) */ + BLI_SMALLSTACK_DECLARE(verts_new, BMVert *); + /* fill with edges from the face-fan, clearing on completion + * (total size will be max fan edge count) */ + BLI_SMALLSTACK_DECLARE(edges, BMEdge *); + /* temp store edges to walk over when filling 'edges', + * (total size will be max radial edges of any edge) */ + BLI_SMALLSTACK_DECLARE(edges_search, BMEdge *); - STACK_INIT(stack, v_edgetot); + /* number of resulting verts, include self */ + int verts_num = 1; + /* track the total number of edges handled, so we know when we've found the last fan */ + int edges_found = 0; - maxindex = 0; - BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { - if (BLI_smallhash_haskey(&visithash, (uintptr_t)e)) { - continue; - } +#define EDGE_VISIT _FLAG_WALK + + /* count and flag at once */ + if (v->e) { + BMEdge *e_first, *e_iter; + e_iter = e_first = v->e; + do { + v_edges_num += 1; + BLI_assert(!BM_ELEM_API_FLAG_TEST(e_iter, EDGE_VISIT)); + BM_ELEM_API_FLAG_ENABLE(e_iter, EDGE_VISIT); + } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); + } + + while (true) { /* Considering only edges and faces incident on vertex v, walk - * the edges & faces and assign an index to each connected set */ - BLI_smallhash_insert(&visithash, (uintptr_t)e, SET_INT_IN_POINTER(maxindex)); + * the edges & collect in the 'edges' list for splitting */ + + BMEdge *e = v->e; + BM_ELEM_API_FLAG_DISABLE(e, EDGE_VISIT); + do { + BLI_assert(!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT)); + BLI_SMALLSTACK_PUSH(edges, e); + edges_found += 1; + if (e->l) { BMLoop *l_iter, *l_first; l_iter = l_first = e->l; do { - l_new = (l_iter->v == v) ? l_iter->prev : l_iter->next; - BLI_assert(BM_vert_in_edge(l_new->e, v)); - if (!BLI_smallhash_haskey(&visithash, (uintptr_t)l_new->e)) { - BLI_smallhash_insert(&visithash, (uintptr_t)l_new->e, SET_INT_IN_POINTER(maxindex)); - STACK_PUSH(stack, l_new->e); + BMLoop *l_adjacent = (l_iter->v == v) ? l_iter->prev : l_iter->next; + BLI_assert(BM_vert_in_edge(l_adjacent->e, v)); + if (BM_ELEM_API_FLAG_TEST(l_adjacent->e, EDGE_VISIT)) { + BM_ELEM_API_FLAG_DISABLE(l_adjacent->e, EDGE_VISIT); + BLI_SMALLSTACK_PUSH(edges_search, l_adjacent->e); } } while ((l_iter = l_iter->radial_next) != l_first); } - } while ((e = STACK_POP(stack))); + } while ((e = BLI_SMALLSTACK_POP(edges_search))); - maxindex++; - } + /* now we have all edges connected to 'v->e' */ - /* Make enough verts to split v for each group */ - if (r_vout != NULL) { - verts = MEM_callocN(sizeof(BMVert *) * maxindex, __func__); - } - else { - verts = BLI_array_alloca(verts, maxindex); - } + BLI_assert(edges_found <= v_edges_num); - verts[0] = v; - for (i = 1; i < maxindex; i++) { - verts[i] = BM_vert_create(bm, v->co, v, BM_CREATE_NOP); - if (copy_select) { - BM_elem_select_copy(bm, bm, verts[i], v); - } - } - - /* Replace v with the new verts in each group */ -#if 0 - BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { - /* call first since its faster then a hash lookup */ - if (l->v != v) { - continue; - } - i = GET_INT_FROM_POINTER(BLI_ghash_lookup(visithash, l->e)); - if (i == 0) { - continue; + if (edges_found == v_edges_num) { + /* We're done! The remaining edges in 'edges' form the last fan, + * which can be left as is. + * if 'edges' were alloc'd it'd be freed here. */ + break; } + else { + BMVert *v_new; - /* Loops here should always refer to an edge that has v as an - * endpoint. For each appearance of this vert in a face, there - * will actually be two iterations: one for the loop heading - * towards vertex v, and another for the loop heading out from - * vertex v. Only need to swap the vertex on one of those times, - * on the outgoing loop. */ + v_new = BM_vert_create(bm, v->co, v, BM_CREATE_NOP); + if (copy_select) { + BM_elem_select_copy(bm, bm, v_new, v); + } - /* XXX - because this clobbers the iterator, this *whole* block is commented, see below */ - l->v = verts[i]; - } -#else - /* note: this is the same as the commented code above *except* that it doesn't break iterator - * by modifying data it loops over [#30632], this re-uses the 'stack' variable which is a bit - * bad practice but save alloc'ing a new array - note, the comment above is useful, keep it - * if you are tidying up code - campbell */ - STACK_INIT(stack, v_edgetot); - BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { - if (l->v == v) { - STACK_PUSH(stack, (BMEdge *)l); - } - } - while ((l = (BMLoop *)(STACK_POP(stack)))) { - if ((i = GET_INT_FROM_POINTER(BLI_smallhash_lookup(&visithash, (uintptr_t)l->e)))) { - l->v = verts[i]; - } - } -#endif + while ((e = BLI_SMALLSTACK_POP(edges))) { + bmesh_edge_vert_swap(e, v_new, v); + } - BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { - i = GET_INT_FROM_POINTER(BLI_smallhash_lookup(&visithash, (uintptr_t)e)); - if (i == 0) { - continue; + if (r_vout) { + BLI_SMALLSTACK_PUSH(verts_new, v_new); + } + verts_num += 1; } - - BLI_assert(e->v1 == v || e->v2 == v); - bmesh_disk_edge_remove(e, v); - bmesh_edge_swapverts(e, v, verts[i]); - bmesh_disk_edge_append(e, verts[i]); } - BLI_smallhash_release(&visithash); +#undef EDGE_VISIT - for (i = 0; i < maxindex; i++) { - BM_CHECK_ELEMENT(verts[i]); - } + /* flags are clean now, handle return values */ if (r_vout_len != NULL) { - *r_vout_len = maxindex; + *r_vout_len = verts_num; } if (r_vout != NULL) { + BMVert **verts; + + verts = MEM_mallocN(sizeof(BMVert *) * verts_num, __func__); *r_vout = verts; + + verts[0] = v; + BLI_SMALLSTACK_AS_TABLE(verts_new, &verts[1]); } } /** + * Utility function for #BM_vert_separate + * + * Takes a list of edges, which have been split from their original. + * + * Any edges which failed to split off in #bmesh_vert_separate will be merged back into the original edge. + * + * \param edges_seperate + * A list-of-lists, each list is from a single original edge (the first edge is the original), + * Check for duplicates (not just with the first) but between all. + * This is O(n2) but radial edges are very rarely >2 and almost never >~10. + * + * \note typically its best to avoid createing the data in the first place, + * but inspecting all loops connectivity is quite involved. + * + * \note this function looks like it could become slow, + * but in common cases its only going to iterate a few times. + */ +static void bmesh_vert_separate__cleanup(BMesh *bm, LinkNode *edges_separate) +{ + do { + LinkNode *n_orig = edges_separate->link; + do { + BMEdge *e_orig = n_orig->link; + LinkNode *n_step = n_orig->next; + LinkNode *n_prev = n_orig; + do { + BMEdge *e = n_step->link; + BLI_assert(e != e_orig); + if ((e->v1 == e_orig->v1) && (e->v2 == e_orig->v2)) { + BM_edge_splice(bm, e_orig, e); + n_prev->next = n_step->next; + n_step = n_prev; + } + } while ((n_prev = n_step), + (n_step = n_step->next)); + + } while ((n_orig = n_orig->next) && n_orig->next); + } while ((edges_separate = edges_separate->next)); +} + +/** * High level function which wraps both #bmesh_vert_separate and #bmesh_edge_separate */ -void BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, - BMEdge **e_in, int e_in_len) +void BM_vert_separate( + BMesh *bm, BMVert *v, + BMEdge **e_in, int e_in_len, + const bool copy_select, + BMVert ***r_vout, int *r_vout_len) { + LinkNode *edges_separate = NULL; int i; for (i = 0; i < e_in_len; i++) { BMEdge *e = e_in[i]; - if (e->l && BM_vert_in_edge(e, v)) { - bmesh_edge_separate(bm, e, e->l, false); + if (bm_edge_supports_separate(e)) { + LinkNode *edges_orig = NULL; + do { + BMLoop *l_sep = e->l; + bmesh_edge_separate(bm, e, l_sep, copy_select); + BLI_linklist_prepend_alloca(&edges_orig, l_sep->e); + BLI_assert(e != l_sep->e); + } while (bm_edge_supports_separate(e)); + BLI_linklist_prepend_alloca(&edges_orig, e); + BLI_linklist_prepend_alloca(&edges_separate, edges_orig); } } - bmesh_vert_separate(bm, v, r_vout, r_vout_len, false); + bmesh_vert_separate(bm, v, r_vout, r_vout_len, copy_select); + + if (edges_separate) { + bmesh_vert_separate__cleanup(bm, edges_separate); + } } + +/** + * A version of #BM_vert_separate which takes a flag. + */ +void BM_vert_separate_hflag( + BMesh *bm, BMVert *v, + const char hflag, + const bool copy_select, + BMVert ***r_vout, int *r_vout_len) +{ + LinkNode *edges_separate = NULL; + BMEdge *e_iter, *e_first; + + e_iter = e_first = v->e; + do { + if (BM_elem_flag_test(e_iter, hflag)) { + BMEdge *e = e_iter; + if (bm_edge_supports_separate(e)) { + LinkNode *edges_orig = NULL; + do { + BMLoop *l_sep = e->l; + bmesh_edge_separate(bm, e, l_sep, copy_select); + /* trick to avoid looping over seperated edges */ + if (edges_separate == NULL && edges_orig == NULL) { + e_first = l_sep->e; + } + BLI_linklist_prepend_alloca(&edges_orig, l_sep->e); + BLI_assert(e != l_sep->e); + } while (bm_edge_supports_separate(e)); + BLI_linklist_prepend_alloca(&edges_orig, e); + BLI_linklist_prepend_alloca(&edges_separate, edges_orig); + } + } + } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first); + + bmesh_vert_separate(bm, v, r_vout, r_vout_len, copy_select); + + if (edges_separate) { + bmesh_vert_separate__cleanup(bm, edges_separate); + } +} + +/** \} */ + + /** * \brief Splice Edge * * Splice two unique edges which share the same two vertices into one edge. + * (\a e_src into \a e_dst, removing e_src). * * \return Success * * \note Edges must already have the same vertices. */ -bool BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target) +bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src) { BMLoop *l; - if (!BM_vert_in_edge(e, e_target->v1) || !BM_vert_in_edge(e, e_target->v2)) { + if (!BM_vert_in_edge(e_src, e_dst->v1) || !BM_vert_in_edge(e_src, e_dst->v2)) { /* not the same vertices can't splice */ /* the caller should really make sure this doesn't happen ever @@ -2244,21 +2330,21 @@ bool BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target) return false; } - while (e->l) { - l = e->l; - BLI_assert(BM_vert_in_edge(e_target, l->v)); - BLI_assert(BM_vert_in_edge(e_target, l->next->v)); - bmesh_radial_loop_remove(l, e); - bmesh_radial_append(e_target, l); + while (e_src->l) { + l = e_src->l; + BLI_assert(BM_vert_in_edge(e_dst, l->v)); + BLI_assert(BM_vert_in_edge(e_dst, l->next->v)); + bmesh_radial_loop_remove(l, e_src); + bmesh_radial_append(e_dst, l); } - BLI_assert(bmesh_radial_length(e->l) == 0); + BLI_assert(bmesh_radial_length(e_src->l) == 0); - BM_CHECK_ELEMENT(e); - BM_CHECK_ELEMENT(e_target); + BM_CHECK_ELEMENT(e_src); + BM_CHECK_ELEMENT(e_dst); /* removes from disks too */ - BM_edge_kill(bm, e); + BM_edge_kill(bm, e_src); return true; } @@ -2274,8 +2360,9 @@ bool BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target) * \note Does nothing if \a l_sep is already the only loop in the * edge radial. */ -void bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep, - const bool copy_select) +void bmesh_edge_separate( + BMesh *bm, BMEdge *e, BMLoop *l_sep, + const bool copy_select) { BMEdge *e_new; #ifndef NDEBUG @@ -2286,7 +2373,7 @@ void bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep, BLI_assert(e->l); if (BM_edge_is_boundary(e)) { - /* no cut required */ + BLI_assert(0); /* no cut required */ return; } @@ -2319,72 +2406,245 @@ void bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep, */ BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep) { - BMVert **vtar; - int len, i; BMVert *v_new = NULL; BMVert *v_sep = l_sep->v; + BMEdge *e_iter; + BMEdge *edges[2]; + int i; /* peel the face from the edge radials on both sides of the * loop vert, disconnecting the face from its fan */ bmesh_edge_separate(bm, l_sep->e, l_sep, false); bmesh_edge_separate(bm, l_sep->prev->e, l_sep->prev, false); - if (bmesh_disk_count(v_sep) == 2) { - /* If there are still only two edges out of v_sep, then - * this whole URMV was just a no-op, so exit now. */ + /* do inline, below */ +#if 0 + if (BM_vert_edge_count_is_equal(v_sep, 2)) { return v_sep; } +#endif - /* Update the disk start, so that v->e points to an edge - * not touching the split loop. This is so that BM_vert_split - * will leave the original v_sep on some *other* fan (not the - * one-face fan that holds the unglue face). */ - while (v_sep->e == l_sep->e || v_sep->e == l_sep->prev->e) { - v_sep->e = bmesh_disk_edge_next(v_sep->e, v_sep); + /* Search for an edge unattached to this loop */ + e_iter = v_sep->e; + while (!ELEM(e_iter, l_sep->e, l_sep->prev->e)) { + e_iter = bmesh_disk_edge_next(e_iter, v_sep); + + /* We've come back around to the initial edge, all touch this loop. + * If there are still only two edges out of v_sep, + * then this whole URMV was just a no-op, so exit now. */ + if (e_iter == v_sep->e) { + BLI_assert(BM_vert_edge_count_is_equal(v_sep, 2)); + return v_sep; + } } - /* Split all fans connected to the vert, duplicating it for - * each fans. */ - bmesh_vert_separate(bm, v_sep, &vtar, &len, false); + v_sep->e = l_sep->e; - /* There should have been at least two fans cut apart here, - * otherwise the early exit would have kicked in. */ - BLI_assert(len >= 2); + v_new = BM_vert_create(bm, v_sep->co, v_sep, BM_CREATE_NOP); - v_new = l_sep->v; + edges[0] = l_sep->e; + edges[1] = l_sep->prev->e; - /* Desired result here is that a new vert should always be - * created for the unglue face. This is so we can glue any - * extras back into the original vert. */ - BLI_assert(v_new != v_sep); - BLI_assert(v_sep == vtar[0]); + for (i = 0; i < ARRAY_SIZE(edges); i++) { + BMEdge *e = edges[i]; + bmesh_edge_vert_swap(e, v_new, v_sep); + } - /* If there are more than two verts as a result, glue together - * all the verts except the one this URMV intended to create */ - if (len > 2) { - for (i = 0; i < len; i++) { - if (vtar[i] == v_new) { - break; + BLI_assert(v_sep != l_sep->v); + BLI_assert(v_sep->e != l_sep->v->e); + + BM_CHECK_ELEMENT(l_sep); + BM_CHECK_ELEMENT(v_sep); + BM_CHECK_ELEMENT(edges[0]); + BM_CHECK_ELEMENT(edges[1]); + BM_CHECK_ELEMENT(v_new); + + return v_new; +} + +/** + * A version of #bmesh_urmv_loop that disconnects multiple loops at once. + * + * Handles the task of finding fans boundaris. + */ +BMVert *bmesh_urmv_loop_multi( + BMesh *bm, BMLoop **larr, int larr_len) +{ + BMVert *v_sep = larr[0]->v; + BMVert *v_new; + int i; + bool is_mixed_any = false; + + BLI_SMALLSTACK_DECLARE(edges, BMEdge *); + +#define LOOP_VISIT _FLAG_WALK +#define EDGE_VISIT _FLAG_WALK + + for (i = 0; i < larr_len; i++) { + BMLoop *l_sep = larr[i]; + + /* all must be from the same vert! */ + BLI_assert(v_sep == l_sep->v); + + BLI_assert(!BM_ELEM_API_FLAG_TEST(l_sep, LOOP_VISIT)); + BM_ELEM_API_FLAG_ENABLE(l_sep, LOOP_VISIT); + + /* weak! but it makes it simpler to check for edges to split + * while doing a radial loop (where loops may be adjacent) */ + BM_ELEM_API_FLAG_ENABLE(l_sep->next, LOOP_VISIT); + BM_ELEM_API_FLAG_ENABLE(l_sep->prev, LOOP_VISIT); + } + + for (i = 0; i < larr_len; i++) { + BMLoop *l_sep = larr[i]; + + BMLoop *loop_pair[2] = {l_sep, l_sep->prev}; + int j; + for (j = 0; j < ARRAY_SIZE(loop_pair); j++) { + BMEdge *e = loop_pair[j]->e; + if (!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT)) { + BMLoop *l_iter, *l_first; + bool is_mixed = false; + + BM_ELEM_API_FLAG_ENABLE(e, EDGE_VISIT); + + l_iter = l_first = e->l; + do { + if (!BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) { + is_mixed = true; + is_mixed_any = true; + break; + } + } while ((l_iter = l_iter->radial_next) != l_first); + + if (is_mixed) { + /* ensure the first loop is one we don't own so we can do a quick check below + * on the edge's loop-flag to see if the edge is mixed or not. */ + e->l = l_iter; + } + BLI_SMALLSTACK_PUSH(edges, e); } } + } - if (i != len) { - /* Swap the single vert that was needed for the - * unglue into the last array slot */ - SWAP(BMVert *, vtar[i], vtar[len - 1]); + if (is_mixed_any == false) { + /* all loops in 'larr' are the soul owners of their edges. + * nothing to split away from, this is a no-op */ + v_new = v_sep; + } + else { + BMEdge *e; + + BLI_assert(!BLI_SMALLSTACK_IS_EMPTY(edges)); + + v_new = BM_vert_create(bm, v_sep->co, v_sep, BM_CREATE_NOP); + while ((e = BLI_SMALLSTACK_POP(edges))) { + BMLoop *l_iter, *l_first, *l_next; + BMEdge *e_new; + + /* disable so copied edge isn't left dirty (loop edges are cleared last too) */ + BM_ELEM_API_FLAG_DISABLE(e, EDGE_VISIT); + + if (!BM_ELEM_API_FLAG_TEST(e->l, LOOP_VISIT)) { + /* edge has some loops owned by us, some owned by other loops */ + BMVert *e_new_v_pair[2]; + + if (e->v1 == v_sep) { + e_new_v_pair[0] = v_new; + e_new_v_pair[1] = e->v2; + } + else { + BLI_assert(v_sep == e->v2); + e_new_v_pair[0] = e->v1; + e_new_v_pair[1] = v_new; + } + + e_new = BM_edge_create(bm, UNPACK2(e_new_v_pair), e, BM_CREATE_NOP); - /* And then glue the rest back together */ - for (i = 1; i < len - 1; i++) { - BM_vert_splice(bm, vtar[i], vtar[0]); + /* now moved all loops from 'larr' to this newly created edge */ + l_iter = l_first = e->l; + do { + l_next = l_iter->radial_next; + if (BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) { + bmesh_radial_loop_remove(l_iter, e); + bmesh_radial_append(e_new, l_iter); + l_iter->e = e_new; + } + } while ((l_iter = l_next) != l_first); } + else { + /* we own the edge entirely, replace the vert */ + bmesh_disk_vert_replace(e, v_new, v_sep); + } + + /* loop vert is handled last! */ } } - MEM_freeN(vtar); + for (i = 0; i < larr_len; i++) { + BMLoop *l_sep = larr[i]; + + l_sep->v = v_new; + + BLI_assert(BM_ELEM_API_FLAG_TEST(l_sep, LOOP_VISIT)); + BLI_assert(BM_ELEM_API_FLAG_TEST(l_sep->prev, LOOP_VISIT)); + BLI_assert(BM_ELEM_API_FLAG_TEST(l_sep->next, LOOP_VISIT)); + BM_ELEM_API_FLAG_DISABLE(l_sep, LOOP_VISIT); + BM_ELEM_API_FLAG_DISABLE(l_sep->prev, LOOP_VISIT); + BM_ELEM_API_FLAG_DISABLE(l_sep->next, LOOP_VISIT); + + + BM_ELEM_API_FLAG_DISABLE(l_sep->prev->e, EDGE_VISIT); + BM_ELEM_API_FLAG_DISABLE(l_sep->e, EDGE_VISIT); + } + +#undef LOOP_VISIT +#undef EDGE_VISIT return v_new; } +static void bmesh_edge_vert_swap__recursive(BMEdge *e, BMVert *v_dst, BMVert *v_src) +{ + BMLoop *l_iter, *l_first; + + BLI_assert(ELEM(v_src, e->v1, e->v2)); + bmesh_disk_vert_replace(e, v_dst, v_src); + + l_iter = l_first = e->l; + do { + if (l_iter->v == v_src) { + l_iter->v = v_dst; + if (BM_vert_in_edge(l_iter->prev->e, v_src)) { + bmesh_edge_vert_swap__recursive(l_iter->prev->e, v_dst, v_src); + } + } + else if (l_iter->next->v == v_src) { + l_iter->next->v = v_dst; + if (BM_vert_in_edge(l_iter->next->e, v_src)) { + bmesh_edge_vert_swap__recursive(l_iter->next->e, v_dst, v_src); + } + } + else { + BLI_assert(l_iter->prev->v != v_src); + } + } while ((l_iter = l_iter->radial_next) != l_first); +} + +/** + * This function assumes l_sep is apart of a larger fan which has already been + * isolated by calling bmesh_edge_separate to segragate it radially. + */ +BMVert *bmesh_urmv_loop_region(BMesh *bm, BMLoop *l_sep) +{ + BMVert *v_new = BM_vert_create(bm, l_sep->v->co, l_sep->v, BM_CREATE_NOP); + /* passing either 'l_sep->e', 'l_sep->prev->e' will work */ + bmesh_edge_vert_swap__recursive(l_sep->e, v_new, l_sep->v); + BLI_assert(l_sep->v == v_new); + return v_new; +} + + /** * \brief Unglue Region Make Vert (URMV) * diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h index ab847fc82eb..2b100eb7b8d 100644 --- a/source/blender/bmesh/intern/bmesh_core.h +++ b/source/blender/bmesh/intern/bmesh_core.h @@ -27,8 +27,9 @@ * \ingroup bmesh */ -BMFace *BM_face_copy(BMesh *bm_dst, BMesh *bm_src, BMFace *f, - const bool copy_verts, const bool copy_edges); +BMFace *BM_face_copy( + BMesh *bm_dst, BMesh *bm_src, BMFace *f, + const bool copy_verts, const bool copy_edges); typedef enum eBMCreateFlag { BM_CREATE_NOP = 0, @@ -40,15 +41,19 @@ typedef enum eBMCreateFlag { BM_CREATE_SKIP_CD = (1 << 2), } eBMCreateFlag; -BMVert *BM_vert_create(BMesh *bm, const float co[3], - const BMVert *v_example, const eBMCreateFlag create_flag); -BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, - const BMEdge *e_example, const eBMCreateFlag create_flag); -BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, - const BMFace *f_example, const eBMCreateFlag create_flag); -BMFace *BM_face_create_verts(BMesh *bm, BMVert **verts, const int len, - const BMFace *f_example, const eBMCreateFlag create_flag, - const bool create_edges); +BMVert *BM_vert_create( + BMesh *bm, const float co[3], + const BMVert *v_example, const eBMCreateFlag create_flag); +BMEdge *BM_edge_create( + BMesh *bm, BMVert *v1, BMVert *v2, + const BMEdge *e_example, const eBMCreateFlag create_flag); +BMFace *BM_face_create( + BMesh *bm, BMVert **verts, BMEdge **edges, const int len, + const BMFace *f_example, const eBMCreateFlag create_flag); +BMFace *BM_face_create_verts( + BMesh *bm, BMVert **verts, const int len, + const BMFace *f_example, const eBMCreateFlag create_flag, + const bool create_edges); void BM_face_edges_kill(BMesh *bm, BMFace *f); void BM_face_verts_kill(BMesh *bm, BMFace *f); @@ -57,25 +62,32 @@ void BM_face_kill(BMesh *bm, BMFace *f); void BM_edge_kill(BMesh *bm, BMEdge *e); void BM_vert_kill(BMesh *bm, BMVert *v); -void bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep, - const bool copy_select); -bool BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target); -bool BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target); +void bmesh_edge_separate( + BMesh *bm, BMEdge *e, BMLoop *l_sep, + const bool copy_select); +bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src); +bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src); bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b); -void bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, - const bool copy_select); +void bmesh_vert_separate( + BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, + const bool copy_select); bool bmesh_loop_reverse(BMesh *bm, BMFace *f); BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del); -void BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, - BMEdge **e_in, int e_in_len); +void BM_vert_separate( + BMesh *bm, BMVert *v, BMEdge **e_in, int e_in_len, const bool copy_select, + BMVert ***r_vout, int *r_vout_len); +void BM_vert_separate_hflag( + BMesh *bm, BMVert *v, const char hflag, const bool copy_select, + BMVert ***r_vout, int *r_vout_len); /* EULER API - For modifying structure */ -BMFace *bmesh_sfme(BMesh *bm, BMFace *f, - BMLoop *l1, BMLoop *l2, - BMLoop **r_l, +BMFace *bmesh_sfme( + BMesh *bm, BMFace *f, + BMLoop *l1, BMLoop *l2, + BMLoop **r_l, #ifdef USE_BMESH_HOLES ListBase *holes, #endif @@ -84,11 +96,15 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, ); BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e); -BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, - const bool do_del, const bool check_edge_splice); +BMEdge *bmesh_jekv( + BMesh *bm, BMEdge *e_kill, BMVert *v_kill, + const bool do_del, const bool check_edge_splice); BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e); BMVert *bmesh_urmv(BMesh *bm, BMFace *f_sep, BMVert *v_sep); BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep); +BMVert *bmesh_urmv_loop_multi( + BMesh *bm, BMLoop **larr, int larr_len); +BMVert *bmesh_urmv_loop_region(BMesh *bm, BMLoop *l_sep); void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b); diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.c b/source/blender/bmesh/intern/bmesh_edgeloop.c index aa1f511e8d7..eaa070151a6 100644 --- a/source/blender/bmesh/intern/bmesh_edgeloop.c +++ b/source/blender/bmesh/intern/bmesh_edgeloop.c @@ -52,8 +52,9 @@ typedef struct BMEdgeLoopStore { /* -------------------------------------------------------------------- */ /* BM_mesh_edgeloops_find & Util Functions */ -static int bm_vert_other_tag(BMVert *v, BMVert *v_prev, - BMEdge **r_e) +static int bm_vert_other_tag( + BMVert *v, BMVert *v_prev, + BMEdge **r_e) { BMIter iter; BMEdge *e, *e_next = NULL; @@ -125,8 +126,9 @@ static bool bm_loop_build(BMEdgeLoopStore *el_store, BMVert *v_prev, BMVert *v, /** * \return listbase of listbases, each linking to a vertex. */ -int BM_mesh_edgeloops_find(BMesh *bm, ListBase *r_eloops, - bool (*test_fn)(BMEdge *, void *user_data), void *user_data) +int BM_mesh_edgeloops_find( + BMesh *bm, ListBase *r_eloops, + bool (*test_fn)(BMEdge *, void *user_data), void *user_data) { BMIter iter; BMEdge *e; @@ -183,8 +185,9 @@ struct VertStep { BMVert *v; }; -static void vs_add(BLI_mempool *vs_pool, ListBase *lb, - BMVert *v, BMEdge *e_prev, const int iter_tot) +static void vs_add( + BLI_mempool *vs_pool, ListBase *lb, + BMVert *v, BMEdge *e_prev, const int iter_tot) { struct VertStep *vs_new = BLI_mempool_alloc(vs_pool); vs_new->v = v; @@ -256,9 +259,10 @@ static bool bm_loop_path_build_step(BLI_mempool *vs_pool, ListBase *lb, const in return (BLI_listbase_is_empty(lb) == false); } -bool BM_mesh_edgeloops_find_path(BMesh *bm, ListBase *r_eloops, - bool (*test_fn)(BMEdge *, void *user_data), void *user_data, - BMVert *v_src, BMVert *v_dst) +bool BM_mesh_edgeloops_find_path( + BMesh *bm, ListBase *r_eloops, + bool (*test_fn)(BMEdge *, void *user_data), void *user_data, + BMVert *v_src, BMVert *v_dst) { BMIter iter; BMEdge *e; diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.h b/source/blender/bmesh/intern/bmesh_edgeloop.h index 527dba120e1..5df4ee5848e 100644 --- a/source/blender/bmesh/intern/bmesh_edgeloop.h +++ b/source/blender/bmesh/intern/bmesh_edgeloop.h @@ -32,17 +32,20 @@ struct ListBase; struct BMEdgeLoopStore; /* multiple edgeloops (ListBase) */ -int BM_mesh_edgeloops_find(BMesh *bm, struct ListBase *r_lb, - bool (*test_fn)(BMEdge *, void *user_data), void *user_data); -bool BM_mesh_edgeloops_find_path(BMesh *bm, ListBase *r_eloops, - bool (*test_fn)(BMEdge *, void *user_data), void *user_data, - BMVert *v_src, BMVert *v_dst); +int BM_mesh_edgeloops_find( + BMesh *bm, struct ListBase *r_lb, + bool (*test_fn)(BMEdge *, void *user_data), void *user_data); +bool BM_mesh_edgeloops_find_path( + BMesh *bm, ListBase *r_eloops, + bool (*test_fn)(BMEdge *, void *user_data), void *user_data, + BMVert *v_src, BMVert *v_dst); void BM_mesh_edgeloops_free(struct ListBase *eloops); void BM_mesh_edgeloops_calc_center(BMesh *bm, struct ListBase *eloops); void BM_mesh_edgeloops_calc_normal(BMesh *bm, struct ListBase *eloops); -void BM_mesh_edgeloops_calc_normal_aligned(BMesh *bm, struct ListBase *eloops, - const float no_align[3]); +void BM_mesh_edgeloops_calc_normal_aligned( + BMesh *bm, struct ListBase *eloops, + const float no_align[3]); void BM_mesh_edgeloops_calc_order(BMesh *UNUSED(bm), ListBase *eloops, const bool use_normals); @@ -59,8 +62,9 @@ const float *BM_edgeloop_center_get(struct BMEdgeLoopStore *el_store); void BM_edgeloop_edges_get(struct BMEdgeLoopStore *el_store, BMEdge **e_arr); void BM_edgeloop_calc_center(BMesh *bm, struct BMEdgeLoopStore *el_store); bool BM_edgeloop_calc_normal(BMesh *bm, struct BMEdgeLoopStore *el_store); -bool BM_edgeloop_calc_normal_aligned(BMesh *bm, struct BMEdgeLoopStore *el_store, - const float no_align[3]); +bool BM_edgeloop_calc_normal_aligned( + BMesh *bm, struct BMEdgeLoopStore *el_store, + const float no_align[3]); void BM_edgeloop_flip(BMesh *bm, struct BMEdgeLoopStore *el_store); void BM_edgeloop_expand(BMesh *bm, struct BMEdgeLoopStore *el_store, int el_store_len); diff --git a/source/blender/bmesh/intern/bmesh_inline.h b/source/blender/bmesh/intern/bmesh_inline.h index 96b2cd396a2..4b55060875b 100644 --- a/source/blender/bmesh/intern/bmesh_inline.h +++ b/source/blender/bmesh/intern/bmesh_inline.h @@ -39,11 +39,13 @@ #define BM_elem_flag_merge( ele_a, ele_b) _bm_elem_flag_merge (&(ele_a)->head, &(ele_b)->head) #define BM_elem_flag_merge_into(ele, ele_a, ele_b)_bm_elem_flag_merge_into (&(ele)->head, &(ele_a)->head, &(ele_b)->head) +ATTR_WARN_UNUSED_RESULT BLI_INLINE char _bm_elem_flag_test(const BMHeader *head, const char hflag) { return head->hflag & hflag; } +ATTR_WARN_UNUSED_RESULT BLI_INLINE bool _bm_elem_flag_test_bool(const BMHeader *head, const char hflag) { return (head->hflag & hflag) != 0; @@ -116,6 +118,7 @@ BLI_INLINE void _bm_elem_index_set(BMHeader *head, const int index) head->index = index; } +ATTR_WARN_UNUSED_RESULT BLI_INLINE int _bm_elem_index_get(const BMHeader *head) { return head->index; diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c index 4ca0da53af6..e53e8ec0e4d 100644 --- a/source/blender/bmesh/intern/bmesh_interp.c +++ b/source/blender/bmesh/intern/bmesh_interp.c @@ -241,8 +241,9 @@ void BM_face_interp_from_face(BMesh *bm, BMFace *f_dst, const BMFace *f_src, con * y * </pre> */ -static int compute_mdisp_quad(BMLoop *l, float v1[3], float v2[3], float v3[3], float v4[3], - float e1[3], float e2[3]) +static int compute_mdisp_quad( + BMLoop *l, float v1[3], float v2[3], float v3[3], float v4[3], + float e1[3], float e2[3]) { float cent[3], n[3], p[3]; @@ -302,9 +303,10 @@ static float quad_coord(const float aa[3], const float bb[3], const float cc[3], return f1; } -static int quad_co(float *x, float *y, - const float v1[3], const float v2[3], const float v3[3], const float v4[3], - const float p[3], const float n[3]) +static int quad_co( + float *r_x, float *r_y, + const float v1[3], const float v2[3], const float v3[3], const float v4[3], + const float p[3], const float n[3]) { float projverts[5][3], n2[3]; float dprojverts[4][3], origin[3] = {0.0f, 0.0f, 0.0f}; @@ -340,14 +342,15 @@ static int quad_co(float *x, float *y, return 0; } - *y = quad_coord(dprojverts[1], dprojverts[0], dprojverts[2], dprojverts[3], 0, 1); - *x = quad_coord(dprojverts[2], dprojverts[1], dprojverts[3], dprojverts[0], 0, 1); + *r_y = quad_coord(dprojverts[1], dprojverts[0], dprojverts[2], dprojverts[3], 0, 1); + *r_x = quad_coord(dprojverts[2], dprojverts[1], dprojverts[3], dprojverts[0], 0, 1); return 1; } -static void mdisp_axis_from_quad(float v1[3], float v2[3], float UNUSED(v3[3]), float v4[3], - float axis_x[3], float axis_y[3]) +static void mdisp_axis_from_quad( + float v1[3], float v2[3], float UNUSED(v3[3]), float v4[3], + float axis_x[3], float axis_y[3]) { sub_v3_v3v3(axis_x, v4, v1); sub_v3_v3v3(axis_y, v2, v1); @@ -358,8 +361,9 @@ static void mdisp_axis_from_quad(float v1[3], float v2[3], float UNUSED(v3[3]), /* tl is loop to project onto, l is loop whose internal displacement, co, is being * projected. x and y are location in loop's mdisps grid of point co. */ -static bool mdisp_in_mdispquad(BMLoop *l, BMLoop *tl, float p[3], float *x, float *y, - int res, float axis_x[3], float axis_y[3]) +static bool mdisp_in_mdispquad( + BMLoop *l, BMLoop *tl, float p[3], float *x, float *y, + int res, float axis_x[3], float axis_y[3]) { float v1[3], v2[3], c[3], v3[3], v4[3], e1[3], e2[3]; float eps = FLT_EPSILON * 4000; @@ -392,8 +396,9 @@ static bool mdisp_in_mdispquad(BMLoop *l, BMLoop *tl, float p[3], float *x, floa return 1; } -static float bm_loop_flip_equotion(float mat[2][2], float b[2], const float target_axis_x[3], const float target_axis_y[3], - const float coord[3], int i, int j) +static float bm_loop_flip_equotion( + float mat[2][2], float b[2], const float target_axis_x[3], const float target_axis_y[3], + const float coord[3], int i, int j) { mat[0][0] = target_axis_x[i]; mat[0][1] = target_axis_y[i]; @@ -405,8 +410,9 @@ static float bm_loop_flip_equotion(float mat[2][2], float b[2], const float targ return mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0]; } -static void bm_loop_flip_disp(const float source_axis_x[3], const float source_axis_y[3], - const float target_axis_x[3], const float target_axis_y[3], float disp[3]) +static void bm_loop_flip_disp( + const float source_axis_x[3], const float source_axis_y[3], + const float target_axis_x[3], const float target_axis_y[3], float disp[3]) { float vx[3], vy[3], coord[3]; float n[3], vec[3]; @@ -453,8 +459,8 @@ static void bm_loop_interp_mdisps(BMesh *bm, BMLoop *l_dst, const BMFace *f_src) /* if no disps data allocate a new grid, the size of the first grid in f_src. */ if (!md_dst->totdisp) { - MDisps *md_src = BM_ELEM_CD_GET_VOID_P(BM_FACE_FIRST_LOOP(f_src), cd_loop_mdisp_offset); - + const MDisps *md_src = BM_ELEM_CD_GET_VOID_P(BM_FACE_FIRST_LOOP(f_src), cd_loop_mdisp_offset); + md_dst->totdisp = md_src->totdisp; md_dst->level = md_src->level; if (md_dst->totdisp) { diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c index 4dc27d75a55..0abf41709a0 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.c +++ b/source/blender/bmesh/intern/bmesh_iterators.c @@ -136,8 +136,9 @@ int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, cons * * Sometimes its convenient to get the iterator as an array. */ -int BMO_iter_as_array(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask, - void **array, const int len) +int BMO_iter_as_array( + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask, + void **array, const int len) { int i = 0; @@ -169,9 +170,10 @@ int BMO_iter_as_array(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_nam * * Caller needs to free the array. */ -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) +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; @@ -212,10 +214,11 @@ void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len, } } -void *BMO_iter_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask, - int *r_len, - /* optional args to avoid an alloc (normally stack array) */ - void **stack_array, int stack_array_size) +void *BMO_iter_as_arrayN( + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask, + int *r_len, + /* optional args to avoid an alloc (normally stack array) */ + void **stack_array, int stack_array_size) { BMOIter iter; BMElem *ele; @@ -273,8 +276,9 @@ int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, cons * * Counts how many flagged / unflagged items are found in this element. */ -int BMO_iter_elem_count_flag(BMesh *bm, const char itype, void *data, - const short oflag, const bool value) +int BMO_iter_elem_count_flag( + BMesh *bm, const char itype, void *data, + const short oflag, const bool value) { BMIter iter; BMElemF *ele; diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h index 49e511bdcb5..c4b184ef8b8 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.h +++ b/source/blender/bmesh/intern/bmesh_iterators.h @@ -197,14 +197,17 @@ typedef struct BMIter { void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index) ATTR_WARN_UNUSED_RESULT; int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len); -void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len, - void **stack_array, int stack_array_size) ATTR_WARN_UNUSED_RESULT; -int BMO_iter_as_array(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask, - void **array, const int len); -void *BMO_iter_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask, - int *r_len, - /* optional args to avoid an alloc (normally stack array) */ - void **stack_array, int stack_array_size); +void *BM_iter_as_arrayN( + BMesh *bm, const char itype, void *data, int *r_len, + void **stack_array, int stack_array_size) ATTR_WARN_UNUSED_RESULT; +int BMO_iter_as_array( + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask, + void **array, const int len); +void *BMO_iter_as_arrayN( + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask, + int *r_len, + /* optional args to avoid an alloc (normally stack array) */ + void **stack_array, int stack_array_size); int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const bool value); int BMO_iter_elem_count_flag(BMesh *bm, const char itype, void *data, const short oflag, const bool value); int BM_iter_mesh_count(const char itype, BMesh *bm); diff --git a/source/blender/bmesh/intern/bmesh_iterators_inline.h b/source/blender/bmesh/intern/bmesh_iterators_inline.h index d46c14bf423..43b054d7845 100644 --- a/source/blender/bmesh/intern/bmesh_iterators_inline.h +++ b/source/blender/bmesh/intern/bmesh_iterators_inline.h @@ -39,6 +39,7 @@ * * Calls an iterators step function to return the next element. */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE void *BM_iter_step(BMIter *iter) { return iter->step(iter); @@ -51,6 +52,7 @@ BLI_INLINE void *BM_iter_step(BMIter *iter) * it with the appropriate function pointers based * upon its type. */ +ATTR_NONNULL(1) BLI_INLINE bool BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *data) { /* int argtype; */ @@ -170,6 +172,7 @@ BLI_INLINE bool BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *da * to return the first element of the iterator. * */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE void *BM_iter_new(BMIter *iter, BMesh *bm, const char itype, void *data) { if (LIKELY(BM_iter_init(iter, bm, itype, data))) { diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c index 8aa64906019..a735f3955fc 100644 --- a/source/blender/bmesh/intern/bmesh_marking.c +++ b/source/blender/bmesh/intern/bmesh_marking.c @@ -626,8 +626,9 @@ void BM_mesh_select_mode_set(BMesh *bm, int selectmode) /** * counts number of elements with flag enabled/disabled */ -static int bm_mesh_flag_count(BMesh *bm, const char htype, const char hflag, - const bool respecthide, const bool test_for_enabled) +static int bm_mesh_flag_count( + BMesh *bm, const char htype, const char hflag, + const bool respecthide, const bool test_for_enabled) { BMElem *ele; BMIter iter; @@ -1013,8 +1014,9 @@ GHash *BM_select_history_map_create(BMesh *bm) return map; } -void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hflag, - const bool respecthide, const bool overwrite, const char hflag_test) +void BM_mesh_elem_hflag_disable_test( + BMesh *bm, const char htype, const char hflag, + const bool respecthide, const bool overwrite, const char hflag_test) { const char iter_types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, @@ -1084,8 +1086,9 @@ void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hfl } } -void BM_mesh_elem_hflag_enable_test(BMesh *bm, const char htype, const char hflag, - const bool respecthide, const bool overwrite, const char hflag_test) +void BM_mesh_elem_hflag_enable_test( + BMesh *bm, const char htype, const char hflag, + const bool respecthide, const bool overwrite, const char hflag_test) { const char iter_types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, @@ -1139,15 +1142,17 @@ void BM_mesh_elem_hflag_enable_test(BMesh *bm, const char htype, const char hfla } } -void BM_mesh_elem_hflag_disable_all(BMesh *bm, const char htype, const char hflag, - const bool respecthide) +void BM_mesh_elem_hflag_disable_all( + BMesh *bm, const char htype, const char hflag, + const bool respecthide) { /* call with 0 hflag_test */ BM_mesh_elem_hflag_disable_test(bm, htype, hflag, respecthide, false, 0); } -void BM_mesh_elem_hflag_enable_all(BMesh *bm, const char htype, const char hflag, - const bool respecthide) +void BM_mesh_elem_hflag_enable_all( + BMesh *bm, const char htype, const char hflag, + const bool respecthide) { /* call with 0 hflag_test */ BM_mesh_elem_hflag_enable_test(bm, htype, hflag, respecthide, false, 0); diff --git a/source/blender/bmesh/intern/bmesh_marking.h b/source/blender/bmesh/intern/bmesh_marking.h index 15f972c6435..0d86567c06e 100644 --- a/source/blender/bmesh/intern/bmesh_marking.h +++ b/source/blender/bmesh/intern/bmesh_marking.h @@ -43,15 +43,19 @@ void BM_face_hide_set(BMFace *f, const bool hide); /* Selection code */ void BM_elem_select_set(BMesh *bm, BMElem *ele, const bool select); -void BM_mesh_elem_hflag_enable_test(BMesh *bm, const char htype, const char hflag, - const bool respecthide, const bool overwrite, const char hflag_test); -void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hflag, - const bool respecthide, const bool overwrite, const char hflag_test); - -void BM_mesh_elem_hflag_enable_all(BMesh *bm, const char htype, const char hflag, - const bool respecthide); -void BM_mesh_elem_hflag_disable_all(BMesh *bm, const char htype, const char hflag, - const bool respecthide); +void BM_mesh_elem_hflag_enable_test( + BMesh *bm, const char htype, const char hflag, + const bool respecthide, const bool overwrite, const char hflag_test); +void BM_mesh_elem_hflag_disable_test( + BMesh *bm, const char htype, const char hflag, + const bool respecthide, const bool overwrite, const char hflag_test); + +void BM_mesh_elem_hflag_enable_all( + BMesh *bm, const char htype, const char hflag, + const bool respecthide); +void BM_mesh_elem_hflag_disable_all( + BMesh *bm, const char htype, const char hflag, + const bool respecthide); /* individual element select functions, BM_elem_select_set is a shortcut for these * that automatically detects which one to use*/ diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index 9a2869b64ef..2a6c98bce2e 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -303,8 +303,9 @@ static void bm_mesh_edges_calc_vectors(BMesh *bm, float (*edgevec)[3], const flo bm->elem_index_dirty &= ~BM_EDGE; } -static void bm_mesh_verts_calc_normals(BMesh *bm, const float (*edgevec)[3], const float (*fnos)[3], - const float (*vcos)[3], float (*vnos)[3]) +static void bm_mesh_verts_calc_normals( + BMesh *bm, const float (*edgevec)[3], const float (*fnos)[3], + const float (*vcos)[3], float (*vnos)[3]) { BM_mesh_elem_index_ensure(bm, (vnos) ? (BM_EDGE | BM_VERT) : BM_EDGE); @@ -437,8 +438,9 @@ void BM_verts_calc_normal_vcos(BMesh *bm, const float (*fnos)[3], const float (* /** * Helpers for #BM_mesh_loop_normals_update and #BM_loops_calc_normals_vnos */ -static void bm_mesh_edges_sharp_tag(BMesh *bm, const float (*vnos)[3], const float (*fnos)[3], float split_angle, - float (*r_lnos)[3]) +static void bm_mesh_edges_sharp_tag( + BMesh *bm, const float (*vnos)[3], const float (*fnos)[3], float split_angle, + float (*r_lnos)[3]) { BMIter eiter, viter; BMVert *v; @@ -1131,8 +1133,9 @@ finally: * These functions ensure its correct and are called more often in debug mode. */ -void BM_mesh_elem_index_validate(BMesh *bm, const char *location, const char *func, - const char *msg_a, const char *msg_b) +void BM_mesh_elem_index_validate( + BMesh *bm, const char *location, const char *func, + const char *msg_a, const char *msg_b) { const char iter_types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, @@ -1379,6 +1382,41 @@ BMFace *BM_face_at_index_find(BMesh *bm, const int index) return BLI_mempool_findelem(bm->fpool, index); } +/** + * Use lookup table when available, else use slower find functions. + * + * \note Try to use #BM_mesh_elem_table_ensure instead. + */ +BMVert *BM_vert_at_index_find_or_table(BMesh *bm, const int index) +{ + if ((bm->elem_table_dirty & BM_VERT) == 0) { + return (index < bm->totvert) ? bm->vtable[index] : NULL; + } + else { + return BM_vert_at_index_find(bm, index); + } +} + +BMEdge *BM_edge_at_index_find_or_table(BMesh *bm, const int index) +{ + if ((bm->elem_table_dirty & BM_EDGE) == 0) { + return (index < bm->totedge) ? bm->etable[index] : NULL; + } + else { + return BM_edge_at_index_find(bm, index); + } +} + +BMFace *BM_face_at_index_find_or_table(BMesh *bm, const int index) +{ + if ((bm->elem_table_dirty & BM_FACE) == 0) { + return (index < bm->totface) ? bm->ftable[index] : NULL; + } + else { + return BM_face_at_index_find(bm, index); + } +} + /** * Return the amount of element of type 'type' in a given bmesh. diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h index bac5da8347e..b157237c7d0 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.h +++ b/source/blender/bmesh/intern/bmesh_mesh.h @@ -49,8 +49,9 @@ void bmesh_edit_begin(BMesh *bm, const BMOpTypeFlag type_flag); void bmesh_edit_end(BMesh *bm, const BMOpTypeFlag type_flag); void BM_mesh_elem_index_ensure(BMesh *bm, const char hflag); -void BM_mesh_elem_index_validate(BMesh *bm, const char *location, const char *func, - const char *msg_a, const char *msg_b); +void BM_mesh_elem_index_validate( + BMesh *bm, const char *location, const char *func, + const char *msg_a, const char *msg_b); #ifndef NDEBUG bool BM_mesh_elem_table_check(BMesh *bm); @@ -68,6 +69,10 @@ BMVert *BM_vert_at_index_find(BMesh *bm, const int index); BMEdge *BM_edge_at_index_find(BMesh *bm, const int index); BMFace *BM_face_at_index_find(BMesh *bm, const int index); +BMVert *BM_vert_at_index_find_or_table(BMesh *bm, const int index); +BMEdge *BM_edge_at_index_find_or_table(BMesh *bm, const int index); +BMFace *BM_face_at_index_find_or_table(BMesh *bm, const int index); + // XXX int BM_mesh_elem_count(BMesh *bm, const char htype); diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index 98521137816..a0ef12c28db 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -203,8 +203,9 @@ char BM_mesh_cd_flag_from_bmesh(BMesh *bm) } /* Static function for alloc (duplicate in modifiers_bmesh.c) */ -static BMFace *bm_face_create_from_mpoly(MPoly *mp, MLoop *ml, - BMesh *bm, BMVert **vtable, BMEdge **etable) +static BMFace *bm_face_create_from_mpoly( + MPoly *mp, MLoop *ml, + BMesh *bm, BMVert **vtable, BMEdge **etable) { BMVert **verts = BLI_array_alloca(verts, mp->totloop); BMEdge **edges = BLI_array_alloca(edges, mp->totloop); @@ -224,8 +225,9 @@ static BMFace *bm_face_create_from_mpoly(MPoly *mp, MLoop *ml, * * \warning This function doesn't calculate face normals. */ -void BM_mesh_bm_from_me(BMesh *bm, Mesh *me, - const bool calc_face_normal, const bool set_key, int act_key_nr) +void BM_mesh_bm_from_me( + BMesh *bm, Mesh *me, + const bool calc_face_normal, const bool set_key, int act_key_nr) { BM_mesh_bm_from_me_ex(bm, me, CD_MASK_BMESH, calc_face_normal, set_key, act_key_nr); } diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.h b/source/blender/bmesh/intern/bmesh_mesh_conv.h index f910c696fb6..0d235a128ab 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.h +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.h @@ -42,8 +42,9 @@ void BM_mesh_cd_flag_ensure(BMesh *bm, struct Mesh *mesh, const char cd_flag); void BM_mesh_cd_flag_apply(BMesh *bm, const char cd_flag); char BM_mesh_cd_flag_from_bmesh(BMesh *bm); -void BM_mesh_bm_from_me(BMesh *bm, struct Mesh *me, - const bool calc_face_normal, const bool set_key, int act_key_nr); +void BM_mesh_bm_from_me( + BMesh *bm, struct Mesh *me, + const bool calc_face_normal, const bool set_key, int act_key_nr); void BM_mesh_bm_from_me_ex(BMesh *bm, struct Mesh *me, CustomDataMask mask, const bool calc_face_normal, const bool set_key, int act_key_nr); void BM_mesh_bm_to_me(BMesh *bm, struct Mesh *me, bool do_tessface); diff --git a/source/blender/bmesh/intern/bmesh_mesh_validate.c b/source/blender/bmesh/intern/bmesh_mesh_validate.c index 494da3b889b..478194735f3 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_validate.c +++ b/source/blender/bmesh/intern/bmesh_mesh_validate.c @@ -195,7 +195,7 @@ bool BM_mesh_validate(BMesh *bm) ERRMSG("Finished - errors %d", errtot); - return true; + return (errtot == 0); } diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index 85e9ec3aa24..5891876c22c 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -276,10 +276,11 @@ BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f_a, BMFace *f_b, BMEdge *e, const * if the split is successful (and the original original face will be the * other side). NULL if the split fails. */ -BMFace *BM_face_split(BMesh *bm, BMFace *f, - BMLoop *l_a, BMLoop *l_b, - BMLoop **r_l, BMEdge *example, - const bool no_double) +BMFace *BM_face_split( + BMesh *bm, BMFace *f, + BMLoop *l_a, BMLoop *l_b, + BMLoop **r_l, BMEdge *example, + const bool no_double) { const bool has_mdisp = CustomData_has_layer(&bm->ldata, CD_MDISPS); BMFace *f_new, *f_tmp; @@ -357,10 +358,11 @@ BMFace *BM_face_split(BMesh *bm, BMFace *f, * if the split is successful (and the original original face will be the * other side). NULL if the split fails. */ -BMFace *BM_face_split_n(BMesh *bm, BMFace *f, - BMLoop *l_a, BMLoop *l_b, - float cos[][3], int n, - BMLoop **r_l, BMEdge *example) +BMFace *BM_face_split_n( + BMesh *bm, BMFace *f, + BMLoop *l_a, BMLoop *l_b, + float cos[][3], int n, + BMLoop **r_l, BMEdge *example) { BMFace *f_new, *f_tmp; BMLoop *l_dummy; @@ -991,8 +993,9 @@ bool BM_face_split_edgenet( * * \returns The New Edge */ -BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac, - const bool do_del, const bool join_faces, const bool kill_degenerate_faces) +BMEdge *BM_vert_collapse_faces( + BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac, + const bool do_del, const bool join_faces, const bool kill_degenerate_faces) { BMEdge *e_new = NULL; BMVert *tv = BM_edge_other_vert(e_kill, v_kill); @@ -1104,8 +1107,9 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float * * \return The New Edge */ -BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, - const bool do_del, const bool kill_degenerate_faces) +BMEdge *BM_vert_collapse_edge( + BMesh *bm, BMEdge *e_kill, BMVert *v_kill, + const bool do_del, const bool kill_degenerate_faces) { /* nice example implementation but we want loops to have their customdata * accounted for */ @@ -1354,8 +1358,9 @@ bool BM_face_validate(BMFace *face, FILE *err) * * \note #BM_edge_rotate_check must have already run. */ -void BM_edge_calc_rotate(BMEdge *e, const bool ccw, - BMLoop **r_l1, BMLoop **r_l2) +void BM_edge_calc_rotate( + BMEdge *e, const bool ccw, + BMLoop **r_l1, BMLoop **r_l2) { BMVert *v1, *v2; BMFace *fa, *fb; @@ -1517,8 +1522,9 @@ bool BM_edge_rotate_check_degenerate(BMEdge *e, BMLoop *l1, BMLoop *l2) return true; } -bool BM_edge_rotate_check_beauty(BMEdge *e, - BMLoop *l1, BMLoop *l2) +bool BM_edge_rotate_check_beauty( + BMEdge *e, + BMLoop *l1, BMLoop *l2) { /* Stupid check for now: * Could compare angles of surrounding edges @@ -1644,3 +1650,9 @@ BMVert *BM_face_loop_separate(BMesh *bm, BMLoop *sl) { return bmesh_urmv_loop(bm, sl); } + +BMVert *BM_face_loop_separate_multi( + BMesh *bm, BMLoop **larr, int larr_len) +{ + return bmesh_urmv_loop_multi(bm, larr, larr_len); +} diff --git a/source/blender/bmesh/intern/bmesh_mods.h b/source/blender/bmesh/intern/bmesh_mods.h index 59aee323bba..1b826b1e0b2 100644 --- a/source/blender/bmesh/intern/bmesh_mods.h +++ b/source/blender/bmesh/intern/bmesh_mods.h @@ -35,24 +35,29 @@ bool BM_disk_dissolve(BMesh *bm, BMVert *v); BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e, const bool do_del); -BMFace *BM_face_split(BMesh *bm, BMFace *f, - BMLoop *l_a, BMLoop *l_b, - BMLoop **r_l, - BMEdge *example, const bool no_double); - -BMFace *BM_face_split_n(BMesh *bm, BMFace *f, - BMLoop *l_a, BMLoop *l_b, - float cos[][3], int n, - BMLoop **r_l, BMEdge *example); - -bool BM_face_split_edgenet(BMesh *bm, BMFace *f, - BMEdge **edge_net, const int edge_net_len, - BMFace ***r_face_arr, int *r_face_arr_len); - -BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac, - const bool do_del, const bool join_faces, const bool kill_degenerate_faces); -BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, - const bool do_del, const bool kill_degenerate_faces); +BMFace *BM_face_split( + BMesh *bm, BMFace *f, + BMLoop *l_a, BMLoop *l_b, + BMLoop **r_l, + BMEdge *example, const bool no_double); + +BMFace *BM_face_split_n( + BMesh *bm, BMFace *f, + BMLoop *l_a, BMLoop *l_b, + float cos[][3], int n, +BMLoop **r_l, BMEdge *example); + +bool BM_face_split_edgenet( + BMesh *bm, BMFace *f, + BMEdge **edge_net, const int edge_net_len, + BMFace ***r_face_arr, int *r_face_arr_len); + +BMEdge *BM_vert_collapse_faces( + BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac, + const bool do_del, const bool join_faces, const bool kill_degenerate_faces); +BMEdge *BM_vert_collapse_edge( + BMesh *bm, BMEdge *e_kill, BMVert *v_kill, + const bool do_del, const bool kill_degenerate_faces); BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float percent); @@ -61,13 +66,16 @@ BMVert *BM_edge_split_n(BMesh *bm, BMEdge *e, int numcuts, BMVert **r_varr); bool BM_face_validate(BMFace *face, FILE *err); -void BM_edge_calc_rotate(BMEdge *e, const bool ccw, - BMLoop **r_l1, BMLoop **r_l2); +void BM_edge_calc_rotate( + BMEdge *e, const bool ccw, + BMLoop **r_l1, BMLoop **r_l2); bool BM_edge_rotate_check(BMEdge *e); -bool BM_edge_rotate_check_degenerate(BMEdge *e, - BMLoop *l1, BMLoop *l2); -bool BM_edge_rotate_check_beauty(BMEdge *e, - BMLoop *l1, BMLoop *l2); +bool BM_edge_rotate_check_degenerate( + BMEdge *e, + BMLoop *l1, BMLoop *l2); +bool BM_edge_rotate_check_beauty( + BMEdge *e, + BMLoop *l1, BMLoop *l2); BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_flag); /* flags for BM_edge_rotate */ @@ -81,5 +89,7 @@ enum { BMVert *BM_face_vert_separate(BMesh *bm, BMFace *sf, BMVert *sv); BMVert *BM_face_loop_separate(BMesh *bm, BMLoop *sl); +BMVert *BM_face_loop_separate_multi( + BMesh *bm, BMLoop **larr, int larr_len); #endif /* __BMESH_MODS_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index d0679b9919a..2ba65f5a1e7 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -359,6 +359,7 @@ static BMOpDefine bmo_collapse_def = { "collapse", /* slots_in */ {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {"uvs", BMO_OP_SLOT_BOOL}, /* also collapse UVs and such */ {{'\0'}}, }, {{{'\0'}}}, /* no output */ diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h index 33a956b652f..96f954f8ee7 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.h +++ b/source/blender/bmesh/intern/bmesh_operator_api.h @@ -273,9 +273,10 @@ BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identif (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); +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 { @@ -335,11 +336,12 @@ void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_na void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *op, const char htype, const short oflag); -void BMO_mesh_selected_remap(BMesh *bm, - BMOpSlot *slot_vert_map, - BMOpSlot *slot_edge_map, - BMOpSlot *slot_face_map, - const bool check_select); +void BMO_mesh_selected_remap( + BMesh *bm, + BMOpSlot *slot_vert_map, + BMOpSlot *slot_edge_map, + BMOpSlot *slot_face_map, + const bool check_select); /* copies the values from another slot to the end of the output slot */ #define BMO_slot_buffer_append(op_src, slots_src, slot_name_src, \ @@ -347,53 +349,62 @@ void BMO_mesh_selected_remap(BMesh *bm, _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); +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, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const short oflag); +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, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const short oflag); +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, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const short oflag); +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, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const short oflag); +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, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag, const bool do_flush); +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 bool do_flush); /* clears tool-flag flag from all elements inside a slot array. */ -void BMO_slot_buffer_hflag_disable(BMesh *bm, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag, const bool do_flush); +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 bool 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, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag); +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); /* 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, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag); +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); void BMO_slot_buffer_from_array(BMOperator *op, BMOpSlot *slot, BMHeader **ele_buffer, int ele_buffer_len); @@ -405,19 +416,23 @@ void *BMO_slot_buffer_get_single(BMOpSlot *slot); 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(BMOperator *op, BMOpSlot *slot, - const void *element, const void *data); +void BMO_slot_map_insert( + BMOperator *op, BMOpSlot *slot, + const void *element, const void *data); /* 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, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], - 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, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], - 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, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], - 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 @@ -466,9 +481,10 @@ typedef struct BMOIter { void *BMO_slot_buffer_get_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); -void *BMO_iter_new(BMOIter *iter, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - 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); void **BMO_iter_map_value_p(BMOIter *iter); diff --git a/source/blender/bmesh/intern/bmesh_operator_api_inline.h b/source/blender/bmesh/intern/bmesh_operator_api_inline.h index 2b78b775723..4f995e08b9c 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api_inline.h +++ b/source/blender/bmesh/intern/bmesh_operator_api_inline.h @@ -38,55 +38,67 @@ * ghash or a mapping slot to do it. */ /* flags 15 and 16 (1 << 14 and 1 << 15) are reserved for bmesh api use */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE short _bmo_elem_flag_test(BMesh *bm, BMFlagLayer *oflags, const short oflag) { return oflags[bm->stackdepth - 1].f & oflag; } +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE bool _bmo_elem_flag_test_bool(BMesh *bm, BMFlagLayer *oflags, const short oflag) { return (oflags[bm->stackdepth - 1].f & oflag) != 0; } +ATTR_NONNULL(1, 2) BLI_INLINE void _bmo_elem_flag_enable(BMesh *bm, BMFlagLayer *oflags, const short oflag) { oflags[bm->stackdepth - 1].f |= oflag; } +ATTR_NONNULL(1, 2) BLI_INLINE void _bmo_elem_flag_disable(BMesh *bm, BMFlagLayer *oflags, const short oflag) { oflags[bm->stackdepth - 1].f &= (short)~oflag; } +ATTR_NONNULL(1, 2) BLI_INLINE void _bmo_elem_flag_set(BMesh *bm, BMFlagLayer *oflags, const short oflag, int val) { if (val) oflags[bm->stackdepth - 1].f |= oflag; else oflags[bm->stackdepth - 1].f &= (short)~oflag; } +ATTR_NONNULL(1, 2) BLI_INLINE void _bmo_elem_flag_toggle(BMesh *bm, BMFlagLayer *oflags, const short oflag) { oflags[bm->stackdepth - 1].f ^= oflag; } -BLI_INLINE void BMO_slot_map_int_insert(BMOperator *op, BMOpSlot *slot, - void *element, const int val) +ATTR_NONNULL(1, 2) +BLI_INLINE void BMO_slot_map_int_insert( + BMOperator *op, BMOpSlot *slot, + void *element, const int val) { union { void *ptr; int val; } t = {NULL}; BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT); BMO_slot_map_insert(op, slot, element, ((t.val = val), t.ptr)); } -BLI_INLINE void BMO_slot_map_bool_insert(BMOperator *op, BMOpSlot *slot, - void *element, const bool val) +ATTR_NONNULL(1, 2) +BLI_INLINE void BMO_slot_map_bool_insert( + BMOperator *op, BMOpSlot *slot, + void *element, const bool val) { union { void *ptr; bool val; } t = {NULL}; BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL); BMO_slot_map_insert(op, slot, element, ((t.val = val), t.ptr)); } -BLI_INLINE void BMO_slot_map_float_insert(BMOperator *op, BMOpSlot *slot, - void *element, const float val) +ATTR_NONNULL(1, 2) +BLI_INLINE void BMO_slot_map_float_insert( + BMOperator *op, BMOpSlot *slot, + void *element, const float val) { union { void *ptr; float val; } t = {NULL}; BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT); @@ -99,15 +111,19 @@ BLI_INLINE void BMO_slot_map_float_insert(BMOperator *op, BMOpSlot *slot, * 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(BMOperator *op, BMOpSlot *slot, - const void *element, void *val) +ATTR_NONNULL(1, 2) +BLI_INLINE void BMO_slot_map_ptr_insert( + BMOperator *op, BMOpSlot *slot, + const void *element, void *val) { BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL); BMO_slot_map_insert(op, slot, element, val); } -BLI_INLINE void BMO_slot_map_elem_insert(BMOperator *op, BMOpSlot *slot, - const void *element, void *val) +ATTR_NONNULL(1, 2) +BLI_INLINE void BMO_slot_map_elem_insert( + BMOperator *op, BMOpSlot *slot, + const void *element, void *val) { BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_ELEM); BMO_slot_map_insert(op, slot, element, val); @@ -115,25 +131,30 @@ BLI_INLINE void BMO_slot_map_elem_insert(BMOperator *op, BMOpSlot *slot, /* no values */ -BLI_INLINE void BMO_slot_map_empty_insert(BMOperator *op, BMOpSlot *slot, - const void *element) +ATTR_NONNULL(1, 2) +BLI_INLINE void BMO_slot_map_empty_insert( + BMOperator *op, BMOpSlot *slot, + const void *element) { BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_EMPTY); BMO_slot_map_insert(op, slot, element, NULL); } +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BMO_slot_map_contains(BMOpSlot *slot, const void *element) { BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); return BLI_ghash_haskey(slot->data.ghash, element); } +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE void **BMO_slot_map_data_get(BMOpSlot *slot, const void *element) { return BLI_ghash_lookup_p(slot->data.ghash, element); } +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE float BMO_slot_map_float_get(BMOpSlot *slot, const void *element) { void **data; @@ -148,6 +169,7 @@ BLI_INLINE float BMO_slot_map_float_get(BMOpSlot *slot, const void *element) } } +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE int BMO_slot_map_int_get(BMOpSlot *slot, const void *element) { void **data; @@ -162,6 +184,7 @@ BLI_INLINE int BMO_slot_map_int_get(BMOpSlot *slot, const void *element) } } +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BMO_slot_map_bool_get(BMOpSlot *slot, const void *element) { void **data; @@ -176,6 +199,7 @@ BLI_INLINE bool BMO_slot_map_bool_get(BMOpSlot *slot, const void *element) } } +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE void *BMO_slot_map_ptr_get(BMOpSlot *slot, const void *element) { void **val = BMO_slot_map_data_get(slot, element); @@ -185,6 +209,7 @@ BLI_INLINE void *BMO_slot_map_ptr_get(BMOpSlot *slot, const void *element) return NULL; } +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE void *BMO_slot_map_elem_get(BMOpSlot *slot, const void *element) { void **val = (void **) BMO_slot_map_data_get(slot, element); diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index ba154b04838..dda1f2fe30a 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -281,9 +281,10 @@ BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identif * define used. * Copies data from one slot to another. */ -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) +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 *slot_src = BMO_slot_get(slot_args_src, slot_name_src); BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst); @@ -543,8 +544,9 @@ void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_nam * */ -static int bmo_mesh_flag_count(BMesh *bm, const char htype, const short oflag, - const bool test_for_enabled) +static int bmo_mesh_flag_count( + BMesh *bm, const char htype, const short oflag, + const bool test_for_enabled) { const char iter_types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, @@ -602,11 +604,12 @@ void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char hty } } -void BMO_mesh_selected_remap(BMesh *bm, - BMOpSlot *slot_vert_map, - BMOpSlot *slot_edge_map, - BMOpSlot *slot_face_map, - const bool check_select) +void BMO_mesh_selected_remap( + BMesh *bm, + BMOpSlot *slot_vert_map, + BMOpSlot *slot_edge_map, + BMOpSlot *slot_face_map, + const bool check_select) { if (bm->selected.first) { BMEditSelection *ese, *ese_next; @@ -663,8 +666,9 @@ int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_na /* inserts a key/value mapping into a mapping slot. note that it copies the * value, it doesn't store a reference to it. */ -void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, - const void *element, const void *data) +void BMO_slot_map_insert( + BMOperator *op, BMOpSlot *slot, + const void *element, const void *data) { (void) op; /* Ignored in release builds. */ @@ -717,8 +721,9 @@ void *bmo_slot_buffer_grow(BMesh *bm, BMOperator *op, int slot_code, int totadd) } #endif -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) +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 gh_iter; BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); @@ -759,8 +764,9 @@ void *BMO_slot_buffer_alloc(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS] * * Copies all elements of a certain type into an operator slot. */ -void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], - 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(slot_args, slot_name); int totelement = 0, i = 0; @@ -809,9 +815,10 @@ void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_ * 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, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const char hflag, - const bool test_for_enabled) +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 bool test_for_enabled) { BMOpSlot *output = BMO_slot_get(slot_args, slot_name); int totelement = 0, i = 0; @@ -872,16 +879,18 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, BMOpSlot slot_ } } -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) +void BMO_slot_buffer_from_enabled_hflag( + BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char htype, const char hflag) { bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, true); } -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) +void BMO_slot_buffer_from_disabled_hflag( + BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char htype, const char hflag) { bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, false); } @@ -927,9 +936,10 @@ void *BMO_slot_buffer_get_single(BMOpSlot *slot) /** * Copies the values from another slot to the end of the output slot. */ -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) +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 *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst); BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src); @@ -964,10 +974,11 @@ void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const cha * 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, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, - const char htype, const short oflag, - const bool test_for_enabled) +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 bool test_for_enabled) { BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); int totelement, i = 0; @@ -1026,16 +1037,18 @@ static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, } } -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) +void BMO_slot_buffer_from_enabled_flag( + BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char htype, const short oflag) { bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, true); } -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) +void BMO_slot_buffer_from_disabled_flag( + BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char htype, const short oflag) { bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, false); } @@ -1046,9 +1059,10 @@ void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, * Header Flags elements in a slots buffer, automatically * using the selection API where appropriate. */ -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 bool do_flush) +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 bool do_flush) { BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BMElem **data = (BMElem **)slot->data.buf; @@ -1082,9 +1096,10 @@ void BMO_slot_buffer_hflag_enable(BMesh *bm, * Removes flags from elements in a slots buffer, automatically * using the selection API where appropriate. */ -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 bool do_flush) +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 bool do_flush) { BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BMElem **data = (BMElem **)slot->data.buf; @@ -1116,9 +1131,10 @@ void BMO_slot_buffer_hflag_disable(BMesh *bm, * * Flags elements in a slots buffer */ -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) +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(slot_args, slot_name); BMHeader **data = slot->data.p; @@ -1140,9 +1156,10 @@ void BMO_slot_buffer_flag_enable(BMesh *bm, * * Removes flags from elements in a slots buffer */ -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) +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(slot_args, slot_name); BMHeader **data = (BMHeader **)slot->data.buf; @@ -1394,9 +1411,10 @@ void *BMO_slot_buffer_get_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char * \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, - BMOpSlot slot_args[BMO_OP_MAX_SLOTS], 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(slot_args, slot_name); diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h index f39fe29b596..d9961e589da 100644 --- a/source/blender/bmesh/intern/bmesh_operators.h +++ b/source/blender/bmesh/intern/bmesh_operators.h @@ -46,6 +46,7 @@ enum { SUBD_FALLOFF_ROOT, SUBD_FALLOFF_SHARP, SUBD_FALLOFF_LIN, + SUBD_FALLOFF_INVSQUARE = 7, /* matching PROP_INVSQUARE */ }; enum { @@ -130,14 +131,15 @@ extern const BMOpDefine *bmo_opdefines[]; extern const int bmo_opdefines_total; /*------specific operator helper functions-------*/ -void BM_mesh_esubdivide(BMesh *bm, const char edge_hflag, - const float smooth, const short smooth_falloff, const bool use_smooth_even, - const float fractal, const float along_normal, - const int numcuts, - const int seltype, const int cornertype, - const short use_single_edge, const short use_grid_fill, - const short use_only_quads, - const int seed); +void BM_mesh_esubdivide( + BMesh *bm, const char edge_hflag, + const float smooth, const short smooth_falloff, const bool use_smooth_even, + const float fractal, const float along_normal, + const int numcuts, + const int seltype, const int cornertype, + const short use_single_edge, const short use_grid_fill, + const short use_only_quads, + const int seed); #include "intern/bmesh_operator_api_inline.h" diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index bc06ba2c9b1..d2d31d6a562 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -102,8 +102,9 @@ static float bm_face_calc_poly_normal(const BMFace *f, float n[3]) * Same as #calc_poly_normal and #bm_face_calc_poly_normal * but takes an array of vertex locations. */ -static float bm_face_calc_poly_normal_vertex_cos(BMFace *f, float r_no[3], - float const (*vertexCos)[3]) +static float bm_face_calc_poly_normal_vertex_cos( + BMFace *f, float r_no[3], + float const (*vertexCos)[3]) { BMLoop *l_first = BM_FACE_FIRST_LOOP(f); BMLoop *l_iter = l_first; @@ -127,8 +128,9 @@ static float bm_face_calc_poly_normal_vertex_cos(BMFace *f, float r_no[3], /** * \brief COMPUTE POLY CENTER (BMFace) */ -static void bm_face_calc_poly_center_mean_vertex_cos(BMFace *f, float r_cent[3], - float const (*vertexCos)[3]) +static void bm_face_calc_poly_center_mean_vertex_cos( + BMFace *f, float r_cent[3], + float const (*vertexCos)[3]) { BMLoop *l_first = BM_FACE_FIRST_LOOP(f); BMLoop *l_iter = l_first; @@ -548,8 +550,9 @@ void BM_face_normal_update(BMFace *f) } /* exact same as 'BM_face_calc_normal' but accepts vertex coords */ -float BM_face_calc_normal_vcos(BMesh *bm, BMFace *f, float r_no[3], - float const (*vertexCos)[3]) +float BM_face_calc_normal_vcos( + BMesh *bm, BMFace *f, float r_no[3], + float const (*vertexCos)[3]) { BMLoop *l; @@ -607,8 +610,9 @@ float BM_face_calc_normal_subset(BMLoop *l_first, BMLoop *l_last, float r_no[3]) } /* exact same as 'BM_face_calc_normal' but accepts vertex coords */ -void BM_face_calc_center_mean_vcos(BMesh *bm, BMFace *f, float r_cent[3], - float const (*vertexCos)[3]) +void BM_face_calc_center_mean_vcos( + BMesh *bm, BMFace *f, float r_cent[3], + float const (*vertexCos)[3]) { /* must have valid index data */ BLI_assert((bm->elem_index_dirty & BM_VERT) == 0); diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h index 9980b59a298..582b4248c7d 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.h +++ b/source/blender/bmesh/intern/bmesh_polygon.h @@ -36,16 +36,18 @@ void BM_bmesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_loopt void BM_face_calc_tessellation(const BMFace *f, BMLoop **r_loops, unsigned int (*r_index)[3]); float BM_face_calc_normal(const BMFace *f, float r_no[3]) ATTR_NONNULL(); -float BM_face_calc_normal_vcos(BMesh *bm, BMFace *f, float r_no[3], - float const (*vertexCos)[3]) ATTR_NONNULL(); +float BM_face_calc_normal_vcos( + BMesh *bm, BMFace *f, float r_no[3], + float const (*vertexCos)[3]) ATTR_NONNULL(); float BM_face_calc_normal_subset(BMLoop *l_first, BMLoop *l_last, float r_no[3]) ATTR_NONNULL(); float BM_face_calc_area(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); float BM_face_calc_perimeter(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); void BM_face_calc_plane(BMFace *f, float r_plane[3]) ATTR_NONNULL(); void BM_face_calc_center_bounds(BMFace *f, float center[3]) ATTR_NONNULL(); void BM_face_calc_center_mean(BMFace *f, float center[3]) ATTR_NONNULL(); -void BM_face_calc_center_mean_vcos(BMesh *bm, BMFace *f, float r_cent[3], - float const (*vertexCos)[3]) ATTR_NONNULL(); +void BM_face_calc_center_mean_vcos( + BMesh *bm, BMFace *f, float r_cent[3], + float const (*vertexCos)[3]) ATTR_NONNULL(); void BM_face_calc_center_mean_weighted(BMFace *f, float center[3]) ATTR_NONNULL(); void BM_face_normal_update(BMFace *f) ATTR_NONNULL(); diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 4d3dd580ab3..031fc68e66f 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -501,10 +501,10 @@ bool BM_verts_in_face(BMVert **varr, int len, BMFace *f) /** * Returns whether or not a given edge is part of a given face. */ -bool BM_edge_in_face(BMEdge *e, BMFace *f) +bool BM_edge_in_face(const BMEdge *e, const BMFace *f) { if (e->l) { - BMLoop *l_iter, *l_first; + const BMLoop *l_iter, *l_first; l_iter = l_first = e->l; do { @@ -861,9 +861,9 @@ bool BM_vert_is_wire(const BMVert *v) */ bool BM_vert_is_manifold(const BMVert *v) { - BMEdge *e, *e_old; - BMLoop *l; - int len, count, flag; + BMEdge *e_iter, *e_first, *e_prev; + BMLoop *l_iter, *l_first; + int loop_num = 0, loop_num_region = 0, boundary_num = 0; if (v->e == NULL) { /* loose vert */ @@ -871,51 +871,50 @@ bool BM_vert_is_manifold(const BMVert *v) } /* count edges while looking for non-manifold edges */ - len = 0; - e_old = e = v->e; + e_first = e_iter = v->e; + l_first = e_iter->l ? e_iter->l : NULL; do { /* loose edge or edge shared by more than two faces, * edges with 1 face user are OK, otherwise we could * use BM_edge_is_manifold() here */ - if (e->l == NULL || bmesh_radial_length(e->l) > 2) { + if (e_iter->l == NULL || (e_iter->l != e_iter->l->radial_next->radial_next)) { return false; } - len++; - } while ((e = bmesh_disk_edge_next(e, v)) != e_old); - - count = 1; - flag = 1; - e = NULL; - e_old = v->e; - l = e_old->l; - while (e != e_old) { - l = (l->v == v) ? l->prev : l->next; - e = l->e; - count++; /* count the edges */ - - if (flag && l->radial_next == l) { - /* we've hit the edge of an open mesh, reset once */ - flag = 0; - count = 1; - e_old = e; - e = NULL; - l = e_old->l; + + /* count radial loops */ + if (e_iter->l->v == v) { + loop_num += 1; } - else if (l->radial_next == l) { - /* break the loop */ - e = e_old; + + if (!BM_edge_is_boundary(e_iter)) { + /* non boundary check opposite loop */ + if (e_iter->l->radial_next->v == v) { + loop_num += 1; + } } else { - l = l->radial_next; + /* start at the boundary */ + l_first = e_iter->l; + boundary_num += 1; + /* >2 boundaries cant be manifold */ + if (boundary_num == 3) { + return false; + } } - } + } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first); - if (count < len) { - /* vert shared by multiple regions */ - return false; - } + e_first = l_first->e; + l_first = (l_first->v == v) ? l_first : l_first->next; + BLI_assert(l_first->v == v); - return true; + l_iter = l_first; + e_prev = e_first; + + do { + loop_num_region += 1; + } while (((l_iter = BM_vert_step_fan_loop(l_iter, &e_prev)) != l_first) && (l_iter != NULL)); + + return (loop_num == loop_num_region); } /** @@ -1184,8 +1183,9 @@ BMLoop *BM_face_edge_share_loop(BMFace *f, BMEdge *e) * \note This is in fact quite a simple check, mainly include this function so the intent is more obvious. * We know these 2 verts will _always_ make up the loops edge */ -void BM_edge_ordered_verts_ex(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2, - const BMLoop *edge_loop) +void BM_edge_ordered_verts_ex( + const BMEdge *edge, BMVert **r_v1, BMVert **r_v2, + const BMLoop *edge_loop) { BLI_assert(edge_loop->e == edge); (void)edge; /* quiet warning in release build */ @@ -1220,7 +1220,7 @@ bool BM_loop_is_convex(const BMLoop *l) * * \return angle in radians */ -float BM_loop_calc_face_angle(BMLoop *l) +float BM_loop_calc_face_angle(const BMLoop *l) { return angle_v3v3v3(l->prev->v->co, l->v->co, @@ -1235,7 +1235,7 @@ float BM_loop_calc_face_angle(BMLoop *l) * \param l The loop to calculate the normal at * \param r_normal Resulting normal */ -void BM_loop_calc_face_normal(BMLoop *l, float r_normal[3]) +void BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) { if (normal_tri_v3(r_normal, l->prev->v->co, @@ -1257,7 +1257,7 @@ void BM_loop_calc_face_normal(BMLoop *l, float r_normal[3]) * \param l The loop to calculate the direction at * \param r_dir Resulting direction */ -void BM_loop_calc_face_direction(BMLoop *l, float r_dir[3]) +void BM_loop_calc_face_direction(const BMLoop *l, float r_dir[3]) { float v_prev[3]; float v_next[3]; @@ -1281,7 +1281,7 @@ void BM_loop_calc_face_direction(BMLoop *l, float r_dir[3]) * \param l The loop to calculate the tangent at * \param r_tangent Resulting tangent */ -void BM_loop_calc_face_tangent(BMLoop *l, float r_tangent[3]) +void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3]) { float v_prev[3]; float v_next[3]; @@ -1393,7 +1393,7 @@ void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_ta * * \returns the angle in radians */ -float BM_vert_calc_edge_angle_ex(BMVert *v, const float fallback) +float BM_vert_calc_edge_angle_ex(const BMVert *v, const float fallback) { BMEdge *e1, *e2; @@ -1415,7 +1415,7 @@ float BM_vert_calc_edge_angle_ex(BMVert *v, const float fallback) } } -float BM_vert_calc_edge_angle(BMVert *v) +float BM_vert_calc_edge_angle(const BMVert *v) { return BM_vert_calc_edge_angle_ex(v, DEG2RADF(90.0f)); } @@ -1424,14 +1424,14 @@ float BM_vert_calc_edge_angle(BMVert *v) * \note this isn't optimal to run on an array of verts, * see 'solidify_add_thickness' for a function which runs on an array. */ -float BM_vert_calc_shell_factor(BMVert *v) +float BM_vert_calc_shell_factor(const BMVert *v) { BMIter iter; BMLoop *l; float accum_shell = 0.0f; float accum_angle = 0.0f; - BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) { + BM_ITER_ELEM (l, &iter, (BMVert *)v, BM_LOOPS_OF_VERT) { const float face_angle = BM_loop_calc_face_angle(l); accum_shell += shell_v3v3_normalized_to_dist(v->no, l->f->no) * face_angle; accum_angle += face_angle; @@ -1446,15 +1446,15 @@ float BM_vert_calc_shell_factor(BMVert *v) } /* alternate version of #BM_vert_calc_shell_factor which only * uses 'hflag' faces, but falls back to all if none found. */ -float BM_vert_calc_shell_factor_ex(BMVert *v, const float no[3], const char hflag) +float BM_vert_calc_shell_factor_ex(const BMVert *v, const float no[3], const char hflag) { BMIter iter; - BMLoop *l; + const BMLoop *l; float accum_shell = 0.0f; float accum_angle = 0.0f; int tot_sel = 0, tot = 0; - BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) { + BM_ITER_ELEM (l, &iter, (BMVert *)v, BM_LOOPS_OF_VERT) { if (BM_elem_flag_test(l->f, hflag)) { /* <-- main difference to BM_vert_calc_shell_factor! */ const float face_angle = BM_loop_calc_face_angle(l); accum_shell += shell_v3v3_normalized_to_dist(no, l->f->no) * face_angle; @@ -1483,15 +1483,15 @@ float BM_vert_calc_shell_factor_ex(BMVert *v, const float no[3], const char hfla * \note quite an obscure function. * used in bmesh operators that have a relative scale options, */ -float BM_vert_calc_mean_tagged_edge_length(BMVert *v) +float BM_vert_calc_mean_tagged_edge_length(const BMVert *v) { BMIter iter; BMEdge *e; int tot; float length = 0.0f; - BM_ITER_ELEM_INDEX (e, &iter, v, BM_EDGES_OF_VERT, tot) { - BMVert *v_other = BM_edge_other_vert(e, v); + BM_ITER_ELEM_INDEX (e, &iter, (BMVert *)v, BM_EDGES_OF_VERT, tot) { + const BMVert *v_other = BM_edge_other_vert(e, v); if (BM_elem_flag_test(v_other, BM_ELEM_TAG)) { length += BM_edge_calc_length(e); } @@ -2128,9 +2128,10 @@ float BM_mesh_calc_volume(BMesh *bm, bool is_signed) * (having both set is supported too). * \return The number of groups found. */ -int BM_mesh_calc_face_groups(BMesh *bm, int *r_groups_array, int (**r_group_index)[2], - BMElemFilterFunc filter_fn, void *user_data, - const char hflag_test, const char htype_step) +int BM_mesh_calc_face_groups( + BMesh *bm, int *r_groups_array, int (**r_group_index)[2], + BMElemFilterFunc filter_fn, void *user_data, + const char hflag_test, const char htype_step) { #ifdef DEBUG int group_index_len = 1; @@ -2285,9 +2286,10 @@ int BM_mesh_calc_face_groups(BMesh *bm, int *r_groups_array, int (**r_group_inde * \note Unlike #BM_mesh_calc_face_groups there is no 'htype_step' argument, * since we always walk over verts. */ -int BM_mesh_calc_edge_groups(BMesh *bm, int *r_groups_array, int (**r_group_index)[2], - BMElemFilterFunc filter_fn, void *user_data, - const char hflag_test) +int BM_mesh_calc_edge_groups( + BMesh *bm, int *r_groups_array, int (**r_group_index)[2], + BMElemFilterFunc filter_fn, void *user_data, + const char hflag_test) { #ifdef DEBUG int group_index_len = 1; @@ -2416,6 +2418,9 @@ float bmesh_subd_falloff_calc(const int falloff, float val) break; case SUBD_FALLOFF_LIN: break; + case SUBD_FALLOFF_INVSQUARE: + val = val * (2.0f - val); + break; default: BLI_assert(0); break; diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index 6d25d9fbfec..e4f7c78bdc1 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -31,7 +31,7 @@ bool BM_vert_in_face(BMVert *v, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNU int BM_verts_in_face_count(BMVert **varr, int len, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); bool BM_verts_in_face(BMVert **varr, int len, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -bool BM_edge_in_face(BMEdge *e, BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BM_edge_in_face(const BMEdge *e, const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BLI_INLINE bool BM_edge_in_loop(const BMEdge *e, const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BLI_INLINE bool BM_vert_in_edge(const BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); @@ -96,10 +96,10 @@ BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) ATTR_W float BM_loop_point_side_of_loop_test(const BMLoop *l, const float co[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); float BM_loop_point_side_of_edge_test(const BMLoop *l, const float co[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_loop_calc_face_angle(BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -void BM_loop_calc_face_normal(BMLoop *l, float r_normal[3]) ATTR_NONNULL(); -void BM_loop_calc_face_direction(BMLoop *l, float r_normal[3]); -void BM_loop_calc_face_tangent(BMLoop *l, float r_tangent[3]); +float BM_loop_calc_face_angle(const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +void BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) ATTR_NONNULL(); +void BM_loop_calc_face_direction(const BMLoop *l, float r_normal[3]); +void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3]); float BM_edge_calc_face_angle_ex(const BMEdge *e, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); float BM_edge_calc_face_angle(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); @@ -107,11 +107,11 @@ float BM_edge_calc_face_angle_signed_ex(const BMEdge *e, const float fallback) float BM_edge_calc_face_angle_signed(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_tangent[3]) ATTR_NONNULL(); -float BM_vert_calc_edge_angle(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_vert_calc_edge_angle_ex(BMVert *v, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_vert_calc_shell_factor(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_vert_calc_shell_factor_ex(BMVert *v, const float no[3], const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -float BM_vert_calc_mean_tagged_edge_length(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +float BM_vert_calc_edge_angle(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +float BM_vert_calc_edge_angle_ex(const BMVert *v, const float fallback) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +float BM_vert_calc_shell_factor(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +float BM_vert_calc_shell_factor_ex(const BMVert *v, const float no[3], const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +float BM_vert_calc_mean_tagged_edge_length(const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BMLoop *BM_face_find_shortest_loop(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); BMLoop *BM_face_find_longest_loop(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); @@ -142,8 +142,9 @@ BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v) ATTR_WARN_UNUSED_RESULT AT BMLoop *BM_face_edge_share_loop(BMFace *f, BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); void BM_edge_ordered_verts(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2) ATTR_NONNULL(); -void BM_edge_ordered_verts_ex(const BMEdge *edge, BMVert **r_v1, BMVert **r_v2, - const BMLoop *edge_loop) ATTR_NONNULL(); +void BM_edge_ordered_verts_ex( + const BMEdge *edge, BMVert **r_v1, BMVert **r_v2, + const BMLoop *edge_loop) ATTR_NONNULL(); bool BM_vert_is_all_edge_flag_test(const BMVert *v, const char hflag, const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); bool BM_vert_is_all_face_flag_test(const BMVert *v, const char hflag, const bool respect_hide) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); @@ -157,12 +158,16 @@ bool BM_face_is_normal_valid(const BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNU float BM_mesh_calc_volume(BMesh *bm, bool is_signed) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -int BM_mesh_calc_face_groups(BMesh *bm, int *r_groups_array, int (**r_group_index)[2], - BMElemFilterFunc filter_fn, void *user_data, - const char hflag_test, const char htype_step) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3); -int BM_mesh_calc_edge_groups(BMesh *bm, int *r_groups_array, int (**r_group_index)[2], - BMElemFilterFunc filter_fn, void *user_data, - const char hflag_test) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3); +int BM_mesh_calc_face_groups( + BMesh *bm, int *r_groups_array, int (**r_group_index)[2], + BMElemFilterFunc filter_fn, void *user_data, + const char hflag_test, const char htype_step) + ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3); +int BM_mesh_calc_edge_groups( + BMesh *bm, int *r_groups_array, int (**r_group_index)[2], + BMElemFilterFunc filter_fn, void *user_data, + const char hflag_test) + ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3); /* not really any good place to put this */ float bmesh_subd_falloff_calc(const int falloff, float val) ATTR_WARN_UNUSED_RESULT; diff --git a/source/blender/bmesh/intern/bmesh_queries_inline.h b/source/blender/bmesh/intern/bmesh_queries_inline.h index 1ca56beb746..430ba10fb42 100644 --- a/source/blender/bmesh/intern/bmesh_queries_inline.h +++ b/source/blender/bmesh/intern/bmesh_queries_inline.h @@ -30,6 +30,7 @@ * Returns whether or not a given vertex is * is part of a given edge. */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BM_vert_in_edge(const BMEdge *e, const BMVert *v) { return (ELEM(v, e->v1, e->v2)); @@ -38,6 +39,7 @@ BLI_INLINE bool BM_vert_in_edge(const BMEdge *e, const BMVert *v) /** * Returns whether or not a given edge is part of a given loop. */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE bool BM_edge_in_loop(const BMEdge *e, const BMLoop *l) { return (l->e == e || l->prev->e == e); @@ -47,6 +49,7 @@ BLI_INLINE bool BM_edge_in_loop(const BMEdge *e, const BMLoop *l) * Returns whether or not two vertices are in * a given edge */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2, 3) BLI_INLINE bool BM_verts_in_edge(const BMVert *v1, const BMVert *v2, const BMEdge *e) { return ((e->v1 == v1 && e->v2 == v2) || @@ -57,6 +60,7 @@ BLI_INLINE bool BM_verts_in_edge(const BMVert *v1, const BMVert *v2, const BMEdg * Given a edge and one of its vertices, returns * the other vertex. */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE BMVert *BM_edge_other_vert(BMEdge *e, const BMVert *v) { if (e->v1 == v) { @@ -72,6 +76,7 @@ BLI_INLINE BMVert *BM_edge_other_vert(BMEdge *e, const BMVert *v) * Tests whether or not the edge is part of a wire. * (ie: has no faces attached to it) */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) { return (e->l == NULL); @@ -83,6 +88,7 @@ BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) */ #if 1 /* fast path for checking manifold */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e) { const BMLoop *l = e->l; @@ -100,6 +106,7 @@ BLI_INLINE int BM_edge_is_manifold(BMEdge *e) * Tests that the edge is manifold and * that both its faces point the same way. */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e) { const BMLoop *l = e->l; @@ -115,6 +122,7 @@ BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e) */ #if 1 /* fast path for checking boundary */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) { const BMLoop *l = e->l; @@ -130,6 +138,7 @@ BLI_INLINE int BM_edge_is_boundary(BMEdge *e) /** * Tests whether one loop is next to another within the same face. */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) { BLI_assert(l_a->f == l_b->f); @@ -140,6 +149,7 @@ BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) /** * Check if we have a single wire edge user. */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE bool BM_vert_is_wire_endpoint(const BMVert *v) { const BMEdge *e = v->e; diff --git a/source/blender/bmesh/intern/bmesh_structure.c b/source/blender/bmesh/intern/bmesh_structure.c index cf56c3b4b83..cb302139a4c 100644 --- a/source/blender/bmesh/intern/bmesh_structure.c +++ b/source/blender/bmesh/intern/bmesh_structure.c @@ -40,19 +40,56 @@ * MISC utility functions. */ -bool bmesh_edge_swapverts(BMEdge *e, BMVert *v_orig, BMVert *v_new) +void bmesh_disk_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) { - if (e->v1 == v_orig) { - e->v1 = v_new; + if (e->v1 == v_src) { + e->v1 = v_dst; e->v1_disk_link.next = e->v1_disk_link.prev = NULL; - return true; } - else if (e->v2 == v_orig) { - e->v2 = v_new; + else if (e->v2 == v_src) { + e->v2 = v_dst; e->v2_disk_link.next = e->v2_disk_link.prev = NULL; - return true; } - return false; + else { + BLI_assert(0); + } +} + +/** + * Handles all connected data, use with care. + * + * Assumes caller has setup correct state before the swap is done. + */ +void bmesh_edge_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) +{ + /* swap out loops */ + if (e->l) { + BMLoop *l_iter, *l_first; + l_iter = l_first = e->l; + do { + if (l_iter->v == v_src) { + l_iter->v = v_dst; + } + else if (l_iter->next->v == v_src) { + l_iter->next->v = v_dst; + } + else { + BLI_assert(l_iter->prev->v != v_src); + } + } while ((l_iter = l_iter->radial_next) != l_first); + } + + /* swap out edges */ + bmesh_disk_vert_replace(e, v_dst, v_src); +} + +void bmesh_disk_vert_replace(BMEdge *e, BMVert *v_dst, BMVert *v_src) +{ + BLI_assert(e->v1 == v_src || e->v2 == v_src); + bmesh_disk_edge_remove(e, v_src); /* remove e from tv's disk cycle */ + bmesh_disk_vert_swap(e, v_dst, v_src); /* swap out tv for v_new in e */ + bmesh_disk_edge_append(e, v_dst); /* add e to v_dst's disk cycle */ + BLI_assert(e->v1 != e->v2); } /** @@ -88,6 +125,7 @@ bool bmesh_edge_swapverts(BMEdge *e, BMVert *v_orig, BMVert *v_new) * the disk cycle has no problems dealing with non-manifold conditions involving faces. * * Functions relating to this cycle: + * - #bmesh_disk_vert_replace * - #bmesh_disk_edge_append * - #bmesh_disk_edge_remove * - #bmesh_disk_edge_next @@ -228,7 +266,7 @@ bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v) if (!BM_vert_in_edge(e, v)) return false; - if (bmesh_disk_count(v) != len || len == 0) + if (bmesh_disk_count_ex(v, len + 1) != len || len == 0) return false; e_iter = e; diff --git a/source/blender/bmesh/intern/bmesh_structure.h b/source/blender/bmesh/intern/bmesh_structure.h index 4a6247d7165..07f94796bb2 100644 --- a/source/blender/bmesh/intern/bmesh_structure.h +++ b/source/blender/bmesh/intern/bmesh_structure.h @@ -70,7 +70,9 @@ BMLoop *bmesh_radial_faceloop_find_vert(const BMFace *f, const BMVert *v) ATTR_W bool bmesh_radial_validate(int radlen, BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); /* EDGE UTILITIES */ -bool bmesh_edge_swapverts(BMEdge *e, BMVert *v_orig, BMVert *v_new) ATTR_NONNULL(); +void bmesh_disk_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL(); +void bmesh_edge_vert_swap(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL(); +void bmesh_disk_vert_replace(BMEdge *e, BMVert *v_dst, BMVert *v_src) ATTR_NONNULL(); BMEdge *bmesh_disk_edge_exists(const BMVert *v1, const BMVert *v2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); bool bmesh_disk_validate(int len, BMEdge *e, BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); diff --git a/source/blender/bmesh/intern/bmesh_structure_inline.h b/source/blender/bmesh/intern/bmesh_structure_inline.h index 5b7e890f5ea..64292194ae7 100644 --- a/source/blender/bmesh/intern/bmesh_structure_inline.h +++ b/source/blender/bmesh/intern/bmesh_structure_inline.h @@ -27,6 +27,7 @@ #ifndef __BMESH_STRUCTURE_INLINE_H__ #define __BMESH_STRUCTURE_INLINE_H__ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE BMDiskLink *bmesh_disk_edge_link_from_vert(const BMEdge *e, const BMVert *v) { BLI_assert(BM_vert_in_edge(e, v)); @@ -40,6 +41,7 @@ BLI_INLINE BMDiskLink *bmesh_disk_edge_link_from_vert(const BMEdge *e, const BMV * * \return Pointer to the next edge in the disk cycle for the vertex v. */ +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE BMEdge *bmesh_disk_edge_next_safe(const BMEdge *e, const BMVert *v) { if (v == e->v1) @@ -49,6 +51,7 @@ BLI_INLINE BMEdge *bmesh_disk_edge_next_safe(const BMEdge *e, const BMVert *v) return NULL; } +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) BLI_INLINE BMEdge *bmesh_disk_edge_prev_safe(const BMEdge *e, const BMVert *v) { if (v == e->v1) @@ -58,11 +61,13 @@ BLI_INLINE BMEdge *bmesh_disk_edge_prev_safe(const BMEdge *e, const BMVert *v) return NULL; } +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE BMEdge *bmesh_disk_edge_next(const BMEdge *e, const BMVert *v) { return BM_DISK_EDGE_NEXT(e, v); } +ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2) BLI_INLINE BMEdge *bmesh_disk_edge_prev(const BMEdge *e, const BMVert *v) { return BM_DISK_EDGE_PREV(e, v); diff --git a/source/blender/bmesh/intern/bmesh_walkers.c b/source/blender/bmesh/intern/bmesh_walkers.c index 20b56632099..d16eb572540 100644 --- a/source/blender/bmesh/intern/bmesh_walkers.c +++ b/source/blender/bmesh/intern/bmesh_walkers.c @@ -74,10 +74,11 @@ void *BMW_begin(BMWalker *walker, void *start) * a given type. The elements visited are filtered * by the bitmask 'searchmask'. */ -void BMW_init(BMWalker *walker, BMesh *bm, int type, - short mask_vert, short mask_edge, short mask_face, - BMWFlag flag, - int layer) +void BMW_init( + BMWalker *walker, BMesh *bm, int type, + short mask_vert, short mask_edge, short mask_face, + BMWFlag flag, + int layer) { memset(walker, 0, sizeof(BMWalker)); diff --git a/source/blender/bmesh/intern/bmesh_walkers.h b/source/blender/bmesh/intern/bmesh_walkers.h index d551ea9fba9..e84880dc61e 100644 --- a/source/blender/bmesh/intern/bmesh_walkers.h +++ b/source/blender/bmesh/intern/bmesh_walkers.h @@ -76,10 +76,11 @@ typedef struct BMWalker { /* initialize a walker. searchmask restricts some (not all) walkers to * elements with a specific tool flag set. flags is specific to each walker.*/ -void BMW_init(struct BMWalker *walker, BMesh *bm, int type, - short mask_vert, short mask_edge, short mask_face, - BMWFlag flag, - int layer); +void BMW_init( + struct BMWalker *walker, BMesh *bm, int type, + short mask_vert, short mask_edge, short mask_face, + BMWFlag flag, + int layer); void *BMW_begin(BMWalker *walker, void *start); void *BMW_step(struct BMWalker *walker); void BMW_end(struct BMWalker *walker); diff --git a/source/blender/bmesh/operators/bmo_connect_concave.c b/source/blender/bmesh/operators/bmo_connect_concave.c index a00f65bd10f..107aead6994 100644 --- a/source/blender/bmesh/operators/bmo_connect_concave.c +++ b/source/blender/bmesh/operators/bmo_connect_concave.c @@ -79,8 +79,8 @@ static bool bm_face_split_by_concave( struct Heap *pf_heap, struct EdgeHash *pf_ehash) { const int f_base_len = f_base->len; - int faces_array_tot = f_base->len - 3; - int edges_array_tot = f_base->len - 3; + int faces_array_tot = f_base_len - 3; + int edges_array_tot = f_base_len - 3; BMFace **faces_array = BLI_array_alloca(faces_array, faces_array_tot); BMEdge **edges_array = BLI_array_alloca(edges_array, edges_array_tot); const int quad_method = 0, ngon_method = 0; /* beauty */ diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c index ecb41363761..ac0466a74d2 100644 --- a/source/blender/bmesh/operators/bmo_dissolve.c +++ b/source/blender/bmesh/operators/bmo_dissolve.c @@ -494,7 +494,7 @@ void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op) static void bm_mesh_edge_collapse_flagged(BMesh *bm, const int flag, const short oflag) { - BMO_op_callf(bm, flag, "collapse edges=%fe", oflag); + BMO_op_callf(bm, flag, "collapse edges=%fe uvs=%b", oflag, true); } void bmo_dissolve_degenerate_exec(BMesh *bm, BMOperator *op) diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c index 27e140eb990..3d899bdef28 100644 --- a/source/blender/bmesh/operators/bmo_inset.c +++ b/source/blender/bmesh/operators/bmo_inset.c @@ -974,7 +974,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op) v_glue = v_split; } else { - BM_vert_splice(bm, v_split, v_glue); + BM_vert_splice(bm, v_glue, v_split); } } } diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c index 871bee64c19..73b6268e78b 100644 --- a/source/blender/bmesh/operators/bmo_removedoubles.c +++ b/source/blender/bmesh/operators/bmo_removedoubles.c @@ -380,8 +380,11 @@ void bmo_collapse_exec(BMesh *bm, BMOperator *op) float min[3], max[3], center[3]; unsigned int i, tot; BMOpSlot *slot_targetmap; - - BMO_op_callf(bm, op->flag, "collapse_uvs edges=%s", op, "edges"); + + if (BMO_slot_bool_get(op->slots_in, "uvs")) { + 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"); diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index 003c27671a5..410da65f828 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -163,10 +163,11 @@ static BMEdge *connect_smallest_face(BMesh *bm, BMVert *v_a, BMVert *v_b, BMFace return NULL; } /* calculates offset for co, based on fractal, sphere or smooth settings */ -static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params, float perc, - BMVert *vsta, BMVert *vend) +static void alter_co( + BMVert *v, BMEdge *UNUSED(e_orig), + const SubDParams *params, const float perc, + const BMVert *v_a, const BMVert *v_b) { - float tvec[3], fac; float *co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset_tmp); int i; @@ -178,28 +179,26 @@ static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params } else if (params->use_smooth) { /* we calculate an offset vector vec1[], to be added to *co */ - float len, nor[3], nor1[3], nor2[3], val; + float dir[3], tvec[3]; + float fac, len, val; - sub_v3_v3v3(nor, vsta->co, vend->co); - len = 0.5f * normalize_v3(nor); - - copy_v3_v3(nor1, vsta->no); - copy_v3_v3(nor2, vend->no); + sub_v3_v3v3(dir, v_a->co, v_b->co); + len = M_SQRT1_2 * normalize_v3(dir); /* cosine angle */ - fac = dot_v3v3(nor, nor1); - mul_v3_v3fl(tvec, nor1, fac); + fac = dot_v3v3(dir, v_a->no); + mul_v3_v3fl(tvec, v_a->no, fac); /* cosine angle */ - fac = -dot_v3v3(nor, nor2); - madd_v3_v3fl(tvec, nor2, fac); + fac = -dot_v3v3(dir, v_b->no); + madd_v3_v3fl(tvec, v_b->no, fac); /* falloff for multi subdivide */ val = fabsf(1.0f - 2.0f * fabsf(0.5f - perc)); val = bmesh_subd_falloff_calc(params->smooth_falloff, val); if (params->use_smooth_even) { - val *= BM_vert_calc_shell_factor(v); + val *= shell_v3v3_mid_normalized_to_dist(v_a->no, v_b->no); } mul_v3_fl(tvec, params->smooth * val * len); @@ -208,12 +207,13 @@ static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params } if (params->use_fractal) { - const float len = len_v3v3(vsta->co, vend->co); - float normal[3], co2[3], base1[3], base2[3]; + float normal[3], co2[3], base1[3], base2[3], tvec[3]; + const float len = len_v3v3(v_a->co, v_b->co); + float fac; fac = params->fractal * len; - mid_v3_v3v3(normal, vsta->no, vend->no); + mid_v3_v3v3(normal, v_a->no, v_b->no); ortho_basis_v3v3_v3(base1, base2, normal); add_v3_v3v3(co2, v->co, params->fractal_ofs); @@ -234,9 +234,12 @@ static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params * 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 */ - sub_v3_v3v3(tvec, v->co, co); if (params->shape_info.totlayer > 1) { + float tvec[3]; + + sub_v3_v3v3(tvec, v->co, co); + /* skip the last layer since its the temp */ i = params->shape_info.totlayer - 1; co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset); @@ -250,19 +253,21 @@ static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params /* assumes in the edge is the correct interpolated vertices already */ /* percent defines the interpolation, rad and flag are for special options */ /* results in new vertex with correct coordinate, vertex normal and weight group info */ -static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge, BMEdge *oedge, - const SubDParams *params, float percent, - float percent2, - BMEdge **out, BMVert *vsta, BMVert *vend) +static BMVert *bm_subdivide_edge_addvert( + BMesh *bm, BMEdge *edge, BMEdge *e_orig, + const SubDParams *params, + const float factor_edge_split, const float factor_subd, + BMVert *v_a, BMVert *v_b, + BMEdge **r_edge) { - BMVert *ev; + BMVert *v_new; - ev = BM_edge_split(bm, edge, edge->v1, out, percent); + v_new = BM_edge_split(bm, edge, edge->v1, r_edge, factor_edge_split); - BMO_elem_flag_enable(bm, ev, ELE_INNER); + BMO_elem_flag_enable(bm, v_new, ELE_INNER); /* offset for smooth or sphere or fractal */ - alter_co(ev, oedge, params, percent2, vsta, vend); + alter_co(v_new, e_orig, params, factor_subd, v_a, v_b); #if 0 //BMESH_TODO /* clip if needed by mirror modifier */ @@ -279,35 +284,40 @@ static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge, BMEdge *oedge, } #endif - interp_v3_v3v3(ev->no, vsta->no, vend->no, percent2); - normalize_v3(ev->no); + interp_v3_v3v3(v_new->no, v_a->no, v_b->no, factor_subd); + normalize_v3(v_new->no); - return ev; + return v_new; } -static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge, BMEdge *oedge, - int curpoint, int totpoint, const SubDParams *params, - BMEdge **newe, BMVert *vsta, BMVert *vend) +static BMVert *subdivide_edge_num( + BMesh *bm, BMEdge *edge, BMEdge *e_orig, + int curpoint, int totpoint, const SubDParams *params, + BMVert *v_a, BMVert *v_b, + BMEdge **r_edge) { - BMVert *ev; - float percent, percent2 = 0.0f; + BMVert *v_new; + float factor_edge_split, factor_subd; if (BMO_elem_flag_test(bm, edge, EDGE_PERCENT) && totpoint == 1) { - percent = BMO_slot_map_float_get(params->slot_edge_percents, edge); + factor_edge_split = BMO_slot_map_float_get(params->slot_edge_percents, edge); + factor_subd = 0.0f; } else { - percent = 1.0f / (float)(totpoint + 1 - curpoint); - percent2 = (float)(curpoint + 1) / (float)(totpoint + 1); - + factor_edge_split = 1.0f / (float)(totpoint + 1 - curpoint); + factor_subd = (float)(curpoint + 1) / (float)(totpoint + 1); } - ev = bm_subdivide_edge_addvert(bm, edge, oedge, params, percent, - percent2, newe, vsta, vend); - return ev; + v_new = bm_subdivide_edge_addvert( + bm, edge, e_orig, params, + factor_edge_split, factor_subd, + v_a, v_b, r_edge); + return v_new; } -static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, const SubDParams *params, - BMVert *vsta, BMVert *vend) +static void bm_subdivide_multicut( + BMesh *bm, BMEdge *edge, const SubDParams *params, + BMVert *v_a, BMVert *v_b) { BMEdge *eed = edge, *e_new, e_tmp = *edge; BMVert *v, v1_tmp = *edge->v1, v2_tmp = *edge->v2, *v1 = edge->v1, *v2 = edge->v2; @@ -317,7 +327,7 @@ static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, const SubDParams *par e_tmp.v2 = &v2_tmp; for (i = 0; i < numcuts; i++) { - v = subdivideedgenum(bm, eed, &e_tmp, i, params->numcuts, params, &e_new, vsta, vend); + v = subdivide_edge_num(bm, eed, &e_tmp, i, params->numcuts, params, v_a, v_b, &e_new); BMO_elem_flag_enable(bm, v, SUBD_SPLIT | ELE_SPLIT); BMO_elem_flag_enable(bm, eed, SUBD_SPLIT | ELE_SPLIT); @@ -434,7 +444,7 @@ static void quad_2edge_split_innervert(BMesh *bm, BMFace *UNUSED(face), BMVert * e = connect_smallest_face(bm, verts[i], verts[numcuts + (numcuts - i)], &f_new); e_tmp = *e; - v = bm_subdivide_edge_addvert(bm, e, &e_tmp, params, 0.5f, 0.5f, &e_new, e->v1, e->v2); + v = bm_subdivide_edge_addvert(bm, e, &e_tmp, params, 0.5f, 0.5f, e->v1, e->v2, &e_new); if (i != numcuts - 1) { connect_smallest_face(bm, v_last, v, &f_new); @@ -577,8 +587,7 @@ static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts e_tmp = *e; for (a = 0; a < numcuts; a++) { - v = subdivideedgenum(bm, e, &e_tmp, a, numcuts, params, &e_new, - v1, v2); + v = subdivide_edge_num(bm, e, &e_tmp, a, numcuts, params, v1, v2, &e_new); BMESH_ASSERT(v != NULL); @@ -685,8 +694,7 @@ static void tri_3edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts, e_tmp.v1 = &v1_tmp; e_tmp.v2 = &v2_tmp; for (j = 0; j < i; j++) { - v = subdivideedgenum(bm, e, &e_tmp, j, i, params, &e_new, - verts[a], verts[b]); + v = subdivide_edge_num(bm, e, &e_tmp, j, i, params, verts[a], verts[b], &e_new); lines[i + 1][j + 1] = v; BMO_elem_flag_enable(bm, e_new, ELE_INNER); diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c index da1991a187d..964d0b1dfc6 100644 --- a/source/blender/bmesh/operators/bmo_utils.c +++ b/source/blender/bmesh/operators/bmo_utils.c @@ -208,7 +208,7 @@ static void bmo_region_extend_expand( BMEdge *e; BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { - if (!BMO_elem_flag_test(bm, e, SEL_ORIG)) { + if (!BMO_elem_flag_test(bm, e, SEL_ORIG) && !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { found = true; break; } @@ -221,7 +221,7 @@ static void bmo_region_extend_expand( BMEdge *e; BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { - if (!BMO_elem_flag_test(bm, e, SEL_FLAG)) { + if (!BMO_elem_flag_test(bm, e, SEL_FLAG) && !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { BMO_elem_flag_enable(bm, e, SEL_FLAG); BMO_elem_flag_enable(bm, BM_edge_other_vert(e, v), SEL_FLAG); } @@ -232,7 +232,7 @@ static void bmo_region_extend_expand( BMFace *f; BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) { - if (!BMO_elem_flag_test(bm, f, SEL_FLAG)) { + if (!BMO_elem_flag_test(bm, f, SEL_FLAG) && !BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { bmo_face_flag_set_flush(bm, f, SEL_FLAG, true); } } @@ -243,7 +243,7 @@ static void bmo_region_extend_expand( BMEdge *e; BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { if (BM_edge_is_wire(e)) { - if (!BMO_elem_flag_test(bm, e, SEL_FLAG)) { + if (!BMO_elem_flag_test(bm, e, SEL_FLAG) && !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { BMO_elem_flag_enable(bm, e, SEL_FLAG); BMO_elem_flag_enable(bm, BM_edge_other_vert(e, v), SEL_FLAG); } @@ -267,7 +267,9 @@ static void bmo_region_extend_expand( BMFace *f_other; BM_ITER_ELEM (f_other, &fiter, l->e, BM_FACES_OF_EDGE) { - if (!BMO_elem_flag_test(bm, f_other, SEL_ORIG | SEL_FLAG)) { + if (!BMO_elem_flag_test(bm, f_other, SEL_ORIG | SEL_FLAG) && + !BM_elem_flag_test(f_other, BM_ELEM_HIDDEN)) + { BMO_elem_flag_enable(bm, f_other, SEL_FLAG); } } @@ -277,7 +279,9 @@ static void bmo_region_extend_expand( BMFace *f_other; BM_ITER_ELEM (f_other, &fiter, l->v, BM_FACES_OF_VERT) { - if (!BMO_elem_flag_test(bm, f_other, SEL_ORIG | SEL_FLAG)) { + if (!BMO_elem_flag_test(bm, f_other, SEL_ORIG | SEL_FLAG) && + !BM_elem_flag_test(f_other, BM_ELEM_HIDDEN)) + { BMO_elem_flag_enable(bm, f_other, SEL_FLAG); } } diff --git a/source/blender/bmesh/tools/bmesh_beautify.c b/source/blender/bmesh/tools/bmesh_beautify.c index b64c3aab5d7..19fe492c670 100644 --- a/source/blender/bmesh/tools/bmesh_beautify.c +++ b/source/blender/bmesh/tools/bmesh_beautify.c @@ -274,11 +274,12 @@ BLI_INLINE bool edge_in_array(const BMEdge *e, const BMEdge **edge_array, const } /* recalc an edge in the heap (surrounding geometry has changed) */ -static void bm_edge_update_beauty_cost_single(BMEdge *e, Heap *eheap, HeapNode **eheap_table, GSet **edge_state_arr, - /* only for testing the edge is in the array */ - const BMEdge **edge_array, const int edge_array_len, +static void bm_edge_update_beauty_cost_single( + BMEdge *e, Heap *eheap, HeapNode **eheap_table, GSet **edge_state_arr, + /* only for testing the edge is in the array */ + const BMEdge **edge_array, const int edge_array_len, - const short flag, const short method) + const short flag, const short method) { if (edge_in_array(e, edge_array, edge_array_len)) { const int i = BM_elem_index_get(e); @@ -316,10 +317,11 @@ static void bm_edge_update_beauty_cost_single(BMEdge *e, Heap *eheap, HeapNode * } /* we have rotated an edge, tag other edges and clear this one */ -static void bm_edge_update_beauty_cost(BMEdge *e, Heap *eheap, HeapNode **eheap_table, GSet **edge_state_arr, - const BMEdge **edge_array, const int edge_array_len, - /* only for testing the edge is in the array */ - const short flag, const short method) +static void bm_edge_update_beauty_cost( + BMEdge *e, Heap *eheap, HeapNode **eheap_table, GSet **edge_state_arr, + const BMEdge **edge_array, const int edge_array_len, + /* only for testing the edge is in the array */ + const short flag, const short method) { int i; diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index a2a0f974a79..252c16e8919 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -244,8 +244,9 @@ static void create_mesh_bmvert(BMesh *bm, VMesh *vm, int i, int j, int k, BMVert BM_elem_flag_disable(nv->v, BM_ELEM_TAG); } -static void copy_mesh_vert(VMesh *vm, int ito, int jto, int kto, - int ifrom, int jfrom, int kfrom) +static void copy_mesh_vert( + VMesh *vm, int ito, int jto, int kto, + int ifrom, int jfrom, int kfrom) { NewVert *nvto, *nvfrom; @@ -361,8 +362,9 @@ static BMFace *boundvert_rep_face(BoundVert *v) * * \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 **face_arr, BMFace *facerep, int mat_nr, bool do_interp) +static BMFace *bev_create_ngon( + BMesh *bm, BMVert **vert_arr, const int totv, + BMFace **face_arr, BMFace *facerep, int mat_nr, bool do_interp) { BMIter iter; BMLoop *l; @@ -402,15 +404,17 @@ static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, const int totv, return f; } -static BMFace *bev_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, - BMFace *facerep, int mat_nr, bool do_interp) +static BMFace *bev_create_quad_tri( + BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, + BMFace *facerep, int mat_nr, bool do_interp) { BMVert *varr[4] = {v1, v2, v3, v4}; return bev_create_ngon(bm, varr, v4 ? 4 : 3, NULL, facerep, mat_nr, do_interp); } -static BMFace *bev_create_quad_tri_ex(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, - BMFace *f1, BMFace *f2, BMFace *f3, BMFace *f4, int mat_nr) +static BMFace *bev_create_quad_tri_ex( + BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, + BMFace *f1, BMFace *f2, BMFace *f3, BMFace *f4, int mat_nr) { BMVert *varr[4] = {v1, v2, v3, v4}; BMFace *farr[4] = {f1, f2, f3, f4}; @@ -419,8 +423,9 @@ static BMFace *bev_create_quad_tri_ex(BMesh *bm, BMVert *v1, BMVert *v2, BMVert /* Is Loop layer layer_index contiguous across shared vertex of l1 and l2? */ -static bool contig_ldata_across_loops(BMesh *bm, BMLoop *l1, BMLoop *l2, - int layer_index) +static bool contig_ldata_across_loops( + BMesh *bm, BMLoop *l1, BMLoop *l2, + int layer_index) { const int offset = bm->ldata.layers[layer_index].offset; const int type = bm->ldata.layers[layer_index].type; @@ -478,7 +483,10 @@ static bool contig_ldata_across_edge(BMesh *bm, BMEdge *e, BMFace *f1, BMFace *f return true; } -/* Like bev_create_quad_tri, but when verts straddle an old edge. +/** + * Like #bev_create_quad_tri, but when verts straddle an old edge. + * + * <pre> * e * | * v1+---|---+v4 @@ -487,13 +495,16 @@ static bool contig_ldata_across_edge(BMesh *bm, BMEdge *e, BMFace *f1, BMFace *f * v2+---|---+v3 * | * f1 | f2 + * </pre> * * Most CustomData for loops can be interpolated in their respective * faces' loops, but for UVs and other 'has_math_cd' layers, only * do this if the UVs are continuous across the edge e, otherwise pick * one side (f1, arbitrarily), and interpolate them all on that side. - * For face data, use f1 (arbitrarily) as face representative. */ -static BMFace *bev_create_quad_straddle(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, + * For face data, use f1 (arbitrarily) as face representative. + */ +static BMFace *bev_create_quad_straddle( + BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, BMFace *f1, BMFace *f2, int mat_nr, bool is_seam) { BMFace *f, *facerep; @@ -737,8 +748,9 @@ static bool offset_meet_edge(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, float meetc * already, prefer to keep the offset the same on this end. * Otherwise, pick a point between the two intersection points on emid that minimizes * the sum of squares of errors from desired offset. */ -static void offset_on_edge_between(BevelParams *bp, EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, - BMVert *v, float meetco[3]) +static void offset_on_edge_between( + BevelParams *bp, EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, + BMVert *v, float meetco[3]) { float d, ang1, ang2, sina1, sina2, lambda; float meet1[3], meet2[3]; @@ -793,8 +805,9 @@ static void offset_on_edge_between(BevelParams *bp, EdgeHalf *e1, EdgeHalf *e2, * Viewed from the vertex normal side, the CCW order of the edges is e1, emid, e2. * The offset lines may not meet exactly: the lines may be angled so that they can't meet. * In that case, pick the offset_on_edge_between. */ -static void offset_in_two_planes(BevelParams *bp, EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, - BMVert *v, float meetco[3]) +static void offset_in_two_planes( + BevelParams *bp, EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, + BMVert *v, float meetco[3]) { float dir1[3], dir2[3], dirmid[3], norm_perp1[3], norm_perp2[3], off1a[3], off1b[3], off2a[3], off2b[3], isect2[3], @@ -1079,8 +1092,9 @@ static int bev_ccw_test(BMEdge *a, BMEdge *b, BMFace *f) * and B has the right side as columns - both extended into homogeneous coords. * So M = B*(Ainverse). Doing Ainverse by hand gives the code below. */ -static bool make_unit_square_map(const float va[3], const float vmid[3], const float vb[3], - float r_mat[4][4]) +static bool make_unit_square_map( + const float va[3], const float vmid[3], const float vb[3], + float r_mat[4][4]) { float vo[3], vd[3], vb_vmid[3], va_vmid[3], vddir[3]; @@ -1128,8 +1142,9 @@ static bool make_unit_square_map(const float va[3], const float vmid[3], const f * and 1/2{va+vb+vc-vd} * and Blender matrices have cols at m[i][*]. */ -static void make_unit_cube_map(const float va[3], const float vb[3], const float vc[3], - const float vd[3], float r_mat[4][4]) +static void make_unit_cube_map( + const float va[3], const float vb[3], const float vc[3], + const float vd[3], float r_mat[4][4]) { copy_v3_v3(r_mat[0], va); sub_v3_v3(r_mat[0], vb); @@ -1861,9 +1876,10 @@ static void vmesh_center(VMesh *vm, float r_cent[3]) } } -static void avg4(float co[3], - const NewVert *v0, const NewVert *v1, - const NewVert *v2, const NewVert *v3) +static void avg4( + float co[3], + const NewVert *v0, const NewVert *v1, + const NewVert *v2, const NewVert *v3) { add_v3_v3v3(co, v0->co, v1->co); add_v3_v3(co, v2->co); @@ -3755,10 +3771,11 @@ static float bevel_limit_offset(BMesh *bm, BevelParams *bp) * * \warning all tagged edges _must_ be manifold. */ -void BM_mesh_bevel(BMesh *bm, const float offset, const int offset_type, - const float segments, const float profile, - const bool vertex_only, const bool use_weights, const bool limit_offset, - const struct MDeformVert *dvert, const int vertex_group, const int mat) +void BM_mesh_bevel( + BMesh *bm, const float offset, const int offset_type, + const float segments, const float profile, + const bool vertex_only, const bool use_weights, const bool limit_offset, + const struct MDeformVert *dvert, const int vertex_group, const int mat) { BMIter iter; BMVert *v, *v_next; diff --git a/source/blender/bmesh/tools/bmesh_bevel.h b/source/blender/bmesh/tools/bmesh_bevel.h index 52d8faa5401..b4bb6c56b7d 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.h +++ b/source/blender/bmesh/tools/bmesh_bevel.h @@ -29,9 +29,10 @@ struct MDeformVert; -void BM_mesh_bevel(BMesh *bm, const float offset, const int offset_type, const float segments, - const float profile, const bool vertex_only, const bool use_weights, - const bool limit_offset, const struct MDeformVert *dvert, const int vertex_group, - const int mat); +void BM_mesh_bevel( + BMesh *bm, const float offset, const int offset_type, const float segments, + const float profile, const bool vertex_only, const bool use_weights, + const bool limit_offset, const struct MDeformVert *dvert, const int vertex_group, + const int mat); #endif /* __BMESH_BEVEL_H__ */ diff --git a/source/blender/bmesh/tools/bmesh_decimate.h b/source/blender/bmesh/tools/bmesh_decimate.h index a1b26990587..1efa829c60d 100644 --- a/source/blender/bmesh/tools/bmesh_decimate.h +++ b/source/blender/bmesh/tools/bmesh_decimate.h @@ -32,13 +32,15 @@ void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, c void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool tag_only); void BM_mesh_decimate_unsubdivide(BMesh *bm, const int iterations); -void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, - const BMO_Delimit delimit, - BMVert **vinput_arr, const int vinput_len, - BMEdge **einput_arr, const int einput_len, - const short oflag_out); -void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, - const BMO_Delimit delimit); +void BM_mesh_decimate_dissolve_ex( + BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, + const BMO_Delimit delimit, + BMVert **vinput_arr, const int vinput_len, + BMEdge **einput_arr, const int einput_len, + const short oflag_out); +void BM_mesh_decimate_dissolve( + BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, + const BMO_Delimit delimit); /* these weights are accumulated so too high values may reach 'inf' too quickly */ #define BM_MESH_DECIM_WEIGHT_MAX 100000.0f diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c index 811a144fc39..47c41c44d81 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c @@ -112,18 +112,19 @@ static void bm_decim_build_quadrics(BMesh *bm, Quadric *vquadrics) } -static void bm_decim_calc_target_co(BMEdge *e, float optimize_co[3], - const Quadric *vquadrics) +static void bm_decim_calc_target_co( + BMEdge *e, float optimize_co[3], + const Quadric *vquadrics) { /* compute an edge contraction target for edge 'e' * this is computed by summing it's vertices quadrics and * optimizing the result. */ Quadric q; - BLI_quadric_add_qu_ququ(&q, - &vquadrics[BM_elem_index_get(e->v1)], - &vquadrics[BM_elem_index_get(e->v2)]); - + BLI_quadric_add_qu_ququ( + &q, + &vquadrics[BM_elem_index_get(e->v1)], + &vquadrics[BM_elem_index_get(e->v2)]); if (BLI_quadric_optimize(&q, optimize_co, OPTIMIZE_EPS)) { return; /* all is good */ @@ -183,9 +184,10 @@ static bool bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_ return false; } -static void bm_decim_build_edge_cost_single(BMEdge *e, - const Quadric *vquadrics, const float *vweights, - Heap *eheap, HeapNode **eheap_table) +static void bm_decim_build_edge_cost_single( + BMEdge *e, + const Quadric *vquadrics, const float *vweights, + Heap *eheap, HeapNode **eheap_table) { const Quadric *q1, *q2; float optimize_co[3]; @@ -258,16 +260,18 @@ static void bm_decim_build_edge_cost_single(BMEdge *e, /* use this for degenerate cases - add back to the heap with an invalid cost, * this way it may be calculated again if surrounding geometry changes */ -static void bm_decim_invalid_edge_cost_single(BMEdge *e, - Heap *eheap, HeapNode **eheap_table) +static void bm_decim_invalid_edge_cost_single( + BMEdge *e, + Heap *eheap, HeapNode **eheap_table) { BLI_assert(eheap_table[BM_elem_index_get(e)] == NULL); eheap_table[BM_elem_index_get(e)] = BLI_heap_insert(eheap, COST_INVALID, e); } -static void bm_decim_build_edge_cost(BMesh *bm, - const Quadric *vquadrics, const float *vweights, - Heap *eheap, HeapNode **eheap_table) +static void bm_decim_build_edge_cost( + BMesh *bm, + const Quadric *vquadrics, const float *vweights, + Heap *eheap, HeapNode **eheap_table) { BMIter iter; BMEdge *e; @@ -442,8 +446,9 @@ static void bm_decim_triangulate_end(BMesh *bm) /** * \param v is the target to merge into. */ -static void bm_edge_collapse_loop_customdata(BMesh *bm, BMLoop *l, BMVert *v_clear, BMVert *v_other, - const float customdata_fac) +static void bm_edge_collapse_loop_customdata( + BMesh *bm, BMLoop *l, BMVert *v_clear, BMVert *v_other, + const float customdata_fac) { /* disable seam check - the seam check would have to be done per layer, its not really that important */ //#define USE_SEAM @@ -698,15 +703,16 @@ static bool bm_edge_collapse_is_degenerate_topology(BMEdge *e_first) * \param e_clear_other let caller know what edges we remove besides \a e_clear * \param customdata_flag merge factor, scales from 0 - 1 ('v_clear' -> 'v_other') */ -static bool bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e_clear_other[2], +static bool bm_edge_collapse( + BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e_clear_other[2], #ifdef USE_CUSTOMDATA - const CD_UseFlag customdata_flag, - const float customdata_fac + const CD_UseFlag customdata_flag, + const float customdata_fac #else - const CD_UseFlag UNUSED(customdata_flag), - const float UNUSED(customdata_fac) + const CD_UseFlag UNUSED(customdata_flag), + const float UNUSED(customdata_fac) #endif - ) + ) { BMVert *v_other; @@ -782,12 +788,12 @@ static bool bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_ BM_edge_kill(bm, e_clear); v_other->head.hflag |= v_clear->head.hflag; - BM_vert_splice(bm, v_clear, v_other); + BM_vert_splice(bm, v_other, v_clear); e_a_other[1]->head.hflag |= e_a_other[0]->head.hflag; e_b_other[1]->head.hflag |= e_b_other[0]->head.hflag; - BM_edge_splice(bm, e_a_other[0], e_a_other[1]); - BM_edge_splice(bm, e_b_other[0], e_b_other[1]); + BM_edge_splice(bm, e_a_other[1], e_a_other[0]); + BM_edge_splice(bm, e_b_other[1], e_b_other[0]); // BM_mesh_validate(bm); @@ -831,10 +837,10 @@ static bool bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_ BM_edge_kill(bm, e_clear); v_other->head.hflag |= v_clear->head.hflag; - BM_vert_splice(bm, v_clear, v_other); + BM_vert_splice(bm, v_other, v_clear); e_a_other[1]->head.hflag |= e_a_other[0]->head.hflag; - BM_edge_splice(bm, e_a_other[0], e_a_other[1]); + BM_edge_splice(bm, e_a_other[1], e_a_other[0]); // BM_mesh_validate(bm); @@ -847,10 +853,11 @@ static bool bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_ /* collapse e the edge, removing e->v2 */ -static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, - Quadric *vquadrics, float *vweights, - Heap *eheap, HeapNode **eheap_table, - const CD_UseFlag customdata_flag) +static void bm_decim_edge_collapse( + BMesh *bm, BMEdge *e, + Quadric *vquadrics, float *vweights, + Heap *eheap, HeapNode **eheap_table, + const CD_UseFlag customdata_flag) { int e_clear_other[2]; BMVert *v_other = e->v1; diff --git a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c index 096349e8e9c..09c7b932b7a 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c +++ b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c @@ -98,11 +98,12 @@ fail: } -void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, - const BMO_Delimit delimit, - BMVert **vinput_arr, const int vinput_len, - BMEdge **einput_arr, const int einput_len, - const short oflag_out) +void BM_mesh_decimate_dissolve_ex( + BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, + const BMO_Delimit delimit, + BMVert **vinput_arr, const int vinput_len, + BMEdge **einput_arr, const int einput_len, + const short oflag_out) { const int eheap_table_len = do_dissolve_boundaries ? einput_len : max_ii(einput_len, vinput_len); void *_heap_table = MEM_mallocN(sizeof(HeapNode *) * eheap_table_len, __func__); @@ -316,8 +317,9 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool MEM_freeN(_heap_table); } -void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, - const BMO_Delimit delimit) +void BM_mesh_decimate_dissolve( + BMesh *bm, const float angle_limit, const bool do_dissolve_boundaries, + const BMO_Delimit delimit) { int vinput_len; int einput_len; diff --git a/source/blender/bmesh/tools/bmesh_edgenet.c b/source/blender/bmesh/tools/bmesh_edgenet.c index 1328b81b746..e93ffe6b141 100644 --- a/source/blender/bmesh/tools/bmesh_edgenet.c +++ b/source/blender/bmesh/tools/bmesh_edgenet.c @@ -450,8 +450,9 @@ static LinkNode *bm_edgenet_path_calc_best( * \param use_edge_tag Only fill tagged edges. * \param face_oflag if nonzero, apply all new faces with this bmo flag. */ -void BM_mesh_edgenet(BMesh *bm, - const bool use_edge_tag, const bool use_new_face_tag) +void BM_mesh_edgenet( + BMesh *bm, + const bool use_edge_tag, const bool use_new_face_tag) { VertNetInfo *vnet_info = MEM_callocN(sizeof(*vnet_info) * (size_t)bm->totvert, __func__); BLI_mempool *edge_queue_pool = BLI_mempool_create(sizeof(LinkNode), 0, 512, BLI_MEMPOOL_NOP); diff --git a/source/blender/bmesh/tools/bmesh_edgenet.h b/source/blender/bmesh/tools/bmesh_edgenet.h index 327a7f5aa23..1ad5cadae7c 100644 --- a/source/blender/bmesh/tools/bmesh_edgenet.h +++ b/source/blender/bmesh/tools/bmesh_edgenet.h @@ -27,7 +27,8 @@ * \ingroup bmesh */ -void BM_mesh_edgenet(BMesh *bm, - const bool use_edge_tag, const bool use_new_face_tag); +void BM_mesh_edgenet( + BMesh *bm, + const bool use_edge_tag, const bool use_new_face_tag); #endif /* __BMESH_EDGENET_H__ */ diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.c b/source/blender/bmesh/tools/bmesh_edgesplit.c index 947b77675d8..74b1660080b 100644 --- a/source/blender/bmesh/tools/bmesh_edgesplit.c +++ b/source/blender/bmesh/tools/bmesh_edgesplit.c @@ -35,70 +35,16 @@ #include "bmesh_edgesplit.h" /* own include */ - /** - * Remove the BM_ELEM_TAG flag for edges we cant split - * - * un-tag edges not connected to other tagged edges, - * unless they are on a boundary + * \param use_verts Use flagged verts instead of edges. + * \param use_non_manifold Split non-manifold edges (a little slower, must check for doubles). + * \param tag_only Only split tagged edges. + * \param copy_select Copy selection history. */ -static void bm_edgesplit_validate_seams(BMesh *bm) -{ - BMIter iter; - BMEdge *e; - - unsigned char *vtouch; - - BM_mesh_elem_index_ensure(bm, BM_VERT); - - vtouch = MEM_callocN(sizeof(char) * bm->totvert, __func__); - - /* tag all boundary verts so as not to untag an edge which is inbetween only 2 faces [] */ - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - - /* unrelated to flag assignment in this function - since this is the - * only place we loop over all edges, disable tag */ - BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG); - - if (e->l == NULL) { - BM_elem_flag_disable(e, BM_ELEM_TAG); - } - else if (BM_edge_is_boundary(e)) { - unsigned char *vt; - vt = &vtouch[BM_elem_index_get(e->v1)]; if (*vt < 2) (*vt)++; - vt = &vtouch[BM_elem_index_get(e->v2)]; if (*vt < 2) (*vt)++; - - /* while the boundary verts need to be tagged, - * the edge its self can't be split */ - BM_elem_flag_disable(e, BM_ELEM_TAG); - } - } - - /* single marked edges unconnected to any other marked edges - * are illegal, go through and unmark them */ - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e, BM_ELEM_TAG)) { - /* 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)++; - } - } - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e, BM_ELEM_TAG)) { - if (vtouch[BM_elem_index_get(e->v1)] == 1 && - vtouch[BM_elem_index_get(e->v2)] == 1) - { - BM_elem_flag_disable(e, BM_ELEM_TAG); - } - } - } - - MEM_freeN(vtouch); -} - -void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, const bool copy_select) +void BM_mesh_edgesplit( + BMesh *bm, + const bool use_verts, + const bool tag_only, const bool copy_select) { BMIter iter; BMEdge *e; @@ -142,43 +88,13 @@ void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, con } } - bm_edgesplit_validate_seams(bm); - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(e, BM_ELEM_TAG)) { - /* this flag gets copied so we can be sure duplicate edges get it too (important) */ - BM_elem_flag_enable(e, BM_ELEM_INTERNAL_TAG); - - /* keep splitting until each loop has its own edge */ - while (!BM_edge_is_boundary(e)) { - BMLoop *l_sep = e->l; - bmesh_edge_separate(bm, e, l_sep, copy_select); - BLI_assert(l_sep->e != e); - - if (use_ese) { - BMEditSelection *ese = BLI_ghash_lookup(ese_gh, e); - if (UNLIKELY(ese)) { - BM_select_history_store_after_notest(bm, ese, l_sep->e); - } - } - } - BM_elem_flag_enable(e->v1, BM_ELEM_TAG); BM_elem_flag_enable(e->v2, BM_ELEM_TAG); } } - if (use_verts) { - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e->v1, BM_ELEM_TAG) == false) { - BM_elem_flag_disable(e->v1, BM_ELEM_TAG); - } - if (BM_elem_flag_test(e->v2, BM_ELEM_TAG) == false) { - BM_elem_flag_disable(e->v2, BM_ELEM_TAG); - } - } - } - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(e, BM_ELEM_TAG)) { unsigned int i; @@ -191,7 +107,7 @@ void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, con BMVert **vtar; int vtar_len; - bmesh_vert_separate(bm, v, &vtar, &vtar_len, copy_select); + BM_vert_separate_hflag(bm, v, BM_ELEM_TAG, copy_select, &vtar, &vtar_len); /* first value is always in 'v' */ if (vtar_len > 1) { @@ -208,13 +124,22 @@ void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, con MEM_freeN(vtar); } else { - bmesh_vert_separate(bm, v, NULL, NULL, copy_select); + BM_vert_separate_hflag(bm, v, BM_ELEM_TAG, copy_select, NULL, NULL); } } } } } +#ifndef NDEBUG + /* ensure we don't have any double edges! */ + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_TAG)) { + BLI_assert(BM_edge_find_double(e) == NULL); + } + } +#endif + if (use_ese) { BLI_ghash_free(ese_gh, NULL, NULL); } diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.h b/source/blender/bmesh/tools/bmesh_edgesplit.h index bd66f6a9e2f..26040077f43 100644 --- a/source/blender/bmesh/tools/bmesh_edgesplit.h +++ b/source/blender/bmesh/tools/bmesh_edgesplit.h @@ -27,6 +27,9 @@ * \ingroup bmesh */ -void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, const bool copy_select); +void BM_mesh_edgesplit( + BMesh *bm, + const bool use_verts, + const bool tag_only, const bool copy_select); #endif /* __BMESH_EDGESPLIT_H__ */ diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c index ceb6ded5a43..fc12bce8563 100644 --- a/source/blender/bmesh/tools/bmesh_intersect.c +++ b/source/blender/bmesh/tools/bmesh_intersect.c @@ -1006,7 +1006,7 @@ bool BM_mesh_intersect( !BM_vert_splice_check_double(v_prev, vi) && !BM_vert_pair_share_face_check(v_prev, vi)) { - BM_vert_splice(bm, v_prev, vi); + BM_vert_splice(bm, vi, v_prev); } else { copy_v3_v3(v_prev->co, vi->co); @@ -1228,7 +1228,7 @@ bool BM_mesh_intersect( if (!BM_edge_exists(UNPACK2(splice_ls[i])) && !BM_vert_splice_check_double(UNPACK2(splice_ls[i]))) { - BM_vert_splice(bm, UNPACK2(splice_ls[i])); + BM_vert_splice(bm, splice_ls[i][1], splice_ls[i][0]); } } } @@ -1267,10 +1267,8 @@ bool BM_mesh_intersect( face_edges_split(bm, f, e_ls_base); } } -#else - (void)totface_orig; #endif /* USE_NET */ - + (void)totface_orig; #ifdef USE_SEPARATE if (use_separate) { diff --git a/source/blender/bmesh/tools/bmesh_region_match.c b/source/blender/bmesh/tools/bmesh_region_match.c index 484eea73bbe..72c3bc90599 100644 --- a/source/blender/bmesh/tools/bmesh_region_match.c +++ b/source/blender/bmesh/tools/bmesh_region_match.c @@ -190,14 +190,16 @@ static bool ghashutil_bmelem_indexcmp(const void *a, const void *b) return (a != b); } -static GHash *ghash_bmelem_new_ex(const char *info, - const unsigned int nentries_reserve) +static GHash *ghash_bmelem_new_ex( + const char *info, + const unsigned int nentries_reserve) { return BLI_ghash_new_ex(ghashutil_bmelem_indexhash, ghashutil_bmelem_indexcmp, info, nentries_reserve); } -static GSet *gset_bmelem_new_ex(const char *info, - const unsigned int nentries_reserve) +static GSet *gset_bmelem_new_ex( + const char *info, + const unsigned int nentries_reserve) { return BLI_gset_new_ex(ghashutil_bmelem_indexhash, ghashutil_bmelem_indexcmp, info, nentries_reserve); } diff --git a/source/blender/bmesh/tools/bmesh_triangulate.h b/source/blender/bmesh/tools/bmesh_triangulate.h index 550109ffef9..c6a5e04dfb2 100644 --- a/source/blender/bmesh/tools/bmesh_triangulate.h +++ b/source/blender/bmesh/tools/bmesh_triangulate.h @@ -30,7 +30,8 @@ #ifndef __BMESH_TRIANGULATE_H__ #define __BMESH_TRIANGULATE_H__ -void BM_mesh_triangulate(BMesh *bm, const int quad_method, const int ngon_method, const bool tag_only, - BMOperator *op, BMOpSlot *slot_facemap_out); +void BM_mesh_triangulate( + BMesh *bm, const int quad_method, const int ngon_method, const bool tag_only, + BMOperator *op, BMOpSlot *slot_facemap_out); #endif /* __BMESH_TRIANGULATE_H__ */ diff --git a/source/blender/bmesh/tools/bmesh_wireframe.c b/source/blender/bmesh/tools/bmesh_wireframe.c index 79fea3e5da1..87e571a49aa 100644 --- a/source/blender/bmesh/tools/bmesh_wireframe.c +++ b/source/blender/bmesh/tools/bmesh_wireframe.c @@ -55,8 +55,9 @@ static BMLoop *bm_edge_tag_faceloop(BMEdge *e) return NULL; } -static void bm_vert_boundary_tangent(BMVert *v, float r_no[3], float r_no_face[3], - BMVert **r_va_other, BMVert **r_vb_other) +static void bm_vert_boundary_tangent( + BMVert *v, float r_no[3], float r_no_face[3], + BMVert **r_va_other, BMVert **r_vb_other) { BMIter iter; BMEdge *e_iter; diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp index b2d9aed579b..ac8ac2b9867 100644 --- a/source/blender/collada/SceneExporter.cpp +++ b/source/blender/collada/SceneExporter.cpp @@ -150,7 +150,7 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce) if (!instance_controller_created) { COLLADASW::InstanceGeometry instGeom(mSW); instGeom.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, this->export_settings->use_object_instantiation))); - + instGeom.setName(translate_id(id_name(ob))); InstanceWriter::add_material_bindings(instGeom.getBindMaterial(), ob, this->export_settings->active_uv_only); instGeom.add(); diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index f15efa89ea6..d3813e2fb7a 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -131,7 +131,7 @@ Object *bc_add_object(Scene *scene, int type, const char *name) { Object *ob = BKE_object_add_only_object(G.main, type, name); - ob->data = BKE_object_obdata_add_from_type(G.main, type); + ob->data = BKE_object_obdata_add_from_type(G.main, type, name); ob->lay = scene->lay; DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp index fdd75033aea..572e63a2ced 100644 --- a/source/blender/compositor/nodes/COM_ImageNode.cpp +++ b/source/blender/compositor/nodes/COM_ImageNode.cpp @@ -79,7 +79,6 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo int numberOfOutputs = this->getNumberOfOutputSockets(); bool outputStraightAlpha = (editorNode->custom1 & CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT) != 0; BKE_image_user_frame_calc(imageuser, context.getFramenumber(), 0); - NodeOperation *combined_operation = NULL; /* force a load, we assume iuser index will be set OK anyway */ if (image && image->type == IMA_TYPE_MULTILAYER) { bool is_multilayer_ok = false; @@ -124,44 +123,40 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo } } - if (STREQ(bnodeSocket->identifier, "Alpha")) { - BLI_assert(combined_operation != NULL); - NodeOutput *outputSocket = this->getOutputSocket(index); - SeparateChannelOperation *separate_operation; - separate_operation = new SeparateChannelOperation(); - separate_operation->setChannel(3); - converter.addOperation(separate_operation); - converter.addLink(combined_operation->getOutputSocket(), separate_operation->getInputSocket(0)); - converter.mapOutputSocket(outputSocket, separate_operation->getOutputSocket()); - operation = separate_operation; - } - else { - if (rpass) { - switch (rpass->channels) { - case 1: - operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index, - rpass->passtype, view, COM_DT_VALUE); - break; - /* using image operations for both 3 and 4 channels (RGB and RGBA respectively) */ - /* XXX any way to detect actual vector images? */ - case 3: - operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index, - rpass->passtype, view, COM_DT_VECTOR); - break; - case 4: - operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index, - rpass->passtype, view, COM_DT_COLOR); - break; - default: - /* dummy operation is added below */ - break; - } - if (index == 0 && operation) { - converter.addPreview(operation->getOutputSocket()); - } - if (STREQ(rpass->chan_id, "RGBA")) { - combined_operation = operation; - } + if (rpass) { + switch (rpass->channels) { + case 1: + operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index, + rpass->passtype, view, COM_DT_VALUE); + break; + /* using image operations for both 3 and 4 channels (RGB and RGBA respectively) */ + /* XXX any way to detect actual vector images? */ + case 3: + operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index, + rpass->passtype, view, COM_DT_VECTOR); + break; + case 4: + operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index, + rpass->passtype, view, COM_DT_COLOR); + break; + default: + /* dummy operation is added below */ + break; + } + if (index == 0 && operation) { + converter.addPreview(operation->getOutputSocket()); + } + if (rpass->passtype == SCE_PASS_COMBINED) { + BLI_assert(operation != NULL); + BLI_assert(index < numberOfOutputs - 1); + NodeOutput *outputSocket = this->getOutputSocket(index + 1); + SeparateChannelOperation *separate_operation; + separate_operation = new SeparateChannelOperation(); + separate_operation->setChannel(3); + converter.addOperation(separate_operation); + converter.addLink(operation->getOutputSocket(), separate_operation->getInputSocket(0)); + converter.mapOutputSocket(outputSocket, separate_operation->getOutputSocket()); + index++; } } diff --git a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp index cbf9bb211c1..ce42de7a149 100644 --- a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp @@ -133,6 +133,9 @@ float *BlurBaseOperation::make_dist_fac_inverse(float rad, int size, int falloff case PROP_SHARP: val = val * val; break; + case PROP_INVSQUARE: + val = val * (2.0f - val); + break; case PROP_LIN: /* fall-through */ #ifndef NDEBUG diff --git a/source/blender/compositor/operations/COM_CompositorOperation.cpp b/source/blender/compositor/operations/COM_CompositorOperation.cpp index eacbdf91be2..76f74c144f6 100644 --- a/source/blender/compositor/operations/COM_CompositorOperation.cpp +++ b/source/blender/compositor/operations/COM_CompositorOperation.cpp @@ -82,7 +82,7 @@ void CompositorOperation::deinitExecution() RenderResult *rr = RE_AcquireResultWrite(re); if (rr) { - RenderView *rv = (RenderView *)BLI_findstring(&rr->views, this->m_viewName, offsetof(RenderView, name)); + RenderView *rv = RE_RenderViewGetByName(rr, this->m_viewName); if (rv->rectf != NULL) { MEM_freeN(rv->rectf); diff --git a/source/blender/compositor/operations/COM_CropOperation.cpp b/source/blender/compositor/operations/COM_CropOperation.cpp index 9bcc6fb2541..e5427589fce 100644 --- a/source/blender/compositor/operations/COM_CropOperation.cpp +++ b/source/blender/compositor/operations/COM_CropOperation.cpp @@ -36,27 +36,28 @@ void CropBaseOperation::updateArea() SocketReader *inputReference = this->getInputSocketReader(0); float width = inputReference->getWidth(); float height = inputReference->getHeight(); + NodeTwoXYs local_settings = *this->m_settings; if (width > 0.0f && height > 0.0f) { if (this->m_relative) { - this->m_settings->x1 = width * this->m_settings->fac_x1; - this->m_settings->x2 = width * this->m_settings->fac_x2; - this->m_settings->y1 = height * this->m_settings->fac_y1; - this->m_settings->y2 = height * this->m_settings->fac_y2; + local_settings.x1 = width * local_settings.fac_x1; + local_settings.x2 = width * local_settings.fac_x2; + local_settings.y1 = height * local_settings.fac_y1; + local_settings.y2 = height * local_settings.fac_y2; } - if (width <= this->m_settings->x1 + 1) - this->m_settings->x1 = width - 1; - if (height <= this->m_settings->y1 + 1) - this->m_settings->y1 = height - 1; - if (width <= this->m_settings->x2 + 1) - this->m_settings->x2 = width - 1; - if (height <= this->m_settings->y2 + 1) - this->m_settings->y2 = height - 1; + if (width <= local_settings.x1 + 1) + local_settings.x1 = width - 1; + if (height <= local_settings.y1 + 1) + local_settings.y1 = height - 1; + if (width <= local_settings.x2 + 1) + local_settings.x2 = width - 1; + if (height <= local_settings.y2 + 1) + local_settings.y2 = height - 1; - this->m_xmax = max(this->m_settings->x1, this->m_settings->x2) + 1; - this->m_xmin = min(this->m_settings->x1, this->m_settings->x2); - this->m_ymax = max(this->m_settings->y1, this->m_settings->y2) + 1; - this->m_ymin = min(this->m_settings->y1, this->m_settings->y2); + this->m_xmax = max(local_settings.x1, local_settings.x2) + 1; + this->m_xmin = min(local_settings.x1, local_settings.x2); + this->m_ymax = max(local_settings.y1, local_settings.y2) + 1; + this->m_ymin = min(local_settings.y1, local_settings.y2); } else { this->m_xmax = 0; diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 4828343fa0e..67485248bf1 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -2496,12 +2496,13 @@ static void ANIM_OT_channels_select_border(wmOperatorType *ot) /* ******************* Rename Operator ***************************** */ /* Allow renaming some channels by clicking on them */ -static void rename_anim_channels(bAnimContext *ac, int channel_index) +static bool rename_anim_channels(bAnimContext *ac, int channel_index) { ListBase anim_data = {NULL, NULL}; const bAnimChannelType *acf; bAnimListElem *ale; int filter; + bool success = false; /* get the channel that was clicked on */ /* filter channels */ @@ -2516,7 +2517,7 @@ static void rename_anim_channels(bAnimContext *ac, int channel_index) printf("Error: animation channel (index = %d) not found in rename_anim_channels()\n", channel_index); ANIM_animdata_freelist(&anim_data); - return; + return false; } /* check that channel can be renamed */ @@ -2536,6 +2537,7 @@ static void rename_anim_channels(bAnimContext *ac, int channel_index) */ if (ac->ads) { ac->ads->renameIndex = channel_index + 1; + success = true; } } } @@ -2543,22 +2545,18 @@ static void rename_anim_channels(bAnimContext *ac, int channel_index) /* free temp data and tag for refresh */ ANIM_animdata_freelist(&anim_data); ED_region_tag_redraw(ac->ar); + return success; } -static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) +static int animchannels_channel_get(bAnimContext *ac, const int mval[2]) { - bAnimContext ac; ARegion *ar; View2D *v2d; int channel_index; float x, y; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - /* get useful pointers from animation context data */ - ar = ac.ar; + ar = ac->ar; v2d = &ar->v2d; /* figure out which channel user clicked in @@ -2566,20 +2564,36 @@ static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), const * so that the tops of channels get caught ok. Since ACHANNEL_FIRST is really ACHANNEL_HEIGHT, we simply use * ACHANNEL_HEIGHT_HALF. */ - UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y); + UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y); - if (ac.datatype == ANIMCONT_NLA) { - SpaceNla *snla = (SpaceNla *)ac.sl; + if (ac->datatype == ANIMCONT_NLA) { + SpaceNla *snla = (SpaceNla *)ac->sl; UI_view2d_listview_view_to_cell(v2d, NLACHANNEL_NAMEWIDTH, NLACHANNEL_STEP(snla), 0, (float)NLACHANNEL_HEIGHT_HALF(snla), x, y, NULL, &channel_index); } else { UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP, 0, (float)ACHANNEL_HEIGHT_HALF, x, y, NULL, &channel_index); } - + + return channel_index; +} + +static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) +{ + bAnimContext ac; + int channel_index; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + channel_index = animchannels_channel_get(&ac, event->mval); + /* handle click */ - rename_anim_channels(&ac, channel_index); - - return OPERATOR_FINISHED; + if (rename_anim_channels(&ac, channel_index)) + return OPERATOR_FINISHED; + else + /* allow event to be handled by selectall operator */ + return OPERATOR_PASS_THROUGH; } static void ANIM_OT_channels_rename(wmOperatorType *ot) @@ -3008,6 +3022,105 @@ static void ANIM_OT_channels_click(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } +static bool select_anim_channel_keys(bAnimContext *ac, int channel_index, bool extend) +{ + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + bool success = false; + FCurve *fcu; + int i; + + /* get the channel that was clicked on */ + /* filter channels */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* get channel from index */ + ale = BLI_findlink(&anim_data, channel_index); + if (ale == NULL) { + /* channel not found */ + if (G.debug & G_DEBUG) + printf("Error: animation channel (index = %d) not found in rename_anim_channels()\n", channel_index); + + ANIM_animdata_freelist(&anim_data); + return false; + } + + fcu = (FCurve *)ale->key_data; + success = (fcu != NULL); + + ANIM_animdata_freelist(&anim_data); + + /* F-Curve may not have any keyframes */ + if (fcu->bezt) { + BezTriple *bezt; + + if (!extend) { + filter = (ANIMFILTER_DATA_VISIBLE); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu_inner = (FCurve *)ale->key_data; + + if (fcu_inner) { + for (i = 0, bezt = fcu_inner->bezt; i < fcu_inner->totvert; i++, bezt++) { + bezt->f2 = bezt->f1 = bezt->f3 = 0; + } + } + } + + ANIM_animdata_freelist(&anim_data); + } + + for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { + bezt->f2 = bezt->f1 = bezt->f3 = SELECT; + } + } + + /* free temp data and tag for refresh */ + ED_region_tag_redraw(ac->ar); + return success; +} + +static int animchannels_channel_select_keys_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + bAnimContext ac; + int channel_index; + bool extend = RNA_boolean_get(op->ptr, "extend"); + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + channel_index = animchannels_channel_get(&ac, event->mval); + + /* handle click */ + if (select_anim_channel_keys(&ac, channel_index, extend)) { + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); + return OPERATOR_FINISHED; + } + else + /* allow event to be handled by selectall operator */ + return OPERATOR_PASS_THROUGH; +} + +static void ANIM_OT_channel_select_keys(wmOperatorType *ot) +{ + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Select Channel keyframes"; + ot->idname = "ANIM_OT_channel_select_keys"; + ot->description = "Select all keyframes of channel under mouse"; + + /* api callbacks */ + ot->invoke = animchannels_channel_select_keys_invoke; + ot->poll = animedit_poll_channels_active; + + prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); +} + /* ************************************************************************** */ /* Operator Registration */ @@ -3017,8 +3130,9 @@ void ED_operatortypes_animchannels(void) WM_operatortype_append(ANIM_OT_channels_select_border); WM_operatortype_append(ANIM_OT_channels_click); + WM_operatortype_append(ANIM_OT_channel_select_keys); WM_operatortype_append(ANIM_OT_channels_rename); - + WM_operatortype_append(ANIM_OT_channels_find); WM_operatortype_append(ANIM_OT_channels_setting_enable); @@ -3058,7 +3172,9 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf) /* rename */ WM_keymap_add_item(keymap, "ANIM_OT_channels_rename", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "ANIM_OT_channels_rename", LEFTMOUSE, KM_DBL_CLICK, 0, 0); - + WM_keymap_add_item(keymap, "ANIM_OT_channel_select_keys", LEFTMOUSE, KM_DBL_CLICK, 0, 0); + RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channel_select_keys", LEFTMOUSE, KM_DBL_CLICK, KM_SHIFT, 0)->ptr, "extend", true); + /* find (i.e. a shortcut for setting the name filter) */ WM_keymap_add_item(keymap, "ANIM_OT_channels_find", FKEY, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index aa06740ed0e..45663371ae3 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -962,7 +962,7 @@ static void MARKER_OT_move(wmOperatorType *ot) ot->cancel = ed_marker_move_cancel; /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; /* rna storage */ RNA_def_int(ot->srna, "frames", 0, INT_MIN, INT_MAX, "Frames", "", INT_MIN, INT_MAX); diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index 47eafcbaed1..2de42933dc0 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -247,7 +247,7 @@ static void ANIM_OT_change_frame(wmOperatorType *ot) ot->poll = change_frame_poll; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR; /* rna */ ot->prop = RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME); diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 64ced437142..092408d7de5 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -1696,7 +1696,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op) char *path; float cfra = (float)CFRA; short success = 0; - int a, index, length; + int index; const bool all = RNA_boolean_get(op->ptr, "all"); short flag = 0; @@ -1715,7 +1715,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op) NlaStrip *strip = (NlaStrip *)ptr.data; FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), flag); - success += insert_keyframe_direct(op->reports, ptr, prop, fcu, cfra, 0); + success = insert_keyframe_direct(op->reports, ptr, prop, fcu, cfra, 0); } else { /* standard properties */ @@ -1723,16 +1723,11 @@ static int insert_key_button_exec(bContext *C, wmOperator *op) if (path) { if (all) { - length = RNA_property_array_length(&ptr, prop); - - if (length) index = 0; - else length = 1; + /* -1 indicates operating on the entire array (or the property itself otherwise) */ + index = -1; } - else - length = 1; - for (a = 0; a < length; a++) - success += insert_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index + a, cfra, flag); + success = insert_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index, cfra, flag); MEM_freeN(path); } @@ -1795,7 +1790,7 @@ static int delete_key_button_exec(bContext *C, wmOperator *op) char *path; float cfra = (float)CFRA; // XXX for now, don't bother about all the yucky offset crap short success = 0; - int a, index, length; + int index; const bool all = RNA_boolean_get(op->ptr, "all"); /* try to insert keyframe using property retrieved from UI */ @@ -1806,17 +1801,11 @@ static int delete_key_button_exec(bContext *C, wmOperator *op) if (path) { if (all) { - length = RNA_property_array_length(&ptr, prop); - - if (length) index = 0; - else length = 1; + /* -1 indicates operating on the entire array (or the property itself otherwise) */ + index = -1; } - else - length = 1; - - for (a = 0; a < length; a++) - success += delete_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index + a, cfra, 0); + success = delete_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index, cfra, 0); MEM_freeN(path); } else if (G.debug & G_DEBUG) @@ -1865,7 +1854,7 @@ static int clear_key_button_exec(bContext *C, wmOperator *op) PropertyRNA *prop = NULL; char *path; short success = 0; - int a, index, length; + int index; const bool all = RNA_boolean_get(op->ptr, "all"); /* try to insert keyframe using property retrieved from UI */ @@ -1876,17 +1865,11 @@ static int clear_key_button_exec(bContext *C, wmOperator *op) if (path) { if (all) { - length = RNA_property_array_length(&ptr, prop); - - if (length) index = 0; - else length = 1; + /* -1 indicates operating on the entire array (or the property itself otherwise) */ + index = -1; } - else - length = 1; - - for (a = 0; a < length; a++) - success += clear_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index + a, 0); + success += clear_keyframe(op->reports, ptr.id.data, NULL, NULL, path, index, 0); MEM_freeN(path); } else if (G.debug & G_DEBUG) diff --git a/source/blender/editors/armature/pose_group.c b/source/blender/editors/armature/pose_group.c index 413a74d24b5..4d9df06f33f 100644 --- a/source/blender/editors/armature/pose_group.c +++ b/source/blender/editors/armature/pose_group.c @@ -130,6 +130,7 @@ static int pose_groups_menu_invoke(bContext *C, wmOperator *op, const wmEvent *U { Object *ob = ED_pose_object_from_context(C); bPose *pose; + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "type"); uiPopupMenu *pup; uiLayout *layout; @@ -140,6 +141,17 @@ static int pose_groups_menu_invoke(bContext *C, wmOperator *op, const wmEvent *U if (ELEM(NULL, ob, ob->pose)) return OPERATOR_CANCELLED; pose = ob->pose; + + /* If group index is set, try to use it! */ + if (RNA_property_is_set(op->ptr, prop)) { + const int num_groups = BLI_listbase_count(&pose->agroups); + const int group = RNA_property_int_get(op->ptr, prop); + + /* just use the active group index, and call the exec callback for the calling operator */ + if (group > 0 && group <= num_groups) { + return op->type->exec(C, op); + } + } /* if there's no active group (or active is invalid), create a new menu to find it */ if (pose->active_group <= 0) { diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c index 7c53896b969..555a53ae532 100644 --- a/source/blender/editors/curve/editcurve_add.c +++ b/source/blender/editors/curve/editcurve_add.c @@ -121,7 +121,7 @@ Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type const float grid = 1.0f; const int cutype = (type & CU_TYPE); // poly, bezier, nurbs, etc const int stype = (type & CU_PRIMITIVE); - const int force_3d = ((Curve *)obedit->data)->flag & CU_3D; /* could be adding to an existing 3D curve */ + const bool force_3d = (((Curve *)obedit->data)->flag & CU_3D) != 0; /* could be adding to an existing 3D curve */ unit_m4(umat); unit_m4(viewmat); @@ -488,9 +488,10 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf) if (!isSurf) { /* adding curve */ if (obedit == NULL || obedit->type != OB_CURVE) { + const char *name = get_curve_defname(type); Curve *cu; - obedit = ED_object_add_type(C, OB_CURVE, loc, rot, true, layer); + obedit = ED_object_add_type(C, OB_CURVE, name, loc, rot, true, layer); newob = true; cu = (Curve *)obedit->data; @@ -505,7 +506,8 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf) } else { /* adding surface */ if (obedit == NULL || obedit->type != OB_SURF) { - obedit = ED_object_add_type(C, OB_SURF, loc, rot, true, layer); + const char *name = get_surf_defname(type); + obedit = ED_object_add_type(C, OB_SURF, name, loc, rot, true, layer); newob = true; } else { @@ -513,18 +515,6 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf) } } - /* rename here, the undo stack checks name for valid undo pushes */ - if (newob) { - if (obedit->type == OB_CURVE) { - rename_id((ID *)obedit, get_curve_defname(type)); - rename_id((ID *)obedit->data, get_curve_defname(type)); - } - else { - rename_id((ID *)obedit, get_surf_defname(type)); - rename_id((ID *)obedit->data, get_surf_defname(type)); - } - } - /* ED_object_add_type doesnt do an undo, is needed for redo operator on primitive */ if (newob && enter_editmode) ED_undo_push(C, "Enter Editmode"); diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index 4297344e6fe..b67ae228b25 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -526,7 +526,7 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, const int a; float rot[3] = {0.f, 0.f, 0.f}; - obedit = BKE_object_add(bmain, scene, OB_FONT); + obedit = BKE_object_add(bmain, scene, OB_FONT, NULL); base = scene->basact; /* seems to assume view align ? TODO - look into this, could be an operator option */ diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index 0d35d3ce716..ffcd204135f 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -761,7 +761,7 @@ static void gp_draw_strokes_edit(bGPDframe *gpf, int offsx, int offsy, int winx, { bGPDstroke *gps; - const int no_xray = (dflag & GP_DRAWDATA_NO_XRAY); + const bool no_xray = (dflag & GP_DRAWDATA_NO_XRAY) != 0; int mask_orig = 0; /* set up depth masks... */ diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 778f98d212e..e902f9552b5 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -48,6 +48,7 @@ #include "BKE_context.h" #include "BKE_global.h" #include "BKE_report.h" +#include "BKE_screen.h" #include "BKE_tracking.h" #include "DNA_object_types.h" @@ -1030,6 +1031,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p) /* set current area * - must verify that region data is 3D-view (and not something else) */ + /* CAUTION: If this is the "toolbar", then this will change on the first stroke */ p->sa = curarea; p->ar = ar; @@ -1252,6 +1254,7 @@ static void gp_paint_initstroke(tGPsdata *p, short paintmode) /* when drawing in the camera view, in 2D space, set the subrect */ + p->subrect = NULL; if (!(p->gpd->flag & GP_DATA_VIEWALIGN)) { if (p->sa->spacetype == SPACE_VIEW3D) { View3D *v3d = p->sa->spacedata.first; @@ -1777,6 +1780,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event else { /* toolbar invoked - don't start drawing yet... */ /* printf("\tGP - hotkey invoked... waiting for click-drag\n"); */ + op->flag |= OP_IS_MODAL_CURSOR_REGION; } WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); @@ -1814,8 +1818,10 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op) if (gp_session_initdata(C, p)) gp_paint_initstroke(p, p->paintmode); - if (p->status != GP_STATUS_ERROR) + if (p->status != GP_STATUS_ERROR) { p->status = GP_STATUS_PAINTING; + op->flag &= ~OP_IS_MODAL_CURSOR_REGION; + } return op->customdata; } @@ -1831,6 +1837,7 @@ static void gpencil_stroke_end(wmOperator *op) gp_session_cleanup(p); p->status = GP_STATUS_IDLING; + op->flag |= OP_IS_MODAL_CURSOR_REGION; p->gpd = NULL; p->gpl = NULL; @@ -1856,6 +1863,11 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) * in 3D space. */ + if (p->status == GP_STATUS_IDLING) { + ARegion *ar = CTX_wm_region(C); + p->ar = ar; + } + /* we don't pass on key events, GP is used with key-modifiers - prevents Dkey to insert drivers */ if (ISKEYBOARD(event->type)) { if (ELEM(event->type, LEFTARROWKEY, DOWNARROWKEY, RIGHTARROWKEY, UPARROWKEY, ZKEY)) { @@ -1938,29 +1950,88 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) } } else if (event->val == KM_PRESS) { - /* Switch paintmode (temporarily if need be) based on which button was used - * NOTE: This is to make it more convenient to erase strokes when using drawing sessions + bool in_bounds = false; + + /* Check if we're outside the bounds of the active region + * NOTE: An exception here is that if launched from the toolbar, + * whatever region we're now in should become the new region */ - if (event->type == LEFTMOUSE) { - /* restore drawmode to default */ - p->paintmode = RNA_enum_get(op->ptr, "mode"); + if ((p->ar) && (p->ar->regiontype == RGN_TYPE_TOOLS)) { + /* Change to whatever region is now under the mouse */ + ARegion *current_region = BKE_area_find_region_xy(p->sa, RGN_TYPE_ANY, event->x, event->y); + + if (G.debug & G_DEBUG) { + printf("found alternative region %p (old was %p) - at %d %d (sa: %d %d -> %d %d)\n", + current_region, p->ar, event->x, event->y, + p->sa->totrct.xmin, p->sa->totrct.ymin, p->sa->totrct.xmax, p->sa->totrct.ymax); + } + + if (current_region) { + /* Assume that since we found the cursor in here, it is in bounds + * and that this should be the region that we begin drawing in + */ + p->ar = current_region; + in_bounds = true; + } + else { + /* Out of bounds, or invalid in some other way */ + p->status = GP_STATUS_ERROR; + estate = OPERATOR_CANCELLED; + + if (G.debug & G_DEBUG) + printf("%s: Region under cursor is out of bounds, so cannot be drawn on\n", __func__); + } } - else if (event->type == RIGHTMOUSE) { - /* turn on eraser */ - p->paintmode = GP_PAINTMODE_ERASER; + else if (p->ar) { + rcti region_rect; + + /* Perform bounds check using */ + ED_region_visible_rect(p->ar, ®ion_rect); + in_bounds = BLI_rcti_isect_pt_v(®ion_rect, event->mval); } - - gpencil_draw_toggle_eraser_cursor(C, p, p->paintmode == GP_PAINTMODE_ERASER); - - /* not painting, so start stroke (this should be mouse-button down) */ - p = gpencil_stroke_begin(C, op); - - if (p->status == GP_STATUS_ERROR) { + else { + /* No region */ + p->status = GP_STATUS_ERROR; estate = OPERATOR_CANCELLED; + + if (G.debug & G_DEBUG) + printf("%s: No active region found in GP Paint session data\n", __func__); + } + + if (in_bounds) { + /* Switch paintmode (temporarily if need be) based on which button was used + * NOTE: This is to make it more convenient to erase strokes when using drawing sessions + */ + if (event->type == LEFTMOUSE) { + /* restore drawmode to default */ + p->paintmode = RNA_enum_get(op->ptr, "mode"); + } + else if (event->type == RIGHTMOUSE) { + /* turn on eraser */ + p->paintmode = GP_PAINTMODE_ERASER; + } + + gpencil_draw_toggle_eraser_cursor(C, p, p->paintmode == GP_PAINTMODE_ERASER); + + /* not painting, so start stroke (this should be mouse-button down) */ + p = gpencil_stroke_begin(C, op); + + if (p->status == GP_STATUS_ERROR) { + estate = OPERATOR_CANCELLED; + } + } + else if (p->status != GP_STATUS_ERROR) { + /* User clicked outside bounds of window while idling, so exit paintmode + * NOTE: Don't eter this case if an error occurred while finding the + * region (as above) + */ + p->status = GP_STATUS_DONE; + estate = OPERATOR_FINISHED; } } else { p->status = GP_STATUS_IDLING; + op->flag |= OP_IS_MODAL_CURSOR_REGION; } } diff --git a/source/blender/editors/hair/hair_edit.c b/source/blender/editors/hair/hair_edit.c index 67059912e92..a637673369e 100644 --- a/source/blender/editors/hair/hair_edit.c +++ b/source/blender/editors/hair/hair_edit.c @@ -270,7 +270,7 @@ void hair_init_viewdata(bContext *C, HairViewData *viewdata) /* needed or else the draw matrix can be incorrect */ view3d_operator_needs_opengl(C); - view3d_validate_backbuf(&viewdata->vc); + ED_view3d_backbuf_validate(&viewdata->vc); /* we may need to force an update here by setting the rv3d as dirty * for now it seems ok, but take care!: * rv3d->depths->dirty = 1; */ diff --git a/source/blender/editors/include/ED_buttons.h b/source/blender/editors/include/ED_buttons.h index 64c16605dec..9a987d7618c 100644 --- a/source/blender/editors/include/ED_buttons.h +++ b/source/blender/editors/include/ED_buttons.h @@ -37,4 +37,6 @@ bool ED_texture_context_check_particles(const struct bContext *C); bool ED_texture_context_check_linestyle(const struct bContext *C); bool ED_texture_context_check_others(const struct bContext *C); +void ED_buttons_id_unref(struct SpaceButs *sbuts, const struct ID *id); + #endif /* __ED_BUTTONS_H__ */ diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 8fb6fcbd0d7..ea544135d3b 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -137,9 +137,27 @@ bool EDBM_backbuf_border_mask_init(struct ViewContext *vc, const int mcords[][2] short xmin, short ymin, short xmax, short ymax); bool EDBM_backbuf_circle_init(struct ViewContext *vc, short xs, short ys, short rads); -struct BMVert *EDBM_vert_find_nearest(struct ViewContext *vc, float *r_dist, const bool sel, const bool strict); -struct BMEdge *EDBM_edge_find_nearest(struct ViewContext *vc, float *r_dist); -struct BMFace *EDBM_face_find_nearest(struct ViewContext *vc, float *r_dist); +struct BMVert *EDBM_vert_find_nearest_ex( + struct ViewContext *vc, float *r_dist, + const bool use_select_bias, bool use_cycle); +struct BMVert *EDBM_vert_find_nearest( + struct ViewContext *vc, float *r_dist); + +struct BMEdge *EDBM_edge_find_nearest_ex( + struct ViewContext *vc, float *r_dist, + float *r_dist_center, + const bool use_select_bias, const bool use_cycle, + struct BMEdge **r_eed_zbuf); +struct BMEdge *EDBM_edge_find_nearest( + struct ViewContext *vc, float *r_dist); + +struct BMFace *EDBM_face_find_nearest_ex( + struct ViewContext *vc, float *r_dist, + float *r_dist_center, + const bool use_select_bias, const bool use_cycle, + struct BMFace **r_efa_zbuf); +struct BMFace *EDBM_face_find_nearest( + struct ViewContext *vc, float *r_dist); bool EDBM_select_pick(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle); diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index b02ebeb650b..1445308c485 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -103,6 +103,8 @@ void ED_node_set_active(struct Main *bmain, struct bNodeTree *ntree, struct bNod void ED_node_composite_job(const struct bContext *C, struct bNodeTree *nodetree, struct Scene *scene_owner); +void ED_node_id_unref(struct SpaceNode *snode, const ID *id); + /* node_ops.c */ void ED_operatormacros_node(void); diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 3b7157bd465..c52174c8f2d 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -138,8 +138,10 @@ bool ED_object_add_generic_get_opts(struct bContext *C, struct wmOperator *op, c bool *enter_editmode, unsigned int *layer, bool *is_view_aligned); struct Object *ED_object_add_type( - struct bContext *C, int type, const float loc[3], const float rot[3], - bool enter_editmode, unsigned int layer) ATTR_RETURNS_NONNULL; + struct bContext *C, + int type, const char *name, const float loc[3], const float rot[3], + bool enter_editmode, unsigned int layer) + ATTR_NONNULL(1) ATTR_RETURNS_NONNULL; void ED_object_single_users(struct Main *bmain, struct Scene *scene, const bool full, const bool copy_groups); void ED_object_single_user(struct Main *bmain, struct Scene *scene, struct Object *ob); diff --git a/source/blender/editors/include/ED_outliner.h b/source/blender/editors/include/ED_outliner.h new file mode 100644 index 00000000000..af4af8e2f5d --- /dev/null +++ b/source/blender/editors/include/ED_outliner.h @@ -0,0 +1,36 @@ +/* + * ***** 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) 2015, Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file ED_outliner.h + * \ingroup editors + */ + +#ifndef __ED_OUTLINER_H__ +#define __ED_OUTLINER_H__ + +struct ID; +struct SpaceOops; + +/* Used to check whether a given texture context is valid in current context. */ +void ED_outliner_id_unref(struct SpaceOops *so, const struct ID *id); + +#endif /* __ED_OUTLINER_H__ */ diff --git a/source/blender/editors/include/ED_paint.h b/source/blender/editors/include/ED_paint.h index 822dab61a06..e46f4b966c0 100644 --- a/source/blender/editors/include/ED_paint.h +++ b/source/blender/editors/include/ED_paint.h @@ -58,7 +58,7 @@ void ED_undo_paint_push_end(int type); void ED_image_undo_restore(struct bContext *C, struct ListBase *lb); void ED_image_undo_free(struct ListBase *lb); void ED_imapaint_clear_partial_redraw(void); -void ED_imapaint_dirty_region(struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h); +void ED_imapaint_dirty_region(struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h, bool find_old); void ED_imapaint_bucket_fill(struct bContext *C, float color[3], struct wmOperator *op); #endif /* __ED_PAINT_H__ */ diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 90b0b3510bc..7f6679b827b 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -66,6 +66,7 @@ void ED_region_header_init(struct ARegion *ar); void ED_region_header(const struct bContext *C, struct ARegion *ar); void ED_region_toggle_hidden(struct bContext *C, struct ARegion *ar); void ED_region_info_draw(struct ARegion *ar, const char *text, int block, float fill_color[4]); +void ED_region_image_metadata_draw(int x, int y, struct ImBuf *ibuf, rctf frame, float zoomx, float zoomy); void ED_region_grid_draw(struct ARegion *ar, float zoomx, float zoomy); float ED_region_blend_factor(struct ARegion *ar); void ED_region_visible_rect(struct ARegion *ar, struct rcti *rect); @@ -75,7 +76,6 @@ void ED_region_visible_rect(struct ARegion *ar, struct rcti *rect); void ED_spacetypes_keymap(struct wmKeyConfig *keyconf); int ED_area_header_switchbutton(const struct bContext *C, struct uiBlock *block, int yco); - /* areas */ void ED_area_initialize(struct wmWindowManager *wm, struct wmWindow *win, struct ScrArea *sa); void ED_area_exit(struct bContext *C, struct ScrArea *sa); @@ -85,6 +85,7 @@ void ED_area_tag_redraw(ScrArea *sa); void ED_area_tag_redraw_regiontype(ScrArea *sa, int type); void ED_area_tag_refresh(ScrArea *sa); void ED_area_do_refresh(struct bContext *C, ScrArea *sa); +void ED_area_azones_update(ScrArea *sa, const int mouse_xy[]); void ED_area_headerprint(ScrArea *sa, const char *str); void ED_area_newspace(struct bContext *C, ScrArea *sa, int type); void ED_area_prevspace(struct bContext *C, ScrArea *sa); diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h index 356c2f70029..ba5449eefa4 100644 --- a/source/blender/editors/include/ED_util.h +++ b/source/blender/editors/include/ED_util.h @@ -42,6 +42,8 @@ void ED_editors_exit(struct bContext *C); bool ED_editors_flush_edits(const struct bContext *C, bool for_render); +void ED_spacedata_id_unref(struct SpaceLink *sl, const struct ID *id); + /* ************** Undo ************************ */ /* undo.c */ diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index ff4b8a5b631..be4204e7cb7 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -219,6 +219,7 @@ void ED_view3d_win_to_vector(const struct ARegion *ar, const float mval[2], floa bool ED_view3d_win_to_segment(const struct ARegion *ar, struct View3D *v3d, const float mval[2], float r_ray_start[3], float r_ray_end[3], const bool do_clip); void ED_view3d_ob_project_mat_get(const struct RegionView3D *v3d, struct Object *ob, float pmat[4][4]); +void ED_view3d_ob_project_mat_get_from_obmat(const struct RegionView3D *rv3d, float obmat[4][4], float pmat[4][4]); void ED_view3d_unproject(struct bglMats *mats, float out[3], const float x, const float y, const float z); /* end */ @@ -267,12 +268,13 @@ float ED_view3d_radius_to_dist( void drawcircball(int mode, const float cent[3], float rad, float tmat[4][4]); /* backbuffer select and draw support */ -void view3d_validate_backbuf(struct ViewContext *vc); -struct ImBuf *view3d_read_backbuf(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax); -unsigned int view3d_sample_backbuf_rect(struct ViewContext *vc, const int mval[2], int size, - unsigned int min, unsigned int max, float *dist, short strict, - void *handle, bool (*indextest)(void *handle, unsigned int index)); -unsigned int view3d_sample_backbuf(struct ViewContext *vc, int x, int y); +void ED_view3d_backbuf_validate(struct ViewContext *vc); +struct ImBuf *ED_view3d_backbuf_read(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax); +unsigned int ED_view3d_backbuf_sample_rect( + struct ViewContext *vc, const int mval[2], int size, + unsigned int min, unsigned int max, float *r_dist); +int ED_view3d_backbuf_sample_size_clamp(struct ARegion *ar, const float dist); +unsigned int ED_view3d_backbuf_sample(struct ViewContext *vc, int x, int y); /* draws and does a 4x4 sample */ bool ED_view3d_autodist(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, @@ -343,8 +345,6 @@ bool ED_view3d_lock(struct RegionView3D *rv3d); uint64_t ED_view3d_datamask(const struct Scene *scene, const struct View3D *v3d); uint64_t ED_view3d_screen_datamask(const struct bScreen *screen); -bool ED_view3d_view_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d); - bool ED_view3d_offset_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d); /* camera lock functions */ @@ -391,4 +391,7 @@ void ED_view3d_operator_properties_viewmat_get(struct wmOperator *op, int *winx, void ED_view3d_stop_render_preview(struct wmWindowManager *wm, struct ARegion *ar); void ED_view3d_shade_update(struct Main *bmain, struct Scene *scene, struct View3D *v3d, struct ScrArea *sa); +#define V3D_IS_ZBUF(v3d) \ + (((v3d)->flag & V3D_ZBUF_SELECT) && ((v3d)->drawtype > OB_WIRE)) + #endif /* __ED_VIEW3D_H__ */ diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 4ca0be7c80d..1e0cc972ef8 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -483,6 +483,14 @@ bool UI_but_active_only(const struct bContext *C, struct ARegion *ar, uiBlock void UI_but_execute(const struct bContext *C, uiBut *but); +bool UI_but_online_manual_id( + const uiBut *but, + char *r_str, size_t maxlength) + ATTR_WARN_UNUSED_RESULT; +bool UI_but_online_manual_id_from_active( + const struct bContext *C, + char *r_str, size_t maxlength) + ATTR_WARN_UNUSED_RESULT; /* Buttons * @@ -675,6 +683,7 @@ void UI_but_func_drawextra_set( void *arg1, void *arg2); void UI_but_func_tooltip_set(uiBut *but, uiButToolTipFunc func, void *argN); +void UI_but_tooltip_timer_remove(struct bContext *C, uiBut *but); bool UI_textbutton_activate_rna(const struct bContext *C, struct ARegion *ar, const void *rna_poin_data, const char *rna_prop_id); diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index 3923c5c4432..2b19b6180e5 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -294,7 +294,10 @@ enum { TH_INFO_DEBUG_TEXT, TH_VIEW_OVERLAY, - TH_V3D_CLIPPING_BORDER + TH_V3D_CLIPPING_BORDER, + + TH_METADATA_BG, + TH_METADATA_TEXT }; /* XXX WARNING: previous is saved in file, so do not change order! */ diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 5714a40d508..5c548d3afd5 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -37,6 +37,7 @@ #include "MEM_guardedalloc.h" +#include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_userdef_types.h" @@ -1951,6 +1952,56 @@ uiBut *ui_but_drag_multi_edit_get(uiBut *but) return but_iter; } +/** \name Check to show extra icons + * + * Extra icons are shown on the right hand side of buttons. + * \{ */ + +static bool ui_but_icon_extra_is_visible_search_unlink(const uiBut *but) +{ + BLI_assert(but->type == UI_BTYPE_SEARCH_MENU); + return ((but->editstr == NULL) && + (but->drawstr[0] != '\0') && + (but->flag & UI_BUT_SEARCH_UNLINK)); +} + +static bool ui_but_icon_extra_is_visible_eyedropper(uiBut *but) +{ + StructRNA *type; + short idcode; + + BLI_assert(but->type == UI_BTYPE_SEARCH_MENU && (but->flag & UI_BUT_SEARCH_UNLINK)); + + if (but->rnaprop == NULL) { + return false; + } + + type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop); + idcode = RNA_type_to_ID_code(type); + + + return ((but->editstr == NULL) && + (idcode == ID_OB || OB_DATA_SUPPORT_ID(idcode))); +} + +uiButExtraIconType ui_but_icon_extra_get(uiBut *but) +{ + if ((but->flag & UI_BUT_SEARCH_UNLINK) == 0) { + /* pass */ + } + else if (ui_but_icon_extra_is_visible_search_unlink(but)) { + return UI_BUT_ICONEXTRA_UNLINK; + } + else if (ui_but_icon_extra_is_visible_eyedropper(but)) { + return UI_BUT_ICONEXTRA_EYEDROPPER; + } + + return UI_BUT_ICONEXTRA_NONE; +} + +/** \} */ + + static double ui_get_but_scale_unit(uiBut *but, double value) { UnitSettings *unit = but->block->unit; @@ -2714,11 +2765,11 @@ void ui_but_update(uiBut *but) } else { const int prec = ui_but_calc_float_precision(but, value); - slen += BLI_snprintf(but->drawstr + slen, sizeof(but->drawstr) - slen, "%.*f", prec, value); + slen += BLI_snprintf_rlen(but->drawstr + slen, sizeof(but->drawstr) - slen, "%.*f", prec, value); } } else { - slen += BLI_snprintf(but->drawstr + slen, sizeof(but->drawstr) - slen, "%d", (int)value); + slen += BLI_snprintf_rlen(but->drawstr + slen, sizeof(but->drawstr) - slen, "%d", (int)value); } if (but->rnaprop) { diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c index f5847a9d701..44e06bab4ab 100644 --- a/source/blender/editors/interface/interface_eyedropper.c +++ b/source/blender/editors/interface/interface_eyedropper.c @@ -176,8 +176,8 @@ static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int if (sa) { if (sa->spacetype == SPACE_IMAGE) { - ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); - if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) { + ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my); + if (ar) { SpaceImage *sima = sa->spacedata.first; int mval[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin}; @@ -188,8 +188,8 @@ static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int } } else if (sa->spacetype == SPACE_NODE) { - ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); - if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) { + ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my); + if (ar) { SpaceNode *snode = sa->spacedata.first; int mval[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin}; @@ -200,8 +200,8 @@ static void eyedropper_color_sample_fl(bContext *C, Eyedropper *UNUSED(eye), int } } else if (sa->spacetype == SPACE_CLIP) { - ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); - if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) { + ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my); + if (ar) { SpaceClip *sc = sa->spacedata.first; int mval[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin}; @@ -456,6 +456,8 @@ static void datadropper_exit(bContext *C, wmOperator *op) op->customdata = NULL; } + + WM_event_add_mousemove(C); } static void datadropper_cancel(bContext *C, wmOperator *op) @@ -482,8 +484,8 @@ static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int if (sa) { if (sa->spacetype == SPACE_VIEW3D) { - ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); - if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) { + ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my); + if (ar) { const int mval[2] = { mx - ar->winrct.xmin, my - ar->winrct.ymin}; @@ -765,8 +767,8 @@ static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx, if (sa) { if (sa->spacetype == SPACE_VIEW3D) { - ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW); - if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) { + ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my); + if (ar) { View3D *v3d = sa->spacedata.first; RegionView3D *rv3d = ar->regiondata; /* weak, we could pass in some reference point */ diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index bc35fde633c..1d71a5db350 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -332,7 +332,6 @@ static void button_activate_exit(bContext *C, uiBut *but, uiHandleButtonData *da const bool mousemove, const bool onfree); static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *userdata); static void ui_handle_button_activate(bContext *C, ARegion *ar, uiBut *but, uiButtonActivateType type); -static void button_timers_tooltip_remove(bContext *C, uiBut *but); #ifdef USE_DRAG_MULTINUM static void ui_multibut_restore(uiHandleButtonData *data, uiBlock *block); @@ -3301,9 +3300,11 @@ static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButton static int ui_do_but_SEARCH_UNLINK(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) { + uiButExtraIconType extra_icon_type; + /* unlink icon is on right */ - if (ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY) && event->val == KM_PRESS && - ui_but_is_search_unlink_visible(but)) + if ((ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY)) && + ((extra_icon_type = ui_but_icon_extra_get(but)) != UI_BUT_ICONEXTRA_NONE)) { ARegion *ar = data->region; rcti rect; @@ -3314,14 +3315,29 @@ static int ui_do_but_SEARCH_UNLINK(bContext *C, uiBlock *block, uiBut *but, uiHa BLI_rcti_rctf_copy(&rect, &but->rect); rect.xmin = rect.xmax - (BLI_rcti_size_y(&rect)); + /* handle click on unlink/eyedropper icon */ if (BLI_rcti_isect_pt(&rect, x, y)) { - /* most likely NULL, but let's check, and give it temp zero string */ - if (data->str == NULL) - data->str = MEM_callocN(1, "temp str"); - data->str[0] = 0; + /* doing this on KM_PRESS calls eyedropper after clicking unlink icon */ + if (event->val == KM_RELEASE) { + /* unlink */ + if (extra_icon_type == UI_BUT_ICONEXTRA_UNLINK) { + /* most likely NULL, but let's check, and give it temp zero string */ + if (data->str == NULL) { + data->str = MEM_callocN(1, "temp str"); + } + data->str[0] = 0; - ui_apply_but_TEX(C, but, data); - button_activate_state(C, but, BUTTON_STATE_EXIT); + ui_apply_but_TEX(C, but, data); + button_activate_state(C, but, BUTTON_STATE_EXIT); + } + /* eyedropper */ + else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) { + WM_operator_name_call(C, "UI_OT_eyedropper_id", WM_OP_INVOKE_DEFAULT, NULL); + } + else { + BLI_assert(0); + } + } return WM_UI_HANDLER_BREAK; } @@ -5939,7 +5955,7 @@ static void menu_add_shortcut_cancel(struct bContext *C, void *arg1) static void popup_change_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) { uiBut *but = (uiBut *)arg1; - button_timers_tooltip_remove(C, but); + UI_but_tooltip_timer_remove(C, but); UI_popup_block_invoke(C, menu_change_shortcut, but); } @@ -5960,7 +5976,7 @@ static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) static void popup_add_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) { uiBut *but = (uiBut *)arg1; - button_timers_tooltip_remove(C, but); + UI_but_tooltip_timer_remove(C, but); UI_popup_block_ex(C, menu_add_shortcut, NULL, menu_add_shortcut_cancel, but); } @@ -6009,7 +6025,7 @@ static bool ui_but_menu(bContext *C, uiBut *but) return false; } - button_timers_tooltip_remove(C, but); + UI_but_tooltip_timer_remove(C, but); /* highly unlikely getting the label ever fails */ UI_but_string_info_get(C, but, &label, NULL); @@ -6237,14 +6253,9 @@ static bool ui_but_menu(bContext *C, uiBut *but) char buf[512]; PointerRNA ptr_props; - if (but->rnapoin.data && but->rnaprop) { - BLI_snprintf(buf, sizeof(buf), "%s.%s", - RNA_struct_identifier(but->rnapoin.type), RNA_property_identifier(but->rnaprop)); - - WM_operator_properties_create(&ptr_props, "WM_OT_doc_view_manual"); - RNA_string_set(&ptr_props, "doc_id", buf); - uiItemFullO(layout, "WM_OT_doc_view_manual", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"), - ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0); + if (UI_but_online_manual_id(but, buf, sizeof(buf))) { + uiItemO(layout, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"), + ICON_NONE, "WM_OT_doc_view_manual_ui_context"); WM_operator_properties_create(&ptr_props, "WM_OT_doc_view"); RNA_string_set(&ptr_props, "doc_id", buf); @@ -6260,30 +6271,6 @@ static bool ui_but_menu(bContext *C, uiBut *but) uiItemFullO(layout, "WM_OT_doc_edit", "Submit Description", ICON_NONE, ptr_props.data, WM_OP_INVOKE_DEFAULT, 0); #endif } - else if (but->optype) { - WM_operator_py_idname(buf, but->optype->idname); - - - WM_operator_properties_create(&ptr_props, "WM_OT_doc_view_manual"); - RNA_string_set(&ptr_props, "doc_id", buf); - uiItemFullO(layout, "WM_OT_doc_view_manual", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"), - ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0); - - WM_operator_properties_create(&ptr_props, "WM_OT_doc_view"); - RNA_string_set(&ptr_props, "doc_id", buf); - uiItemFullO(layout, "WM_OT_doc_view", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"), - ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0); - - /* XXX inactive option, not for public! */ -#if 0 - WM_operator_properties_create(&ptr_props, "WM_OT_doc_edit"); - RNA_string_set(&ptr_props, "doc_id", buf); - RNA_string_set(&ptr_props, "doc_new", but->optype->description); - - uiItemFullO(layout, "WM_OT_doc_edit", CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Submit Description"), - ICON_NONE, ptr_props.data, WM_OP_INVOKE_DEFAULT, 0); -#endif - } } /* perhaps we should move this into (G.debug & G_DEBUG) - campbell */ @@ -6861,14 +6848,6 @@ static bool ui_but_is_interactive(const uiBut *but, const bool labeledit) return true; } -bool ui_but_is_search_unlink_visible(const uiBut *but) -{ - BLI_assert(but->type == UI_BTYPE_SEARCH_MENU); - return ((but->editstr == NULL) && - (but->drawstr[0] != '\0') && - (but->flag & UI_BUT_SEARCH_UNLINK)); -} - /* x and y are only used in case event is NULL... */ static uiBut *ui_but_find_mouse_over_ex(ARegion *ar, const int x, const int y, const bool labeledit) { @@ -6956,7 +6935,8 @@ static bool button_modal_state(uiHandleButtonState state) BUTTON_STATE_MENU_OPEN); } -static void button_timers_tooltip_remove(bContext *C, uiBut *but) +/* removes tooltip timer from active but (meaning tooltip is disabled until it's reenabled again) */ +void UI_but_tooltip_timer_remove(bContext *C, uiBut *but) { uiHandleButtonData *data; @@ -7040,7 +7020,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s } else { but->flag |= UI_SELECT; - button_timers_tooltip_remove(C, but); + UI_but_tooltip_timer_remove(C, but); } /* text editing */ @@ -7669,7 +7649,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but) case WHEELDOWNMOUSE: case MIDDLEMOUSE: case MOUSEPAN: - button_timers_tooltip_remove(C, but); + UI_but_tooltip_timer_remove(C, but); /* fall-through */ default: /* handle button type specific events */ @@ -8644,7 +8624,7 @@ static int ui_handle_menu_event( { if (!but || !ui_but_contains_point_px(ar, but, event->x, event->y)) { if (but) { - button_timers_tooltip_remove(C, but); + UI_but_tooltip_timer_remove(C, but); } menu->is_grab = true; diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index d7b6824f812..d9558af5f71 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -121,6 +121,14 @@ enum { /* warn: rest of uiBut->flag in UI_interface.h */ }; +/* some buttons display icons only under special conditions + * (e.g. 'x' icon in search menu) - used with ui_but_icon_extra_get */ +typedef enum uiButExtraIconType { + UI_BUT_ICONEXTRA_NONE = 1, + UI_BUT_ICONEXTRA_UNLINK, + UI_BUT_ICONEXTRA_EYEDROPPER, +} uiButExtraIconType; + /* but->pie_dir */ typedef enum RadialDirection { UI_RADIAL_NONE = -1, @@ -456,6 +464,7 @@ extern bool ui_but_string_set(struct bContext *C, uiBut *but, const char *str) A extern bool ui_but_string_set_eval_num(struct bContext *C, uiBut *but, const char *str, double *value) ATTR_NONNULL(); extern int ui_but_string_get_max_length(uiBut *but); extern uiBut *ui_but_drag_multi_edit_get(uiBut *but); +extern uiButExtraIconType ui_but_icon_extra_get(uiBut *but); extern void ui_but_default_set(struct bContext *C, const bool all, const bool use_afterfunc); @@ -466,7 +475,6 @@ extern bool ui_but_is_unit(const uiBut *but) ATTR_WARN_UNUSED_RESULT; extern bool ui_but_is_compatible(const uiBut *but_a, const uiBut *but_b) ATTR_WARN_UNUSED_RESULT; extern bool ui_but_is_rna_valid(uiBut *but) ATTR_WARN_UNUSED_RESULT; extern bool ui_but_is_utf8(const uiBut *but) ATTR_WARN_UNUSED_RESULT; -extern bool ui_but_is_search_unlink_visible(const uiBut *but) ATTR_WARN_UNUSED_RESULT; extern int ui_but_is_pushed_ex(uiBut *but, double *value) ATTR_WARN_UNUSED_RESULT; extern int ui_but_is_pushed(uiBut *but) ATTR_WARN_UNUSED_RESULT; diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 5aee8e18ba0..239d6f7c493 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -82,6 +82,14 @@ /* only show pin header button for pinned panels */ #define USE_PIN_HIDDEN +/* the state of the mouse position relative to the panel */ +typedef enum uiPanelMouseState { + PANEL_MOUSE_OUTSIDE, /* mouse is not in the panel */ + PANEL_MOUSE_INSIDE_CONTENT, /* mouse is in the actual panel content */ + PANEL_MOUSE_INSIDE_HEADER, /* mouse is in the panel header */ + PANEL_MOUSE_INSIDE_SCALE, /* mouse is inside panel scale widget */ +} uiPanelMouseState; + typedef enum uiHandlePanelState { PANEL_STATE_DRAG, PANEL_STATE_DRAG_SCALE, @@ -1128,6 +1136,158 @@ static void ui_do_drag(const bContext *C, const wmEvent *event, Panel *panel) /******************* region level panel interaction *****************/ +static uiPanelMouseState ui_panel_mouse_state_get(const uiBlock *block, const Panel *pa, const int mx, const int my) +{ + /* open panel */ + if (pa->flag & PNL_CLOSEDX) { + if ((block->rect.xmin <= mx) && (block->rect.xmin + PNL_HEADER >= mx)) { + return PANEL_MOUSE_INSIDE_HEADER; + } + } + /* outside left/right side */ + else if ((block->rect.xmin > mx) || (block->rect.xmax < mx)) { + /* pass */ + } + else if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my)) { + return PANEL_MOUSE_INSIDE_HEADER; + } + /* open panel */ + else if (!(pa->flag & PNL_CLOSEDY)) { + if (pa->control & UI_PNL_SCALE) { + if (block->rect.xmax - PNL_HEADER <= mx) { + if (block->rect.ymin + PNL_HEADER >= my) { + return PANEL_MOUSE_INSIDE_SCALE; + } + } + } + if ((block->rect.xmin <= mx) && (block->rect.xmax >= mx)) { + if ((block->rect.ymin <= my) && (block->rect.ymax + PNL_HEADER >= my)) { + return PANEL_MOUSE_INSIDE_CONTENT; + } + } + } + return PANEL_MOUSE_OUTSIDE; +} + +typedef struct uiPanelDragCollapseHandle { + bool was_first_open; + int xy_init[2]; +} uiPanelDragCollapseHandle; + +static void ui_panel_drag_collapse_handler_remove(bContext *UNUSED(C), void *userdata) +{ + uiPanelDragCollapseHandle *dragcol_data = userdata; + MEM_freeN(dragcol_data); +} + +static void ui_panel_drag_collapse(bContext *C, uiPanelDragCollapseHandle *dragcol_data, const int xy_dst[2]) +{ + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = CTX_wm_region(C); + uiBlock *block; + Panel *pa; + + for (block = ar->uiblocks.first; block; block = block->next) { + float xy_a_block[2] = {UNPACK2(dragcol_data->xy_init)}; + float xy_b_block[2] = {UNPACK2(xy_dst)}; + rctf rect = block->rect; + int oldflag; + const bool is_horizontal = (panel_aligned(sa, ar) == BUT_HORIZONTAL); + + if ((pa = block->panel) == 0 || (pa->type && (pa->type->flag & PNL_NO_HEADER))) { + continue; + } + oldflag = pa->flag; + + /* lock one axis */ + if (is_horizontal) { + xy_b_block[1] = dragcol_data->xy_init[1]; + } + else { + xy_b_block[0] = dragcol_data->xy_init[0]; + } + + /* use cursor coords in block space */ + ui_window_to_block_fl(ar, block, &xy_a_block[0], &xy_a_block[1]); + ui_window_to_block_fl(ar, block, &xy_b_block[0], &xy_b_block[1]); + + /* set up rect to match header size */ + rect.ymin = rect.ymax; + rect.ymax = rect.ymin + PNL_HEADER; + if (pa->flag & PNL_CLOSEDX) { + rect.xmin = rect.xmin; + rect.xmax = rect.xmin + PNL_HEADER; + } + + /* touch all panels between last mouse coord and the current one */ + if (BLI_rctf_isect_segment(&rect, xy_a_block, xy_b_block)) { + /* force panel to close */ + if (dragcol_data->was_first_open == true) { + pa->flag |= (is_horizontal ? PNL_CLOSEDX : PNL_CLOSEDY); + } + /* force panel to open */ + else { + pa->flag &= ~PNL_CLOSED; + } + + /* if pa->flag has changed this means a panel was opened/closed here */ + if (pa->flag != oldflag) { + panel_activate_state(C, pa, PANEL_STATE_ANIMATION); + } + } + } +} + +/** + * Panel drag-collapse (modal handler) + * Clicking and dragging over panels toggles their collapse state based on the panel that was first + * dragged over. If it was open all affected panels incl the initial one are closed and vise versa. + */ +static int ui_panel_drag_collapse_handler(bContext *C, const wmEvent *event, void *userdata) +{ + wmWindow *win = CTX_wm_window(C); + uiPanelDragCollapseHandle *dragcol_data = userdata; + short retval = WM_UI_HANDLER_CONTINUE; + + switch (event->type) { + case MOUSEMOVE: + ui_panel_drag_collapse(C, dragcol_data, &event->x); + + retval = WM_UI_HANDLER_BREAK; + break; + case LEFTMOUSE: + if (event->val == KM_RELEASE) { + /* done! */ + WM_event_remove_ui_handler( + &win->modalhandlers, + ui_panel_drag_collapse_handler, + ui_panel_drag_collapse_handler_remove, + dragcol_data, true); + ui_panel_drag_collapse_handler_remove(C, dragcol_data); + } + /* don't let any left-mouse event fall through! */ + retval = WM_UI_HANDLER_BREAK; + break; + } + + return retval; +} + +static void ui_panel_drag_collapse_handler_add(const bContext *C, const bool was_open) +{ + wmWindow *win = CTX_wm_window(C); + wmEvent *event = win->eventstate; + uiPanelDragCollapseHandle *dragcol_data = MEM_mallocN(sizeof(*dragcol_data), __func__); + + dragcol_data->was_first_open = was_open; + copy_v2_v2_int(dragcol_data->xy_init, &event->x); + + WM_event_add_ui_handler( + C, &win->modalhandlers, + ui_panel_drag_collapse_handler, + ui_panel_drag_collapse_handler_remove, + dragcol_data, false); +} /* this function is supposed to call general window drawing too */ /* also it supposes a block has panel, and isn't a menu */ @@ -1199,15 +1359,27 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in /* snap back up so full panel aligns with screen edge */ if (block->panel->snap & PNL_SNAP_BOTTOM) block->panel->ofsy = 0; + + if (event == LEFTMOUSE) { + ui_panel_drag_collapse_handler_add(C, false); + } } else if (align == BUT_HORIZONTAL) { block->panel->flag |= PNL_CLOSEDX; + + if (event == LEFTMOUSE) { + ui_panel_drag_collapse_handler_add(C, true); + } } else { - /* snap down to bottom screen edge*/ + /* snap down to bottom screen edge */ block->panel->flag |= PNL_CLOSEDY; if (block->panel->snap & PNL_SNAP_BOTTOM) block->panel->ofsy = -block->panel->sizey; + + if (event == LEFTMOUSE) { + ui_panel_drag_collapse_handler_add(C, true); + } } for (pa = ar->panels.first; pa; pa = pa->next) { @@ -1722,8 +1894,8 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar) } for (block = ar->uiblocks.last; block; block = block->prev) { - bool inside = false, inside_header = false, inside_scale = false; - + uiPanelMouseState mouse_state; + mx = event->x; my = event->y; ui_window_to_block(ar, block, &mx, &my); @@ -1735,32 +1907,11 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar) continue; if (pa->type && pa->type->flag & PNL_NO_HEADER) /* XXX - accessed freed panels when scripts reload, need to fix. */ continue; - - /* clicked at panel header? */ - if (pa->flag & PNL_CLOSEDX) { - if (block->rect.xmin <= mx && block->rect.xmin + PNL_HEADER >= mx) - inside_header = true; - } - else if (block->rect.xmin > mx || block->rect.xmax < mx) { - /* outside left/right side */ - } - else if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my)) { - inside_header = true; - } - else if (!(pa->flag & PNL_CLOSEDY)) { - /* open panel */ - if (pa->control & UI_PNL_SCALE) { - if (block->rect.xmax - PNL_HEADER <= mx) - if (block->rect.ymin + PNL_HEADER >= my) - inside_scale = true; - } - if (block->rect.xmin <= mx && block->rect.xmax >= mx) - if (block->rect.ymin <= my && block->rect.ymax + PNL_HEADER >= my) - inside = true; - } - + + mouse_state = ui_panel_mouse_state_get(block, pa, mx, my); + /* XXX hardcoded key warning */ - if ((inside || inside_header) && event->val == KM_PRESS) { + if (ELEM(mouse_state, PANEL_MOUSE_INSIDE_CONTENT, PANEL_MOUSE_INSIDE_HEADER) && event->val == KM_PRESS) { if (event->type == AKEY && ((event->ctrl + event->oskey + event->shift + event->alt) == 0)) { if (pa->flag & PNL_CLOSEDY) { @@ -1779,13 +1930,13 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar) if (ui_but_is_active(ar)) continue; - if (inside || inside_header) { + if (ELEM(mouse_state, PANEL_MOUSE_INSIDE_CONTENT, PANEL_MOUSE_INSIDE_HEADER)) { if (event->val == KM_PRESS) { /* open close on header */ if (ELEM(event->type, RETKEY, PADENTER)) { - if (inside_header) { + if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) { ui_handle_panel_header(C, block, mx, my, RETKEY, event->ctrl, event->shift); retval = WM_UI_HANDLER_BREAK; break; @@ -1795,12 +1946,12 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar) /* all inside clicks should return in break - overlapping/float panels */ retval = WM_UI_HANDLER_BREAK; - if (inside_header) { - ui_handle_panel_header(C, block, mx, my, 0, event->ctrl, event->shift); + if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) { + ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl, event->shift); retval = WM_UI_HANDLER_BREAK; break; } - else if (inside_scale && !(pa->flag & PNL_CLOSED)) { + else if ((mouse_state == PANEL_MOUSE_INSIDE_SCALE) && !(pa->flag & PNL_CLOSED)) { panel_activate_state(C, pa, PANEL_STATE_DRAG_SCALE); retval = WM_UI_HANDLER_BREAK; break; @@ -1808,7 +1959,7 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar) } else if (event->type == RIGHTMOUSE) { - if (inside_header) { + if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) { ui_panel_menu(C, ar, block->panel); retval = WM_UI_HANDLER_BREAK; break; diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index c3a9d17d255..8d2ee04a2e9 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -1634,17 +1634,14 @@ static uiBlock *ui_icon_view_menu_cb(bContext *C, ARegion *ar, void *arg_litem) static RNAUpdateCb cb; uiBlock *block; uiBut *but; - int icon; + int icon, value; EnumPropertyItem *item; int a; bool free; /* arg_litem is malloced, can be freed by parent button */ cb = *((RNAUpdateCb *)arg_litem); - - /* unused */ - // icon = RNA_property_enum_get(&cb.ptr, cb.prop); - + block = UI_block_begin(C, ar, "_popup", UI_EMBOSS); UI_block_flag_enable(block, UI_BLOCK_LOOP); @@ -1659,7 +1656,9 @@ static uiBlock *ui_icon_view_menu_cb(bContext *C, ARegion *ar, void *arg_litem) y = (a / 8) * UI_UNIT_X * 5; icon = item[a].icon; - but = uiDefIconButR_prop(block, UI_BTYPE_ROW, 0, icon, x, y, UI_UNIT_X * 5, UI_UNIT_Y * 5, &cb.ptr, cb.prop, -1, 0, icon, -1, -1, NULL); + value = item[a].value; + but = uiDefIconButR_prop(block, UI_BTYPE_ROW, 0, icon, x, y, UI_UNIT_X * 5, UI_UNIT_Y * 5, + &cb.ptr, cb.prop, -1, 0, value, -1, -1, NULL); UI_but_flag_enable(but, UI_HAS_ICON | UI_BUT_ICON_PREVIEW); } @@ -1677,36 +1676,35 @@ void uiTemplateIconView(uiLayout *layout, PointerRNA *ptr, const char *propname) { PropertyRNA *prop = RNA_struct_find_property(ptr, propname); RNAUpdateCb *cb; + EnumPropertyItem *items; uiBlock *block; uiBut *but; -// rctf rect; /* UNUSED */ - int icon; - - if (!prop || RNA_property_type(prop) != PROP_ENUM) + int value, icon = ICON_NONE, tot_items; + bool free_items; + + if (!prop || RNA_property_type(prop) != PROP_ENUM) { + RNA_warning("property of type Enum not found: %s.%s", RNA_struct_identifier(ptr->type), propname); return; - - icon = RNA_property_enum_get(ptr, prop); - + } + + block = uiLayoutAbsoluteBlock(layout); + + RNA_property_enum_items(block->evil_C, ptr, prop, &items, &tot_items, &free_items); + value = RNA_property_enum_get(ptr, prop); + RNA_enum_icon_from_value(items, value, &icon); + cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb"); cb->ptr = *ptr; cb->prop = prop; - -// rect.xmin = 0; rect.xmax = 10.0f * UI_UNIT_X; -// rect.ymin = 0; rect.ymax = 10.0f * UI_UNIT_X; - - block = uiLayoutAbsoluteBlock(layout); - but = uiDefBlockButN(block, ui_icon_view_menu_cb, MEM_dupallocN(cb), "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, ""); + but = uiDefBlockButN(block, ui_icon_view_menu_cb, cb, "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, ""); - -// but = uiDefIconButR_prop(block, UI_BTYPE_ROW, 0, icon, 0, 0, BLI_rctf_size_x(&rect), BLI_rctf_size_y(&rect), ptr, prop, -1, 0, icon, -1, -1, NULL); - but->icon = icon; UI_but_flag_enable(but, UI_HAS_ICON | UI_BUT_ICON_PREVIEW); - - UI_but_funcN_set(but, rna_update_cb, MEM_dupallocN(cb), NULL); - - MEM_freeN(cb); + + if (free_items) { + MEM_freeN(items); + } } /********************* Histogram Template ************************/ diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 28bd637ae59..14d97dd883e 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -52,6 +52,9 @@ #include "UI_interface.h" #include "UI_resources.h" +#include "WM_api.h" +#include "WM_types.h" + #include "interface_intern.h" @@ -309,6 +312,34 @@ int UI_calc_float_precision(int prec, double value) return prec; } +bool UI_but_online_manual_id(const uiBut *but, char *r_str, size_t maxlength) +{ + if (but->rnapoin.id.data && but->rnapoin.data && but->rnaprop) { + BLI_snprintf(r_str, maxlength, "%s.%s", RNA_struct_identifier(but->rnapoin.type), + RNA_property_identifier(but->rnaprop)); + return true; + } + else if (but->optype) { + WM_operator_py_idname(r_str, but->optype->idname); + return true; + } + + *r_str = '\0'; + return false; +} + +bool UI_but_online_manual_id_from_active(const struct bContext *C, char *r_str, size_t maxlength) +{ + uiBut *but = UI_context_active_but_get(C); + + if (but) { + return UI_but_online_manual_id(but, r_str, maxlength); + } + + *r_str = '\0'; + return false; +} + /* -------------------------------------------------------------------- */ /* Modal Button Store API */ diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index b3c3d7f53a9..08bd2d3360c 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1501,6 +1501,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB const bool show_menu_icon = ui_but_draw_menu_icon(but); float alpha = (float)wcol->text[3] / 255.0f; char password_str[UI_MAX_DRAW_STR]; + uiButExtraIconType extra_icon_type; ui_but_text_password_hide(password_str, but, false); @@ -1540,11 +1541,23 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB } /* unlink icon for this button type */ - if ((but->type == UI_BTYPE_SEARCH_MENU) && ui_but_is_search_unlink_visible(but)) { + if ((but->type == UI_BTYPE_SEARCH_MENU) && + ((extra_icon_type = ui_but_icon_extra_get(but)) != UI_BUT_ICONEXTRA_NONE)) + { rcti temp = *rect; temp.xmin = temp.xmax - (BLI_rcti_size_y(rect) * 1.08f); - widget_draw_icon(but, ICON_X, alpha, &temp, false); + + if (extra_icon_type == UI_BUT_ICONEXTRA_UNLINK) { + widget_draw_icon(but, ICON_X, alpha, &temp, false); + } + else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) { + widget_draw_icon(but, ICON_EYEDROPPER, alpha, &temp, false); + } + else { + BLI_assert(0); + } + rect->xmax -= ICON_SIZE_FROM_BUTRECT(rect); } diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 15e742c930a..8e003e50df3 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -569,6 +569,13 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo cp = ts->paint_curve_pivot; break; + case TH_METADATA_BG: + cp = ts->metadatabg; + break; + case TH_METADATA_TEXT: + cp = ts->metadatatext; + break; + case TH_UV_OTHERS: cp = ts->uv_others; break; @@ -2602,6 +2609,15 @@ void init_userdef_do_versions(void) cp[3] = 255; } } + + if (U.versionfile < 274 || (U.versionfile == 274 && U.subversionfile < 5)) { + bTheme *btheme; + for (btheme = U.themes.first; btheme; btheme = btheme->next) { + copy_v4_v4_char(btheme->tima.metadatatext, btheme->tima.text_hi); + copy_v4_v4_char(btheme->tseq.metadatatext, btheme->tseq.text_hi); + } + } + if (U.pixelsize == 0.0f) U.pixelsize = 1.0f; diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 5730c967880..816c9a93d8c 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -328,7 +328,7 @@ static void VIEW2D_OT_pan(wmOperatorType *ot) ot->cancel = view_pan_cancel; /* operator is modal */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; /* rna - must keep these in sync with the other operators */ RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX); @@ -661,7 +661,9 @@ static void view_zoomstep_apply_ex(bContext *C, v2dViewZoomData *vzd, const bool const float zoomx = (float)(BLI_rcti_size_x(&v2d->mask) + 1) / BLI_rctf_size_x(&v2d->cur); /* only move view to mouse if zoom fac is inside minzoom/maxzoom */ - if (IN_RANGE_INCL(zoomx, v2d->minzoom, v2d->maxzoom)) { + if (((v2d->keepzoom & V2D_LIMITZOOM) == 0) || + IN_RANGE_INCL(zoomx, v2d->minzoom, v2d->maxzoom)) + { float mval_fac = (vzd->mx_2d - cur_old.xmin) / BLI_rctf_size_x(&cur_old); float mval_faci = 1.0f - mval_fac; float ofs = (mval_fac * dx) - (mval_faci * dx); @@ -692,7 +694,9 @@ static void view_zoomstep_apply_ex(bContext *C, v2dViewZoomData *vzd, const bool const float zoomy = (float)(BLI_rcti_size_y(&v2d->mask) + 1) / BLI_rctf_size_y(&v2d->cur); /* only move view to mouse if zoom fac is inside minzoom/maxzoom */ - if (IN_RANGE_INCL(zoomy, v2d->minzoom, v2d->maxzoom)) { + if (((v2d->keepzoom & V2D_LIMITZOOM) == 0) || + IN_RANGE_INCL(zoomy, v2d->minzoom, v2d->maxzoom)) + { float mval_fac = (vzd->my_2d - cur_old.ymin) / BLI_rctf_size_y(&cur_old); float mval_faci = 1.0f - mval_fac; float ofs = (mval_fac * dy) - (mval_faci * dy); @@ -1175,7 +1179,7 @@ static void VIEW2D_OT_zoom(wmOperatorType *ot) ot->poll = view_zoom_poll; /* operator is repeatable */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; /* rna - must keep these in sync with the other operators */ prop = RNA_def_float(ot->srna, "deltax", 0, -FLT_MAX, FLT_MAX, "Delta X", "", -FLT_MAX, FLT_MAX); diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index 7e767d8f6c8..2efa9e211c9 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -253,7 +253,7 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline return; if (sc) - undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) != 0; + undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT); /* TODO, add this to sequence editor */ handle_size = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) * U.pixelsize; @@ -422,7 +422,7 @@ static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (* float (*points)[2] = orig_points; if (sc) { - int undistort = sc->clip && sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT; + const bool undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT); if (undistort) { int i; diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index 113f0f71b53..35fc4483702 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -446,7 +446,7 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, bool select, bool exten } } - view3d_validate_backbuf(vc); + ED_view3d_backbuf_validate(vc); ibuf = IMB_allocImBuf(sx, sy, 32, IB_rect); rt = ibuf->rect; diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c index 6ce5e8a304b..c67ee41703a 100644 --- a/source/blender/editors/mesh/editmesh_add.c +++ b/source/blender/editors/mesh/editmesh_add.c @@ -62,10 +62,7 @@ static Object *make_prim_init(bContext *C, const char *idname, *was_editmode = false; if (obedit == NULL || obedit->type != OB_MESH) { - obedit = ED_object_add_type(C, OB_MESH, loc, rot, false, layer); - - rename_id((ID *)obedit, idname); - rename_id((ID *)obedit->data, idname); + obedit = ED_object_add_type(C, OB_MESH, idname, loc, rot, false, layer); /* create editmode */ ED_object_editmode_enter(C, EM_DO_UNDO | EM_IGNORE_LAYER); /* rare cases the active layer is messed up */ diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index 0e48cbcd589..1e44d7e654d 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -477,7 +477,7 @@ void MESH_OT_bevel(wmOperatorType *ot) ot->poll = ED_operator_editmesh; /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING; RNA_def_enum(ot->srna, "offset_type", offset_type_items, 0, "Amount Type", "What distance Amount measures"); prop = RNA_def_float(ot->srna, "offset", 0.0f, -FLT_MAX, FLT_MAX, "Amount", "", 0.0f, 1.0f); diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c index 5c7efcc40da..e8f9a76a873 100644 --- a/source/blender/editors/mesh/editmesh_extrude.c +++ b/source/blender/editors/mesh/editmesh_extrude.c @@ -574,8 +574,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w mul_mat3_m4_v3(vc.obedit->imat, nor); /* local space */ /* correct the normal to be aligned on the view plane */ - copy_v3_v3(view_vec, vc.rv3d->viewinv[2]); - mul_mat3_m4_v3(vc.obedit->imat, view_vec); + mul_v3_mat3_m4v3(view_vec, vc.obedit->imat, vc.rv3d->viewinv[2]); cross_v3_v3v3(cross, nor, view_vec); cross_v3_v3v3(nor, view_vec, cross); normalize_v3(nor); diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c index f1c3ca30610..80d3777d057 100644 --- a/source/blender/editors/mesh/editmesh_inset.c +++ b/source/blender/editors/mesh/editmesh_inset.c @@ -499,7 +499,7 @@ void MESH_OT_inset(wmOperatorType *ot) ot->poll = ED_operator_editmesh; /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING; /* properties */ RNA_def_boolean(ot->srna, "use_boundary", true, "Boundary", "Inset face boundaries"); diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index f3745ed72fb..cfd0d3fdcf5 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -1319,18 +1319,63 @@ static BMElem *bm_elem_from_knife_edge(KnifeEdge *kfe) return ele_test; } +/* Do edges e1 and e2 go between exactly the same coordinates? */ +static bool coinciding_edges(BMEdge *e1, BMEdge *e2) +{ + const float *co11, *co12, *co21, *co22; + + co11 = e1->v1->co; + co12 = e1->v2->co; + co21 = e2->v1->co; + co22 = e2->v2->co; + if ((equals_v3v3(co11, co21) && equals_v3v3(co12, co22)) || + (equals_v3v3(co11, co22) && equals_v3v3(co12, co21))) + { + return true; + } + else { + return false; + } +} + +/* Callback used in point_is_visible to exclude hits on the faces that are the same + * as or contain the hitting element (which is in user_data). + * Also (see T44492) want to exclude hits on faces that butt up to the hitting element + * (e.g., when you double an edge by an edge split). + */ static bool bm_ray_cast_cb_elem_not_in_face_check(BMFace *f, void *user_data) { + bool ans; + BMEdge *e, *e2; + BMIter iter; + switch (((BMElem *)user_data)->head.htype) { case BM_FACE: - return (BMFace *)user_data != f; + ans = (BMFace *)user_data != f; + break; case BM_EDGE: - return !BM_edge_in_face((BMEdge *)user_data, f); + e = (BMEdge *)user_data; + ans = !BM_edge_in_face(e, f); + if (ans) { + /* Is it a boundary edge, coincident with a split edge? */ + if (BM_edge_is_boundary(e)) { + BM_ITER_ELEM(e2, &iter, f, BM_EDGES_OF_FACE) { + if (coinciding_edges(e, e2)) { + ans = false; + break; + } + } + } + } + break; case BM_VERT: - return !BM_vert_in_face((BMVert *)user_data, f); + ans = !BM_vert_in_face((BMVert *)user_data, f); + break; default: - return true; + ans = true; + break; } + return ans; } @@ -2831,8 +2876,7 @@ static void knife_recalc_projmat(KnifeTool_OpData *kcd) ED_view3d_ob_project_mat_get(kcd->ar->regiondata, kcd->ob, kcd->projmat); invert_m4_m4(kcd->projmat_inv, kcd->projmat); - copy_v3_v3(kcd->proj_zaxis, kcd->vc.rv3d->viewinv[2]); - mul_mat3_m4_v3(kcd->ob->imat, kcd->proj_zaxis); + mul_v3_mat3_m4v3(kcd->proj_zaxis, kcd->ob->imat, kcd->vc.rv3d->viewinv[2]); normalize_v3(kcd->proj_zaxis); kcd->is_ortho = ED_view3d_clip_range_get(kcd->vc.v3d, kcd->vc.rv3d, @@ -3006,6 +3050,8 @@ static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event) knifetool_init(C, kcd, only_select, cut_through, true); + op->flag |= OP_IS_MODAL_CURSOR_REGION; + /* add a modal handler for this operator - handles loop selection */ WM_cursor_modal_set(CTX_wm_window(C), BC_KNIFECURSOR); WM_event_add_modal_handler(C, op); @@ -3098,6 +3144,9 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_FINISHED; } + em_setup_viewcontext(C, &kcd->vc); + kcd->ar = kcd->vc.ar; + view3d_operator_needs_opengl(C); ED_view3d_init_mats_rv3d(obedit, kcd->vc.rv3d); /* needed to initialize clipping */ @@ -3257,6 +3306,13 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event) } } + if (kcd->mode == MODE_DRAGGING) { + op->flag &= ~OP_IS_MODAL_CURSOR_REGION; + } + else { + op->flag |= OP_IS_MODAL_CURSOR_REGION; + } + if (do_refresh) { /* we don't really need to update mval, * but this happens to be the best way to refresh at the moment */ diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 3d93210382c..c7f9522ab3f 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -553,6 +553,7 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event) /* add a modal handler for this operator - handles loop selection */ if (is_interactive) { + op->flag |= OP_IS_MODAL_CURSOR_REGION; WM_event_add_modal_handler(C, op); } @@ -639,6 +640,9 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event) bool show_cuts = false; const bool has_numinput = hasNumInput(&lcd->num); + em_setup_viewcontext(C, &lcd->vc); + lcd->ar = lcd->vc.ar; + view3d_operator_needs_opengl(C); /* using the keyboard to input the number of cuts */ @@ -835,7 +839,7 @@ void MESH_OT_loopcut(wmOperatorType *ot) prop = RNA_def_property(ot->srna, "falloff", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, proportional_falloff_curve_only_items); - RNA_def_property_enum_default(prop, PROP_ROOT); + RNA_def_property_enum_default(prop, PROP_INVSQUARE); RNA_def_property_ui_text(prop, "Falloff", "Falloff type the feather"); RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */ diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c index 4eaac6cc1d3..72dfb89e5f3 100644 --- a/source/blender/editors/mesh/editmesh_path.c +++ b/source/blender/editors/mesh/editmesh_path.c @@ -94,7 +94,7 @@ static bool mouse_mesh_shortest_path_vert(ViewContext *vc) float dist = ED_view3d_select_dist_px(); const bool use_length = true; - v_dst = EDBM_vert_find_nearest(vc, &dist, false, false); + v_dst = EDBM_vert_find_nearest(vc, &dist); if (v_dst) { struct UserData user_data = {bm, vc->obedit->data, vc->scene}; LinkNode *path = NULL; diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index 45e16ceff7b..abd88ae65aa 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -559,9 +559,10 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve } } - /* this should be impossible, but sanity checks are a good thing */ - if (!v) + /* (v == NULL) should be impossible */ + if ((v == NULL) || (v->e == NULL)) { return OPERATOR_CANCELLED; + } is_wire = BM_vert_is_wire(v); @@ -570,12 +571,11 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve if (v->e) { /* find closest edge to mouse cursor */ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { - const bool is_boundary = BM_edge_is_boundary(e); /* consider wire as boundary for this purpose, * otherwise we can't a face away from a wire edge */ - totboundary_edge += (is_boundary != 0 || BM_edge_is_wire(e)); + totboundary_edge += (BM_edge_is_boundary(e) || BM_edge_is_wire(e)); if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { - if (is_boundary == false && BM_edge_is_manifold(e)) { + if (BM_edge_is_manifold(e)) { d = edbm_rip_edgedist_squared(ar, projectMat, e->v1->co, e->v2->co, fmval, INSET_DEFAULT); if ((e2 == NULL) || (d < dist_sq)) { dist_sq = d; @@ -622,6 +622,32 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve } } + if (e2) { + /* Try to split off a non-manifold fan (when we have multiple disconnected fans) */ + + /* note: we're lazy here and first split then check there are any faces remaining, + * this isn't good practice, however its less hassle then checking for multiple-disconnected regions */ + BMLoop *l_sep = e2->l->v == v ? e2->l : e2->l->next; + BMVert *v_new; + BLI_assert(l_sep->v == v); + v_new = bmesh_urmv_loop_region(bm, l_sep); + if (BM_vert_find_first_loop(v)) { + BM_vert_select_set(bm, v, false); + BM_select_history_remove(bm, v); + + BM_vert_select_set(bm, v_new, true); + if (ese.ele) { + BM_select_history_store(bm, v_new); + } + + return OPERATOR_FINISHED; + } + else { + /* rewind */ + BM_vert_splice(bm, v, v_new); + } + } + /* should we go ahead with edge rip or do we need to do special case, split off vertex?: * split off vertex if... * - we cant find an edge - this means we are ripping a faces vert that is connected to other @@ -715,7 +741,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve } for (i = 2; i < vout_len; i++) { - BM_vert_splice(bm, vout[i], vout[1]); + BM_vert_splice(bm, vout[1], vout[i]); } } @@ -734,20 +760,42 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve /* unlike edge split, for single vertex split we only use the operator in one of the cases * but both allocate fill */ - /* rip two adjacent edges */ - if (BM_edge_is_boundary(e2) || BM_vert_face_count_is_equal(v, 2)) { - /* Don't run the edge split operator in this case */ + { BMVert *v_rip; + BMLoop *larr[2]; + int larr_len = 0; - l = BM_edge_vert_share_loop(e2->l, v); + /* rip two adjacent edges */ + if (BM_edge_is_boundary(e2) || BM_vert_face_count_is_equal(v, 2)) { + /* Don't run the edge split operator in this case */ - /* only tag for face-fill (we don't call the operator) */ - if (BM_edge_is_boundary(e2)) { - BM_elem_flag_enable(e2, BM_ELEM_TAG); + l = BM_edge_vert_share_loop(e2->l, v); + larr[larr_len] = l; + larr_len++; + + /* only tag for face-fill (we don't call the operator) */ + if (BM_edge_is_boundary(e2)) { + BM_elem_flag_enable(e2, BM_ELEM_TAG); + } + else { + BM_elem_flag_enable(l->e, BM_ELEM_TAG); + BM_elem_flag_enable(l->prev->e, BM_ELEM_TAG); + } } else { - BM_elem_flag_enable(l->e, BM_ELEM_TAG); - BM_elem_flag_enable(l->prev->e, BM_ELEM_TAG); + if (BM_edge_is_manifold(e2)) { + BMLoop *l_iter, *l_first; + + l_iter = l_first = e2->l; + do { + larr[larr_len] = BM_edge_vert_share_loop(l_iter, v); + BM_elem_flag_enable(larr[larr_len]->e, BM_ELEM_TAG); + larr_len++; + } while ((l_iter = l_iter->radial_next) != l_first); + } + else { + /* looks like there are no split edges, we could just return/report-error? - Campbell */ + } } /* keep directly before edgesplit */ @@ -755,13 +803,12 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve fill_uloop_pairs = edbm_tagged_loop_pairs_to_fill(bm); } -#if 0 - v_rip = BM_face_vert_separate(bm, l->f, v); -#else - v_rip = BM_face_loop_separate(bm, l); -#endif - - BLI_assert(v_rip); + if (larr_len) { + v_rip = BM_face_loop_separate_multi(bm, larr, larr_len); + } + else { + v_rip = NULL; + } if (v_rip) { BM_vert_select_set(bm, v_rip, true); @@ -771,27 +818,6 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve return OPERATOR_CANCELLED; } } - else { - if (BM_edge_is_manifold(e2)) { - l = e2->l; - e = BM_loop_other_edge_loop(l, v)->e; - BM_elem_flag_enable(e, BM_ELEM_TAG); - - l = e2->l->radial_next; - e = BM_loop_other_edge_loop(l, v)->e; - BM_elem_flag_enable(e, BM_ELEM_TAG); - } - else { - /* looks like there are no split edges, we could just return/report-error? - Campbell */ - } - - /* keep directly before edgesplit */ - if (do_fill) { - fill_uloop_pairs = edbm_tagged_loop_pairs_to_fill(bm); - } - - BM_mesh_edgesplit(em->bm, true, true, true); - } { /* --- select which vert --- */ diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 0c3f69e4996..4ce493def5b 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -36,6 +36,7 @@ #include "BLI_linklist.h" #include "BLI_linklist_stack.h" #include "BLI_math.h" +#include "BLI_math_bits.h" #include "BLI_rand.h" #include "BLI_array.h" @@ -196,11 +197,11 @@ bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xma unsigned int *dr; int a; - if (vc->obedit == NULL || vc->v3d->drawtype < OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT) == 0) { + if (vc->obedit == NULL || !V3D_IS_ZBUF(vc->v3d)) { return false; } - buf = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax); + buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax); if (buf == NULL) return false; if (bm_vertoffs == 0) return false; @@ -271,11 +272,11 @@ bool EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short return false; } } - else if (vc->v3d->drawtype < OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT) == 0) { + else if (!V3D_IS_ZBUF(vc->v3d)) { return false; } - buf = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax); + buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax); if (buf == NULL) return false; if (bm_vertoffs == 0) return false; @@ -320,13 +321,13 @@ bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) return false; } } - else if (vc->v3d->drawtype < OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT) == 0) { + else if (!V3D_IS_ZBUF(vc->v3d)) { return false; } xmin = xs - rads; xmax = xs + rads; ymin = ys - rads; ymax = ys + rads; - buf = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax); + buf = ED_view3d_backbuf_read(vc, xmin, ymin, xmax, ymax); if (bm_vertoffs == 0) return false; if (buf == NULL) return false; @@ -350,194 +351,369 @@ bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) } + +/* -------------------------------------------------------------------- */ + +/** \name Find Nearest Vert/Edge/Face + * + * \note Screen-space manhatten distances are used here, + * since its faster and good enough for the purpose of selection. + * + * \note \a dist_bias is used so we can bias against selected items. + * when choosing between elements of a single type, but return the real distance + * to avoid the bias interfering with distance comparisons when mixing types. + * \{ */ + +#define FIND_NEAR_SELECT_BIAS 5 +#define FIND_NEAR_CYCLE_THRESHOLD_MIN 3 + +struct NearestVertUserData_Hit { + float dist; + float dist_bias; + int index; + BMVert *vert; +}; + +struct NearestVertUserData { + float mval_fl[2]; + bool use_select_bias; + bool use_cycle; + int cycle_index_prev; + + struct NearestVertUserData_Hit hit; + struct NearestVertUserData_Hit hit_cycle; +}; + static void findnearestvert__doClosest(void *userData, BMVert *eve, const float screen_co[2], int index) { - struct { float mval_fl[2], pass, select, strict; float dist, lastIndex, closestIndex; BMVert *closest; } *data = userData; + struct NearestVertUserData *data = userData; + float dist_test, dist_test_bias; - if (data->pass == 0) { - if (index <= data->lastIndex) - return; - } - else { - if (index > data->lastIndex) - return; + dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co); + + if (data->use_select_bias && BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + dist_test_bias += FIND_NEAR_SELECT_BIAS; } - if (data->dist > 3) { - float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co); - if (BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->select) { - if (data->strict == 1) { - return; - } - else { - dist_test += 5; - } - } + if (dist_test_bias < data->hit.dist_bias) { + data->hit.dist_bias = dist_test_bias; + data->hit.dist = dist_test; + data->hit.index = index; + data->hit.vert = eve; + } - if (dist_test < data->dist) { - data->dist = dist_test; - data->closest = eve; - data->closestIndex = index; + if (data->use_cycle) { + if ((data->hit_cycle.vert == NULL) && + (index > data->cycle_index_prev) && + (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN)) + { + data->hit_cycle.dist_bias = dist_test_bias; + data->hit_cycle.dist = dist_test; + data->hit_cycle.index = index; + data->hit_cycle.vert = eve; } } } - -static bool findnearestvert__backbufIndextest(void *handle, unsigned int index) -{ - BMEditMesh *em = (BMEditMesh *)handle; - BMVert *eve = BM_vert_at_index_find(em->bm, index - 1); - return !(eve && BM_elem_flag_test(eve, BM_ELEM_SELECT)); -} /** - * findnearestvert - * - * dist (in/out): minimal distance to the nearest and at the end, actual distance - * sel: selection bias - * if SELECT, selected vertice are given a 5 pixel bias to make them further than unselect verts - * if 0, unselected vertice are given the bias - * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased + * Nearest vertex under the cursor. + * + * \param r_dist (in/out), minimal distance to the nearest and at the end, actual distance + * \param use_select_bias + * - When true, selected vertice are given a 5 pixel bias to make them further than unselect verts. + * - When false, unselected vertice are given the bias. + * \param use_cycle Cycle over elements within #FIND_NEAR_CYCLE_THRESHOLD_MIN in order of index. */ -BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist, const bool sel, const bool strict) +BMVert *EDBM_vert_find_nearest_ex( + ViewContext *vc, float *r_dist, + const bool use_select_bias, bool use_cycle) { - if (vc->v3d->drawtype > OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) { - float distance; + BMesh *bm = vc->em->bm; + + if (V3D_IS_ZBUF(vc->v3d)) { + const int dist_px = ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist); + float dist_test; unsigned int index; BMVert *eve; - if (strict) { - index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_wireoffs, 0xFFFFFF, &distance, - strict, vc->em, findnearestvert__backbufIndextest); - } - else { - index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_wireoffs, 0xFFFFFF, &distance, - 0, NULL, NULL); - } - - eve = index ? BM_vert_at_index_find(vc->em->bm, index - 1) : NULL; + index = ED_view3d_backbuf_sample_rect( + vc, vc->mval, dist_px, bm_wireoffs, 0xFFFFFF, &dist_test); + eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL; - if (eve && distance < *r_dist) { - *r_dist = distance; - return eve; - } - else { - return NULL; + if (eve) { + if (dist_test < *r_dist) { + *r_dist = dist_test; + return eve; + } } - + return NULL; } else { - struct { float mval_fl[2], pass, select, strict; float dist, lastIndex, closestIndex; BMVert *closest; } data; - static int lastSelectedIndex = 0; - static BMVert *lastSelected = NULL; - - if (lastSelected && BM_vert_at_index_find(vc->em->bm, lastSelectedIndex) != lastSelected) { - lastSelectedIndex = 0; - lastSelected = NULL; + struct NearestVertUserData data = {{0}}; + const struct NearestVertUserData_Hit *hit; + const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT; + + static int prev_select_index = 0; + static const BMVert *prev_select_elem = NULL; + + if ((use_cycle == false) || + (prev_select_elem && (prev_select_elem != BM_vert_at_index_find_or_table(bm, prev_select_index)))) + { + prev_select_index = 0; + prev_select_elem = NULL; } - data.lastIndex = lastSelectedIndex; data.mval_fl[0] = vc->mval[0]; data.mval_fl[1] = vc->mval[1]; - data.select = sel ? BM_ELEM_SELECT : 0; - data.dist = *r_dist; - data.strict = strict; - data.closest = NULL; - data.closestIndex = 0; - - data.pass = 0; + data.use_select_bias = use_select_bias; + data.use_cycle = use_cycle; + data.hit.dist = data.hit_cycle.dist = \ + data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist; + data.cycle_index_prev = prev_select_index; ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, clip_flag); - mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + hit = (data.use_cycle && data.hit_cycle.vert) ? &data.hit_cycle : &data.hit; + *r_dist = hit->dist; - if (data.dist > 3) { - data.pass = 1; - mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - } + prev_select_elem = hit->vert; + prev_select_index = hit->index; - *r_dist = data.dist; - lastSelected = data.closest; - lastSelectedIndex = data.closestIndex; + return hit->vert; + } +} + +BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist) +{ + return EDBM_vert_find_nearest_ex(vc, r_dist, false, false); +} + +/* find the distance to the edge we already have */ +struct NearestEdgeUserData_ZBuf { + float mval_fl[2]; + float dist; + const BMEdge *edge_test; +}; + +static void find_nearest_edge_center__doZBuf( + void *userData, BMEdge *eed, + const float screen_co_a[2], const float screen_co_b[2], + int UNUSED(index)) +{ + struct NearestEdgeUserData_ZBuf *data = userData; + + if (eed == data->edge_test) { + float dist_test; + float screen_co_mid[2]; + + mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b); + dist_test = len_manhattan_v2v2(data->mval_fl, screen_co_mid); - return data.closest; + if (dist_test < data->dist) { + data->dist = dist_test; + } } } +struct NearestEdgeUserData_Hit { + float dist; + float dist_bias; + int index; + BMEdge *edge; + + /* edges only, un-biased manhatten distance to which ever edge we pick + * (not used for choosing) */ + float dist_center; +}; + +struct NearestEdgeUserData { + ViewContext vc; + float mval_fl[2]; + bool use_select_bias; + bool use_cycle; + int cycle_index_prev; + + struct NearestEdgeUserData_Hit hit; + struct NearestEdgeUserData_Hit hit_cycle; +}; + /* note; uses v3d, so needs active 3d window */ -static void findnearestedge__doClosest(void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int UNUSED(index)) +static void find_nearest_edge__doClosest( + void *userData, BMEdge *eed, + const float screen_co_a[2], const float screen_co_b[2], + int index) { - struct { ViewContext vc; float mval_fl[2]; float dist; BMEdge *closest; } *data = userData; - int distance; + struct NearestEdgeUserData *data = userData; + float dist_test, dist_test_bias; - distance = dist_to_line_segment_v2(data->mval_fl, screen_co_a, screen_co_b); - - if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) { - distance += 5; + float fac = line_point_factor_v2(data->mval_fl, screen_co_a, screen_co_b); + float screen_co[2]; + + if (fac <= 0.0f) { + fac = 0.0f; + copy_v2_v2(screen_co, screen_co_a); + } + else if (fac >= 1.0f) { + fac = 1.0f; + copy_v2_v2(screen_co, screen_co_b); + } + else { + interp_v2_v2v2(screen_co, screen_co_a, screen_co_b, fac); } - if (distance < data->dist) { - if (data->vc.rv3d->rflag & RV3D_CLIPPING) { - float lambda = line_point_factor_v2(data->mval_fl, screen_co_a, screen_co_b); - float vec[3]; + dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co); - vec[0] = eed->v1->co[0] + lambda * (eed->v2->co[0] - eed->v1->co[0]); - vec[1] = eed->v1->co[1] + lambda * (eed->v2->co[1] - eed->v1->co[1]); - vec[2] = eed->v1->co[2] + lambda * (eed->v2->co[2] - eed->v1->co[2]); + if (data->use_select_bias && BM_elem_flag_test(eed, BM_ELEM_SELECT)) { + dist_test += FIND_NEAR_SELECT_BIAS; + } - if (ED_view3d_clipping_test(data->vc.rv3d, vec, true) == 0) { - data->dist = distance; - data->closest = eed; - } + if (data->vc.rv3d->rflag & RV3D_CLIPPING) { + float vec[3]; + + interp_v3_v3v3(vec, eed->v1->co, eed->v2->co, fac); + if (ED_view3d_clipping_test(data->vc.rv3d, vec, true)) { + return; } - else { - data->dist = distance; - data->closest = eed; + } + + if (dist_test_bias < data->hit.dist_bias) { + float screen_co_mid[2]; + + data->hit.dist_bias = dist_test_bias; + data->hit.dist = dist_test; + data->hit.index = index; + data->hit.edge = eed; + + mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b); + data->hit.dist_center = len_manhattan_v2v2(data->mval_fl, screen_co_mid); + } + + if (data->use_cycle) { + if ((data->hit_cycle.edge == NULL) && + (index > data->cycle_index_prev) && + (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN)) + { + float screen_co_mid[2]; + + data->hit_cycle.dist_bias = dist_test_bias; + data->hit_cycle.dist = dist_test; + data->hit_cycle.index = index; + data->hit_cycle.edge = eed; + + mid_v2_v2v2(screen_co_mid, screen_co_a, screen_co_b); + data->hit_cycle.dist_center = len_manhattan_v2v2(data->mval_fl, screen_co_mid); } } } -BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist) + +BMEdge *EDBM_edge_find_nearest_ex( + ViewContext *vc, float *r_dist, + float *r_dist_center, + const bool use_select_bias, const bool use_cycle, + BMEdge **r_eed_zbuf) { + BMesh *bm = vc->em->bm; - if (vc->v3d->drawtype > OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) { - float distance; + if (V3D_IS_ZBUF(vc->v3d)) { + const int dist_px = ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist); + float dist_test = 0.0f; unsigned int index; BMEdge *eed; - view3d_validate_backbuf(vc); - - index = view3d_sample_backbuf_rect(vc, vc->mval, 50, bm_solidoffs, bm_wireoffs, &distance, 0, NULL, NULL); - eed = index ? BM_edge_at_index_find(vc->em->bm, index - 1) : NULL; - - if (eed && distance < *r_dist) { - *r_dist = distance; - return eed; + ED_view3d_backbuf_validate(vc); + + index = ED_view3d_backbuf_sample_rect(vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &dist_test); + eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL; + + if (r_eed_zbuf) { + *r_eed_zbuf = eed; } - else { - return NULL; + + /* exception for faces (verts don't need this) */ + if (r_dist_center && eed) { + struct NearestEdgeUserData_ZBuf data; + + data.mval_fl[0] = vc->mval[0]; + data.mval_fl[1] = vc->mval[1]; + data.dist = FLT_MAX; + data.edge_test = eed; + + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + + mesh_foreachScreenEdge(vc, find_nearest_edge_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + + *r_dist_center = data.dist; } + /* end exception */ + + if (eed) { + if (dist_test < *r_dist) { + *r_dist = dist_test; + return eed; + } + } + return NULL; } else { - struct { ViewContext vc; float mval_fl[2]; float dist; BMEdge *closest; } data; + struct NearestEdgeUserData data = {{0}}; + const struct NearestEdgeUserData_Hit *hit; + /* interpolate along the edge before doing a clipping plane test */ + const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT & ~V3D_PROJ_TEST_CLIP_BB; + + static int prev_select_index = 0; + static const BMEdge *prev_select_elem = NULL; + + if ((use_cycle == false) || + (prev_select_elem && (prev_select_elem != BM_edge_at_index_find_or_table(bm, prev_select_index)))) + { + prev_select_index = 0; + prev_select_elem = NULL; + } data.vc = *vc; data.mval_fl[0] = vc->mval[0]; data.mval_fl[1] = vc->mval[1]; - data.dist = *r_dist; - data.closest = NULL; + data.use_select_bias = use_select_bias; + data.use_cycle = use_cycle; + data.hit.dist = data.hit_cycle.dist = \ + data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist; + data.cycle_index_prev = prev_select_index; + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); + mesh_foreachScreenEdge(vc, find_nearest_edge__doClosest, &data, clip_flag); + + hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit; + *r_dist = hit->dist; + if (r_dist_center) { + *r_dist_center = hit->dist_center; + } - mesh_foreachScreenEdge(vc, findnearestedge__doClosest, &data, V3D_PROJ_TEST_CLIP_WIN); + prev_select_elem = hit->edge; + prev_select_index = hit->index; - *r_dist = data.dist; - return data.closest; + return hit->edge; } } -static void findnearestface__getDistance(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index)) +BMEdge *EDBM_edge_find_nearest( + ViewContext *vc, float *r_dist) { - struct { float mval_fl[2]; float dist; BMFace *toFace; } *data = userData; + return EDBM_edge_find_nearest_ex(vc, r_dist, false, false, false, NULL); +} + +/* find the distance to the face we already have */ +struct NearestFaceUserData_ZBuf { + float mval_fl[2]; + float dist; + const BMFace *face_test; +}; - if (efa == data->toFace) { +static void find_nearest_face_center__doZBuf(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index)) +{ + struct NearestFaceUserData_ZBuf *data = userData; + + if (efa == data->face_test) { const float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co); if (dist_test < data->dist) { @@ -545,96 +721,152 @@ static void findnearestface__getDistance(void *userData, BMFace *efa, const floa } } } + + +struct NearestFaceUserData_Hit { + float dist; + float dist_bias; + int index; + BMFace *face; +}; + +struct NearestFaceUserData { + float mval_fl[2]; + bool use_select_bias; + bool use_cycle; + int cycle_index_prev; + + struct NearestFaceUserData_Hit hit; + struct NearestFaceUserData_Hit hit_cycle; +}; + static void findnearestface__doClosest(void *userData, BMFace *efa, const float screen_co[2], int index) { - struct { float mval_fl[2], pass; float dist, lastIndex, closestIndex; BMFace *closest; } *data = userData; + struct NearestFaceUserData *data = userData; + float dist_test, dist_test_bias; - if (data->pass == 0) { - if (index <= data->lastIndex) - return; - } - else { - if (index > data->lastIndex) - return; + dist_test = dist_test_bias = len_manhattan_v2v2(data->mval_fl, screen_co); + + if (data->use_select_bias && BM_elem_flag_test(efa, BM_ELEM_SELECT)) { + dist_test_bias += FIND_NEAR_SELECT_BIAS; } - if (data->dist > 3) { - const float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co); + if (dist_test_bias < data->hit.dist_bias) { + data->hit.dist_bias = dist_test_bias; + data->hit.dist = dist_test; + data->hit.index = index; + data->hit.face = efa; + } - if (dist_test < data->dist) { - data->dist = dist_test; - data->closest = efa; - data->closestIndex = index; + if (data->use_cycle) { + if ((data->hit_cycle.face == NULL) && + (index > data->cycle_index_prev) && + (dist_test_bias < FIND_NEAR_CYCLE_THRESHOLD_MIN)) + { + data->hit_cycle.dist_bias = dist_test_bias; + data->hit_cycle.dist = dist_test; + data->hit_cycle.index = index; + data->hit_cycle.face = efa; } } } -BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) + +BMFace *EDBM_face_find_nearest_ex( + ViewContext *vc, float *r_dist, + float *r_dist_center, + const bool use_select_bias, const bool use_cycle, + BMFace **r_efa_zbuf) { + BMesh *bm = vc->em->bm; - if (vc->v3d->drawtype > OB_WIRE && (vc->v3d->flag & V3D_ZBUF_SELECT)) { + if (V3D_IS_ZBUF(vc->v3d)) { + float dist_test = 0.0f; unsigned int index; BMFace *efa; - view3d_validate_backbuf(vc); + ED_view3d_backbuf_validate(vc); - index = view3d_sample_backbuf(vc, vc->mval[0], vc->mval[1]); - efa = index ? BM_face_at_index_find(vc->em->bm, index - 1) : NULL; + index = ED_view3d_backbuf_sample(vc, vc->mval[0], vc->mval[1]); + efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL; - if (efa) { - struct { float mval_fl[2]; float dist; BMFace *toFace; } data; + if (r_efa_zbuf) { + *r_efa_zbuf = efa; + } + + /* exception for faces (verts don't need this) */ + if (r_dist_center && efa) { + struct NearestFaceUserData_ZBuf data; data.mval_fl[0] = vc->mval[0]; data.mval_fl[1] = vc->mval[1]; data.dist = FLT_MAX; - data.toFace = efa; + data.face_test = efa; ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenFace(vc, findnearestface__getDistance, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + mesh_foreachScreenFace(vc, find_nearest_face_center__doZBuf, &data, V3D_PROJ_TEST_CLIP_DEFAULT); - if ((vc->em->selectmode == SCE_SELECT_FACE) || (data.dist < *r_dist)) { /* only faces, no dist check */ - *r_dist = data.dist; + *r_dist_center = data.dist; + } + /* end exception */ + + if (efa) { + if (dist_test < *r_dist) { + *r_dist = dist_test; return efa; } } - return NULL; } else { - struct { float mval_fl[2], pass; float dist, lastIndex, closestIndex; BMFace *closest; } data; - static int lastSelectedIndex = 0; - static BMFace *lastSelected = NULL; + struct NearestFaceUserData data = {{0}}; + const struct NearestFaceUserData_Hit *hit; + const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT; - if (lastSelected && BM_face_at_index_find(vc->em->bm, lastSelectedIndex) != lastSelected) { - lastSelectedIndex = 0; - lastSelected = NULL; + static int prev_select_index = 0; + static const BMFace *prev_select_elem = NULL; + + if ((use_cycle == false) || + (prev_select_elem && (prev_select_elem != BM_face_at_index_find_or_table(bm, prev_select_index)))) + { + prev_select_index = 0; + prev_select_elem = NULL; } - data.lastIndex = lastSelectedIndex; data.mval_fl[0] = vc->mval[0]; data.mval_fl[1] = vc->mval[1]; - data.dist = *r_dist; - data.closest = NULL; - data.closestIndex = 0; + data.use_select_bias = use_select_bias; + data.use_cycle = use_cycle; + data.hit.dist = data.hit_cycle.dist = \ + data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist; + data.cycle_index_prev = prev_select_index; - data.pass = 0; ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); - mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag); - if (data.dist > 3.0f) { - data.pass = 1; - mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT); + hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit; + *r_dist = hit->dist; + if (r_dist_center) { + *r_dist_center = hit->dist; } - *r_dist = data.dist; - lastSelected = data.closest; - lastSelectedIndex = data.closestIndex; + prev_select_elem = hit->face; + prev_select_index = hit->index; - return data.closest; + return hit->face; } } +BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) +{ + return EDBM_face_find_nearest_ex(vc, r_dist, NULL, false, false, NULL); +} + +#undef FIND_NEAR_SELECT_BIAS +#undef FIND_NEAR_CYCLE_THRESHOLD_MIN + + /* best distance based on screen coords. * use em->selectmode to define how to use * selected vertices and edges get disadvantage @@ -643,35 +875,78 @@ BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist) static int unified_findnearest(ViewContext *vc, BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa) { BMEditMesh *em = vc->em; - float dist = ED_view3d_select_dist_px(); - - *r_eve = NULL; - *r_eed = NULL; - *r_efa = NULL; + static short mval_prev[2] = {-1, -1}; + /* only cycle while the mouse remains still */ + const bool use_cycle = ((mval_prev[0] == vc->mval[0]) && (mval_prev[1] == vc->mval[1])); + const float dist_init = ED_view3d_select_dist_px(); + /* since edges select lines, we give dots advantage of ~20 pix */ + const float dist_margin = (dist_init / 2); + float dist = dist_init; + BMFace *efa_zbuf = NULL; + BMEdge *eed_zbuf = NULL; + BMVert *eve = NULL; + BMEdge *eed = NULL; + BMFace *efa = NULL; + + /* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */ - view3d_validate_backbuf(vc); - - if (em->selectmode & SCE_SELECT_VERTEX) - *r_eve = EDBM_vert_find_nearest(vc, &dist, BM_ELEM_SELECT, 0); - if (em->selectmode & SCE_SELECT_FACE) - *r_efa = EDBM_face_find_nearest(vc, &dist); + ED_view3d_backbuf_validate(vc); + + if ((dist > 0.0f) && em->selectmode & SCE_SELECT_FACE) { + float dist_center = 0.0f; + float *dist_center_p = (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_VERTEX)) ? &dist_center : NULL; + efa = EDBM_face_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf); + if (efa && dist_center_p) { + dist = min_ff(dist_margin, dist_center); + } + } + + if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) { + float dist_center = 0.0f; + float *dist_center_p = (em->selectmode & SCE_SELECT_VERTEX) ? &dist_center : NULL; + eed = EDBM_edge_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf); + if (eed && dist_center_p) { + dist = min_ff(dist_margin, dist_center); + } + } - dist -= 20; /* since edges select lines, we give dots advantage of 20 pix */ - if (em->selectmode & SCE_SELECT_EDGE) - *r_eed = EDBM_edge_find_nearest(vc, &dist); + if ((dist > 0.0f) && em->selectmode & SCE_SELECT_VERTEX) { + eve = EDBM_vert_find_nearest_ex(vc, &dist, true, use_cycle); + } /* return only one of 3 pointers, for frontbuffer redraws */ - if (*r_eed) { - *r_efa = NULL; *r_eve = NULL; + if (eve) { + efa = NULL; eed = NULL; } - else if (*r_efa) { - *r_eve = NULL; + else if (eed) { + efa = NULL; } - - return (*r_eve || *r_eed || *r_efa); + + /* there may be a face under the cursor, who's center if too far away + * use this if all else fails, it makes sense to select this */ + if ((eve || eed || efa) == 0) { + if (eed_zbuf) { + eed = eed_zbuf; + } + else if (efa_zbuf) { + efa = efa_zbuf; + } + } + + mval_prev[0] = vc->mval[0]; + mval_prev[1] = vc->mval[1]; + + *r_eve = eve; + *r_eed = eed; + *r_efa = efa; + + return (eve || eed || efa); } +/** \} */ + + /* **************** SIMILAR "group" SELECTS. FACE, EDGE AND VERTEX ************** */ static EnumPropertyItem prop_similar_compare_types[] = { {SIM_CMP_EQ, "EQUAL", 0, "Equal", ""}, @@ -1286,7 +1561,7 @@ static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool de em = vc.em; /* no afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad */ - view3d_validate_backbuf(&vc); + ED_view3d_backbuf_validate(&vc); eed = EDBM_edge_find_nearest(&vc, &dist); if (eed == NULL) { diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 93ebbbcf620..54acf4abf7c 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -96,7 +96,7 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op) } BM_mesh_esubdivide(em->bm, BM_ELEM_SELECT, - smooth, SUBD_FALLOFF_ROOT, false, + smooth, SUBD_FALLOFF_INVSQUARE, false, fractal, along_normal, cuts, SUBDIV_SELECT_ORIG, RNA_enum_get(op->ptr, "quadcorner"), @@ -492,7 +492,7 @@ static int edbm_collapse_edge_exec(bContext *C, wmOperator *op) Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(obedit); - if (!EDBM_op_callf(em, op, "collapse edges=%he", BM_ELEM_SELECT)) + if (!EDBM_op_callf(em, op, "collapse edges=%he uvs=%b", BM_ELEM_SELECT, true)) return OPERATOR_CANCELLED; EDBM_update_generic(em, true, true); @@ -2049,9 +2049,7 @@ static int edbm_merge_exec(bContext *C, wmOperator *op) ok = merge_firstlast(em, true, uvs, op); break; case 5: - ok = true; - if (!EDBM_op_callf(em, op, "collapse edges=%he", BM_ELEM_SELECT)) - ok = false; + ok = EDBM_op_callf(em, op, "collapse edges=%he uvs=%b", BM_ELEM_SELECT, uvs); break; default: BLI_assert(0); diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index 86991d7dfeb..f497cd7a1aa 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -748,7 +748,7 @@ static int mesh_customdata_clear_exec__internal(bContext *C, } /* Clear Mask */ -static int mesh_customdata_clear_mask_poll(bContext *C) +static int mesh_customdata_mask_clear_poll(bContext *C) { Object *ob = ED_object_context(C); if (ob && ob->type == OB_MESH) { @@ -772,7 +772,7 @@ static int mesh_customdata_clear_mask_poll(bContext *C) } return false; } -static int mesh_customdata_clear_mask_exec(bContext *C, wmOperator *UNUSED(op)) +static int mesh_customdata_mask_clear_exec(bContext *C, wmOperator *UNUSED(op)) { int ret_a = mesh_customdata_clear_exec__internal(C, BM_VERT, CD_PAINT_MASK); int ret_b = mesh_customdata_clear_exec__internal(C, BM_LOOP, CD_GRID_PAINT_MASK); @@ -787,24 +787,24 @@ static int mesh_customdata_clear_mask_exec(bContext *C, wmOperator *UNUSED(op)) } } -void MESH_OT_customdata_clear_mask(wmOperatorType *ot) +void MESH_OT_customdata_mask_clear(wmOperatorType *ot) { /* identifiers */ ot->name = "Clear Sculpt-Mask Data"; - ot->idname = "MESH_OT_customdata_clear_mask"; + ot->idname = "MESH_OT_customdata_mask_clear"; ot->description = "Clear vertex sculpt masking data from the mesh"; /* api callbacks */ - ot->exec = mesh_customdata_clear_mask_exec; - ot->poll = mesh_customdata_clear_mask_poll; + ot->exec = mesh_customdata_mask_clear_exec; + ot->poll = mesh_customdata_mask_clear_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } /* Clear Skin */ -static int mesh_customdata_clear_skin_poll(bContext *C) +static bool mesh_customdata_skin_has(bContext *C) { Object *ob = ED_object_context(C); @@ -819,21 +819,60 @@ static int mesh_customdata_clear_skin_poll(bContext *C) } return false; } -static int mesh_customdata_clear_skin_exec(bContext *C, wmOperator *UNUSED(op)) + +static int mesh_customdata_skin_add_poll(bContext *C) +{ + return !mesh_customdata_skin_has(C); +} + +static int mesh_customdata_skin_add_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *ob = ED_object_context(C); + Mesh *me = ob->data; + + BKE_mesh_ensure_skin_customdata(me); + + DAG_id_tag_update(&me->id, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); + + return OPERATOR_FINISHED; +} + +void MESH_OT_customdata_skin_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Skin Data"; + ot->idname = "MESH_OT_customdata_skin_add"; + ot->description = "Add a vertex skin layer"; + + /* api callbacks */ + ot->exec = mesh_customdata_skin_add_exec; + ot->poll = mesh_customdata_skin_add_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int mesh_customdata_skin_clear_poll(bContext *C) +{ + return mesh_customdata_skin_has(C); +} + +static int mesh_customdata_skin_clear_exec(bContext *C, wmOperator *UNUSED(op)) { return mesh_customdata_clear_exec__internal(C, BM_VERT, CD_MVERT_SKIN); } -void MESH_OT_customdata_clear_skin(wmOperatorType *ot) +void MESH_OT_customdata_skin_clear(wmOperatorType *ot) { /* identifiers */ ot->name = "Clear Skin Data"; - ot->idname = "MESH_OT_customdata_clear_skin"; + ot->idname = "MESH_OT_customdata_skin_clear"; ot->description = "Clear vertex skin layer"; /* api callbacks */ - ot->exec = mesh_customdata_clear_skin_exec; - ot->poll = mesh_customdata_clear_skin_poll; + ot->exec = mesh_customdata_skin_clear_exec; + ot->poll = mesh_customdata_skin_clear_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index c7355120a57..9226146bc51 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -232,8 +232,9 @@ void MESH_OT_uv_texture_remove(struct wmOperatorType *ot); void MESH_OT_vertex_color_add(struct wmOperatorType *ot); void MESH_OT_vertex_color_remove(struct wmOperatorType *ot); /* no create_mask yet */ -void MESH_OT_customdata_clear_mask(struct wmOperatorType *ot); -void MESH_OT_customdata_clear_skin(struct wmOperatorType *ot); +void MESH_OT_customdata_mask_clear(struct wmOperatorType *ot); +void MESH_OT_customdata_skin_add(struct wmOperatorType *ot); +void MESH_OT_customdata_skin_clear(struct wmOperatorType *ot); void MESH_OT_customdata_custom_splitnormals_add(struct wmOperatorType *ot); void MESH_OT_customdata_custom_splitnormals_clear(struct wmOperatorType *ot); void MESH_OT_drop_named_image(struct wmOperatorType *ot); diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c index 440ab14dacd..0d9f6f2a0be 100644 --- a/source/blender/editors/mesh/mesh_navmesh.c +++ b/source/blender/editors/mesh/mesh_navmesh.c @@ -325,7 +325,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, if (createob) { /* create new object */ - obedit = ED_object_add_type(C, OB_MESH, co, rot, false, lay); + obedit = ED_object_add_type(C, OB_MESH, "Navmesh", co, rot, false, lay); } else { obedit = base->object; @@ -429,7 +429,6 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, obedit->gameflag &= ~OB_COLLISION; obedit->gameflag |= OB_NAVMESH; obedit->body_type = OB_BODY_TYPE_NAVMESH; - rename_id((ID *)obedit, "Navmesh"); } BKE_mesh_ensure_navmesh(obedit->data); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 126d1cb0ad9..197df48d688 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -151,8 +151,9 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_uv_texture_remove); WM_operatortype_append(MESH_OT_vertex_color_add); WM_operatortype_append(MESH_OT_vertex_color_remove); - WM_operatortype_append(MESH_OT_customdata_clear_mask); - WM_operatortype_append(MESH_OT_customdata_clear_skin); + WM_operatortype_append(MESH_OT_customdata_mask_clear); + WM_operatortype_append(MESH_OT_customdata_skin_add); + WM_operatortype_append(MESH_OT_customdata_skin_clear); WM_operatortype_append(MESH_OT_customdata_custom_splitnormals_add); WM_operatortype_append(MESH_OT_customdata_custom_splitnormals_clear); WM_operatortype_append(MESH_OT_drop_named_image); @@ -409,7 +410,7 @@ void ED_keymap_mesh(wmKeyConfig *keyconf) /* use KM_CLICK because same key is used for tweaks */ kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_CLICK, KM_CTRL, 0); RNA_boolean_set(kmi->ptr, "rotate_source", true); - kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_PRESS, KM_SHIFT | KM_CTRL, 0); + kmi = WM_keymap_add_item(keymap, "MESH_OT_dupli_extrude_cursor", ACTIONMOUSE, KM_CLICK, KM_SHIFT | KM_CTRL, 0); RNA_boolean_set(kmi->ptr, "rotate_source", false); WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_mesh_delete", XKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index 00d79b22e99..2491685161c 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -1082,11 +1082,11 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], unsigned int * on an edge in the backbuf, we can still select a face */ float dummy_dist; - *index = view3d_sample_backbuf_rect(&vc, mval, size, 1, me->totpoly + 1, &dummy_dist, 0, NULL, NULL); + *index = ED_view3d_backbuf_sample_rect(&vc, mval, size, 1, me->totpoly + 1, &dummy_dist); } else { /* sample only on the exact position */ - *index = view3d_sample_backbuf(&vc, mval[0], mval[1]); + *index = ED_view3d_backbuf_sample(&vc, mval[0], mval[1]); } if ((*index) == 0 || (*index) > (unsigned int)me->totpoly) @@ -1248,11 +1248,11 @@ bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int * on an face in the backbuf, we can still select a vert */ float dummy_dist; - *index = view3d_sample_backbuf_rect(&vc, mval, size, 1, me->totvert + 1, &dummy_dist, 0, NULL, NULL); + *index = ED_view3d_backbuf_sample_rect(&vc, mval, size, 1, me->totvert + 1, &dummy_dist); } else { /* sample only on the exact position */ - *index = view3d_sample_backbuf(&vc, mval[0], mval[1]); + *index = ED_view3d_backbuf_sample(&vc, mval[0], mval[1]); } if ((*index) == 0 || (*index) > (unsigned int)me->totvert) diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 37faa7ba664..27d77f0635e 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -394,8 +394,11 @@ bool ED_object_add_generic_get_opts(bContext *C, wmOperator *op, const char view /* For object add primitive operators. * Do not call undo push in this function (users of this function have to). */ -Object *ED_object_add_type(bContext *C, int type, const float loc[3], const float rot[3], - bool enter_editmode, unsigned int layer) +Object *ED_object_add_type( + bContext *C, + int type, const char *name, + const float loc[3], const float rot[3], + bool enter_editmode, unsigned int layer) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); @@ -406,7 +409,7 @@ Object *ED_object_add_type(bContext *C, int type, const float loc[3], const floa ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO); /* freedata, and undo */ /* deselects all, sets scene->basact */ - ob = BKE_object_add(bmain, scene, type); + ob = BKE_object_add(bmain, scene, type, name); BASACT->lay = ob->lay = layer; /* editor level activate, notifiers */ ED_base_object_activate(C, BASACT); @@ -447,7 +450,7 @@ static int object_add_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; radius = RNA_float_get(op->ptr, "radius"); - ob = ED_object_add_type(C, RNA_enum_get(op->ptr, "type"), loc, rot, enter_editmode, layer); + ob = ED_object_add_type(C, RNA_enum_get(op->ptr, "type"), NULL, loc, rot, enter_editmode, layer); if (ob->type == OB_LATTICE) { /* lattice is a special case! @@ -504,9 +507,9 @@ static int effector_add_exec(bContext *C, wmOperator *op) if (type == PFIELD_GUIDE) { Curve *cu; - ob = ED_object_add_type(C, OB_CURVE, loc, rot, false, layer); + const char *name = CTX_DATA_(BLF_I18NCONTEXT_ID_OBJECT, "CurveGuide"); + ob = ED_object_add_type(C, OB_CURVE, name, loc, rot, false, layer); - rename_id(&ob->id, CTX_DATA_(BLF_I18NCONTEXT_ID_OBJECT, "CurveGuide")); cu = ob->data; cu->flag |= CU_PATH | CU_3D; ED_object_editmode_enter(C, 0); @@ -516,9 +519,9 @@ static int effector_add_exec(bContext *C, wmOperator *op) ED_object_editmode_exit(C, EM_FREEDATA); } else { - ob = ED_object_add_type(C, OB_EMPTY, loc, rot, false, layer); + const char *name = CTX_DATA_(BLF_I18NCONTEXT_ID_OBJECT, "Field"); + ob = ED_object_add_type(C, OB_EMPTY, name, loc, rot, false, layer); BKE_object_obdata_size_init(ob, dia); - rename_id(&ob->id, CTX_DATA_(BLF_I18NCONTEXT_ID_OBJECT, "Field")); if (ELEM(type, PFIELD_WIND, PFIELD_VORTEX)) ob->empty_drawtype = OB_SINGLE_ARROW; } @@ -569,7 +572,7 @@ static int object_camera_add_exec(bContext *C, wmOperator *op) if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL)) return OPERATOR_CANCELLED; - ob = ED_object_add_type(C, OB_CAMERA, loc, rot, false, layer); + ob = ED_object_add_type(C, OB_CAMERA, NULL, loc, rot, false, layer); if (v3d) { if (v3d->camera == NULL) @@ -626,7 +629,7 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; if (obedit == NULL || obedit->type != OB_MBALL) { - obedit = ED_object_add_type(C, OB_MBALL, loc, rot, true, layer); + obedit = ED_object_add_type(C, OB_MBALL, NULL, loc, rot, true, layer); newob = true; } else { @@ -685,7 +688,7 @@ static int object_add_text_exec(bContext *C, wmOperator *op) if (obedit && obedit->type == OB_FONT) return OPERATOR_CANCELLED; - obedit = ED_object_add_type(C, OB_FONT, loc, rot, enter_editmode, layer); + obedit = ED_object_add_type(C, OB_FONT, NULL, loc, rot, enter_editmode, layer); BKE_object_obdata_size_init(obedit, RNA_float_get(op->ptr, "radius")); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit); @@ -729,7 +732,7 @@ static int object_armature_add_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; if ((obedit == NULL) || (obedit->type != OB_ARMATURE)) { - obedit = ED_object_add_type(C, OB_ARMATURE, loc, rot, true, layer); + obedit = ED_object_add_type(C, OB_ARMATURE, NULL, loc, rot, true, layer); ED_object_editmode_enter(C, 0); newob = true; } @@ -786,7 +789,7 @@ static int object_empty_add_exec(bContext *C, wmOperator *op) if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &layer, NULL)) return OPERATOR_CANCELLED; - ob = ED_object_add_type(C, OB_EMPTY, loc, rot, false, layer); + ob = ED_object_add_type(C, OB_EMPTY, NULL, loc, rot, false, layer); BKE_object_empty_draw_type_set(ob, type); BKE_object_obdata_size_init(ob, RNA_float_get(op->ptr, "radius")); @@ -846,7 +849,7 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv if (!ED_object_add_generic_get_opts(C, op, 'Z', NULL, rot, NULL, &layer, NULL)) return OPERATOR_CANCELLED; - ob = ED_object_add_type(C, OB_EMPTY, NULL, rot, false, layer); + ob = ED_object_add_type(C, OB_EMPTY, NULL, NULL, rot, false, layer); /* add under the mouse */ ED_object_location_from_view(C, ob->loc); @@ -916,13 +919,11 @@ static int object_lamp_add_exec(bContext *C, wmOperator *op) if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &layer, NULL)) return OPERATOR_CANCELLED; - ob = ED_object_add_type(C, OB_LAMP, loc, rot, false, layer); + ob = ED_object_add_type(C, OB_LAMP, get_lamp_defname(type), loc, rot, false, layer); BKE_object_obdata_size_init(ob, RNA_float_get(op->ptr, "radius")); la = (Lamp *)ob->data; la->type = type; - rename_id(&ob->id, get_lamp_defname(type)); - rename_id(&la->id, get_lamp_defname(type)); if (BKE_scene_use_new_shading_nodes(scene)) { ED_node_shader_default(C, &la->id); @@ -988,8 +989,7 @@ static int group_instance_add_exec(bContext *C, wmOperator *op) if (group) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Object *ob = ED_object_add_type(C, OB_EMPTY, loc, rot, false, layer); - rename_id(&ob->id, group->id.name + 2); + Object *ob = ED_object_add_type(C, OB_EMPTY, group->id.name + 2, loc, rot, false, layer); ob->dup_group = group; ob->transflag |= OB_DUPLIGROUP; id_lib_extern(&group->id); @@ -1044,7 +1044,7 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op) if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, &layer, NULL)) return OPERATOR_CANCELLED; - ob = ED_object_add_type(C, OB_SPEAKER, loc, rot, false, layer); + ob = ED_object_add_type(C, OB_SPEAKER, NULL, loc, rot, false, layer); /* to make it easier to start using this immediately in NLA, a default sound clip is created * ready to be moved around to retime the sound and/or make new sound clips diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index 578335a385b..b382fbafcfd 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -775,11 +775,7 @@ static int bake( copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat); invert_m4_m4(highpoly[i].imat, highpoly[i].obmat); - /* rotation */ - normalize_m4_m4(highpoly[i].rotmat, highpoly[i].imat); - zero_v3(highpoly[i].rotmat[3]); - if (is_negative_m4(highpoly[i].rotmat)) - negate_mat3_m4(highpoly[i].rotmat); + highpoly[i].is_flip_object = is_negative_m4(highpoly[i].ob->obmat); i++; } diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index d459dd417c7..f214741467f 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -1662,7 +1662,7 @@ static short get_new_constraint_target(bContext *C, int con_type, Object **tar_o Object *obt; /* add new target object */ - obt = BKE_object_add(bmain, scene, OB_EMPTY); + obt = BKE_object_add(bmain, scene, OB_EMPTY, NULL); /* set layers OK */ newbase = BASACT; diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c index b39e8470a95..a7802b6a411 100644 --- a/source/blender/editors/object/object_data_transfer.c +++ b/source/blender/editors/object/object_data_transfer.c @@ -325,7 +325,7 @@ static bool data_transfer_exec_is_object_valid( static int data_transfer_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); - Object *ob_src = CTX_data_active_object(C); + Object *ob_src = ED_object_active_context(C); ListBase ctx_objects; CollectionPointerLink *ctx_ob_dst; @@ -419,7 +419,7 @@ static int data_transfer_exec(bContext *C, wmOperator *op) /* Note this context poll is only really partial, it cannot check for all possible invalid cases. */ static int data_transfer_poll(bContext *C) { - Object *ob = ED_object_context(C); + Object *ob = ED_object_active_context(C); ID *data = (ob) ? ob->data : NULL; return (ob && ob->type == OB_MESH && data); } diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 76e84e67972..1769b3a8527 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -1771,6 +1771,77 @@ void OBJECT_OT_game_property_remove(wmOperatorType *ot) RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Property index to remove ", 0, INT_MAX); } +#define GAME_PROPERTY_MOVE_UP 1 +#define GAME_PROPERTY_MOVE_DOWN -1 + +static int game_property_move(bContext *C, wmOperator *op) +{ + Object *ob = CTX_data_active_object(C); + bProperty *prop; + bProperty *otherprop = NULL; + const int index = RNA_int_get(op->ptr, "index"); + const int dir = RNA_int_get(op->ptr, "direction"); + + if (ob == NULL) + return OPERATOR_CANCELLED; + + prop = BLI_findlink(&ob->prop, index); + /* invalid index */ + if (prop == NULL) + return OPERATOR_CANCELLED; + + if (dir == GAME_PROPERTY_MOVE_UP) { + otherprop = prop->prev; + } + else if (dir == GAME_PROPERTY_MOVE_DOWN) { + otherprop = prop->next; + } + else { + BLI_assert(0); + } + + if (prop && otherprop) { + BLI_listbase_swaplinks(&ob->prop, prop, otherprop); + + WM_event_add_notifier(C, NC_LOGIC, NULL); + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } +} + +void OBJECT_OT_game_property_move(wmOperatorType *ot) +{ + static EnumPropertyItem direction_property_move[] = { + {GAME_PROPERTY_MOVE_UP, "UP", 0, "Up", ""}, + {GAME_PROPERTY_MOVE_DOWN, "DOWN", 0, "Down", ""}, + {0, NULL, 0, NULL, NULL} + }; + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Move Game Property"; + ot->description = "Move game property"; + ot->idname = "OBJECT_OT_game_property_move"; + + /* api callbacks */ + ot->exec = game_property_move; + ot->poll = ED_operator_object_active_editable; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + prop = RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Property index to move", 0, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN); + RNA_def_enum(ot->srna, "direction", direction_property_move, 0, "Direction", + "Direction for moving the property"); +} + +#undef GAME_PROPERTY_MOVE_UP +#undef GAME_PROPERTY_MOVE_DOWN + #define COPY_PROPERTIES_REPLACE 1 #define COPY_PROPERTIES_MERGE 2 #define COPY_PROPERTIES_COPY 3 diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index 1d764ced524..8797b75a801 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -448,11 +448,12 @@ static Object *add_hook_object_new(Main *bmain, Scene *scene, Object *obedit) Base *base, *basedit; Object *ob; - ob = BKE_object_add(bmain, scene, OB_EMPTY); + ob = BKE_object_add(bmain, scene, OB_EMPTY, NULL); basedit = BKE_scene_base_find(scene, obedit); - base = BKE_scene_base_find(scene, ob); + base = scene->basact; base->lay = ob->lay = obedit->lay; + BLI_assert(scene->basact->object == ob); /* icky, BKE_object_add sets new base as active. * so set it back to the original edit object */ diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index d535457fc5b..2801d2711e7 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -94,6 +94,7 @@ void OBJECT_OT_game_property_new(struct wmOperatorType *ot); void OBJECT_OT_game_property_remove(struct wmOperatorType *ot); void OBJECT_OT_game_property_copy(struct wmOperatorType *ot); void OBJECT_OT_game_property_clear(struct wmOperatorType *ot); +void OBJECT_OT_game_property_move(struct wmOperatorType *ot); void OBJECT_OT_logic_bricks_copy(struct wmOperatorType *ot); void OBJECT_OT_game_physics_copy(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index ac5ec1976ab..1cee54c33fa 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -459,7 +459,7 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene * if (totvert == 0) return 0; /* add new mesh */ - obn = BKE_object_add(bmain, scene, OB_MESH); + obn = BKE_object_add(bmain, scene, OB_MESH, NULL); me = obn->data; me->totvert = totvert; @@ -1704,7 +1704,7 @@ static Object *modifier_skin_armature_create(Main *bmain, Scene *scene, Object * NULL, me->totvert); - arm_ob = BKE_object_add(bmain, scene, OB_ARMATURE); + arm_ob = BKE_object_add(bmain, scene, OB_ARMATURE, NULL); BKE_object_transform_copy(arm_ob, skin_ob); arm = arm_ob->data; arm->layer = 1; diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 422f0c12e51..00c6a41423a 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -206,6 +206,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_game_property_remove); WM_operatortype_append(OBJECT_OT_game_property_copy); WM_operatortype_append(OBJECT_OT_game_property_clear); + WM_operatortype_append(OBJECT_OT_game_property_move); WM_operatortype_append(OBJECT_OT_logic_bricks_copy); WM_operatortype_append(OBJECT_OT_game_physics_copy); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 2d981594524..19648c291f7 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -342,12 +342,10 @@ static int make_proxy_exec(bContext *C, wmOperator *op) Base *newbase, *oldbase = BASACT; char name[MAX_ID_NAME + 4]; - /* Add new object for the proxy */ - newob = BKE_object_add(bmain, scene, OB_EMPTY); - BLI_snprintf(name, sizeof(name), "%s_proxy", ((ID *)(gob ? gob : ob))->name + 2); - rename_id(&newob->id, name); + /* Add new object for the proxy */ + newob = BKE_object_add(bmain, scene, OB_EMPTY, name); /* set layers OK */ newbase = BASACT; /* BKE_object_add sets active... */ diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 92fe5ded4dd..340b662c0ef 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -939,8 +939,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) /* convert the offset to parent space */ BKE_object_to_mat4(ob, obmat); - copy_v3_v3(centn, cent); - mul_mat3_m4_v3(obmat, centn); /* omit translation part */ + mul_v3_mat3_m4v3(centn, obmat, cent); /* omit translation part */ add_v3_v3(ob->loc, centn); @@ -970,8 +969,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) ob_other->flag |= OB_DONE; DAG_id_tag_update(&ob_other->id, OB_RECALC_OB | OB_RECALC_DATA); - copy_v3_v3(centn, cent); - mul_mat3_m4_v3(ob_other->obmat, centn); /* omit translation part */ + mul_v3_mat3_m4v3(centn, ob_other->obmat, cent); /* omit translation part */ add_v3_v3(ob_other->loc, centn); BKE_object_where_is_calc(scene, ob_other); diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index f885cbbb24f..960b29ae38e 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -2062,7 +2062,7 @@ void ED_vgroup_mirror(Object *ob, /* object mode / weight paint */ MVert *mv, *mv_mirr; int vidx, vidx_mirr; - const int use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; + const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; if (me->dvert == NULL) { goto cleanup; diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index e714dfc464c..5349377f6ff 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -400,12 +400,12 @@ static void PE_set_view3d_data(bContext *C, PEData *data) /* note, the object argument means the modelview matrix does not account for the objects matrix, use viewmat rather than (obmat * viewmat) */ view3d_get_transformation(data->vc.ar, data->vc.rv3d, NULL, &data->mats); - if ((data->vc.v3d->drawtype>OB_WIRE) && (data->vc.v3d->flag & V3D_ZBUF_SELECT)) { + if (V3D_IS_ZBUF(data->vc.v3d)) { if (data->vc.v3d->flag & V3D_INVALID_BACKBUF) { /* needed or else the draw matrix can be incorrect */ view3d_operator_needs_opengl(C); - view3d_validate_backbuf(&data->vc); + ED_view3d_backbuf_validate(&data->vc); /* we may need to force an update here by setting the rv3d as dirty * for now it seems ok, but take care!: * rv3d->depths->dirty = 1; */ @@ -443,8 +443,8 @@ static bool key_test_depth(PEData *data, const float co[3], const int screen_co[ float depth; /* nothing to do */ - if ((v3d->drawtype<=OB_WIRE) || (v3d->flag & V3D_ZBUF_SELECT)==0) - return 1; + if (!V3D_IS_ZBUF(v3d)) + return true; /* used to calculate here but all callers have the screen_co already, so pass as arg */ #if 0 diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c index 9b4f128ef86..c8b944f7d2a 100644 --- a/source/blender/editors/physics/rigidbody_object.c +++ b/source/blender/editors/physics/rigidbody_object.c @@ -348,6 +348,7 @@ static int rigidbody_objects_shape_change_exec(bContext *C, wmOperator *op) if (changed) { /* send updates */ WM_event_add_notifier(C, NC_OBJECT | ND_POINTCACHE, NULL); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* done */ return OPERATOR_FINISHED; diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h index 5c6744b0248..54429f9f066 100644 --- a/source/blender/editors/render/render_intern.h +++ b/source/blender/editors/render/render_intern.h @@ -44,6 +44,7 @@ void OBJECT_OT_material_slot_assign(struct wmOperatorType *ot); void OBJECT_OT_material_slot_select(struct wmOperatorType *ot); void OBJECT_OT_material_slot_deselect(struct wmOperatorType *ot); void OBJECT_OT_material_slot_copy(struct wmOperatorType *ot); +void OBJECT_OT_material_slot_move(struct wmOperatorType *ot); void MATERIAL_OT_new(struct wmOperatorType *ot); void TEXTURE_OT_new(struct wmOperatorType *ot); diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 2f279122ae4..2ba1e615a9e 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -189,11 +189,15 @@ static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibu */ /* TODO(sergey): Need to check has_combined here? */ if (iuser->passtype == SCE_PASS_COMBINED) { + RenderView *rv; size_t view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname); + rv = RE_RenderViewGetById(rr, view_id); + /* find current float rect for display, first case is after composite... still weak */ - rectf = RE_RenderViewGetRectf(rr, view_id); - if (rectf == NULL) { - if (RE_RenderViewGetRect32(rr, view_id)) { + if (rv->rectf) + rectf = rv->rectf; + else { + if (rv->rect32) { /* special case, currently only happens with sequencer rendering, * which updates the whole frame, so we can only mark display buffer * as invalid here (sergey) diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index ded2489e1e5..7fbdf9dc66b 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -248,6 +248,7 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr) Object *camera = NULL; ImBuf *ibuf; float winmat[4][4]; + float *rectf = RE_RenderViewGetById(rr, oglrender->view_id)->rectf; int sizex = oglrender->sizex; int sizey = oglrender->sizey; const short view_context = (v3d != NULL); @@ -271,7 +272,6 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr) ibuf = BKE_sequencer_give_ibuf(&context, CFRA, chanshown); if (ibuf) { - float *rectf; ImBuf *linear_ibuf; BLI_assert((oglrender->sizex == ibuf->x) && (oglrender->sizey == ibuf->y)); @@ -292,7 +292,6 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr) BKE_sequencer_imbuf_from_sequencer_space(scene, linear_ibuf); } - rectf = RE_RenderViewGetRectf(rr, oglrender->view_id); memcpy(rectf, linear_ibuf->rect_float, sizeof(float) * 4 * oglrender->sizex * oglrender->sizey); IMB_freeImBuf(linear_ibuf); @@ -317,10 +316,12 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr) gp_rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect"); GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, gp_rect); + BLI_assert(rectf != NULL); + for (i = 0; i < sizex * sizey * 4; i += 4) { float col_src[4]; rgba_uchar_to_float(col_src, &gp_rect[i]); - blend_color_mix_float(&rr->rectf[i], &rr->rectf[i], col_src); + blend_color_mix_float(&rectf[i], &rectf[i], col_src); } GPU_offscreen_unbind(oglrender->ofs, true); @@ -338,7 +339,9 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr) /* render 3d view */ if (rv3d->persp == RV3D_CAMOB && v3d->camera) { - /*int is_ortho = scene->r.mode & R_ORTHO;*/ +#if 0 + const bool is_ortho = (scene->r.mode & R_ORTHO) != 0; +#endif camera = BKE_camera_multiview_render(oglrender->scene, v3d->camera, viewname); RE_GetCameraWindow(oglrender->re, camera, scene->r.cfra, winmat); if (camera->type == OB_CAMERA) { @@ -443,8 +446,8 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr) if (rect) { int profile_to; - float *rectf = RE_RenderViewGetRectf(rr, oglrender->view_id); - + float *rectf = RE_RenderViewGetById(rr, oglrender->view_id)->rectf; + if (BKE_scene_check_color_management_enabled(scene)) profile_to = IB_PROFILE_LINEAR_RGB; else @@ -475,12 +478,14 @@ static void screen_opengl_render_write(OGLRender *oglrender) rr = RE_AcquireResultRead(oglrender->re); + BKE_render_result_stamp_info(scene, camera, rr); + BKE_image_path_from_imformat( name, scene->r.pic, oglrender->bmain->name, scene->r.cfra, &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, false, NULL); /* write images as individual images or stereo */ - ok = RE_WriteRenderViewsImage(oglrender->reports, rr, scene, camera, false, name); + ok = RE_WriteRenderViewsImage(oglrender->reports, rr, scene, false, name); RE_ReleaseResultImage(oglrender->re); @@ -802,7 +807,7 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op) } } else { - ok = RE_WriteRenderViewsImage(op->reports, rr, scene, scene->camera, true, name); + ok = RE_WriteRenderViewsImage(op->reports, rr, scene, true, name); if (ok) { printf("Saved: %s", name); BKE_reportf(op->reports, RPT_INFO, "Saved file: %s", name); diff --git a/source/blender/editors/render/render_ops.c b/source/blender/editors/render/render_ops.c index 6aaad98f946..f98083f7e74 100644 --- a/source/blender/editors/render/render_ops.c +++ b/source/blender/editors/render/render_ops.c @@ -47,6 +47,7 @@ void ED_operatortypes_render(void) WM_operatortype_append(OBJECT_OT_material_slot_select); WM_operatortype_append(OBJECT_OT_material_slot_deselect); WM_operatortype_append(OBJECT_OT_material_slot_copy); + WM_operatortype_append(OBJECT_OT_material_slot_move); WM_operatortype_append(MATERIAL_OT_new); WM_operatortype_append(TEXTURE_OT_new); diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index e6fbfda3067..65d4c2301a9 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -525,6 +525,7 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect, rcti *newrect) { Render *re; + RenderView *rv; RenderResult rres; char name[32]; int offx = 0; @@ -549,10 +550,15 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect, /* test if something rendered ok */ re = RE_GetRender(name); + if (re == NULL) + return false; + + RE_AcquireResultImageViews(re, &rres); + /* material preview only needs monoscopy (view 0) */ - RE_AcquireResultImage(re, &rres, 0); + rv = RE_RenderViewGetById(&rres, 0); - if (rres.rectf) { + if (rv->rectf) { if (ABS(rres.rectx - newx) < 2 && ABS(rres.recty - newy) < 2) { @@ -577,7 +583,7 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect, } } - RE_ReleaseResultImage(re); + RE_ReleaseResultImageViews(re, &rres); return ok; } diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 3de21536148..3b8b874a462 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -41,8 +41,9 @@ #include "DNA_space_types.h" #include "DNA_world_types.h" -#include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLI_listbase.h" +#include "BLI_math_vector.h" #include "BLF_translation.h" @@ -202,7 +203,7 @@ static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op)) if (nurbs) { for (nu = nurbs->first; nu; nu = nu->next) if (isNurbsel(nu)) - nu->mat_nr = nu->charidx = ob->actcol - 1; + nu->mat_nr = ob->actcol - 1; } } else if (ob->type == OB_FONT) { @@ -381,6 +382,74 @@ void OBJECT_OT_material_slot_copy(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; } +static int material_slot_move_exec(bContext *C, wmOperator *op) +{ + Object *ob = ED_object_context(C); + + unsigned int *slot_remap; + int index_pair[2]; + + int dir = RNA_enum_get(op->ptr, "direction"); + + if (!ob || ob->totcol < 2) { + return OPERATOR_CANCELLED; + } + + /* up */ + if (dir == 1 && ob->actcol > 1) { + index_pair[0] = ob->actcol - 2; + index_pair[1] = ob->actcol - 1; + ob->actcol--; + } + /* down */ + else if (dir == -1 && ob->actcol < ob->totcol) { + index_pair[0] = ob->actcol - 1; + index_pair[1] = ob->actcol - 0; + ob->actcol++; + } + else { + return OPERATOR_CANCELLED; + } + + slot_remap = MEM_mallocN(sizeof(unsigned int) * ob->totcol, __func__); + + range_vn_u(slot_remap, ob->totcol, 0); + + slot_remap[index_pair[0]] = index_pair[1]; + slot_remap[index_pair[1]] = index_pair[0]; + + BKE_material_remap_object(ob, slot_remap); + + MEM_freeN(slot_remap); + + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW | ND_DATA, ob); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_material_slot_move(wmOperatorType *ot) +{ + static EnumPropertyItem material_slot_move[] = { + {1, "UP", 0, "Up", ""}, + {-1, "DOWN", 0, "Down", ""}, + {0, NULL, 0, NULL, NULL} + }; + + /* identifiers */ + ot->name = "Move Material"; + ot->idname = "OBJECT_OT_material_slot_move"; + ot->description = "Move the active material up/down in the list"; + + /* api callbacks */ + ot->exec = material_slot_move_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_enum(ot->srna, "direction", material_slot_move, 0, "Direction", "Direction to move, UP or DOWN"); +} + /********************** new material operator *********************/ static int new_material_exec(bContext *C, wmOperator *UNUSED(op)) diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index d786c0cfc36..a0ab8de0101 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -61,6 +61,9 @@ #include "BIF_glutil.h" #include "BLF_api.h" +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + #include "UI_interface.h" #include "UI_interface_icons.h" #include "UI_resources.h" @@ -149,6 +152,34 @@ void ED_area_do_refresh(bContext *C, ScrArea *sa) } /** + * Action zones are only updated if the mouse is inside of them, but in some cases (currently only fullscreen icon) + * it might be needed to update their properties and redraw if the mouse isn't inside. + */ +void ED_area_azones_update(ScrArea *sa, const int mouse_xy[2]) +{ + AZone *az; + bool changed = false; + + for (az = sa->actionzones.first; az; az = az->next) { + if (az->type == AZONE_FULLSCREEN) { + /* only if mouse is not hovering the azone */ + if (BLI_rcti_isect_pt_v(&az->rect, mouse_xy) == false) { + az->alpha = 0.0f; + changed = true; + + /* can break since currently only this is handled here */ + break; + } + } + } + + if (changed) { + sa->flag &= ~AREA_FLAG_ACTIONZONES_UPDATE; + ED_area_tag_redraw(sa); + } +} + +/** * \brief Corner widget use for quitting fullscreen. */ static void area_draw_azone_fullscreen(short x1, short y1, short x2, short y2, float alpha) @@ -366,6 +397,11 @@ static void region_draw_azone_tria(AZone *az) glDisable(GL_BLEND); } +static void area_azone_tag_update(ScrArea *sa) +{ + sa->flag |= AREA_FLAG_ACTIONZONES_UPDATE; +} + static void region_draw_azones(ScrArea *sa, ARegion *ar) { AZone *az; @@ -406,6 +442,10 @@ static void region_draw_azones(ScrArea *sa, ARegion *ar) } else if (az->type == AZONE_FULLSCREEN) { area_draw_azone_fullscreen(az->x1, az->y1, az->x2, az->y2, az->alpha); + + if (az->alpha != 0.0f) { + area_azone_tag_update(sa); + } } } } @@ -2027,6 +2067,196 @@ void ED_region_info_draw(ARegion *ar, const char *text, int block, float fill_co glScissor(scissor[0], scissor[1], scissor[2], scissor[3]); } +#define MAX_METADATA_STR 1024 + +const char *meta_data_list[] = +{ + "File", + "Strip", + "Note", + "Date", + "RenderTime", + "Marker", + "Time", + "Frame", + "Camera", + "Scene" +}; + +BLI_INLINE bool metadata_is_valid(ImBuf *ibuf, char *r_str, short index, int offset) +{ + return (IMB_metadata_get_field(ibuf, meta_data_list[index], r_str + offset, MAX_METADATA_STR - offset) && r_str[0]); +} + +static void metadata_draw_imbuf(ImBuf *ibuf, rctf rect, int fontid, const bool is_top) +{ + char temp_str[MAX_METADATA_STR]; + int line_width; + int ofs_y = 0; + short i; + int len; + const float height = BLF_height_max(fontid); + const float vertical_offset = height + (0.1f * U.widget_unit); + + if (is_top) { + for (i = 0; i < 4; i++) { + /* first line */ + if (i == 0) { + bool do_newline = false; + len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[0]); + if (metadata_is_valid(ibuf, temp_str, 0, len)) { + BLF_position(fontid, rect.xmin + (0.2f * U.widget_unit), + rect.ymax - vertical_offset, 0.0f); + BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); + do_newline = true; + } + + len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[1]); + if (metadata_is_valid(ibuf, temp_str, 1, len)) { + line_width = BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); + BLF_position(fontid, rect.xmax - line_width - (0.2f * U.widget_unit), + rect.ymax - vertical_offset, 0.0f); + BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); + do_newline = true; + } + + if (do_newline) + ofs_y += vertical_offset; + } + else if (i == 1) { + len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]); + if (metadata_is_valid(ibuf, temp_str, i + 1, len)) { + BLF_position(fontid, rect.xmin + (0.2f * U.widget_unit), + rect.ymax - vertical_offset - ofs_y, 0.0f); + BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); + ofs_y += vertical_offset; + } + } + else { + len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i + 1]); + if (metadata_is_valid(ibuf, temp_str, i + 1, len)) { + line_width = BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); + BLF_position(fontid, rect.xmax - line_width - (0.2f * U.widget_unit), + rect.ymax - vertical_offset - ofs_y, 0.0f); + BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); + ofs_y += vertical_offset; + } + } + } + } + else { + int ofs_x = 0; + for (i = 5; i < 10; i++) { + len = BLI_snprintf_rlen(temp_str, MAX_METADATA_STR, "%s: ", meta_data_list[i]); + if (metadata_is_valid(ibuf, temp_str, i, len)) { + BLF_position(fontid, rect.xmin + (0.2f * U.widget_unit) + ofs_x, + rect.ymin + (0.3f * U.widget_unit), 0.0f); + BLF_draw(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX); + + ofs_x += BLF_width(fontid, temp_str, BLF_DRAW_STR_DUMMY_MAX) + UI_UNIT_X; + } + } + } +} + +static float metadata_box_height_get(ImBuf *ibuf, int fontid, const bool is_top) +{ + char str[MAX_METADATA_STR]; + short i, count = 0; + const float height = BLF_height_max(fontid) + 0.1f * U.widget_unit; + + if (is_top) { + if (metadata_is_valid(ibuf, str, 0, 0) || metadata_is_valid(ibuf, str, 1, 0)) { + count++; + } + for (i = 2; i < 5; i++) { + if (metadata_is_valid(ibuf, str, i, 0)) { + count++; + } + } + } + else { + for (i = 5; i < 10; i++) { + if (metadata_is_valid(ibuf, str, i, 0)) { + count = 1; + } + } + } + + if (count) { + return (height * count + (0.1f * U.widget_unit)); + } + + return 0; +} + +#undef MAX_METADATA_STR + +void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, rctf frame, float zoomx, float zoomy) +{ + float box_y; + rctf rect; + uiStyle *style = UI_style_get_dpi(); + + if (!ibuf->metadata) + return; + + /* find window pixel coordinates of origin */ + glPushMatrix(); + + /* offset and zoom using ogl */ + glTranslatef(x, y, 0.0f); + glScalef(zoomx, zoomy, 1.0f); + + BLF_size(blf_mono_font, style->widgetlabel.points * 1.5f, U.dpi); + + /* *** upper box*** */ + + /* get needed box height */ + box_y = metadata_box_height_get(ibuf, blf_mono_font, true); + + if (box_y) { + UI_ThemeColor(TH_METADATA_BG); + + /* set up rect */ + BLI_rctf_init(&rect, frame.xmin, frame.xmax, frame.ymax, frame.ymax + box_y); + /* draw top box */ + glRectf(rect.xmin, rect.ymin, rect.xmax, rect.ymax); + + BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + BLF_enable(blf_mono_font, BLF_CLIPPING); + + UI_ThemeColor(TH_METADATA_TEXT); + metadata_draw_imbuf(ibuf, rect, blf_mono_font, true); + + BLF_disable(blf_mono_font, BLF_CLIPPING); + } + + + /* *** lower box*** */ + + box_y = metadata_box_height_get(ibuf, blf_mono_font, false); + + if (box_y) { + UI_ThemeColor(TH_METADATA_BG); + + /* set up box rect */ + BLI_rctf_init(&rect, frame.xmin, frame.xmax, frame.ymin - box_y, frame.ymin); + /* draw top box */ + glRectf(rect.xmin, rect.ymin, rect.xmax, rect.ymax); + + BLF_clipping(blf_mono_font, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + BLF_enable(blf_mono_font, BLF_CLIPPING); + + UI_ThemeColor(TH_METADATA_TEXT); + metadata_draw_imbuf(ibuf, rect, blf_mono_font, false); + + BLF_disable(blf_mono_font, BLF_CLIPPING); + } + + glPopMatrix(); +} + void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy) { float gridsize, gridstep = 1.0f / 32.0f; diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index 6001534e88d..8a8b61e09fe 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -579,25 +579,25 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, continue; if (type == GL_FLOAT) { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * components + subpart_x * offset_x * components]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_FLOAT, &f_rect[((size_t)subpart_y) * offset_y * img_w * components + subpart_x * offset_x * components]); /* add an extra border of pixels so linear looks ok at edges of full image. */ if (subpart_w < tex_w) - glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); + glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_FLOAT, &f_rect[((size_t)subpart_y) * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); if (subpart_h < tex_h) - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_FLOAT, &f_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]); if (subpart_w < tex_w && subpart_h < tex_h) - glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); + glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_FLOAT, &f_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); } else { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * components + subpart_x * offset_x * components]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[((size_t)subpart_y) * offset_y * img_w * components + subpart_x * offset_x * components]); if (subpart_w < tex_w) - glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); + glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[((size_t)subpart_y) * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); if (subpart_h < tex_h) - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]); if (subpart_w < tex_w && subpart_h < tex_h) - glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); + glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); } glEnable(GL_TEXTURE_2D); @@ -991,7 +991,7 @@ void bgl_get_mats(bglMats *mats) /** * \note \a viewdist is only for ortho at the moment. */ -void bglPolygonOffset(float viewdist, float dist) +void bglPolygonOffset(float viewdist, float dist) { static float winmat[16], offset = 0.0; @@ -1007,8 +1007,25 @@ void bglPolygonOffset(float viewdist, float dist) /* dist is from camera to center point */ - if (winmat[15] > 0.5f) offs = 0.00001f * dist * viewdist; // ortho tweaking - else offs = 0.0005f * dist; // should be clipping value or so... + if (winmat[15] > 0.5f) { +#if 1 + offs = 0.00001f * dist * viewdist; // ortho tweaking +#else + static float depth_fac = 0.0f; + if (depth_fac == 0.0f) { + int depthbits; + glGetIntegerv(GL_DEPTH_BITS, &depthbits); + depth_fac = 1.0f / (float)((1 << depthbits) - 1); + } + offs = (-1.0 / winmat[10]) * dist * depth_fac; + + UNUSED_VARS(viewdist); +#endif + } + else { + /* should be clipping value or so... */ + offs = 0.0005f * dist; + } winmat[14] -= offs; offset += offs; diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 67c18ac287e..9745d01fc89 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -4252,6 +4252,8 @@ void ED_keymap_screen(wmKeyConfig *keyconf) WM_keymap_verify_item(keymap, "SCREEN_OT_area_dupli", EVT_ACTIONZONE_AREA, 0, KM_SHIFT, 0); WM_keymap_verify_item(keymap, "SCREEN_OT_area_swap", EVT_ACTIONZONE_AREA, 0, KM_CTRL, 0); WM_keymap_verify_item(keymap, "SCREEN_OT_region_scale", EVT_ACTIONZONE_REGION, 0, 0, 0); + kmi = WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", EVT_ACTIONZONE_FULLSCREEN, 0, 0, 0); + RNA_boolean_set(kmi->ptr, "use_hide_panels", true); /* area move after action zones */ WM_keymap_verify_item(keymap, "SCREEN_OT_area_move", LEFTMOUSE, KM_PRESS, 0, 0); @@ -4279,8 +4281,6 @@ void ED_keymap_screen(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", SPACEKEY, KM_PRESS, KM_SHIFT, 0); kmi = WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", F10KEY, KM_PRESS, KM_ALT, 0); RNA_boolean_set(kmi->ptr, "use_hide_panels", true); - kmi = WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", EVT_ACTIONZONE_FULLSCREEN, 0, 0, 0); - RNA_boolean_set(kmi->ptr, "use_hide_panels", true); WM_keymap_add_item(keymap, "SCREEN_OT_screenshot", F3KEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "SCREEN_OT_screencast", F3KEY, KM_PRESS, KM_ALT, 0); diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 7992767072a..346be5b336e 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -215,7 +215,7 @@ void *image_undo_find_tile(Image *ima, ImBuf *ibuf, int x_tile, int y_tile, unsi return NULL; } -void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile, unsigned short **mask, bool **valid, bool proj) +void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile, unsigned short **mask, bool **valid, bool proj, bool find_prev) { ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE); UndoImageTile *tile; @@ -226,7 +226,7 @@ void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, /* check if tile is already pushed */ /* in projective painting we keep accounting of tiles, so if we need one pushed, just push! */ - if (!proj) { + if (find_prev) { data = image_undo_find_tile(ima, ibuf, x_tile, y_tile, mask, true); if (data) return data; @@ -445,7 +445,7 @@ void imapaint_region_tiles(ImBuf *ibuf, int x, int y, int w, int h, int *tx, int *ty = (y >> IMAPAINT_TILE_BITS); } -void ED_imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int h) +void ED_imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int h, bool find_old) { ImBuf *tmpibuf = NULL; int tilex, tiley, tilew, tileh, tx, ty; @@ -474,7 +474,7 @@ void ED_imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int for (ty = tiley; ty <= tileh; ty++) for (tx = tilex; tx <= tilew; tx++) - image_undo_push_tile(ima, ibuf, &tmpibuf, tx, ty, NULL, NULL, false); + image_undo_push_tile(ima, ibuf, &tmpibuf, tx, ty, NULL, NULL, false, find_old); ibuf->userflags |= IB_BITMAPDIRTY; diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c index eff604658d9..1ad700b2964 100644 --- a/source/blender/editors/sculpt_paint/paint_image_2d.c +++ b/source/blender/editors/sculpt_paint/paint_image_2d.c @@ -1049,7 +1049,7 @@ static int paint_2d_op(void *state, ImBuf *ibufb, unsigned short *curveb, unsign for (a = 0; a < tot; a++) { ED_imapaint_dirty_region(s->image, s->canvas, region[a].destx, region[a].desty, - region[a].width, region[a].height); + region[a].width, region[a].height, true); if (s->do_masking) { /* masking, find original pixels tiles from undo buffer to composite over */ @@ -1306,12 +1306,12 @@ static void paint_2d_fill_add_pixel_byte( const int x_px, const int y_px, ImBuf *ibuf, BLI_Stack *stack, BLI_bitmap *touched, const float color[4], float threshold_sq) { - int coordinate; + size_t coordinate; if (x_px >= ibuf->x || x_px < 0 || y_px >= ibuf->y || y_px < 0) return; - coordinate = y_px * ibuf->x + x_px; + coordinate = ((size_t)y_px) * ibuf->x + x_px; if (!BLI_BITMAP_TEST(touched, coordinate)) { float color_f[4]; @@ -1329,12 +1329,12 @@ static void paint_2d_fill_add_pixel_float( const int x_px, const int y_px, ImBuf *ibuf, BLI_Stack *stack, BLI_bitmap *touched, const float color[4], float threshold_sq) { - int coordinate; + size_t coordinate; if (x_px >= ibuf->x || x_px < 0 || y_px >= ibuf->y || y_px < 0) return; - coordinate = y_px * ibuf->x + x_px; + coordinate = ((size_t)y_px) * ibuf->x + x_px; if (!BLI_BITMAP_TEST(touched, coordinate)) { if (compare_len_squared_v3v3(ibuf->rect_float + 4 * coordinate, color, threshold_sq)) { @@ -1386,21 +1386,21 @@ void paint_2d_bucket_fill( if (!mouse_init || !br) { /* first case, no image UV, fill the whole image */ - ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y); + ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y, false); if (do_float) { for (x_px = 0; x_px < ibuf->x; x_px++) { for (y_px = 0; y_px < ibuf->y; y_px++) { - blend_color_mix_float(ibuf->rect_float + 4 * (y_px * ibuf->x + x_px), - ibuf->rect_float + 4 * (y_px * ibuf->x + x_px), color_f); + blend_color_mix_float(ibuf->rect_float + 4 * (((size_t)y_px) * ibuf->x + x_px), + ibuf->rect_float + 4 * (((size_t)y_px) * ibuf->x + x_px), color_f); } } } else { for (x_px = 0; x_px < ibuf->x; x_px++) { for (y_px = 0; y_px < ibuf->y; y_px++) { - blend_color_mix_byte((unsigned char *)(ibuf->rect + y_px * ibuf->x + x_px), - (unsigned char *)(ibuf->rect + y_px * ibuf->x + x_px), (unsigned char *)&color_b); + blend_color_mix_byte((unsigned char *)(ibuf->rect + ((size_t)y_px) * ibuf->x + x_px), + (unsigned char *)(ibuf->rect + ((size_t)y_px) * ibuf->x + x_px), (unsigned char *)&color_b); } } } @@ -1410,7 +1410,7 @@ void paint_2d_bucket_fill( * value is within the brush fill threshold from the fill color */ BLI_Stack *stack; BLI_bitmap *touched; - int coordinate; + size_t coordinate; int width = ibuf->x; float image_init[2]; int minx = ibuf->x, miny = ibuf->y, maxx = 0, maxy = 0; @@ -1428,12 +1428,12 @@ void paint_2d_bucket_fill( } /* change image invalidation method later */ - ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y); + ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y, false); - stack = BLI_stack_new(sizeof(int), __func__); - touched = BLI_BITMAP_NEW(ibuf->x * ibuf->y, "bucket_fill_bitmap"); + stack = BLI_stack_new(sizeof(size_t), __func__); + touched = BLI_BITMAP_NEW(((size_t)ibuf->x) * ibuf->y, "bucket_fill_bitmap"); - coordinate = (y_px * ibuf->x + x_px); + coordinate = (((size_t)y_px) * ibuf->x + x_px); if (do_float) { copy_v4_v4(pixel_color, ibuf->rect_float + 4 * coordinate); @@ -1566,7 +1566,7 @@ void paint_2d_gradient_fill( do_float = (ibuf->rect_float != NULL); /* this will be substituted by something else when selection is available */ - ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y); + ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y, false); if (do_float) { for (x_px = 0; x_px < ibuf->x; x_px++) { @@ -1590,8 +1590,8 @@ void paint_2d_gradient_fill( /* convert to premultiplied */ mul_v3_fl(color_f, color_f[3]); color_f[3] *= br->alpha; - IMB_blend_color_float(ibuf->rect_float + 4 * (y_px * ibuf->x + x_px), - ibuf->rect_float + 4 * (y_px * ibuf->x + x_px), + IMB_blend_color_float(ibuf->rect_float + 4 * (((size_t)y_px) * ibuf->x + x_px), + ibuf->rect_float + 4 * (((size_t)y_px) * ibuf->x + x_px), color_f, br->blend); } } @@ -1619,8 +1619,8 @@ void paint_2d_gradient_fill( linearrgb_to_srgb_v3_v3(color_f, color_f); rgba_float_to_uchar((unsigned char *)&color_b, color_f); ((unsigned char *)&color_b)[3] *= br->alpha; - IMB_blend_color_byte((unsigned char *)(ibuf->rect + y_px * ibuf->x + x_px), - (unsigned char *)(ibuf->rect + y_px * ibuf->x + x_px), + IMB_blend_color_byte((unsigned char *)(ibuf->rect + ((size_t)y_px) * ibuf->x + x_px), + (unsigned char *)(ibuf->rect + ((size_t)y_px) * ibuf->x + x_px), (unsigned char *)&color_b, br->blend); } } diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index b01d315650f..70127d0d425 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -43,6 +43,7 @@ #include "BLI_blenlib.h" #include "BLI_linklist.h" #include "BLI_math.h" +#include "BLI_math_bits.h" #include "BLI_math_color_blend.h" #include "BLI_memarena.h" #include "BLI_threads.h" @@ -134,6 +135,8 @@ BLI_INLINE unsigned char f_to_char(const float val) //#define PROJ_DEBUG_PRINT_CLIP 1 #define PROJ_DEBUG_WINCLIP 1 + +#ifndef PROJ_DEBUG_NOSEAMBLEED /* projectFaceSeamFlags options */ //#define PROJ_FACE_IGNORE (1<<0) /* When the face is hidden, backfacing or occluded */ //#define PROJ_FACE_INIT (1<<1) /* When we have initialized the faces data */ @@ -151,6 +154,13 @@ BLI_INLINE unsigned char f_to_char(const float val) #define PROJ_FACE_WINDING_INIT 1 #define PROJ_FACE_WINDING_CW 2 +/* a slightly scaled down face is used to get fake 3D location for edge pixels in the seams + * as this number approaches 1.0f the likelihood increases of float precision errors where + * it is occluded by an adjacent face */ +#define PROJ_FACE_SCALE_SEAM 0.99f +#endif /* PROJ_DEBUG_NOSEAMBLEED */ + + #define PROJ_SRC_VIEW 1 #define PROJ_SRC_IMAGE_CAM 2 #define PROJ_SRC_IMAGE_VIEW 3 @@ -159,12 +169,6 @@ BLI_INLINE unsigned char f_to_char(const float val) #define PROJ_VIEW_DATA_ID "view_data" #define PROJ_VIEW_DATA_SIZE (4 * 4 + 4 * 4 + 3) /* viewmat + winmat + clipsta + clipend + is_ortho */ - -/* a slightly scaled down face is used to get fake 3D location for edge pixels in the seams - * as this number approaches 1.0f the likelihood increases of float precision errors where - * it is occluded by an adjacent face */ -#define PROJ_FACE_SCALE_SEAM 0.99f - #define PROJ_BUCKET_NULL 0 #define PROJ_BUCKET_INIT (1 << 0) // #define PROJ_BUCKET_CLONE_INIT (1<<1) @@ -190,9 +194,32 @@ typedef struct ProjPaintImage { unsigned short **maskRect; /* the mask accumulation must happen on canvas, not on space screen bucket. * Here we store the mask rectangle */ bool **valid; /* store flag to enforce validation of undo rectangle */ - int touch; + bool touch; } ProjPaintImage; +/** + * Handle for stroke (operator customdata) + */ +typedef struct ProjStrokeHandle { + /* Support for painting from multiple views at once, + * currently used to impliment summetry painting, + * we can assume at least the first is set while painting. */ + struct ProjPaintState *ps_views[8]; + int ps_views_tot; + int symmetry_flags; + + int orig_brush_size; + + bool need_redraw; + + /* trick to bypass regular paint and allow clone picking */ + bool is_clone_cursor_pick; + + /* In ProjPaintState, only here for convenience */ + Scene *scene; + Brush *brush; +} ProjStrokeHandle; + /* Main projection painting struct passed to all projection painting functions */ typedef struct ProjPaintState { View3D *v3d; @@ -208,24 +235,14 @@ typedef struct ProjPaintState { Brush *brush; short tool, blend, mode; - int orig_brush_size; + float brush_size; Object *ob; + /* for symmetry, we need to store modified object matrix */ + float obmat[4][4]; + float obmat_imat[4][4]; /* end similarities with ImagePaintState */ - DerivedMesh *dm; - int dm_totface; - int dm_totedge; - int dm_totvert; - int dm_release; - - MVert *dm_mvert; - MEdge *dm_medge; - MFace *dm_mface; - MTFace **dm_mtface; - MTFace **dm_mtface_clone; /* other UV map, use for cloning between layers */ - MTFace *dm_mtface_stencil; - Image *stencil_ima; Image *canvas_ima; Image *clone_ima; @@ -236,24 +253,16 @@ typedef struct ProjPaintState { LinkNode **bucketRect; /* screen sized 2D array, each pixel has a linked list of ProjPixel's */ LinkNode **bucketFaces; /* bucketRect aligned array linkList of faces overlapping each bucket */ unsigned char *bucketFlags; /* store if the bucks have been initialized */ -#ifndef PROJ_DEBUG_NOSEAMBLEED - char *faceSeamFlags; /* store info about faces, if they are initialized etc*/ - char *faceWindingFlags; /* save the winding of the face in uv space, helps as an extra validation step for seam detection */ - float (*faceSeamUVs)[4][2]; /* expanded UVs for faces to use as seams */ - LinkNode **vertFaces; /* Only needed for when seam_bleed_px is enabled, use to find UV seams */ -#endif + char *vertFlags; /* store options per vert, now only store if the vert is pointing away from the view */ int buckets_x; /* The size of the bucket grid, the grid span's screenMin/screenMax so you can paint outsize the screen or with 2 brushes at once */ int buckets_y; - ProjPaintImage *projImages; - int pixel_sizeof; /* result of project_paint_pixel_sizeof(), constant per stroke */ int image_tot; /* size of projectImages array */ float (*screenCoords)[4]; /* verts projected into floating point screen space */ - float *cavities; /* cavity amount for vertices */ float screenMin[2]; /* 2D bounds for mesh verts on the screen's plane (screenspace) */ float screenMax[2]; float screen_width; /* Calculated from screenMin & screenMax */ @@ -272,12 +281,15 @@ typedef struct ProjPaintState { bool do_mask_normal; /* mask out pixels based on their normals */ bool do_mask_cavity; /* mask out pixels based on cavity */ bool do_new_shading_nodes; /* cache BKE_scene_use_new_shading_nodes value */ - float normal_angle; /* what angle to mask at*/ + float normal_angle; /* what angle to mask at */ + float normal_angle__cos; /* cos(normal_angle), faster to compare */ float normal_angle_inner; + float normal_angle_inner__cos; float normal_angle_range; /* difference between normal_angle and normal_angle_inner, for easy access */ bool do_face_sel; /* quick access to (me->editflag & ME_EDIT_PAINT_FACE_SEL) */ bool is_ortho; + bool is_flip_object; /* the object is negative scaled */ bool do_masking; /* use masking during painting. Some operations such as airbrush may disable */ bool is_texbrush; /* only to avoid running */ bool is_maskbrush; /* mask brush is applied before masking */ @@ -302,13 +314,51 @@ typedef struct ProjPaintState { int bucketMax[2]; int context_bucket_x, context_bucket_y; /* must lock threads while accessing these */ - /* redraw */ - bool need_redraw; - struct CurveMapping *cavity_curve; BlurKernel *blurkernel; + + + /* -------------------------------------------------------------------- */ + /* Vars shared between multiple views (keep last) */ + /** + * This data is owned by ``ProjStrokeHandle.ps_views[0]``, + * all other views re-use the data. + */ + +#define PROJ_PAINT_STATE_SHARED_MEMCPY(ps_dst, ps_src) \ + MEMCPY_STRUCT_OFS(ps_dst, ps_src, is_shared_user) + +#define PROJ_PAINT_STATE_SHARED_CLEAR(ps) \ + MEMSET_STRUCT_OFS(ps, 0, is_shared_user) + + bool is_shared_user; + + ProjPaintImage *projImages; + float *cavities; /* cavity amount for vertices */ + +#ifndef PROJ_DEBUG_NOSEAMBLEED + char *faceSeamFlags; /* store info about faces, if they are initialized etc*/ + char *faceWindingFlags; /* save the winding of the face in uv space, helps as an extra validation step for seam detection */ + float (*faceSeamUVs)[4][2]; /* expanded UVs for faces to use as seams */ + LinkNode **vertFaces; /* Only needed for when seam_bleed_px is enabled, use to find UV seams */ +#endif + SpinLock *tile_lock; + + DerivedMesh *dm; + int dm_totface; + int dm_totedge; + int dm_totvert; + int dm_release; + + MVert *dm_mvert; + MEdge *dm_medge; + MFace *dm_mface; + MTFace *dm_mtface_stencil; + + MTFace **dm_mtface; + MTFace **dm_mtface_clone; /* other UV map, use for cloning between layers */ } ProjPaintState; typedef union pixelPointer { @@ -326,25 +376,27 @@ typedef union pixelStore { typedef struct ProjPixel { float projCoSS[2]; /* the floating point screen projection of this pixel */ float worldCoSS[3]; + + short x_px, y_px; + + unsigned short image_index; /* if anyone wants to paint onto more than 65535 images they can bite me */ + unsigned char bb_cell_index; + + /* for various reasons we may want to mask out painting onto this pixel */ + unsigned short mask; + /* Only used when the airbrush is disabled. * Store the max mask value to avoid painting over an area with a lower opacity * with an advantage that we can avoid touching the pixel at all, if the * new mask value is lower then mask_accum */ unsigned short *mask_accum; - /* for various reasons we may want to mask out painting onto this pixel */ - unsigned short mask; - - short x_px, y_px; /* horrible hack, store tile valid flag pointer here to re-validate tiles used for anchored and drag-dot strokes */ bool *valid; PixelPointer origColor; PixelStore newColor; PixelPointer pixel; - - short image_index; /* if anyone wants to paint onto more than 32768 images they can bite me */ - unsigned char bb_cell_index; } ProjPixel; typedef struct ProjPixelClone { @@ -474,7 +526,9 @@ static float VecZDepthPersp( /* Return the top-most face index that the screen space coord 'pt' touches (or -1) */ -static int project_paint_PickFace(const ProjPaintState *ps, const float pt[2], float w[3], int *side) +static int project_paint_PickFace( + const ProjPaintState *ps, const float pt[2], + float w[3], int *r_side) { LinkNode *node; float w_tmp[3]; @@ -531,7 +585,7 @@ static int project_paint_PickFace(const ProjPaintState *ps, const float pt[2], f } } - *side = best_side; + *r_side = best_side; return best_face_index; /* will be -1 or a valid face */ } @@ -718,7 +772,7 @@ static bool project_bucket_point_occluded( int face_index; int isect_ret; float w[3]; /* not needed when clipping */ - const short do_clip = ps->rv3d ? ps->rv3d->rflag & RV3D_CLIPPING : 0; + const bool do_clip = ps->rv3d ? (ps->rv3d->rflag & RV3D_CLIPPING) != 0 : 0; /* we could return 0 for 1 face buckets, as long as this function assumes * that the point its testing is only every originated from an existing face */ @@ -1228,22 +1282,22 @@ static void screen_px_from_persp( static void project_face_pixel( const MTFace *tf_other, ImBuf *ibuf_other, const float w[3], - int side, unsigned char rgba_ub[4], float rgba_f[4]) + bool side, unsigned char rgba_ub[4], float rgba_f[4]) { const float *uvCo1, *uvCo2, *uvCo3; float uv_other[2], x, y; - uvCo1 = (float *)tf_other->uv[0]; + uvCo1 = tf_other->uv[0]; if (side == 1) { - uvCo2 = (float *)tf_other->uv[2]; - uvCo3 = (float *)tf_other->uv[3]; + uvCo2 = tf_other->uv[2]; + uvCo3 = tf_other->uv[3]; } else { - uvCo2 = (float *)tf_other->uv[1]; - uvCo3 = (float *)tf_other->uv[2]; + uvCo2 = tf_other->uv[1]; + uvCo3 = tf_other->uv[2]; } - interp_v2_v2v2v2(uv_other, uvCo1, uvCo2, uvCo3, (float *)w); + interp_v2_v2v2v2(uv_other, uvCo1, uvCo2, uvCo3, w); /* use */ uvco_to_wrapped_pxco(uv_other, ibuf_other->x, ibuf_other->y, &x, &y); @@ -1262,7 +1316,7 @@ static void project_face_pixel( static float project_paint_uvpixel_mask( const ProjPaintState *ps, const int face_index, - const int side, + const bool side, const float w[3]) { float mask; @@ -1327,7 +1381,7 @@ static float project_paint_uvpixel_mask( /* calculate mask */ if (ps->do_mask_normal) { MFace *mf = &ps->dm_mface[face_index]; - float no[3], angle; + float no[3], angle_cos; if (mf->flag & ME_SMOOTH) { const short *no1, *no2, *no3; no1 = ps->dm_mvert[mf->v1].no; @@ -1366,9 +1420,13 @@ static float project_paint_uvpixel_mask( #endif } + if (UNLIKELY(ps->is_flip_object)) { + negate_v3(no); + } + /* now we can use the normal as a mask */ if (ps->is_ortho) { - angle = angle_normalized_v3v3(ps->viewDir, no); + angle_cos = dot_v3v3(ps->viewDir, no); } else { /* Annoying but for the perspective view we need to get the pixels location in 3D space :/ */ @@ -1389,15 +1447,18 @@ static float project_paint_uvpixel_mask( viewDirPersp[1] = (ps->viewPos[1] - (w[0] * co1[1] + w[1] * co2[1] + w[2] * co3[1])); viewDirPersp[2] = (ps->viewPos[2] - (w[0] * co1[2] + w[1] * co2[2] + w[2] * co3[2])); normalize_v3(viewDirPersp); + if (UNLIKELY(ps->is_flip_object)) { + negate_v3(viewDirPersp); + } - angle = angle_normalized_v3v3(viewDirPersp, no); + angle_cos = dot_v3v3(viewDirPersp, no); } - if (angle >= ps->normal_angle) { + if (angle_cos <= ps->normal_angle__cos) { return 0.0f; /* outsize the normal limit*/ } - else if (angle > ps->normal_angle_inner) { - mask *= (ps->normal_angle - angle) / ps->normal_angle_range; + else if (angle_cos < ps->normal_angle_inner__cos) { + mask *= (ps->normal_angle - acosf(angle_cos)) / ps->normal_angle_range; } /* otherwise no mask normal is needed, were within the limit */ } @@ -1440,10 +1501,10 @@ static int project_paint_undo_subtiles(const TileInfo *tinf, int tx, int ty) if (generate_tile) { volatile void *undorect; if (tinf->masked) { - undorect = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, &pjIma->maskRect[tile_index], &pjIma->valid[tile_index], true); + undorect = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, &pjIma->maskRect[tile_index], &pjIma->valid[tile_index], true, false); } else { - undorect = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, NULL, &pjIma->valid[tile_index], true); + undorect = image_undo_push_tile(pjIma->ima, pjIma->ibuf, tinf->tmpibuf, tx, ty, NULL, &pjIma->valid[tile_index], true, false); } pjIma->ibuf->userflags |= IB_BITMAPDIRTY; @@ -1470,7 +1531,7 @@ static ProjPixel *project_paint_uvpixel_init( const int face_index, const float pixelScreenCo[4], const float world_spaceCo[3], - const int side, + const bool side, const float w[3]) { ProjPixel *projPixel; @@ -1591,7 +1652,7 @@ static ProjPixel *project_paint_uvpixel_init( } else { float co[2]; - sub_v2_v2v2(co, projPixel->projCoSS, (float *)ps->cloneOffset); + sub_v2_v2v2(co, projPixel->projCoSS, ps->cloneOffset); /* no need to initialize the bucket, we're only checking buckets faces and for this * the faces are already initialized in project_paint_delayed_face_init(...) */ @@ -1976,7 +2037,10 @@ static float angle_2d_clockwise(const float p1[2], const float p2[2], const floa #define ISECT_ALL4 ((1 << 4) - 1) /* limit must be a fraction over 1.0f */ -static bool IsectPT2Df_limit(float pt[2], float v1[2], float v2[2], float v3[2], float limit) +static bool IsectPT2Df_limit( + const float pt[2], + const float v1[2], const float v2[2], const float v3[2], + const float limit) { return ((area_tri_v2(pt, v1, v2) + area_tri_v2(pt, v2, v3) + @@ -2043,9 +2107,9 @@ static bool line_rect_clip( static void project_bucket_clip_face( - const bool is_ortho, + const bool is_ortho, const bool is_flip_object, const rctf *bucket_bounds, - float *v1coSS, float *v2coSS, float *v3coSS, + const float *v1coSS, const float *v2coSS, const float *v3coSS, const float *uv1co, const float *uv2co, const float *uv3co, float bucket_bounds_uv[8][2], int *tot, bool cull) @@ -2071,7 +2135,8 @@ static void project_bucket_clip_face( inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v3coSS) << 2; if (inside_bucket_flag == ISECT_ALL3) { - flip = ((line_point_side_v2(v1coSS, v2coSS, v3coSS) > 0.0f) != + /* is_flip_object is used here because we use the face winding */ + flip = (((line_point_side_v2(v1coSS, v2coSS, v3coSS) > 0.0f) != is_flip_object) != (line_point_side_v2(uv1co, uv2co, uv3co) > 0.0f)); /* all screenspace points are inside the bucket bounding box, @@ -2193,7 +2258,7 @@ static void project_bucket_clip_face( float cent[2] = {0.0f, 0.0f}; /*float up[2] = {0.0f, 1.0f};*/ int i; - short doubles; + bool doubles; (*tot) = 0; @@ -2404,7 +2469,7 @@ static bool IsectPoly2Df(const float pt[2], float uv[][2], const int tot) static bool IsectPoly2Df_twoside(const float pt[2], float uv[][2], const int tot) { int i; - int side = (line_point_side_v2(uv[tot - 1], uv[0], pt) > 0.0f); + bool side = (line_point_side_v2(uv[tot - 1], uv[0], pt) > 0.0f); for (i = 1; i < tot; i++) { if ((line_point_side_v2(uv[i - 1], uv[i], pt) > 0.0f) != side) @@ -2423,7 +2488,8 @@ static bool IsectPoly2Df_twoside(const float pt[2], float uv[][2], const int tot static void project_paint_face_init( const ProjPaintState *ps, const int thread_index, const int bucket_index, const int face_index, const int image_index, - const rctf *bucket_bounds, ImBuf *ibuf, ImBuf **tmpibuf, const short clamp_u, const short clamp_v) + const rctf *bucket_bounds, ImBuf *ibuf, ImBuf **tmpibuf, + const bool clamp_u, const bool clamp_v) { /* Projection vars, to get the 3D locations into screen space */ MemArena *arena = ps->arena_mt[thread_index]; @@ -2448,8 +2514,8 @@ static void project_paint_face_init( float mask; float uv[2]; /* Image floating point UV - same as x, y but from 0.0-1.0 */ - int side; - float *v1coSS, *v2coSS, *v3coSS; /* vert co screen-space, these will be assigned to mf->v1,2,3 or mf->v1,3,4 */ + bool side; + const float *v1coSS, *v2coSS, *v3coSS; /* vert co screen-space, these will be assigned to mf->v1,2,3 or mf->v1,3,4 */ float *vCo[4]; /* vertex screenspace coords */ @@ -2473,6 +2539,7 @@ static void project_paint_face_init( float uv_clip[8][2]; int uv_clip_tot; const bool is_ortho = ps->is_ortho; + const bool is_flip_object = ps->is_flip_object; const bool do_backfacecull = ps->do_backfacecull; const bool do_clip = ps->rv3d ? ps->rv3d->rflag & RV3D_CLIPPING : 0; @@ -2534,11 +2601,12 @@ static void project_paint_face_init( /* This funtion gives is a concave polyline in UV space from the clipped quad and tri*/ project_bucket_clip_face( - is_ortho, bucket_bounds, + is_ortho, is_flip_object, + bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, uv_clip, &uv_clip_tot, - ps->do_backfacecull || ps->do_occlude); + do_backfacecull || ps->do_occlude); /* sometimes this happens, better just allow for 8 intersectiosn even though there should be max 6 */ #if 0 @@ -2851,6 +2919,8 @@ static void project_paint_face_init( } } } +#else + UNUSED_VARS(vCo, threaded); #endif // PROJ_DEBUG_NOSEAMBLEED } @@ -2902,7 +2972,10 @@ static void project_bucket_init(const ProjPaintState *ps, const int thread_index ima = ps->projImages[0].ima; for (node = ps->bucketFaces[bucket_index]; node; node = node->next) { - project_paint_face_init(ps, thread_index, bucket_index, GET_INT_FROM_POINTER(node->link), 0, bucket_bounds, ibuf, &tmpibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V); + project_paint_face_init( + ps, thread_index, bucket_index, GET_INT_FROM_POINTER(node->link), 0, + bucket_bounds, ibuf, &tmpibuf, + (ima->tpageflag & IMA_CLAMP_U) != 0, (ima->tpageflag & IMA_CLAMP_V) != 0); } } else { @@ -2926,7 +2999,10 @@ static void project_bucket_init(const ProjPaintState *ps, const int thread_index } /* context switching done */ - project_paint_face_init(ps, thread_index, bucket_index, face_index, image_index, bucket_bounds, ibuf, &tmpibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V); + project_paint_face_init( + ps, thread_index, bucket_index, face_index, image_index, + bucket_bounds, ibuf, &tmpibuf, + (ima->tpageflag & IMA_CLAMP_U) != 0, (ima->tpageflag & IMA_CLAMP_V) != 0); } } @@ -3078,7 +3154,8 @@ static void proj_paint_state_non_cddm_init(ProjPaintState *ps) } } -static void proj_paint_state_viewport_init(ProjPaintState *ps) +static void proj_paint_state_viewport_init( + ProjPaintState *ps, const char symmetry_flag) { float mat[3][3]; float viewmat[4][4]; @@ -3088,7 +3165,19 @@ static void proj_paint_state_viewport_init(ProjPaintState *ps) ps->viewDir[1] = 0.0f; ps->viewDir[2] = 1.0f; - invert_m4_m4(ps->ob->imat, ps->ob->obmat); + copy_m4_m4(ps->obmat, ps->ob->obmat); + + if (symmetry_flag) { + int i; + for (i = 0; i < 3; i++) { + if ((symmetry_flag >> i) & 1) { + negate_v3(ps->obmat[i]); + ps->is_flip_object = !ps->is_flip_object; + } + } + } + + invert_m4_m4(ps->obmat_imat, ps->obmat); if (ELEM(ps->source, PROJ_SRC_VIEW, PROJ_SRC_VIEW_FILL)) { /* normal drawing */ @@ -3098,7 +3187,7 @@ static void proj_paint_state_viewport_init(ProjPaintState *ps) copy_m4_m4(viewmat, ps->rv3d->viewmat); copy_m4_m4(viewinv, ps->rv3d->viewinv); - ED_view3d_ob_project_mat_get(ps->rv3d, ps->ob, ps->projectMat); + ED_view3d_ob_project_mat_get_from_obmat(ps->rv3d, ps->obmat, ps->projectMat); ps->is_ortho = ED_view3d_clip_range_get(ps->v3d, ps->rv3d, &ps->clipsta, &ps->clipend, true); } @@ -3151,24 +3240,27 @@ static void proj_paint_state_viewport_init(ProjPaintState *ps) } /* same as #ED_view3d_ob_project_mat_get */ - mul_m4_m4m4(vmat, viewmat, ps->ob->obmat); + mul_m4_m4m4(vmat, viewmat, ps->obmat); mul_m4_m4m4(ps->projectMat, winmat, vmat); } /* viewDir - object relative */ - invert_m4_m4(ps->ob->imat, ps->ob->obmat); copy_m3_m4(mat, viewinv); mul_m3_v3(mat, ps->viewDir); - copy_m3_m4(mat, ps->ob->imat); + copy_m3_m4(mat, ps->obmat_imat); mul_m3_v3(mat, ps->viewDir); normalize_v3(ps->viewDir); + if (UNLIKELY(ps->is_flip_object)) { + negate_v3(ps->viewDir); + } + /* viewPos - object relative */ copy_v3_v3(ps->viewPos, viewinv[3]); - copy_m3_m4(mat, ps->ob->imat); + copy_m3_m4(mat, ps->obmat_imat); mul_m3_v3(mat, ps->viewPos); - add_v3_v3(ps->viewPos, ps->ob->imat[3]); + add_v3_v3(ps->viewPos, ps->obmat_imat[3]); } static void proj_paint_state_screen_coords_init(ProjPaintState *ps, const int diameter) @@ -3234,6 +3326,8 @@ static void proj_paint_state_screen_coords_init(ProjPaintState *ps, const int di CLAMP(ps->screenMin[1], (float)(-diameter), (float)(ps->winy + diameter)); CLAMP(ps->screenMax[1], (float)(-diameter), (float)(ps->winy + diameter)); +#else + UNUSED_VARS(diameter); #endif } else if (ps->source != PROJ_SRC_VIEW_FILL) { /* re-projection, use bounds */ @@ -3313,12 +3407,14 @@ static void proj_paint_state_thread_init(ProjPaintState *ps, const bool reset_th if (reset_threads) ps->thread_tot = 1; - if (ps->thread_tot > 1) { - ps->tile_lock = MEM_mallocN(sizeof(SpinLock), "projpaint_tile_lock"); - BLI_spin_init(ps->tile_lock); - } + if (ps->is_shared_user == false) { + if (ps->thread_tot > 1) { + ps->tile_lock = MEM_mallocN(sizeof(SpinLock), "projpaint_tile_lock"); + BLI_spin_init(ps->tile_lock); + } - image_undo_init_locks(); + image_undo_init_locks(); + } for (a = 0; a < ps->thread_tot; a++) { ps->arena_mt[a] = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "project paint arena"); @@ -3337,16 +3433,22 @@ static void proj_paint_state_vert_flags_init(ProjPaintState *ps) for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++) { normal_short_to_float_v3(no, mv->no); + if (UNLIKELY(ps->is_flip_object)) { + negate_v3(no); + } if (ps->is_ortho) { - if (angle_normalized_v3v3(ps->viewDir, no) >= ps->normal_angle) { /* 1 vert of this face is towards us */ + if (dot_v3v3(ps->viewDir, no) <= ps->normal_angle__cos) { /* 1 vert of this face is towards us */ ps->vertFlags[a] |= PROJ_VERT_CULL; } } else { sub_v3_v3v3(viewDirPersp, ps->viewPos, mv->co); normalize_v3(viewDirPersp); - if (angle_normalized_v3v3(viewDirPersp, no) >= ps->normal_angle) { /* 1 vert of this face is towards us */ + if (UNLIKELY(ps->is_flip_object)) { + negate_v3(viewDirPersp); + } + if (dot_v3v3(viewDirPersp, no) <= ps->normal_angle__cos) { /* 1 vert of this face is towards us */ ps->vertFlags[a] |= PROJ_VERT_CULL; } } @@ -3628,7 +3730,7 @@ static bool project_paint_backface_cull( } } else { - if (line_point_side_v2(coSS->v1, coSS->v2, coSS->v3) < 0.0f) { + if ((line_point_side_v2(coSS->v1, coSS->v2, coSS->v3) < 0.0f) != ps->is_flip_object) { return true; } @@ -3670,7 +3772,8 @@ static void project_paint_prepare_all_faces( ProjPaintState *ps, MemArena *arena, const ProjPaintFaceLookup *face_lookup, ProjPaintLayerClone *layer_clone, - MTFace *tf_base) + MTFace *tf_base, + const bool is_multi_view) { /* Image Vars - keep track of images we have used */ LinkNode *image_LinkList = NULL; @@ -3729,20 +3832,21 @@ static void project_paint_prepare_all_faces( ProjPaintFaceCoSS coSS; proj_paint_face_coSS_init(ps, mf, &coSS); - if (project_paint_flt_max_cull(ps, &coSS)) { - continue; - } + if (is_multi_view == false) { + if (project_paint_flt_max_cull(ps, &coSS)) { + continue; + } #ifdef PROJ_DEBUG_WINCLIP - if (project_paint_winclip(ps, mf, &coSS)) { - continue; - } + if (project_paint_winclip(ps, mf, &coSS)) { + continue; + } #endif //PROJ_DEBUG_WINCLIP - - if (project_paint_backface_cull(ps, mf, &coSS)) { - continue; + if (project_paint_backface_cull(ps, mf, &coSS)) { + continue; + } } if (tpage_last != tpage) { @@ -3767,18 +3871,22 @@ static void project_paint_prepare_all_faces( } /* build an array of images we use*/ - project_paint_build_proj_ima(ps, arena, image_LinkList); + if (ps->is_shared_user == false) { + project_paint_build_proj_ima(ps, arena, image_LinkList); + } /* we have built the array, discard the linked list */ BLI_linklist_free(image_LinkList, NULL); } /* run once per stroke before projection painting */ -static void project_paint_begin(ProjPaintState *ps) +static void project_paint_begin( + ProjPaintState *ps, + const bool is_multi_view, const char symmetry_flag) { ProjPaintLayerClone layer_clone; ProjPaintFaceLookup face_lookup; - MTFace *tf_base; + MTFace *tf_base = NULL; MemArena *arena; /* at the moment this is just ps->arena_mt[0], but use this to show were not multithreading */ @@ -3792,10 +3900,13 @@ static void project_paint_begin(ProjPaintState *ps) ED_view3d_clipping_local(ps->rv3d, ps->ob->obmat); /* faster clipping lookups */ ps->do_face_sel = ((((Mesh *)ps->ob->data)->editflag & ME_EDIT_PAINT_FACE_SEL) != 0); + ps->is_flip_object = (ps->ob->transflag & OB_NEG_SCALE) != 0; /* paint onto the derived mesh */ - if (!proj_paint_state_dm_init(ps)) { - return; + if (ps->is_shared_user == false) { + if (!proj_paint_state_dm_init(ps)) { + return; + } } proj_paint_face_lookup_init(ps, &face_lookup); @@ -3817,11 +3928,13 @@ static void project_paint_begin(ProjPaintState *ps) } /* when using subsurf or multires, mface arrays are thrown away, we need to keep a copy */ - proj_paint_state_non_cddm_init(ps); + if (ps->is_shared_user == false) { + proj_paint_state_non_cddm_init(ps); - proj_paint_state_cavity_init(ps); + proj_paint_state_cavity_init(ps); + } - proj_paint_state_viewport_init(ps); + proj_paint_state_viewport_init(ps, symmetry_flag); /* calculate vert screen coords * run this early so we can calculate the x/y resolution of our bucket rect */ @@ -3850,7 +3963,9 @@ static void project_paint_begin(ProjPaintState *ps) ps->bucketFlags = MEM_callocN(sizeof(char) * ps->buckets_x * ps->buckets_y, "paint-bucketFaces"); #ifndef PROJ_DEBUG_NOSEAMBLEED - proj_paint_state_seam_bleed_init(ps); + if (ps->is_shared_user == false) { + proj_paint_state_seam_bleed_init(ps); + } #endif proj_paint_state_thread_init(ps, reset_threads); @@ -3858,7 +3973,7 @@ static void project_paint_begin(ProjPaintState *ps) proj_paint_state_vert_flags_init(ps); - project_paint_prepare_all_faces(ps, arena, &face_lookup, &layer_clone, tf_base); + project_paint_prepare_all_faces(ps, arena, &face_lookup, &layer_clone, tf_base, is_multi_view); } static void paint_proj_begin_clone(ProjPaintState *ps, const float mouse[2]) @@ -3867,7 +3982,7 @@ static void paint_proj_begin_clone(ProjPaintState *ps, const float mouse[2]) if (ps->tool == PAINT_TOOL_CLONE) { float projCo[4]; copy_v3_v3(projCo, ED_view3d_cursor3d_get(ps->scene, ps->v3d)); - mul_m4_v3(ps->ob->imat, projCo); + mul_m4_v3(ps->obmat_imat, projCo); projCo[3] = 1.0f; mul_m4_v4(ps->projectMat, projCo); @@ -3879,14 +3994,16 @@ static void paint_proj_begin_clone(ProjPaintState *ps, const float mouse[2]) static void project_paint_end(ProjPaintState *ps) { int a; - ProjPaintImage *projIma; image_undo_remove_masks(); /* 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); - DAG_id_tag_update(&projIma->ima->id, 0); + if (ps->is_shared_user == false) { + ProjPaintImage *projIma; + for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) { + BKE_image_release_ibuf(projIma->ima, projIma->ibuf, NULL); + DAG_id_tag_update(&projIma->ima->id, 0); + } } BKE_image_release_ibuf(ps->reproject_image, ps->reproject_ibuf, NULL); @@ -3895,68 +4012,81 @@ static void project_paint_end(ProjPaintState *ps) MEM_freeN(ps->bucketRect); MEM_freeN(ps->bucketFaces); MEM_freeN(ps->bucketFlags); - MEM_freeN(ps->dm_mtface); - if (ps->do_layer_clone) - MEM_freeN(ps->dm_mtface_clone); - if (ps->thread_tot > 1) { - BLI_spin_end(ps->tile_lock); - MEM_freeN((void *)ps->tile_lock); - } - image_undo_end_locks(); + + if (ps->is_shared_user == false) { + + /* must be set for non-shared */ + BLI_assert(ps->dm_mtface || ps->is_shared_user); + if (ps->dm_mtface) + MEM_freeN(ps->dm_mtface); + + if (ps->do_layer_clone) + MEM_freeN(ps->dm_mtface_clone); + if (ps->thread_tot > 1) { + BLI_spin_end(ps->tile_lock); + MEM_freeN((void *)ps->tile_lock); + } + + image_undo_end_locks(); #ifndef PROJ_DEBUG_NOSEAMBLEED - if (ps->seam_bleed_px > 0.0f) { - MEM_freeN(ps->vertFaces); - MEM_freeN(ps->faceSeamFlags); - MEM_freeN(ps->faceWindingFlags); - MEM_freeN(ps->faceSeamUVs); - } + if (ps->seam_bleed_px > 0.0f) { + MEM_freeN(ps->vertFaces); + MEM_freeN(ps->faceSeamFlags); + MEM_freeN(ps->faceWindingFlags); + MEM_freeN(ps->faceSeamUVs); + } #endif + if (ps->do_mask_cavity) { + MEM_freeN(ps->cavities); + } + + /* copy for subsurf/multires, so throw away */ + if (ps->dm->type != DM_TYPE_CDDM) { + if (ps->dm_mvert) MEM_freeN(ps->dm_mvert); + if (ps->dm_mface) MEM_freeN(ps->dm_mface); + /* looks like these don't need copying */ +#if 0 + if (ps->dm_mtface) MEM_freeN(ps->dm_mtface); + if (ps->dm_mtface_clone) MEM_freeN(ps->dm_mtface_clone); + if (ps->dm_mtface_stencil) MEM_freeN(ps->dm_mtface_stencil); +#endif + } + + if (ps->dm_release) + ps->dm->release(ps->dm); + } + if (ps->blurkernel) { paint_delete_blur_kernel(ps->blurkernel); MEM_freeN(ps->blurkernel); } - if (ps->do_mask_cavity) { - MEM_freeN(ps->cavities); - } - if (ps->vertFlags) MEM_freeN(ps->vertFlags); for (a = 0; a < ps->thread_tot; a++) { BLI_memarena_free(ps->arena_mt[a]); } +} - /* copy for subsurf/multires, so throw away */ - if (ps->dm->type != DM_TYPE_CDDM) { - if (ps->dm_mvert) MEM_freeN(ps->dm_mvert); - if (ps->dm_mface) MEM_freeN(ps->dm_mface); - /* looks like these don't need copying */ -#if 0 - if (ps->dm_mtface) MEM_freeN(ps->dm_mtface); - if (ps->dm_mtface_clone) MEM_freeN(ps->dm_mtface_clone); - if (ps->dm_mtface_stencil) MEM_freeN(ps->dm_mtface_stencil); -#endif - } +/* 1 = an undo, -1 is a redo. */ +static void partial_redraw_single_init(ImagePaintPartialRedraw *pr) +{ + pr->x1 = 10000000; + pr->y1 = 10000000; - if (ps->dm_release) - ps->dm->release(ps->dm); + pr->x2 = -1; + pr->y2 = -1; + + pr->enabled = 1; } -/* 1 = an undo, -1 is a redo. */ static void partial_redraw_array_init(ImagePaintPartialRedraw *pr) { int tot = PROJ_BOUNDBOX_SQUARED; while (tot--) { - pr->x1 = 10000000; - pr->y1 = 10000000; - - pr->x2 = -1; - pr->y2 = -1; - - pr->enabled = 1; - + partial_redraw_single_init(pr); pr++; } } @@ -4000,6 +4130,8 @@ static bool project_image_refresh_tagged(ProjPaintState *ps) imapaint_image_update(NULL, projIma->ima, projIma->ibuf, true); redraw = 1; } + + partial_redraw_single_init(pr); } projIma->touch = 0; /* clear for reuse */ @@ -4414,7 +4546,8 @@ static void *do_projectpaint_thread(void *ph_v) const float brush_radius = ps->brush_size; const float brush_radius_sq = brush_radius * brush_radius; /* avoid a square root with every dist comparison */ - short lock_alpha = ELEM(brush->blend, IMB_BLEND_ERASE_ALPHA, IMB_BLEND_ADD_ALPHA) ? 0 : brush->flag & BRUSH_LOCK_ALPHA; + const bool lock_alpha = ELEM(brush->blend, IMB_BLEND_ERASE_ALPHA, IMB_BLEND_ADD_ALPHA) ? + 0 : (brush->flag & BRUSH_LOCK_ALPHA) != 0; LinkNode *smearPixels = NULL; LinkNode *smearPixels_f = NULL; @@ -4818,7 +4951,8 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po /* calculate pivot for rotation around seletion if needed */ if (U.uiflag & USER_ORBIT_SELECTION) { float w[3]; - int side, index; + int index; + int side; index = project_paint_PickFace(ps, pos, w, &side); @@ -4837,7 +4971,7 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po } ups->average_stroke_counter++; - mul_m4_v3(ps->ob->obmat, world); + mul_m4_v3(ps->obmat, world); add_v3_v3(ups->average_stroke_accum, world); ups->last_stroke_valid = true; } @@ -4847,33 +4981,21 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po } -void paint_proj_stroke(const bContext *C, void *pps, const float prev_pos[2], const float pos[2], const bool eraser, float pressure, float distance, float size) +static void paint_proj_stroke_ps( + const bContext *UNUSED(C), void *ps_handle_p, const float prev_pos[2], const float pos[2], + const bool eraser, float pressure, float distance, float size, + /* extra view */ + ProjPaintState *ps + ) { - ProjPaintState *ps = pps; + ProjStrokeHandle *ps_handle = ps_handle_p; Brush *brush = ps->brush; Scene *scene = ps->scene; - int a; ps->brush_size = size; ps->blend = brush->blend; if (eraser) ps->blend = IMB_BLEND_ERASE_ALPHA; - - /* clone gets special treatment here to avoid going through image initialization */ - if (ps->tool == PAINT_TOOL_CLONE && ps->mode == BRUSH_STROKE_INVERT) { - View3D *v3d = ps->v3d; - float *cursor = ED_view3d_cursor3d_get(scene, v3d); - int mval_i[2] = {(int)pos[0], (int)pos[1]}; - - view3d_operator_needs_opengl(C); - - if (!ED_view3d_autodist(scene, ps->ar, v3d, mval_i, cursor, false, NULL)) - return; - - ED_region_tag_redraw(ps->ar); - - return; - } /* handle gradient and inverted stroke color here */ if (ps->tool == PAINT_TOOL_DRAW) { @@ -4894,14 +5016,42 @@ void paint_proj_stroke(const bContext *C, void *pps, const float prev_pos[2], co } } - /* continue adding to existing partial redraw rects until redraw */ - if (!ps->need_redraw) { - for (a = 0; a < ps->image_tot; a++) - partial_redraw_array_init(ps->projImages[a].partRedrawRect); + if (project_paint_op(ps, prev_pos, pos)) { + ps_handle->need_redraw = true; + project_image_refresh_tagged(ps); } +} + + +void paint_proj_stroke( + const bContext *C, void *ps_handle_p, const float prev_pos[2], const float pos[2], + const bool eraser, float pressure, float distance, float size) +{ + int i; + ProjStrokeHandle *ps_handle = ps_handle_p; + + /* clone gets special treatment here to avoid going through image initialization */ + if (ps_handle->is_clone_cursor_pick) { + Scene *scene = ps_handle->scene; + View3D *v3d = CTX_wm_view3d(C); + ARegion *ar = CTX_wm_region(C); + float *cursor = ED_view3d_cursor3d_get(scene, v3d); + int mval_i[2] = {(int)pos[0], (int)pos[1]}; + + view3d_operator_needs_opengl(C); + + if (!ED_view3d_autodist(scene, ar, v3d, mval_i, cursor, false, NULL)) + return; - if (project_paint_op(ps, prev_pos, pos)) - ps->need_redraw = true; + ED_region_tag_redraw(ar); + + return; + } + + for (i = 0; i < ps_handle->ps_views_tot; i++) { + ProjPaintState *ps = ps_handle->ps_views[i]; + paint_proj_stroke_ps(C, ps_handle_p, prev_pos, pos, eraser, pressure, distance, size, ps); + } } @@ -5001,6 +5151,9 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int if (ps->normal_angle_range <= 0.0f) ps->do_mask_normal = false; /* no need to do blending */ + ps->normal_angle__cos = cosf(ps->normal_angle); + ps->normal_angle_inner__cos = cosf(ps->normal_angle_inner); + ps->dither = settings->imapaint.dither; return; @@ -5008,51 +5161,116 @@ static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int void *paint_proj_new_stroke(bContext *C, Object *ob, const float mouse[2], int mode) { - ProjPaintState *ps = MEM_callocN(sizeof(ProjPaintState), "ProjectionPaintState"); + ProjStrokeHandle *ps_handle; + Scene *scene = CTX_data_scene(C); + ToolSettings *settings = scene->toolsettings; + int i; + bool is_multi_view; + char symmetry_flag_views[ARRAY_SIZE(ps_handle->ps_views)] = {0}; - project_state_init(C, ob, ps, mode); + ps_handle = MEM_callocN(sizeof(ProjStrokeHandle), "ProjStrokeHandle"); + ps_handle->scene = scene; + ps_handle->brush = BKE_paint_brush(&settings->imapaint.paint); - if (ps->tool == PAINT_TOOL_CLONE && mode == BRUSH_STROKE_INVERT) { + /* bypass regular stroke logic */ + if ((ps_handle->brush->imagepaint_tool == PAINT_TOOL_CLONE) && + (mode == BRUSH_STROKE_INVERT)) + { view3d_operator_needs_opengl(C); - return ps; + ps_handle->is_clone_cursor_pick = true; + return ps_handle; } - paint_brush_init_tex(ps->brush); + ps_handle->orig_brush_size = BKE_brush_size_get(scene, ps_handle->brush); - ps->source = (ps->tool == PAINT_TOOL_FILL) ? PROJ_SRC_VIEW_FILL : PROJ_SRC_VIEW; + ps_handle->symmetry_flags = settings->imapaint.paint.symmetry_flags & PAINT_SYMM_AXIS_ALL; + ps_handle->ps_views_tot = 1 + (pow_i(2, count_bits_i(ps_handle->symmetry_flags)) - 1); + is_multi_view = (ps_handle->ps_views_tot != 1); - if (ps->ob == NULL || !(ps->ob->lay & ps->v3d->lay)) { - MEM_freeN(ps); - return NULL; + for (i = 0; i < ps_handle->ps_views_tot; i++) { + ProjPaintState *ps = MEM_callocN(sizeof(ProjPaintState), "ProjectionPaintState"); + ps_handle->ps_views[i] = ps; } - ps->orig_brush_size = BKE_brush_size_get(ps->scene, ps->brush); + if (ps_handle->symmetry_flags) { + int index = 0; + + int x = 0; + do { + int y = 0; + do { + int z = 0; + do { + symmetry_flag_views[index++] = ( + (x ? PAINT_SYMM_X : 0) | + (y ? PAINT_SYMM_Y : 0) | + (z ? PAINT_SYMM_Z : 0)); + BLI_assert(index <= ps_handle->ps_views_tot); + } while ((z++ == 0) && (ps_handle->symmetry_flags & PAINT_SYMM_Z)); + } while ((y++ == 0) && (ps_handle->symmetry_flags & PAINT_SYMM_Y)); + } while ((x++ == 0) && (ps_handle->symmetry_flags & PAINT_SYMM_X)); + BLI_assert(index == ps_handle->ps_views_tot); + } + + for (i = 0; i < ps_handle->ps_views_tot; i++) { + ProjPaintState *ps = ps_handle->ps_views[i]; + + project_state_init(C, ob, ps, mode); + + if (ps->ob == NULL || !(ps->ob->lay & ps->v3d->lay)) { + ps_handle->ps_views_tot = i + 1; + goto fail; + } + } /* Don't allow brush size below 2 */ - if (BKE_brush_size_get(ps->scene, ps->brush) < 2) - BKE_brush_size_set(ps->scene, ps->brush, 2 * U.pixelsize); + if (BKE_brush_size_get(scene, ps_handle->brush) < 2) + BKE_brush_size_set(scene, ps_handle->brush, 2 * U.pixelsize); /* allocate and initialize spatial data structures */ - project_paint_begin(ps); - if (ps->dm == NULL) { - MEM_freeN(ps); - return NULL; + for (i = 0; i < ps_handle->ps_views_tot; i++) { + ProjPaintState *ps = ps_handle->ps_views[i]; + + ps->source = (ps->tool == PAINT_TOOL_FILL) ? PROJ_SRC_VIEW_FILL : PROJ_SRC_VIEW; + project_image_refresh_tagged(ps); + + /* re-use! */ + if (i != 0) { + ps->is_shared_user = true; + PROJ_PAINT_STATE_SHARED_MEMCPY(ps, ps_handle->ps_views[0]); + } + + project_paint_begin(ps, is_multi_view, symmetry_flag_views[i]); + + paint_proj_begin_clone(ps, mouse); + + if (ps->dm == NULL) { + goto fail; + return NULL; + } } - paint_proj_begin_clone(ps, mouse); + paint_brush_init_tex(ps_handle->brush); - return ps; + return ps_handle; + + +fail: + for (i = 0; i < ps_handle->ps_views_tot; i++) { + ProjPaintState *ps = ps_handle->ps_views[i]; + MEM_freeN(ps); + } + MEM_freeN(ps_handle); + return NULL; } -void paint_proj_redraw(const bContext *C, void *pps, bool final) +void paint_proj_redraw(const bContext *C, void *ps_handle_p, bool final) { - ProjPaintState *ps = pps; - - if (ps->need_redraw) { - project_image_refresh_tagged(ps); + ProjStrokeHandle *ps_handle = ps_handle_p; - ps->need_redraw = false; + if (ps_handle->need_redraw) { + ps_handle->need_redraw = false; } else if (!final) { return; @@ -5067,19 +5285,34 @@ void paint_proj_redraw(const bContext *C, void *pps, bool final) } } -void paint_proj_stroke_done(void *pps) +void paint_proj_stroke_done(void *ps_handle_p) { - ProjPaintState *ps = pps; - if (ps->tool == PAINT_TOOL_CLONE && ps->mode == BRUSH_STROKE_INVERT) { - MEM_freeN(ps); + ProjStrokeHandle *ps_handle = ps_handle_p; + Scene *scene = ps_handle->scene; + int i; + + if (ps_handle->is_clone_cursor_pick) { + MEM_freeN(ps_handle); return; } - BKE_brush_size_set(ps->scene, ps->brush, ps->orig_brush_size); - paint_brush_exit_tex(ps->brush); + for (i = 1; i < ps_handle->ps_views_tot; i++) { + PROJ_PAINT_STATE_SHARED_CLEAR(ps_handle->ps_views[i]); + } - project_paint_end(ps); - MEM_freeN(ps); + BKE_brush_size_set(scene, ps_handle->brush, ps_handle->orig_brush_size); + + paint_brush_exit_tex(ps_handle->brush); + + for (i = 0; i < ps_handle->ps_views_tot; i++) { + ProjPaintState *ps; + ps = ps_handle->ps_views[i]; + project_paint_end(ps); + MEM_freeN(ps); + + } + + MEM_freeN(ps_handle); } /* use project paint to re-apply an image */ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op) @@ -5159,7 +5392,7 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op) ED_image_undo_restore, ED_image_undo_free, NULL); /* allocate and initialize spatial data structures */ - project_paint_begin(&ps); + project_paint_begin(&ps, false, 0); if (ps.dm == NULL) { BKE_brush_size_set(scene, ps.brush, orig_brush_size); @@ -5241,7 +5474,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - image = BKE_image_add_from_imbuf(ibuf); + image = BKE_image_add_from_imbuf(ibuf, "image_view"); /* Drop reference to ibuf so that the image owns it */ IMB_freeImBuf(ibuf); @@ -5271,8 +5504,6 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op) array[2] = is_ortho ? 1.0f : 0.0f; IDP_AddToGroup(idgroup, view_data); - - rename_id(&image->id, "image_view"); } return OPERATOR_FINISHED; diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index 77059a22de7..fd7e053fea3 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -145,7 +145,7 @@ typedef struct ImagePaintPartialRedraw { int image_texture_paint_poll(struct bContext *C); void *image_undo_find_tile(struct Image *ima, struct ImBuf *ibuf, int x_tile, int y_tile, unsigned short **mask, bool validate); -void *image_undo_push_tile(struct Image *ima, struct ImBuf *ibuf, struct ImBuf **tmpibuf, int x_tile, int y_tile, unsigned short **, bool **valid, bool proj); +void *image_undo_push_tile(struct Image *ima, struct ImBuf *ibuf, struct ImBuf **tmpibuf, int x_tile, int y_tile, unsigned short **, bool **valid, bool proj, bool find_prev); void image_undo_remove_masks(void); void image_undo_init_locks(void); void image_undo_end_locks(void); @@ -160,7 +160,7 @@ void paint_2d_redraw(const bContext *C, void *ps, bool final); void paint_2d_stroke_done(void *ps); void paint_2d_stroke(void *ps, const float prev_mval[2], const float mval[2], const bool eraser, float pressure, float distance, float size); void paint_2d_bucket_fill(const struct bContext *C, const float color[3], struct Brush *br, const float mouse_init[2], void *ps); -void paint_2d_gradient_fill (const struct bContext *C, struct Brush *br, const float mouse_init[2], const float mouse_final[2], void *ps); +void paint_2d_gradient_fill(const struct bContext *C, struct Brush *br, const float mouse_init[2], const float mouse_final[2], void *ps); void *paint_proj_new_stroke(struct bContext *C, struct Object *ob, const float mouse[2], int mode); void paint_proj_stroke(const struct bContext *C, void *ps, const float prevmval_i[2], const float mval_i[2], const bool eraser, float pressure, float distance, float size); void paint_proj_redraw(const struct bContext *C, void *pps, bool final); diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index f5a65be880e..f0963cae1ce 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -1015,7 +1015,7 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str return false; } -static void paint_stroke_line_constrain (PaintStroke *stroke, float mouse[2]) +static void paint_stroke_line_constrain(PaintStroke *stroke, float mouse[2]) { if (stroke->constrain_line) { float line[2]; diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index b19cced2f8e..f1edf8a5fd9 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -379,7 +379,7 @@ static int imapaint_pick_face(ViewContext *vc, const int mval[2], unsigned int * return 0; /* sample only on the exact position */ - *r_index = view3d_sample_backbuf(vc, mval[0], mval[1]); + *r_index = ED_view3d_backbuf_sample(vc, mval[0], mval[1]); if ((*r_index) == 0 || (*r_index) > (unsigned int)totpoly) { return 0; diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 9bca0fd2976..1a31442faf4 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -209,7 +209,7 @@ static void do_shared_vertex_tesscol(Mesh *me, bool *mfacetag) { /* if no mcol: do not do */ /* if tface: only the involved faces, otherwise all */ - const int use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL); + const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; MFace *mface; int a; short *scolmain, *scol; @@ -280,7 +280,7 @@ static void do_shared_vertex_tesscol(Mesh *me, bool *mfacetag) static void do_shared_vertexcol(Mesh *me, bool *mlooptag, bool *mfacetag, const bool do_tessface) { - const int use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL); + const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; MPoly *mp; int (*scol)[4]; int i, j; @@ -878,7 +878,7 @@ static int sample_backbuf_area(ViewContext *vc, int *indexar, int totface, int x * brushes with size > 64, why is this here? */ /*if (size > 64.0) size = 64.0;*/ - ibuf = view3d_read_backbuf(vc, x - size, y - size, x + size, y + size); + ibuf = ED_view3d_backbuf_read(vc, x - size, y - size, x + size, y + size); if (ibuf) { unsigned int *rt = ibuf->rect; @@ -1091,7 +1091,7 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *even me = BKE_mesh_from_object(vc.obact); if (me && me->dvert && vc.v3d && vc.rv3d) { - const int use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; + const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; int v_idx_best = -1; unsigned int index; @@ -1177,7 +1177,7 @@ static EnumPropertyItem *weight_paint_sample_enum_itemf(bContext *C, PointerRNA if (me && me->dvert && vc.v3d && vc.rv3d && vc.obact->defbase.first) { const int defbase_tot = BLI_listbase_count(&vc.obact->defbase); - const int use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; + const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; int *groups = MEM_callocN(defbase_tot * sizeof(int), "groups"); bool found = false; unsigned int index; diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 40ef8970d68..1d2f623bf9d 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -4966,6 +4966,9 @@ static int sculpt_symmetrize_exec(bContext *C, wmOperator *UNUSED(op)) sd->symmetrize_direction, 0.00001f); sculpt_dynamic_topology_triangulate(ss->bm); + /* bisect operator flags edges (keep tags clean for edge queue) */ + BM_mesh_elem_hflag_disable_all(ss->bm, BM_EDGE, BM_ELEM_TAG, false); + /* Finish undo */ BM_log_all_added(ss->bm, ss->bm_log); sculpt_undo_push_end(); diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index bce9a375091..8a3b48125d0 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -51,6 +51,7 @@ #include "BKE_global.h" #include "BKE_main.h" #include "BKE_report.h" +#include "BKE_library.h" #include "BKE_packedFile.h" #include "BKE_scene.h" #include "BKE_sound.h" @@ -105,8 +106,9 @@ static int sound_open_exec(bContext *C, wmOperator *op) if (!op->customdata) sound_open_init(C, op); - if (sound == NULL || sound->playback_handle == NULL) { + if (sound->playback_handle == NULL) { if (op->customdata) MEM_freeN(op->customdata); + BKE_libblock_free(bmain, sound); BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index 73091e7f261..bc42f1dd5bb 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -59,6 +59,7 @@ #include "RNA_access.h" +#include "ED_buttons.h" #include "ED_armature.h" #include "ED_screen.h" #include "ED_physics.h" @@ -1179,3 +1180,33 @@ ID *buttons_context_id_path(const bContext *C) return NULL; } + +void ED_buttons_id_unref(SpaceButs *sbuts, const ID *id) +{ + if (sbuts->pinid == id) { + sbuts->pinid = NULL; + sbuts->flag &= ~SB_PIN_CONTEXT; + } + + if (sbuts->path) { + ButsContextPath *path = sbuts->path; + int i; + + for (i = 0; i < path->len; i++) { + if (path->ptr[i].id.data == id) { + break; + } + } + + if (i == path->len) { + /* pass */ + } + else if (i == 0) { + MEM_SAFE_FREE(sbuts->path); + } + else { + memset(&path->ptr[i], 0, sizeof(path->ptr[i]) * (path->len - i)); + path->len = i; + } + } +} diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index 6c55d8d034e..d0210025183 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -1123,7 +1123,9 @@ static void draw_plane_marker_ex(SpaceClip *sc, Scene *scene, MovieTrackingPlane { bool tiny = (sc->flag & SC_SHOW_TINY_MARKER) != 0; bool is_selected_track = (plane_track->flag & SELECT) != 0; - bool draw_plane_quad = plane_track->image == NULL || plane_track->image_opacity == 0.0f; + const bool has_image = plane_track->image != NULL && + BKE_image_has_ibuf(plane_track->image, NULL); + const bool draw_plane_quad = !has_image || plane_track->image_opacity == 0.0f; float px[2]; if (draw_outline) { diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index 17783e1412d..1d398177d9f 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -658,7 +658,7 @@ void CLIP_OT_view_zoom(wmOperatorType *ot) ot->poll = ED_space_clip_view_clip_poll; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; /* properties */ prop = RNA_def_float(ot->srna, "factor", 0.0f, -FLT_MAX, FLT_MAX, "Factor", diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c index 5f919c9b51d..48f8f587106 100644 --- a/source/blender/editors/space_clip/clip_utils.c +++ b/source/blender/editors/space_clip/clip_utils.c @@ -177,9 +177,7 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track) MovieTracking *tracking = &clip->tracking; MovieTrackingStabilization *stab = &tracking->stabilization; MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking); - MovieTrackingPlaneTrack *plane_track, *next_plane_track; ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking); - ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking); bool has_bundle = false, update_stab = false; char track_name_escaped[MAX_NAME], prefix[MAX_NAME * 2]; @@ -197,49 +195,7 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track) has_bundle = true; /* Make sure no plane will use freed track */ - for (plane_track = plane_tracks_base->first; - plane_track; - plane_track = next_plane_track) - { - bool found = false; - int i; - - next_plane_track = plane_track->next; - - for (i = 0; i < plane_track->point_tracksnr; i++) { - if (plane_track->point_tracks[i] == track) { - found = true; - break; - } - } - - if (!found) { - continue; - } - - if (plane_track->point_tracksnr > 4) { - int track_index; - MovieTrackingTrack **new_point_tracks; - - new_point_tracks = MEM_mallocN(sizeof(*new_point_tracks) * plane_track->point_tracksnr, - "new point tracks array"); - - for (i = 0, track_index = 0; i < plane_track->point_tracksnr; i++) { - if (plane_track->point_tracks[i] != track) { - new_point_tracks[track_index++] = plane_track->point_tracks[i]; - } - } - - MEM_freeN(plane_track->point_tracks); - plane_track->point_tracks = new_point_tracks; - plane_track->point_tracksnr--; - } - else { - /* Delete planes with less than 3 point tracks in it. */ - BKE_tracking_plane_track_free(plane_track); - BLI_freelinkN(plane_tracks_base, plane_track); - } - } + BKE_tracking_plane_tracks_remove_point_track(tracking, track); /* Delete f-curves associated with the track (such as weight, i.e.) */ BLI_strescape(track_name_escaped, track->name, sizeof(track_name_escaped)); diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index fc2c0d3d45c..5ba82f7f71f 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -206,7 +206,7 @@ static void clip_scopes_tag_refresh(ScrArea *sa) if (sc->mode != SC_MODE_TRACKING) return; - /* only while proeprties are visible */ + /* only while properties are visible */ for (ar = sa->regionbase.first; ar; ar = ar->next) { if (ar->regiontype == RGN_TYPE_UI && ar->flag & RGN_FLAG_HIDDEN) return; diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index db8881a865e..538c1a4e5ea 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -825,12 +825,8 @@ static void apply_mouse_slide(bContext *C, SlideMarkerData *data) plane_track = plane_track->next) { if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) { - int i; - for (i = 0; i < plane_track->point_tracksnr; i++) { - if (plane_track->point_tracks[i] == data->track) { - BKE_tracking_track_plane_from_existing_motion(plane_track, framenr); - break; - } + if (BKE_tracking_plane_track_has_point_track(plane_track, data->track)) { + BKE_tracking_track_plane_from_existing_motion(plane_track, framenr); } } } @@ -1070,7 +1066,7 @@ void CLIP_OT_slide_marker(wmOperatorType *ot) ot->modal = slide_marker_modal; /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING; /* properties */ RNA_def_float_vector(ot->srna, "offset", 2, NULL, -FLT_MAX, FLT_MAX, @@ -1883,7 +1879,7 @@ void CLIP_OT_clear_track_path(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* proeprties */ + /* properties */ RNA_def_enum(ot->srna, "action", clear_path_actions, TRACK_CLEAR_REMAINED, "Action", "Clear action to execute"); RNA_def_boolean(ot->srna, "clear_active", 0, "Clear Active", "Clear active track only instead of all selected tracks"); } @@ -3117,6 +3113,12 @@ static int join_tracks_exec(bContext *C, wmOperator *op) if (tracking->stabilization.rot_track == track) tracking->stabilization.rot_track = act_track; + /* TODO(sergey): Re-evaluate planes with auto-key. */ + BKE_tracking_plane_tracks_replace_point_track(tracking, + track, + act_track); + + BKE_tracking_track_free(track); BLI_freelinkN(tracksbase, track); } @@ -4181,7 +4183,7 @@ void CLIP_OT_slide_plane_marker(wmOperatorType *ot) ot->modal = slide_plane_marker_modal; /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING; } /********************** Insert track keyframe operator *********************/ diff --git a/source/blender/editors/space_clip/tracking_select.c b/source/blender/editors/space_clip/tracking_select.c index 0b29c253f3a..8a2bf17c667 100644 --- a/source/blender/editors/space_clip/tracking_select.c +++ b/source/blender/editors/space_clip/tracking_select.c @@ -997,6 +997,6 @@ void CLIP_OT_select_grouped(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - /* proeprties */ + /* properties */ RNA_def_enum(ot->srna, "group", select_group_items, TRACK_CLEAR_REMAINED, "Action", "Clear action to execute"); } diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index a6f3a73841e..d5b9c169192 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -307,10 +307,10 @@ static void file_draw_string(int sx, int sy, const char *string, float width, in /* no text clipping needed, UI_fontstyle_draw does it but is a bit too strict (for buttons it works) */ rect.xmin = sx; - rect.xmax = (int)(sx + ceil(width + 4.0f)); + rect.xmax = (int)(sx + ceil(width + 5.0f / UI_DPI_FAC)); rect.ymin = sy - height; rect.ymax = sy; - + UI_fontstyle_draw(&fs, &rect, fname); } @@ -329,6 +329,7 @@ static void file_draw_preview(uiBlock *block, struct direntry *file, int sx, int float fx, fy; float dx, dy; int xco, yco; + float ui_imbx, ui_imby; float scaledx, scaledy; float scale; int ex, ey; @@ -336,23 +337,26 @@ static void file_draw_preview(uiBlock *block, struct direntry *file, int sx, int BLI_assert(imb != NULL); - if ((imb->x * UI_DPI_FAC > layout->prv_w) || - (imb->y * UI_DPI_FAC > layout->prv_h)) + ui_imbx = imb->x * UI_DPI_FAC; + ui_imby = imb->y * UI_DPI_FAC; + /* Unlike thumbnails, icons are not scaled up. */ + if (((ui_imbx > layout->prv_w) || (ui_imby > layout->prv_h)) || + (!is_icon && ((ui_imbx < layout->prv_w) || (ui_imby < layout->prv_h)))) { if (imb->x > imb->y) { scaledx = (float)layout->prv_w; - scaledy = ( (float)imb->y / (float)imb->x) * layout->prv_w; + scaledy = ((float)imb->y / (float)imb->x) * layout->prv_w; scale = scaledx / imb->x; } else { scaledy = (float)layout->prv_h; - scaledx = ( (float)imb->x / (float)imb->y) * layout->prv_h; + scaledx = ((float)imb->x / (float)imb->y) * layout->prv_h; scale = scaledy / imb->y; } } else { - scaledx = (float)imb->x * UI_DPI_FAC; - scaledy = (float)imb->y * UI_DPI_FAC; + scaledx = ui_imbx; + scaledy = ui_imby; scale = UI_DPI_FAC; } diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 87e6183f4f8..2853ee9c053 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -1349,7 +1349,7 @@ static void thumbnails_startjob(void *tjv, short *stop, short *do_update, float else if (limg->flags & FILE_TYPE_FTFONT) { source = THB_SOURCE_FONT; } - limg->img = IMB_thumb_manage(limg->path, THB_NORMAL, source); + limg->img = IMB_thumb_manage(limg->path, THB_LARGE, source); *do_update = true; PIL_sleep_ms(10); limg = limg->next; diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 6858f536e92..82409c9ecb4 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -102,6 +102,8 @@ short ED_fileselect_set_params(SpaceFile *sfile) /* set path to most recently opened .blend */ BLI_split_dirfile(G.main->name, sfile->params->dir, sfile->params->file, sizeof(sfile->params->dir), sizeof(sfile->params->file)); sfile->params->filter_glob[0] = '\0'; + /* set the default thumbnails size */ + sfile->params->thumbnail_size = 128; } params = sfile->params; @@ -527,8 +529,8 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar) layout->textheight = textheight; if (params->display == FILE_IMGDISPLAY) { - layout->prv_w = 4.8f * UI_UNIT_X; - layout->prv_h = 4.8f * UI_UNIT_Y; + layout->prv_w = ((float)params->thumbnail_size / 20.0f) * UI_UNIT_X; + layout->prv_h = ((float)params->thumbnail_size / 20.0f) * UI_UNIT_Y; layout->tile_border_x = 0.3f * UI_UNIT_X; layout->tile_border_y = 0.3f * UI_UNIT_X; layout->prv_border_x = 0.3f * UI_UNIT_X; diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c index c6ee6875403..fdf7b458865 100644 --- a/source/blender/editors/space_file/fsmenu.c +++ b/source/blender/editors/space_file/fsmenu.c @@ -565,7 +565,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) pathString = CFURLCopyFileSystemPath(cfURL, kCFURLPOSIXPathStyle); - if (pathString == NULL || !CFStringGetCString(pathString, line, sizeof(line), kCFStringEncodingASCII)) + if (pathString == NULL || !CFStringGetCString(pathString, line, sizeof(line), kCFStringEncodingUTF8)) continue; /* Exclude "all my files" as it makes no sense in blender fileselector */ diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index c398d32dad5..e52eea248ed 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -312,10 +312,11 @@ static void ui_imageuser_slot_menu(bContext *UNUSED(C), uiLayout *layout, void * static const char *ui_imageuser_layer_fake_name(RenderResult *rr) { - if (RE_RenderViewGetRectf(rr, 0)) { + RenderView *rv = RE_RenderViewGetById(rr, 0); + if (rv->rectf) { return IFACE_("Composite"); } - else if (RE_RenderViewGetRect32(rr, 0)) { + else if (rv->rect32) { return IFACE_("Sequence"); } else { @@ -580,7 +581,7 @@ static void image_multi_decpass_cb(bContext *C, void *rr_v, void *iuser_v) ImageUser *iuser = iuser_v; RenderLayer *rl; RenderPass *rp; - RenderPass *prev= NULL; + RenderPass *prev = NULL; int layer = iuser->layer; if (RE_HasFakeLayer(rr)) @@ -728,12 +729,12 @@ static void uiblock_layer_pass_buttons(uiLayout *layout, Image *image, RenderRes } } -static void uiblock_layer_pass_arrow_buttons(uiLayout *layout, Image *image, RenderResult *rr, ImageUser *iuser, short *render_slot) +static void uiblock_layer_pass_arrow_buttons(uiLayout *layout, Image *image, RenderResult *rr, ImageUser *iuser, + int menus_width, short *render_slot) { uiBlock *block = uiLayoutGetBlock(layout); uiLayout *row; uiBut *but; - const float dpi_fac = UI_DPI_FAC; row = uiLayoutRow(layout, true); @@ -750,7 +751,7 @@ static void uiblock_layer_pass_arrow_buttons(uiLayout *layout, Image *image, Ren but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_TRIA_RIGHT, 0, 0, 0.90f * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Next Layer")); UI_but_func_set(but, image_multi_inclay_cb, rr, iuser); - uiblock_layer_pass_buttons(row, image, rr, iuser, 230 * dpi_fac, render_slot); + uiblock_layer_pass_buttons(row, image, rr, iuser, menus_width, render_slot); /* decrease, increase arrows */ but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_TRIA_LEFT, 0, 0, 0.85f * UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Previous Pass")); @@ -867,10 +868,17 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char else if (ima->type == IMA_TYPE_R_RESULT) { /* browse layer/passes */ RenderResult *rr; + const float dpi_fac = UI_DPI_FAC; + const int menus_width = 230 * dpi_fac; /* use BKE_image_acquire_renderresult so we get the correct slot in the menu */ rr = BKE_image_acquire_renderresult(scene, ima); - uiblock_layer_pass_arrow_buttons(layout, ima, rr, iuser, &ima->render_slot); + if (rr) { + uiblock_layer_pass_arrow_buttons(layout, ima, rr, iuser, menus_width, &ima->render_slot); + } + else { + uiblock_layer_pass_buttons(layout, ima, rr, iuser, menus_width, &ima->render_slot); + } BKE_image_release_renderresult(scene, ima); } } @@ -903,7 +911,8 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char /* multilayer? */ if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) { - uiblock_layer_pass_arrow_buttons(layout, ima, ima->rr, iuser, NULL); + const float dpi_fac = UI_DPI_FAC; + uiblock_layer_pass_arrow_buttons(layout, ima, ima->rr, iuser, 230 * dpi_fac, NULL); } else if (ima->source != IMA_SRC_GENERATED) { if (compact == 0) { @@ -1211,12 +1220,20 @@ void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser /* render layers and passes */ if (ima && iuser) { - const float dpi_fac = UI_DPI_FAC; RenderResult *rr; + const float dpi_fac = UI_DPI_FAC; + const int menus_width = 160 * dpi_fac; + const bool is_render_result = (ima->type == IMA_TYPE_R_RESULT); /* use BKE_image_acquire_renderresult so we get the correct slot in the menu */ rr = BKE_image_acquire_renderresult(scene, ima); - uiblock_layer_pass_buttons(layout, ima, rr, iuser, 160 * dpi_fac, (ima->type == IMA_TYPE_R_RESULT) ? &ima->render_slot : NULL); + if (rr && is_render_result) { + uiblock_layer_pass_arrow_buttons(layout, ima, rr, iuser, menus_width, &ima->render_slot); + } + else { + uiblock_layer_pass_buttons(layout, ima, rr, iuser, menus_width, + is_render_result ? &ima->render_slot : NULL); + } BKE_image_release_renderresult(scene, ima); } } diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 5a3c3e90618..36419ccd10d 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -836,14 +836,30 @@ void draw_image_main(const bContext *C, ARegion *ar) ibuf = ED_space_image_acquire_buffer(sima, &lock); /* draw the image or grid */ - if (ibuf == NULL) + if (ibuf == NULL) { ED_region_grid_draw(ar, zoomx, zoomy); - else if (sima->flag & SI_DRAW_TILE) - draw_image_buffer_repeated(C, sima, ar, scene, ima, ibuf, zoomx, zoomy); - else if (ima && (ima->tpageflag & IMA_TILES)) - draw_image_buffer_tiled(sima, ar, scene, ima, ibuf, 0.0f, 0.0, zoomx, zoomy); - else - draw_image_buffer(C, sima, ar, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy); + } + else { + + if (sima->flag & SI_DRAW_TILE) + draw_image_buffer_repeated(C, sima, ar, scene, ima, ibuf, zoomx, zoomy); + else if (ima && (ima->tpageflag & IMA_TILES)) + draw_image_buffer_tiled(sima, ar, scene, ima, ibuf, 0.0f, 0.0, zoomx, zoomy); + else + draw_image_buffer(C, sima, ar, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy); + + if (sima->flag & SI_DRAW_METADATA) { + int x, y; + rctf frame; + + BLI_rctf_init(&frame, 0.0f, ibuf->x, 0.0f, ibuf->y); + UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y); + + ED_region_image_metadata_draw(x, y, ibuf, frame, zoomx, zoomy); + } + } + + ED_space_image_release_buffer(sima, ibuf, lock); /* paint helpers */ if (show_paint) @@ -866,8 +882,6 @@ void draw_image_main(const bContext *C, ARegion *ar) } #endif - 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_ops.c b/source/blender/editors/space_image/image_ops.c index 756f90fe560..75e6f77ba49 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -378,7 +378,7 @@ void IMAGE_OT_view_pan(wmOperatorType *ot) ot->poll = space_image_main_area_poll; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER | OPTYPE_LOCK_BYPASS; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_LOCK_BYPASS; /* properties */ RNA_def_float_vector(ot->srna, "offset", 2, NULL, -FLT_MAX, FLT_MAX, @@ -594,7 +594,7 @@ void IMAGE_OT_view_zoom(wmOperatorType *ot) ot->poll = space_image_main_area_poll; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER | OPTYPE_LOCK_BYPASS; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_LOCK_BYPASS; /* properties */ prop = RNA_def_float(ot->srna, "factor", 0.0f, -FLT_MAX, FLT_MAX, "Factor", @@ -1672,6 +1672,7 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI goto cleanup; } } + BKE_imbuf_stamp_info(rr, ibuf); } /* fancy multiview OpenEXR */ @@ -1693,6 +1694,7 @@ static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI } else { colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf); + IMB_metadata_copy(colormanaged_ibuf, ibuf); ok = BKE_imbuf_write_as(colormanaged_ibuf, simopts->filepath, imf, save_copy); save_imbuf_post(ibuf, colormanaged_ibuf); } @@ -1931,7 +1933,7 @@ static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op) uiLayout *layout = op->layout; ImageFormatData *imf = op->customdata; PointerRNA imf_ptr, ptr; - const bool is_multiview = RNA_boolean_get(op->ptr, "use_multiview"); + const bool is_multiview = RNA_boolean_get(op->ptr, "show_multiview"); /* image template */ RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr); @@ -1943,7 +1945,7 @@ static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op) /* multiview template */ if (is_multiview) - uiTemplateImageFormatViews(layout, &imf_ptr, NULL); + uiTemplateImageFormatViews(layout, &imf_ptr, op->ptr); } static int image_save_as_poll(bContext *C) @@ -2404,7 +2406,7 @@ static int image_invert_exec(bContext *C, wmOperator *op) const bool b = RNA_boolean_get(op->ptr, "invert_b"); const bool a = RNA_boolean_get(op->ptr, "invert_a"); - int i; + size_t i; if (ibuf == NULL) /* TODO: this should actually never happen, but does for render-results -> cleanup */ return OPERATOR_CANCELLED; @@ -2415,13 +2417,13 @@ static int image_invert_exec(bContext *C, wmOperator *op) /* not strictly needed, because we only imapaint_dirty_region to invalidate all tiles * but better do this right in case someone copies this for a tool that uses partial redraw better */ ED_imapaint_clear_partial_redraw(); - ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y); + ED_imapaint_dirty_region(ima, ibuf, 0, 0, ibuf->x, ibuf->y, false); } /* TODO: make this into an IMB_invert_channels(ibuf,r,g,b,a) method!? */ if (ibuf->rect_float) { float *fp = (float *) ibuf->rect_float; - for (i = ibuf->x * ibuf->y; i > 0; i--, fp += 4) { + for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, fp += 4) { if (r) fp[0] = 1.0f - fp[0]; if (g) fp[1] = 1.0f - fp[1]; if (b) fp[2] = 1.0f - fp[2]; @@ -2435,7 +2437,7 @@ static int image_invert_exec(bContext *C, wmOperator *op) else if (ibuf->rect) { char *cp = (char *) ibuf->rect; - for (i = ibuf->x * ibuf->y; i > 0; i--, cp += 4) { + for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, cp += 4) { if (r) cp[0] = 255 - cp[0]; if (g) cp[1] = 255 - cp[1]; if (b) cp[2] = 255 - cp[2]; diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 32584a3a2df..a9a5e601e10 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -683,7 +683,7 @@ static void image_main_area_draw(const bContext *C, ARegion *ar) View2D *v2d = &ar->v2d; //View2DScrollers *scrollers; float col[3]; - + /* XXX not supported yet, disabling for now */ scene->r.scemode &= ~R_COMP_CROP; diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c index 240d8baa6f2..a1f90f16bbf 100644 --- a/source/blender/editors/space_info/info_ops.c +++ b/source/blender/editors/space_info/info_ops.c @@ -134,7 +134,7 @@ static int autopack_toggle_exec(bContext *C, wmOperator *op) G.fileflags &= ~G_AUTOPACK; } else { - packAll(bmain, op->reports); + packAll(bmain, op->reports, true); G.fileflags |= G_AUTOPACK; } @@ -161,7 +161,7 @@ static int pack_all_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); - packAll(bmain, op->reports); + packAll(bmain, op->reports, true); G.fileflags |= G_AUTOPACK; return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index a0dfb285a1c..48a39cd79fc 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -56,6 +56,8 @@ #include "ED_info.h" #include "ED_armature.h" +#include "GPU_extensions.h" + #define MAX_INFO_LEN 512 #define MAX_INFO_NUM_LEN 16 @@ -381,6 +383,7 @@ static void stats_string(Scene *scene) Object *ob = (scene->basact) ? scene->basact->object : NULL; uintptr_t mem_in_use, mmap_in_use; char memstr[MAX_INFO_MEM_LEN]; + char gpumemstr[MAX_INFO_MEM_LEN] = ""; char *s; size_t ofs = 0; @@ -416,11 +419,22 @@ static void stats_string(Scene *scene) /* get memory statistics */ - s = memstr; - ofs += BLI_snprintf(s + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" | Mem:%.2fM"), + ofs = BLI_snprintf(memstr, MAX_INFO_MEM_LEN, IFACE_(" | Mem:%.2fM"), (double)((mem_in_use - mmap_in_use) >> 10) / 1024.0); if (mmap_in_use) - BLI_snprintf(s + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" (%.2fM)"), (double)((mmap_in_use) >> 10) / 1024.0); + BLI_snprintf(memstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" (%.2fM)"), (double)((mmap_in_use) >> 10) / 1024.0); + + if (GPU_mem_stats_supported()) { + int gpu_free_mem, gpu_tot_memory; + + GPU_mem_stats_get(&gpu_tot_memory, &gpu_free_mem); + + ofs = BLI_snprintf(gpumemstr, MAX_INFO_MEM_LEN, IFACE_(" | Free GPU Mem:%.2fM"), (double)((gpu_free_mem)) / 1024.0); + + if (gpu_tot_memory) { + BLI_snprintf(gpumemstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_("/%.2fM"), (double)((gpu_tot_memory)) / 1024.0); + } + } s = stats->infostr; ofs = 0; @@ -447,22 +461,23 @@ static void stats_string(Scene *scene) } ofs += BLI_strncpy_rlen(s + ofs, memstr, MAX_INFO_LEN - ofs); + ofs += BLI_strncpy_rlen(s + ofs, gpumemstr, MAX_INFO_LEN - ofs); } else if (ob && (ob->mode & OB_MODE_POSE)) { - ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Bones:%s/%s %s"), - stats_fmt.totbonesel, stats_fmt.totbone, memstr); + ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Bones:%s/%s %s%s"), + stats_fmt.totbonesel, stats_fmt.totbone, memstr, gpumemstr); } else if (stats_is_object_dynamic_topology_sculpt(ob)) { - ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%s | Tris:%s"), stats_fmt.totvert, - stats_fmt.tottri); + ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%s | Tris:%s%s"), stats_fmt.totvert, + stats_fmt.tottri, gpumemstr); } else { ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, - IFACE_("Verts:%s | Faces:%s | Tris:%s | Objects:%s/%s | Lamps:%s/%s%s"), + IFACE_("Verts:%s | Faces:%s | Tris:%s | Objects:%s/%s | Lamps:%s/%s%s%s"), stats_fmt.totvert, stats_fmt.totface, stats_fmt.tottri, stats_fmt.totobjsel, stats_fmt.totobj, stats_fmt.totlampsel, - stats_fmt.totlamp, memstr); + stats_fmt.totlamp, memstr, gpumemstr); } if (ob) diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 52156a2394e..4d37fcc9276 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -433,7 +433,7 @@ static void nla_draw_strip_text(AnimData *adt, NlaTrack *nlt, NlaStrip *strip, i /* just print the name and the range */ if (strip->flag & NLASTRIP_FLAG_TEMP_META) { - str_len = BLI_snprintf(str, sizeof(str), "%d) Temp-Meta", index); + str_len = BLI_snprintf_rlen(str, sizeof(str), "%d) Temp-Meta", index); } else { str_len = BLI_strncpy_rlen(str, strip->name, sizeof(str)); @@ -490,11 +490,11 @@ static void nla_draw_strip_frames_text(NlaTrack *UNUSED(nlt), NlaStrip *strip, V * while also preserving some accuracy, since we do use floats */ /* start frame */ - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.1f", strip->start); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.1f", strip->start); UI_view2d_text_cache_add(v2d, strip->start - 1.0f, ymaxc + ytol, numstr, numstr_len, col); /* end frame */ - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.1f", strip->end); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.1f", strip->end); UI_view2d_text_cache_add(v2d, strip->end, ymaxc + ytol, numstr, numstr_len, col); } diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 87a64e95e63..e27cb041dc5 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -163,14 +163,14 @@ void ED_node_tag_update_nodetree(Main *bmain, bNodeTree *ntree) ntreeTexCheckCyclics(ntree); } -static int compare_nodes(bNode *a, bNode *b) +static bool compare_nodes(const bNode *a, const bNode *b) { bNode *parent; /* These tell if either the node or any of the parent nodes is selected. * A selected parent means an unselected node is also in foreground! */ - int a_select = (a->flag & NODE_SELECT), b_select = (b->flag & NODE_SELECT); - int a_active = (a->flag & NODE_ACTIVE), b_active = (b->flag & NODE_ACTIVE); + bool a_select = (a->flag & NODE_SELECT) != 0, b_select = (b->flag & NODE_SELECT) != 0; + bool a_active = (a->flag & NODE_ACTIVE) != 0, b_active = (b->flag & NODE_ACTIVE) != 0; /* if one is an ancestor of the other */ /* XXX there might be a better sorting algorithm for stable topological sort, this is O(n^2) worst case */ diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 360087d77c7..ffd51bcc44e 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -740,6 +740,34 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node) } } +void ED_node_id_unref(SpaceNode *snode, const ID *id) +{ + if (GS(id->name) == ID_SCE) { + if (snode->id == id) { + /* nasty DNA logic for SpaceNode: + * ideally should be handled by editor code, but would be bad level call + */ + bNodeTreePath *path, *path_next; + for (path = snode->treepath.first; path; path = path_next) { + path_next = path->next; + MEM_freeN(path); + } + BLI_listbase_clear(&snode->treepath); + + snode->id = NULL; + snode->from = NULL; + snode->nodetree = NULL; + snode->edittree = NULL; + } + } + else if (GS(id->name) == ID_OB) { + if (snode->from == id) { + snode->flag &= ~SNODE_PIN; + snode->from = NULL; + } + } +} + void ED_node_post_apply_transform(bContext *UNUSED(C), bNodeTree *UNUSED(ntree)) { /* XXX This does not work due to layout functions relying on node->block, diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c index b69808d4e81..f1d9d4efcc6 100644 --- a/source/blender/editors/space_node/node_group.c +++ b/source/blender/editors/space_node/node_group.c @@ -456,8 +456,8 @@ static int node_group_separate_selected(bNodeTree *ntree, bNodeTree *ngroup, flo /* add internal links to the ntree */ for (link = ngroup->links.first; link; link = link_next) { - int fromselect = (link->fromnode && (link->fromnode->flag & NODE_SELECT)); - int toselect = (link->tonode && (link->tonode->flag & NODE_SELECT)); + const bool fromselect = (link->fromnode && (link->fromnode->flag & NODE_SELECT)); + const bool toselect = (link->tonode && (link->tonode->flag & NODE_SELECT)); link_next = link->next; if (make_copy) { diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c index dda84eb0cbf..8c5d2d82468 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.c @@ -292,7 +292,7 @@ void NODE_OT_backimage_move(wmOperatorType *ot) ot->cancel = snode_bg_viewmove_cancel; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; } static int backimage_zoom_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index 62cb0bc73cd..de90c417bdd 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -203,12 +203,10 @@ void ED_node_tree_path_get_fixedbuf(SpaceNode *snode, char *value, int max_lengt value[0] = '\0'; for (path = snode->treepath.first, i = 0; path; path = path->next, ++i) { if (i == 0) { - BLI_strncpy(value, path->node_name, max_length); - size = strlen(path->node_name); + size = BLI_strncpy_rlen(value, path->node_name, max_length); } else { - BLI_snprintf(value, max_length, "/%s", path->node_name); - size = strlen(path->node_name) + 1; + size = BLI_snprintf_rlen(value, max_length, "/%s", path->node_name); } max_length -= size; if (max_length <= 0) diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 798dae2cef3..058b8c4de5a 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -39,20 +39,24 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLI_mempool.h" #include "BLF_translation.h" #include "BKE_animsys.h" #include "BKE_context.h" #include "BKE_depsgraph.h" +#include "BKE_global.h" #include "BKE_library.h" #include "BKE_main.h" +#include "BKE_outliner_treehash.h" #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_material.h" #include "BKE_group.h" #include "ED_object.h" +#include "ED_outliner.h" #include "ED_screen.h" #include "ED_keyframing.h" @@ -1952,3 +1956,35 @@ void OUTLINER_OT_group_link(wmOperatorType *ot) /* properties */ RNA_def_string(ot->srna, "object", "Object", MAX_ID_NAME, "Object", "Target Object"); } + +/******** Utils to clear any ref to freed ID... **********/ + +void ED_outliner_id_unref(SpaceOops *so, const ID *id) +{ + /* Some early out checks. */ + if (!TREESTORE_ID_TYPE(id)) { + return; /* ID type is not used by outilner... */ + } + + if (so->search_tse.id == id) { + so->search_tse.id = NULL; + } + + if (so->treestore) { + TreeStoreElem *tselem; + BLI_mempool_iter iter; + bool changed = false; + + BLI_mempool_iternew(so->treestore, &iter); + while ((tselem = BLI_mempool_iterstep(&iter))) { + if (tselem->id == id) { + tselem->id = NULL; + changed = true; + } + } + if (so->treehash && changed) { + /* rebuild hash table, because it depends on ids too */ + BKE_outliner_treehash_rebuild_from_treestore(so->treehash, so->treestore); + } + } +} diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index b4b73a11a14..38672ef14dd 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -57,6 +57,10 @@ typedef struct TreeElement { PointerRNA rnaptr; // RNA Pointer } TreeElement; +#define TREESTORE_ID_TYPE(_id) \ + (ELEM(GS((_id)->name), ID_SCE, ID_LI, ID_OB, ID_ME, ID_CU, ID_MB, ID_MA, ID_TE, ID_IM, ID_LT, ID_LA, ID_CA) || \ + ELEM(GS((_id)->name), ID_KE, ID_WO, ID_SPK, ID_GR, ID_AR, ID_AC, ID_BR, ID_PA, ID_GD, ID_LS)) + /* TreeElement->flag */ #define TE_ACTIVE 1 #define TE_ICONROW 2 diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index e5833103658..66863b8061b 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -427,8 +427,7 @@ static void group_instance_cb(bContext *C, Scene *scene, TreeElement *UNUSED(te) { Group *group = (Group *)tselem->id; - Object *ob = ED_object_add_type(C, OB_EMPTY, scene->cursor, NULL, false, scene->layact); - rename_id(&ob->id, group->id.name + 2); + Object *ob = ED_object_add_type(C, OB_EMPTY, group->id.name + 2, scene->cursor, NULL, false, scene->layact); ob->dup_group = group; ob->transflag |= OB_DUPLIGROUP; id_lib_extern(&group->id); @@ -1654,9 +1653,14 @@ static int outliner_operation(bContext *C, wmOperator *UNUSED(op), const wmEvent Scene *scene = CTX_data_scene(C); ARegion *ar = CTX_wm_region(C); SpaceOops *soops = CTX_wm_space_outliner(C); + uiBut *but = UI_context_active_but_get(C); TreeElement *te; float fmval[2]; + if (but) { + UI_but_tooltip_timer_remove(C, but); + } + UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]); for (te = soops->tree.first; te; te = te->next) { diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index 17a6e952ee1..4b07c400220 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -855,6 +855,11 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i return NULL; } + if (type == 0) { + /* Zero type means real ID, ensure we do not get non-outliner ID types here... */ + BLI_assert(TREESTORE_ID_TYPE(id)); + } + te = MEM_callocN(sizeof(TreeElement), "tree elem"); /* add to the visual tree */ BLI_addtail(lb, te); diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index 373095d68f9..f4b1afba6c4 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -30,6 +30,7 @@ #include <stdlib.h> #include <math.h> #include <string.h> +#include <ctype.h> #include "MEM_guardedalloc.h" @@ -751,11 +752,94 @@ void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot) RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory"); } +int sequencer_image_seq_get_minmax_frame(wmOperator *op, int sfra, int *r_minframe) +{ + int minframe = INT32_MAX, maxframe = INT32_MIN; + + RNA_BEGIN (op->ptr, itemptr, "files") + { + char *filename = NULL, *filename_stripped; + int frame; + /* just get the first filename */ + filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0); + + if (filename) { + bool is_numeric; + + filename_stripped = filename; + + /* strip numeric extensions */ + while (*filename_stripped && isdigit(*filename_stripped)) { + filename_stripped++; + } + + is_numeric = (filename_stripped != filename && *filename_stripped == '.'); + + if (is_numeric) { + /* was the number really an extension? */ + *filename_stripped = 0; + frame = atoi(filename); + minframe = min_ii(minframe, frame); + maxframe = max_ii(maxframe, frame); + } + + MEM_freeN(filename); + } + } + RNA_END; + + if (minframe == INT32_MAX) { + minframe = sfra; + maxframe = minframe + 1; + } + + *r_minframe = minframe; + + return maxframe - minframe + 1; +} + +void sequencer_image_seq_reserve_frames(wmOperator *op, StripElem *se, int len, int minframe) +{ + int i; + char *filename = NULL, *filename_stripped; + RNA_BEGIN (op->ptr, itemptr, "files") + { + /* just get the first filename */ + filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0); + break; + } + RNA_END; + + filename_stripped = filename; + + if (filename_stripped) { + + /* strip numeric extensions */ + while (*filename_stripped && isdigit(*filename_stripped)) { + filename_stripped++; + } + + /* was the number really an extension? */ + if (*filename_stripped == '.') + filename_stripped++; + else { + filename_stripped = filename; + } + + for (i = 0; i < len; i++, se++) { + BLI_snprintf(se->name, sizeof(se->name), "%04d.%s", minframe + i, filename_stripped); + } + + MEM_freeN(filename); + } +} + + /* add image operator */ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) { + int minframe; /* cant use the generic function for this */ - Scene *scene = CTX_data_scene(C); /* only for sound */ Editing *ed = BKE_sequencer_editing_get(scene, true); SeqLoadInfo seq_load; @@ -763,11 +847,17 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) Strip *strip; StripElem *se; + const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders"); seq_load_operator_info(&seq_load, op); /* images are unique in how they handle this - 1 per strip elem */ - seq_load.len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files")); + if (use_placeholders) { + seq_load.len = sequencer_image_seq_get_minmax_frame(op, seq_load.start_frame, &minframe); + } + else { + seq_load.len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files")); + } if (seq_load.len == 0) return OPERATOR_CANCELLED; @@ -775,20 +865,24 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) if (seq_load.flag & SEQ_LOAD_REPLACE_SEL) ED_sequencer_deselect_all(scene); - /* main adding function */ seq = BKE_sequencer_add_image_strip(C, ed->seqbasep, &seq_load); strip = seq->strip; se = strip->stripdata; - RNA_BEGIN (op->ptr, itemptr, "files") - { - char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0); - BLI_strncpy(se->name, filename, sizeof(se->name)); - MEM_freeN(filename); - se++; + if (use_placeholders) { + sequencer_image_seq_reserve_frames(op, se, seq_load.len, minframe); + } + else { + RNA_BEGIN (op->ptr, itemptr, "files") + { + char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0); + BLI_strncpy(se->name, filename, sizeof(se->name)); + MEM_freeN(filename); + se++; + } + RNA_END; } - RNA_END; if (seq_load.len == 1) { if (seq_load.start_frame < seq_load.end_frame) { @@ -861,6 +955,8 @@ void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot) WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE, FILE_SPECIAL, FILE_OPENFILE, WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH | WM_FILESEL_FILES, FILE_DEFAULTDISPLAY); sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_ENDFRAME); + + RNA_def_boolean(ot->srna, "use_placeholders", false, "Use Placeholders", "Use placeholders for missing frames of the strip"); } diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index baadc28cd65..0c811ca1af7 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -63,6 +63,7 @@ #include "ED_markers.h" #include "ED_mask.h" #include "ED_sequencer.h" +#include "ED_screen.h" #include "ED_space_api.h" #include "UI_interface.h" @@ -425,12 +426,12 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_cla size_t numstr_len; if (direction == SEQ_LEFTHANDLE) { - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", seq->startdisp); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", seq->startdisp); x1 = rx1; y1 -= 0.45f; } else { - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", seq->enddisp - 1); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", seq->enddisp - 1); x1 = x2 - handsize_clamped * 0.75f; y1 = y2 + 0.05f; } @@ -980,6 +981,76 @@ static void sequencer_display_size(Scene *scene, SpaceSeq *sseq, float r_viewrec } } +static void sequencer_draw_gpencil(const bContext *C) +{ + /* draw grease-pencil (image aligned) */ + ED_gpencil_draw_2dimage(C); + + /* ortho at pixel level */ + UI_view2d_view_restore(C); + + /* draw grease-pencil (screen aligned) */ + ED_gpencil_draw_view2d(C, 0); +} + +/* draws content borders plus safety borders if needed */ +static void sequencer_draw_borders(const SpaceSeq *sseq, const View2D *v2d, const Scene *scene) +{ + float x1 = v2d->tot.xmin; + float y1 = v2d->tot.ymin; + float x2 = v2d->tot.xmax; + float y2 = v2d->tot.ymax; + + /* border */ + setlinestyle(3); + + UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 1.0, 0); + + glBegin(GL_LINE_LOOP); + glVertex2f(x1 - 0.5f, y1 - 0.5f); + glVertex2f(x1 - 0.5f, y2 + 0.5f); + glVertex2f(x2 + 0.5f, y2 + 0.5f); + glVertex2f(x2 + 0.5f, y1 - 0.5f); + glEnd(); + + /* safety border */ + if (sseq->flag & SEQ_SHOW_SAFE_MARGINS) { + UI_draw_safe_areas( + x1, x2, y1, y2, + scene->safe_areas.title, + scene->safe_areas.action); + + if (sseq->flag & SEQ_SHOW_SAFE_CENTER) { + UI_draw_safe_areas( + x1, x2, y1, y2, + scene->safe_areas.title_center, + scene->safe_areas.action_center); + } + } + + setlinestyle(0); +} + +/* draws checkerboard background for transparent content */ +static void sequencer_draw_background(const SpaceSeq *sseq, View2D *v2d, const float viewrect[2]) +{ + /* setting up the view */ + UI_view2d_totRect_set(v2d, viewrect[0] + 0.5f, viewrect[1] + 0.5f); + UI_view2d_curRect_validate(v2d); + UI_view2d_view_ortho(v2d); + + /* only draw alpha for main buffer */ + if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { + if (sseq->flag & SEQ_USE_ALPHA) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + fdrawcheckerboard(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax); + glColor4f(1.0, 1.0, 1.0, 1.0); + } + } +} + void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq, int cfra, int frame_ofs, bool draw_overlay, bool draw_backdrop) { struct Main *bmain = CTX_data_main(C); @@ -996,7 +1067,9 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq const bool is_imbuf = ED_space_sequencer_check_show_imbuf(sseq); int format, type; bool glsl_used = false; + const bool draw_gpencil = ((sseq->flag & SEQ_SHOW_GPENCIL) && sseq->gpd); const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME}; + bool draw_metadata = false; if (G.is_rendering == false && (scene->r.seq_flag & R_SEQ_GL_PREV) == 0) { /* stop all running jobs, except screen one. currently previews frustrate Render @@ -1018,6 +1091,9 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq glClear(GL_COLOR_BUFFER_BIT); } + /* without this colors can flicker from previous opengl state */ + glColor4ub(255, 255, 255, 255); + /* only initialize the preview if a render is in progress */ if (G.is_rendering) return; @@ -1029,15 +1105,24 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq /* for now we only support Left/Right */ ibuf = sequencer_ibuf_get(bmain, scene, sseq, cfra, frame_ofs, names[sseq->multiview_eye]); - if (ibuf == NULL) - return; + if ((ibuf == NULL) || + (ibuf->rect == NULL && ibuf->rect_float == NULL)) + { + /* gpencil can also be drawn if no imbuf is invalid */ + if (draw_gpencil && is_imbuf) { + sequencer_display_size(scene, sseq, viewrect); + + sequencer_draw_background(sseq, v2d, viewrect); + sequencer_draw_borders(sseq, v2d, scene); - if (ibuf->rect == NULL && ibuf->rect_float == NULL) + sequencer_draw_gpencil(C); + } return; + } sequencer_display_size(scene, sseq, viewrect); - if (sseq->mainb != SEQ_DRAW_IMG_IMBUF || sseq->zebra != 0) { + if (!draw_backdrop && (sseq->mainb != SEQ_DRAW_IMG_IMBUF || sseq->zebra != 0)) { SequencerScopes *scopes = &sseq->scopes; sequencer_check_scopes(scopes, ibuf); @@ -1096,28 +1181,10 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq } } - /* without this colors can flicker from previous opengl state */ - glColor4ub(255, 255, 255, 255); - if (!draw_backdrop) { - UI_view2d_totRect_set(v2d, viewrect[0] + 0.5f, viewrect[1] + 0.5f); - UI_view2d_curRect_validate(v2d); - - /* setting up the view - actual drawing starts here */ - UI_view2d_view_ortho(v2d); - - /* only draw alpha for main buffer */ - if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { - if (sseq->flag & SEQ_USE_ALPHA) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - fdrawcheckerboard(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax); - glColor4f(1.0, 1.0, 1.0, 1.0); - } - } + sequencer_draw_background(sseq, v2d, viewrect); } - + if (scope) { IMB_freeImBuf(ibuf); ibuf = scope; @@ -1238,10 +1305,12 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq } } else if (draw_backdrop) { - float aspect = BLI_rcti_size_x(&ar->winrct) / (float)BLI_rcti_size_y(&ar->winrct); + float aspect; float image_aspect = viewrect[0] / viewrect[1]; float imagex, imagey; - + + aspect = BLI_rcti_size_x(&ar->winrct) / (float)BLI_rcti_size_y(&ar->winrct); + if (aspect >= image_aspect) { imagex = image_aspect / aspect; imagey = 1.0f; @@ -1250,28 +1319,22 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq imagex = 1.0f; imagey = aspect / image_aspect; } - + glTexCoord2f(0.0f, 0.0f); glVertex2f(-imagex, -imagey); glTexCoord2f(0.0f, 1.0f); glVertex2f(-imagex, imagey); glTexCoord2f(1.0f, 1.0f); glVertex2f(imagex, imagey); glTexCoord2f(1.0f, 0.0f); glVertex2f(imagex, -imagey); } else { + draw_metadata = ((sseq->flag & SEQ_SHOW_METADATA) != 0); + glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin); glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax); glTexCoord2f(1.0f, 1.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymax); glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin); } glEnd(); - - if (draw_backdrop) { - glPopMatrix(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - - } - + glBindTexture(GL_TEXTURE_2D, last_texid); glDisable(GL_TEXTURE_2D); if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) @@ -1286,63 +1349,29 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq if (!scope) IMB_freeImBuf(ibuf); - + + if (draw_metadata) { + ED_region_image_metadata_draw(0.0, 0.0, ibuf, v2d->tot, 1.0, 1.0); + } + if (draw_backdrop) { + glPopMatrix(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); return; } - - if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { - - float x1 = v2d->tot.xmin; - float y1 = v2d->tot.ymin; - float x2 = v2d->tot.xmax; - float y2 = v2d->tot.ymax; - - /* border */ - setlinestyle(3); - - UI_ThemeColorBlendShade(TH_WIRE, TH_BACK, 1.0, 0); - glBegin(GL_LINE_LOOP); - glVertex2f(x1 - 0.5f, y1 - 0.5f); - glVertex2f(x1 - 0.5f, y2 + 0.5f); - glVertex2f(x2 + 0.5f, y2 + 0.5f); - glVertex2f(x2 + 0.5f, y1 - 0.5f); - glEnd(); - - /* safety border */ - if (sseq->flag & SEQ_SHOW_SAFE_MARGINS) { - UI_draw_safe_areas( - x1, x2, y1, y2, - scene->safe_areas.title, - scene->safe_areas.action); - - if (sseq->flag & SEQ_SHOW_SAFE_CENTER) { - UI_draw_safe_areas( - x1, x2, y1, y2, - scene->safe_areas.title_center, - scene->safe_areas.action_center); - } - } - - setlinestyle(0); + if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { + sequencer_draw_borders(sseq, v2d, scene); } - - if (sseq->flag & SEQ_SHOW_GPENCIL) { - if (is_imbuf) { - /* draw grease-pencil (image aligned) */ - ED_gpencil_draw_2dimage(C); - } + + if (draw_gpencil && is_imbuf) { + sequencer_draw_gpencil(C); } - - /* ortho at pixel level */ - UI_view2d_view_restore(C); - - if (sseq->flag & SEQ_SHOW_GPENCIL) { - if (is_imbuf) { - /* draw grease-pencil (screen aligned) */ - ED_gpencil_draw_view2d(C, 0); - } + else { + /* ortho at pixel level */ + UI_view2d_view_restore(C); } diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 138d9b943fc..39023f5c0a3 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -3694,12 +3694,21 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op) Editing *ed = BKE_sequencer_editing_get(scene, false); Sequence *seq = BKE_sequencer_active_get(scene); const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path"); + const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders"); + int minframe; if (seq->type == SEQ_TYPE_IMAGE) { char directory[FILE_MAX]; - const int len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files")); + int len; StripElem *se; + /* need to find min/max frame for placeholders */ + if (use_placeholders) { + len = sequencer_image_seq_get_minmax_frame(op, seq->sfra, &minframe); + } + else { + len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files")); + } if (len == 0) return OPERATOR_CANCELLED; @@ -3717,14 +3726,19 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op) } seq->strip->stripdata = se = MEM_callocN(len * sizeof(StripElem), "stripelem"); - RNA_BEGIN (op->ptr, itemptr, "files") - { - char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0); - BLI_strncpy(se->name, filename, sizeof(se->name)); - MEM_freeN(filename); - se++; + if (use_placeholders) { + sequencer_image_seq_reserve_frames(op, se, len, minframe); + } + else { + RNA_BEGIN (op->ptr, itemptr, "files") + { + char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0); + BLI_strncpy(se->name, filename, sizeof(se->name)); + MEM_freeN(filename); + se++; + } + RNA_END; } - RNA_END; /* reset these else we wont see all the images */ seq->anim_startofs = seq->anim_endofs = 0; @@ -3799,4 +3813,5 @@ void SEQUENCER_OT_change_path(struct wmOperatorType *ot) WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE, FILE_SPECIAL, FILE_OPENFILE, WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH | WM_FILESEL_FILEPATH | WM_FILESEL_FILES, FILE_DEFAULTDISPLAY); + RNA_def_boolean(ot->srna, "use_placeholders", false, "Use Placeholders", "Use placeholders for missing frames of the strip"); } diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h index 78255507321..0158a2d4872 100644 --- a/source/blender/editors/space_sequencer/sequencer_intern.h +++ b/source/blender/editors/space_sequencer/sequencer_intern.h @@ -45,6 +45,8 @@ struct ARegion; struct ARegionType; struct Scene; struct Main; +struct wmOperator; +struct StripElem; /* space_sequencer.c */ struct ARegion *sequencer_has_buttons_region(struct ScrArea *sa); @@ -202,5 +204,9 @@ void SEQUENCER_OT_sample(struct wmOperatorType *ot); /* sequencer_preview.c */ void sequencer_preview_add_sound(const struct bContext *C, struct Sequence *seq); +/* sequencer_add */ +int sequencer_image_seq_get_minmax_frame(struct wmOperator *op, int sfra, int *r_minframe); +void sequencer_image_seq_reserve_frames(struct wmOperator *op, struct StripElem *se, int len, int minframe); + #endif /* __SEQUENCER_INTERN_H__ */ diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 7a7f189b187..769718e1567 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -564,7 +564,10 @@ static void sequencer_preview_area_draw(const bContext *C, ARegion *ar) SpaceSeq *sseq = sa->spacedata.first; Scene *scene = CTX_data_scene(C); wmWindowManager *wm = CTX_wm_manager(C); - int show_split = scene->ed && scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW && sseq->mainb == SEQ_DRAW_IMG_IMBUF; + const bool show_split = ( + scene->ed && + (scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) && + (sseq->mainb == SEQ_DRAW_IMG_IMBUF)); /* XXX temp fix for wrong setting in sseq->mainb */ if (sseq->mainb == SEQ_DRAW_SEQUENCE) sseq->mainb = SEQ_DRAW_IMG_IMBUF; diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index ad8050a50e8..fce864d975f 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -2233,7 +2233,7 @@ void TEXT_OT_scroll(wmOperatorType *ot) ot->poll = text_scroll_poll; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER | OPTYPE_INTERNAL; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_INTERNAL; /* properties */ RNA_def_int(ot->srna, "lines", 1, INT_MIN, INT_MAX, "Lines", "Number of lines to scroll", -100, 100); diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index b1f8d112765..b374ce64319 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -775,7 +775,7 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl) for (a = 0, mp = mface; a < totpoly; a++, mtpoly++, mp++) { short matnr = mp->mat_nr; - int mf_smooth = mp->flag & ME_SMOOTH; + const bool mf_smooth = (mp->flag & ME_SMOOTH) != 0; Material *mat = (me->mat) ? me->mat[matnr] : NULL; int mode = mat ? mat->game.flag : GEMAT_INVISIBLE; @@ -1107,7 +1107,7 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Mesh *me = ob->data; TexMatCallback data = {scene, ob, me, dm}; bool (*set_face_cb)(void *, int); - int glsl, picking = (G.f & G_PICKSEL); + bool glsl, picking = (G.f & G_PICKSEL) != 0; /* face hiding callback depending on mode */ if (ob == scene->obedit) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index bc966345fc5..da1d053657c 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -736,11 +736,7 @@ static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], const float size = ED_view3d_pixel_size(rv3d, co) * (float)U.obcenter_dia * 0.5f; float verts[CIRCLE_RESOL][3]; - /* using gldepthfunc guarantees that it does write z values, - * but not checks for it, so centers remain visible independent order of drawing */ - if (v3d->zbuf) glDepthFunc(GL_ALWAYS); - /* write to near buffer always */ - glDepthRange(0.0, 0.0); + if (v3d->zbuf) glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); if (special_color) { @@ -770,10 +766,9 @@ static void drawcentercircle(View3D *v3d, RegionView3D *rv3d, const float co[3], /* finish up */ glDisableClientState(GL_VERTEX_ARRAY); - glDepthRange(0.0, 1.0); glDisable(GL_BLEND); - if (v3d->zbuf) glDepthFunc(GL_LEQUAL); + if (v3d->zbuf) glEnable(GL_DEPTH_TEST); } /* *********** text drawing for object/particles/armature ************* */ @@ -3373,7 +3368,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe unit->system, B_UNIT_LENGTH, do_split, false); } else { - numstr_len = BLI_snprintf(numstr, sizeof(numstr), conv_float, len_v3v3(v1, v2)); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), conv_float, len_v3v3(v1, v2)); } view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col); @@ -3450,7 +3445,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe angle = angle_normalized_v3v3(no_a, no_b); - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle)); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle)); view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col); } @@ -3475,7 +3470,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe 3, unit->system, B_UNIT_AREA, do_split, false); \ } \ else { \ - numstr_len = BLI_snprintf(numstr, sizeof(numstr), conv_float, area); \ + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), conv_float, area); \ } \ view3d_cached_text_draw_add(vmid, numstr, numstr_len, 0, txt_flag, col); \ } (void)0 @@ -3593,7 +3588,7 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe angle = angle_v3v3v3(v1, v2, v3); - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle)); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle)); interp_v3_v3v3(fvec, vmid, v2_local, 0.8f); view3d_cached_text_draw_add(fvec, numstr, numstr_len, 0, txt_flag, col); } @@ -3624,7 +3619,7 @@ static void draw_em_indices(BMEditMesh *em) UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col); BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", i); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i); view3d_cached_text_draw_add(v->co, numstr, numstr_len, 0, txt_flag, col); } i++; @@ -3636,7 +3631,7 @@ static void draw_em_indices(BMEditMesh *em) UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col); BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", i); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i); mid_v3_v3v3(pos, e->v1->co, e->v2->co); view3d_cached_text_draw_add(pos, numstr, numstr_len, 0, txt_flag, col); } @@ -3650,7 +3645,7 @@ static void draw_em_indices(BMEditMesh *em) BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { BM_face_calc_center_mean(f, pos); - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%d", i); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%d", i); view3d_cached_text_draw_add(pos, numstr, numstr_len, 0, txt_flag, col); } i++; @@ -4226,7 +4221,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D } if (is_obact && BKE_paint_select_vert_test(ob)) { - const int use_depth = (v3d->flag & V3D_ZBUF_SELECT); + const bool use_depth = (v3d->flag & V3D_ZBUF_SELECT) != 0; glColor3f(0.0f, 0.0f, 0.0f); glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE)); @@ -5398,15 +5393,15 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv if (part->draw & PART_DRAW_NUM) { if (a < totpart && (part->draw & PART_DRAW_HEALTH) && (part->phystype == PART_PHYS_BOIDS)) { - numstr_len = BLI_snprintf(val_pos, sizeof(numstr), "%d:%.2f", a, pa_health); + numstr_len = BLI_snprintf_rlen(val_pos, sizeof(numstr), "%d:%.2f", a, pa_health); } else { - numstr_len = BLI_snprintf(val_pos, sizeof(numstr), "%d", a); + numstr_len = BLI_snprintf_rlen(val_pos, sizeof(numstr), "%d", a); } } else { if (a < totpart && (part->draw & PART_DRAW_HEALTH) && (part->phystype == PART_PHYS_BOIDS)) { - numstr_len = BLI_snprintf(val_pos, sizeof(numstr), "%.2f", pa_health); + numstr_len = BLI_snprintf_rlen(val_pos, sizeof(numstr), "%.2f", pa_health); } } @@ -5647,7 +5642,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv for (a = 0, pa = psys->particles; a < totpart; a++, pa++) { float vec_txt[3]; - numstr_len = BLI_snprintf(numstr, sizeof(numstr), "%i", a); + numstr_len = BLI_snprintf_rlen(numstr, sizeof(numstr), "%i", a); /* use worldspace because object matrix is already applied */ mul_v3_m4v3(vec_txt, ob->imat, cache[a]->co); view3d_cached_text_draw_add(vec_txt, numstr, numstr_len, @@ -8031,9 +8026,8 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* don't show smoke before simulation starts, this could be made an option in the future */ if (smd->domain->fluid && CFRA >= smd->domain->point_cache[0]->startframe) { /* get view vector */ - copy_v3_v3(viewnormal, rv3d->viewinv[2]); invert_m4_m4(ob->imat, ob->obmat); - mul_mat3_m4_v3(ob->imat, viewnormal); + mul_v3_mat3_m4v3(viewnormal, ob->imat, rv3d->viewinv[2]); normalize_v3(viewnormal); /* set dynamic boundaries to draw the volume diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c index 50ccde6da01..d6691f431dd 100644 --- a/source/blender/editors/space_view3d/drawvolume.c +++ b/source/blender/editors/space_view3d/drawvolume.c @@ -105,7 +105,7 @@ void draw_smoke_volume(SmokeDomainSettings *sds, Object *ob, float cor[3] = {1.0f, 1.0f, 1.0f}; int gl_depth = 0, gl_blend = 0; - int use_fire = (sds->active_fields & SM_ACTIVE_FIRE); + const bool use_fire = (sds->active_fields & SM_ACTIVE_FIRE) != 0; /* draw slices of smoke is adapted from c++ code authored * by: Johannes Schmid and Ingemar Rask, 2006, johnny@grob.org */ diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 3c4ab7efc56..1a47553ce43 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -1014,7 +1014,7 @@ static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmN break; case NC_GPENCIL: - if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) { + if (wmn->data == ND_DATA || ELEM(wmn->action, NA_EDITED, NA_SELECTED)) { ED_region_tag_redraw(ar); } break; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index fd6288b1601..57b417ef1d7 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -472,7 +472,7 @@ float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit) return v3d->grid * ED_scene_grid_scale(scene, grid_unit); } -static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit) +static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth) { float grid, grid_scale; unsigned char col_grid[3]; @@ -484,7 +484,8 @@ static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit) grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit); grid = gridlines * grid_scale; - glDepthMask(GL_FALSE); + if (!write_depth) + glDepthMask(GL_FALSE); UI_GetThemeColor3ubv(TH_GRID, col_grid); @@ -1327,12 +1328,12 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d) /* do nothing */ } else if ((base && (base->object->mode & OB_MODE_PARTICLE_EDIT)) && - v3d->drawtype > OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT)) + V3D_IS_ZBUF(v3d)) { /* do nothing */ } - else if (scene->obedit && v3d->drawtype > OB_WIRE && - (v3d->flag & V3D_ZBUF_SELECT)) + else if (scene->obedit && + V3D_IS_ZBUF(v3d)) { /* do nothing */ } @@ -1454,14 +1455,23 @@ static void view3d_opengl_read_Z_pixels(ARegion *ar, int x, int y, int w, int h, glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data); } -void view3d_validate_backbuf(ViewContext *vc) +void ED_view3d_backbuf_validate(ViewContext *vc) { if (vc->v3d->flag & V3D_INVALID_BACKBUF) backdrawview3d(vc->scene, vc->ar, vc->v3d); } +/** + * allow for small values [0.5 - 2.5], + * and large values, FLT_MAX by clamping by the area size + */ +int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist) +{ + return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx)); +} + /* samples a single pixel (copied from vpaint) */ -unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y) +unsigned int ED_view3d_backbuf_sample(ViewContext *vc, int x, int y) { unsigned int col; @@ -1469,7 +1479,7 @@ unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y) return 0; } - view3d_validate_backbuf(vc); + ED_view3d_backbuf_validate(vc); view3d_opengl_read_pixels(vc->ar, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col); glReadBuffer(GL_BACK); @@ -1482,7 +1492,7 @@ unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y) } /* reads full rect, converts indices */ -ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax, short ymax) +ImBuf *ED_view3d_backbuf_read(ViewContext *vc, short xmin, short ymin, short xmax, short ymax) { unsigned int *dr, *rd; struct ImBuf *ibuf, *ibuf1; @@ -1501,7 +1511,7 @@ 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); + ED_view3d_backbuf_validate(vc); view3d_opengl_read_pixels(vc->ar, xminc, yminc, @@ -1541,23 +1551,21 @@ ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax, } /* smart function to sample a rect spiralling outside, nice for backbuf selection */ -unsigned int view3d_sample_backbuf_rect(ViewContext *vc, const int mval[2], int size, - unsigned int min, unsigned int max, float *r_dist, short strict, - void *handle, bool (*indextest)(void *handle, unsigned int index)) +unsigned int ED_view3d_backbuf_sample_rect( + ViewContext *vc, const int mval[2], int size, + unsigned int min, unsigned int max, float *r_dist) { struct ImBuf *buf; - unsigned int *bufmin, *bufmax, *tbuf; + const unsigned int *bufmin, *bufmax, *tbuf; int minx, miny; int a, b, rc, nr, amount, dirvec[4][2]; - int distance = 0; unsigned int index = 0; - bool indexok = false; amount = (size - 1) / 2; minx = mval[0] - (amount + 1); miny = mval[1] - (amount + 1); - buf = view3d_read_backbuf(vc, minx, miny, minx + size - 1, miny + size - 1); + buf = ED_view3d_backbuf_read(vc, minx, miny, minx + size - 1, miny + size - 1); if (!buf) return 0; rc = 0; @@ -1575,21 +1583,19 @@ unsigned int view3d_sample_backbuf_rect(ViewContext *vc, const int mval[2], int for (nr = 1; nr <= size; nr++) { for (a = 0; a < 2; a++) { - for (b = 0; b < nr; b++, distance++) { - if (*tbuf && *tbuf >= min && *tbuf < max) { /* we got a hit */ - if (strict) { - indexok = indextest(handle, *tbuf - min + 1); - if (indexok) { - *r_dist = sqrtf((float)distance); - index = *tbuf - min + 1; - goto exit; - } - } - else { - *r_dist = sqrtf((float)distance); /* XXX, this distance is wrong - */ - index = *tbuf - min + 1; /* messy yah, but indices start at 1 */ - goto exit; - } + for (b = 0; b < nr; b++) { + if (*tbuf && *tbuf >= min && *tbuf < max) { + /* we got a hit */ + + /* get x,y pixel coords from the offset + * (manhatten distance in keeping with other screen-based selection) */ + *r_dist = (float)( + abs(((int)(tbuf - buf->rect) % size) - (size / 2)) + + abs(((int)(tbuf - buf->rect) / size) - (size / 2))); + + /* indices start at 1 here */ + index = (*tbuf - min) + 1; + goto exit; } tbuf += (dirvec[rc][0] + dirvec[rc][1]); @@ -1616,17 +1622,19 @@ static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, Ima if ((ima->flag & IMA_IS_STEREO)) { iuser->flag |= IMA_SHOW_STEREO; - if ((scene->r.scemode & R_MULTIVIEW) == 0) + if ((scene->r.scemode & R_MULTIVIEW) == 0) { iuser->multiview_eye = STEREO_LEFT_ID; - - /* show only left or right camera */ - else if (v3d->stereo3d_camera != STEREO_3D_ID) + } + else if (v3d->stereo3d_camera != STEREO_3D_ID) { + /* show only left or right camera */ iuser->multiview_eye = v3d->stereo3d_camera; + } BKE_image_multiview_index(ima, iuser); } - else + else { iuser->flag &= ~IMA_SHOW_STEREO; + } } static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, @@ -2719,7 +2727,7 @@ static void view3d_draw_objects( const bool draw_grids = !draw_offscreen && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0; const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO); /* only draw grids after in solid modes, else it hovers over mesh wires */ - const bool draw_grids_after = draw_grids && draw_floor && (v3d->drawtype > OB_WIRE); + const bool draw_grids_after = draw_grids && draw_floor && (v3d->drawtype > OB_WIRE) && fx; bool do_composite_xray = false; bool xrayclear = true; @@ -2768,8 +2776,8 @@ static void view3d_draw_objects( glMatrixMode(GL_MODELVIEW); glLoadMatrixf(rv3d->viewmat); } - else { - drawfloor(scene, v3d, grid_unit); + else if (!draw_grids_after) { + drawfloor(scene, v3d, grid_unit, true); } } @@ -2847,7 +2855,7 @@ static void view3d_draw_objects( /* perspective floor goes last to use scene depth and avoid writing to depth buffer */ if (draw_grids_after) { - drawfloor(scene, v3d, grid_unit); + drawfloor(scene, v3d, grid_unit, false); } /* must be before xray draw which clears the depth buffer */ @@ -2932,21 +2940,41 @@ static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar) if (glsl) { RegionView3D *rv3d = ar->regiondata; GPUMaterial *gpumat = GPU_material_world(scene, scene->world); + bool material_not_bound; /* calculate full shader for background */ GPU_material_bind(gpumat, 1, 1, 1.0, false, rv3d->viewmat, rv3d->viewinv, rv3d->viewcamtexcofac, (v3d->scenelock != 0)); + material_not_bound = !GPU_material_bound(gpumat); + + if (material_not_bound) { + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glColor4f(0.0f, 0.0f, 0.0f, 1.0f); + } + glEnable(GL_DEPTH_TEST); glDepthFunc(GL_ALWAYS); glShadeModel(GL_SMOOTH); - glBegin(GL_QUADS); + glBegin(GL_TRIANGLE_STRIP); glVertex3f(-1.0, -1.0, 1.0); glVertex3f(1.0, -1.0, 1.0); - glVertex3f(1.0, 1.0, 1.0); glVertex3f(-1.0, 1.0, 1.0); + glVertex3f(1.0, 1.0, 1.0); glEnd(); glShadeModel(GL_FLAT); + if (material_not_bound) { + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + } + GPU_material_unbind(gpumat); glDepthFunc(GL_LEQUAL); @@ -3160,7 +3188,7 @@ void ED_view3d_draw_offscreen( } /* setup view matrices before fx or unbinding the offscreen buffers will cause issues */ - if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL)) + if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && rv3d->persp == RV3D_CAMOB && v3d->camera) view3d_stereo3d_setup_offscreen(scene, v3d, ar, winmat, viewname); else view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat); @@ -3563,7 +3591,7 @@ static bool view3d_stereo3d_active(const bContext *C, Scene *scene, View3D *v3d, if (WM_stereo3d_enabled(win, true) == false) return false; - if ((v3d->camera == NULL) || rv3d->persp != RV3D_CAMOB) + if ((v3d->camera == NULL) || (v3d->camera->type != OB_CAMERA) || rv3d->persp != RV3D_CAMOB) return false; if (scene->r.views_format & SCE_VIEWS_FORMAT_MULTIVIEW) { @@ -3701,7 +3729,7 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3 #endif /* framebuffer fx needed, we need to draw offscreen first */ - if (v3d->fx_settings.fx_flag) { + if (v3d->fx_settings.fx_flag && v3d->drawtype >= OB_SOLID) { GPUFXSettings fx_settings; BKE_screen_gpu_fx_validate(&v3d->fx_settings); fx_settings = v3d->fx_settings; @@ -3714,9 +3742,6 @@ static void view3d_main_area_draw_objects(const bContext *C, Scene *scene, View3 fx_settings.dof = NULL; } - if (v3d->drawtype < OB_SOLID) - fx_settings.ssao = NULL; - do_compositing = GPU_fx_compositor_initialize_passes(rv3d->compositor, &ar->winrct, &ar->drawrct, &fx_settings); } diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 236fefc7088..2ae638b22e4 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -517,6 +517,7 @@ void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, bool do_clip) typedef struct ViewOpsData { /* context pointers (assigned by viewops_data_alloc) */ + Scene *scene; ScrArea *sa; ARegion *ar; View3D *v3d; @@ -589,6 +590,7 @@ static void viewops_data_alloc(bContext *C, wmOperator *op) /* store data */ op->customdata = vod; + vod->scene = CTX_data_scene(C); vod->sa = CTX_wm_area(C); vod->ar = CTX_wm_region(C); vod->v3d = vod->sa->spacedata.first; @@ -1310,7 +1312,7 @@ void VIEW3D_OT_rotate(wmOperatorType *ot) ot->cancel = viewrotate_cancel; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; } /** \name NDOF Utility Functions @@ -2053,7 +2055,7 @@ void VIEW3D_OT_move(wmOperatorType *ot) ot->cancel = viewmove_cancel; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; } /* ************************ viewzoom ******************************** */ @@ -2093,16 +2095,63 @@ void viewzoom_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom"); } -static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my) +static void view_zoom_mouseloc_camera( + Scene *scene, View3D *v3d, + ARegion *ar, float dfac, int mx, int my) { RegionView3D *rv3d = ar->regiondata; + const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom); + const float zoomfac_new = CLAMPIS(zoomfac * (1.0f / dfac), RV3D_CAMZOOM_MIN_FACTOR, RV3D_CAMZOOM_MAX_FACTOR); + const float camzoom_new = BKE_screen_view3d_zoom_from_fac(zoomfac_new); + + + if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) { + float zoomfac_px; + rctf camera_frame_old; + rctf camera_frame_new; + + const float pt_src[2] = {mx, my}; + float pt_dst[2]; + float delta_px[2]; + + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &camera_frame_old, false); + BLI_rctf_translate(&camera_frame_old, ar->winrct.xmin, ar->winrct.ymin); + + rv3d->camzoom = camzoom_new; + CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); + + ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &camera_frame_new, false); + BLI_rctf_translate(&camera_frame_new, ar->winrct.xmin, ar->winrct.ymin); + + BLI_rctf_transform_pt_v(&camera_frame_new, &camera_frame_old, pt_dst, pt_src); + sub_v2_v2v2(delta_px, pt_dst, pt_src); + + /* translate the camera offset using pixel space delta + * mapped back to the camera (same logic as panning in camera view) */ + zoomfac_px = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom) * 2.0f; + + rv3d->camdx += delta_px[0] / (ar->winx * zoomfac_px); + rv3d->camdy += delta_px[1] / (ar->winy * zoomfac_px); + CLAMP(rv3d->camdx, -1.0f, 1.0f); + CLAMP(rv3d->camdy, -1.0f, 1.0f); + } + else { + rv3d->camzoom = camzoom_new; + CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); + } +} + +static void view_zoom_mouseloc_3d(ARegion *ar, float dfac, int mx, int my) +{ + RegionView3D *rv3d = ar->regiondata; + const float dist_new = rv3d->dist * dfac; if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) { float dvec[3]; float tvec[3]; float tpos[3]; float mval_f[2]; - float new_dist; + float zfac; negate_v3_v3(tpos, rv3d->ofs); @@ -2119,105 +2168,133 @@ static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my) negate_v3(tvec); /* Offset to target position and dolly */ - new_dist = rv3d->dist * dfac; - copy_v3_v3(rv3d->ofs, tvec); - rv3d->dist = new_dist; + rv3d->dist = dist_new; /* Calculate final offset */ madd_v3_v3v3fl(rv3d->ofs, tvec, dvec, dfac); } else { - rv3d->dist *= dfac; + rv3d->dist = dist_new; } } - -static void viewzoom_apply(ViewOpsData *vod, const int xy[2], const short viewzoom, const short zoom_invert) +static float viewzoom_scale_value( + const rcti *winrct, + const short viewzoom, + const bool zoom_invert, const bool zoom_invert_force, + const int xy[2], const int xy_orig[2], + const float val, const float val_orig, + double *r_timer_lastdraw) { - float zfac = 1.0; - bool use_cam_zoom; - float dist_range[2]; - - use_cam_zoom = (vod->rv3d->persp == RV3D_CAMOB) && !(vod->rv3d->is_persp && ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)); - - ED_view3d_dist_range_get(vod->v3d, dist_range); - - if (use_cam_zoom) { - float delta; - delta = (xy[0] - vod->origx + xy[1] - vod->origy) / 10.0f; - vod->rv3d->camzoom = vod->camzoom_prev + (zoom_invert ? -delta : delta); - - CLAMP(vod->rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); - } + float zfac; if (viewzoom == USER_ZOOM_CONT) { double time = PIL_check_seconds_timer(); - float time_step = (float)(time - vod->timer_lastdraw); + float time_step = (float)(time - *r_timer_lastdraw); float fac; if (U.uiflag & USER_ZOOM_HORIZ) { - fac = (float)(vod->origx - xy[0]); + fac = (float)(xy_orig[0] - xy[0]); } else { - fac = (float)(vod->origy - xy[1]); + fac = (float)(xy_orig[1] - xy[1]); } - if (zoom_invert) { + if (zoom_invert != zoom_invert_force) { fac = -fac; } /* oldstyle zoom */ zfac = 1.0f + ((fac / 20.0f) * time_step); - vod->timer_lastdraw = time; + *r_timer_lastdraw = time; } else if (viewzoom == USER_ZOOM_SCALE) { /* method which zooms based on how far you move the mouse */ const int ctr[2] = { - BLI_rcti_cent_x(&vod->ar->winrct), - BLI_rcti_cent_y(&vod->ar->winrct), + BLI_rcti_cent_x(winrct), + BLI_rcti_cent_y(winrct), }; - const float len_new = 5 + len_v2v2_int(ctr, xy); - const float len_old = 5 + len_v2v2_int(ctr, &vod->origx); - zfac = vod->dist_prev * ((len_old + 5) / (len_new + 5)) / vod->rv3d->dist; + float len_new = 5 + len_v2v2_int(ctr, xy); + float len_old = 5 + len_v2v2_int(ctr, xy_orig); + + /* intentionally ignore 'zoom_invert' for scale */ + if (zoom_invert_force) { + SWAP(float, len_new, len_old); + } + + zfac = val_orig * (len_old / max_ff(len_new, 1.0f)) / val; } else { /* USER_ZOOM_DOLLY */ - float len1, len2; - + float len_new = 5; + float len_old = 5; + if (U.uiflag & USER_ZOOM_HORIZ) { - len1 = (vod->ar->winrct.xmax - xy[0]) + 5; - len2 = (vod->ar->winrct.xmax - vod->origx) + 5; + len_new += (winrct->xmax - xy[0]); + len_old += (winrct->xmax - xy_orig[0]); } else { - len1 = (vod->ar->winrct.ymax - xy[1]) + 5; - len2 = (vod->ar->winrct.ymax - vod->origy) + 5; - } - if (zoom_invert) { - SWAP(float, len1, len2); + len_new += (winrct->ymax - xy[1]); + len_old += (winrct->ymax - xy_orig[1]); } - - if (use_cam_zoom) { - /* zfac is ignored in this case, see below */ -#if 0 - zfac = vod->camzoom_prev * (2.0f * ((len1 / len2) - 1.0f) + 1.0f) / vod->rv3d->camzoom; -#endif - } - else { - zfac = vod->dist_prev * (2.0f * ((len1 / len2) - 1.0f) + 1.0f) / vod->rv3d->dist; + + if (zoom_invert != zoom_invert_force) { + SWAP(float, len_new, len_old); } + + zfac = val_orig * (2.0f * ((len_new / max_ff(len_old, 1.0f)) - 1.0f) + 1.0f) / val; } - if (!use_cam_zoom) { - if (zfac != 1.0f) { - const float zfac_min = dist_range[0] / vod->rv3d->dist; - const float zfac_max = dist_range[1] / vod->rv3d->dist; - CLAMP(zfac, zfac_min, zfac_max); - if (zfac != 1.0f) { - view_zoom_mouseloc(vod->ar, zfac, vod->oldx, vod->oldy); - } - } + return zfac; +} + +static void viewzoom_apply_camera( + ViewOpsData *vod, const int xy[2], + const short viewzoom, const bool zoom_invert) +{ + float zfac; + float zoomfac_prev = BKE_screen_view3d_zoom_to_fac(vod->camzoom_prev) * 2.0f; + float zoomfac = BKE_screen_view3d_zoom_to_fac(vod->rv3d->camzoom) * 2.0f; + + zfac = viewzoom_scale_value( + &vod->ar->winrct, viewzoom, zoom_invert, true, xy, &vod->origx, + zoomfac, zoomfac_prev, + &vod->timer_lastdraw); + + if (zfac != 1.0f && zfac != 0.0f) { + /* calculate inverted, then invert again (needed because of camera zoom scaling) */ + zfac = 1.0f / zfac; + view_zoom_mouseloc_camera( + vod->scene, vod->v3d, + vod->ar, zfac, vod->oldx, vod->oldy); + } + + ED_region_tag_redraw(vod->ar); +} + +static void viewzoom_apply_3d( + ViewOpsData *vod, const int xy[2], + const short viewzoom, const bool zoom_invert) +{ + float zfac; + float dist_range[2]; + + ED_view3d_dist_range_get(vod->v3d, dist_range); + + zfac = viewzoom_scale_value( + &vod->ar->winrct, viewzoom, zoom_invert, false, xy, &vod->origx, + vod->rv3d->dist, vod->dist_prev, + &vod->timer_lastdraw); + + if (zfac != 1.0f) { + const float zfac_min = dist_range[0] / vod->rv3d->dist; + const float zfac_max = dist_range[1] / vod->rv3d->dist; + CLAMP(zfac, zfac_min, zfac_max); + + view_zoom_mouseloc_3d( + vod->ar, zfac, vod->oldx, vod->oldy); } /* these limits were in old code too */ @@ -2231,6 +2308,19 @@ static void viewzoom_apply(ViewOpsData *vod, const int xy[2], const short viewzo ED_region_tag_redraw(vod->ar); } +static void viewzoom_apply( + ViewOpsData *vod, const int xy[2], + const short viewzoom, const bool zoom_invert) +{ + if ((vod->rv3d->persp == RV3D_CAMOB) && + (vod->rv3d->is_persp && ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) == 0) + { + viewzoom_apply_camera(vod, xy, viewzoom, zoom_invert); + } + else { + viewzoom_apply_3d(vod, xy, viewzoom, zoom_invert); + } +} static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event) { @@ -2291,6 +2381,7 @@ static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event) static int viewzoom_exec(bContext *C, wmOperator *op) { + Scene *scene = CTX_data_scene(C); View3D *v3d; RegionView3D *rv3d; ScrArea *sa; @@ -2323,22 +2414,26 @@ static int viewzoom_exec(bContext *C, wmOperator *op) ED_view3d_dist_range_get(v3d, dist_range); if (delta < 0) { + const float step = 1.2f; /* this min and max is also in viewmove() */ if (use_cam_zoom) { - rv3d->camzoom -= 10.0f; - if (rv3d->camzoom < RV3D_CAMZOOM_MIN) rv3d->camzoom = RV3D_CAMZOOM_MIN; + view_zoom_mouseloc_camera(scene, v3d, ar, step, mx, my); } - else if (rv3d->dist < dist_range[1]) { - view_zoom_mouseloc(ar, 1.2f, mx, my); + else { + if (rv3d->dist < dist_range[1]) { + view_zoom_mouseloc_3d(ar, step, mx, my); + } } } else { + const float step = 1.0f / 1.2f; if (use_cam_zoom) { - rv3d->camzoom += 10.0f; - if (rv3d->camzoom > RV3D_CAMZOOM_MAX) rv3d->camzoom = RV3D_CAMZOOM_MAX; + view_zoom_mouseloc_camera(scene, v3d, ar, step, mx, my); } - else if (rv3d->dist > dist_range[0]) { - view_zoom_mouseloc(ar, 0.83333f, mx, my); + else { + if (rv3d->dist > dist_range[0]) { + view_zoom_mouseloc_3d(ar, step, mx, my); + } } } @@ -2468,7 +2563,7 @@ void VIEW3D_OT_zoom(wmOperatorType *ot) ot->cancel = viewzoom_cancel; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX); prop = RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Zoom Position X", "", 0, INT_MAX); @@ -2722,7 +2817,7 @@ void VIEW3D_OT_dolly(wmOperatorType *ot) ot->cancel = viewdolly_cancel; /* flags */ - ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; + ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR; RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX); RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Zoom Position X", "", 0, INT_MAX); diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index a3dfd62ba6b..469a7e63903 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -296,10 +296,10 @@ static void fly_update_header(bContext *C, FlyInfo *fly) "Ctrl: free look, " "X: Upright x axis (%s), " "Z: Upright z axis (%s), " - "(+/- | Wheel): speed"), + "(+/- | Wheel): speed"), WM_bool_as_string(fly->xlock != FLY_AXISLOCK_STATE_OFF), - WM_bool_as_string(fly->zlock != FLY_AXISLOCK_STATE_OFF)); + WM_bool_as_string(fly->zlock != FLY_AXISLOCK_STATE_OFF)); ED_area_headerprint(CTX_wm_area(C), header); #undef HEADER_LENGTH diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c index 74e3fde0eec..ba0626c58ea 100644 --- a/source/blender/editors/space_view3d/view3d_project.c +++ b/source/blender/editors/space_view3d/view3d_project.c @@ -605,6 +605,14 @@ void ED_view3d_ob_project_mat_get(const RegionView3D *rv3d, Object *ob, float pm mul_m4_m4m4(pmat, (float (*)[4])rv3d->winmat, vmat); } +void ED_view3d_ob_project_mat_get_from_obmat(const RegionView3D *rv3d, float obmat[4][4], float pmat[4][4]) +{ + float vmat[4][4]; + + mul_m4_m4m4(vmat, (float (*)[4])rv3d->viewmat, obmat); + mul_m4_m4m4(pmat, (float (*)[4])rv3d->winmat, vmat); +} + /** * Uses window coordinates (x,y) and depth component z to find a point in * modelspace */ diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c index eba31866f54..98b1e846c70 100644 --- a/source/blender/editors/space_view3d/view3d_ruler.c +++ b/source/blender/editors/space_view3d/view3d_ruler.c @@ -187,8 +187,9 @@ typedef struct RulerInfo { /* wm state */ wmWindow *win; - ARegion *ar; + ScrArea *sa; void *draw_handle_pixel; + ARegion *ar; /* re-assigned every modal update */ } RulerInfo; /* -------------------------------------------------------------------- */ @@ -435,7 +436,7 @@ static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *a UnitSettings *unit = &scene->unit; RulerItem *ruler_item; RulerInfo *ruler_info = arg; - RegionView3D *rv3d = ruler_info->ar->regiondata; + RegionView3D *rv3d = ar->regiondata; // ARegion *ar = ruler_info->ar; const float cap_size = 4.0f; const float bg_margin = 4.0f * U.pixelsize; @@ -798,12 +799,14 @@ static int view3d_ruler_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE op->customdata = ruler_info; ruler_info->win = win; - ruler_info->ar = ar; + ruler_info->sa = sa; ruler_info->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ruler_info_draw_pixel, ruler_info, REGION_DRAW_POST_PIXEL); view3d_ruler_header_update(sa); + op->flag |= OP_IS_MODAL_CURSOR_REGION; + WM_cursor_modal_set(win, BC_CROSSCURSOR); WM_event_add_modal_handler(C, op); @@ -825,15 +828,17 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event) int exit_code = OPERATOR_RUNNING_MODAL; RulerInfo *ruler_info = op->customdata; ScrArea *sa = CTX_wm_area(C); - ARegion *ar = ruler_info->ar; + ARegion *ar = CTX_wm_region(C); RegionView3D *rv3d = ar->regiondata; /* its possible to change spaces while running the operator [#34894] */ - if (UNLIKELY(ar != CTX_wm_region(C))) { + if (UNLIKELY(sa != ruler_info->sa)) { exit_code = OPERATOR_FINISHED; goto exit; } + ruler_info->ar = ar; + switch (event->type) { case LEFTMOUSE: if (event->val == KM_RELEASE) { @@ -1019,6 +1024,13 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event) } + if (ruler_info->state == RULER_STATE_DRAG) { + op->flag &= ~OP_IS_MODAL_CURSOR_REGION; + } + else { + op->flag |= OP_IS_MODAL_CURSOR_REGION; + } + if (do_draw) { view3d_ruler_header_update(sa); diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 2e30f38c053..1847de3c6a2 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -727,7 +727,7 @@ static void do_lasso_select_meshobject__doSelectVert(void *userData, MVert *mv, } static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], short moves, bool extend, bool select) { - const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT); + const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0; Object *ob = vc->obact; Mesh *me = ob->data; rcti rect; @@ -1645,7 +1645,7 @@ static void do_paintvert_box_select__doSelectVert(void *userData, MVert *mv, con } static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, bool extend) { - const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT); + const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0; Mesh *me; MVert *mvert; struct ImBuf *ibuf; @@ -1666,7 +1666,7 @@ static int do_paintvert_box_select(ViewContext *vc, rcti *rect, bool select, boo if (use_zbuf) { selar = MEM_callocN(me->totvert + 1, "selar"); - view3d_validate_backbuf(vc); + ED_view3d_backbuf_validate(vc); ibuf = IMB_allocImBuf(sx, sy, 32, IB_rect); rt = ibuf->rect; @@ -2192,7 +2192,7 @@ void VIEW3D_OT_select_border(wmOperatorType *ot) static bool mouse_weight_paint_vertex_select(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle, Object *obact) { View3D *v3d = CTX_wm_view3d(C); - const int use_zbuf = (v3d->flag & V3D_ZBUF_SELECT); + const bool use_zbuf = (v3d->flag & V3D_ZBUF_SELECT) != 0; Mesh *me = obact->data; /* already checked for NULL */ unsigned int index = 0; @@ -2462,7 +2462,7 @@ static void paint_vertsel_circle_select_doSelectVert(void *userData, MVert *mv, } static void paint_vertsel_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad) { - const int use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT); + const bool use_zbuf = (vc->v3d->flag & V3D_ZBUF_SELECT) != 0; Object *ob = vc->obact; Mesh *me = ob->data; bool bbsel; diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index 11756e4feca..fb98f8b91a7 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -344,7 +344,7 @@ static void walk_update_header(bContext *C, WalkInfo *walk) char header[HEADER_LENGTH]; BLI_snprintf(header, HEADER_LENGTH, IFACE_("LMB/Return: confirm, Esc/RMB: cancel, " - "Tab: gravity (%s), " + "Tab: gravity (%s), " "WASD: move around, " "Shift: fast, Alt: slow, " "QE: up and down, MMB/Space: teleport, V: jump, " diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index f8e529aa4bf..3cf0c53d564 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -54,6 +54,7 @@ #include "BLI_memarena.h" #include "BKE_nla.h" +#include "BKE_editmesh.h" #include "BKE_editmesh_bvh.h" #include "BKE_context.h" #include "BKE_constraint.h" @@ -911,7 +912,7 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cm { if (!(t->flag & T_NO_CONSTRAINT)) { int constraint_axis, constraint_plane; - int edit_2d = (t->flag & T_2D_EDIT); + const bool edit_2d = (t->flag & T_2D_EDIT) != 0; const char *msg1 = "", *msg2 = "", *msg3 = ""; char axis; diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 4d7537a02f9..844a4bbc33b 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -39,9 +39,6 @@ #include "DNA_listBase.h" -#include "BLI_smallhash.h" -#include "BKE_editmesh.h" - /* ************************** Types ***************************** */ struct TransInfo; @@ -261,7 +258,7 @@ typedef struct EdgeSlideData { typedef struct TransDataVertSlideVert { /* TransDataGenericSlideVert */ - BMVert *v; + struct BMVert *v; struct LinkNode **cd_loop_groups; float co_orig_3d[3]; /* end generic */ diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 0bf419b3f75..14bea356cac 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -31,6 +31,7 @@ #include <string.h> #include <math.h> +#include <limits.h> #include "DNA_anim_types.h" #include "DNA_brush_types.h" @@ -342,20 +343,20 @@ static void createTransEdge(TransInfo *t) BMIter iter; float mtx[3][3], smtx[3][3]; int count = 0, countsel = 0; - int propmode = t->flag & T_PROP_EDIT; + const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; int cd_edge_float_offset; BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) countsel++; - if (propmode) count++; + if (is_prop_edit) count++; } } if (countsel == 0) return; - if (propmode) { + if (is_prop_edit) { t->total = count; } else { @@ -381,7 +382,7 @@ static void createTransEdge(TransInfo *t) BLI_assert(cd_edge_float_offset != -1); BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { - if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && (BM_elem_flag_test(eed, BM_ELEM_SELECT) || propmode)) { + if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && (BM_elem_flag_test(eed, BM_ELEM_SELECT) || is_prop_edit)) { float *fl_ptr; /* need to set center for center calculations */ mid_v3_v3v3(td->center, eed->v1->co, eed->v2->co); @@ -1331,18 +1332,18 @@ static void createTransMBallVerts(TransInfo *t) TransDataExtension *tx; float mtx[3][3], smtx[3][3]; int count = 0, countsel = 0; - int propmode = t->flag & T_PROP_EDIT; + const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; /* count totals */ for (ml = mb->editelems->first; ml; ml = ml->next) { if (ml->flag & SELECT) countsel++; - if (propmode) count++; + if (is_prop_edit) count++; } /* note: in prop mode we need at least 1 selected */ if (countsel == 0) return; - if (propmode) t->total = count; + if (is_prop_edit) t->total = count; else t->total = countsel; td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(MBall EditMode)"); @@ -1352,7 +1353,7 @@ static void createTransMBallVerts(TransInfo *t) pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); for (ml = mb->editelems->first; ml; ml = ml->next) { - if (propmode || (ml->flag & SELECT)) { + if (is_prop_edit || (ml->flag & SELECT)) { td->loc = &ml->x; copy_v3_v3(td->iloc, td->loc); copy_v3_v3(td->center, td->loc); @@ -1465,7 +1466,7 @@ static void createTransCurveVerts(TransInfo *t) float mtx[3][3], smtx[3][3]; int a; int count = 0, countsel = 0; - int propmode = t->flag & T_PROP_EDIT; + const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; short hide_handles = (cu->drawflag & CU_HIDE_HANDLES); ListBase *nurbs; @@ -1480,13 +1481,13 @@ static void createTransCurveVerts(TransInfo *t) if (bezt->hide == 0) { if (hide_handles) { if (bezt->f2 & SELECT) countsel += 3; - if (propmode) count += 3; + if (is_prop_edit) count += 3; } else { if (bezt->f1 & SELECT) countsel++; if (bezt->f2 & SELECT) countsel++; if (bezt->f3 & SELECT) countsel++; - if (propmode) count += 3; + if (is_prop_edit) count += 3; } } } @@ -1494,7 +1495,7 @@ static void createTransCurveVerts(TransInfo *t) else { for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) { if (bp->hide == 0) { - if (propmode) count++; + if (is_prop_edit) count++; if (bp->f1 & SELECT) countsel++; } } @@ -1503,7 +1504,7 @@ static void createTransCurveVerts(TransInfo *t) /* note: in prop mode we need at least 1 selected */ if (countsel == 0) return; - if (propmode) t->total = count; + if (is_prop_edit) t->total = count; else t->total = countsel; t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Curve EditMode)"); @@ -1538,7 +1539,7 @@ static void createTransCurveVerts(TransInfo *t) } } - if (propmode || + if (is_prop_edit || ((bezt->f2 & SELECT) && hide_handles) || ((bezt->f1 & SELECT) && hide_handles == 0)) { @@ -1572,7 +1573,7 @@ static void createTransCurveVerts(TransInfo *t) } /* This is the Curve Point, the other two are handles */ - if (propmode || (bezt->f2 & SELECT)) { + if (is_prop_edit || (bezt->f2 & SELECT)) { copy_v3_v3(td->iloc, bezt->vec[1]); td->loc = bezt->vec[1]; copy_v3_v3(td->center, td->loc); @@ -1608,7 +1609,7 @@ static void createTransCurveVerts(TransInfo *t) count++; tail++; } - if (propmode || + if (is_prop_edit || ((bezt->f2 & SELECT) && hide_handles) || ((bezt->f3 & SELECT) && hide_handles == 0)) { @@ -1645,12 +1646,12 @@ static void createTransCurveVerts(TransInfo *t) (void)hdata; /* quiet warning */ } - else if (propmode && head != tail) { + else if (is_prop_edit && head != tail) { calc_distanceCurveVerts(head, tail - 1); head = tail; } } - if (propmode && head != tail) + if (is_prop_edit && head != tail) calc_distanceCurveVerts(head, tail - 1); /* TODO - in the case of tilt and radius we can also avoid allocating the initTransDataCurveHandles @@ -1665,7 +1666,7 @@ static void createTransCurveVerts(TransInfo *t) head = tail = td; for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) { if (bp->hide == 0) { - if (propmode || (bp->f1 & SELECT)) { + if (is_prop_edit || (bp->f1 & SELECT)) { copy_v3_v3(td->iloc, bp->vec); td->loc = bp->vec; copy_v3_v3(td->center, td->loc); @@ -1690,12 +1691,12 @@ static void createTransCurveVerts(TransInfo *t) tail++; } } - else if (propmode && head != tail) { + else if (is_prop_edit && head != tail) { calc_distanceCurveVerts(head, tail - 1); head = tail; } } - if (propmode && head != tail) + if (is_prop_edit && head != tail) calc_distanceCurveVerts(head, tail - 1); } } @@ -1711,14 +1712,14 @@ static void createTransLatticeVerts(TransInfo *t) float mtx[3][3], smtx[3][3]; int a; int count = 0, countsel = 0; - int propmode = t->flag & T_PROP_EDIT; + const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; bp = latt->def; a = latt->pntsu * latt->pntsv * latt->pntsw; while (a--) { if (bp->hide == 0) { if (bp->f1 & SELECT) countsel++; - if (propmode) count++; + if (is_prop_edit) count++; } bp++; } @@ -1726,7 +1727,7 @@ static void createTransLatticeVerts(TransInfo *t) /* note: in prop mode we need at least 1 selected */ if (countsel == 0) return; - if (propmode) t->total = count; + if (is_prop_edit) t->total = count; else t->total = countsel; t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Lattice EditMode)"); @@ -1737,7 +1738,7 @@ static void createTransLatticeVerts(TransInfo *t) bp = latt->def; a = latt->pntsu * latt->pntsv * latt->pntsw; while (a--) { - if (propmode || (bp->f1 & SELECT)) { + if (is_prop_edit || (bp->f1 & SELECT)) { if (bp->hide == 0) { copy_v3_v3(td->iloc, bp->vec); td->loc = bp->vec; @@ -1778,7 +1779,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t) float mat[4][4]; int i, k, transformparticle; int count = 0, hasselected = 0; - int propmode = t->flag & T_PROP_EDIT; + const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; if (edit == NULL || t->settings->particle.selectmode == SCE_SELECT_PATH) return; @@ -1800,7 +1801,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t) hasselected = 1; transformparticle = 1; } - else if (propmode) + else if (is_prop_edit) transformparticle = 1; } } @@ -1850,7 +1851,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t) if (key->flag & PEK_SELECT) td->flag |= TD_SELECTED; - else if (!propmode) + else if (!is_prop_edit) td->flag |= TD_SKIP; unit_m3(td->mtx); @@ -1879,7 +1880,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t) tx++; tail++; } - if (propmode && head != tail) + if (is_prop_edit && head != tail) calc_distanceCurveVerts(head, tail - 1); } } @@ -1895,7 +1896,8 @@ void flushTransParticles(TransInfo *t) PTCacheEditKey *key; TransData *td; float mat[4][4], imat[4][4], co[3]; - int i, k, propmode = t->flag & T_PROP_EDIT; + int i, k; + const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; if (psys) psmd = psys_get_modifier(ob, psys); @@ -1916,7 +1918,7 @@ void flushTransParticles(TransInfo *t) /* optimization for proportional edit */ - if (!propmode || !compare_v3v3(key->co, co, 0.0001f)) { + if (!is_prop_edit || !compare_v3v3(key->co, co, 0.0001f)) { copy_v3_v3(key->co, co); point->flag |= PEP_EDIT_RECALC; } @@ -2487,7 +2489,7 @@ static void createTransEditVerts(TransInfo *t) float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL; float *dists = NULL; int a; - int propmode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0; + const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0; int mirror = 0; int cd_vert_bweight_offset = -1; bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0; @@ -2527,7 +2529,7 @@ static void createTransEditVerts(TransInfo *t) cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); } - if (propmode) { + if (prop_mode) { unsigned int count = 0; BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { @@ -2538,7 +2540,7 @@ static void createTransEditVerts(TransInfo *t) t->total = count; /* allocating scratch arrays */ - if (propmode & T_PROP_CONNECTED) + if (prop_mode & T_PROP_CONNECTED) dists = MEM_mallocN(em->bm->totvert * sizeof(float), "scratch nears"); } else { @@ -2560,7 +2562,7 @@ static void createTransEditVerts(TransInfo *t) * matrix inversion still works and we can still moving along the other */ pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); - if (propmode & T_PROP_CONNECTED) { + if (prop_mode & T_PROP_CONNECTED) { editmesh_set_connectivity_distance(em->bm, mtx, dists); } @@ -2589,7 +2591,7 @@ static void createTransEditVerts(TransInfo *t) { mappedcos = BKE_crazyspace_get_mapped_editverts(t->scene, t->obedit); quats = MEM_mallocN(em->bm->totvert * sizeof(*quats), "crazy quats"); - BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !propmode); + BKE_crazyspace_set_quats_editmesh(em, defcos, mappedcos, quats, !prop_mode); if (mappedcos) MEM_freeN(mappedcos); } @@ -2614,7 +2616,7 @@ static void createTransEditVerts(TransInfo *t) BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) { if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { - if (propmode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) { struct TransIslandData *v_island = (island_info && island_vert_map[a] != -1) ? &island_info[island_vert_map[a]] : NULL; float *bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) : NULL; @@ -2627,8 +2629,8 @@ static void createTransEditVerts(TransInfo *t) if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) tob->flag |= TD_SELECTED; - if (propmode) { - if (propmode & T_PROP_CONNECTED) { + if (prop_mode) { + if (prop_mode & T_PROP_CONNECTED) { tob->dist = dists[a]; } else { @@ -2933,15 +2935,15 @@ static void createTransUVs(bContext *C, TransInfo *t) UvElementMap *elementmap = NULL; BLI_bitmap *island_enabled = NULL; int count = 0, countsel = 0, count_rejected = 0; - const bool propmode = (t->flag & T_PROP_EDIT) != 0; - const bool propconnected = (t->flag & T_PROP_CONNECTED) != 0; + const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; + const bool is_prop_connected = (t->flag & T_PROP_CONNECTED) != 0; const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); if (!ED_space_image_show_uvedit(sima, t->obedit)) return; /* count */ - if (propconnected) { + if (is_prop_connected) { /* create element map with island information */ if (ts->uv_flag & UV_SYNC_SELECTION) { elementmap = BM_uv_element_map_create(em->bm, false, true); @@ -2965,14 +2967,14 @@ static void createTransUVs(bContext *C, TransInfo *t) if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { countsel++; - if (propconnected) { + if (is_prop_connected) { UvElement *element = BM_uv_element_get(elementmap, efa, l); BLI_BITMAP_ENABLE(island_enabled, element->island); } } - if (propmode) { + if (is_prop_edit) { count++; } } @@ -2980,13 +2982,13 @@ static void createTransUVs(bContext *C, TransInfo *t) /* note: in prop mode we need at least 1 selected */ if (countsel == 0) { - if (propconnected) { + if (is_prop_connected) { MEM_freeN(island_enabled); } return; } - t->total = (propmode) ? count : countsel; + t->total = (is_prop_edit) ? count : countsel; t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(UV Editing)"); /* for each 2d uv coord a 3d vector is allocated, so that they can be * treated just as if they were 3d verts */ @@ -3003,10 +3005,10 @@ static void createTransUVs(bContext *C, TransInfo *t) continue; BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (!propmode && !uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) + if (!is_prop_edit && !uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) continue; - if (propconnected) { + if (is_prop_connected) { UvElement *element = BM_uv_element_get(elementmap, efa, l); if (!BLI_BITMAP_TEST(island_enabled, element->island)) { count_rejected++; @@ -3019,7 +3021,7 @@ static void createTransUVs(bContext *C, TransInfo *t) } } - if (propconnected) { + if (is_prop_connected) { t->total -= count_rejected; BM_uv_element_map_free(elementmap); MEM_freeN(island_enabled); @@ -3534,7 +3536,7 @@ static void posttrans_action_clean(bAnimContext *ac, bAction *act) /* ----------------------------- */ /* fully select selected beztriples, but only include if it's on the right side of cfra */ -static int count_fcurve_keys(FCurve *fcu, char side, float cfra, bool propedit) +static int count_fcurve_keys(FCurve *fcu, char side, float cfra, bool is_prop_edit) { BezTriple *bezt; int i, count = 0, count_all = 0; @@ -3554,13 +3556,13 @@ static int count_fcurve_keys(FCurve *fcu, char side, float cfra, bool propedit) } } - if (propedit && count > 0) + if (is_prop_edit && count > 0) return count_all; else return count; } /* fully select selected beztriples, but only include if it's on the right side of cfra */ -static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra, bool propedit) +static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra, bool is_prop_edit) { bGPDframe *gpf; int count = 0, count_all = 0; @@ -3577,14 +3579,14 @@ static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra, bool prop } } - if (propedit && count > 0) + if (is_prop_edit && count > 0) return count_all; else return count; } /* fully select selected beztriples, but only include if it's on the right side of cfra */ -static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra, bool propedit) +static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra, bool is_prop_edit) { MaskLayerShape *masklayer_shape; int count = 0, count_all = 0; @@ -3601,7 +3603,7 @@ static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra, boo } } - if (propedit && count > 0) + if (is_prop_edit && count > 0) return count_all; else return count; @@ -3631,7 +3633,7 @@ static void TimeToTransData(TransData *td, float *time, AnimData *adt, float ypo * The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data * on the named side are used. */ -static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FCurve *fcu, AnimData *adt, char side, float cfra, bool propedit, float ypos) +static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FCurve *fcu, AnimData *adt, char side, float cfra, bool is_prop_edit, float ypos) { BezTriple *bezt; TransData2D *td2d = *td2dv; @@ -3642,7 +3644,7 @@ static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FC for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { /* only add selected keyframes (for now, proportional edit is not enabled) */ - if (propedit || (bezt->f2 & SELECT)) { /* note this MUST match count_fcurve_keys(), so can't use BEZSELECTED() macro */ + if (is_prop_edit || (bezt->f2 & SELECT)) { /* note this MUST match count_fcurve_keys(), so can't use BEZSELECTED() macro */ /* only add if on the right 'side' of the current frame */ if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) { TimeToTransData(td, bezt->vec[1], adt, ypos); @@ -3700,14 +3702,14 @@ void flushTransIntFrameActionData(TransInfo *t) * The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data * on the named side are used. */ -static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, char side, float cfra, bool propedit, float ypos) +static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, char side, float cfra, bool is_prop_edit, float ypos) { bGPDframe *gpf; int count = 0; /* check for select frames on right side of current frame */ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { - if (propedit || (gpf->flag & GP_FRAME_SELECT)) { + if (is_prop_edit || (gpf->flag & GP_FRAME_SELECT)) { if (FrameOnMouseSide(side, (float)gpf->framenum, cfra)) { /* memory is calloc'ed, so that should zero everything nicely for us */ td->val = &tfd->val; @@ -3731,14 +3733,14 @@ static int GPLayerToTransData(TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, } /* refer to comment above #GPLayerToTransData, this is the same but for masks */ -static int MaskLayerToTransData(TransData *td, tGPFtransdata *tfd, MaskLayer *masklay, char side, float cfra, bool propedit, float ypos) +static int MaskLayerToTransData(TransData *td, tGPFtransdata *tfd, MaskLayer *masklay, char side, float cfra, bool is_prop_edit, float ypos) { MaskLayerShape *masklay_shape; int count = 0; /* check for select frames on right side of current frame */ for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) { - if (propedit || (masklay_shape->flag & MASK_SHAPE_SELECT)) { + if (is_prop_edit || (masklay_shape->flag & MASK_SHAPE_SELECT)) { if (FrameOnMouseSide(side, (float)masklay_shape->frame, cfra)) { /* memory is calloc'ed, so that should zero everything nicely for us */ td->val = &tfd->val; @@ -3781,7 +3783,7 @@ static void createTransActionData(bContext *C, TransInfo *t) ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; - const bool propedit = (t->flag & T_PROP_EDIT) != 0; + const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; int count = 0; float cfra; @@ -3824,11 +3826,11 @@ static void createTransActionData(bContext *C, TransInfo *t) cfra = (float)CFRA; if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) - adt_count = count_fcurve_keys(ale->key_data, t->frame_side, cfra, propedit); + adt_count = count_fcurve_keys(ale->key_data, t->frame_side, cfra, is_prop_edit); else if (ale->type == ANIMTYPE_GPLAYER) - adt_count = count_gplayer_frames(ale->data, t->frame_side, cfra, propedit); + adt_count = count_gplayer_frames(ale->data, t->frame_side, cfra, is_prop_edit); else if (ale->type == ANIMTYPE_MASKLAYER) - adt_count = count_masklayer_frames(ale->data, t->frame_side, cfra, propedit); + adt_count = count_masklayer_frames(ale->data, t->frame_side, cfra, is_prop_edit); else BLI_assert(0); @@ -3874,7 +3876,7 @@ static void createTransActionData(bContext *C, TransInfo *t) for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt; - if (propedit && !ale->tag) + if (is_prop_edit && !ale->tag) continue; adt = ANIM_nla_mapping_get(&ac, ale); @@ -3887,7 +3889,7 @@ static void createTransActionData(bContext *C, TransInfo *t) bGPDlayer *gpl = (bGPDlayer *)ale->data; int i; - i = GPLayerToTransData(td, tfd, gpl, t->frame_side, cfra, propedit, ypos); + i = GPLayerToTransData(td, tfd, gpl, t->frame_side, cfra, is_prop_edit, ypos); td += i; tfd += i; } @@ -3895,7 +3897,7 @@ static void createTransActionData(bContext *C, TransInfo *t) MaskLayer *masklay = (MaskLayer *)ale->data; int i; - i = MaskLayerToTransData(td, tfd, masklay, t->frame_side, cfra, propedit, ypos); + i = MaskLayerToTransData(td, tfd, masklay, t->frame_side, cfra, is_prop_edit, ypos); td += i; tfd += i; } @@ -3903,7 +3905,7 @@ static void createTransActionData(bContext *C, TransInfo *t) AnimData *adt = ANIM_nla_mapping_get(&ac, ale); FCurve *fcu = (FCurve *)ale->key_data; - td = ActionFCurveToTransData(td, &td2d, fcu, adt, t->frame_side, cfra, propedit, ypos); + td = ActionFCurveToTransData(td, &td2d, fcu, adt, t->frame_side, cfra, is_prop_edit, ypos); } } @@ -3933,7 +3935,7 @@ static void createTransActionData(bContext *C, TransInfo *t) } /* calculate distances for proportional editing */ - if (propedit) { + if (is_prop_edit) { td = t->data; for (ale = anim_data.first; ale; ale = ale->next) { @@ -3959,13 +3961,14 @@ static void createTransActionData(bContext *C, TransInfo *t) } else { bGPDframe *gpf_iter; - float min = FLT_MAX; + int min = INT_MAX; for (gpf_iter = gpl->frames.first; gpf_iter; gpf_iter = gpf->next) { if (gpf_iter->flag & GP_FRAME_SELECT) { if (FrameOnMouseSide(t->frame_side, (float)gpf_iter->framenum, cfra)) { - float val = fabsf(gpf->framenum - gpf_iter->framenum); - if (val < min) + int val = abs(gpf->framenum - gpf_iter->framenum); + if (val < min) { min = val; + } } } } @@ -3985,13 +3988,14 @@ static void createTransActionData(bContext *C, TransInfo *t) } else { MaskLayerShape *masklay_iter; - float min = FLT_MAX; + int min = INT_MAX; for (masklay_iter = masklay->splines_shapes.first; masklay_iter; masklay_iter = masklay_iter->next) { if (masklay_iter->flag & MASK_SHAPE_SELECT) { if (FrameOnMouseSide(t->frame_side, (float)masklay_iter->frame, cfra)) { - float val = fabsf(masklay_shape->frame - masklay_iter->frame); - if (val < min) + int val = abs(masklay_shape->frame - masklay_iter->frame); + if (val < min) { min = val; + } } } } @@ -4181,7 +4185,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) const bool is_translation_mode = graph_edit_is_translation_mode(t); const bool use_handle = !(sipo->flag & SIPO_NOHANDLES); const bool use_local_center = graph_edit_use_local_center(t); - const bool propedit = (t->flag & T_PROP_EDIT) != 0; + const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; short anim_map_flag = ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS; /* determine what type of data we are operating on */ @@ -4235,7 +4239,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) const bool sel1 = use_handle ? (bezt->f1 & SELECT) != 0 : sel2; const bool sel3 = use_handle ? (bezt->f3 & SELECT) != 0 : sel2; - if (propedit) { + if (is_prop_edit) { curvecount += 3; if (sel2 || sel1 || sel3) selected = true; @@ -4259,7 +4263,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) } } - if (propedit) { + if (is_prop_edit) { if (selected) { count += curvecount; ale->tag = true; @@ -4315,7 +4319,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) float cfra; /* F-Curve may not have any keyframes */ - if (fcu->bezt == NULL || (propedit && ale->tag == 0)) + if (fcu->bezt == NULL || (is_prop_edit && ale->tag == 0)) continue; /* convert current-frame to action-time (slightly less accurate, especially under @@ -4338,7 +4342,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) TransDataCurveHandleFlags *hdata = NULL; /* short h1=1, h2=1; */ /* UNUSED */ - if (propedit) { + if (is_prop_edit) { bool is_sel = (sel2 || sel1 || sel3); /* we always select all handles for proportional editing if central handle is selected */ initTransDataCurveHandles(td, bezt); @@ -4410,7 +4414,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) testhandles_fcurve(fcu, use_handle); } - if (propedit) { + if (is_prop_edit) { /* loop 2: build transdata arrays */ td = t->data; @@ -6529,7 +6533,7 @@ static void createTransObject(bContext *C, TransInfo *t) TransData *td = NULL; TransDataExtension *tx; - int propmode = t->flag & T_PROP_EDIT; + const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; set_trans_object_base_flags(t); @@ -6542,7 +6546,7 @@ static void createTransObject(bContext *C, TransInfo *t) return; } - if (propmode) { + if (is_prop_edit) { t->total += count_proportional_objects(t); } @@ -6575,7 +6579,7 @@ static void createTransObject(bContext *C, TransInfo *t) } CTX_DATA_END; - if (propmode) { + if (is_prop_edit) { View3D *v3d = t->view; Base *base; @@ -7332,9 +7336,10 @@ static void MaskHandleToTransData(MaskSplinePoint *point, eMaskWhichHandle which } } -static void MaskPointToTransData(Scene *scene, MaskSplinePoint *point, - TransData *td, TransData2D *td2d, TransDataMasking *tdm, - const int propmode, const float asp[2]) +static void MaskPointToTransData( + Scene *scene, MaskSplinePoint *point, + TransData *td, TransData2D *td2d, TransDataMasking *tdm, + const bool is_prop_edit, const float asp[2]) { BezTriple *bezt = &point->bezt; const bool is_sel_point = MASKPOINT_ISSEL_KNOT(point); @@ -7344,7 +7349,7 @@ static void MaskPointToTransData(Scene *scene, MaskSplinePoint *point, BKE_mask_point_parent_matrix_get(point, CFRA, parent_matrix); invert_m3_m3(parent_inverse_matrix, parent_matrix); - if (propmode || is_sel_point) { + if (is_prop_edit || is_sel_point) { int i; tdm->point = point; @@ -7464,7 +7469,7 @@ static void createTransMaskingData(bContext *C, TransInfo *t) TransData2D *td2d = NULL; TransDataMasking *tdm = NULL; int count = 0, countsel = 0; - int propmode = t->flag & T_PROP_EDIT; + const bool is_prop_edit = (t->flag & T_PROP_EDIT); float asp[2]; t->total = 0; @@ -7514,7 +7519,7 @@ static void createTransMaskingData(bContext *C, TransInfo *t) } } - if (propmode) + if (is_prop_edit) count += 3; } } @@ -7527,7 +7532,7 @@ static void createTransMaskingData(bContext *C, TransInfo *t) ED_mask_get_aspect(t->sa, t->ar, &asp[0], &asp[1]); - t->total = (propmode) ? count : countsel; + t->total = (is_prop_edit) ? count : countsel; td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Mask Editing)"); /* for each 2d uv coord a 3d vector is allocated, so that they can be * treated just as if they were 3d verts */ @@ -7550,10 +7555,10 @@ static void createTransMaskingData(bContext *C, TransInfo *t) for (i = 0; i < spline->tot_point; i++) { MaskSplinePoint *point = &spline->points[i]; - if (propmode || MASKPOINT_ISSEL_ANY(point)) { - MaskPointToTransData(scene, point, td, td2d, tdm, propmode, asp); + if (is_prop_edit || MASKPOINT_ISSEL_ANY(point)) { + MaskPointToTransData(scene, point, td, td2d, tdm, is_prop_edit, asp); - if (propmode || MASKPOINT_ISSEL_KNOT(point)) { + if (is_prop_edit || MASKPOINT_ISSEL_KNOT(point)) { td += 3; td2d += 3; tdm += 3; @@ -7796,8 +7801,8 @@ static void createTransGPencil(bContext *C, TransInfo *t) const Scene *scene = CTX_data_scene(C); const int cfra = CFRA; - const int propedit = (t->flag & T_PROP_EDIT); - const int propedit_connected = (t->flag & T_PROP_CONNECTED); + const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0; + const bool is_prop_edit_connected = (t->flag & T_PROP_CONNECTED) != 0; /* == Grease Pencil Strokes to Transform Data == @@ -7828,9 +7833,9 @@ static void createTransGPencil(bContext *C, TransInfo *t) continue; } - if (propedit) { + if (is_prop_edit) { /* Proportional Editing... */ - if (propedit_connected) { + if (is_prop_edit_connected) { /* connected only - so only if selected */ if (gps->flag & GP_STROKE_SELECT) t->total += gps->totpoints; @@ -7937,8 +7942,8 @@ static void createTransGPencil(bContext *C, TransInfo *t) } /* What we need to include depends on proportional editing settings... */ - if (propedit) { - if (propedit_connected) { + if (is_prop_edit) { + if (is_prop_edit_connected) { /* A) "Connected" - Only those in selected strokes */ stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0; } @@ -7957,7 +7962,7 @@ static void createTransGPencil(bContext *C, TransInfo *t) bGPDspoint *pt; int i; -#if 0 /* XXX: this isn't needed anymore; cannot calculate center this way or propedit breaks */ +#if 0 /* XXX: this isn't needed anymore; cannot calculate center this way or is_prop_edit breaks */ const float ninv = 1.0f / gps->totpoints; float center[3] = {0.0f}; @@ -7972,7 +7977,7 @@ static void createTransGPencil(bContext *C, TransInfo *t) bool point_ok; /* include point? */ - if (propedit) { + if (is_prop_edit) { /* Always all points in strokes that get included */ point_ok = true; } @@ -8015,7 +8020,7 @@ static void createTransGPencil(bContext *C, TransInfo *t) } /* March over these points, and calculate the proportional editing distances */ - if (propedit && (head != tail)) { + if (is_prop_edit && (head != tail)) { /* XXX: for now, we are similar enough that this works... */ calc_distanceCurveVerts(head, tail - 1); } diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index fc8e6cd0286..ae8cbc721e3 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -895,6 +895,11 @@ static void postOrtho(const bool ortho) } } +BLI_INLINE bool manipulator_rotate_is_visible(const int drawflags) +{ + return (drawflags & (MAN_ROT_X | MAN_ROT_Y | MAN_ROT_Z)); +} + static void draw_manipulator_rotate( View3D *v3d, RegionView3D *rv3d, const int drawflags, const int combo, const bool is_moving, const bool is_picksel) @@ -908,8 +913,8 @@ static void draw_manipulator_rotate( const int colcode = (is_moving) ? MAN_MOVECOL : MAN_RGB; bool ortho; - /* when called while moving in mixed mode, do not draw when... */ - if ((drawflags & MAN_ROT_C) == 0) return; + /* skip drawing if all axes are locked */ + if (manipulator_rotate_is_visible(drawflags) == false) return; /* Init stuff */ glDisable(GL_DEPTH_TEST); @@ -1448,8 +1453,8 @@ static void draw_manipulator_rotate_cyl( int axis_order[3] = {2, 0, 1}; int i; - /* when called while moving in mixed mode, do not draw when... */ - if ((drawflags & MAN_ROT_C) == 0) return; + /* skip drawing if all axes are locked */ + if (manipulator_rotate_is_visible(drawflags) == false) return; manipulator_axis_order(rv3d, axis_order); diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index e33bc19fc92..8e0b3d708e2 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -38,6 +38,7 @@ #include "BKE_context.h" #include "BKE_global.h" #include "BKE_report.h" +#include "BKE_editmesh.h" #include "RNA_access.h" #include "RNA_define.h" @@ -488,7 +489,7 @@ static int transform_invoke(bContext *C, wmOperator *op, const wmEvent *event) /* add temp handler */ WM_event_add_modal_handler(C, op); - op->flag |= OP_GRAB_POINTER; // XXX maybe we want this with the manipulator only? + op->flag |= OP_IS_MODAL_GRAB_CURSOR; // XXX maybe we want this with the manipulator only? return OPERATOR_RUNNING_MODAL; } } diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index fd189e91141..e8a0f35c6b0 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -1400,11 +1400,8 @@ static bool snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *ar invert_m4_m4(imat, obmat); - copy_v3_v3(ray_start_local, ray_start); - copy_v3_v3(ray_normal_local, ray_normal); - - mul_m4_v3(imat, ray_start_local); - mul_mat3_m4_v3(imat, ray_normal_local); + mul_v3_m4v3(ray_start_local, imat, ray_start); + mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal); if (arm->edbo) { EditBone *eBone; @@ -1762,11 +1759,8 @@ static bool snapEmpty(short snap_mode, ARegion *ar, Object *ob, float obmat[4][4 invert_m4_m4(imat, obmat); - copy_v3_v3(ray_start_local, ray_start); - copy_v3_v3(ray_normal_local, ray_normal); - - mul_m4_v3(imat, ray_start_local); - mul_mat3_m4_v3(imat, ray_normal_local); + mul_v3_m4v3(ray_start_local, imat, ray_start); + mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal); switch (snap_mode) { case SCE_SNAP_MODE_VERTEX: @@ -2111,12 +2105,8 @@ static bool peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[4][4], transpose_m3_m4(timat, imat); - copy_v3_v3(ray_start_local, ray_start); - copy_v3_v3(ray_normal_local, ray_normal); - - mul_m4_v3(imat, ray_start_local); - mul_mat3_m4_v3(imat, ray_normal_local); - + mul_v3_m4v3(ray_start_local, imat, ray_start); + mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal); /* If number of vert is more than an arbitrary limit, * test against boundbox first diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt index f4189a18da4..d1495d85e64 100644 --- a/source/blender/editors/util/CMakeLists.txt +++ b/source/blender/editors/util/CMakeLists.txt @@ -24,6 +24,7 @@ set(INC ../../blenkernel ../../blenlib ../../bmesh + ../../imbuf ../../gpu ../../makesdna ../../makesrna diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index 438eb1f3864..433c7603f35 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -38,6 +38,7 @@ #include "DNA_mesh_types.h" #include "DNA_object_types.h" #include "DNA_screen_types.h" +#include "DNA_space_types.h" #include "DNA_scene_types.h" #include "DNA_packedFile_types.h" @@ -58,9 +59,12 @@ #include "BKE_paint.h" #include "ED_armature.h" +#include "ED_buttons.h" #include "ED_image.h" #include "ED_mesh.h" +#include "ED_node.h" #include "ED_object.h" +#include "ED_outliner.h" #include "ED_paint.h" #include "ED_space_api.h" #include "ED_util.h" @@ -318,3 +322,25 @@ void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *ar, void *arg_info glEnd(); setlinestyle(0); } + +/** + * Use to free ID references within runtime data (stored outside of DNA) + * + * \note Typically notifiers take care of this, + * but there are times we have to free references immediately, see: T44376 + */ +void ED_spacedata_id_unref(struct SpaceLink *sl, const ID *id) +{ + + switch (sl->spacetype) { + case SPACE_OUTLINER: + ED_outliner_id_unref((SpaceOops *)sl, id); + break; + case SPACE_BUTS: + ED_buttons_id_unref((SpaceButs *)sl, id); + break; + case SPACE_NODE: + ED_node_id_unref((SpaceNode *)sl, id); + break; + } +} diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 444c579a62b..2ec7fe677ae 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -3098,9 +3098,10 @@ static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mo Scene *scene = CTX_data_scene(C); ToolSettings *ts = scene->toolsettings; BMEditMesh *em = BKE_editmesh_from_object(obedit); - const int use_face_center = (ts->uv_flag & UV_SYNC_SELECTION) ? - (ts->selectmode == SCE_SELECT_FACE) : - (ts->uv_selectmode == UV_SELECT_FACE); + const bool use_face_center = ( + (ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_FACE) : + (ts->uv_selectmode == UV_SELECT_FACE)); const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); const int cd_poly_tex_offset = CustomData_get_offset(&em->bm->pdata, CD_MTEXPOLY); diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index 793f84b05ec..f915a4b2e51 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -681,7 +681,7 @@ void UV_OT_minimize_stretch(wmOperatorType *ot) /* identifiers */ ot->name = "Minimize Stretch"; ot->idname = "UV_OT_minimize_stretch"; - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING; ot->description = "Reduce UV stretching by relaxing angles"; /* api callbacks */ diff --git a/source/blender/freestyle/intern/application/Controller.cpp b/source/blender/freestyle/intern/application/Controller.cpp index add7420b89a..5cd2e16847d 100644 --- a/source/blender/freestyle/intern/application/Controller.cpp +++ b/source/blender/freestyle/intern/application/Controller.cpp @@ -927,6 +927,12 @@ void Controller::InsertStyleModule(unsigned index, const char *iFileName) _Canvas->InsertStyleModule(index, sm); } +void Controller::InsertStyleModule(unsigned index, const char *iName, const char *iBuffer) +{ + StyleModule *sm = new BufferedStyleModule(iBuffer, iName, _inter); + _Canvas->InsertStyleModule(index, sm); +} + void Controller::InsertStyleModule(unsigned index, const char *iName, struct Text *iText) { StyleModule *sm = new BlenderStyleModule(iText, iName, _inter); diff --git a/source/blender/freestyle/intern/application/Controller.h b/source/blender/freestyle/intern/application/Controller.h index 9fe57d92cf4..a09964a4e79 100644 --- a/source/blender/freestyle/intern/application/Controller.h +++ b/source/blender/freestyle/intern/application/Controller.h @@ -90,6 +90,7 @@ public: Render *RenderStrokes(Render *re, bool render); void SwapStyleModules(unsigned i1, unsigned i2); void InsertStyleModule(unsigned index, const char *iFileName); + void InsertStyleModule(unsigned index, const char *iName, const char *iBuffer); void InsertStyleModule(unsigned index, const char *iName, struct Text *iText); void AddStyleModule(const char *iFileName); void RemoveStyleModule(unsigned index); diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp index 0e8f6222c8c..1ddc311b1ae 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -126,7 +126,7 @@ BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : Str BKE_scene_set_background(freestyle_bmain, freestyle_scene); // Camera - Object *object_camera = BKE_object_add(freestyle_bmain, freestyle_scene, OB_CAMERA); + Object *object_camera = BKE_object_add(freestyle_bmain, freestyle_scene, OB_CAMERA, NULL); Camera *camera = (Camera *)object_camera->data; camera->type = CAM_ORTHO; diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h b/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h index 2bc43798878..1d73125f627 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h +++ b/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h @@ -36,6 +36,34 @@ struct Text; namespace Freestyle { +class BufferedStyleModule : public StyleModule +{ +public: + BufferedStyleModule(const string& buffer, const string& file_name, Interpreter *inter) : StyleModule(file_name, inter) + { + _buffer = buffer; + } + + virtual ~BufferedStyleModule() + { + } + +protected: + virtual int interpret() + { + PythonInterpreter *py_inter = dynamic_cast<PythonInterpreter*>(_inter); + BLI_assert(py_inter != 0); + return py_inter->interpretString(_buffer, getFileName()); + } + +private: + string _buffer; + +#ifdef WITH_CXX_GUARDEDALLOC + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BufferedStyleModule") +#endif +}; + class BlenderStyleModule : public StyleModule { public: @@ -62,7 +90,6 @@ private: #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BlenderStyleModule") #endif - }; } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp index 6b102410aa6..291ed98f905 100644 --- a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp +++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp @@ -211,16 +211,12 @@ static char *escape_quotes(char *name) return s; } -static Text *create_lineset_handler(Main *bmain, char *layer_name, char *lineset_name) +static char * create_lineset_handler(char *layer_name, char *lineset_name) { + const char *fmt = "__import__('parameter_editor').process('%s', '%s')\n"; char *s1 = escape_quotes(layer_name); char *s2 = escape_quotes(lineset_name); - Text *text = BKE_text_add(bmain, lineset_name); - BKE_text_write(text, "import parameter_editor; parameter_editor.process('"); - BKE_text_write(text, s1); - BKE_text_write(text, "', '"); - BKE_text_write(text, s2); - BKE_text_write(text, "')\n"); + char *text = BLI_sprintfN(fmt, s1, s2); MEM_freeN(s1); MEM_freeN(s2); return text; @@ -293,7 +289,7 @@ static bool test_edge_type_conditions(struct edge_type_condition *conditions, return true; } -static void prepare(Main *bmain, Render *re, SceneRenderLayer *srl) +static void prepare(Render *re, SceneRenderLayer *srl) { // load mesh re->i.infostr = "Freestyle: Mesh loading"; @@ -369,9 +365,10 @@ static void prepare(Main *bmain, Render *re, SceneRenderLayer *srl) cout << " " << layer_count+1 << ": " << lineset->name << " - " << (lineset->linestyle ? (lineset->linestyle->id.name + 2) : "<NULL>") << endl; } - Text *text = create_lineset_handler(bmain, srl->name, lineset->name); - controller->InsertStyleModule(layer_count, lineset->name, text); + char *buffer = create_lineset_handler(srl->name, lineset->name); + controller->InsertStyleModule(layer_count, lineset->name, buffer); controller->toggleLayer(layer_count, true); + MEM_freeN(buffer); if (!(lineset->selection & FREESTYLE_SEL_EDGE_TYPES) || !lineset->edge_types) { ++use_ridges_and_valleys; ++use_suggestive_contours; @@ -584,9 +581,7 @@ void FRS_init_stroke_rendering(Render *re) Render *FRS_do_stroke_rendering(Render *re, SceneRenderLayer *srl, int render) { - Main *freestyle_bmain = re->freestyle_bmain; Render *freestyle_render = NULL; - Text *text, *next_text; if (!render) return controller->RenderStrokes(re, false); @@ -607,7 +602,7 @@ Render *FRS_do_stroke_rendering(Render *re, SceneRenderLayer *srl, int render) // - add style modules // - set parameters // - compute view map - prepare(freestyle_bmain, re, srl); + prepare(re, srl); if (re->test_break(re->tbh)) { controller->CloseFile(); @@ -635,14 +630,6 @@ Render *FRS_do_stroke_rendering(Render *re, SceneRenderLayer *srl, int render) } } - // Free temp main (currently only text blocks are stored there) - for (text = (Text *)freestyle_bmain->text.first; text; text = next_text) { - next_text = (Text *) text->id.next; - - BKE_text_unlink(freestyle_bmain, text); - BKE_libblock_free(freestyle_bmain, text); - } - return freestyle_render; } diff --git a/source/blender/freestyle/intern/python/BPy_Operators.cpp b/source/blender/freestyle/intern/python/BPy_Operators.cpp index a214fc444c7..1b2b18c2c99 100644 --- a/source/blender/freestyle/intern/python/BPy_Operators.cpp +++ b/source/blender/freestyle/intern/python/BPy_Operators.cpp @@ -34,6 +34,8 @@ #include "BPy_StrokeShader.h" #include "BPy_Convert.h" +#include <sstream> + #ifdef __cplusplus extern "C" { #endif @@ -539,7 +541,15 @@ static PyObject *Operators_create(BPy_Operators * /*self*/, PyObject *args, PyOb PyErr_SetString(PyExc_TypeError, "Operators.create(): 2nd argument must be a list of StrokeShader objects"); return NULL; } - shaders.push_back(((BPy_StrokeShader *)py_ss)->ss); + StrokeShader *shader = ((BPy_StrokeShader *)py_ss)->ss; + if (!shader) { + stringstream ss; + ss << "Operators.create(): item " << (i + 1) + << " of the shaders list is invalid likely due to missing call of StrokeShader.__init__()"; + PyErr_SetString(PyExc_TypeError, ss.str().c_str()); + return NULL; + } + shaders.push_back(shader); } if (Operators::create(*(((BPy_UnaryPredicate1D *)obj1)->up1D), shaders) < 0) { if (!PyErr_Occurred()) diff --git a/source/blender/freestyle/intern/system/PythonInterpreter.h b/source/blender/freestyle/intern/system/PythonInterpreter.h index 60193590944..ddb79b2df0b 100644 --- a/source/blender/freestyle/intern/system/PythonInterpreter.h +++ b/source/blender/freestyle/intern/system/PythonInterpreter.h @@ -51,6 +51,8 @@ extern "C" { #include "BKE_text.h" #include "BPY_extern.h" + +#include "bpy_util.h" } namespace Freestyle { @@ -105,6 +107,26 @@ public: return 0; } + int interpretString(const string& str, const string& name) + { + ReportList *reports = CTX_wm_reports(_context); + + BKE_reports_clear(reports); + + if (BPY_string_exec(_context, str.c_str()) != 0) { + BPy_errors_to_report(reports); + cerr << "\nError executing Python script from PythonInterpreter::interpretString" << endl; + cerr << "Name: " << name << endl; + cerr << "Errors: " << endl; + BKE_reports_print(reports, RPT_ERROR); + return 1; + } + + BKE_reports_clear(reports); + + return 0; + } + int interpretText(struct Text *text, const string& name) { ReportList *reports = CTX_wm_reports(_context); diff --git a/source/blender/gpu/GPU_debug.h b/source/blender/gpu/GPU_debug.h index a74c0e7c67b..f89df2b54aa 100644 --- a/source/blender/gpu/GPU_debug.h +++ b/source/blender/gpu/GPU_debug.h @@ -63,7 +63,7 @@ void gpu_assert_no_gl_errors(const char *file, int line, const char *str); #ifdef WITH_GPU_DEBUG /* inserts a debug marker message for the debug context messaging system */ -void gpu_string_marker (size_t size, const char *str); +void gpu_string_marker(size_t size, const char *str); # define GPU_STRING_MARKER(size, str) gpu_string_marker((size), (str)) #else /* WITH_GPU_DEBUG */ diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index 20aa4919416..845ae9d2b30 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -104,11 +104,11 @@ void GPU_render_text(struct MTFace *tface, int mode, /* Mipmap settings * - these will free textures on changes */ -void GPU_set_mipmap(int mipmap); -int GPU_get_mipmap(void); -void GPU_set_linear_mipmap(int linear); -int GPU_get_linear_mipmap(void); -void GPU_paint_set_mipmap(int mipmap); +void GPU_set_mipmap(bool mipmap); +bool GPU_get_mipmap(void); +void GPU_set_linear_mipmap(bool linear); +bool GPU_get_linear_mipmap(void); +void GPU_paint_set_mipmap(bool mipmap); /* Anisotropic filtering settings * - these will free textures on changes */ diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index 27a4396e5d8..f3927ba960b 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -71,6 +71,9 @@ int GPU_max_texture_size(void); int GPU_color_depth(void); void GPU_get_dfdy_factors(float fac[2]); +bool GPU_mem_stats_supported(void); +void GPU_mem_stats_get(int *totalmem, int *freemem); + void GPU_code_generate_glsl_lib(void); /* GPU Types */ diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index b61bdf969cc..7bb044a1ae3 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -186,7 +186,7 @@ bool GPU_lamp_override_visible(GPULamp *lamp, struct SceneRenderLayer *srl, stru void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap, float viewmat[4][4], float viewinv[4][4], float cameraborder[4], bool scenelock); void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float obcol[4], float autobumpscale); void GPU_material_unbind(GPUMaterial *material); -int GPU_material_bound(GPUMaterial *material); +bool GPU_material_bound(GPUMaterial *material); struct Scene *GPU_material_scene(GPUMaterial *material); GPUMatType GPU_Material_get_type(GPUMaterial *material); diff --git a/source/blender/gpu/intern/gpu_debug.c b/source/blender/gpu/intern/gpu_debug.c index a0dde9c8f3b..7bcc51aef31 100644 --- a/source/blender/gpu/intern/gpu_debug.c +++ b/source/blender/gpu/intern/gpu_debug.c @@ -356,6 +356,7 @@ void gpu_assert_no_gl_errors(const char* file, int line, const char* str) GLboolean gl_ok = gpu_report_gl_errors(file, line, str); BLI_assert(gl_ok); + (void) gl_ok; } } diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index daf6b90f604..a24067fc381 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -117,7 +117,7 @@ void GPU_render_text(MTFace *tface, int mode, /* color has been set */ if (tface->mode & TF_OBCOL) - col= NULL; + col = NULL; else if (!col) glColor3f(1.0f, 1.0f, 1.0f); @@ -239,8 +239,12 @@ static struct GPUTextureState { int curtileYRep, tileYRep; Image *ima, *curima; - int domipmap, linearmipmap; - int texpaint; /* store this so that new images created while texture painting won't be set to mipmapped */ + /* also controls min/mag filtering */ + bool domipmap; + /* only use when 'domipmap' is set */ + bool linearmipmap; + /* store this so that new images created while texture painting won't be set to mipmapped */ + bool texpaint; int alphablend; float anisotropic; @@ -281,49 +285,53 @@ static void gpu_generate_mipmap(GLenum target) glDisable(target); } -void GPU_set_mipmap(int mipmap) +void GPU_set_mipmap(bool mipmap) { - if (GTS.domipmap != (mipmap != 0)) { + if (GTS.domipmap != mipmap) { GPU_free_images(); - GTS.domipmap = mipmap != 0; + GTS.domipmap = mipmap; } } -void GPU_set_linear_mipmap(int linear) +void GPU_set_linear_mipmap(bool linear) { - if (GTS.linearmipmap != (linear != 0)) { - GPU_free_images(); - GTS.linearmipmap = linear != 0; + if (GTS.linearmipmap != linear) { + GTS.linearmipmap = linear; } } -int GPU_get_mipmap(void) +bool GPU_get_mipmap(void) { return GTS.domipmap && !GTS.texpaint; } -int GPU_get_linear_mipmap(void) +bool GPU_get_linear_mipmap(void) { return GTS.linearmipmap; } -static GLenum gpu_get_mipmap_filter(int mag) +static GLenum gpu_get_mipmap_filter(bool mag) { /* linearmipmap is off by default *when mipmapping is off, * use unfiltered display */ if (mag) { - if (GTS.linearmipmap || GTS.domipmap) + if (GTS.domipmap) return GL_LINEAR; else return GL_NEAREST; } else { - if (GTS.linearmipmap) - return GL_LINEAR_MIPMAP_LINEAR; - else if (GTS.domipmap) - return GL_LINEAR_MIPMAP_NEAREST; - else + if (GTS.domipmap) { + if (GTS.linearmipmap) { + return GL_LINEAR_MIPMAP_LINEAR; + } + else { + return GL_LINEAR_MIPMAP_NEAREST; + } + } + else { return GL_NEAREST; + } } } @@ -931,7 +939,7 @@ int GPU_set_tpage(MTFace *tface, int mipmap, int alphablend) * temporary disabling/enabling mipmapping on all images for quick texture * updates with glTexSubImage2D. images that didn't change don't have to be * re-uploaded to OpenGL */ -void GPU_paint_set_mipmap(int mipmap) +void GPU_paint_set_mipmap(bool mipmap) { Image *ima; diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index 0d735d11902..54e3339eb29 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -560,7 +560,8 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const f GPUTexture *tex; GLenum type, format, internalformat; void *pixels = NULL; - const float vfBorderColor[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + int r_width; + bool rescale = false; if (!GLEW_VERSION_1_2) return NULL; @@ -603,37 +604,90 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const f internalformat = GL_INTENSITY; } + /* 3D textures are quite heavy, test if it's possible to create them first */ + glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL); + glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width); + + while (r_width == 0) { + rescale = true; + tex->w /= 2; + tex->h /= 2; + tex->depth /= 2; + glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL); + glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width); + } + + /* really unlikely to happen but keep this just in case */ + tex->w = max_ii(tex->w, 1); + tex->h = max_ii(tex->h, 1); + tex->depth = max_ii(tex->depth, 1); + #if 0 if (fpixels) pixels = GPU_texture_convert_pixels(w*h*depth, fpixels); #endif - glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL); - GPU_ASSERT_NO_GL_ERRORS("3D glTexImage3D"); - if (fpixels) { - if (!GPU_non_power_of_two_support() && (w != tex->w || h != tex->h || depth != tex->depth)) { - /* clear first to avoid unitialized pixels */ - float *zero= MEM_callocN(sizeof(float)*tex->w*tex->h*tex->depth, "zero"); - glTexSubImage3D(tex->target, 0, 0, 0, 0, tex->w, tex->h, tex->depth, format, type, zero); - MEM_freeN(zero); + /* hardcore stuff, 3D texture rescaling - warning, this is gonna hurt your performance a lot, but we need it + * for gooseberry */ + if (rescale && fpixels) { + unsigned int i, j, k; + unsigned int xf = w / tex->w, yf = h / tex->h, zf = depth / tex->depth; + float *tex3d = MEM_mallocN(channels * sizeof(float)*tex->w*tex->h*tex->depth, "tex3d"); + + GPU_print_error_debug("You need to scale a 3D texture, feel the pain!"); + + for (k = 0; k < tex->depth; k++) { + for (j = 0; j < tex->h; j++) { + for (i = 0; i < tex->w; i++) { + /* obviously doing nearest filtering here, it's going to be slow in any case, let's not make it worse */ + float xb = i * xf; + float yb = j * yf; + float zb = k * zf; + unsigned int offset = k * (tex->w * tex->h) + i * tex->h + j; + unsigned int offset_orig = (zb) * (w * h) + (xb) * h + (yb); + + if (channels == 4) { + tex3d[offset * 4] = fpixels[offset_orig * 4]; + tex3d[offset * 4 + 1] = fpixels[offset_orig * 4 + 1]; + tex3d[offset * 4 + 2] = fpixels[offset_orig * 4 + 2]; + tex3d[offset * 4 + 3] = fpixels[offset_orig * 4 + 3]; + } + else + tex3d[offset] = fpixels[offset_orig]; + } + } } - glTexSubImage3D(tex->target, 0, 0, 0, 0, w, h, depth, format, type, fpixels); - GPU_ASSERT_NO_GL_ERRORS("3D glTexSubImage3D"); + glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, tex3d); + + MEM_freeN(tex3d); + } + else { + if (fpixels) { + if (!GPU_non_power_of_two_support() && (w != tex->w || h != tex->h || depth != tex->depth)) { + /* clear first to avoid unitialized pixels */ + float *zero= MEM_callocN(sizeof(float)*tex->w*tex->h*tex->depth, "zero"); + glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL); + glTexSubImage3D(tex->target, 0, 0, 0, 0, tex->w, tex->h, tex->depth, GL_INTENSITY, GL_FLOAT, zero); + glTexSubImage3D(tex->target, 0, 0, 0, 0, w, h, depth, format, type, fpixels); + MEM_freeN(zero); + } + else { + glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, fpixels); + } + + GPU_ASSERT_NO_GL_ERRORS("3D glTexSubImage3D"); + } } - glTexParameterfv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, vfBorderColor); - GPU_ASSERT_NO_GL_ERRORS("3D GL_TEXTURE_BORDER_COLOR"); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - GPU_ASSERT_NO_GL_ERRORS("3D GL_LINEAR"); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - GPU_ASSERT_NO_GL_ERRORS("3D GL_CLAMP_TO_BORDER"); if (pixels) MEM_freeN(pixels); @@ -2030,6 +2084,34 @@ void GPU_shader_free_builtin_shaders(void) } } +bool GPU_mem_stats_supported(void) +{ + return (GLEW_NVX_gpu_memory_info || (GLEW_ATI_meminfo)) && (G.debug & G_DEBUG_GPU_MEM); +} + + +void GPU_mem_stats_get(int *totalmem, int *freemem) +{ + if (GLEW_NVX_gpu_memory_info) { + /* returned value in Kb */ + glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, totalmem); + + glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, freemem); + } + else if (GLEW_ATI_meminfo) { + int stats[4]; + + glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, stats); + *freemem = stats[0]; + *totalmem = 0; + } + else { + *totalmem = 0; + *freemem = 0; + } +} + + #if 0 /* unused */ /* GPUPixelBuffer */ diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 4d46ef3af7b..12672b5f5af 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -102,7 +102,6 @@ struct GPUMaterial { /* for binding the material */ GPUPass *pass; GPUVertexAttribs attribs; - int bound; int builtins; int alpha, obcolalpha; int dynproperty; @@ -114,6 +113,7 @@ struct GPUMaterial { int cameratexcofacloc; ListBase lamps; + bool bound; }; struct GPULamp { @@ -400,7 +400,7 @@ void GPU_material_unbind(GPUMaterial *material) } } -int GPU_material_bound(GPUMaterial *material) +bool GPU_material_bound(GPUMaterial *material) { return material->bound; } diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index a39832dd1cb..7c7f2db09d2 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -547,8 +547,21 @@ void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height, const float col[4], struct ColorManagedDisplay *display, int x1, int y1, int x2, int y2); -/* defined in metadata.c */ +/** + * + * \attention Defined in metadata.c + */ +/** read the field from the image info into the field + * \param img - the ImBuf that contains the image data + * \param key - the key of the field + * \param value - the data in the field, first one found with key is returned, + * memory has to be allocated by user. + * \param len - length of value buffer allocated by user. + * \return - 1 (true) if ImageInfo present and value for the key found, 0 (false) otherwise + */ +bool IMB_metadata_get_field(struct ImBuf *img, const char *key, char *value, const size_t len); bool IMB_metadata_change_field(struct ImBuf *img, const char *key, const char *field); +void IMB_metadata_copy(struct ImBuf *dimb, struct ImBuf *simb); /* exported for image tools in blender, to quickly allocate 32 bits rect */ bool imb_addrectImBuf(struct ImBuf *ibuf); diff --git a/source/blender/imbuf/intern/IMB_filetype.h b/source/blender/imbuf/intern/IMB_filetype.h index 9327c15c415..0e6438fb729 100644 --- a/source/blender/imbuf/intern/IMB_filetype.h +++ b/source/blender/imbuf/intern/IMB_filetype.h @@ -88,7 +88,7 @@ int imb_savejp2(struct ImBuf *ibuf, const char *name, int flags); /* jpeg */ int imb_is_a_jpeg(unsigned char *mem); int imb_savejpeg(struct ImBuf *ibuf, const char *name, int flags); -struct ImBuf *imb_load_jpeg (unsigned char *buffer, size_t size, int flags, char colorspace[IM_MAX_SPACE]); +struct ImBuf *imb_load_jpeg(unsigned char *buffer, size_t size, int flags, char colorspace[IM_MAX_SPACE]); /* bmp */ int imb_is_a_bmp(unsigned char *buf); diff --git a/source/blender/imbuf/intern/IMB_metadata.h b/source/blender/imbuf/intern/IMB_metadata.h index 5d4a0028ee1..bc0b2c70ecb 100644 --- a/source/blender/imbuf/intern/IMB_metadata.h +++ b/source/blender/imbuf/intern/IMB_metadata.h @@ -47,16 +47,6 @@ struct ImBuf; /* free blender ImMetaData struct */ void IMB_metadata_free(struct ImBuf *img); -/** read the field from the image info into the field - * \param img - the ImBuf that contains the image data - * \param key - the key of the field - * \param value - the data in the field, first one found with key is returned, - * memory has to be allocated by user. - * \param len - length of value buffer allocated by user. - * \return - 1 (true) if ImageInfo present and value for the key found, 0 (false) otherwise - */ -bool IMB_metadata_get_field(struct ImBuf *img, const char *key, char *value, const size_t len); - /** set user data in the ImMetaData struct, which has to be allocated with IMB_metadata_create * before calling this function. * \param img - the ImBuf that contains the image data diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c index b28d19e3e15..79f869968d3 100644 --- a/source/blender/imbuf/intern/allocimbuf.c +++ b/source/blender/imbuf/intern/allocimbuf.c @@ -210,6 +210,8 @@ ImBuf *IMB_makeSingleUser(ImBuf *ibuf) rval = IMB_dupImBuf(ibuf); + IMB_metadata_copy(rval, ibuf); + IMB_freeImBuf(ibuf); return rval; @@ -465,10 +467,10 @@ ImBuf *IMB_dupImBuf(ImBuf *ibuf1) if (ibuf2 == NULL) return NULL; if (flags & IB_rect) - memcpy(ibuf2->rect, ibuf1->rect, x * y * sizeof(int)); + memcpy(ibuf2->rect, ibuf1->rect, ((size_t)x) * y * sizeof(int)); if (flags & IB_rectfloat) - memcpy(ibuf2->rect_float, ibuf1->rect_float, ibuf1->channels * x * y * sizeof(float)); + memcpy(ibuf2->rect_float, ibuf1->rect_float, ((size_t)ibuf1->channels) * x * y * sizeof(float)); if (ibuf1->encodedbuffer) { ibuf2->encodedbuffersize = ibuf1->encodedbuffersize; diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 20baa1614c9..d6fdcad0819 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1306,8 +1306,8 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l float dither = ibuf->dither; bool is_data = (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) != 0; - int offset = channels * start_line * ibuf->x; - int display_buffer_byte_offset = DISPLAY_BUFFER_CHANNELS * start_line * ibuf->x; + size_t offset = ((size_t)channels) * start_line * ibuf->x; + size_t display_buffer_byte_offset = ((size_t)DISPLAY_BUFFER_CHANNELS) * start_line * ibuf->x; memset(handle, 0, sizeof(DisplayBufferThread)); @@ -1344,7 +1344,7 @@ static void display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle, int channels = handle->channels; int width = handle->width; - int buffer_size = channels * width * height; + size_t buffer_size = ((size_t)channels) * width * height; bool is_data = handle->is_data; bool is_data_display = handle->cm_processor->is_data_result; @@ -1357,11 +1357,11 @@ static void display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle, float *fp; unsigned char *cp; - int i; + size_t i; /* first convert byte buffer to float, keep in image space */ for (i = 0, fp = linear_buffer, cp = byte_buffer; - i < width * height; + i < ((size_t)width) * height; i++, fp += channels, cp += channels) { if (channels == 3) { @@ -1440,7 +1440,7 @@ static void *do_display_buffer_apply_thread(void *handle_v) } else { bool is_straight_alpha, predivide; - float *linear_buffer = MEM_mallocN(channels * width * height * sizeof(float), + float *linear_buffer = MEM_mallocN(((size_t)channels) * width * height * sizeof(float), "color conversion linear buffer"); display_buffer_apply_get_linear_buffer(handle, height, linear_buffer, &is_straight_alpha); @@ -1467,14 +1467,14 @@ static void *do_display_buffer_apply_thread(void *handle_v) } if (display_buffer) { - memcpy(display_buffer, linear_buffer, width * height * channels * sizeof(float)); + memcpy(display_buffer, linear_buffer, ((size_t)width) * height * channels * sizeof(float)); if (is_straight_alpha && channels == 4) { - int i; + size_t i; float *fp; for (i = 0, fp = display_buffer; - i < width * height; + i < ((size_t)width) * height; i++, fp += channels) { straight_to_premul_v4(fp); @@ -2959,7 +2959,7 @@ void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, flo for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { - float *pixel = buffer + channels * (y * width + x); + float *pixel = buffer + channels * (((size_t)y) * width + x); curve_mapping_apply_pixel(cm_processor->curve_mapping, pixel, channels); } diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp index 15c8d86d61c..6bf82776afe 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp @@ -60,6 +60,7 @@ #include <PixelFormat.h> #include <stdio.h> // printf +#include <stdlib.h> // malloc #include <math.h> // sqrt #include <sys/types.h> @@ -1147,7 +1148,7 @@ void* DirectDrawSurface::readData(uint &rsize) uint size = stream.size - header_size; rsize = size; - unsigned char *data = new unsigned char[size]; + unsigned char *data = (unsigned char *)malloc(sizeof(*data) * size); stream.seek(header_size); mem_read(stream, data, size); diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index 3417fe2fc1d..455b78bce4d 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -184,16 +184,16 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, if (channels_from == 1) { /* single channel input */ - const float *from = rect_from + stride_from * y; - uchar *to = rect_to + stride_to * y * 4; + const float *from = rect_from + ((size_t)stride_from) * y; + uchar *to = rect_to + ((size_t)stride_to) * y * 4; for (x = 0; x < width; x++, from++, to += 4) to[0] = to[1] = to[2] = to[3] = FTOCHAR(from[0]); } else if (channels_from == 3) { /* RGB input */ - const float *from = rect_from + stride_from * y * 3; - uchar *to = rect_to + stride_to * y * 4; + const float *from = rect_from + ((size_t)stride_from) * y * 3; + uchar *to = rect_to + ((size_t)stride_to) * y * 4; if (profile_to == profile_from) { /* no color space conversion */ @@ -221,8 +221,8 @@ void IMB_buffer_byte_from_float(uchar *rect_to, const float *rect_from, } else if (channels_from == 4) { /* RGBA input */ - const float *from = rect_from + stride_from * y * 4; - uchar *to = rect_to + stride_to * y * 4; + const float *from = rect_from + ((size_t)stride_from) * y * 4; + uchar *to = rect_to + ((size_t)stride_to) * y * 4; if (profile_to == profile_from) { float straight[4]; @@ -334,8 +334,8 @@ void IMB_buffer_byte_from_float_mask(uchar *rect_to, const float *rect_from, if (channels_from == 1) { /* single channel input */ - const float *from = rect_from + stride_from * y; - uchar *to = rect_to + stride_to * y * 4; + const float *from = rect_from + ((size_t)stride_from) * y; + uchar *to = rect_to + ((size_t)stride_to) * y * 4; for (x = 0; x < width; x++, from++, to += 4) if (*mask++ == FILTER_MASK_USED) @@ -343,8 +343,8 @@ void IMB_buffer_byte_from_float_mask(uchar *rect_to, const float *rect_from, } else if (channels_from == 3) { /* RGB input */ - const float *from = rect_from + stride_from * y * 3; - uchar *to = rect_to + stride_to * y * 4; + const float *from = rect_from + ((size_t)stride_from) * y * 3; + uchar *to = rect_to + ((size_t)stride_to) * y * 4; for (x = 0; x < width; x++, from += 3, to += 4) { if (*mask++ == FILTER_MASK_USED) { @@ -355,8 +355,8 @@ void IMB_buffer_byte_from_float_mask(uchar *rect_to, const float *rect_from, } else if (channels_from == 4) { /* RGBA input */ - const float *from = rect_from + stride_from * y * 4; - uchar *to = rect_to + stride_to * y * 4; + const float *from = rect_from + ((size_t)stride_from) * y * 4; + uchar *to = rect_to + ((size_t)stride_to) * y * 4; float straight[4]; @@ -408,7 +408,7 @@ void IMB_buffer_float_from_byte(float *rect_to, const uchar *rect_from, /* RGBA input */ for (y = 0; y < height; y++) { const uchar *from = rect_from + stride_from * y * 4; - float *to = rect_to + stride_to * y * 4; + float *to = rect_to + ((size_t)stride_to) * y * 4; if (profile_to == profile_from) { /* no color space conversion */ @@ -460,8 +460,8 @@ void IMB_buffer_float_from_float(float *rect_to, const float *rect_from, if (channels_from == 1) { /* single channel input */ for (y = 0; y < height; y++) { - const float *from = rect_from + stride_from * y; - float *to = rect_to + stride_to * y * 4; + const float *from = rect_from + ((size_t)stride_from) * y; + float *to = rect_to + ((size_t)stride_to) * y * 4; for (x = 0; x < width; x++, from++, to += 4) to[0] = to[1] = to[2] = to[3] = from[0]; @@ -470,8 +470,8 @@ void IMB_buffer_float_from_float(float *rect_to, const float *rect_from, else if (channels_from == 3) { /* RGB input */ for (y = 0; y < height; y++) { - const float *from = rect_from + stride_from * y * 3; - float *to = rect_to + stride_to * y * 4; + const float *from = rect_from + ((size_t)stride_from) * y * 3; + float *to = rect_to + ((size_t)stride_to) * y * 4; if (profile_to == profile_from) { /* no color space conversion */ @@ -499,12 +499,12 @@ void IMB_buffer_float_from_float(float *rect_to, const float *rect_from, else if (channels_from == 4) { /* RGBA input */ for (y = 0; y < height; y++) { - const float *from = rect_from + stride_from * y * 4; - float *to = rect_to + stride_to * y * 4; + const float *from = rect_from + ((size_t)stride_from) * y * 4; + float *to = rect_to + ((size_t)stride_to) * y * 4; if (profile_to == profile_from) { /* same profile, copy */ - memcpy(to, from, sizeof(float) * 4 * width); + memcpy(to, from, sizeof(float) * ((size_t)4) * width); } else if (profile_to == IB_PROFILE_LINEAR_RGB) { /* convert to sRGB to linear */ @@ -541,8 +541,8 @@ void IMB_buffer_float_from_float_mask(float *rect_to, const float *rect_from, in if (channels_from == 1) { /* single channel input */ for (y = 0; y < height; y++) { - const float *from = rect_from + stride_from * y; - float *to = rect_to + stride_to * y * 4; + const float *from = rect_from + ((size_t)stride_from) * y; + float *to = rect_to + ((size_t)stride_to) * y * 4; for (x = 0; x < width; x++, from++, to += 4) if (*mask++ == FILTER_MASK_USED) @@ -552,8 +552,8 @@ void IMB_buffer_float_from_float_mask(float *rect_to, const float *rect_from, in else if (channels_from == 3) { /* RGB input */ for (y = 0; y < height; y++) { - const float *from = rect_from + stride_from * y * 3; - float *to = rect_to + stride_to * y * 4; + const float *from = rect_from + ((size_t)stride_from) * y * 3; + float *to = rect_to + ((size_t)stride_to) * y * 4; for (x = 0; x < width; x++, from += 3, to += 4) { if (*mask++ == FILTER_MASK_USED) { @@ -566,8 +566,8 @@ void IMB_buffer_float_from_float_mask(float *rect_to, const float *rect_from, in else if (channels_from == 4) { /* RGBA input */ for (y = 0; y < height; y++) { - const float *from = rect_from + stride_from * y * 4; - float *to = rect_to + stride_to * y * 4; + const float *from = rect_from + ((size_t)stride_from) * y * 4; + float *to = rect_to + ((size_t)stride_to) * y * 4; for (x = 0; x < width; x++, from += 4, to += 4) if (*mask++ == FILTER_MASK_USED) @@ -590,8 +590,8 @@ void IMB_buffer_byte_from_byte(uchar *rect_to, const uchar *rect_from, /* always RGBA input */ for (y = 0; y < height; y++) { - const uchar *from = rect_from + stride_from * y * 4; - uchar *to = rect_to + stride_to * y * 4; + const uchar *from = rect_from + ((size_t)stride_from) * y * 4; + uchar *to = rect_to + ((size_t)stride_to) * y * 4; if (profile_to == profile_from) { /* same profile, copy */ @@ -690,8 +690,8 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w imb_addrectImBuf(ibuf); /* do conversion */ - rect_float = ibuf->rect_float + (x + y * ibuf->x) * ibuf->channels; - rect_byte = (uchar *)ibuf->rect + (x + y * ibuf->x) * 4; + rect_float = ibuf->rect_float + (x + ((size_t)y) * ibuf->x) * ibuf->channels; + rect_byte = (uchar *)ibuf->rect + (x + ((size_t)y) * ibuf->x) * 4; if (is_data) { /* exception for non-color data, just copy float */ @@ -734,9 +734,9 @@ void IMB_float_from_rect(ImBuf *ibuf) */ rect_float = ibuf->rect_float; if (rect_float == NULL) { - int size; + size_t size; - size = ibuf->x * ibuf->y; + size = ((size_t)ibuf->x) * ibuf->y; size = size * 4 * sizeof(float); ibuf->channels = 4; @@ -771,22 +771,22 @@ void IMB_color_to_bw(ImBuf *ibuf) { float *rct_fl = ibuf->rect_float; uchar *rct = (uchar *)ibuf->rect; - int i; + size_t i; if (rct_fl) { - for (i = ibuf->x * ibuf->y; i > 0; i--, rct_fl += 4) + for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, rct_fl += 4) rct_fl[0] = rct_fl[1] = rct_fl[2] = IMB_colormanagement_get_luminance(rct_fl); } if (rct) { - for (i = ibuf->x * ibuf->y; i > 0; i--, rct += 4) + for (i = ((size_t)ibuf->x * ibuf->y); i > 0; i--, rct += 4) rct[0] = rct[1] = rct[2] = IMB_colormanagement_get_luminance_byte(rct); } } void IMB_buffer_float_clamp(float *buf, int width, int height) { - int i, total = width * height * 4; + size_t i, total = ((size_t)width) * height * 4; for (i = 0; i < total; i++) { buf[i] = min_ff(1.0, buf[i]); } @@ -794,7 +794,7 @@ void IMB_buffer_float_clamp(float *buf, int width, int height) void IMB_buffer_float_unpremultiply(float *buf, int width, int height) { - int total = width * height; + size_t total = ((size_t)width) * height; float *fp = buf; while (total--) { premul_to_straight_v4(fp); @@ -804,7 +804,7 @@ void IMB_buffer_float_unpremultiply(float *buf, int width, int height) void IMB_buffer_float_premultiply(float *buf, int width, int height) { - int total = width * height; + size_t total = ((size_t)width) * height; float *fp = buf; while (total--) { straight_to_premul_v4(fp); @@ -816,14 +816,14 @@ void IMB_buffer_float_premultiply(float *buf, int width, int height) void IMB_saturation(ImBuf *ibuf, float sat) { - int i; + size_t i; unsigned char *rct = (unsigned char *)ibuf->rect; float *rct_fl = ibuf->rect_float; float hsv[3]; if (rct) { float rgb[3]; - for (i = ibuf->x * ibuf->y; i > 0; i--, rct += 4) { + for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, rct += 4) { rgb_uchar_to_float(rgb, rct); rgb_to_hsv_v(rgb, hsv); hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rgb, rgb + 1, rgb + 2); @@ -832,7 +832,7 @@ void IMB_saturation(ImBuf *ibuf, float sat) } if (rct_fl) { - for (i = ibuf->x * ibuf->y; i > 0; i--, rct_fl += 4) { + for (i = ((size_t)ibuf->x) * ibuf->y; i > 0; i--, rct_fl += 4) { rgb_to_hsv_v(rct_fl, hsv); hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rct_fl, rct_fl + 1, rct_fl + 2); } diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c index 8234b01992b..90219461772 100644 --- a/source/blender/imbuf/intern/imageprocess.c +++ b/source/blender/imbuf/intern/imageprocess.c @@ -343,7 +343,7 @@ void IMB_processor_apply_threaded(int buffer_lines, int handle_size, void *init_ void IMB_alpha_under_color_float(float *rect_float, int x, int y, float backcol[3]) { - int a = x * y; + size_t a = ((size_t)x) * y; float *fp = rect_float; while (a--) { @@ -366,7 +366,7 @@ void IMB_alpha_under_color_float(float *rect_float, int x, int y, float backcol[ void IMB_alpha_under_color_byte(unsigned char *rect, int x, int y, float backcol[3]) { - int a = x * y; + size_t a = ((size_t)x) * y; unsigned char *cp = rect; while (a--) { diff --git a/source/blender/imbuf/intern/metadata.c b/source/blender/imbuf/intern/metadata.c index 8cb5070dd62..134bbe88f15 100644 --- a/source/blender/imbuf/intern/metadata.c +++ b/source/blender/imbuf/intern/metadata.c @@ -79,6 +79,13 @@ bool IMB_metadata_get_field(struct ImBuf *img, const char *key, char *field, con return retval; } +void IMB_metadata_copy(struct ImBuf *dimb, struct ImBuf *simb) +{ + if (simb->metadata) { + dimb->metadata = IDP_CopyProperty(simb->metadata); + } +} + bool IMB_metadata_add_field(struct ImBuf *img, const char *key, const char *value) { IDProperty *prop; diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 1262f0af95d..58c5be8b110 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -111,8 +111,8 @@ extern "C" static struct ExrPass *imb_exr_get_pass(ListBase *lb, char *passname); static bool exr_has_multiview(MultiPartInputFile& file); static bool exr_has_multipart_file(MultiPartInputFile& file); -static int exr_has_alpha(MultiPartInputFile& file); -static int exr_has_zbuffer(MultiPartInputFile& file); +static bool exr_has_alpha(MultiPartInputFile& file); +static bool exr_has_zbuffer(MultiPartInputFile& file); static void exr_printf(const char *__restrict format, ...); static void imb_exr_type_by_channels(ChannelList& channels, StringVector& views, bool *r_singlelayer, bool *r_multilayer, bool *r_multiview); @@ -368,8 +368,8 @@ static bool imb_save_openexr_half(ImBuf *ibuf, const char *name, const int flags ImBuf * (*getbuffer)(void *base, const size_t view_id)) { const int channels = ibuf->channels; - const int is_alpha = (channels >= 4) && (ibuf->planes == 32); - const int is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */ + const bool is_alpha = (channels >= 4) && (ibuf->planes == 32); + const bool is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */ const int width = ibuf->x; const int height = ibuf->y; const bool is_multiview = (flags & IB_multiview) && ibuf->userdata; @@ -485,8 +485,8 @@ static bool imb_save_openexr_float(ImBuf *ibuf, const char *name, const int flag ImBuf * (*getbuffer)(void *base, const size_t view_id)) { const int channels = ibuf->channels; - const int is_alpha = (channels >= 4) && (ibuf->planes == 32); - const int is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */ + const bool is_alpha = (channels >= 4) && (ibuf->planes == 32); + const bool is_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; /* summarize */ const int width = ibuf->x; const int height = ibuf->y; const bool is_multiview = (flags & IB_multiview) && ibuf->userdata; @@ -1235,9 +1235,15 @@ void IMB_exr_multilayer_convert(void *handle, void *base, ExrLayer *lay; ExrPass *pass; - /* add views to RenderResult */ - for (StringVector::const_iterator i = data->multiView->begin(); i != data->multiView->end(); ++i) { - addview(base, (*i).c_str()); + /* RenderResult needs at least one RenderView */ + if (data->multiView->size() == 0) { + addview(base, ""); + } + else { + /* add views to RenderResult */ + for (StringVector::const_iterator i = data->multiView->begin(); i != data->multiView->end(); ++i) { + addview(base, (*i).c_str()); + } } if (BLI_listbase_is_empty(&data->layers)) { @@ -1266,7 +1272,7 @@ void IMB_exr_multiview_convert(void *handle, void *base, ExrLayer *lay; ExrPass *pass; ImBuf *ibuf = NULL; - const int is_alpha = exr_has_alpha(*file); + const bool is_alpha = exr_has_alpha(*file); Box2i dw = file->header(0).dataWindow(); const size_t width = dw.max.x - dw.min.x + 1; const size_t height = dw.max.y - dw.min.y + 1; @@ -1691,12 +1697,12 @@ static bool exr_has_chroma(MultiPartInputFile& file) file.header(0).channels().findChannel("RY") != NULL; } -static int exr_has_zbuffer(MultiPartInputFile& file) +static bool exr_has_zbuffer(MultiPartInputFile& file) { return !(file.header(0).channels().findChannel("Z") == NULL); } -static int exr_has_alpha(MultiPartInputFile& file) +static bool exr_has_alpha(MultiPartInputFile& file) { return !(file.header(0).channels().findChannel("A") == NULL); } diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c index 4001b681ad9..c7b347cb20c 100644 --- a/source/blender/imbuf/intern/rectop.c +++ b/source/blender/imbuf/intern/rectop.c @@ -322,30 +322,30 @@ void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask, do_float = (sbuf && sbuf->rect_float && dbuf->rect_float && obuf->rect_float); if (do_char) { - drect = dbuf->rect + desty * dbuf->x + destx; - orect = obuf->rect + origy * obuf->x + origx; + drect = dbuf->rect + ((size_t)desty) * dbuf->x + destx; + orect = obuf->rect + ((size_t)origy) * obuf->x + origx; } if (do_float) { - drectf = dbuf->rect_float + (desty * dbuf->x + destx) * 4; - orectf = obuf->rect_float + (origy * obuf->x + origx) * 4; + drectf = dbuf->rect_float + (((size_t)desty) * dbuf->x + destx) * 4; + orectf = obuf->rect_float + (((size_t)origy) * obuf->x + origx) * 4; } if (dmaskrect) - dmaskrect += origy * obuf->x + origx; + dmaskrect += ((size_t)origy) * obuf->x + origx; destskip = dbuf->x; origskip = obuf->x; if (sbuf) { - if (do_char) srect = sbuf->rect + srcy * sbuf->x + srcx; - if (do_float) srectf = sbuf->rect_float + (srcy * sbuf->x + srcx) * 4; + if (do_char) srect = sbuf->rect + ((size_t)srcy) * sbuf->x + srcx; + if (do_float) srectf = sbuf->rect_float + (((size_t)srcy) * sbuf->x + srcx) * 4; srcskip = sbuf->x; if (cmaskrect) - cmaskrect += srcy * sbuf->x + srcx; + cmaskrect += ((size_t)srcy) * sbuf->x + srcx; if (texmaskrect) - texmaskrect += srcy * sbuf->x + srcx; + texmaskrect += ((size_t)srcy) * sbuf->x + srcx; } else { srect = drect; diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index 2318553eecc..a608aa0db34 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -283,9 +283,14 @@ static bool thumbpath_from_uri(const char *uri, char *path, const int path_len, void IMB_thumb_makedirs(void) { char tpath[FILE_MAX]; +#if 0 /* UNUSED */ if (get_thumb_dir(tpath, THB_NORMAL)) { BLI_dir_create_recursive(tpath); } +#endif + if (get_thumb_dir(tpath, THB_LARGE)) { + BLI_dir_create_recursive(tpath); + } if (get_thumb_dir(tpath, THB_FAIL)) { BLI_dir_create_recursive(tpath); } diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index 205ed7e7380..40c028c3aa1 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -157,6 +157,7 @@ typedef struct Nurb { short tilt_interp; /* KEY_LINEAR, KEY_CARDINAL, KEY_BSPLINE */ short radius_interp; + /* only used for dynamically generated Nurbs created from OB_FONT's */ int charidx; } Nurb; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 0e4a0c77950..725f2e9fb42 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -657,8 +657,10 @@ typedef struct RenderData { /* render simplify */ int simplify_flag; short simplify_subsurf; - short simplify_shadowsamples; + short simplify_subsurf_render; + short simplify_shadowsamples, pad9; float simplify_particles; + float simplify_particles_render; float simplify_aosss; /* cineon */ diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index 84ac0c5e792..eb76c90c0fc 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -281,6 +281,8 @@ enum { AREA_FLAG_TEMP_TYPE = (1 << 6), /* for temporary fullscreens (file browser, image editor render) that are opened above user set fullscreens */ AREA_FLAG_STACKED_FULLSCREEN = (1 << 7), + /* update action zones (even if the mouse is not intersecting them) */ + AREA_FLAG_ACTIONZONES_UPDATE = (1 << 8), }; #define EDGEWIDTH 1 @@ -372,6 +374,8 @@ enum { RGN_TYPE_TOOL_PROPS = 6, RGN_TYPE_PREVIEW = 7 }; +/* use for function args */ +#define RGN_TYPE_ANY -1 /* region alignment */ #define RGN_ALIGN_NONE 0 diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 29b78c158fd..d6785da7486 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -534,6 +534,7 @@ typedef enum eSpaceSeq_Flag { SEQ_ALL_WAVEFORMS = (1 << 7), /* draw all waveforms */ SEQ_NO_WAVEFORMS = (1 << 8), /* draw no waveforms */ SEQ_SHOW_SAFE_CENTER = (1 << 9), + SEQ_SHOW_METADATA = (1 << 10), } eSpaceSeq_Flag; /* sseq->view */ @@ -590,6 +591,8 @@ typedef struct FileSelectParams { int active_file; int sel_first; int sel_last; + unsigned short thumbnail_size; + short pad; /* short */ short type; /* XXXXX for now store type here, should be moved to the operator */ @@ -834,6 +837,7 @@ typedef enum eSpaceImage_Flag { SI_COLOR_CORRECTION = (1 << 24), SI_NO_DRAW_TEXPAINT = (1 << 25), + SI_DRAW_METADATA = (1 << 26) } eSpaceImage_Flag; /* Text Editor ============================================ */ diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index afa1f03a8ca..e0b51a1b25b 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -338,6 +338,9 @@ typedef struct ThemeSpace { char paint_curve_pivot[4]; char paint_curve_handle[4]; + + char metadatabg[4]; + char metadatatext[4]; } ThemeSpace; diff --git a/source/blender/makesdna/DNA_view2d_types.h b/source/blender/makesdna/DNA_view2d_types.h index a7921be44d5..6f2e347c84d 100644 --- a/source/blender/makesdna/DNA_view2d_types.h +++ b/source/blender/makesdna/DNA_view2d_types.h @@ -43,7 +43,7 @@ typedef struct View2D { rcti mask; /* mask - region (in screenspace) within which 'cur' can be viewed */ float min[2], max[2]; /* min/max sizes of 'cur' rect (only when keepzoom not set) */ - float minzoom, maxzoom; /* self explanatory. allowable zoom factor range (only when keepzoom set) */ + float minzoom, maxzoom; /* allowable zoom factor range (only when (keepzoom & V2D_LIMITZOOM)) is set */ short scroll; /* scroll - scrollbars to display (bitflag) */ short scroll_ui; /* scroll_ui - temp settings used for UI drawing of scrollers */ diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 66ee1fe4242..a0516590d43 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -379,6 +379,9 @@ enum { #define RV3D_CAMZOOM_MIN -30 #define RV3D_CAMZOOM_MAX 600 -#endif +/* #BKE_screen_view3d_zoom_to_fac() values above */ +#define RV3D_CAMZOOM_MIN_FACTOR 0.1657359312880714853f +#define RV3D_CAMZOOM_MAX_FACTOR 44.9852813742385702928f +#endif diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 6eb2f2487b0..51ed8bb6c0d 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -390,10 +390,16 @@ enum { /* wmOperator flag */ enum { - OP_GRAB_POINTER = (1 << 0), /* low level flag so exec() operators can tell if they were invoked, use with care. * typically this shouldn't make any difference, but it rare cases its needed (see smooth-view) */ - OP_IS_INVOKE = (1 << 1), + OP_IS_INVOKE = (1 << 0), + + /* When the cursor is grabbed */ + OP_IS_MODAL_GRAB_CURSOR = (1 << 1), + + /* allow modal operators to have the region under the cursor for their context + * (the regiontype is maintained to prevent errors) */ + OP_IS_MODAL_CURSOR_REGION = (1 << 2), }; #endif /* __DNA_WINDOWMANAGER_TYPES_H__ */ diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c index 481d139a9de..6140a34b271 100644 --- a/source/blender/makesrna/intern/rna_lamp.c +++ b/source/blender/makesrna/intern/rna_lamp.c @@ -828,7 +828,8 @@ static void rna_def_sun_lamp(BlenderRNA *brna) prop = RNA_def_property(srna, "show_shadow_box", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "mode", LA_SHOW_SHADOW_BOX); - RNA_def_property_ui_text(prop, "Show Shadow Box", "Draw box in 3D view to visualize which object are contained in it"); + RNA_def_property_ui_text(prop, "Show Shadow Box", + "Draw a box in 3D view to visualize which objects are contained in it"); RNA_def_property_update(prop, 0, "rna_Lamp_draw_update"); } diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index 59c3befad9e..168f23ceaa1 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -61,6 +61,7 @@ #include "BKE_image.h" #include "BKE_texture.h" #include "BKE_scene.h" +#include "BKE_sound.h" #include "BKE_text.h" #include "BKE_action.h" #include "BKE_group.h" @@ -87,6 +88,7 @@ #include "DNA_mesh_types.h" #include "DNA_object_types.h" #include "DNA_speaker_types.h" +#include "DNA_sound_types.h" #include "DNA_text_types.h" #include "DNA_texture_types.h" #include "DNA_group_types.h" @@ -548,6 +550,25 @@ static void rna_Main_speakers_remove(Main *bmain, ReportList *reports, PointerRN } } +static bSound *rna_Main_sounds_load(Main *bmain, const char *name) +{ + bSound *sound = BKE_sound_new_file(bmain, name); + id_us_min(&sound->id); + return sound; +} +static void rna_Main_sounds_remove(Main *bmain, ReportList *reports, PointerRNA *sound_ptr) +{ + Speaker *sound = sound_ptr->data; + if (ID_REAL_USERS(sound) <= 0) { + BKE_libblock_free(bmain, sound); + RNA_POINTER_INVALIDATE(sound_ptr); + } + else { + BKE_reportf(reports, RPT_ERROR, "Sound '%s' must have zero users to be removed, found %d", + sound->id.name + 2, ID_REAL_USERS(sound)); + } +} + static Text *rna_Main_texts_new(Main *bmain, const char *name) { return BKE_text_add(bmain, name); @@ -1585,7 +1606,21 @@ void RNA_def_main_sounds(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_struct_sdna(srna, "Main"); RNA_def_struct_ui_text(srna, "Main Sounds", "Collection of sounds"); - /* TODO, 'load' */ + /* load func */ + func = RNA_def_function(srna, "load", "rna_Main_sounds_load"); + RNA_def_function_ui_description(func, "Add a new sound to the main database from a file"); + parm = RNA_def_string_file_path(func, "filepath", "Path", FILE_MAX, "", "path for the datablock"); + RNA_def_property_flag(parm, PROP_REQUIRED); + /* return type */ + parm = RNA_def_pointer(func, "sound", "Sound", "", "New text datablock"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_Main_sounds_remove"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_ui_description(func, "Remove a sound from the current blendfile"); + parm = RNA_def_pointer(func, "sound", "Sound", "", "Sound to remove"); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR); + RNA_def_property_clear_flag(parm, PROP_THICK_WRAP); func = RNA_def_function(srna, "tag", "rna_Main_sounds_tag"); parm = RNA_def_boolean(func, "value", 0, "Value", ""); diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index b1f0adb0d98..400e98befd0 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -1143,6 +1143,37 @@ static int rna_MeshSkinVertexLayer_data_length(PointerRNA *ptr) /* End skin vertices */ +/* Paint mask */ +DEFINE_CUSTOMDATA_LAYER_COLLECTION(vertex_paint_mask, vdata, CD_PAINT_MASK) + +static char *rna_MeshPaintMaskLayer_path(PointerRNA *ptr) +{ + CustomDataLayer *cdl = ptr->data; + char name_esc[sizeof(cdl->name) * 2]; + BLI_strescape(name_esc, cdl->name, sizeof(name_esc)); + return BLI_sprintfN("vertex_paint_masks[\"%s\"]", name_esc); +} + +static char *rna_MeshPaintMask_path(PointerRNA *ptr) +{ + return rna_VertCustomData_data_path(ptr, "vertex_paint_masks", CD_PAINT_MASK); +} + +static void rna_MeshPaintMaskLayer_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + Mesh *me = rna_mesh(ptr); + CustomDataLayer *layer = (CustomDataLayer *)ptr->data; + rna_iterator_array_begin(iter, layer->data, sizeof(MFloatProperty), me->totvert, 0, NULL); +} + +static int rna_MeshPaintMaskLayer_data_length(PointerRNA *ptr) +{ + Mesh *me = rna_mesh(ptr); + return me->totvert; +} + +/* End paint mask */ + static void rna_TexturePoly_image_set(PointerRNA *ptr, PointerRNA value) { MTexPoly *tf = (MTexPoly *)ptr->data; @@ -1783,6 +1814,7 @@ static void UNUSED_FUNCTION(rna_mesh_unused)(void) { /* unused functions made by macros */ (void)rna_Mesh_skin_vertice_index_range; + (void)rna_Mesh_vertex_paint_mask_index_range; (void)rna_Mesh_tessface_uv_texture_active_set; (void)rna_Mesh_tessface_uv_texture_clone_get; (void)rna_Mesh_tessface_uv_texture_clone_index_get; @@ -3172,6 +3204,36 @@ static void rna_def_skin_vertices(BlenderRNA *brna, PropertyRNA *UNUSED(cprop)) RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); } +static void rna_def_paint_mask(BlenderRNA *brna, PropertyRNA *UNUSED(cprop)) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "MeshPaintMaskLayer", NULL); + RNA_def_struct_ui_text(srna, "Mesh Paint Mask Layer", "Per-vertex paint mask data"); + RNA_def_struct_sdna(srna, "CustomDataLayer"); + RNA_def_struct_path_func(srna, "rna_MeshPaintMaskLayer_path"); + + prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_type(prop, "MeshPaintMaskProperty"); + RNA_def_property_ui_text(prop, "Data", ""); + + RNA_def_property_collection_funcs(prop, "rna_MeshPaintMaskLayer_data_begin", "rna_iterator_array_next", + "rna_iterator_array_end", "rna_iterator_array_get", + "rna_MeshPaintMaskLayer_data_length", NULL, NULL, NULL); + + srna = RNA_def_struct(brna, "MeshPaintMaskProperty", NULL); + RNA_def_struct_sdna(srna, "MFloatProperty"); + RNA_def_struct_ui_text(srna, "Mesh Paint Mask Property", + "Floating point paint mask value"); + RNA_def_struct_path_func(srna, "rna_MeshPaintMask_path"); + + prop = RNA_def_property(srna, "value", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "f"); + RNA_def_property_ui_text(prop, "Value", ""); + RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); +} + static void rna_def_mesh(BlenderRNA *brna) { StructRNA *srna; @@ -3376,6 +3438,16 @@ static void rna_def_mesh(BlenderRNA *brna) rna_def_skin_vertices(brna, prop); /* End skin vertices */ + /* Paint mask */ + prop = RNA_def_property(srna, "vertex_paint_masks", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "vdata.layers", "vdata.totlayer"); + RNA_def_property_collection_funcs(prop, "rna_Mesh_vertex_paint_masks_begin", NULL, NULL, NULL, + "rna_Mesh_vertex_paint_masks_length", NULL, NULL, NULL); + RNA_def_property_struct_type(prop, "MeshPaintMaskLayer"); + RNA_def_property_ui_text(prop, "Vertex Paint Mask", "Vertex paint mask"); + rna_def_paint_mask(brna, prop); + /* End paint mask */ + prop = RNA_def_property(srna, "use_auto_smooth", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_AUTOSMOOTH); RNA_def_property_ui_text(prop, "Auto Smooth", diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index da77b9ee6ea..f1b12963c6a 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -2258,8 +2258,13 @@ static void rna_NodeSocketStandard_value_update(struct bContext *C, PointerRNA * nodeFindNode(ntree, sock, &node, NULL); } - if (node) + if (node) { nodeSynchronizeID(node, true); + + /* extra update for sockets that get synced to material */ + if (node->id && ELEM(node->type, SH_NODE_MATERIAL, SH_NODE_MATERIAL_EXT)) + WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, node->id); + } } diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index f5d50f5dfe1..d3d6e0a6ad5 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -1010,7 +1010,7 @@ static int rna_GameObjectSettings_physics_type_get(PointerRNA *ptr) static void rna_GameObjectSettings_physics_type_set(PointerRNA *ptr, int value) { Object *ob = (Object *)ptr->id.data; - const int was_navmesh = (ob->gameflag & OB_NAVMESH); + const int gameflag_prev = ob->gameflag; ob->body_type = value; switch (ob->body_type) { @@ -1068,7 +1068,7 @@ static void rna_GameObjectSettings_physics_type_set(PointerRNA *ptr, int value) break; } - if (was_navmesh != (ob->gameflag & OB_NAVMESH)) { + if ((gameflag_prev & OB_NAVMESH) != (ob->gameflag & OB_NAVMESH)) { if (ob->type == OB_MESH) { /* this is needed to refresh the derived meshes draw func */ DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA); @@ -1687,6 +1687,7 @@ static void rna_def_object_game_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "physics_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "body_type"); RNA_def_property_enum_items(prop, body_type_items); + RNA_def_property_enum_default(prop, OB_BODY_TYPE_STATIC); RNA_def_property_enum_funcs(prop, "rna_GameObjectSettings_physics_type_get", "rna_GameObjectSettings_physics_type_set", NULL); RNA_def_property_ui_text(prop, "Physics Type", "Select the type of physical representation"); @@ -1706,12 +1707,14 @@ static void rna_def_object_game_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "mass", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.01, 10000.0); + RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text(prop, "Mass", "Mass of the object"); prop = RNA_def_property(srna, "radius", PROP_FLOAT, PROP_NONE | PROP_UNIT_LENGTH); RNA_def_property_float_sdna(prop, NULL, "inertia"); RNA_def_property_range(prop, 0.01f, FLT_MAX); RNA_def_property_ui_range(prop, 0.01f, 10.0f, 1, 3); + RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text(prop, "Radius", "Radius of bounding sphere and material physics"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); @@ -1722,11 +1725,13 @@ static void rna_def_object_game_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "damping", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "damping"); RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_float_default(prop, 0.04f); RNA_def_property_ui_text(prop, "Damping", "General movement damping"); prop = RNA_def_property(srna, "rotation_damping", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "rdamping"); RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_float_default(prop, 0.1f); RNA_def_property_ui_text(prop, "Rotation Damping", "General rotation damping"); prop = RNA_def_property(srna, "velocity_min", PROP_FLOAT, PROP_NONE); @@ -1743,16 +1748,19 @@ static void rna_def_object_game_settings(BlenderRNA *brna) 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.01, 1.0); + RNA_def_property_float_default(prop, 0.15f); 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_float_default(prop, 10.0f); 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_float_default(prop, 55.0f); RNA_def_property_ui_text(prop, "Fall Speed Max", "Maximum speed at which the character will fall"); /* Collision Masks */ @@ -1813,6 +1821,7 @@ static void rna_def_object_game_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "form_factor", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "formfactor"); RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_float_default(prop, 0.4f); RNA_def_property_ui_text(prop, "Form Factor", "Form factor scales the inertia tensor"); prop = RNA_def_property(srna, "use_anisotropic_friction", PROP_BOOLEAN, PROP_NONE); @@ -1845,6 +1854,7 @@ static void rna_def_object_game_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "collision_margin", PROP_FLOAT, PROP_NONE | PROP_UNIT_LENGTH); RNA_def_property_float_sdna(prop, NULL, "margin"); RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_float_default(prop, 0.04f); RNA_def_property_ui_text(prop, "Collision Margin", "Extra margin around object for collision detection, small amount required " "for stability"); @@ -1860,6 +1870,7 @@ static void rna_def_object_game_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "obstacle_radius", PROP_FLOAT, PROP_NONE | PROP_UNIT_LENGTH); RNA_def_property_float_sdna(prop, NULL, "obstacleRad"); RNA_def_property_range(prop, 0.0, 1000.0); + RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text(prop, "Obstacle Radius", "Radius of object representation in obstacle simulation"); /* state */ diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 44f2013f2cc..9ea4a40b7ab 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -134,6 +134,7 @@ EnumPropertyItem proportional_falloff_curve_only_items[] = { {PROP_SMOOTH, "SMOOTH", ICON_SMOOTHCURVE, "Smooth", "Smooth falloff"}, {PROP_SPHERE, "SPHERE", ICON_SPHERECURVE, "Sphere", "Spherical falloff"}, {PROP_ROOT, "ROOT", ICON_ROOTCURVE, "Root", "Root falloff"}, + {PROP_INVSQUARE, "INVERSE_SQUARE", ICON_ROOTCURVE, "Inverse Square", "Inverse Square falloff"}, {PROP_SHARP, "SHARP", ICON_SHARPCURVE, "Sharp", "Sharp falloff"}, {PROP_LIN, "LINEAR", ICON_LINCURVE, "Linear", "Linear falloff"}, {0, NULL, 0, NULL, NULL} @@ -373,10 +374,8 @@ EnumPropertyItem stereo3d_display_items[] = { "(anaglyph glasses are required)"}, {S3D_DISPLAY_INTERLACE, "INTERLACE", 0, "Interlace", "Render views for left and right eyes interlaced in a single image (3D-ready monitor is required)"}, -#ifdef DEBUG /* MULTIVIEW_TODO: quadbuffer mode not fully working */ {S3D_DISPLAY_PAGEFLIP, "TIMESEQUENTIAL", 0, "Time Sequential", "Render alternate eyes (also known as page flip, quad buffer support in the graphic card is required)"}, -#endif {S3D_DISPLAY_SIDEBYSIDE, "SIDEBYSIDE", 0, "Side-by-Side", "Render views for left and right eyes side-by-side"}, {S3D_DISPLAY_TOPBOTTOM, "TOPBOTTOM", 0, "Top-Bottom", "Render views for left and right eyes one above another"}, {0, NULL, 0, NULL, NULL} @@ -3493,36 +3492,42 @@ static void rna_def_scene_game_recast_data(BlenderRNA *brna) prop = RNA_def_property(srna, "cell_size", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "cellsize"); RNA_def_property_ui_range(prop, 0.1, 1, 1, 2); + RNA_def_property_float_default(prop, 0.3f); RNA_def_property_ui_text(prop, "Cell Size", "Rasterized cell size"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "cell_height", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "cellheight"); RNA_def_property_ui_range(prop, 0.1, 1, 1, 2); + RNA_def_property_float_default(prop, 0.2f); RNA_def_property_ui_text(prop, "Cell Height", "Rasterized cell height"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "agent_height", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "agentheight"); RNA_def_property_ui_range(prop, 0.1, 5, 1, 2); + RNA_def_property_float_default(prop, 2.0f); RNA_def_property_ui_text(prop, "Agent Height", "Minimum height where the agent can still walk"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "agent_radius", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "agentradius"); RNA_def_property_ui_range(prop, 0.1, 5, 1, 2); + RNA_def_property_float_default(prop, 0.6f); RNA_def_property_ui_text(prop, "Agent Radius", "Radius of the agent"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "climb_max", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "agentmaxclimb"); RNA_def_property_ui_range(prop, 0.1, 5, 1, 2); + RNA_def_property_float_default(prop, 0.9f); RNA_def_property_ui_text(prop, "Max Climb", "Maximum height between grid cells the agent can climb"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "slope_max", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "agentmaxslope"); RNA_def_property_range(prop, 0, M_PI_2); + RNA_def_property_float_default(prop, M_PI_4); RNA_def_property_ui_text(prop, "Max Slope", "Maximum walkable slope angle"); RNA_def_property_update(prop, NC_SCENE, NULL); @@ -3530,42 +3535,49 @@ static void rna_def_scene_game_recast_data(BlenderRNA *brna) prop = RNA_def_property(srna, "region_min_size", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "regionminsize"); RNA_def_property_ui_range(prop, 0, 150, 1, 2); + RNA_def_property_float_default(prop, 8.0f); RNA_def_property_ui_text(prop, "Min Region Size", "Minimum regions size (smaller regions will be deleted)"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "region_merge_size", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "regionmergesize"); RNA_def_property_ui_range(prop, 0, 150, 1, 2); + RNA_def_property_float_default(prop, 20.0f); RNA_def_property_ui_text(prop, "Merged Region Size", "Minimum regions size (smaller regions will be merged)"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "edge_max_len", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "edgemaxlen"); RNA_def_property_ui_range(prop, 0, 50, 1, 2); + RNA_def_property_float_default(prop, 12.0f); RNA_def_property_ui_text(prop, "Max Edge Length", "Maximum contour edge length"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "edge_max_error", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "edgemaxerror"); RNA_def_property_ui_range(prop, 0.1, 3.0, 1, 2); + RNA_def_property_float_default(prop, 1.3f); RNA_def_property_ui_text(prop, "Max Edge Error", "Maximum distance error from contour to cells"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "verts_per_poly", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "vertsperpoly"); RNA_def_property_ui_range(prop, 3, 12, 1, -1); + RNA_def_property_int_default(prop, 6); RNA_def_property_ui_text(prop, "Verts Per Poly", "Max number of vertices per polygon"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "sample_dist", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "detailsampledist"); RNA_def_property_ui_range(prop, 0.0, 16.0, 1, 2); + RNA_def_property_float_default(prop, 6.0f); RNA_def_property_ui_text(prop, "Sample Distance", "Detail mesh sample spacing"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "sample_max_error", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "detailsamplemaxerror"); RNA_def_property_ui_range(prop, 0.0, 16.0, 1, 2); + RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text(prop, "Max Sample Error", "Detail mesh simplification max sample error"); RNA_def_property_update(prop, NC_SCENE, NULL); } @@ -3777,12 +3789,14 @@ static void rna_def_scene_game_data(BlenderRNA *brna) prop = RNA_def_property(srna, "resolution_x", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "xplay"); RNA_def_property_range(prop, 4, 10000); + RNA_def_property_int_default(prop, 640); RNA_def_property_ui_text(prop, "Resolution X", "Number of horizontal pixels in the screen"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "resolution_y", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "yplay"); RNA_def_property_range(prop, 4, 10000); + RNA_def_property_int_default(prop, 480); RNA_def_property_ui_text(prop, "Resolution Y", "Number of vertical pixels in the screen"); RNA_def_property_update(prop, NC_SCENE, NULL); @@ -3799,12 +3813,14 @@ static void rna_def_scene_game_data(BlenderRNA *brna) prop = RNA_def_property(srna, "depth", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "depth"); RNA_def_property_range(prop, 8, 32); + RNA_def_property_int_default(prop, 32); RNA_def_property_ui_text(prop, "Bits", "Display bit depth of full screen display"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "exit_key", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "exitkey"); RNA_def_property_enum_items(prop, event_type_items); + RNA_def_property_enum_default(prop, ESCKEY); RNA_def_property_enum_funcs(prop, NULL, "rna_GameSettings_exit_key_set", NULL); RNA_def_property_ui_text(prop, "Exit Key", "The key that exits the Game Engine"); RNA_def_property_update(prop, NC_SCENE, NULL); @@ -3819,6 +3835,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) prop = RNA_def_property(srna, "frequency", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "freqplay"); RNA_def_property_range(prop, 4, 2000); + RNA_def_property_int_default(prop, 60); RNA_def_property_ui_text(prop, "Freq", "Display clock frequency of fullscreen display"); RNA_def_property_update(prop, NC_SCENE, NULL); @@ -3856,12 +3873,14 @@ static void rna_def_scene_game_data(BlenderRNA *brna) prop = RNA_def_property(srna, "stereo_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "stereomode"); RNA_def_property_enum_items(prop, stereo_modes_items); + RNA_def_property_enum_default(prop, STEREO_ANAGLYPH); RNA_def_property_ui_text(prop, "Stereo Mode", "Stereographic techniques"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "stereo_eye_separation", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "eyeseparation"); RNA_def_property_range(prop, 0.01, 5.0); + RNA_def_property_float_default(prop, 0.1f); RNA_def_property_ui_text(prop, "Eye Separation", "Set the distance between the eyes - the camera focal distance/30 should be fine"); RNA_def_property_update(prop, NC_SCENE, NULL); @@ -3876,18 +3895,21 @@ static void rna_def_scene_game_data(BlenderRNA *brna) prop = RNA_def_property(srna, "dome_tessellation", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "dome.res"); RNA_def_property_ui_range(prop, 1, 8, 1, 1); + RNA_def_property_int_default(prop, 4); RNA_def_property_ui_text(prop, "Tessellation", "Tessellation level - check the generated mesh in wireframe mode"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "dome_buffer_resolution", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "dome.resbuf"); RNA_def_property_ui_range(prop, 0.1, 1.0, 0.1, 2); + RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text(prop, "Buffer Resolution", "Buffer Resolution - decrease it to increase speed"); RNA_def_property_update(prop, NC_SCENE, NULL); prop = RNA_def_property(srna, "dome_angle", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "dome.angle"); RNA_def_property_ui_range(prop, 90, 250, 1, 1); + RNA_def_property_int_default(prop, 180); RNA_def_property_ui_text(prop, "Angle", "Field of View of the Dome - it only works in mode Fisheye and Truncated"); RNA_def_property_update(prop, NC_SCENE, NULL); @@ -3908,6 +3930,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) prop = RNA_def_property(srna, "physics_engine", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "physicsEngine"); RNA_def_property_enum_items(prop, physics_engine_items); + RNA_def_property_enum_default(prop, WOPHY_BULLET); RNA_def_property_ui_text(prop, "Physics Engine", "Physics engine used for physics simulation in the game engine"); RNA_def_property_update(prop, NC_SCENE, NULL); @@ -3915,6 +3938,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "gravity"); RNA_def_property_ui_range(prop, 0.0, 25.0, 1, 2); RNA_def_property_range(prop, 0.0, 10000.0); + RNA_def_property_float_default(prop, 9.8f); RNA_def_property_ui_text(prop, "Physics Gravity", "Gravitational constant used for physics simulation in the game engine"); RNA_def_property_update(prop, NC_SCENE, NULL); @@ -3922,6 +3946,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) prop = RNA_def_property(srna, "occlusion_culling_resolution", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "occlusionRes"); RNA_def_property_range(prop, 128.0, 1024.0); + RNA_def_property_int_default(prop, 128); RNA_def_property_ui_text(prop, "Occlusion Resolution", "Size of the occlusion buffer, use higher value for better precision (slower)"); RNA_def_property_update(prop, NC_SCENE, NULL); @@ -3930,6 +3955,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "ticrate"); RNA_def_property_ui_range(prop, 1, 60, 1, 1); RNA_def_property_range(prop, 1, 10000); + RNA_def_property_int_default(prop, 60); RNA_def_property_ui_text(prop, "Frames Per Second", "Nominal number of game frames per second " "(physics fixed timestep = 1/fps, independently of actual frame rate)"); @@ -3939,6 +3965,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "maxlogicstep"); RNA_def_property_range(prop, 1, 10000); RNA_def_property_ui_range(prop, 1, 50, 1, 1); + RNA_def_property_int_default(prop, 5); RNA_def_property_ui_text(prop, "Max Logic Steps", "Maximum number of logic frame per game frame if graphics slows down the game, " "higher value allows better synchronization with physics"); @@ -3948,6 +3975,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "maxphystep"); RNA_def_property_range(prop, 1, 10000); RNA_def_property_ui_range(prop, 1, 50, 1, 1); + RNA_def_property_int_default(prop, 5); RNA_def_property_ui_text(prop, "Max Physics Steps", "Maximum number of physics step per game frame if graphics slows down the game, " "higher value allows physics to keep up with realtime"); @@ -3957,6 +3985,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "physubstep"); RNA_def_property_range(prop, 1, 50); RNA_def_property_ui_range(prop, 1, 5, 1, 1); + RNA_def_property_int_default(prop, 1); RNA_def_property_ui_text(prop, "Physics Sub Steps", "Number of simulation substep per physic timestep, " "higher value give better physics precision"); @@ -3966,6 +3995,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "lineardeactthreshold"); RNA_def_property_ui_range(prop, 0.001, 10000.0, 2, 3); RNA_def_property_range(prop, 0.001, 10000.0); + RNA_def_property_float_default(prop, 0.8f); RNA_def_property_ui_text(prop, "Deactivation Linear Threshold", "Linear velocity that an object must be below before the deactivation timer can start"); RNA_def_property_update(prop, NC_SCENE, NULL); @@ -3974,6 +4004,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "angulardeactthreshold"); RNA_def_property_ui_range(prop, 0.001, 10000.0, 2, 3); RNA_def_property_range(prop, 0.001, 10000.0); + RNA_def_property_float_default(prop, 1.0f); RNA_def_property_ui_text(prop, "Deactivation Angular Threshold", "Angular velocity that an object must be below before the deactivation timer can start"); RNA_def_property_update(prop, NC_SCENE, NULL); @@ -4117,6 +4148,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) prop = RNA_def_property(srna, "level_height", PROP_FLOAT, PROP_ACCELERATION); RNA_def_property_float_sdna(prop, NULL, "levelHeight"); RNA_def_property_range(prop, 0.0f, 200.0f); + RNA_def_property_float_default(prop, 2.0f); RNA_def_property_ui_text(prop, "Level height", "Max difference in heights of obstacles to enable their interaction"); RNA_def_property_update(prop, NC_SCENE, NULL); @@ -4145,6 +4177,7 @@ static void rna_def_scene_game_data(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "scehysteresis"); RNA_def_property_range(prop, 0, 100); RNA_def_property_ui_range(prop, 0, 100, 10, 1); + RNA_def_property_int_default(prop, 10); RNA_def_property_ui_text(prop, "Hysteresis %", "Minimum distance change required to transition to the previous level of detail"); RNA_def_property_update(prop, NC_SCENE, NULL); @@ -5792,6 +5825,17 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Simplify Child Particles", "Global child particles percentage"); RNA_def_property_update(prop, 0, "rna_Scene_simplify_update"); + prop = RNA_def_property(srna, "simplify_subdivision_render", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "simplify_subsurf_render"); + RNA_def_property_ui_range(prop, 0, 6, 1, -1); + RNA_def_property_ui_text(prop, "Simplify Subdivision", "Global maximum subdivision level during rendering"); + RNA_def_property_update(prop, 0, "rna_Scene_simplify_update"); + + prop = RNA_def_property(srna, "simplify_child_particles_render", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "simplify_particles_render"); + RNA_def_property_ui_text(prop, "Simplify Child Particles", "Global child particles percentage during rendering"); + RNA_def_property_update(prop, 0, "rna_Scene_simplify_update"); + prop = RNA_def_property(srna, "simplify_shadow_samples", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "simplify_shadowsamples"); RNA_def_property_ui_range(prop, 1, 16, 1, -1); diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c index 881688281f3..44169fa641e 100644 --- a/source/blender/makesrna/intern/rna_sequencer_api.c +++ b/source/blender/makesrna/intern/rna_sequencer_api.c @@ -232,7 +232,8 @@ static Sequence *rna_Sequences_new_sound(ID *id, Editing *ed, Main *bmain, Repor bSound *sound = BKE_sound_new_file(bmain, file); - if (sound == NULL || sound->playback_handle == NULL) { + if (sound->playback_handle == NULL) { + BKE_libblock_free(bmain, sound); BKE_report(reports, RPT_ERROR, "Sequences.new_sound: unable to open sound file"); return NULL; } diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index e174d1ce5d0..2b7ed3dc057 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -1348,6 +1348,19 @@ static void rna_BackgroundImage_opacity_set(PointerRNA *ptr, float value) bgpic->blend = 1.0f - value; } +/* radius internally (expose as a distance value) */ +static float rna_BackgroundImage_size_get(PointerRNA *ptr) +{ + BGpic *bgpic = ptr->data; + return bgpic->size * 2.0f; +} + +static void rna_BackgroundImage_size_set(PointerRNA *ptr, float value) +{ + BGpic *bgpic = ptr->data; + bgpic->size = value * 0.5f; +} + static BGpic *rna_BackgroundImage_new(View3D *v3d) { BGpic *bgpic = ED_view3D_background_image_new(v3d); @@ -1917,6 +1930,11 @@ static void rna_def_space_image_uv(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Draw Other Objects", "Draw other selected objects that share the same image"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL); + prop = RNA_def_property(srna, "show_metadata", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_DRAW_METADATA); + RNA_def_property_ui_text(prop, "Draw Metadata", "Draw metadata properties of the image"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL); + prop = RNA_def_property(srna, "show_texpaint", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SI_NO_DRAW_TEXPAINT); RNA_def_property_ui_text(prop, "Draw Texture Paint UVs", "Draw overlay of texture paint uv layer"); @@ -2103,15 +2121,16 @@ static void rna_def_background_image(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Y Offset", "Offset image vertically from the world origin"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); - prop = RNA_def_property(srna, "size", PROP_FLOAT, PROP_NONE); + prop = RNA_def_property(srna, "size", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "size"); - RNA_def_property_ui_text(prop, "Size", "Scaling factor for the background image"); + RNA_def_property_float_funcs(prop, "rna_BackgroundImage_size_get", "rna_BackgroundImage_size_set", NULL); + RNA_def_property_ui_text(prop, "Size", "Size of the background image (ortho view only)"); RNA_def_property_range(prop, 0.0, FLT_MAX); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_EULER); RNA_def_property_float_sdna(prop, NULL, "rotation"); - RNA_def_property_ui_text(prop, "Rotation", "Rotation for the background image"); + RNA_def_property_ui_text(prop, "Rotation", "Rotation for the background image (ortho view only)"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); prop = RNA_def_property(srna, "use_flip_x", PROP_BOOLEAN, PROP_NONE); @@ -3055,6 +3074,11 @@ static void rna_def_space_sequencer(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Center-Cut Safe Areas", "Show safe areas to fit content in a different aspect ratio"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); + prop = RNA_def_property(srna, "show_metadata", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SHOW_METADATA); + RNA_def_property_ui_text(prop, "Show Metadata", "Show metadata of first visible strip"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); + prop = RNA_def_property(srna, "show_seconds", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SEQ_DRAWFRAMES); RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames"); @@ -3679,6 +3703,14 @@ static void rna_def_fileselect_params(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; + static EnumPropertyItem thumbnail_size_items[] = { + {32, "TINY", 0, "Tiny", ""}, + {64, "SMALL", 0, "Small", ""}, + {128, "NORMAL", 0, "Normal", ""}, + {256, "LARGE", 0, "Large", ""}, + {0, NULL, 0, NULL, NULL} + }; + srna = RNA_def_struct(brna, "FileSelectParams", NULL); RNA_def_struct_ui_text(srna, "File Select Parameters", "File Select Parameters"); @@ -3783,6 +3815,12 @@ static void rna_def_fileselect_params(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Name Filter", "Filter by name, supports '*' wildcard"); RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_LIST, NULL); + + prop = RNA_def_property(srna, "thumbnail_size", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "thumbnail_size"); + RNA_def_property_enum_items(prop, thumbnail_size_items); + RNA_def_property_ui_text(prop, "Thumbnails Size", "Change the size of the thumbnails"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_LIST, NULL); } static void rna_def_filemenu_entry(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index ef52fe2a084..a441f2f57dc 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -2386,6 +2386,18 @@ static void rna_def_userdef_theme_space_image(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Current Frame", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); + prop = RNA_def_property(srna, "metadatabg", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "metadatabg"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Metadata Background", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "metadatatext", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "metadatatext"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Metadata Text", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + rna_def_userdef_theme_spaces_curves(srna, false, false, false, true); rna_def_userdef_theme_spaces_paint_curves(srna); @@ -2488,6 +2500,18 @@ static void rna_def_userdef_theme_space_seq(BlenderRNA *brna) RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Preview Background", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "metadatabg", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "metadatabg"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Metadata Background", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "metadatatext", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "metadatatext"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Metadata Text", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); } static void rna_def_userdef_theme_space_action(BlenderRNA *brna) @@ -3648,7 +3672,7 @@ static void rna_def_userdef_edit(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Grease Pencil Eraser Radius", "Radius of eraser 'brush'"); - prop = RNA_def_property(srna, "grease_pencil_default_color", PROP_FLOAT, PROP_COLOR); + prop = RNA_def_property(srna, "grease_pencil_default_color", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "gpencil_new_layer_col"); RNA_def_property_array(prop, 4); RNA_def_property_ui_text(prop, "Grease Pencil Default Color", "Color of new Grease Pencil layers"); diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index f01e1d02028..3b8ddd011c0 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -414,7 +414,7 @@ static EnumPropertyItem operator_flag_items[] = { {OPTYPE_UNDO, "UNDO", 0, "Undo", "Push an undo event (needed for operator redo)"}, {OPTYPE_BLOCKING, "BLOCKING", 0, "Blocking", "Block anything else from using the cursor"}, {OPTYPE_MACRO, "MACRO", 0, "Macro", "Use to check if an operator is a macro"}, - {OPTYPE_GRAB_POINTER, "GRAB_POINTER", 0, "Grab Pointer", + {OPTYPE_GRAB_CURSOR, "GRAB_CURSOR", 0, "Grab Pointer", "Use so the operator grabs the mouse focus, enables wrapping when continuous grab " "is enabled"}, {OPTYPE_PRESET, "PRESET", 0, "Preset", "Display a preset button with the operators settings"}, @@ -511,6 +511,11 @@ static int rna_Operator_has_reports_get(PointerRNA *ptr) return (op->reports && op->reports->list.first); } +static PointerRNA rna_Operator_options_get(PointerRNA *ptr) +{ + return rna_pointer_inherit_refine(ptr, &RNA_OperatorOptions, ptr->data); +} + static PointerRNA rna_Operator_properties_get(PointerRNA *ptr) { wmOperator *op = (wmOperator *)ptr->data; @@ -1390,6 +1395,33 @@ static void rna_KeyMapItem_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poi #else /* RNA_RUNTIME */ +/** + * expose ``Operator.options`` as its own type so we can control each flags use (some are read-only). + */ +static void rna_def_operator_options_runtime(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "OperatorOptions", NULL); + RNA_def_struct_ui_text(srna, "Operator Options", "Runtime options"); + RNA_def_struct_sdna(srna, "wmOperator"); + + prop = RNA_def_property(srna, "is_grab_cursor", PROP_BOOLEAN, PROP_BOOLEAN); + RNA_def_property_boolean_sdna(prop, NULL, "flag", OP_IS_MODAL_GRAB_CURSOR); + RNA_def_property_ui_text(prop, "Grab Cursor", "True when the cursor is grabbed"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + + prop = RNA_def_property(srna, "is_invoke", PROP_BOOLEAN, PROP_BOOLEAN); + RNA_def_property_boolean_sdna(prop, NULL, "flag", OP_IS_INVOKE); + RNA_def_property_ui_text(prop, "Invoke", "True when invoked (even if only the execute callbacks available)"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + + prop = RNA_def_property(srna, "use_cursor_region", PROP_BOOLEAN, PROP_BOOLEAN); + RNA_def_property_boolean_sdna(prop, NULL, "flag", OP_IS_MODAL_CURSOR_REGION); + RNA_def_property_ui_text(prop, "Focus Region", "Enable to use the region under the cursor for modal execution"); +} + static void rna_def_operator(BlenderRNA *brna) { StructRNA *srna; @@ -1424,6 +1456,12 @@ static void rna_def_operator(BlenderRNA *brna) prop = RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "UILayout"); + prop = RNA_def_property(srna, "options", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_struct_type(prop, "OperatorOptions"); + RNA_def_property_pointer_funcs(prop, "rna_Operator_options_get", NULL, NULL, NULL); + RNA_def_property_ui_text(prop, "Options", "Runtime options"); + /* Registration */ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "type->idname"); @@ -2169,6 +2207,7 @@ static void rna_def_keyconfig(BlenderRNA *brna) void RNA_def_wm(BlenderRNA *brna) { rna_def_operator(brna); + rna_def_operator_options_runtime(brna); rna_def_operator_utils(brna); rna_def_operator_filelist_element(brna); rna_def_macro_operator(brna); diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c index 8a92deec8eb..542c75f3276 100644 --- a/source/blender/modifiers/intern/MOD_decimate.c +++ b/source/blender/modifiers/intern/MOD_decimate.c @@ -163,7 +163,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, switch (dmd->mode) { case MOD_DECIM_MODE_COLLAPSE: { - const int do_triangulate = (dmd->flag & MOD_DECIM_FLAG_TRIANGULATE) != 0; + const bool do_triangulate = (dmd->flag & MOD_DECIM_FLAG_TRIANGULATE) != 0; BM_mesh_decimate_collapse(bm, dmd->percent, vweights, do_triangulate); break; } @@ -174,7 +174,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, } case MOD_DECIM_MODE_DISSOLVE: { - const int do_dissolve_boundaries = (dmd->flag & MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS) != 0; + const bool do_dissolve_boundaries = (dmd->flag & MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS) != 0; BM_mesh_decimate_dissolve(bm, dmd->angle, do_dissolve_boundaries, (BMO_Delimit)dmd->delimit); break; } diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c index 5285bc4124d..73bc61e5519 100644 --- a/source/blender/modifiers/intern/MOD_mirror.c +++ b/source/blender/modifiers/intern/MOD_mirror.c @@ -94,7 +94,7 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd, int axis) { const float tolerance_sq = mmd->tolerance * mmd->tolerance; - const int do_vtargetmap = !(mmd->flag & MOD_MIR_NO_MERGE); + const bool do_vtargetmap = (mmd->flag & MOD_MIR_NO_MERGE) == 0; int tot_vtargetmap = 0; /* total merge vertices */ DerivedMesh *result; diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c index 2c9f5e32440..a9160189a7b 100644 --- a/source/blender/modifiers/intern/MOD_screw.c +++ b/source/blender/modifiers/intern/MOD_screw.c @@ -138,14 +138,14 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm = derivedData; DerivedMesh *result; ScrewModifierData *ltmd = (ScrewModifierData *) md; - const int useRenderParams = flag & MOD_APPLY_RENDER; + const bool use_render_params = (flag & MOD_APPLY_RENDER) != 0; int *origindex; int mpoly_index = 0; unsigned int step; unsigned int i, j; unsigned int i1, i2; - unsigned int step_tot = useRenderParams ? ltmd->render_steps : ltmd->steps; + unsigned int step_tot = use_render_params ? ltmd->render_steps : ltmd->steps; const bool do_flip = ltmd->flag & MOD_SCREW_NORMAL_FLIP ? 1 : 0; const int quad_ord[4] = { diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index bd16fd07044..50b1404a8e5 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -249,6 +249,7 @@ static bool build_hull(SkinOutput *so, Frame **frames, int totframe) /* Apply face attributes to hull output */ BMO_ITER (f, &oiter, op.slots_out, "geom.out", BM_FACE) { + BM_face_normal_update(f); if (so->smd->flag & MOD_SKIN_SMOOTH_SHADING) BM_elem_flag_enable(f, BM_ELEM_SMOOTH); f->mat_nr = so->mat_nr; @@ -960,6 +961,7 @@ static void add_poly(SkinOutput *so, BLI_assert(v1 && v2 && v3); f = BM_face_create_verts(so->bm, verts, v4 ? 4 : 3, NULL, BM_CREATE_NO_DOUBLE, true); + BM_face_normal_update(f); if (so->smd->flag & MOD_SKIN_SMOOTH_SHADING) BM_elem_flag_enable(f, BM_ELEM_SMOOTH); f->mat_nr = so->mat_nr; @@ -1421,6 +1423,9 @@ static void hull_merge_triangles(SkinOutput *so, const SkinModifierData *smd) if (adj[0]->len == 3 && adj[1]->len == 3) { BMVert *quad[4]; + BLI_assert(BM_face_is_normal_valid(adj[0])); + BLI_assert(BM_face_is_normal_valid(adj[1])); + /* Construct quad using the two triangles adjacent to * the edge */ quad_from_tris(e, adj, quad); @@ -1783,6 +1788,9 @@ static BMesh *build_skin(SkinNode *skin_nodes, skin_output_connections(&so, skin_nodes, medge, totedge); hull_merge_triangles(&so, smd); + bmesh_edit_end(so.bm, 0); + BMO_pop(so.bm); + return so.bm; } @@ -1844,7 +1852,6 @@ static DerivedMesh *base_skin(DerivedMesh *origdm, result = CDDM_from_bmesh(bm, false); BM_mesh_free(bm); - CDDM_calc_edges(result); result->dirty |= DM_DIRTY_NORMALS; skin_set_orig_indices(result); diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c index 08b8854c728..c96080d8cf9 100644 --- a/source/blender/modifiers/intern/MOD_solidify.c +++ b/source/blender/modifiers/intern/MOD_solidify.c @@ -255,7 +255,7 @@ static DerivedMesh *applyModifier( /* weights */ MDeformVert *dvert; - const int defgrp_invert = ((smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0); + const bool defgrp_invert = (smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0; int defgrp_index; /* array size is doubled in case of using a shell */ diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c index f17858264f8..7ada058d883 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.c +++ b/source/blender/modifiers/intern/MOD_subsurf.c @@ -88,7 +88,7 @@ static bool isDisabled(ModifierData *md, int useRenderParams) SubsurfModifierData *smd = (SubsurfModifierData *) md; int levels = (useRenderParams) ? smd->renderLevels : smd->levels; - return get_render_subsurf_level(&md->scene->r, levels) == 0; + return get_render_subsurf_level(&md->scene->r, levels, useRenderParams != 0) == 0; } static DerivedMesh *applyModifier(ModifierData *md, Object *ob, diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c index a10386a6f41..113f1654d02 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.c +++ b/source/blender/modifiers/intern/MOD_uvproject.c @@ -139,7 +139,7 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, Image *image = umd->image; MPoly *mpoly, *mp; MLoop *mloop; - int override_image = ((umd->flags & MOD_UVPROJECT_OVERRIDEIMAGE) != 0); + const bool override_image = (umd->flags & MOD_UVPROJECT_OVERRIDEIMAGE) != 0; Projector projectors[MOD_UVPROJECT_MAXPROJECTORS]; int num_projectors = 0; char uvname[MAX_CUSTOMDATA_LAYER_NAME]; diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c index 4433922f9bb..266cfcc59a6 100644 --- a/source/blender/modifiers/intern/MOD_weightvgmix.c +++ b/source/blender/modifiers/intern/MOD_weightvgmix.c @@ -234,7 +234,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der int i; /* Flags. */ #if 0 - int do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview); + const bool do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview) != 0; #endif /* Get number of verts. */ diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index 057674f1144..390475b57f5 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -366,7 +366,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der int i; /* Flags. */ #if 0 - int do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview); + const bool do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview) != 0; #endif #ifdef USE_TIMEIT diff --git a/source/blender/nodes/composite/node_composite_util.c b/source/blender/nodes/composite/node_composite_util.c index 8e279cf6d68..bbfb07a316d 100644 --- a/source/blender/nodes/composite/node_composite_util.c +++ b/source/blender/nodes/composite/node_composite_util.c @@ -43,7 +43,7 @@ void cmp_node_update_default(bNodeTree *UNUSED(ntree), bNode *node) for (sock = node->outputs.first; sock; sock = sock->next) { if (sock->cache) { //free_compbuf(sock->cache); - //sock->cache= NULL; + //sock->cache = NULL; } } node->need_exec = 1; diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index 23d47065f59..19e93447608 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -190,7 +190,7 @@ static void cmp_node_image_add_multilayer_outputs(bNodeTree *ntree, bNode *node, sockdata->pass_index = index; sockdata->pass_flag = rpass->passtype; - if (STREQ(rpass->chan_id, "RGBA")) { + if (rpass->passtype == SCE_PASS_COMBINED) { sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, SOCK_FLOAT, PROP_NONE, "Alpha", "Alpha"); sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer"); sock->storage = sockdata; diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c index 93ce469c150..3482227f044 100644 --- a/source/blender/nodes/texture/node_texture_tree.c +++ b/source/blender/nodes/texture/node_texture_tree.c @@ -337,7 +337,7 @@ int ntreeTexExecTree( data.osatex = osatex; data.target = texres; data.do_preview = preview; - data.do_manage = (shi) ? shi->do_manage : 0; + data.do_manage = (shi) ? shi->do_manage : true; data.thread = thread; data.which_output = which_output; data.cfra = cfra; diff --git a/source/blender/python/bmesh/bmesh_py_api.c b/source/blender/python/bmesh/bmesh_py_api.c index bc14e1ac3a6..f74737ba8f4 100644 --- a/source/blender/python/bmesh/bmesh_py_api.c +++ b/source/blender/python/bmesh/bmesh_py_api.c @@ -108,7 +108,7 @@ PyDoc_STRVAR(bpy_bm_update_edit_mesh_doc, " :type mesh: :class:`bpy.types.Mesh`\n" " :arg tessface: Option to recalculate n-gon tessellation.\n" " :type tessface: boolean\n" -" :arg destructive: Use when grometry has been added or removed.\n" +" :arg destructive: Use when geometry has been added or removed.\n" " :type destructive: boolean\n" ); static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args, PyObject *kw) diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.c b/source/blender/python/bmesh/bmesh_py_ops_call.c index 84c1031a24a..a4c057acac2 100644 --- a/source/blender/python/bmesh/bmesh_py_ops_call.c +++ b/source/blender/python/bmesh/bmesh_py_ops_call.c @@ -69,9 +69,10 @@ static int bpy_bm_op_as_py_error(BMesh *bm) * \param htype Test \a value matches this type. * \param descr Description text. */ -static int bpy_slot_from_py_elem_check(BPy_BMElem *value, BMesh *bm, const char htype, - /* for error messages */ - const char *opname, const char *slot_name, const char *descr) +static int bpy_slot_from_py_elem_check( + BPy_BMElem *value, BMesh *bm, const char htype, + /* for error messages */ + const char *opname, const char *slot_name, const char *descr) { if (!BPy_BMElem_Check(value) || !(value->ele->head.htype & htype)) @@ -107,10 +108,11 @@ static int bpy_slot_from_py_elem_check(BPy_BMElem *value, BMesh *bm, const char * \param htype_bmo The type(s) supported by the target slot. * \param descr Description text. */ -static int bpy_slot_from_py_elemseq_check(BPy_BMGeneric *value, BMesh *bm, - const char htype_py, const char htype_bmo, - /* for error messages */ - const char *opname, const char *slot_name, const char *descr) +static int bpy_slot_from_py_elemseq_check( + BPy_BMGeneric *value, BMesh *bm, + const char htype_py, const char htype_bmo, + /* for error messages */ + const char *opname, const char *slot_name, const char *descr) { if (value->bm == NULL) { PyErr_Format(PyExc_TypeError, @@ -142,9 +144,10 @@ static int bpy_slot_from_py_elemseq_check(BPy_BMGeneric *value, BMesh *bm, /** * Use for giving py args to an operator. */ -static int bpy_slot_from_py(BMesh *bm, BMOperator *bmop, BMOpSlot *slot, PyObject *value, - /* the are just for exception messages */ - const char *opname, const char *slot_name) +static int bpy_slot_from_py( + BMesh *bm, BMOperator *bmop, BMOpSlot *slot, PyObject *value, + /* the are just for exception messages */ + const char *opname, const char *slot_name) { switch (slot->slot_type) { case BMO_OP_SLOT_BOOL: diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index 0edca96404f..14fdada66bb 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -3757,10 +3757,11 @@ void bpy_bm_generic_invalidate(BPy_BMGeneric *self) * * The 'bm_r' value is assigned when empty, and used when set. */ -void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size, - const char htype, - const bool do_unique_check, const bool do_bm_check, - const char *error_prefix) +void *BPy_BMElem_PySeq_As_Array( + BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size, + const char htype, + const bool do_unique_check, const bool do_bm_check, + const char *error_prefix) { BMesh *bm = (r_bm && *r_bm) ? *r_bm : NULL; PyObject *seq_fast; diff --git a/source/blender/python/bmesh/bmesh_py_types.h b/source/blender/python/bmesh/bmesh_py_types.h index 66059a642d1..630afcb32c0 100644 --- a/source/blender/python/bmesh/bmesh_py_types.h +++ b/source/blender/python/bmesh/bmesh_py_types.h @@ -158,10 +158,11 @@ PyObject *BPy_BMIter_CreatePyObject(BMesh *bm); PyObject *BPy_BMElem_CreatePyObject(BMesh *bm, BMHeader *ele); /* just checks type and creates v/e/f/l */ -void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size, - const char htype, - const bool do_unique_check, const bool do_bm_check, - const char *error_prefix); +void *BPy_BMElem_PySeq_As_Array( + BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size, + const char htype, + const bool do_unique_check, const bool do_bm_check, + const char *error_prefix); PyObject *BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_len); PyObject *BPy_BMVert_Array_As_Tuple(BMesh *bm, BMVert **elem, Py_ssize_t elem_len); diff --git a/source/blender/python/bmesh/bmesh_py_types_customdata.c b/source/blender/python/bmesh/bmesh_py_types_customdata.c index 7b6e062896f..3adf37f78f0 100644 --- a/source/blender/python/bmesh/bmesh_py_types_customdata.c +++ b/source/blender/python/bmesh/bmesh_py_types_customdata.c @@ -116,6 +116,9 @@ PyDoc_STRVAR(bpy_bmlayeraccess_collection__color_doc, PyDoc_STRVAR(bpy_bmlayeraccess_collection__skin_doc, "Accessor for skin layer.\n\ntype: :class:`BMLayerCollection`" ); +PyDoc_STRVAR(bpy_bmlayeraccess_collection__paint_mask_doc, +"Accessor for paint mask layer.\n\ntype: :class:`BMLayerCollection`" +); #ifdef WITH_FREESTYLE PyDoc_STRVAR(bpy_bmlayeraccess_collection__freestyle_edge_doc, "Accessor for Freestyle edge layer.\n\ntype: :class:`BMLayerCollection`" @@ -196,6 +199,7 @@ static PyGetSetDef bpy_bmlayeraccess_vert_getseters[] = { {(char *)"shape", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__shape_doc, (void *)CD_SHAPEKEY}, {(char *)"bevel_weight", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__bevel_weight_doc, (void *)CD_BWEIGHT}, {(char *)"skin", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__skin_doc, (void *)CD_MVERT_SKIN}, + {(char *)"paint_mask", (getter)bpy_bmlayeraccess_collection_get, (setter)NULL, (char *)bpy_bmlayeraccess_collection__paint_mask_doc, (void *)CD_PAINT_MASK}, {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; @@ -984,6 +988,7 @@ PyObject *BPy_BMLayerItem_GetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer) break; } case CD_PROP_FLT: + case CD_PAINT_MASK: { ret = PyFloat_FromDouble(*(float *)value); break; @@ -1061,6 +1066,7 @@ int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObj break; } case CD_PROP_FLT: + case CD_PAINT_MASK: { float tmp_val = PyFloat_AsDouble(py_value); if (UNLIKELY(tmp_val == -1 && PyErr_Occurred())) { diff --git a/source/blender/python/bmesh/bmesh_py_utils.c b/source/blender/python/bmesh/bmesh_py_utils.c index 0dd6ee7d51a..b7890926a85 100644 --- a/source/blender/python/bmesh/bmesh_py_utils.c +++ b/source/blender/python/bmesh/bmesh_py_utils.c @@ -253,7 +253,7 @@ static PyObject *bpy_bm_utils_vert_splice(PyObject *UNUSED(self), PyObject *args } /* should always succeed */ - ok = BM_vert_splice(bm, py_vert->v, py_vert_target->v); + ok = BM_vert_splice(bm, py_vert_target->v, py_vert->v); BLI_assert(ok == true); UNUSED_VARS_NDEBUG(ok); @@ -307,7 +307,7 @@ static PyObject *bpy_bm_utils_vert_separate(PyObject *UNUSED(self), PyObject *ar return NULL; } - BM_vert_separate(bm, py_vert->v, &elem, &elem_len, edge_array, edge_array_len); + BM_vert_separate(bm, py_vert->v, edge_array, edge_array_len, false, &elem, &elem_len); /* return collected verts */ ret = BPy_BMVert_Array_As_Tuple(bm, elem, elem_len); MEM_freeN(elem); @@ -670,7 +670,7 @@ PyDoc_STRVAR(bpy_bm_utils_face_vert_separate_doc, " :type face: :class:`bmesh.types.BMFace`\n" " :arg vert: A vertex in the face to separate.\n" " :type vert: :class:`bmesh.types.BMVert`\n" -" :return vert: The newly created vertex or None of failure.\n" +" :return vert: The newly created vertex or None on failure.\n" " :rtype vert: :class:`bmesh.types.BMVert`\n" "\n" " .. note::\n" @@ -749,9 +749,9 @@ PyDoc_STRVAR(bpy_bm_utils_loop_separate_doc, "\n" " Rip a vertex in a face away and add a new vertex.\n" "\n" -" :arg loop: The to separate.\n" -" :type loop: :class:`bmesh.types.BMFace`\n" -" :return vert: The newly created vertex or None of failure.\n" +" :arg loop: The loop to separate.\n" +" :type loop: :class:`bmesh.types.BMLoop`\n" +" :return vert: The newly created vertex or None on failure.\n" " :rtype vert: :class:`bmesh.types.BMVert`\n" ); static PyObject *bpy_bm_utils_loop_separate(PyObject *UNUSED(self), BPy_BMLoop *value) diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index c8a4971847b..04ab34efeb4 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -287,6 +287,7 @@ static PyGetSetDef bpy_app_getsets[] = { {(char *)"debug_wm", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_WM}, {(char *)"debug_depsgraph", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_DEPSGRAPH}, {(char *)"debug_simdata", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_SIMDATA}, + {(char *)"debug_gpumem", bpy_app_debug_get, bpy_app_debug_set, (char *)bpy_app_debug_doc, (void *)G_DEBUG_GPU_MEM}, {(char *)"debug_value", bpy_app_debug_value_get, bpy_app_debug_value_set, (char *)bpy_app_debug_value_doc, NULL}, {(char *)"tempdir", bpy_app_tempdir_get, NULL, (char *)bpy_app_tempdir_doc, NULL}, diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index 8370aea4c99..0e9e6b74396 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -2965,9 +2965,10 @@ static struct PyMethodDef props_methods[] = { static struct PyModuleDef props_module = { PyModuleDef_HEAD_INIT, "bpy.props", - "This module defines properties to extend blenders internal data, the result of these functions" - " is used to assign properties to classes registered with blender and can't be used directly.\n" - ".. warning:: All parameters to these functions must be passed as keywords.", + "This module defines properties to extend Blender's internal data. The result of these functions" + " is used to assign properties to classes registered with Blender and can't be used directly.\n" + "\n" + ".. warning:: All parameters to these functions must be passed as keywords.\n", -1, /* multiple "initialization" just copies the module dict. */ props_methods, NULL, NULL, NULL, NULL diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c index bb4080decef..ae5c058406f 100644 --- a/source/blender/python/mathutils/mathutils_geometry.c +++ b/source/blender/python/mathutils/mathutils_geometry.c @@ -850,7 +850,7 @@ PyDoc_STRVAR(M_Geometry_intersect_point_quad_2d_doc, "\n" " Takes 5 vectors (using only the x and y coordinates): one is the point and the next 4 define the quad, \n" " only the x and y are used from the vectors. Returns 1 if the point is within the quad, otherwise 0.\n" -" Works only with convex quads without singular edges." +" Works only with convex quads without singular edges.\n" "\n" " :arg pt: Point\n" " :type pt: :class:`mathutils.Vector`\n" diff --git a/source/blender/render/extern/include/RE_bake.h b/source/blender/render/extern/include/RE_bake.h index e8a8986714d..0750ea1aa28 100644 --- a/source/blender/render/extern/include/RE_bake.h +++ b/source/blender/render/extern/include/RE_bake.h @@ -61,10 +61,10 @@ typedef struct BakeHighPolyData { struct ModifierData *tri_mod; struct Mesh *me; char restrict_flag; + bool is_flip_object; float obmat[4][4]; float imat[4][4]; - float rotmat[4][4]; } BakeHighPolyData; /* external_engine.c */ diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 20678b29d0e..2df4cde2b27 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -49,6 +49,7 @@ struct Scene; struct SceneRenderLayer; struct EnvMap; struct RenderResult; +struct StampData; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* this include is what is exposed of render to outside world */ @@ -137,6 +138,9 @@ typedef struct RenderResult { int rectx, recty; short crop, sample_nr; + /* the following rect32, rectf and rectz buffers are for temporary storage only, for RenderResult structs + * created in #RE_AcquireResultImage - which do not have RenderView */ + /* optional, 32 bits version of picture, used for ogl render and image curves */ int *rect32; /* if this exists, a copy of one of layers, or result of composited layers */ @@ -171,6 +175,8 @@ typedef struct RenderResult { /* render info text */ char *text; char *error; + + struct StampData *stamp_data; } RenderResult; @@ -261,7 +267,7 @@ void RE_init_threadcount(Render *re); /* the main processor, assumes all was set OK! */ void RE_TileProcessor(struct Render *re); -bool RE_WriteRenderViewsImage(struct ReportList *reports, struct RenderResult *rr, struct Scene *scene, struct Object *camera, const bool stamp, char *name); +bool RE_WriteRenderViewsImage(struct ReportList *reports, struct RenderResult *rr, struct Scene *scene, const bool stamp, char *name); bool RE_WriteRenderViewsMovie(struct ReportList *reports, struct RenderResult *rr, struct Scene *scene, struct RenderData *rd, struct bMovieHandle *mh, const size_t width, const size_t height, void **movie_ctx_arr, const size_t totvideos, bool preview); @@ -350,12 +356,8 @@ bool RE_allow_render_generic_object(struct Object *ob); bool RE_HasFakeLayer(RenderResult *res); bool RE_RenderResult_is_stereo(RenderResult *res); - -float *RE_RenderViewGetRectf(struct RenderResult *rr, const int view_id); -float *RE_RenderViewGetRectz(struct RenderResult *rr, const int view_id); -int *RE_RenderViewGetRect32(struct RenderResult *rr, const int view_id); -void RE_RenderViewSetRectf(struct RenderResult *res, const int view_id, float *rect); -void RE_RenderViewSetRectz(struct RenderResult *res, const int view_id, float *rect); +struct RenderView *RE_RenderViewGetById(struct RenderResult *res, const int view_id); +struct RenderView *RE_RenderViewGetByName(struct RenderResult *res, const char *viewname); #endif /* __RE_PIPELINE_H__ */ diff --git a/source/blender/render/intern/include/render_result.h b/source/blender/render/intern/include/render_result.h index e7a2cbf99cd..f031be9e9c9 100644 --- a/source/blender/render/intern/include/render_result.h +++ b/source/blender/render/intern/include/render_result.h @@ -60,6 +60,7 @@ struct RenderResult *render_result_new_full_sample(struct Render *re, struct RenderResult *render_result_new_from_exr(void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty); +void render_result_view_new(struct RenderResult *rr, const char *viewname); void render_result_views_new(struct RenderResult *rr, struct RenderData *rd); /* Merge */ diff --git a/source/blender/render/intern/source/bake_api.c b/source/blender/render/intern/source/bake_api.c index 1f7555bc5c5..bc5db5b9862 100644 --- a/source/blender/render/intern/source/bake_api.c +++ b/source/blender/render/intern/source/bake_api.c @@ -300,7 +300,7 @@ static bool cast_ray_highpoly( mul_v3_m4v3(co_high, highpoly[i].imat, co); /* rotates */ - mul_v3_m4v3(dir_high, highpoly[i].rotmat, dir); + mul_v3_mat3_m4v3(dir_high, highpoly[i].imat, dir); normalize_v3(dir_high); /* cast ray */ diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index d36ab46d145..87c886929d6 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -1209,8 +1209,7 @@ static void particle_normal_ren(short ren_as, ParticleSettings *part, Render *re sd->time = 0.0f; sd->size = hasize; - copy_v3_v3(vel, state->vel); - mul_mat3_m4_v3(re->viewmat, vel); + mul_v3_mat3_m4v3(vel, re->viewmat, state->vel); normalize_v3(vel); if (part->draw & PART_DRAW_VEL_LENGTH) diff --git a/source/blender/render/intern/source/multires_bake.c b/source/blender/render/intern/source/multires_bake.c index 6ba85ea5329..de57d4e7ba6 100644 --- a/source/blender/render/intern/source/multires_bake.c +++ b/source/blender/render/intern/source/multires_bake.c @@ -127,9 +127,13 @@ typedef struct { static void multiresbake_get_normal(const MResolvePixelData *data, float norm[],const int face_num, const int vert_index) { - unsigned int indices[] = {data->mface[face_num].v1, data->mface[face_num].v2, - data->mface[face_num].v3, data->mface[face_num].v4}; - const int smoothnormal = (data->mface[face_num].flag & ME_SMOOTH); + const unsigned int indices[] = { + data->mface[face_num].v1, + data->mface[face_num].v2, + data->mface[face_num].v3, + data->mface[face_num].v4, + }; + const bool smoothnormal = (data->mface[face_num].flag & ME_SMOOTH) != 0; if (!smoothnormal) { /* flat */ if (data->precomputed_normals) { diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index e9b0a2bcbf4..a4089002ba5 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -363,6 +363,7 @@ void RE_AcquireResultImageViews(Render *re, RenderResult *rr) rr->layers = re->result->layers; rr->xof = re->disprect.xmin; rr->yof = re->disprect.ymin; + rr->stamp_data = re->result->stamp_data; } } } @@ -379,6 +380,8 @@ void RE_ReleaseResultImageViews(Render *re, RenderResult *rr) } /* fill provided result struct with what's currently active or done */ +/* this RenderResult struct is the only exception to the rule of a RenderResult */ +/* always having at least one RenderView */ void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id) { memset(rr, 0, sizeof(RenderResult)); @@ -394,18 +397,16 @@ void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id) rr->recty = re->result->recty; /* actview view */ - rv = BLI_findlink(&re->result->views, view_id); - if (rv == NULL) - rv = (RenderView *)re->result->views.first; + rv = RE_RenderViewGetById(re->result, view_id); - rr->rectf = rv ? rv->rectf : NULL; - rr->rectz = rv ? rv->rectz : NULL; - rr->rect32 = rv ? rv->rect32 : NULL; + rr->rectf = rv->rectf; + rr->rectz = rv->rectz; + rr->rect32 = rv->rect32; /* active layer */ rl = render_get_active_layer(re, re->result); - if (rl && rv) { + if (rl) { if (rv->rectf == NULL) rr->rectf = RE_RenderLayerGetPass(rl, SCE_PASS_COMBINED, rv->name); @@ -413,7 +414,7 @@ void RE_AcquireResultImage(Render *re, RenderResult *rr, const int view_id) rr->rectz = RE_RenderLayerGetPass(rl, SCE_PASS_Z, rv->name); } - rr->have_combined = rv ? (rv->rectf != NULL) : false; + rr->have_combined = (rv->rectf != NULL); rr->layers = re->result->layers; rr->views = re->result->views; @@ -435,9 +436,9 @@ void RE_ResultGet32(Render *re, unsigned int *rect) RenderResult rres; const size_t view_id = BKE_scene_multiview_view_id_get(&re->r, re->viewname); - RE_AcquireResultImage(re, &rres, view_id); - render_result_rect_get_pixels(&rres, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings, 0); - RE_ReleaseResultImage(re); + RE_AcquireResultImageViews(re, &rres); + render_result_rect_get_pixels(&rres, rect, re->rectx, re->recty, &re->scene->view_settings, &re->scene->display_settings, view_id); + RE_ReleaseResultImageViews(re, &rres); } /* caller is responsible for allocating rect in correct size! */ @@ -746,6 +747,7 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, re->result = MEM_callocN(sizeof(RenderResult), "new render result"); re->result->rectx = re->rectx; re->result->recty = re->recty; + render_result_view_new(re->result, "new temporary view"); } if (re->r.scemode & R_VIEWPORT_PREVIEW) @@ -768,11 +770,14 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, static void render_result_rescale(Render *re) { RenderResult *result = re->result; + RenderView *rv; int x, y; float scale_x, scale_y; float *src_rectf; - src_rectf = result->rectf; + rv = RE_RenderViewGetById(result, 0); + src_rectf = rv->rectf; + if (src_rectf == NULL) { RenderLayer *rl = render_get_active_layer(re, re->result); if (rl != NULL) { @@ -790,7 +795,7 @@ static void render_result_rescale(Render *re) ""); if (re->result != NULL) { - dst_rectf = re->result->rectf; + dst_rectf = RE_RenderViewGetById(re->result, 0)->rectf; if (dst_rectf == NULL) { RenderLayer *rl; rl = render_get_active_layer(re, re->result); @@ -2232,7 +2237,7 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) } } - for (nr = 0, rv = re->result->views.first; rv; rv = rv->next, nr++) { + for (nr = 0, rv = rectfs->first; rv; rv = rv->next, nr++) { rectf = rv->rectf; /* ensure we get either composited result or the active layer */ @@ -2285,7 +2290,7 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) /* store the final result */ BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); - rv = BLI_findlink(&re->result->views, nr); + rv = RE_RenderViewGetById(re->result, nr); if (rv->rectf) MEM_freeN(rv->rectf); rv->rectf = rectf; @@ -2483,7 +2488,7 @@ static void renderresult_stampinfo(Render *re) for (rv = re->result->views.first;rv;rv = rv->next, nr++) { RE_SetActiveRenderView(re, rv->name); RE_AcquireResultImage(re, &rres, nr); - BKE_image_stamp_buf(re->scene, RE_GetCamera(re), (unsigned char *)rv->rect32, rv->rectf, rres.rectx, rres.recty, 4); + BKE_image_stamp_buf(re->scene, RE_GetCamera(re), (unsigned char *)rres.rect32, rres.rectf, rres.rectx, rres.recty, 4); RE_ReleaseResultImage(re); } } @@ -2569,7 +2574,7 @@ static void do_render_seq(Render *re) BLI_rw_mutex_unlock(&re->resultmutex); for (view_id = 0; view_id < tot_views; view_id++) { - RenderView *rv = BLI_findlink(&rr->views, view_id); + RenderView *rv = RE_RenderViewGetById(rr, view_id); BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); if (ibuf_arr[view_id]) { @@ -2614,6 +2619,8 @@ static void do_render_seq(Render *re) /* main loop: doing sequence + fields + blur + 3d render + compositing */ static void do_render_all_options(Render *re) { + Object *camera; + re->current_scene_update(re->suh, re->scene); BKE_scene_camera_switch_update(re->scene); @@ -2647,6 +2654,10 @@ static void do_render_all_options(Render *re) re->stats_draw(re->sdh, &re->i); + /* save render result stamp if needed */ + camera = RE_GetCamera(re); + BKE_render_result_stamp_info(re->scene, camera, re->result); + /* stamp image info here */ if ((re->r.stamp & R_STAMP_ALL) && (re->r.stamp & R_STAMP_DRAW)) { renderresult_stampinfo(re); @@ -3082,7 +3093,7 @@ void RE_RenderFreestyleExternal(Render *re) } #endif -bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scene, struct Object *camera, const bool stamp, char *name) +bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scene, const bool stamp, char *name) { bool is_mono; bool ok = true; @@ -3125,8 +3136,7 @@ bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scen if (stamp) { /* writes the name of the individual cameras */ - Object *view_camera = BKE_camera_multiview_render(scene, camera, rv->name); - ok = BKE_imbuf_write_stamp(scene, view_camera, ibuf, name, &rd->im_format); + ok = BKE_imbuf_write_stamp(scene, rr, ibuf, name, &rd->im_format); } else { ok = BKE_imbuf_write(ibuf, name, &rd->im_format); @@ -3152,8 +3162,7 @@ bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scen if (stamp) { /* writes the name of the individual cameras */ - Object *view_camera = BKE_camera_multiview_render(scene, camera, rv->name); - ok = BKE_imbuf_write_stamp(scene, view_camera, ibuf, name, &rd->im_format); + ok = BKE_imbuf_write_stamp(scene, rr, ibuf, name, &rd->im_format); } else { ok = BKE_imbuf_write(ibuf, name, &rd->im_format); @@ -3188,7 +3197,7 @@ bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scen ibuf_arr[2] = IMB_stereo3d_ImBuf(&scene->r.im_format, ibuf_arr[0], ibuf_arr[1]); if (stamp) - ok = BKE_imbuf_write_stamp(scene, camera, ibuf_arr[2], name, &rd->im_format); + ok = BKE_imbuf_write_stamp(scene, rr, ibuf_arr[2], name, &rd->im_format); else ok = BKE_imbuf_write(ibuf_arr[2], name, &rd->im_format); @@ -3214,7 +3223,7 @@ bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scen &scene->display_settings, &imf); if (stamp) - ok = BKE_imbuf_write_stamp(scene, camera, ibuf_arr[2], name, &rd->im_format); + ok = BKE_imbuf_write_stamp(scene, rr, ibuf_arr[2], name, &rd->im_format); else ok = BKE_imbuf_write(ibuf_arr[2], name, &imf); @@ -3324,7 +3333,6 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie RenderResult rres; double render_time; bool ok = true; - Object *camera = RE_GetCamera(re); RE_AcquireResultImageViews(re, &rres); @@ -3341,7 +3349,7 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie &scene->r.im_format, (scene->r.scemode & R_EXTENSION) != 0, true, NULL); /* write images as individual images or stereo */ - ok = RE_WriteRenderViewsImage(re->reports, &rres, scene, camera, true, name); + ok = RE_WriteRenderViewsImage(re->reports, &rres, scene, true, name); } RE_ReleaseResultImageViews(re, &rres); diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index 303494d2beb..019484f7ed2 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -115,7 +115,9 @@ void render_result_free(RenderResult *res) MEM_freeN(res->text); if (res->error) MEM_freeN(res->error); - + if (res->stamp_data) + MEM_freeN(res->stamp_data); + MEM_freeN(res); } @@ -484,7 +486,7 @@ static RenderPass *render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int const size_t view_id = BLI_findstringindex(&rr->views, viewname, offsetof(RenderView, name)); const char *typestr = name_from_passtype(passtype, -1); RenderPass *rpass = MEM_callocN(sizeof(RenderPass), typestr); - int rectsize = rr->rectx * rr->recty * channels; + size_t rectsize = ((size_t)rr->rectx) * rr->recty * channels; BLI_addtail(&rl->passes, rpass); rpass->passtype = passtype; @@ -909,10 +911,16 @@ RenderResult *render_result_new_from_exr(void *exrhandle, const char *colorspace return rr; } +void render_result_view_new(RenderResult *rr, const char *viewname) +{ + RenderView *rv = MEM_callocN(sizeof(RenderView), "new render view"); + BLI_addtail(&rr->views, rv); + BLI_strncpy(rv->name, viewname, sizeof(rv->name)); +} + void render_result_views_new(RenderResult *rr, RenderData *rd) { SceneRenderView *srv; - RenderView *rv; /* clear previously existing views - for sequencer */ render_result_views_free(rr); @@ -920,19 +928,15 @@ void render_result_views_new(RenderResult *rr, RenderData *rd) /* check renderdata for amount of views */ if ((rd->scemode & R_MULTIVIEW)) { for (srv = rd->views.first; srv; srv = srv->next) { - if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) continue; - - rv = MEM_callocN(sizeof(RenderView), "new render view"); - BLI_addtail(&rr->views, rv); - - BLI_strncpy(rv->name, srv->name, sizeof(rv->name)); + if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) + continue; + render_result_view_new(rr, srv->name); } } /* we always need at least one view */ if (BLI_listbase_count_ex(&rr->views, 1) == 0) { - rv = MEM_callocN(sizeof(RenderView), "new render view"); - BLI_addtail(&rr->views, rv); + render_result_view_new(rr, ""); } } @@ -940,22 +944,23 @@ void render_result_views_new(RenderResult *rr, RenderData *rd) static void do_merge_tile(RenderResult *rr, RenderResult *rrpart, float *target, float *tile, int pixsize) { - int y, ofs, copylen, tilex, tiley; + int y, tilex, tiley; + size_t ofs, copylen; copylen = tilex = rrpart->rectx; tiley = rrpart->recty; if (rrpart->crop) { /* filters add pixel extra */ - tile += pixsize * (rrpart->crop + rrpart->crop * tilex); + tile += pixsize * (rrpart->crop + ((size_t)rrpart->crop) * tilex); copylen = tilex - 2 * rrpart->crop; tiley -= 2 * rrpart->crop; - ofs = (rrpart->tilerect.ymin + rrpart->crop) * rr->rectx + (rrpart->tilerect.xmin + rrpart->crop); + ofs = (((size_t)rrpart->tilerect.ymin) + rrpart->crop) * rr->rectx + (rrpart->tilerect.xmin + rrpart->crop); target += pixsize * ofs; } else { - ofs = (rrpart->tilerect.ymin * rr->rectx + rrpart->tilerect.xmin); + ofs = (((size_t)rrpart->tilerect.ymin) * rr->rectx + rrpart->tilerect.xmin); target += pixsize * ofs; } @@ -1461,12 +1466,13 @@ bool render_result_exr_file_cache_read(Render *re) ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd, const int view_id) { ImBuf *ibuf = IMB_allocImBuf(rr->rectx, rr->recty, rd->im_format.planes, 0); - + RenderView *rv = RE_RenderViewGetById(rr, view_id); + /* if not exists, BKE_imbuf_write makes one */ - ibuf->rect = (unsigned int *) RE_RenderViewGetRect32(rr, view_id); - ibuf->rect_float = RE_RenderViewGetRectf(rr, view_id); - ibuf->zbuf_float = RE_RenderViewGetRectz(rr, view_id); - + ibuf->rect = (unsigned int *) rv->rect32; + ibuf->rect_float = rv->rectf; + ibuf->zbuf_float = rv->rectz; + /* float factor for random dither, imbuf takes care of it */ ibuf->dither = rd->dither_intensity; @@ -1503,7 +1509,7 @@ ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd, const int vi void render_result_rect_from_ibuf(RenderResult *rr, RenderData *UNUSED(rd), ImBuf *ibuf, const int view_id) { - RenderView *rv = BLI_findlink(&rr->views, view_id); + RenderView *rv = RE_RenderViewGetById(rr, view_id); if (ibuf->rect_float) { if (!rv->rectf) @@ -1524,15 +1530,11 @@ void render_result_rect_from_ibuf(RenderResult *rr, RenderData *UNUSED(rd), ImBu /* Same things as above, old rectf can hang around from previous render. */ MEM_SAFE_FREE(rv->rectf); } - - /* clean up non-view buffers */ - MEM_SAFE_FREE(rr->rect32); - MEM_SAFE_FREE(rr->rectf); } void render_result_rect_fill_zero(RenderResult *rr, const int view_id) { - RenderView *rv = BLI_findlink(&rr->views, view_id); + RenderView *rv = RE_RenderViewGetById(rr, view_id); if (rv->rectf) memset(rv->rectf, 0, 4 * sizeof(float) * rr->rectx * rr->recty); @@ -1546,15 +1548,13 @@ void render_result_rect_get_pixels(RenderResult *rr, unsigned int *rect, int rec const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, const int view_id) { - if (rr->rect32) { - int *rect32 = RE_RenderViewGetRect32(rr, view_id); - memcpy(rect, (rect32 ? rect32 : rr->rect32), sizeof(int) * rr->rectx * rr->recty); - } - else if (rr->rectf) { - float *rectf = RE_RenderViewGetRectf(rr, view_id); - IMB_display_buffer_transform_apply((unsigned char *) rect, (rectf ? rectf : rr->rectf), rr->rectx, rr->recty, 4, + RenderView *rv = RE_RenderViewGetById(rr, view_id); + + if (rv->rect32) + memcpy(rect, rv->rect32, sizeof(int) * rr->rectx * rr->recty); + else if (rv->rectf) + IMB_display_buffer_transform_apply((unsigned char *) rect, rv->rectf, rr->rectx, rr->recty, 4, view_settings, display_settings, true); - } else /* else fill with black */ memset(rect, 0, sizeof(int) * rectx * recty); @@ -1588,47 +1588,16 @@ bool RE_RenderResult_is_stereo(RenderResult *res) return true; } -void RE_RenderViewSetRectf(RenderResult *res, const int view_id, float *rect) -{ - RenderView *rv = BLI_findlink(&res->views, view_id); - if (rv) { - rv->rectf = rect; - } -} - -void RE_RenderViewSetRectz(RenderResult *res, const int view_id, float *rect) +RenderView *RE_RenderViewGetById(RenderResult *res, const int view_id) { RenderView *rv = BLI_findlink(&res->views, view_id); - if (rv) { - rv->rectz = rect; - } + BLI_assert(res->views.first); + return rv ? rv : res->views.first; } -float *RE_RenderViewGetRectz(RenderResult *res, const int view_id) +RenderView *RE_RenderViewGetByName(RenderResult *res, const char *viewname) { - RenderView *rv = BLI_findlink(&res->views, view_id); - if (rv) { - return rv->rectz; - } - return res->rectz; + RenderView *rv = BLI_findstring(&res->views, viewname, offsetof(RenderView, name)); + BLI_assert(res->views.first); + return rv ? rv : res->views.first; } - -float *RE_RenderViewGetRectf(RenderResult *res, const int view_id) -{ - RenderView *rv = BLI_findlink(&res->views, view_id); - if (rv) { - return rv->rectf; - } - return res->rectf; -} - -int *RE_RenderViewGetRect32(RenderResult *res, const int view_id) -{ - RenderView *rv = BLI_findlink(&res->views, view_id); - if (rv) { - return rv->rect32; - } - return res->rect32; -} - - diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index 9ea7cb62c58..5a5e67e1e43 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -423,14 +423,11 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert } if (texco & TEXCO_GLOB) { - copy_v3_v3(shi->gl, shi->co); - mul_m4_v3(R.viewinv, shi->gl); + mul_v3_m4v3(shi->gl, R.viewinv, shi->co); if (shi->osatex) { - copy_v3_v3(shi->dxgl, shi->dxco); - mul_mat3_m4_v3(R.viewinv, shi->dxgl); - copy_v3_v3(shi->dygl, shi->dyco); - mul_mat3_m4_v3(R.viewinv, shi->dygl); + mul_v3_mat3_m4v3(shi->dxgl, R.viewinv, shi->dxco); + mul_v3_mat3_m4v3(shi->dygl, R.viewinv, shi->dyco); } } diff --git a/source/blender/render/intern/source/texture_ocean.c b/source/blender/render/intern/source/texture_ocean.c index 5261374b34d..a932123243d 100644 --- a/source/blender/render/intern/source/texture_ocean.c +++ b/source/blender/render/intern/source/texture_ocean.c @@ -73,7 +73,7 @@ int ocean_texture(Tex *tex, const float texvec[2], TexResult *texres) return 0; } else { - const int do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS); + const bool do_normals = (omd->flag & MOD_OCEAN_GENERATE_NORMALS) != 0; int cfra = R.r.cfra; int retval = TEX_INT; diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index dbeea80ba82..d4148a56dd2 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -175,6 +175,7 @@ bool WM_modal_tweak_exit(const struct wmEvent *event, int tweak_event); void WM_event_add_notifier(const struct bContext *C, unsigned int type, void *reference); void WM_main_add_notifier(unsigned int type, void *reference); void WM_main_remove_notifier_reference(const void *reference); +void WM_main_remove_editor_id_reference(const struct ID *id); /* reports */ void WM_report(const struct bContext *C, ReportType type, const char *message); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 165ed6df091..c9a0849c192 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -123,17 +123,22 @@ struct ImBuf; /* ************** wmOperatorType ************************ */ /* flag */ -#define OPTYPE_REGISTER 1 /* register operators in stack after finishing */ -#define OPTYPE_UNDO 2 /* do undo push after after */ -#define OPTYPE_BLOCKING 4 /* let blender grab all input from the WM (X11) */ -#define OPTYPE_MACRO 8 -#define OPTYPE_GRAB_POINTER 16 /* grabs the cursor and optionally enables continuous cursor wrapping */ -#define OPTYPE_PRESET 32 /* show preset menu */ -#define OPTYPE_INTERNAL 64 /* some operators are mainly for internal use - * and don't make sense to be accessed from the - * search menu, even if poll() returns true. - * currently only used for the search toolbox */ -#define OPTYPE_LOCK_BYPASS 128 /* Allow operator to run when interface is locked */ +enum { + OPTYPE_REGISTER = (1 << 0), /* register operators in stack after finishing */ + OPTYPE_UNDO = (1 << 1), /* do undo push after after */ + OPTYPE_BLOCKING = (1 << 2), /* let blender grab all input from the WM (X11) */ + OPTYPE_MACRO = (1 << 3), + OPTYPE_GRAB_CURSOR = (1 << 4), /* grabs the cursor and optionally enables continuous cursor wrapping */ + OPTYPE_PRESET = (1 << 5), /* show preset menu */ + + /* some operators are mainly for internal use + * and don't make sense to be accessed from the + * search menu, even if poll() returns true. + * currently only used for the search toolbox */ + OPTYPE_INTERNAL = (1 << 6), + + OPTYPE_LOCK_BYPASS = (1 << 7), /* Allow operator to run when interface is locked */ +}; /* context to call operator in for WM_operator_name_call */ /* rna_ui.c contains EnumPropertyItem's of these, keep in sync */ diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 2280782f7bd..69bee8bab80 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -63,6 +63,7 @@ #include "ED_fileselect.h" #include "ED_info.h" +#include "ED_outliner.h" #include "ED_screen.h" #include "ED_view3d.h" #include "ED_util.h" @@ -217,6 +218,7 @@ void WM_main_remove_notifier_reference(const void *reference) { Main *bmain = G.main; wmWindowManager *wm = bmain->wm.first; + if (wm) { wmNotifier *note, *note_next; @@ -232,6 +234,24 @@ void WM_main_remove_notifier_reference(const void *reference) } } +void WM_main_remove_editor_id_reference(const ID *id) +{ + Main *bmain = G.main; + bScreen *sc; + + for (sc = bmain->screen.first; sc; sc = sc->id.next) { + ScrArea *sa; + + for (sa = sc->areabase.first; sa; sa = sa->next) { + SpaceLink *sl; + + for (sl = sa->spacedata.first; sl; sl = sl->next) { + ED_spacedata_id_unref(sl, id); + } + } + } +} + static void wm_notifier_clear(wmNotifier *note) { /* NULL the entire notifier, only leaving (next, prev) members intact */ @@ -293,7 +313,7 @@ void wm_event_do_notifiers(bContext *C) do_anim = true; } } - if (ELEM(note->category, NC_SCENE, NC_OBJECT, NC_GEOM, NC_SCENE, NC_WM)) { + if (ELEM(note->category, NC_SCENE, NC_OBJECT, NC_GEOM, NC_WM)) { ED_info_stats_clear(win->screen->scene); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO, NULL); } @@ -1085,11 +1105,11 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, if (op->opm) { wrap = (U.uiflag & USER_CONTINUOUS_MOUSE) && - ((op->opm->flag & OP_GRAB_POINTER) || (op->opm->type->flag & OPTYPE_GRAB_POINTER)); + ((op->opm->flag & OP_IS_MODAL_GRAB_CURSOR) || (op->opm->type->flag & OPTYPE_GRAB_CURSOR)); } else { wrap = (U.uiflag & USER_CONTINUOUS_MOUSE) && - ((op->flag & OP_GRAB_POINTER) || (ot->flag & OPTYPE_GRAB_POINTER)); + ((op->flag & OP_IS_MODAL_GRAB_CURSOR) || (ot->flag & OPTYPE_GRAB_CURSOR)); } /* exception, cont. grab in header is annoying */ @@ -1337,7 +1357,7 @@ void wm_event_free_handler(wmEventHandler *handler) } /* only set context when area/region is part of screen */ -static void wm_handler_op_context(bContext *C, wmEventHandler *handler) +static void wm_handler_op_context(bContext *C, wmEventHandler *handler, const wmEvent *event) { bScreen *screen = CTX_wm_screen(C); @@ -1358,10 +1378,27 @@ static void wm_handler_op_context(bContext *C, wmEventHandler *handler) } else { ARegion *ar; + wmOperator *op = handler->op ? (handler->op->opm ? handler->op->opm : handler->op) : NULL; CTX_wm_area_set(C, sa); - for (ar = sa->regionbase.first; ar; ar = ar->next) - if (ar == handler->op_region) - break; + + if (op && (op->flag & OP_IS_MODAL_CURSOR_REGION)) { + ar = BKE_area_find_region_xy(sa, handler->op_region_type, event->x, event->y); + if (ar) { + handler->op_region = ar; + } + } + else { + ar = NULL; + } + + if (ar == NULL) { + for (ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar == handler->op_region) { + break; + } + } + } + /* XXX no warning print here, after full-area and back regions are remade */ if (ar) CTX_wm_region_set(C, ar); @@ -1379,11 +1416,12 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers) /* C is zero on freeing database, modal handlers then already were freed */ while ((handler = BLI_pophead(handlers))) { if (handler->op) { + wmWindow *win = CTX_wm_window(C); if (handler->op->type->cancel) { ScrArea *area = CTX_wm_area(C); ARegion *region = CTX_wm_region(C); - wm_handler_op_context(C, handler); + wm_handler_op_context(C, handler, win->eventstate); if (handler->op->type->flag & OPTYPE_UNDO) wm->op_undo_depth++; @@ -1397,7 +1435,7 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers) CTX_wm_region_set(C, region); } - WM_cursor_grab_disable(CTX_wm_window(C), NULL); + WM_cursor_grab_disable(win, NULL); WM_operator_free(handler->op); } else if (handler->ui_remove) { @@ -1569,7 +1607,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand ARegion *region = CTX_wm_region(C); bool dbl_click_disabled = false; - wm_handler_op_context(C, handler); + wm_handler_op_context(C, handler, event); wm_region_mouse_co(C, event); wm_event_modalkeymap(C, op, event, &dbl_click_disabled); @@ -1717,7 +1755,7 @@ static int wm_handler_fileselect_do(bContext *C, ListBase *handlers, wmEventHand ED_screen_full_prevspace(C, CTX_wm_area(C)); } - wm_handler_op_context(C, handler); + wm_handler_op_context(C, handler, CTX_wm_window(C)->eventstate); /* needed for UI_popup_menu_reports */ @@ -1843,7 +1881,7 @@ static int wm_action_not_handled(int action) static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers) { #ifndef NDEBUG - const int do_debug_handler = (G.debug & G_DEBUG_HANDLERS) && + const bool do_debug_handler = (G.debug & G_DEBUG_HANDLERS) && /* comment this out to flood the console! (if you really want to test) */ !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) ; @@ -2330,6 +2368,11 @@ void wm_event_do_handlers(bContext *C) break; } + /* update azones if needed - done here because it needs to be independent from redraws */ + if (sa->flag & AREA_FLAG_ACTIONZONES_UPDATE) { + ED_area_azones_update(sa, &event->x); + } + if (wm_event_inside_i(event, &sa->totrct)) { CTX_wm_area_set(C, sa); @@ -2529,6 +2572,7 @@ wmEventHandler *WM_event_add_modal_handler(bContext *C, wmOperator *op) handler->op_area = CTX_wm_area(C); /* means frozen screen context for modal handlers! */ handler->op_region = CTX_wm_region(C); + handler->op_region_type = handler->op_region ? handler->op_region->regiontype : -1; BLI_addhead(&win->modalhandlers, handler); diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index df0d27bc43e..a3cbb2b6eec 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -951,7 +951,7 @@ int wm_file_write(bContext *C, const char *filepath, int fileflags, ReportList * /* operator now handles overwrite checks */ if (G.fileflags & G_AUTOPACK) { - packAll(G.main, reports); + packAll(G.main, reports, false); } /* don't forget not to return without! */ diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 71a025f3660..b5c267e8a39 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -149,9 +149,11 @@ void WM_init(bContext *C, int argc, const char **argv) WM_menutype_init(); WM_uilisttype_init(); - set_free_windowmanager_cb(wm_close_and_free); /* library.c */ - set_free_notifier_reference_cb(WM_main_remove_notifier_reference); /* library.c */ - set_blender_test_break_cb(wm_window_testbreak); /* blender.c */ + BKE_library_callback_free_window_manager_set(wm_close_and_free); /* library.c */ + BKE_library_callback_free_notifier_reference_set(WM_main_remove_notifier_reference); /* library.c */ + BKE_library_callback_free_editor_id_reference_set(WM_main_remove_editor_id_reference); /* library.c */ + BKE_blender_callback_test_break_set(wm_window_testbreak); /* blender.c */ + BKE_spacedata_callback_id_unref_set(ED_spacedata_id_unref); /* screen.c */ DAG_editors_update_cb(ED_render_id_flush_update, ED_render_scene_update); /* depsgraph.c */ ED_spacetypes_init(); /* editors/space_api/spacetype.c */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index cb2db94f609..dfff5b4982f 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -341,7 +341,9 @@ static int wm_macro_modal(bContext *C, wmOperator *op, const wmEvent *event) * */ if (op->opm->type->flag & OPTYPE_BLOCKING) { int bounds[4] = {-1, -1, -1, -1}; - int wrap = (U.uiflag & USER_CONTINUOUS_MOUSE) && ((op->opm->flag & OP_GRAB_POINTER) || (op->opm->type->flag & OPTYPE_GRAB_POINTER)); + const bool wrap = ( + (U.uiflag & USER_CONTINUOUS_MOUSE) && + ((op->opm->flag & OP_IS_MODAL_GRAB_CURSOR) || (op->opm->type->flag & OPTYPE_GRAB_CURSOR))); if (wrap) { ARegion *ar = CTX_wm_region(C); @@ -4831,6 +4833,38 @@ static void WM_OT_previews_ensure(wmOperatorType *ot) ot->exec = previews_ensure_exec; } +static int doc_view_manual_ui_context_exec(bContext *C, wmOperator *UNUSED(op)) +{ + PointerRNA ptr_props; + char buf[512]; + short retval = OPERATOR_CANCELLED; + + if (UI_but_online_manual_id_from_active(C, buf, sizeof(buf))) { + WM_operator_properties_create(&ptr_props, "WM_OT_doc_view_manual"); + RNA_string_set(&ptr_props, "doc_id", buf); + + retval = WM_operator_name_call_ptr( + C, WM_operatortype_find("WM_OT_doc_view_manual", false), + WM_OP_EXEC_DEFAULT, &ptr_props); + + WM_operator_properties_free(&ptr_props); + } + + return retval; +} + +static void WM_OT_doc_view_manual_ui_context(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "View Online Manual"; + ot->idname = "WM_OT_doc_view_manual_ui_context"; + ot->description = "View a context based online manual in a web browser"; + + /* callbacks */ + ot->poll = ED_operator_regionactive; + ot->exec = doc_view_manual_ui_context_exec; +} + /* ******************************************************* */ static void operatortype_ghash_free_cb(wmOperatorType *ot) @@ -4927,6 +4961,7 @@ void wm_operatortype_init(void) WM_operatortype_append(WM_OT_console_toggle); #endif WM_operatortype_append(WM_OT_previews_ensure); + WM_operatortype_append(WM_OT_doc_view_manual_ui_context); } /* circleselect-like modal operators */ @@ -5153,6 +5188,8 @@ void wm_window_keymap(wmKeyConfig *keyconf) WM_keymap_verify_item(keymap, "WM_OT_window_fullscreen_toggle", F11KEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "WM_OT_quit_blender", QKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "WM_OT_doc_view_manual_ui_context", F1KEY, KM_PRESS, KM_ALT, 0); + /* debug/testing */ WM_keymap_verify_item(keymap, "WM_OT_redraw_timer", TKEY, KM_PRESS, KM_ALT | KM_CTRL, 0); WM_keymap_verify_item(keymap, "WM_OT_debug_menu", DKEY, KM_PRESS, KM_ALT | KM_CTRL, 0); diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c index 328223645bc..717583f69ba 100644 --- a/source/blender/windowmanager/intern/wm_stereo.c +++ b/source/blender/windowmanager/intern/wm_stereo.c @@ -363,8 +363,7 @@ static bool wm_stereo3d_is_fullscreen_required(eStereoDisplayMode stereo_display { return ELEM(stereo_display, S3D_DISPLAY_SIDEBYSIDE, - S3D_DISPLAY_TOPBOTTOM, - S3D_DISPLAY_PAGEFLIP); + S3D_DISPLAY_TOPBOTTOM); } bool WM_stereo3d_enabled(wmWindow *win, bool skip_stereo3d_check) @@ -451,44 +450,61 @@ int wm_stereo3d_set_exec(bContext *C, wmOperator *op) wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); const bool is_fullscreen = WM_window_is_fullscreen(win); - char display_mode = win->stereo3d_format->display_mode; + char prev_display_mode = win->stereo3d_format->display_mode; + Stereo3dData *s3dd; if (G.background) return OPERATOR_CANCELLED; - if (op->customdata) { - Stereo3dData *s3dd = op->customdata; - *win->stereo3d_format = s3dd->stereo3d_format; + if (op->customdata == NULL) { + /* no invoke means we need to set the operator properties here */ + wm_stereo3d_set_init(C, op); + wm_stereo3d_set_properties(C, op); } - /* pageflip requires a new window to be created with the proper OS flags */ - if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) { - if (wm_stereo3d_quadbuffer_supported() == false) { - BKE_report(op->reports, RPT_ERROR, "Quad-buffer not supported by the system"); - win->stereo3d_format->display_mode = display_mode; - return OPERATOR_CANCELLED; - } + s3dd = op->customdata; + *win->stereo3d_format = s3dd->stereo3d_format; + + if (prev_display_mode == S3D_DISPLAY_PAGEFLIP && + prev_display_mode != win->stereo3d_format->display_mode) + { + /* in case the hardward supports pageflip but not the display */ if (wm_window_duplicate_exec(C, op) == OPERATOR_FINISHED) { wm_window_close(C, wm, win); - win = wm->windows.last; } else { BKE_report(op->reports, RPT_ERROR, - "Fail to create a window compatible with time sequential (page-flip) display method"); - win->stereo3d_format->display_mode = display_mode; - return OPERATOR_CANCELLED; + "Failed to create a window without quad-buffer support, you may experience flickering"); + } + } + else if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) { + /* pageflip requires a new window to be created with the proper OS flags */ + if (wm_window_duplicate_exec(C, op) == OPERATOR_FINISHED) { + if (wm_stereo3d_quadbuffer_supported()) { + wm_window_close(C, wm, win); + BKE_report(op->reports, RPT_INFO, "Quad-buffer window successfully created"); + } + else { + wmWindow *win_new = wm->windows.last; + wm_window_close(C, wm, win_new); + win->stereo3d_format->display_mode = prev_display_mode; + BKE_report(op->reports, RPT_ERROR, "Quad-buffer not supported by the system"); + } + } + else { + BKE_report(op->reports, RPT_ERROR, + "Failed to create a window compatible with the time sequential display method"); + win->stereo3d_format->display_mode = prev_display_mode; } } - if (wm_stereo3d_is_fullscreen_required(win->stereo3d_format->display_mode)) { + if (wm_stereo3d_is_fullscreen_required(s3dd->stereo3d_format.display_mode)) { if (!is_fullscreen) { BKE_report(op->reports, RPT_INFO, "Stereo 3D Mode requires the window to be fullscreen"); } } - if (op->customdata) { - MEM_freeN(op->customdata); - } + MEM_freeN(op->customdata); WM_event_add_notifier(C, NC_WINDOW, NULL); return OPERATOR_FINISHED; diff --git a/source/blender/windowmanager/wm_event_system.h b/source/blender/windowmanager/wm_event_system.h index f89177a82ea..a097343d037 100644 --- a/source/blender/windowmanager/wm_event_system.h +++ b/source/blender/windowmanager/wm_event_system.h @@ -56,6 +56,7 @@ typedef struct wmEventHandler { wmOperator *op; /* for derived/modal handlers */ struct ScrArea *op_area; /* for derived/modal handlers */ struct ARegion *op_region; /* for derived/modal handlers */ + short op_region_type; /* for derived/modal handlers */ /* ui handler */ wmUIHandlerFunc ui_handle; /* callback receiving events */ diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index f8a42159c27..08d01a9c79e 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -227,8 +227,6 @@ struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name) void RE_init_texture_rng() RET_NONE void RE_exit_texture_rng() RET_NONE -float *RE_RenderViewGetRectf(struct RenderResult *rr, int view_id) {STUB_ASSERT(0); return (float *) NULL;} -float *RE_RenderViewGetRectz(struct RenderResult *rr, int view_id) {STUB_ASSERT(0); return (float *) NULL;} bool RE_layers_have_name(struct RenderResult *result) {STUB_ASSERT(0); return 0;} void RE_engine_active_view_set(struct RenderEngine *engine, const char *viewname) {STUB_ASSERT(0);} void RE_engine_get_camera_model_matrix(struct RenderEngine *engine, struct Object *camera, float *r_modelmat) {STUB_ASSERT(0);} diff --git a/source/creator/creator.c b/source/creator/creator.c index 440710f0572..721e43cda4d 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -1024,6 +1024,7 @@ static int set_ge_parameters(int argc, const char **argv, void *data) } /* linearMipMap */ if (STREQ(argv[a], "linearmipmap")) { + GPU_set_mipmap(1); GPU_set_linear_mipmap(1); //linearMipMap = 1; } @@ -1491,6 +1492,7 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle) BLI_argsAdd(ba, 1, NULL, "--debug-value", "<value>\n\tSet debug value of <value> on startup\n", set_debug_value, NULL); BLI_argsAdd(ba, 1, NULL, "--debug-jobs", "\n\tEnable time profiling for background jobs.", debug_mode_generic, (void *)G_DEBUG_JOBS); BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph", "\n\tEnable debug messages from dependency graph", debug_mode_generic, (void *)G_DEBUG_DEPSGRAPH); + BLI_argsAdd(ba, 1, NULL, "--debug-gpumem", "\n\tEnable GPU memory stats in status bar", debug_mode_generic, (void *)G_DEBUG_GPU_MEM); BLI_argsAdd(ba, 1, NULL, "--verbose", "<verbose>\n\tSet logging verbosity level.", set_verbosity, NULL); diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index 4f251a66ccf..1a489c301e2 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -117,11 +117,9 @@ typedef struct ThreadInfo { } ThreadInfo; KX_BlenderSceneConverter::KX_BlenderSceneConverter( - struct Main* maggie, - class KX_KetsjiEngine* engine - ) - : m_maggie(maggie), - /*m_maggie_dyn(NULL),*/ + Main *maggie, + KX_KetsjiEngine *engine) + :m_maggie(maggie), m_ketsjiEngine(engine), m_alwaysUseExpandFraming(false), m_usemat(false), @@ -134,13 +132,11 @@ KX_BlenderSceneConverter::KX_BlenderSceneConverter( pthread_mutex_init(&m_threadinfo->merge_lock, NULL); } - KX_BlenderSceneConverter::~KX_BlenderSceneConverter() { // clears meshes, and hashmaps from blender to gameengine data - int i; // delete sumoshapes - + if (m_threadinfo) { vector<pthread_t>::iterator pit = m_threadinfo->threads.begin(); while (pit != m_threadinfo->threads.end()) { @@ -153,104 +149,83 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter() } int numAdtLists = m_map_blender_to_gameAdtList.size(); - for (i=0; i<numAdtLists; i++) { - BL_InterpolatorList *adtList= *m_map_blender_to_gameAdtList.at(i); + for (int i = 0; i < numAdtLists; i++) { + BL_InterpolatorList *adtList = *m_map_blender_to_gameAdtList.at(i); delete (adtList); } - vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator itw = m_worldinfos.begin(); + vector<pair<KX_Scene *, KX_WorldInfo *> >::iterator itw = m_worldinfos.begin(); while (itw != m_worldinfos.end()) { delete (*itw).second; itw++; } m_worldinfos.clear(); - vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator itp = m_polymaterials.begin(); + vector<pair<KX_Scene *,RAS_IPolyMaterial *> >::iterator itp = m_polymaterials.begin(); while (itp != m_polymaterials.end()) { - //m_polymat_cache.erase((*itp).second->GetBlenderMaterial()); delete (*itp).second; itp++; } m_polymaterials.clear(); // delete after RAS_IPolyMaterial - vector<pair<KX_Scene*,BL_Material *> >::iterator itmat = m_materials.begin(); + vector<pair<KX_Scene *,BL_Material *> >::iterator itmat = m_materials.begin(); while (itmat != m_materials.end()) { - //m_mat_cache.erase((*itmat).second->material); delete (*itmat).second; itmat++; } m_materials.clear(); - - vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator itm = m_meshobjects.begin(); + vector<pair<KX_Scene *,RAS_MeshObject *> >::iterator itm = m_meshobjects.begin(); while (itm != m_meshobjects.end()) { delete (*itm).second; itm++; } m_meshobjects.clear(); - /* free any data that was dynamically loaded */ - while (m_DynamicMaggie.size() != 0) - { + while (m_DynamicMaggie.size() != 0) { FreeBlendFile(m_DynamicMaggie[0]); } m_DynamicMaggie.clear(); } -void KX_BlenderSceneConverter::SetNewFileName(const STR_String& filename) +void KX_BlenderSceneConverter::SetNewFileName(const STR_String &filename) { m_newfilename = filename; } - - bool KX_BlenderSceneConverter::TryAndLoadNewFile() { bool result = false; - // find the file -/* if () - { - result = true; - } - // if not, clear the newfilename - else - { - m_newfilename = ""; - } -*/ return result; } -Scene *KX_BlenderSceneConverter::GetBlenderSceneForName(const STR_String& name) +Scene *KX_BlenderSceneConverter::GetBlenderSceneForName(const STR_String &name) { Scene *sce; /** * Find the specified scene by name, or NULL if nothing matches. */ - if ((sce= (Scene *)BLI_findstring(&m_maggie->scene, name.ReadPtr(), offsetof(ID, name) + 2))) + if ((sce = (Scene *)BLI_findstring(&m_maggie->scene, name.ReadPtr(), offsetof(ID, name) + 2))) return sce; - for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) { - Main *main= *it; + for (vector<Main *>::iterator it=m_DynamicMaggie.begin(); !(it == m_DynamicMaggie.end()); it++) { + Main *main = *it; if ((sce= (Scene *)BLI_findstring(&main->scene, name.ReadPtr(), offsetof(ID, name) + 2))) return sce; } return NULL; - } -void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene, - class RAS_IRasterizer* rendertools, - class RAS_ICanvas* canvas, - bool libloading) +void KX_BlenderSceneConverter::ConvertScene(KX_Scene *destinationscene, RAS_IRasterizer *rendertools, + RAS_ICanvas *canvas, bool libloading) { //find out which physics engine Scene *blenderscene = destinationscene->GetBlenderScene(); @@ -266,13 +241,12 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene, // when doing threaded conversion, so it's disabled for now. // SG_SetActiveStage(SG_STAGE_CONVERTER); - switch (blenderscene->gm.physicsEngine) - { + switch (blenderscene->gm.physicsEngine) { #ifdef WITH_BULLET case WOPHY_BULLET: { SYS_SystemHandle syshandle = SYS_GetSystem(); /*unused*/ - int visualizePhysics = SYS_GetCommandLineInt(syshandle,"show_physics",0); + int visualizePhysics = SYS_GetCommandLineInt(syshandle, "show_physics", 0); phy_env = CcdPhysicsEnvironment::Create(blenderscene, visualizePhysics); physics_engine = UseBullet; @@ -291,7 +265,8 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene, destinationscene->SetPhysicsEnvironment(phy_env); - BL_ConvertBlenderObjects(m_maggie, + BL_ConvertBlenderObjects( + m_maggie, destinationscene, m_ketsjiEngine, physics_engine, @@ -299,8 +274,7 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene, canvas, this, m_alwaysUseExpandFraming, - libloading - ); + libloading); //These lookup are not needed during game m_map_blender_to_gameactuator.clear(); @@ -326,30 +300,32 @@ void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene) // delete the scene first as it will stop the use of entities delete scene; // delete the entities of this scene - vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit; + vector<pair<KX_Scene *, KX_WorldInfo *> >::iterator worldit; size = m_worldinfos.size(); - for (i=0, worldit=m_worldinfos.begin(); i<size; ) { + for (i = 0, worldit = m_worldinfos.begin(); i < size; ) { if ((*worldit).first == scene) { delete (*worldit).second; *worldit = m_worldinfos.back(); m_worldinfos.pop_back(); size--; - } else { + } + else { i++; worldit++; } } - vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator polymit; + vector<pair<KX_Scene *, RAS_IPolyMaterial *> >::iterator polymit; size = m_polymaterials.size(); - for (i=0, polymit=m_polymaterials.begin(); i<size; ) { + for (i = 0, polymit = m_polymaterials.begin(); i < size; ) { if ((*polymit).first == scene) { m_polymat_cache[scene].erase((*polymit).second->GetBlenderMaterial()); delete (*polymit).second; *polymit = m_polymaterials.back(); m_polymaterials.pop_back(); size--; - } else { + } + else { i++; polymit++; } @@ -357,16 +333,17 @@ void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene) m_polymat_cache.erase(scene); - vector<pair<KX_Scene*,BL_Material*> >::iterator matit; + vector<pair<KX_Scene *, BL_Material *> >::iterator matit; size = m_materials.size(); - for (i=0, matit=m_materials.begin(); i<size; ) { + for (i = 0, matit = m_materials.begin(); i < size; ) { if ((*matit).first == scene) { m_mat_cache[scene].erase((*matit).second->material); delete (*matit).second; *matit = m_materials.back(); m_materials.pop_back(); size--; - } else { + } + else { i++; matit++; } @@ -374,15 +351,16 @@ void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene) m_mat_cache.erase(scene); - vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator meshit; + vector<pair<KX_Scene *, RAS_MeshObject *> >::iterator meshit; size = m_meshobjects.size(); - for (i=0, meshit=m_meshobjects.begin(); i<size; ) { + for (i = 0, meshit = m_meshobjects.begin(); i < size; ) { if ((*meshit).first == scene) { delete (*meshit).second; *meshit = m_meshobjects.back(); m_meshobjects.pop_back(); size--; - } else { + } + else { i++; meshit++; } @@ -425,43 +403,34 @@ bool KX_BlenderSceneConverter::GetCacheMaterials() void KX_BlenderSceneConverter::RegisterBlenderMaterial(BL_Material *mat) { // First make sure we don't register the material twice - vector<pair<KX_Scene*,BL_Material*> >::iterator it; + vector<pair<KX_Scene *, BL_Material *> >::iterator it; for (it = m_materials.begin(); it != m_materials.end(); ++it) if (it->second == mat) return; - m_materials.push_back(pair<KX_Scene*,BL_Material *>(m_currentScene,mat)); + m_materials.push_back(pair<KX_Scene *, BL_Material *> (m_currentScene, mat)); } - - -void KX_BlenderSceneConverter::SetAlwaysUseExpandFraming( - bool to_what) +void KX_BlenderSceneConverter::SetAlwaysUseExpandFraming(bool to_what) { m_alwaysUseExpandFraming= to_what; } - - -void KX_BlenderSceneConverter::RegisterGameObject( - KX_GameObject *gameobject, - struct Object *for_blenderobject) +void KX_BlenderSceneConverter::RegisterGameObject(KX_GameObject *gameobject, Object *for_blenderobject) { /* only maintained while converting, freed during game runtime */ - m_map_blender_to_gameobject.insert(CHashedPtr(for_blenderobject),gameobject); + m_map_blender_to_gameobject.insert(CHashedPtr(for_blenderobject), gameobject); } /* only need to run this during conversion since * m_map_blender_to_gameobject is freed after conversion */ -void KX_BlenderSceneConverter::UnregisterGameObject( - KX_GameObject *gameobject) +void KX_BlenderSceneConverter::UnregisterGameObject(KX_GameObject *gameobject) { - struct Object *bobp= gameobject->GetBlenderObject(); + Object *bobp = gameobject->GetBlenderObject(); if (bobp) { CHashedPtr bptr(bobp); - KX_GameObject **gobp= m_map_blender_to_gameobject[bptr]; - if (gobp && *gobp == gameobject) - { + KX_GameObject **gobp = m_map_blender_to_gameobject[bptr]; + if (gobp && *gobp == gameobject) { // also maintain m_map_blender_to_gameobject if the gameobject // being removed is matching the blender object m_map_blender_to_gameobject.remove(bptr); @@ -469,47 +438,41 @@ void KX_BlenderSceneConverter::UnregisterGameObject( } } -KX_GameObject *KX_BlenderSceneConverter::FindGameObject( - struct Object *for_blenderobject) +KX_GameObject *KX_BlenderSceneConverter::FindGameObject(Object *for_blenderobject) { - KX_GameObject **obp= m_map_blender_to_gameobject[CHashedPtr(for_blenderobject)]; - - return obp?*obp:NULL; + KX_GameObject **obp = m_map_blender_to_gameobject[CHashedPtr(for_blenderobject)]; + + return obp ? *obp : NULL; } -void KX_BlenderSceneConverter::RegisterGameMesh( - RAS_MeshObject *gamemesh, - struct Mesh *for_blendermesh) +void KX_BlenderSceneConverter::RegisterGameMesh(RAS_MeshObject *gamemesh, Mesh *for_blendermesh) { if (for_blendermesh) { /* dynamically loaded meshes we don't want to keep lookups for */ m_map_mesh_to_gamemesh.insert(CHashedPtr(for_blendermesh),gamemesh); } - m_meshobjects.push_back(pair<KX_Scene*,RAS_MeshObject*>(m_currentScene,gamemesh)); + m_meshobjects.push_back(pair<KX_Scene *, RAS_MeshObject *> (m_currentScene,gamemesh)); } - - -RAS_MeshObject *KX_BlenderSceneConverter::FindGameMesh( - struct Mesh *for_blendermesh/*, - unsigned int onlayer*/) +RAS_MeshObject *KX_BlenderSceneConverter::FindGameMesh(Mesh *for_blendermesh) { - RAS_MeshObject** meshp = m_map_mesh_to_gamemesh[CHashedPtr(for_blendermesh)]; - - if (meshp/* && onlayer==(*meshp)->GetLightLayer()*/) { + RAS_MeshObject **meshp = m_map_mesh_to_gamemesh[CHashedPtr(for_blendermesh)]; + + if (meshp) { return *meshp; - } else { + } + else { return NULL; } -} +} void KX_BlenderSceneConverter::RegisterPolyMaterial(RAS_IPolyMaterial *polymat) { // First make sure we don't register the material twice - vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator it; + vector<pair<KX_Scene *, RAS_IPolyMaterial *> >::iterator it; for (it = m_polymaterials.begin(); it != m_polymaterials.end(); ++it) if (it->second == polymat) return; - m_polymaterials.push_back(pair<KX_Scene*,RAS_IPolyMaterial*>(m_currentScene,polymat)); + m_polymaterials.push_back(pair<KX_Scene *, RAS_IPolyMaterial *> (m_currentScene, polymat)); } void KX_BlenderSceneConverter::CachePolyMaterial(KX_Scene *scene, Material *mat, RAS_IPolyMaterial *polymat) @@ -518,94 +481,82 @@ void KX_BlenderSceneConverter::CachePolyMaterial(KX_Scene *scene, Material *mat, m_polymat_cache[scene][mat] = polymat; } -RAS_IPolyMaterial *KX_BlenderSceneConverter::FindCachedPolyMaterial(KX_Scene *scene, struct Material *mat) +RAS_IPolyMaterial *KX_BlenderSceneConverter::FindCachedPolyMaterial(KX_Scene *scene, Material *mat) { return (m_use_mat_cache) ? m_polymat_cache[scene][mat] : NULL; } -void KX_BlenderSceneConverter::CacheBlenderMaterial(KX_Scene *scene, struct Material *mat, BL_Material *blmat) +void KX_BlenderSceneConverter::CacheBlenderMaterial(KX_Scene *scene, Material *mat, BL_Material *blmat) { if (m_use_mat_cache && mat) m_mat_cache[scene][mat] = blmat; } - -BL_Material *KX_BlenderSceneConverter::FindCachedBlenderMaterial(KX_Scene *scene, struct Material *mat) +BL_Material *KX_BlenderSceneConverter::FindCachedBlenderMaterial(KX_Scene *scene, Material *mat) { return (m_use_mat_cache) ? m_mat_cache[scene][mat] : NULL; } - -void KX_BlenderSceneConverter::RegisterInterpolatorList(BL_InterpolatorList *actList, struct bAction *for_act) +void KX_BlenderSceneConverter::RegisterInterpolatorList(BL_InterpolatorList *actList, bAction *for_act) { m_map_blender_to_gameAdtList.insert(CHashedPtr(for_act), actList); } -BL_InterpolatorList *KX_BlenderSceneConverter::FindInterpolatorList(struct bAction *for_act) +BL_InterpolatorList *KX_BlenderSceneConverter::FindInterpolatorList(bAction *for_act) { BL_InterpolatorList **listp = m_map_blender_to_gameAdtList[CHashedPtr(for_act)]; - return listp?*listp:NULL; + return listp ? *listp : NULL; } - -void KX_BlenderSceneConverter::RegisterGameActuator(SCA_IActuator *act, struct bActuator *for_actuator) +void KX_BlenderSceneConverter::RegisterGameActuator(SCA_IActuator *act, bActuator *for_actuator) { m_map_blender_to_gameactuator.insert(CHashedPtr(for_actuator), act); } -SCA_IActuator *KX_BlenderSceneConverter::FindGameActuator(struct bActuator *for_actuator) +SCA_IActuator *KX_BlenderSceneConverter::FindGameActuator(bActuator *for_actuator) { SCA_IActuator **actp = m_map_blender_to_gameactuator[CHashedPtr(for_actuator)]; - return actp?*actp:NULL; + return actp ? *actp : NULL; } - -void KX_BlenderSceneConverter::RegisterGameController(SCA_IController *cont, struct bController *for_controller) +void KX_BlenderSceneConverter::RegisterGameController(SCA_IController *cont, bController *for_controller) { m_map_blender_to_gamecontroller.insert(CHashedPtr(for_controller), cont); } -SCA_IController *KX_BlenderSceneConverter::FindGameController(struct bController *for_controller) +SCA_IController *KX_BlenderSceneConverter::FindGameController(bController *for_controller) { SCA_IController **contp = m_map_blender_to_gamecontroller[CHashedPtr(for_controller)]; - return contp?*contp:NULL; + return contp ? *contp : NULL; } - - void KX_BlenderSceneConverter::RegisterWorldInfo(KX_WorldInfo *worldinfo) { - m_worldinfos.push_back(pair<KX_Scene*,KX_WorldInfo*>(m_currentScene,worldinfo)); + m_worldinfos.push_back(pair<KX_Scene *, KX_WorldInfo *> (m_currentScene, worldinfo)); } -void KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo) +void KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo) { //TODO this entire function is deprecated, written for 2.4x //the functionality should be rewritten, currently it does nothing - KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes(); + KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes(); int numScenes = scenes->size(); int i; - for (i=0;i<numScenes;i++) - { - KX_Scene* scene = scenes->at(i); - //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment(); - CListValue* parentList = scene->GetRootParentList(); + for (i = 0; i < numScenes; i++) { + KX_Scene *scene = scenes->at(i); + CListValue *parentList = scene->GetRootParentList(); int numObjects = parentList->GetCount(); int g; - for (g=0;g<numObjects;g++) - { - KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g); + for (g = 0; g < numObjects; g++) { + KX_GameObject *gameObj = (KX_GameObject *)parentList->GetValue(g); if (gameObj->IsRecordAnimation()) { - - Object* blenderObject = gameObj->GetBlenderObject(); - if (blenderObject) - { + Object *blenderObject = gameObj->GetBlenderObject(); + if (blenderObject) { #if 0 //erase existing ipo's Ipo* ipo = blenderObject->ipo;//findIpoForName(blenderObject->id.name+2); - if (ipo) - { //clear the curve data + if (ipo) { //clear the curve data if (clearIpo) {//rcruiz IpoCurve *icu1; @@ -630,64 +581,52 @@ void KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo) localDel_ipoCurve( tmpicu ); } } - } else - { ipo = NULL; // XXX add_ipo(blenderObject->id.name+2, ID_OB); + } + else { + ipo = NULL; // XXX add_ipo(blenderObject->id.name+2, ID_OB); blenderObject->ipo = ipo; - } #endif } } - } - - } - - - } -void KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo() +void KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo() { //TODO the functionality should be rewritten } - - ///this generates ipo curves for position, rotation, allowing to use game physics in animation -void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) +// this generates ipo curves for position, rotation, allowing to use game physics in animation +void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) { - - KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes(); + KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes(); int numScenes = scenes->size(); int i; - for (i=0;i<numScenes;i++) - { - KX_Scene* scene = scenes->at(i); + for (i = 0; i < numScenes; i++) { + KX_Scene *scene = scenes->at(i); //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment(); - CListValue* parentList = scene->GetObjectList(); + CListValue *parentList = scene->GetObjectList(); int numObjects = parentList->GetCount(); int g; - for (g=0;g<numObjects;g++) - { - KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g); - Object* blenderObject = gameObj->GetBlenderObject(); - if (blenderObject && blenderObject->parent==NULL && gameObj->IsRecordAnimation()) { - - if (blenderObject->adt==NULL) + for (g = 0; g < numObjects; g++) { + KX_GameObject *gameObj = (KX_GameObject *)parentList->GetValue(g); + Object *blenderObject = gameObj->GetBlenderObject(); + if (blenderObject && blenderObject->parent == NULL && gameObj->IsRecordAnimation()) { + if (blenderObject->adt == NULL) BKE_animdata_add_id(&blenderObject->id); - if (blenderObject->adt) - { - const MT_Point3& position = gameObj->NodeGetWorldPosition(); + if (blenderObject->adt) { + const MT_Point3 &position = gameObj->NodeGetWorldPosition(); //const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); - const MT_Matrix3x3& orn = gameObj->NodeGetWorldOrientation(); + const MT_Matrix3x3 &orn = gameObj->NodeGetWorldOrientation(); position.getValue(blenderObject->loc); float tmat[3][3]; - for (int r=0;r<3;r++) - for (int c=0;c<3;c++) + for (int r = 0; r < 3; r++) + for (int c = 0; c < 3; c++) tmat[r][c] = (float)orn[c][r]; mat3_to_compatible_eul(blenderObject->rot, blenderObject->rot, tmat); @@ -772,27 +711,22 @@ void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) } } - -void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo() +void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo() { - - KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes(); + KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes(); int numScenes = scenes->size(); int i; - for (i=0;i<numScenes;i++) - { - KX_Scene* scene = scenes->at(i); + for (i = 0; i < numScenes; i++) { + KX_Scene *scene = scenes->at(i); //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment(); - CListValue* parentList = scene->GetRootParentList(); + CListValue *parentList = scene->GetRootParentList(); int numObjects = parentList->GetCount(); int g; - for (g=0;g<numObjects;g++) - { - KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g); + for (g = 0; g < numObjects; g++) { + KX_GameObject *gameObj = (KX_GameObject *)parentList->GetValue(g); if (gameObj->IsRecordAnimation()) { - Object* blenderObject = gameObj->GetBlenderObject(); - if (blenderObject && blenderObject->adt) - { + Object *blenderObject = gameObj->GetBlenderObject(); + if (blenderObject && blenderObject->adt) { bAction *act = verify_adt_action(&blenderObject->id, false); FCurve *fcu; @@ -832,14 +766,14 @@ PyObject *KX_BlenderSceneConverter::GetPyNamespace() } #endif -vector<Main*> &KX_BlenderSceneConverter::GetMainDynamic() +vector<Main *> &KX_BlenderSceneConverter::GetMainDynamic() { return m_DynamicMaggie; } -Main* KX_BlenderSceneConverter::GetMainDynamicPath(const char *path) +Main *KX_BlenderSceneConverter::GetMainDynamicPath(const char *path) { - for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) + for (vector<Main *>::iterator it = m_DynamicMaggie.begin(); !(it == m_DynamicMaggie.end()); it++) if (BLI_path_cmp((*it)->name, path) == 0) return *it; @@ -848,22 +782,21 @@ Main* KX_BlenderSceneConverter::GetMainDynamicPath(const char *path) void KX_BlenderSceneConverter::MergeAsyncLoads() { - vector<KX_Scene*> *merge_scenes; + vector<KX_Scene *> *merge_scenes; - vector<KX_LibLoadStatus*>::iterator mit; - vector<KX_Scene*>::iterator sit; + vector<KX_LibLoadStatus *>::iterator mit; + vector<KX_Scene *>::iterator sit; pthread_mutex_lock(&m_threadinfo->merge_lock); - for (mit=m_mergequeue.begin(); mit!=m_mergequeue.end(); ++mit) { - merge_scenes = (vector<KX_Scene*>*)(*mit)->GetData(); + for (mit = m_mergequeue.begin(); mit != m_mergequeue.end(); ++mit) { + merge_scenes = (vector<KX_Scene *> *)(*mit)->GetData(); for (sit=merge_scenes->begin(); sit!=merge_scenes->end(); ++sit) { (*mit)->GetMergeScene()->MergeScene(*sit); delete (*sit); } - delete merge_scenes; (*mit)->SetData(NULL); @@ -885,17 +818,17 @@ void KX_BlenderSceneConverter::AddScenesToMergeQueue(KX_LibLoadStatus *status) static void *async_convert(void *ptr) { KX_Scene *new_scene = NULL; - KX_LibLoadStatus *status = (KX_LibLoadStatus*)ptr; - vector<Scene*> *scenes = (vector<Scene*>*)status->GetData(); - vector<KX_Scene*> *merge_scenes = new vector<KX_Scene*>(); // Deleted in MergeAsyncLoads + KX_LibLoadStatus *status = (KX_LibLoadStatus *)ptr; + vector<Scene *> *scenes = (vector<Scene *> *)status->GetData(); + vector<KX_Scene *> *merge_scenes = new vector<KX_Scene *>(); // Deleted in MergeAsyncLoads - for (unsigned int i=0; i<scenes->size(); ++i) { + for (unsigned int i = 0; i < scenes->size(); ++i) { new_scene = status->GetEngine()->CreateScene((*scenes)[i], true); if (new_scene) merge_scenes->push_back(new_scene); - status->AddProgress((1.f/scenes->size())*0.9f); // We'll call conversion 90% and merging 10% for now + status->AddProgress((1.0f / scenes->size()) * 0.9f); // We'll call conversion 90% and merging 10% for now } delete scenes; @@ -922,28 +855,21 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFilePath(const char *filepa return LinkBlendFile(bpy_openlib, filepath, group, scene_merge, err_str, options); } -static void load_datablocks(Main *main_newlib, BlendHandle *bpy_openlib, const char *path, int idcode) +static void load_datablocks(Main *main_tmp, BlendHandle *bpy_openlib, const char *path, int idcode) { - Main *main_tmp= NULL; /* created only for linking, then freed */ LinkNode *names = NULL; - short flag= 0; /* don't need any special options */ - - /* here appending/linking starts */ - main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path); int totnames_dummy; - names = BLO_blendhandle_get_datablock_names( bpy_openlib, idcode, &totnames_dummy); + names = BLO_blendhandle_get_datablock_names(bpy_openlib, idcode, &totnames_dummy); - int i=0; - LinkNode *n= names; + int i = 0; + LinkNode *n = names; while (n) { BLO_library_append_named_part(main_tmp, &bpy_openlib, (char *)n->link, idcode); - n= (LinkNode *)n->next; + n = (LinkNode *)n->next; i++; } BLI_linklist_free(names, free); /* free linklist *and* each node's data */ - - BLO_library_append_end(NULL, main_tmp, &bpy_openlib, idcode, flag); } KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options) @@ -956,42 +882,48 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl // TIMEIT_START(bge_link_blend_file); KX_LibLoadStatus *status; - + /* only scene and mesh supported right now */ - if (idcode!=ID_SCE && idcode!=ID_ME &&idcode!=ID_AC) { + if (idcode != ID_SCE && idcode != ID_ME && idcode != ID_AC) { snprintf(err_local, sizeof(err_local), "invalid ID type given \"%s\"\n", group); - *err_str= err_local; + *err_str = err_local; BLO_blendhandle_close(bpy_openlib); return NULL; } if (GetMainDynamicPath(path)) { snprintf(err_local, sizeof(err_local), "blend file already open \"%s\"\n", path); - *err_str= err_local; + *err_str = err_local; BLO_blendhandle_close(bpy_openlib); return NULL; } - if (bpy_openlib==NULL) { + if (bpy_openlib == NULL) { snprintf(err_local, sizeof(err_local), "could not open blendfile \"%s\"\n", path); - *err_str= err_local; + *err_str = err_local; return NULL; } main_newlib = BKE_main_new(); BKE_reports_init(&reports, RPT_STORE); - load_datablocks(main_newlib, bpy_openlib, path, idcode); + short flag = 0; /* don't need any special options */ + /* created only for linking, then freed */ + Main *main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path); + + load_datablocks(main_tmp, bpy_openlib, path, idcode); - if (idcode==ID_SCE && options & LIB_LOAD_LOAD_SCRIPTS) { - load_datablocks(main_newlib, bpy_openlib, path, ID_TXT); + if (idcode == ID_SCE && options & LIB_LOAD_LOAD_SCRIPTS) { + load_datablocks(main_tmp, bpy_openlib, path, ID_TXT); } /* now do another round of linking for Scenes so all actions are properly loaded */ - if (idcode==ID_SCE && options & LIB_LOAD_LOAD_ACTIONS) { - load_datablocks(main_newlib, bpy_openlib, path, ID_AC); + if (idcode == ID_SCE && options & LIB_LOAD_LOAD_ACTIONS) { + load_datablocks(main_tmp, bpy_openlib, path, ID_AC); } - + + BLO_library_append_end(NULL, main_tmp, &bpy_openlib, idcode, flag); + BLO_blendhandle_close(bpy_openlib); BKE_reports_clear(&reports); @@ -1004,42 +936,43 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl status = new KX_LibLoadStatus(this, m_ketsjiEngine, scene_merge, path); - if (idcode==ID_ME) { + if (idcode == ID_ME) { /* Convert all new meshes into BGE meshes */ - ID* mesh; + ID *mesh; - for (mesh= (ID *)main_newlib->mesh.first; mesh; mesh= (ID *)mesh->next ) { + for (mesh = (ID *)main_newlib->mesh.first; mesh; mesh = (ID *)mesh->next ) { if (options & LIB_LOAD_VERBOSE) - printf("MeshName: %s\n", mesh->name+2); + printf("MeshName: %s\n", mesh->name + 2); RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)mesh, NULL, scene_merge, this, false); // For now only use the libloading option for scenes, which need to handle materials/shaders - scene_merge->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj); + scene_merge->GetLogicManager()->RegisterMeshName(meshobj->GetName(), meshobj); } } - else if (idcode==ID_AC) { + else if (idcode == ID_AC) { /* Convert all actions */ ID *action; - for (action= (ID *)main_newlib->action.first; action; action= (ID *)action->next) { + for (action= (ID *)main_newlib->action.first; action; action = (ID *)action->next) { if (options & LIB_LOAD_VERBOSE) - printf("ActionName: %s\n", action->name+2); - scene_merge->GetLogicManager()->RegisterActionName(action->name+2, action); + printf("ActionName: %s\n", action->name + 2); + scene_merge->GetLogicManager()->RegisterActionName(action->name + 2, action); } } - else if (idcode==ID_SCE) { + else if (idcode == ID_SCE) { /* Merge all new linked in scene into the existing one */ ID *scene; // scenes gets deleted by the thread when it's done using it (look in async_convert()) - vector<Scene*> *scenes = (options & LIB_LOAD_ASYNC) ? new vector<Scene*>() : NULL; + vector<Scene *> *scenes = (options & LIB_LOAD_ASYNC) ? new vector<Scene *>() : NULL; - for (scene= (ID *)main_newlib->scene.first; scene; scene= (ID *)scene->next ) { + for (scene = (ID *)main_newlib->scene.first; scene; scene = (ID *)scene->next ) { if (options & LIB_LOAD_VERBOSE) - printf("SceneName: %s\n", scene->name+2); + printf("SceneName: %s\n", scene->name + 2); if (options & LIB_LOAD_ASYNC) { - scenes->push_back((Scene*)scene); - } else { + scenes->push_back((Scene *)scene); + } + else { /* merge into the base scene */ - KX_Scene* other= m_ketsjiEngine->CreateScene((Scene *)scene, true); + KX_Scene* other = m_ketsjiEngine->CreateScene((Scene *)scene, true); scene_merge->MergeScene(other); // RemoveScene(other); // Don't run this, it frees the entire scene converter data, just delete the scene @@ -1050,7 +983,7 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl if (options & LIB_LOAD_ASYNC) { pthread_t id; status->SetData(scenes); - pthread_create(&id, NULL, &async_convert, (void*)status); + pthread_create(&id, NULL, &async_convert, (void *)status); m_threadinfo->threads.push_back(id); } @@ -1064,17 +997,16 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl if (options & LIB_LOAD_LOAD_ACTIONS) { ID *action; - for (action= (ID *)main_newlib->action.first; action; action= (ID *)action->next) { + for (action = (ID *)main_newlib->action.first; action; action = (ID *)action->next) { if (options & LIB_LOAD_VERBOSE) - printf("ActionName: %s\n", action->name+2); - scene_merge->GetLogicManager()->RegisterActionName(action->name+2, action); + printf("ActionName: %s\n", action->name + 2); + scene_merge->GetLogicManager()->RegisterActionName(action->name + 2, action); } } } if (!(options & LIB_LOAD_ASYNC)) status->Finish(); - // TIMEIT_END(bge_link_blend_file); @@ -1084,22 +1016,22 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl /* Note m_map_*** are all ok and don't need to be freed * most are temp and NewRemoveObject frees m_map_gameobject_to_blender */ -bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) +bool KX_BlenderSceneConverter::FreeBlendFile(Main *maggie) { - int maggie_index= -1; - int i=0; + int maggie_index = -1; + int i = 0; - if (maggie==NULL) + if (maggie == NULL) return false; /* tag all false except the one we remove */ - for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) { - Main *main= *it; + for (vector<Main *>::iterator it = m_DynamicMaggie.begin(); !(it == m_DynamicMaggie.end()); it++) { + Main *main = *it; if (main != maggie) { BKE_main_id_tag_all(main, false); } else { - maggie_index= i; + maggie_index = i; } i++; } @@ -1111,15 +1043,12 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) m_DynamicMaggie.erase(m_DynamicMaggie.begin() + maggie_index); BKE_main_id_tag_all(maggie, true); - /* free all tagged objects */ - KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes(); + KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes(); int numScenes = scenes->size(); - - for (int scene_idx=0;scene_idx<numScenes;scene_idx++) - { - KX_Scene* scene = scenes->at(scene_idx); + for (int scene_idx = 0; scene_idx < numScenes; scene_idx++) { + KX_Scene *scene = scenes->at(scene_idx); if (IS_TAGGED(scene->GetBlenderScene())) { m_ketsjiEngine->RemoveScene(scene->GetName()); m_mat_cache.erase(scene); @@ -1128,16 +1057,13 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) numScenes--; } else { - /* in case the mesh might be refered to later */ { - CTR_Map<STR_HashedString,void*> &mapStringToMeshes = scene->GetLogicManager()->GetMeshMap(); + CTR_Map<STR_HashedString, void *> &mapStringToMeshes = scene->GetLogicManager()->GetMeshMap(); - for (int i=0; i<mapStringToMeshes.size(); i++) - { - RAS_MeshObject *meshobj= (RAS_MeshObject *) *mapStringToMeshes.at(i); - if (meshobj && IS_TAGGED(meshobj->GetMesh())) - { + for (int i = 0; i < mapStringToMeshes.size(); i++) { + RAS_MeshObject *meshobj = (RAS_MeshObject *) *mapStringToMeshes.at(i); + if (meshobj && IS_TAGGED(meshobj->GetMesh())) { STR_HashedString mn = meshobj->GetName(); mapStringToMeshes.remove(mn); m_map_mesh_to_gamemesh.remove(CHashedPtr(meshobj->GetMesh())); @@ -1148,15 +1074,13 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) /* Now unregister actions */ { - CTR_Map<STR_HashedString,void*> &mapStringToActions = scene->GetLogicManager()->GetActionMap(); + CTR_Map<STR_HashedString, void *> &mapStringToActions = scene->GetLogicManager()->GetActionMap(); - for (int i=0; i<mapStringToActions.size(); i++) - { - ID *action= (ID*) *mapStringToActions.at(i); + for (int i = 0; i < mapStringToActions.size(); i++) { + ID *action = (ID*) *mapStringToActions.at(i); - if (IS_TAGGED(action)) - { - STR_HashedString an = action->name+2; + if (IS_TAGGED(action)) { + STR_HashedString an = action->name + 2; mapStringToActions.remove(an); i--; } @@ -1166,16 +1090,13 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) //scene->FreeTagged(); /* removed tagged objects and meshes*/ CListValue *obj_lists[] = {scene->GetObjectList(), scene->GetInactiveList(), NULL}; - for (int ob_ls_idx=0; obj_lists[ob_ls_idx]; ob_ls_idx++) - { - CListValue *obs= obj_lists[ob_ls_idx]; - RAS_MeshObject* mesh; + for (int ob_ls_idx = 0; obj_lists[ob_ls_idx]; ob_ls_idx++) { + CListValue *obs = obj_lists[ob_ls_idx]; + RAS_MeshObject *mesh; - for (int ob_idx = 0; ob_idx < obs->GetCount(); ob_idx++) - { - KX_GameObject* gameobj = (KX_GameObject*)obs->GetValue(ob_idx); + for (int ob_idx = 0; ob_idx < obs->GetCount(); ob_idx++) { + KX_GameObject *gameobj = (KX_GameObject*)obs->GetValue(ob_idx); if (IS_TAGGED(gameobj->GetBlenderObject())) { - int size_before = obs->GetCount(); /* Eventually calls RemoveNodeDestructObject @@ -1190,9 +1111,9 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) } else { /* free the mesh, we could be referecing a linked one! */ - int mesh_index= gameobj->GetMeshCount(); + int mesh_index = gameobj->GetMeshCount(); while (mesh_index--) { - mesh= gameobj->GetMesh(mesh_index); + mesh = gameobj->GetMesh(mesh_index); if (IS_TAGGED(mesh->GetMesh())) { gameobj->RemoveMeshes(); /* XXX - slack, should only remove meshes that are library items but mostly objects only have 1 mesh */ break; @@ -1210,11 +1131,9 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) } /* make sure action actuators are not referencing tagged actions */ - for (unsigned int act_idx=0; act_idx<gameobj->GetActuators().size(); act_idx++) - { - if (gameobj->GetActuators()[act_idx]->IsType(SCA_IActuator::KX_ACT_ACTION)) - { - BL_ActionActuator *act = (BL_ActionActuator*)gameobj->GetActuators()[act_idx]; + for (unsigned int act_idx = 0; act_idx < gameobj->GetActuators().size(); act_idx++) { + if (gameobj->GetActuators()[act_idx]->IsType(SCA_IActuator::KX_ACT_ACTION)) { + BL_ActionActuator *act = (BL_ActionActuator *)gameobj->GetActuators()[act_idx]; if (IS_TAGGED(act->GetAction())) act->SetAction(NULL); } @@ -1225,7 +1144,6 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) } } - int size; // delete the entities of this scene @@ -1248,24 +1166,24 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) /* Worlds don't reference original blender data so we need to make a set from them */ - typedef std::set<KX_WorldInfo*> KX_WorldInfoSet; + typedef std::set<KX_WorldInfo *> KX_WorldInfoSet; KX_WorldInfoSet worldset; - for (int scene_idx=0;scene_idx<numScenes;scene_idx++) - { - KX_Scene* scene = scenes->at(scene_idx); + for (int scene_idx = 0; scene_idx < numScenes; scene_idx++) { + KX_Scene *scene = scenes->at(scene_idx); if (scene->GetWorldInfo()) - worldset.insert( scene->GetWorldInfo() ); + worldset.insert(scene->GetWorldInfo()); } - vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit; + vector<pair<KX_Scene *, KX_WorldInfo *> >::iterator worldit; size = m_worldinfos.size(); - for (i=0, worldit=m_worldinfos.begin(); i<size; ) { + for (i = 0, worldit = m_worldinfos.begin(); i < size;) { if ((*worldit).second && (worldset.count((*worldit).second)) == 0) { delete (*worldit).second; *worldit = m_worldinfos.back(); m_worldinfos.pop_back(); size--; - } else { + } + else { i++; worldit++; } @@ -1273,20 +1191,15 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) worldset.clear(); /* done freeing the worlds */ - - - - vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator polymit; + vector<pair<KX_Scene *, RAS_IPolyMaterial *> >::iterator polymit; size = m_polymaterials.size(); + for (i = 0, polymit = m_polymaterials.begin(); i < size; ) { + RAS_IPolyMaterial *mat = (*polymit).second; + Material *bmat = NULL; - - for (i=0, polymit=m_polymaterials.begin(); i<size; ) { - RAS_IPolyMaterial *mat= (*polymit).second; - Material *bmat= NULL; - - KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat); - bmat= bl_mat->GetBlenderMaterial(); + KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial *>(mat); + bmat = bl_mat->GetBlenderMaterial(); if (IS_TAGGED(bmat)) { /* only remove from bucket */ @@ -1297,63 +1210,53 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) polymit++; } - - - for (i=0, polymit=m_polymaterials.begin(); i<size; ) { - RAS_IPolyMaterial *mat= (*polymit).second; - Material *bmat= NULL; + for (i = 0, polymit = m_polymaterials.begin(); i < size; ) { + RAS_IPolyMaterial *mat = (*polymit).second; + Material *bmat = NULL; KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat); - bmat= bl_mat->GetBlenderMaterial(); - - if (bmat) { - //printf("FOUND MAT '%s' !!! ", ((ID*)bmat)->name+2); - } - else { - //printf("LOST MAT !!!"); - } + bmat = bl_mat->GetBlenderMaterial(); if (IS_TAGGED(bmat)) { delete (*polymit).second; *polymit = m_polymaterials.back(); m_polymaterials.pop_back(); size--; - //printf("tagged !\n"); } else { i++; polymit++; - //printf("(un)tagged !\n"); } } - vector<pair<KX_Scene*,BL_Material*> >::iterator matit; + vector<pair<KX_Scene *, BL_Material *> >::iterator matit; size = m_materials.size(); - for (i=0, matit=m_materials.begin(); i<size; ) { - BL_Material *mat= (*matit).second; + for (i = 0, matit = m_materials.begin(); i < size; ) { + BL_Material *mat = (*matit).second; if (IS_TAGGED(mat->material)) { delete (*matit).second; *matit = m_materials.back(); m_materials.pop_back(); size--; - } else { + } + else { i++; matit++; } } - vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator meshit; + vector<pair<KX_Scene *, RAS_MeshObject *> >::iterator meshit; RAS_BucketManager::BucketList::iterator bit; list<RAS_MeshSlot>::iterator msit; RAS_BucketManager::BucketList buckets; size = m_meshobjects.size(); - for (i=0, meshit=m_meshobjects.begin(); i<size; ) { - RAS_MeshObject *me= (*meshit).second; + for (i = 0, meshit = m_meshobjects.begin(); i < size;) { + RAS_MeshObject *me = (*meshit).second; if (IS_TAGGED(me->GetMesh())) { // Before deleting the mesh object, make sure the rasterizer is // no longer referencing it. buckets = meshit->first->GetBucketManager()->GetSolidBuckets(); - for (bit=buckets.begin(); bit!=buckets.end(); bit++) { + for (bit = buckets.begin(); bit != buckets.end(); bit++) { msit = (*bit)->msBegin(); while (msit != (*bit)->msEnd()) { @@ -1366,7 +1269,7 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) // And now the alpha buckets buckets = meshit->first->GetBucketManager()->GetAlphaBuckets(); - for (bit=buckets.begin(); bit!=buckets.end(); bit++) { + for (bit = buckets.begin(); bit != buckets.end(); bit++) { msit = (*bit)->msBegin(); while (msit != (*bit)->msEnd()) { @@ -1382,7 +1285,8 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) *meshit = m_meshobjects.back(); m_meshobjects.pop_back(); size--; - } else { + } + else { i++; meshit++; } @@ -1409,24 +1313,23 @@ bool KX_BlenderSceneConverter::FreeBlendFile(const char *path) bool KX_BlenderSceneConverter::MergeScene(KX_Scene *to, KX_Scene *from) { - { - vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator itp = m_worldinfos.begin(); + vector<pair<KX_Scene *, KX_WorldInfo *> >::iterator itp = m_worldinfos.begin(); while (itp != m_worldinfos.end()) { - if ((*itp).first==from) - (*itp).first= to; + if ((*itp).first == from) + (*itp).first = to; itp++; } } { - vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator itp = m_polymaterials.begin(); + vector<pair<KX_Scene *, RAS_IPolyMaterial *> >::iterator itp = m_polymaterials.begin(); while (itp != m_polymaterials.end()) { - if ((*itp).first==from) { - (*itp).first= to; + if ((*itp).first == from) { + (*itp).first = to; /* also switch internal data */ - RAS_IPolyMaterial*mat= (*itp).second; + RAS_IPolyMaterial *mat = (*itp).second; mat->Replace_IScene(to); } itp++; @@ -1434,29 +1337,29 @@ bool KX_BlenderSceneConverter::MergeScene(KX_Scene *to, KX_Scene *from) } { - vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator itp = m_meshobjects.begin(); + vector<pair<KX_Scene *, RAS_MeshObject *> >::iterator itp = m_meshobjects.begin(); while (itp != m_meshobjects.end()) { - if ((*itp).first==from) - (*itp).first= to; + if ((*itp).first == from) + (*itp).first = to; itp++; } } { - vector<pair<KX_Scene*,BL_Material*> >::iterator itp = m_materials.begin(); + vector<pair<KX_Scene *, BL_Material *> >::iterator itp = m_materials.begin(); while (itp != m_materials.end()) { - if ((*itp).first==from) - (*itp).first= to; + if ((*itp).first == from) + (*itp).first = to; itp++; } } - + return true; } /* This function merges a mesh from the current scene into another main * it does not convert */ -RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene, Main *maggie, const char *name) +RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene *kx_scene, Main *maggie, const char *name) { /* Find a mesh in the current main */ ID *me= static_cast<ID *>(BLI_findstring(&m_maggie->mesh, name, offsetof(ID, name) + 2)); @@ -1464,7 +1367,7 @@ RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene, if (me == NULL) { // The mesh wasn't in the current main, try any dynamic (i.e., LibLoaded) ones - vector<Main*>::iterator it; + vector<Main *>::iterator it; for (it = GetMainDynamic().begin(); it != GetMainDynamic().end(); it++) { me = static_cast<ID *>(BLI_findstring(&(*it)->mesh, name, offsetof(ID, name) + 2)); @@ -1474,12 +1377,12 @@ RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene, break; } } - - if (me==NULL) { + + if (me == NULL) { printf("Could not be found \"%s\"\n", name); return NULL; } - + /* Watch this!, if its used in the original scene can cause big troubles */ if (me->us > 0) { #ifdef DEBUG @@ -1491,34 +1394,32 @@ RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene, BLI_remlink(&from_maggie->mesh, me); /* even if we made the copy it needs to be removed */ BLI_addtail(&maggie->mesh, me); - /* Must copy the materials this uses else we cant free them */ { - Mesh *mesh= (Mesh *)me; - + Mesh *mesh = (Mesh *)me; + /* ensure all materials are tagged */ - for (int i=0; i<mesh->totcol; i++) + for (int i = 0; i < mesh->totcol; i++) { if (mesh->mat[i]) mesh->mat[i]->id.flag &= ~LIB_DOIT; - - for (int i=0; i<mesh->totcol; i++) - { - Material *mat_old= mesh->mat[i]; - + } + + for (int i = 0; i < mesh->totcol; i++) { + Material *mat_old = mesh->mat[i]; + /* if its tagged its a replaced material */ - if (mat_old && (mat_old->id.flag & LIB_DOIT)==0) - { - Material *mat_old= mesh->mat[i]; - Material *mat_new= BKE_material_copy( mat_old ); - + if (mat_old && (mat_old->id.flag & LIB_DOIT) == 0) { + Material *mat_old = mesh->mat[i]; + Material *mat_new = BKE_material_copy(mat_old); + mat_new->id.flag |= LIB_DOIT; mat_old->id.us--; - + BLI_remlink(&G.main->mat, mat_new); // BKE_material_copy uses G.main, and there is no BKE_material_copy_ex BLI_addtail(&maggie->mat, mat_new); - + mesh->mat[i] = mat_new; - + /* the same material may be used twice */ for (int j = i + 1; j < mesh->totcol; j++) { if (mesh->mat[j] == mat_old) { diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index a4c9472df2f..9e5b1464ac0 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -519,7 +519,7 @@ int main(int argc, char** argv) BKE_sound_init_once(); - set_free_windowmanager_cb(wm_free); + BKE_library_callback_free_window_manager_set(wm_free); /* if running blenderplayer the last argument can't be parsed since it has to be the filename. else it is bundled */ isBlenderPlayer = !BLO_is_a_runtime(argv[0]); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index e464883016e..44d9bfa0cf4 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -1907,7 +1907,7 @@ PyMethodDef KX_GameObject::Methods[] = { {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS}, {"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS}, {"getAxisVect",(PyCFunction) KX_GameObject::sPyGetAxisVect, METH_O}, - {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics,METH_NOARGS}, + {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics, METH_VARARGS}, {"restoreDynamics", (PyCFunction)KX_GameObject::sPyRestoreDynamics,METH_NOARGS}, {"enableRigidBody", (PyCFunction)KX_GameObject::sPyEnableRigidBody,METH_NOARGS}, {"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_NOARGS}, @@ -3318,10 +3318,16 @@ PyObject *KX_GameObject::PyApplyImpulse(PyObject *args) -PyObject *KX_GameObject::PySuspendDynamics() +PyObject *KX_GameObject::PySuspendDynamics(PyObject *args) { + bool ghost = false; + + if (!PyArg_ParseTuple(args, "|b", &ghost)) + return NULL; + if (GetPhysicsController()) - GetPhysicsController()->SuspendDynamics(); + GetPhysicsController()->SuspendDynamics(ghost); + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 54bb6ee2605..9c081b449ec 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -517,7 +517,14 @@ public: */ void ActivateGraphicController(bool recurse); + /** Set the object's collison group + * \param filter The group bitfield + */ void SetUserCollisionGroup(unsigned short filter); + + /** Set the object's collison mask + * \param filter The mask bitfield + */ void SetUserCollisionMask(unsigned short mask); unsigned short GetUserCollisionGroup(); unsigned short GetUserCollisionMask(); @@ -907,7 +914,7 @@ public: * Change the layer of the object (when it is added in another layer * than the original layer) */ - void + virtual void SetLayer( int l ); @@ -998,7 +1005,7 @@ public: KX_PYMETHOD_O(KX_GameObject,SetState); KX_PYMETHOD_VARARGS(KX_GameObject,AlignAxisToVect); KX_PYMETHOD_O(KX_GameObject,GetAxisVect); - KX_PYMETHOD_NOARGS(KX_GameObject,SuspendDynamics); + KX_PYMETHOD_VARARGS(KX_GameObject,SuspendDynamics); KX_PYMETHOD_NOARGS(KX_GameObject,RestoreDynamics); KX_PYMETHOD_NOARGS(KX_GameObject,EnableRigidBody); KX_PYMETHOD_NOARGS(KX_GameObject,DisableRigidBody); diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index f0b47684092..40af9b4ca39 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -1108,6 +1108,10 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) KX_SetActiveScene(scene); +#ifdef WITH_PYTHON + scene->RunDrawingCallbacks(scene->GetPreDrawSetupCB()); +#endif + GetSceneViewport(scene, cam, area, viewport); // store the computed viewport in the scene diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index d6b84e98aec..0dec5715588 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -108,6 +108,7 @@ void KX_LightObject::UpdateScene(KX_Scene *kxscene) void KX_LightObject::SetLayer(int layer) { + KX_GameObject::SetLayer(layer); m_lightobj->m_layer = layer; } diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h index 386f8e95789..3a58584223d 100644 --- a/source/gameengine/Ketsji/KX_Light.h +++ b/source/gameengine/Ketsji/KX_Light.h @@ -60,7 +60,7 @@ public: RAS_ILightObject* GetLightData() { return m_lightobj;} void UpdateScene(class KX_Scene *kxscene); - void SetLayer(int layer); + virtual void SetLayer(int layer); virtual int GetGameObjectType() { return OBJ_LIGHT; } diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index a3e1d1562c9..a460d9bd392 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -238,6 +238,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, m_attr_dict = NULL; m_draw_call_pre = NULL; m_draw_call_post = NULL; + m_draw_setup_call_pre = NULL; #endif } @@ -834,12 +835,6 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) (*git)->Relink(&m_map_gameobject_to_replica); // add the object in the layer of the parent (*git)->SetLayer(groupobj->GetLayer()); - // If the object was a light, we need to update it's RAS_LightObject as well - if ((*git)->GetGameObjectType()==SCA_IObject::OBJ_LIGHT) - { - KX_LightObject* lightobj = static_cast<KX_LightObject*>(*git); - lightobj->SetLayer(groupobj->GetLayer()); - } } // replicate crosslinks etc. between logic bricks @@ -915,18 +910,20 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, replica->GetSGNode()->AddChild(childreplicanode); } - // At this stage all the objects in the hierarchy have been duplicated, - // we can update the scenegraph, we need it for the duplication of logic - MT_Point3 newpos = referenceobj->NodeGetWorldPosition(); - replica->NodeSetLocalPosition(newpos); + if (referenceobj) { + // At this stage all the objects in the hierarchy have been duplicated, + // we can update the scenegraph, we need it for the duplication of logic + MT_Point3 newpos = referenceobj->NodeGetWorldPosition(); + replica->NodeSetLocalPosition(newpos); - MT_Matrix3x3 newori = referenceobj->NodeGetWorldOrientation(); - replica->NodeSetLocalOrientation(newori); - - // get the rootnode's scale - MT_Vector3 newscale = referenceobj->GetSGNode()->GetRootSGParent()->GetLocalScale(); - // set the replica's relative scale with the rootnode's scale - replica->NodeSetRelativeScale(newscale); + MT_Matrix3x3 newori = referenceobj->NodeGetWorldOrientation(); + replica->NodeSetLocalOrientation(newori); + + // get the rootnode's scale + MT_Vector3 newscale = referenceobj->GetSGNode()->GetRootSGParent()->GetLocalScale(); + // set the replica's relative scale with the rootnode's scale + replica->NodeSetRelativeScale(newscale); + } replica->GetSGNode()->UpdateWorldData(0); replica->GetSGNode()->SetBBox(originalobj->GetSGNode()->BBox()); @@ -946,13 +943,13 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, { // this will also relink the actuators in the hierarchy (*git)->Relink(&m_map_gameobject_to_replica); - // add the object in the layer of the reference object - (*git)->SetLayer(referenceobj->GetLayer()); - // If the object was a light, we need to update it's RAS_LightObject as well - if ((*git)->GetGameObjectType()==SCA_IObject::OBJ_LIGHT) - { - KX_LightObject* lightobj = static_cast<KX_LightObject*>(*git); - lightobj->SetLayer(referenceobj->GetLayer()); + if (referenceobj) { + // add the object in the layer of the reference object + (*git)->SetLayer(referenceobj->GetLayer()); + } + else { + // We don't know what layer set, so we set all visible layers in the blender scene. + (*git)->SetLayer(m_blenderScene->lay); } } @@ -2399,6 +2396,17 @@ PyObject *KX_Scene::pyattr_get_drawing_callback_post(void *self_v, const KX_PYAT return self->m_draw_call_post; } +PyObject *KX_Scene::pyattr_get_drawing_setup_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Scene* self = static_cast<KX_Scene*>(self_v); + + if (self->m_draw_setup_call_pre == NULL) + self->m_draw_setup_call_pre = PyList_New(0); + + Py_INCREF(self->m_draw_setup_call_pre); + return self->m_draw_setup_call_pre; +} + int KX_Scene::pyattr_set_drawing_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { KX_Scene* self = static_cast<KX_Scene*>(self_v); @@ -2433,6 +2441,22 @@ int KX_Scene::pyattr_set_drawing_callback_post(void *self_v, const KX_PYATTRIBUT return PY_SET_ATTR_SUCCESS; } +int KX_Scene::pyattr_set_drawing_setup_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_Scene* self = static_cast<KX_Scene*>(self_v); + + if (!PyList_CheckExact(value)) { + PyErr_SetString(PyExc_ValueError, "Expected a list"); + return PY_SET_ATTR_FAIL; + } + + Py_XDECREF(self->m_draw_setup_call_pre); + Py_INCREF(value); + + self->m_draw_setup_call_pre = value; + return PY_SET_ATTR_SUCCESS; +} + PyObject *KX_Scene::pyattr_get_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_Scene* self = static_cast<KX_Scene*>(self_v); @@ -2462,6 +2486,7 @@ PyAttributeDef KX_Scene::Attributes[] = { KX_PYATTRIBUTE_RW_FUNCTION("active_camera", KX_Scene, pyattr_get_active_camera, pyattr_set_active_camera), KX_PYATTRIBUTE_RW_FUNCTION("pre_draw", KX_Scene, pyattr_get_drawing_callback_pre, pyattr_set_drawing_callback_pre), KX_PYATTRIBUTE_RW_FUNCTION("post_draw", KX_Scene, pyattr_get_drawing_callback_post, pyattr_set_drawing_callback_post), + KX_PYATTRIBUTE_RW_FUNCTION("pre_draw_setup", KX_Scene, pyattr_get_drawing_setup_callback_pre, pyattr_set_drawing_setup_callback_pre), KX_PYATTRIBUTE_RW_FUNCTION("gravity", KX_Scene, pyattr_get_gravity, pyattr_set_gravity), KX_PYATTRIBUTE_BOOL_RO("suspended", KX_Scene, m_suspend), KX_PYATTRIBUTE_BOOL_RO("activity_culling", KX_Scene, m_activity_culling), @@ -2474,23 +2499,23 @@ KX_PYMETHODDEF_DOC(KX_Scene, addObject, "addObject(object, other, time=0)\n" "Returns the added object.\n") { - PyObject *pyob, *pyreference; + PyObject *pyob, *pyreference = Py_None; KX_GameObject *ob, *reference; int time = 0; - if (!PyArg_ParseTuple(args, "OO|i:addObject", &pyob, &pyreference, &time)) + if (!PyArg_ParseTuple(args, "O|Oi:addObject", &pyob, &pyreference, &time)) return NULL; - if ( !ConvertPythonToGameObject(pyob, &ob, false, "scene.addObject(object, reference, time): KX_Scene (first argument)") || - !ConvertPythonToGameObject(pyreference, &reference, false, "scene.addObject(object, reference, time): KX_Scene (second argument)") ) + if (!ConvertPythonToGameObject(pyob, &ob, false, "scene.addObject(object, reference, time): KX_Scene (first argument)") || + !ConvertPythonToGameObject(pyreference, &reference, true, "scene.addObject(object, reference, time): KX_Scene (second argument)")) return NULL; if (!m_inactivelist->SearchValue(ob)) { PyErr_Format(PyExc_ValueError, "scene.addObject(object, reference, time): KX_Scene (first argument): object must be in an inactive layer"); return NULL; } - SCA_IObject* replica = AddReplicaObject((SCA_IObject*)ob, reference, time); + SCA_IObject *replica = AddReplicaObject((SCA_IObject*)ob, reference, time); // release here because AddReplicaObject AddRef's // the object is added to the scene so we don't want python to own a reference diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 93e764851a9..a5645ea6448 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -107,6 +107,7 @@ class KX_Scene : public PyObjectPlus, public SCA_IScene PyObject* m_attr_dict; PyObject* m_draw_call_pre; PyObject* m_draw_call_post; + PyObject* m_draw_setup_call_pre; #endif struct CullingInfo { @@ -631,6 +632,8 @@ public: static int pyattr_set_drawing_callback_pre(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_drawing_callback_post(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_drawing_callback_post(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_drawing_setup_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_drawing_setup_callback_pre(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_gravity(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); @@ -647,6 +650,7 @@ public: PyObject *GetPreDrawCB() { return m_draw_call_pre; } PyObject *GetPostDrawCB() { return m_draw_call_post; } + PyObject *GetPreDrawSetupCB() { return m_draw_setup_call_pre; } #endif /** diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index b2b8f30a706..0a71c0a7aac 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -123,10 +123,8 @@ bool CleanPairCallback::processOverlap(btBroadphasePair &pair) m_pairCache->cleanOverlappingPair(pair, m_dispatcher); CcdPhysicsController *ctrl0 = (CcdPhysicsController*)(((btCollisionObject*)pair.m_pProxy0->m_clientObject)->getUserPointer()); CcdPhysicsController *ctrl1 = (CcdPhysicsController*)(((btCollisionObject*)pair.m_pProxy1->m_clientObject)->getUserPointer()); - if (ctrl0 && ctrl1) { - ctrl0->GetRigidBody()->activate(true); - ctrl1->GetRigidBody()->activate(true); - } + ctrl0->GetCollisionObject()->activate(false); + ctrl1->GetCollisionObject()->activate(false); } return false; } @@ -1097,6 +1095,10 @@ void CcdPhysicsController::ResolveCombinedVelocities(float linvelX,float linvel void CcdPhysicsController::RefreshCollisions() { + // the object is in an inactive layer so it's useless to update it and can cause problems + if (!GetPhysicsEnvironment()->IsActiveCcdPhysicsController(this)) + return; + btSoftRigidDynamicsWorld *dw = GetPhysicsEnvironment()->GetDynamicsWorld(); btBroadphaseProxy *proxy = m_object->getBroadphaseHandle(); btDispatcher *dispatcher = dw->getDispatcher(); @@ -1104,8 +1106,10 @@ void CcdPhysicsController::RefreshCollisions() CleanPairCallback cleanPairs(proxy, pairCache, dispatcher); pairCache->processAllOverlappingPairs(&cleanPairs, dispatcher); + // Forcibly recreate the physics object - GetPhysicsEnvironment()->UpdateCcdPhysicsController(this, m_cci.m_mass, m_cci.m_collisionFlags, m_cci.m_collisionFilterGroup, m_cci.m_collisionFilterMask); + btBroadphaseProxy* handle = m_object->getBroadphaseHandle(); + GetPhysicsEnvironment()->UpdateCcdPhysicsController(this, GetMass(), m_object->getCollisionFlags(), handle->m_collisionFilterGroup, handle->m_collisionFilterMask); } void CcdPhysicsController::SuspendDynamics(bool ghost) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 984273ec63e..0ecb79d91ea 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -569,6 +569,7 @@ void CcdPhysicsEnvironment::UpdateCcdPhysicsController(CcdPhysicsController* ctr // this function is used when the collisionning group of a controller is changed // remove and add the collistioning object btRigidBody* body = ctrl->GetRigidBody(); + btSoftBody *softBody = ctrl->GetSoftBody(); btCollisionObject* obj = ctrl->GetCollisionObject(); if (obj) { @@ -582,6 +583,9 @@ void CcdPhysicsEnvironment::UpdateCcdPhysicsController(CcdPhysicsController* ctr body->setMassProps(newMass, inertia); m_dynamicsWorld->addRigidBody(body, newCollisionGroup, newCollisionMask); } + else if (softBody) { + m_dynamicsWorld->addSoftBody(softBody); + } else { m_dynamicsWorld->addCollisionObject(obj, newCollisionGroup, newCollisionMask); } @@ -643,6 +647,11 @@ void CcdPhysicsEnvironment::RefreshCcdPhysicsController(CcdPhysicsController* ct } } +bool CcdPhysicsEnvironment::IsActiveCcdPhysicsController(CcdPhysicsController *ctrl) +{ + return (m_controllers.find(ctrl) != m_controllers.end()); +} + void CcdPhysicsEnvironment::AddCcdGraphicController(CcdGraphicController* ctrl) { if (m_cullingTree && !ctrl->GetBroadphaseHandle()) @@ -3672,7 +3681,7 @@ void CcdPhysicsEnvironment::SetupObjectConstraints(KX_GameObject *obj_src, KX_Ga break; } - for (dof; dof < dof_max; dof++) { + for (; dof < dof_max; dof++) { if (dat->flag & dofbit) { phys_env->SetConstraintParam(constraintId, dof, dat->minLimit[dof], dat->maxLimit[dof]); } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index 113db3348ca..3b1fe63db0b 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -227,6 +227,8 @@ protected: void RefreshCcdPhysicsController(CcdPhysicsController* ctrl); + bool IsActiveCcdPhysicsController(CcdPhysicsController *ctrl); + void AddCcdGraphicController(CcdGraphicController* ctrl); void RemoveCcdGraphicController(CcdGraphicController* ctrl); diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index f47f56541ba..95c153a7e2a 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -1074,12 +1074,17 @@ void RAS_OpenGLRasterizer::SetMipmapping(MipmapOption val) RAS_IRasterizer::MipmapOption RAS_OpenGLRasterizer::GetMipmapping() { - if (GPU_get_linear_mipmap()) - return RAS_IRasterizer::RAS_MIPMAP_LINEAR; - else if (GPU_get_mipmap()) - return RAS_IRasterizer::RAS_MIPMAP_NEAREST; - else + if (GPU_get_mipmap()) { + if (GPU_get_linear_mipmap()) { + return RAS_IRasterizer::RAS_MIPMAP_LINEAR; + } + else { + return RAS_IRasterizer::RAS_MIPMAP_NEAREST; + } + } + else { return RAS_IRasterizer::RAS_MIPMAP_NONE; + } } void RAS_OpenGLRasterizer::SetUsingOverrideShader(bool val) |