diff options
author | Jacques Lucke <jacques@blender.org> | 2020-03-31 10:40:01 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2020-03-31 10:40:01 +0300 |
commit | ebecd0aae5757646c56631840d7c68886ef748fa (patch) | |
tree | 44a044edd523f2b15098595a34c322664e67c911 /source | |
parent | 118a9f8589e8be8a8052b727f3ca3ebd2a7c4eb3 (diff) | |
parent | 24f8c8491d8255b3d10d5fa6fcadf8c7f336076c (diff) |
Merge branch 'master' into simulation-data-block
Diffstat (limited to 'source')
297 files changed, 6461 insertions, 4267 deletions
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h index fd6411f7c69..9aee8c9b78b 100644 --- a/source/blender/blenfont/BLF_api.h +++ b/source/blender/blenfont/BLF_api.h @@ -238,11 +238,9 @@ void BLF_thumb_preview(const char *filename, int h, int channels) ATTR_NONNULL(); -/* blf_font_i18.c */ -unsigned char *BLF_get_unifont(int *unifont_size); -void BLF_free_unifont(void); -unsigned char *BLF_get_unifont_mono(int *unifont_size); -void BLF_free_unifont_mono(void); +/* blf_font_default.c */ +int BLF_load_default(const bool unique); +int BLF_load_mono_default(const bool unique); #ifdef DEBUG void BLF_state_print(int fontid); diff --git a/source/blender/blenfont/CMakeLists.txt b/source/blender/blenfont/CMakeLists.txt index fa02d6d21c9..ac927dd388d 100644 --- a/source/blender/blenfont/CMakeLists.txt +++ b/source/blender/blenfont/CMakeLists.txt @@ -41,7 +41,7 @@ set(SRC intern/blf.c intern/blf_dir.c intern/blf_font.c - intern/blf_font_i18n.c + intern/blf_font_default.c intern/blf_glyph.c intern/blf_thumbs.c intern/blf_util.c diff --git a/source/blender/blenfont/intern/blf_font_default.c b/source/blender/blenfont/intern/blf_font_default.c new file mode 100644 index 00000000000..f33d7cd4203 --- /dev/null +++ b/source/blender/blenfont/intern/blf_font_default.c @@ -0,0 +1,59 @@ +/* + * 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) 2011 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup blf + * + * API for loading default font files. + */ + +#include <stdio.h> + +#include "BLF_api.h" + +#include "BLI_path_util.h" + +#include "BKE_appdir.h" + +static int blf_load_font_default(const char *filename, const bool unique) +{ + const char *dir = BKE_appdir_folder_id(BLENDER_DATAFILES, "fonts"); + if (dir == NULL) { + fprintf(stderr, + "%s: 'fonts' data path not found for '%s', will not be able to display text\n", + __func__, + filename); + return -1; + } + + char filepath[FILE_MAX]; + BLI_join_dirfile(filepath, sizeof(filepath), dir, filename); + + return (unique) ? BLF_load_unique(filepath) : BLF_load(filepath); +} + +int BLF_load_default(const bool unique) +{ + return blf_load_font_default("droidsans.ttf", unique); +} + +int BLF_load_mono_default(const bool unique) +{ + return blf_load_font_default("bmonofont-i18n.ttf", unique); +} diff --git a/source/blender/blenfont/intern/blf_font_i18n.c b/source/blender/blenfont/intern/blf_font_i18n.c deleted file mode 100644 index 74113ae4ce1..00000000000 --- a/source/blender/blenfont/intern/blf_font_i18n.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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) 2011 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup blf - * - * API for accessing font files. - */ - -#include <stdlib.h> -#include <string.h> - -#include "BLF_api.h" - -#include "MEM_guardedalloc.h" - -#include "BLI_utildefines.h" - -#include "BKE_appdir.h" - -#ifdef WITH_INTERNATIONAL - -# include "BLI_fileops.h" -# include "BLI_string.h" - -struct FontBuf { - const char *filename; - uchar *data; - int data_len; -}; - -static struct FontBuf unifont_ttf = {"droidsans.ttf.gz"}; -static struct FontBuf unifont_mono_ttf = {"bmonofont-i18n.ttf.gz"}; - -static void fontbuf_load(struct FontBuf *fb) -{ - const char *fontpath = BKE_appdir_folder_id(BLENDER_DATAFILES, "fonts"); - if (fontpath) { - char unifont_path[1024]; - BLI_snprintf(unifont_path, sizeof(unifont_path), "%s/%s", fontpath, fb->filename); - fb->data = (uchar *)BLI_file_ungzip_to_mem(unifont_path, &fb->data_len); - } - else { - printf("%s: 'fonts' data path not found for '%s', continuing\n", __func__, fb->filename); - } -} - -static void fontbuf_free(struct FontBuf *fb) -{ - MEM_SAFE_FREE(fb->data); - fb->data_len = 0; -} - -static uchar *fontbuf_get_mem(struct FontBuf *fb, int *r_size) -{ - if (fb->data == NULL) { - fontbuf_load(fb); - } - *r_size = fb->data_len; - return fb->data; -} - -#endif /* WITH_INTERNATIONAL */ - -uchar *BLF_get_unifont(int *r_unifont_size) -{ -#ifdef WITH_INTERNATIONAL - return fontbuf_get_mem(&unifont_ttf, r_unifont_size); -#else - UNUSED_VARS(r_unifont_size); - return NULL; -#endif -} - -uchar *BLF_get_unifont_mono(int *r_unifont_size) -{ -#ifdef WITH_INTERNATIONAL - return fontbuf_get_mem(&unifont_mono_ttf, r_unifont_size); -#else - UNUSED_VARS(r_unifont_size); - return NULL; -#endif -} - -void BLF_free_unifont(void) -{ -#ifdef WITH_INTERNATIONAL - fontbuf_free(&unifont_ttf); -#endif -} - -void BLF_free_unifont_mono(void) -{ -#ifdef WITH_INTERNATIONAL - fontbuf_free(&unifont_mono_ttf); -#endif -} diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index cd4733a4e62..6c383ae5011 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -61,7 +61,7 @@ typedef struct PoseTree { int stretch; /* disable stretching */ } PoseTree; -/* Core armature functionality */ +/* Core armature functionality. */ struct bArmature *BKE_armature_add(struct Main *bmain, const char *name); struct bArmature *BKE_armature_from_object(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_colorband.h b/source/blender/blenkernel/BKE_colorband.h index 6e03f4db3d2..355682671fe 100644 --- a/source/blender/blenkernel/BKE_colorband.h +++ b/source/blender/blenkernel/BKE_colorband.h @@ -29,7 +29,7 @@ extern "C" { struct ColorBand; -/* in ColorBand struct */ +/** #ColorBand.data length. */ #define MAXCOLORBAND 32 void BKE_colorband_init(struct ColorBand *coba, bool rangetype); diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 4ce740a1f5a..0d8b6efb4b1 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -322,12 +322,12 @@ struct ImageTile *BKE_image_get_tile_from_iuser(struct Image *ima, struct ImageU int BKE_image_get_tile_from_pos(struct Image *ima, const float uv[2], - float new_uv[2], - float ofs[2]); + float r_uv[2], + float r_ofs[2]); -void BKE_image_get_size(struct Image *image, struct ImageUser *iuser, int *width, int *height); -void BKE_image_get_size_fl(struct Image *image, struct ImageUser *iuser, float size[2]); -void BKE_image_get_aspect(struct Image *image, float *aspx, float *aspy); +void BKE_image_get_size(struct Image *image, struct ImageUser *iuser, int *r_width, int *r_height); +void BKE_image_get_size_fl(struct Image *image, struct ImageUser *iuser, float r_size[2]); +void BKE_image_get_aspect(struct Image *image, float *r_aspx, float *r_aspy); /* image_gen.c */ void BKE_image_buf_fill_color( diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h index 19eb40debe6..7059675ec7d 100644 --- a/source/blender/blenkernel/BKE_layer.h +++ b/source/blender/blenkernel/BKE_layer.h @@ -44,10 +44,19 @@ struct Scene; struct View3D; struct ViewLayer; +typedef enum eViewLayerCopyMethod { + VIEWLAYER_ADD_NEW = 0, + VIEWLAYER_ADD_EMPTY = 1, + VIEWLAYER_ADD_COPY = 2, +} eViewLayerCopyMethod; + struct ViewLayer *BKE_view_layer_default_view(const struct Scene *scene); struct ViewLayer *BKE_view_layer_default_render(const struct Scene *scene); struct ViewLayer *BKE_view_layer_find(const struct Scene *scene, const char *layer_name); -struct ViewLayer *BKE_view_layer_add(struct Scene *scene, const char *name); +struct ViewLayer *BKE_view_layer_add(Scene *scene, + const char *name, + ViewLayer *view_layer_source, + const int type); /* DEPRECATED */ struct ViewLayer *BKE_view_layer_context_active_PLACEHOLDER(const struct Scene *scene); diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 9c7d19ea151..cef26345980 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -106,10 +106,10 @@ float BKE_mask_spline_project_co(struct MaskSpline *spline, const eMaskSign sign); /* point */ -eMaskhandleMode BKE_mask_point_handles_mode_get(struct MaskSplinePoint *point); -void BKE_mask_point_handle(struct MaskSplinePoint *point, +eMaskhandleMode BKE_mask_point_handles_mode_get(const struct MaskSplinePoint *point); +void BKE_mask_point_handle(const struct MaskSplinePoint *point, eMaskWhichHandle which_handle, - float handle[2]); + float r_handle[2]); void BKE_mask_point_set_handle(struct MaskSplinePoint *point, eMaskWhichHandle which_handle, float loc[2], diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index a25b73625fa..c37e56149eb 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -125,6 +125,11 @@ typedef enum ModifierApplyFlag { /** Ignore scene simplification flag and use subdivisions * level set in multires modifier. */ MOD_APPLY_IGNORE_SIMPLIFY = 1 << 3, + /** The effect of this modifier will be applied to the base mesh + * The modifier itself will be removed from the modifier stack. + * This flag can be checked to ignore rendering display data to the mesh. + * See `OBJECT_OT_modifier_apply` operator. */ + MOD_APPLY_TO_BASE_MESH = 1 << 4, } ModifierApplyFlag; typedef struct ModifierUpdateDepsgraphContext { diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index c805b5f53a6..fe5b8cff31c 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -197,7 +197,8 @@ void BKE_multires_subdiv_mesh_settings_init(struct SubdivToMeshSettings *mesh_se const struct Object *object, const struct MultiresModifierData *mmd, const bool use_render_params, - const bool ignore_simplify); + const bool ignore_simplify, + const bool ignore_control_edges); /* General helpers. */ diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index df0f0e730a5..556cd7105a9 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -337,11 +337,14 @@ void BKE_sequencer_cache_cleanup_sequence(struct Scene *scene, struct Sequence *seq, struct Sequence *seq_changed, int invalidate_types); -void BKE_sequencer_cache_iterate( - struct Scene *scene, - void *userdata, - bool callback(void *userdata, struct Sequence *seq, int cfra, int cache_type, float cost)); -size_t BKE_sequencer_cache_get_num_items(struct Scene *scene); +void BKE_sequencer_cache_iterate(struct Scene *scene, + void *userdata, + bool callback_init(void *userdata, size_t item_count), + bool callback_iter(void *userdata, + struct Sequence *seq, + int cfra, + int cache_type, + float cost)); bool BKE_sequencer_cache_is_full(struct Scene *scene); /* ********************************************************************** diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index af50e61eb2d..685582bcecf 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -117,8 +117,8 @@ void BKE_sound_ensure_scene(struct Scene *scene); void BKE_sound_destroy_scene(struct Scene *scene); -void BKE_sound_lock_scene(struct Scene *scene); -void BKE_sound_unlock_scene(struct Scene *scene); +void BKE_sound_lock(void); +void BKE_sound_unlock(void); void BKE_sound_reset_scene_specs(struct Scene *scene); diff --git a/source/blender/blenkernel/BKE_subdiv.h b/source/blender/blenkernel/BKE_subdiv.h index 3b342402ecb..0333d52a464 100644 --- a/source/blender/blenkernel/BKE_subdiv.h +++ b/source/blender/blenkernel/BKE_subdiv.h @@ -66,7 +66,7 @@ typedef struct SubdivSettings { /* This refers to an adaptive isolation when creating patches for the subdivided surface. * - * When is set to to false (aka uniform subdivision) fixed depth of isolation is used, which + * When is set to false (aka uniform subdivision) fixed depth of isolation is used, which * allows to iteratively add more subdivisions (uniform subdivision level 2 = uniform subdivision * level 1 + uniform subdivision level 1). Uniform subdivisions will progressively go to a limit * surface. diff --git a/source/blender/blenkernel/BKE_subdiv_ccg.h b/source/blender/blenkernel/BKE_subdiv_ccg.h index 7d612f293ab..f8534371b17 100644 --- a/source/blender/blenkernel/BKE_subdiv_ccg.h +++ b/source/blender/blenkernel/BKE_subdiv_ccg.h @@ -216,7 +216,10 @@ typedef struct SubdivCCG { } dirty; } SubdivCCG; -/* Create real hi-res CCG from subdivision. +/* Create CCG representation of subdivision surface. + * + * NOTE: CCG stores dense verticies in a grid-like storage. There is no edges or + * polygons informations for the high-poly surface. * * NOTE: Subdiv is expected to be refined and ready for evaluation. * NOTE: CCG becomes an owner of subdiv. diff --git a/source/blender/blenkernel/BKE_subdiv_deform.h b/source/blender/blenkernel/BKE_subdiv_deform.h index 72d2b252cf7..11ef225de27 100644 --- a/source/blender/blenkernel/BKE_subdiv_deform.h +++ b/source/blender/blenkernel/BKE_subdiv_deform.h @@ -34,6 +34,10 @@ struct Mesh; struct Subdiv; /* Special version of subdivision surface which calculates final positions for coarse vertices. + * Effectively is pushsing the coarse positions to the limit surface. + * + * One of the usage examples is calculation of crazy space of subdivision modifier, allowing to + * paint on a deformed mesh with subsurf on it. * * vertex_cos are supposed to hold coordinates of the coarse mesh. */ void BKE_subdiv_deform_coarse_vertices(struct Subdiv *subdiv, diff --git a/source/blender/blenkernel/BKE_subdiv_eval.h b/source/blender/blenkernel/BKE_subdiv_eval.h index 095d3c17d63..3f682716928 100644 --- a/source/blender/blenkernel/BKE_subdiv_eval.h +++ b/source/blender/blenkernel/BKE_subdiv_eval.h @@ -50,6 +50,8 @@ void BKE_subdiv_eval_init_displacement(struct Subdiv *subdiv); /* Single point queries. */ +/* Evaluate point at a limit surface, with optional derivatives and normal. */ + void BKE_subdiv_eval_limit_point( struct Subdiv *subdiv, const int ptex_face_index, const float u, const float v, float r_P[3]); void BKE_subdiv_eval_limit_point_and_derivatives(struct Subdiv *subdiv, @@ -72,6 +74,7 @@ void BKE_subdiv_eval_limit_point_and_short_normal(struct Subdiv *subdiv, float r_P[3], short r_N[3]); +/* Evaluate face-varying layer (such as UV). */ void BKE_subdiv_eval_face_varying(struct Subdiv *subdiv, const int face_varying_channel, const int ptex_face_index, @@ -93,6 +96,7 @@ void BKE_subdiv_eval_displacement(struct Subdiv *subdiv, const float dPdv[3], float r_D[3]); +/* Evaluate point on a limit surface with displacement applied to it. */ void BKE_subdiv_eval_final_point( struct Subdiv *subdiv, const int ptex_face_index, const float u, const float v, float r_P[3]); diff --git a/source/blender/blenkernel/BKE_subdiv_foreach.h b/source/blender/blenkernel/BKE_subdiv_foreach.h index f1d4adda37c..bef141b5ac5 100644 --- a/source/blender/blenkernel/BKE_subdiv_foreach.h +++ b/source/blender/blenkernel/BKE_subdiv_foreach.h @@ -160,6 +160,10 @@ typedef struct SubdivForeachContext { /* Invokes callbacks in the order and with values which corresponds to creation * of final subdivided mesh. * + * Main goal is to abstract all the traversal routines to give geometry element + * indices (for vertices, edges, loops, polygons) in the same way as subdivision + * modifier will do for a dense mesh. + * * Returns truth if the whole topology was traversed, without any early exits. * * TODO(sergey): Need to either get rid of subdiv or of coarse_mesh. diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h index 0f852bdc64d..fb925565735 100644 --- a/source/blender/blenkernel/BKE_texture.h +++ b/source/blender/blenkernel/BKE_texture.h @@ -39,7 +39,7 @@ struct Tex; struct TexMapping; struct TexResult; -/* in ColorBand struct */ +/** #ColorBand.data length. */ #define MAXCOLORBAND 32 void BKE_texture_default(struct Tex *tex); diff --git a/source/blender/blenkernel/intern/blender_undo.c b/source/blender/blenkernel/intern/blender_undo.c index 99eb4dc9122..ab382d0e8ff 100644 --- a/source/blender/blenkernel/intern/blender_undo.c +++ b/source/blender/blenkernel/intern/blender_undo.c @@ -124,6 +124,9 @@ MemFileUndoData *BKE_memfile_undo_encode(Main *bmain, MemFileUndoData *mfu_prev) } else { MemFile *prevfile = (mfu_prev) ? &(mfu_prev->memfile) : NULL; + if (prevfile) { + BLO_memfile_clear_future(prevfile); + } /* success = */ /* UNUSED */ BLO_write_file_mem(bmain, prevfile, &mfu->memfile, G.fileflags); mfu->undo_size = mfu->memfile.size; } diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index e6045c45dc8..2306b046026 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -1348,6 +1348,9 @@ void BKE_brush_sculpt_reset(Brush *br) br->flag &= ~BRUSH_SPACE_ATTEN; br->spacing = 5; br->alpha = 0.7f; + br->surface_smooth_shape_preservation = 0.5f; + br->surface_smooth_current_vertex = 0.5f; + br->surface_smooth_iterations = 4; break; case SCULPT_TOOL_SNAKE_HOOK: br->alpha = 1.0f; diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 45e2ff10ba4..04adb642fc0 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -472,9 +472,9 @@ static void contarget_get_mesh_mat(Object *ob, const char *substring, float mat[ /* derive the rotation from the average normal: * - code taken from transform_gizmo.c, - * calc_gizmo_stats, V3D_ORIENT_NORMAL case - */ - /* we need the transpose of the inverse for a normal... */ + * calc_gizmo_stats, V3D_ORIENT_NORMAL case */ + + /* We need the transpose of the inverse for a normal. */ copy_m3_m4(imat, ob->obmat); invert_m3_m3(tmat, imat); @@ -577,7 +577,7 @@ static void constraint_target_to_mat4(Object *ob, copy_m4_m4(mat, ob->obmat); BKE_constraint_mat_convertspace(ob, NULL, mat, from, to, false); } - /* Case VERTEXGROUP */ + /* Case VERTEXGROUP */ /* Current method just takes the average location of all the points in the * VertexGroup, and uses that as the location value of the targets. Where * possible, the orientation will also be calculated, by calculating an diff --git a/source/blender/blenkernel/intern/displist_tangent.c b/source/blender/blenkernel/intern/displist_tangent.c index 4ac8d47feba..88fef1a4cfd 100644 --- a/source/blender/blenkernel/intern/displist_tangent.c +++ b/source/blender/blenkernel/intern/displist_tangent.c @@ -144,7 +144,7 @@ static int face_to_vert_index(SGLSLDisplistToTangent *dlt, v += 1; } - /* Cyclic correction. */ + /* Cyclic correction. */ u = u % dlt->dl->nr; v = v % dlt->dl->parts; diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index ae51c997a08..b095e6dbeec 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -36,6 +36,7 @@ #include "DNA_fluid_types.h" #include "DNA_modifier_types.h" #include "DNA_object_types.h" +#include "DNA_rigidbody_types.h" #include "BKE_effect.h" #include "BKE_fluid.h" @@ -497,6 +498,8 @@ static void manta_set_domain_gravity(Scene *scene, FluidDomainSettings *mds) copy_v3_v3(mds->gravity, gravity); } + + mul_v3_fl(mds->gravity, mds->effector_weights->global_gravity); } static bool BKE_fluid_modifier_init( @@ -642,6 +645,11 @@ static bool is_static_object(Object *ob) } } + /* Active rigid body objects considered to be dynamic fluid objects. */ + if (ob->rigidbody_object && ob->rigidbody_object->type == RBO_TYPE_ACTIVE) { + return false; + } + /* Finally, check if the object has animation data. If so, it is considered dynamic. */ return !BKE_object_moves_in_time(ob, true); } @@ -770,7 +778,9 @@ static void bb_combineMaps(FluidObjectBB *output, /* Values. */ output->numobjs[index_out] = bb1.numobjs[index_in]; - output->influence[index_out] = bb1.influence[index_in]; + if (output->influence && bb1.influence) { + output->influence[index_out] = bb1.influence[index_in]; + } output->distances[index_out] = bb1.distances[index_in]; if (output->velocity && bb1.velocity) { copy_v3_v3(&output->velocity[index_out * 3], &bb1.velocity[index_in * 3]); @@ -785,12 +795,14 @@ static void bb_combineMaps(FluidObjectBB *output, /* Values. */ output->numobjs[index_out] = MAX2(bb2->numobjs[index_in], output->numobjs[index_out]); - if (additive) { - output->influence[index_out] += bb2->influence[index_in] * sample_size; - } - else { - output->influence[index_out] = MAX2(bb2->influence[index_in], - output->influence[index_out]); + if (output->influence && bb2->influence) { + if (additive) { + output->influence[index_out] += bb2->influence[index_in] * sample_size; + } + else { + output->influence[index_out] = MAX2(bb2->influence[index_in], + output->influence[index_out]); + } } output->distances[index_out] = MIN2(bb2->distances[index_in], output->distances[index_out]); diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 555b0af5a63..fc7f15348bc 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -1926,6 +1926,9 @@ void BKE_gpencil_visible_stroke_iter( } LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + if (gps->totpoints == 0) { + continue; + } stroke_cb(gpl, gpf, gps, thunk); } } @@ -1939,6 +1942,9 @@ void BKE_gpencil_visible_stroke_iter( } LISTBASE_FOREACH (bGPDstroke *, gps, &act_gpf->strokes) { + if (gps->totpoints == 0) { + continue; + } stroke_cb(gpl, act_gpf, gps, thunk); } } diff --git a/source/blender/blenkernel/intern/gpencil_geom.c b/source/blender/blenkernel/intern/gpencil_geom.c index c4acc871752..6bdcc9cfbcb 100644 --- a/source/blender/blenkernel/intern/gpencil_geom.c +++ b/source/blender/blenkernel/intern/gpencil_geom.c @@ -430,7 +430,7 @@ bool BKE_gpencil_stroke_sample(bGPDstroke *gps, const float dist, const bool sel stroke_interpolate_deform_weights(gps, 0, 0, 0, &new_dv[0]); } - /* the rest */ + /* The rest. */ while ((next_point_index = stroke_march_next_point(gps, next_point_index, last_coord, diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 953b738213a..5dca9bf2ac5 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -578,16 +578,16 @@ ImageTile *BKE_image_get_tile_from_iuser(Image *ima, ImageUser *iuser) int BKE_image_get_tile_from_pos(struct Image *ima, const float uv[2], - float new_uv[2], - float ofs[2]) + float r_uv[2], + float r_ofs[2]) { float local_ofs[2]; - if (ofs == NULL) { - ofs = local_ofs; + if (r_ofs == NULL) { + r_ofs = local_ofs; } - copy_v2_v2(new_uv, uv); - zero_v2(ofs); + copy_v2_v2(r_uv, uv); + zero_v2(r_ofs); if ((ima->source != IMA_SRC_TILED) || uv[0] < 0.0f || uv[1] < 0.0f || uv[0] >= 10.0f) { return 0; @@ -600,9 +600,9 @@ int BKE_image_get_tile_from_pos(struct Image *ima, if (BKE_image_get_tile(ima, tile_number) == NULL) { return 0; } - ofs[0] = ix; - ofs[1] = iy; - sub_v2_v2(new_uv, ofs); + r_ofs[0] = ix; + r_ofs[1] = iy; + sub_v2_v2(r_uv, r_ofs); return tile_number; } @@ -5341,7 +5341,7 @@ bool BKE_image_has_alpha(struct Image *image) } } -void BKE_image_get_size(Image *image, ImageUser *iuser, int *width, int *height) +void BKE_image_get_size(Image *image, ImageUser *iuser, int *r_width, int *r_height) { ImBuf *ibuf = NULL; void *lock; @@ -5351,22 +5351,22 @@ void BKE_image_get_size(Image *image, ImageUser *iuser, int *width, int *height) } if (ibuf && ibuf->x > 0 && ibuf->y > 0) { - *width = ibuf->x; - *height = ibuf->y; + *r_width = ibuf->x; + *r_height = ibuf->y; } else if (image != NULL && image->type == IMA_TYPE_R_RESULT && iuser != NULL && iuser->scene != NULL) { Scene *scene = iuser->scene; - *width = (scene->r.xsch * scene->r.size) / 100; - *height = (scene->r.ysch * scene->r.size) / 100; + *r_width = (scene->r.xsch * scene->r.size) / 100; + *r_height = (scene->r.ysch * scene->r.size) / 100; if ((scene->r.mode & R_BORDER) && (scene->r.mode & R_CROP)) { - *width *= BLI_rctf_size_x(&scene->r.border); - *height *= BLI_rctf_size_y(&scene->r.border); + *r_width *= BLI_rctf_size_x(&scene->r.border); + *r_height *= BLI_rctf_size_y(&scene->r.border); } } else { - *width = IMG_SIZE_FALLBACK; - *height = IMG_SIZE_FALLBACK; + *r_width = IMG_SIZE_FALLBACK; + *r_height = IMG_SIZE_FALLBACK; } if (image != NULL) { @@ -5374,25 +5374,25 @@ void BKE_image_get_size(Image *image, ImageUser *iuser, int *width, int *height) } } -void BKE_image_get_size_fl(Image *image, ImageUser *iuser, float size[2]) +void BKE_image_get_size_fl(Image *image, ImageUser *iuser, float r_size[2]) { int width, height; BKE_image_get_size(image, iuser, &width, &height); - size[0] = (float)width; - size[1] = (float)height; + r_size[0] = (float)width; + r_size[1] = (float)height; } -void BKE_image_get_aspect(Image *image, float *aspx, float *aspy) +void BKE_image_get_aspect(Image *image, float *r_aspx, float *r_aspy) { - *aspx = 1.0; + *r_aspx = 1.0; /* x is always 1 */ if (image) { - *aspy = image->aspy / image->aspx; + *r_aspy = image->aspy / image->aspx; } else { - *aspy = 1.0f; + *r_aspy = 1.0f; } } diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index a6708413f70..e5567a43cd7 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -952,7 +952,7 @@ static void do_key(const int start, k3 = key_block_get_data(key, actkb, k[2], &freek3); k4 = key_block_get_data(key, actkb, k[3], &freek4); - /* test for more or less points (per key!) */ + /* Test for more or less points (per key!) */ if (tot != k[0]->totelem) { k1tot = 0.0; flagflo |= 1; diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index 8b3a46a3eb5..ffa1eecc87b 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -178,27 +178,70 @@ static ViewLayer *view_layer_add(const char *name) return view_layer; } +static void layer_collection_exclude_all(LayerCollection *layer_collection) +{ + LayerCollection *sub_collection = layer_collection->layer_collections.first; + for (; sub_collection != NULL; sub_collection = sub_collection->next) { + sub_collection->flag |= LAYER_COLLECTION_EXCLUDE; + layer_collection_exclude_all(sub_collection); + } +} + /** * Add a new view layer * by default, a view layer has the master collection */ -ViewLayer *BKE_view_layer_add(Scene *scene, const char *name) +ViewLayer *BKE_view_layer_add(Scene *scene, + const char *name, + ViewLayer *view_layer_source, + const int type) { - ViewLayer *view_layer = view_layer_add(name); + ViewLayer *view_layer_new; + + if (view_layer_source) { + name = view_layer_source->name; + } + + switch (type) { + default: + case VIEWLAYER_ADD_NEW: { + view_layer_new = view_layer_add(name); + BLI_addtail(&scene->view_layers, view_layer_new); + BKE_layer_collection_sync(scene, view_layer_new); + break; + } + case VIEWLAYER_ADD_COPY: { + /* Allocate and copy view layer data */ + view_layer_new = MEM_callocN(sizeof(ViewLayer), "View Layer"); + BLI_addtail(&scene->view_layers, view_layer_new); + BKE_view_layer_copy_data(scene, scene, view_layer_new, view_layer_source, 0); + + BLI_strncpy_utf8(view_layer_new->name, name, sizeof(view_layer_new->name)); + break; + } + case VIEWLAYER_ADD_EMPTY: { + view_layer_new = view_layer_add(name); + BLI_addtail(&scene->view_layers, view_layer_new); - BLI_addtail(&scene->view_layers, view_layer); + /* Initialise layercollections */ + BKE_layer_collection_sync(scene, view_layer_new); + layer_collection_exclude_all(view_layer_new->layer_collections.first); + + /* Update collections after changing visibility */ + BKE_layer_collection_sync(scene, view_layer_new); + break; + } + } /* unique name */ BLI_uniquename(&scene->view_layers, - view_layer, + view_layer_new, DATA_("ViewLayer"), '.', offsetof(ViewLayer, name), - sizeof(view_layer->name)); - - BKE_layer_collection_sync(scene, view_layer); + sizeof(view_layer_new->name)); - return view_layer; + return view_layer_new; } void BKE_view_layer_free(ViewLayer *view_layer) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index aafbcf0d360..6c835dc5fb2 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -38,10 +38,6 @@ #include "BLT_translation.h" #include "DNA_mask_types.h" -#include "DNA_node_types.h" -#include "DNA_screen_types.h" -#include "DNA_sequence_types.h" -#include "DNA_space_types.h" #include "BKE_animsys.h" #include "BKE_curve.h" @@ -52,8 +48,6 @@ #include "BKE_main.h" #include "BKE_mask.h" #include "BKE_movieclip.h" -#include "BKE_node.h" -#include "BKE_sequencer.h" #include "BKE_tracking.h" #include "DEG_depsgraph_build.h" @@ -508,9 +502,9 @@ float BKE_mask_spline_project_co(MaskSpline *spline, /* point */ -eMaskhandleMode BKE_mask_point_handles_mode_get(MaskSplinePoint *point) +eMaskhandleMode BKE_mask_point_handles_mode_get(const MaskSplinePoint *point) { - BezTriple *bezt = &point->bezt; + const BezTriple *bezt = &point->bezt; if (bezt->h1 == bezt->h2 && bezt->h1 == HD_ALIGN) { return MASK_HANDLE_MODE_STICK; @@ -519,23 +513,25 @@ eMaskhandleMode BKE_mask_point_handles_mode_get(MaskSplinePoint *point) return MASK_HANDLE_MODE_INDIVIDUAL_HANDLES; } -void BKE_mask_point_handle(MaskSplinePoint *point, eMaskWhichHandle which_handle, float handle[2]) +void BKE_mask_point_handle(const MaskSplinePoint *point, + eMaskWhichHandle which_handle, + float r_handle[2]) { - BezTriple *bezt = &point->bezt; + const BezTriple *bezt = &point->bezt; if (which_handle == MASK_WHICH_HANDLE_STICK) { float vec[2]; sub_v2_v2v2(vec, bezt->vec[0], bezt->vec[1]); - handle[0] = (bezt->vec[1][0] + vec[1]); - handle[1] = (bezt->vec[1][1] - vec[0]); + r_handle[0] = (bezt->vec[1][0] + vec[1]); + r_handle[1] = (bezt->vec[1][1] - vec[0]); } else if (which_handle == MASK_WHICH_HANDLE_LEFT) { - copy_v2_v2(handle, bezt->vec[0]); + copy_v2_v2(r_handle, bezt->vec[0]); } else if (which_handle == MASK_WHICH_HANDLE_RIGHT) { - copy_v2_v2(handle, bezt->vec[2]); + copy_v2_v2(r_handle, bezt->vec[2]); } else { BLI_assert(!"Unknown handle passed to BKE_mask_point_handle"); diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 31fe93f64ed..16ec4c0a313 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -171,7 +171,6 @@ void BKE_gpencil_material_attr_init(Material *ma) gp_style->fill_rgba[3] = 1.0f; ARRAY_SET_ITEMS(gp_style->mix_rgba, 1.0f, 1.0f, 1.0f, 0.2f); ARRAY_SET_ITEMS(gp_style->texture_scale, 1.0f, 1.0f); - gp_style->texture_opacity = 1.0f; gp_style->texture_pixsize = 100.0f; gp_style->flag |= GP_MATERIAL_STROKE_SHOW; diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c index 955f1aca110..74b79490d67 100644 --- a/source/blender/blenkernel/intern/mesh_convert.c +++ b/source/blender/blenkernel/intern/mesh_convert.c @@ -1304,7 +1304,7 @@ Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph, const ModifierTypeInfo *mti = modifierType_getInfo(md_eval->type); Mesh *result; KeyBlock *kb; - ModifierEvalContext mectx = {depsgraph, ob_eval, 0}; + ModifierEvalContext mectx = {depsgraph, ob_eval, MOD_APPLY_TO_BASE_MESH}; if (!(md_eval->mode & eModifierMode_Realtime)) { return NULL; diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index b40dfcd3b7f..6ccfabcb5d2 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -308,6 +308,7 @@ float (*BKE_multires_create_deformed_base_mesh_vert_coords(struct Depsgraph *dep Object object_for_eval = *object_eval; object_for_eval.data = object->data; + object_for_eval.sculpt = NULL; const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); ModifierEvalContext mesh_eval_context = {depsgraph, &object_for_eval, 0}; diff --git a/source/blender/blenkernel/intern/multires_reshape_vertcos.c b/source/blender/blenkernel/intern/multires_reshape_vertcos.c index 5aff0b3caa2..1ece7344f37 100644 --- a/source/blender/blenkernel/intern/multires_reshape_vertcos.c +++ b/source/blender/blenkernel/intern/multires_reshape_vertcos.c @@ -182,8 +182,7 @@ static void multires_reshape_vertcos_foreach_vertex_every_edge( multires_reshape_vertcos_foreach_vertex(foreach_context, &ptex_coord, subdiv_vertex_index); } -/* Set displacement grids values at a reshape level to a object coordinates of the the given - * source. */ +/* Set displacement grids values at a reshape level to a object coordinates of the given source. */ bool multires_reshape_assign_final_coords_from_vertcos( const MultiresReshapeContext *reshape_context, const float (*vert_coords)[3], diff --git a/source/blender/blenkernel/intern/multires_subdiv.c b/source/blender/blenkernel/intern/multires_subdiv.c index 2ea02ab6974..f7e42942f3e 100644 --- a/source/blender/blenkernel/intern/multires_subdiv.c +++ b/source/blender/blenkernel/intern/multires_subdiv.c @@ -50,9 +50,11 @@ void BKE_multires_subdiv_mesh_settings_init(SubdivToMeshSettings *mesh_settings, const Object *object, const MultiresModifierData *mmd, const bool use_render_params, - const bool ignore_simplify) + const bool ignore_simplify, + const bool ignore_control_edges) { const int level = multires_get_level(scene, object, mmd, use_render_params, ignore_simplify); mesh_settings->resolution = (1 << level) + 1; - mesh_settings->use_optimal_display = (mmd->flags & eMultiresModifierFlag_ControlEdges); + mesh_settings->use_optimal_display = (mmd->flags & eMultiresModifierFlag_ControlEdges) && + !ignore_control_edges; } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 23bd7ae3c8c..b12402d74fc 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -211,7 +211,7 @@ static void scene_init_data(ID *id) /* Master Collection */ scene->master_collection = BKE_collection_master_add(); - BKE_view_layer_add(scene, "View Layer"); + BKE_view_layer_add(scene, "View Layer", NULL, VIEWLAYER_ADD_NEW); } static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag) diff --git a/source/blender/blenkernel/intern/seqcache.c b/source/blender/blenkernel/intern/seqcache.c index d48930e5665..a2c0434a474 100644 --- a/source/blender/blenkernel/intern/seqcache.c +++ b/source/blender/blenkernel/intern/seqcache.c @@ -1401,24 +1401,11 @@ void BKE_sequencer_cache_put(const SeqRenderData *context, } } -size_t BKE_sequencer_cache_get_num_items(struct Scene *scene) -{ - SeqCache *cache = seq_cache_get_from_scene(scene); - if (!cache) { - return 0; - } - - seq_cache_lock(scene); - size_t num_items = BLI_ghash_len(cache->hash); - seq_cache_unlock(scene); - - return num_items; -} - void BKE_sequencer_cache_iterate( struct Scene *scene, void *userdata, - bool callback(void *userdata, struct Sequence *seq, int nfra, int cache_type, float cost)) + bool callback_init(void *userdata, size_t item_count), + bool callback_iter(void *userdata, struct Sequence *seq, int nfra, int cache_type, float cost)) { SeqCache *cache = seq_cache_get_from_scene(scene); if (!cache) { @@ -1426,15 +1413,16 @@ void BKE_sequencer_cache_iterate( } seq_cache_lock(scene); + bool interrupt = callback_init(userdata, BLI_ghash_len(cache->hash)); + GHashIterator gh_iter; BLI_ghashIterator_init(&gh_iter, cache->hash); - bool interrupt = false; while (!BLI_ghashIterator_done(&gh_iter) && !interrupt) { SeqCacheKey *key = BLI_ghashIterator_getKey(&gh_iter); BLI_ghashIterator_step(&gh_iter); - interrupt = callback(userdata, key->seq, key->nfra, key->type, key->cost); + interrupt = callback_iter(userdata, key->seq, key->nfra, key->type, key->cost); } cache->last_key = NULL; diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 70f92c6d6bd..7c34b676e69 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -2499,15 +2499,14 @@ static ImBuf *do_transform_effect(const SeqRenderData *context, /*********************** Glow *************************/ static void RVBlurBitmap2_float(float *map, int width, int height, float blur, int quality) -/* MUUUCCH better than the previous blur. */ -/* We do the blurring in two passes which is a whole lot faster. */ -/* I changed the math around to implement an actual Gaussian */ -/* distribution. */ -/* */ -/* Watch out though, it tends to misbehaven with large blur values on */ -/* a small bitmap. Avoid avoid avoid. */ -/*=============================== */ { + /* Much better than the previous blur! + * We do the blurring in two passes which is a whole lot faster. + * I changed the math around to implement an actual Gaussian distribution. + * + * Watch out though, it tends to misbehave with large blur values on + * a small bitmap. Avoid avoid! */ + float *temp = NULL, *swap; float *filter = NULL; int x, y, i, fx, fy; diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 3bb95eaeff0..97a643e88b6 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -550,12 +550,12 @@ void BKE_sound_destroy_scene(Scene *scene) } } -void BKE_sound_lock_scene(struct Scene *scene) +void BKE_sound_lock() { AUD_Device_lock(sound_device); } -void BKE_sound_unlock_scene(struct Scene *scene) +void BKE_sound_unlock() { AUD_Device_unlock(sound_device); } @@ -1161,10 +1161,10 @@ void BKE_sound_create_scene(Scene *UNUSED(scene)) void BKE_sound_destroy_scene(Scene *UNUSED(scene)) { } -void BKE_sound_lock_scene(Scene *UNUSED(scene)) +void BKE_sound_lock(void) { } -void BKE_sound_unlock_scene(Scene *UNUSED(scene)) +void BKE_sound_unlock(void) { } void BKE_sound_reset_scene_specs(Scene *UNUSED(scene)) diff --git a/source/blender/blenkernel/intern/subdiv_foreach.c b/source/blender/blenkernel/intern/subdiv_foreach.c index 533279f4425..6e39f9f302b 100644 --- a/source/blender/blenkernel/intern/subdiv_foreach.c +++ b/source/blender/blenkernel/intern/subdiv_foreach.c @@ -1875,6 +1875,13 @@ bool BKE_subdiv_foreach_subdiv_geometry(Subdiv *subdiv, if (context->user_data_tls_free != NULL) { parallel_range_settings.func_finalize = subdiv_foreach_finalize; } + + /* TODO(sergey): Possible optimization is to have a single pool and push all + * the tasks into it. + * NOTE: Watch out for callbacks which needs to run for loose geometry as they + * currently are relying on the fact that face/grid callbacks will tag non- + * loose geomtry. */ + BLI_task_parallel_range( 0, coarse_mesh->totpoly, &ctx, subdiv_foreach_task, ¶llel_range_settings); if (context->vertex_loose != NULL) { diff --git a/source/blender/blenkernel/intern/subdiv_mesh.c b/source/blender/blenkernel/intern/subdiv_mesh.c index 0bd6fc259c6..cdb766f2507 100644 --- a/source/blender/blenkernel/intern/subdiv_mesh.c +++ b/source/blender/blenkernel/intern/subdiv_mesh.c @@ -1120,8 +1120,11 @@ static void subdiv_mesh_vertex_of_loose_edge(const struct SubdivForeachContext * * it. Maybe even using vertex varying attributes. */ subdiv_vertex->bweight = 0.0f; /* Reset normal, initialize it in a similar way as edit mode does for a - * vertices adjacent to a loose edges. */ - normal_float_to_short_v3(subdiv_vertex->no, subdiv_vertex->co); + * vertices adjacent to a loose edges. + * See `mesh_evaluate#mesh_calc_normals_vert_fallback` */ + float no[3]; + normalize_v3_v3(no, subdiv_vertex->co); + normal_float_to_short_v3(subdiv_vertex->no, no); } /* ============================================================================= diff --git a/source/blender/blenkernel/intern/tracking_region_tracker.c b/source/blender/blenkernel/intern/tracking_region_tracker.c index 6e8d4146d12..7e37e438e24 100644 --- a/source/blender/blenkernel/intern/tracking_region_tracker.c +++ b/source/blender/blenkernel/intern/tracking_region_tracker.c @@ -75,8 +75,8 @@ static void uint8_rgba_to_float_gray(const unsigned char *rgba, static float *track_get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, - int *width_r, - int *height_r) + int *r_width, + int *r_height) { ImBuf *searchibuf; float *gray_pixels; @@ -85,8 +85,8 @@ static float *track_get_search_floatbuf(ImBuf *ibuf, searchibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, false, true); if (!searchibuf) { - *width_r = 0; - *height_r = 0; + *r_width = 0; + *r_height = 0; return NULL; } @@ -106,8 +106,8 @@ static float *track_get_search_floatbuf(ImBuf *ibuf, IMB_freeImBuf(searchibuf); - *width_r = width; - *height_r = height; + *r_width = width; + *r_height = height; return gray_pixels; } @@ -138,7 +138,7 @@ static ImBuf *tracking_context_get_keyframed_ibuf(MovieClip *clip, MovieTrackingTrack *track, int curfra, bool backwards, - MovieTrackingMarker **marker_keyed_r) + MovieTrackingMarker **r_marker_keyed) { MovieTrackingMarker *marker_keyed; int keyed_framenr; @@ -150,7 +150,7 @@ static ImBuf *tracking_context_get_keyframed_ibuf(MovieClip *clip, keyed_framenr = marker_keyed->framenr; - *marker_keyed_r = marker_keyed; + *r_marker_keyed = marker_keyed; return tracking_context_get_frame_ibuf(clip, user, clip_flag, keyed_framenr); } diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c index 6d484a7b702..b111dee80ad 100644 --- a/source/blender/blenkernel/intern/undo_system.c +++ b/source/blender/blenkernel/intern/undo_system.c @@ -464,12 +464,12 @@ UndoStep *BKE_undosys_step_push_init_with_type(UndoStack *ustack, } UndoStep *us = MEM_callocN(ut->step_size, __func__); - CLOG_INFO(&LOG, 1, "addr=%p, name='%s', type='%s'", us, name, ut->name); if (name != NULL) { BLI_strncpy(us->name, name, sizeof(us->name)); } us->type = ut; ustack->step_init = us; + CLOG_INFO(&LOG, 1, "addr=%p, name='%s', type='%s'", us, us->name, us->type->name); ut->step_encode_init(C, us); undosys_stack_validate(ustack, false); return us; @@ -552,6 +552,8 @@ bool BKE_undosys_step_push_with_type(UndoStack *ustack, us->type = ut; /* Initialized, not added yet. */ + CLOG_INFO(&LOG, 1, "addr=%p, name='%s', type='%s'", us, us->name, us->type->name); + if (!undosys_step_encode(C, G_MAIN, ustack, us)) { MEM_freeN(us); undosys_stack_validate(ustack, true); diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc index c568cb66cc5..6e00a942283 100644 --- a/source/blender/blenkernel/intern/volume.cc +++ b/source/blender/blenkernel/intern/volume.cc @@ -856,7 +856,7 @@ void BKE_volume_grids_backup_restore(Volume *volume, VolumeGridVector *grids, co volume->runtime.grids = grids; } #else - UNUSED_VARS(volume, grids); + UNUSED_VARS(volume, grids, filepath); #endif } @@ -967,7 +967,7 @@ void BKE_volume_grid_unload(const Volume *volume, VolumeGrid *grid) const char *volume_name = volume->id.name + 2; grid->unload(volume_name); #else - UNUSED_VARS(grid); + UNUSED_VARS(volume, grid); #endif } diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h index 89f7d01ffd6..4eb6f184a76 100644 --- a/source/blender/blenlib/BLI_fileops.h +++ b/source/blender/blenlib/BLI_fileops.h @@ -147,6 +147,7 @@ int BLI_access(const char *filename, int mode) ATTR_WARN_UNUSED_RESULT ATTR_NONN bool BLI_file_is_writable(const char *file) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); bool BLI_file_touch(const char *file) ATTR_NONNULL(); +bool BLI_file_alias_target(char *target, const char *filepath); #if 0 /* UNUSED */ int BLI_file_gzip(const char *from, const char *to) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); diff --git a/source/blender/blenlib/BLI_voronoi_2d.h b/source/blender/blenlib/BLI_voronoi_2d.h index 947b120f51a..a48f32c283a 100644 --- a/source/blender/blenlib/BLI_voronoi_2d.h +++ b/source/blender/blenlib/BLI_voronoi_2d.h @@ -73,10 +73,10 @@ void BLI_voronoi_triangulate(const VoronoiSite *sites, struct ListBase *edges, int width, int height, - VoronoiTriangulationPoint **triangulated_points_r, - int *triangulated_points_total_r, - int (**triangles_r)[3], - int *triangles_total_r); + VoronoiTriangulationPoint **r_triangulated_points, + int *r_triangulated_points_total, + int (**r_triangles)[3], + int *r_triangles_total); #ifdef __cplusplus } diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 1de0c192a20..5f5145cab70 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -277,6 +277,13 @@ if(WIN32) ) endif() + +if(APPLE) + list(APPEND SRC + intern/storage_apple.mm + ) +endif() + if(UNIX AND NOT APPLE) list(APPEND LIB bf_intern_libc_compat diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index da80777e6d6..7274a15661a 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -226,11 +226,12 @@ size_t BLI_file_size(const char *path) return stats.st_size; } +#ifndef __APPLE__ eFileAttributes BLI_file_attributes(const char *path) { int ret = 0; -#ifdef WIN32 +# ifdef WIN32 wchar_t wline[FILE_MAXDIR]; BLI_strncpy_wchar_from_utf8(wline, path, ARRAY_SIZE(wline)); DWORD attr = GetFileAttributesW(wline); @@ -265,19 +266,9 @@ eFileAttributes BLI_file_attributes(const char *path) ret |= FILE_ATTR_REPARSE_POINT; } -#endif - -#ifdef __APPLE__ - - /* TODO: - * If Hidden (Invisible) set FILE_ATTR_HIDDEN - * If Locked set FILE_ATTR_READONLY - * If Restricted set FILE_ATTR_RESTRICTED - */ - -#endif +# endif -#ifdef __linux__ +# ifdef __linux__ UNUSED_VARS(path); /* TODO: @@ -285,10 +276,23 @@ eFileAttributes BLI_file_attributes(const char *path) * If Archived set FILE_ATTR_ARCHIVE */ -#endif +# endif return ret; } +#endif + +/** + * Returns the target path of a file-based redirection, like Mac Alias or Win32 Shortcut file. + */ +#ifndef __APPLE__ +bool BLI_file_alias_target(char UNUSED(target[FILE_MAXDIR]), const char *UNUSED(filepath)) +{ + /* TODO: Find target in Win32 Shortcut - Shell Link (.lnk) file. + * Format: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-shllink/ */ + return false; +} +#endif /** * Returns the st_mode from stat-ing the specified path name, or 0 if stat fails diff --git a/source/blender/blenlib/intern/storage_apple.mm b/source/blender/blenlib/intern/storage_apple.mm new file mode 100644 index 00000000000..0cc246b8d4f --- /dev/null +++ b/source/blender/blenlib/intern/storage_apple.mm @@ -0,0 +1,96 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup bli + * + * macOS specific implementations for storage.c. + */ + +#import <Foundation/Foundation.h> + +#include "BLI_fileops.h" +#include "BLI_path_util.h" + +bool BLI_file_alias_target(char targetpath[FILE_MAXDIR], const char *filepath) +{ + @autoreleasepool { + NSError *error = nil; + NSURL *shortcutURL = [[NSURL alloc] initFileURLWithFileSystemRepresentation:filepath + isDirectory:NO + relativeToURL:nil]; + NSURL *targetURL = [NSURL URLByResolvingAliasFileAtURL:shortcutURL + options:NSURLBookmarkResolutionWithoutUI + error:&error]; + BOOL isSame = [shortcutURL isEqual:targetURL] and + ([[[shortcutURL path] stringByStandardizingPath] + isEqualToString:[[targetURL path] stringByStandardizingPath]]); + + if (targetURL == nil) { + return false; + } + else if (isSame) { + [targetURL getFileSystemRepresentation:targetpath maxLength:FILE_MAXDIR]; + return false; + } + else if (![targetURL getFileSystemRepresentation:targetpath maxLength:FILE_MAXDIR]) { + return false; + } + + NSNumber *targetIsDirectory = 0; + [targetURL getResourceValue:&targetIsDirectory forKey:NSURLIsDirectoryKey error:nil]; + } + + return true; +} + +eFileAttributes BLI_file_attributes(const char *path) +{ + int ret = 0; + + @autoreleasepool { + NSURL *fileURL = [[NSURL alloc] initFileURLWithFileSystemRepresentation:path + isDirectory:NO + relativeToURL:nil]; + NSArray *resourceKeys = + @[ NSURLIsAliasFileKey, NSURLIsHiddenKey, NSURLIsReadableKey, NSURLIsWritableKey ]; + + NSDictionary *resourceKeyValues = [fileURL resourceValuesForKeys:resourceKeys error:nil]; + + const bool is_alias = [resourceKeyValues[(void)(@"@%"), NSURLIsAliasFileKey] boolValue]; + const bool is_hidden = [resourceKeyValues[(void)(@"@%"), NSURLIsHiddenKey] boolValue]; + const bool is_readable = [resourceKeyValues[(void)(@"@%"), NSURLIsReadableKey] boolValue]; + const bool is_writable = [resourceKeyValues[(void)(@"@%"), NSURLIsWritableKey] boolValue]; + + if (is_alias) { + ret |= FILE_ATTR_ALIAS; + } + if (is_hidden) { + ret |= FILE_ATTR_HIDDEN; + } + if (is_readable && !is_writable) { + ret |= FILE_ATTR_READONLY; + } + if (!is_readable) { + ret |= FILE_ATTR_SYSTEM; + } + } + + return (eFileAttributes)ret; +} diff --git a/source/blender/blenlib/intern/voronoi_2d.c b/source/blender/blenlib/intern/voronoi_2d.c index 61052aa00f9..59270c58341 100644 --- a/source/blender/blenlib/intern/voronoi_2d.c +++ b/source/blender/blenlib/intern/voronoi_2d.c @@ -792,10 +792,10 @@ void BLI_voronoi_triangulate(const VoronoiSite *sites, ListBase *edges, int width, int height, - VoronoiTriangulationPoint **triangulated_points_r, - int *triangulated_points_total_r, - int (**triangles_r)[3], - int *triangles_total_r) + VoronoiTriangulationPoint **r_triangulated_points, + int *r_triangulated_points_total, + int (**r_triangles)[3], + int *r_triangles_total) { VoronoiTriangulationPoint *triangulated_points = NULL; int(*triangles)[3] = NULL; @@ -853,11 +853,11 @@ void BLI_voronoi_triangulate(const VoronoiSite *sites, mul_v3_fl(triangulation_point->color, 1.0f / triangulation_point->power); } - *triangulated_points_r = triangulated_points; - *triangulated_points_total_r = triangulated_points_total; + *r_triangulated_points = triangulated_points; + *r_triangulated_points_total = triangulated_points_total; - *triangles_r = triangles; - *triangles_total_r = triangles_total; + *r_triangles = triangles; + *r_triangles_total = triangles_total; BLI_freelistN(&boundary_edges); } diff --git a/source/blender/blenloader/BLO_undofile.h b/source/blender/blenloader/BLO_undofile.h index 5f1142cc20e..f280b8f3b9c 100644 --- a/source/blender/blenloader/BLO_undofile.h +++ b/source/blender/blenloader/BLO_undofile.h @@ -60,6 +60,7 @@ extern void memfile_chunk_add(MemFile *memfile, /* exports */ extern void BLO_memfile_free(MemFile *memfile); extern void BLO_memfile_merge(MemFile *first, MemFile *second); +extern void BLO_memfile_clear_future(MemFile *memfile); /* utilities */ extern struct Main *BLO_memfile_main_get(struct MemFile *memfile, diff --git a/source/blender/blenloader/intern/undofile.c b/source/blender/blenloader/intern/undofile.c index 06469a0c087..69c4ba2b1f2 100644 --- a/source/blender/blenloader/intern/undofile.c +++ b/source/blender/blenloader/intern/undofile.c @@ -92,6 +92,14 @@ void BLO_memfile_merge(MemFile *first, MemFile *second) BLO_memfile_free(first); } +/* Clear is_identical_future before adding next memfile. */ +void BLO_memfile_clear_future(MemFile *memfile) +{ + for (MemFileChunk *chunk = memfile->chunks.first; chunk; chunk = chunk->next) { + chunk->is_identical_future = false; + } +} + void memfile_chunk_add(MemFile *memfile, const char *buf, uint size, MemFileChunk **compchunk_step) { MemFileChunk *curchunk = MEM_mallocN(sizeof(MemFileChunk), "MemFileChunk"); diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index a7c9c073018..50b1e385dd4 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -462,7 +462,7 @@ static void do_version_layers_to_collections(Main *bmain, Scene *scene) const bool need_default_renderlayer = scene->r.layers.first == NULL; for (SceneRenderLayer *srl = scene->r.layers.first; srl; srl = srl->next) { - ViewLayer *view_layer = BKE_view_layer_add(scene, srl->name); + ViewLayer *view_layer = BKE_view_layer_add(scene, srl->name, NULL, VIEWLAYER_ADD_NEW); if (srl->layflag & SCE_LAY_DISABLE) { view_layer->flag &= ~VIEW_LAYER_RENDER; @@ -528,7 +528,7 @@ static void do_version_layers_to_collections(Main *bmain, Scene *scene) /* If render layers included overrides, or there are no render layers, * we also create a vanilla viewport layer. */ if (have_override || need_default_renderlayer) { - ViewLayer *view_layer = BKE_view_layer_add(scene, "Viewport"); + ViewLayer *view_layer = BKE_view_layer_add(scene, "Viewport", NULL, VIEWLAYER_ADD_NEW); /* If we ported all the original render layers, * we don't need to make the viewport layer renderable. */ @@ -4852,6 +4852,18 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) wm->xr.session_settings.flag = XR_SESSION_USE_POSITION_TRACKING; } } + + /* Surface deform modifier strength*/ + if (!DNA_struct_elem_find(fd->filesdna, "SurfaceDeformModifierData", "float", "strength")) { + for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) { + for (ModifierData *md = ob->modifiers.first; md; md = md->next) { + if (md->type == eModifierType_SurfaceDeform) { + SurfaceDeformModifierData *sdmd = (SurfaceDeformModifierData *)md; + sdmd->strength = 1.0f; + } + } + } + } } /** diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index 045edc8413f..80395177100 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -582,6 +582,14 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) brush->sculpt_tool = SCULPT_TOOL_SIMPLIFY; } + brush_name = "Draw Face Sets"; + brush = BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2); + if (!brush) { + brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT); + id_us_min(&brush->id); + brush->sculpt_tool = SCULPT_TOOL_DRAW_FACE_SETS; + } + /* Use the same tool icon color in the brush cursor */ for (brush = bmain->brushes.first; brush; brush = brush->id.next) { if (brush->ob_mode & OB_MODE_SCULPT) { diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 07ff55703d9..3bdca9ca054 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -735,11 +735,6 @@ static void write_iddata(WriteData *wd, ID *id) } } } - - /* Clear the accumulated recalc flags in case of undo step saving. */ - if (wd->use_memfile) { - id->recalc_undo_accumulated = 0; - } } static void write_previews(WriteData *wd, const PreviewImage *prv_orig) @@ -2214,6 +2209,7 @@ static void write_mesh(WriteData *wd, Mesh *mesh) mesh->mface = NULL; mesh->totface = 0; memset(&mesh->fdata, 0, sizeof(mesh->fdata)); + memset(&mesh->runtime, 0, sizeof(mesh->runtime)); /* Reduce xdata layers, fill xlayers with layers to be written. * This makes xdata invalid for Blender, which is why we made a @@ -4158,6 +4154,9 @@ static bool write_file_handle(Main *mainvar, /* Very important to do it after every ID write now, otherwise we cannot know whether a * specific ID changed or not. */ mywrite_flush(wd); + + /* Clear the accumulated recalc flags in case of undo step saving. */ + id->recalc_undo_accumulated = 0; } } diff --git a/source/blender/bmesh/operators/bmo_fill_grid.c b/source/blender/bmesh/operators/bmo_fill_grid.c index adc612cfb54..6986655c6de 100644 --- a/source/blender/bmesh/operators/bmo_fill_grid.c +++ b/source/blender/bmesh/operators/bmo_fill_grid.c @@ -616,7 +616,14 @@ void bmo_grid_fill_exec(BMesh *bm, BMOperator *op) count = BM_mesh_edgeloops_find(bm, &eloops, bm_edge_test_cb, (void *)bm); if (count != 2) { - BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Select two edge loops"); + /* Note that this error message has been adjusted to make sense when called + * from the operator 'MESH_OT_fill_grid' which has a 'prepare' pass which can + * extract two 'rail' loops from a single edge loop, see T72075. */ + BMO_error_raise(bm, + op, + BMERR_INVALID_SELECTION, + "Select two edge loops " + "or a single closed edge loop from which two edge loops can be calculated"); goto cleanup; } diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc index e141925725b..c3733cb235c 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc @@ -32,7 +32,7 @@ namespace DEG { RuntimeBackup::RuntimeBackup(const Depsgraph *depsgraph) - : have_backup(nullptr), + : have_backup(false), animation_backup(depsgraph), scene_backup(depsgraph), sound_backup(depsgraph), diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.cc index 36d0138f697..32b2d0b93c1 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.cc @@ -46,7 +46,7 @@ void SceneBackup::reset() void SceneBackup::init_from_scene(Scene *scene) { - BKE_sound_lock_scene(scene); + BKE_sound_lock(); sound_scene = scene->sound_scene; playback_handle = scene->playback_handle; @@ -80,7 +80,7 @@ void SceneBackup::restore_to_scene(Scene *scene) sequencer_backup.restore_to_scene(scene); - BKE_sound_unlock_scene(scene); + BKE_sound_unlock(); reset(); } diff --git a/source/blender/draw/engines/eevee/eevee_bloom.c b/source/blender/draw/engines/eevee/eevee_bloom.c index 6545a1bca84..8fd953478d5 100644 --- a/source/blender/draw/engines/eevee/eevee_bloom.c +++ b/source/blender/draw/engines/eevee/eevee_bloom.c @@ -323,8 +323,8 @@ void EEVEE_bloom_draw(EEVEE_Data *vedata) /* Upsample and accumulate */ for (int i = effects->bloom_iteration_len - 2; i >= 0; i--) { copy_v2_v2(effects->unf_source_texel_size, effects->downsamp_texel_size[i]); - effects->unf_source_buffer = effects->bloom_downsample[i]; - effects->unf_base_buffer = last; + effects->unf_source_buffer = last; + effects->unf_base_buffer = effects->bloom_downsample[i]; GPU_framebuffer_bind(fbl->bloom_accum_fb[i]); DRW_draw_pass(psl->bloom_upsample); diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index 2062f4d83c9..4a1f0a081b2 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -134,7 +134,8 @@ extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; render_pass_index_ += 1; \ } \ } \ - } + } \ + ((void)0) /* *********** FUNCTIONS *********** */ @@ -939,6 +940,45 @@ struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene, return mat; } +static struct GPUMaterial *EEVEE_material_hair_depth_get(struct Scene *scene, + Material *ma, + bool use_hashed_alpha, + bool is_shadow) +{ + const void *engine = &DRW_engine_viewport_eevee_type; + int options = VAR_MAT_MESH | VAR_MAT_HAIR; + + SET_FLAG_FROM_TEST(options, use_hashed_alpha, VAR_MAT_HASH); + SET_FLAG_FROM_TEST(options, !use_hashed_alpha, VAR_MAT_CLIP); + SET_FLAG_FROM_TEST(options, is_shadow, VAR_MAT_SHADOW); + + GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true); + if (mat) { + return mat; + } + + char *defines = eevee_get_defines(options); + + char *frag_str = BLI_string_joinN(e_data.frag_shader_lib, datatoc_prepass_frag_glsl); + + mat = DRW_shader_create_from_material(scene, + ma, + engine, + options, + false, + (is_shadow) ? e_data.vert_shadow_shader_str : + e_data.vert_shader_str, + NULL, + frag_str, + defines, + false); + + MEM_freeN(frag_str); + MEM_freeN(defines); + + return mat; +} + struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma) { const void *engine = &DRW_engine_viewport_eevee_type; @@ -1523,21 +1563,22 @@ static void material_opaque(Material *ma, } } - RENDER_PASS_ITER_BEGIN(stl->g_data->render_passes, render_pass_index, render_pass_flag) - emsg->material_accum_grp[render_pass_index] = DRW_shgroup_material_create( - *gpumat, psl->material_accum_pass[render_pass_index]); - add_standard_uniforms(emsg->material_accum_grp[render_pass_index], - sldata, - vedata, - ssr_id, - &ma->refract_depth, - use_diffuse, - use_glossy, - use_refract, - use_ssrefract, - false, - render_pass_flag); - RENDER_PASS_ITER_END(render_pass_index) + RENDER_PASS_ITER_BEGIN (stl->g_data->render_passes, render_pass_index, render_pass_flag) { + emsg->material_accum_grp[render_pass_index] = DRW_shgroup_material_create( + *gpumat, psl->material_accum_pass[render_pass_index]); + add_standard_uniforms(emsg->material_accum_grp[render_pass_index], + sldata, + vedata, + ssr_id, + &ma->refract_depth, + use_diffuse, + use_glossy, + use_refract, + use_ssrefract, + false, + render_pass_flag); + } + RENDER_PASS_ITER_END(render_pass_index); break; } @@ -1566,21 +1607,22 @@ static void material_opaque(Material *ma, DRW_shgroup_uniform_float(emsg->shading_grp, "specular", spec_p, 1); DRW_shgroup_uniform_float(emsg->shading_grp, "roughness", rough_p, 1); - RENDER_PASS_ITER_BEGIN(stl->g_data->render_passes, render_pass_index, render_pass_flag) - DRWShadingGroup *shgrp = EEVEE_default_render_pass_shading_group_get( - sldata, - vedata, - holdout, - use_ssr, - psl->material_accum_pass[render_pass_index], - render_pass_flag); - - DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1); - DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1); - DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1); - DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1); - emsg->material_accum_grp[render_pass_index] = shgrp; - RENDER_PASS_ITER_END(render_pass_index) + RENDER_PASS_ITER_BEGIN (stl->g_data->render_passes, render_pass_index, render_pass_flag) { + DRWShadingGroup *shgrp = EEVEE_default_render_pass_shading_group_get( + sldata, + vedata, + holdout, + use_ssr, + psl->material_accum_pass[render_pass_index], + render_pass_flag); + + DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1); + DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1); + DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1); + DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1); + emsg->material_accum_grp[render_pass_index] = shgrp; + } + RENDER_PASS_ITER_END(render_pass_index); } /* Fallback default depth prepass */ @@ -1741,31 +1783,92 @@ static void eevee_hair_cache_populate(EEVEE_Data *vedata, DRWShadingGroup *shgrp = NULL; Material *ma = eevee_object_material_get(ob, matnr - 1); + const bool holdout = (ob->base_flag & BASE_HOLDOUT) != 0; + const bool use_gpumat = ma->use_nodes && ma->nodetree && !holdout; + const bool use_alpha_hash = (ma->blend_method == MA_BM_HASHED); + const bool use_alpha_clip = (ma->blend_method == MA_BM_CLIP); + const bool use_ssr = ((stl->effects->enabled_effects & EFFECT_SSR) != 0); + + GPUMaterial *gpumat = use_gpumat ? EEVEE_material_hair_get(scene, ma) : NULL; + eGPUMaterialStatus status_mat_surface = gpumat ? GPU_material_status(gpumat) : GPU_MAT_SUCCESS; float *color_p = &ma->r; float *metal_p = &ma->metallic; float *spec_p = &ma->spec; float *rough_p = &ma->roughness; - bool use_ssr = ((stl->effects->enabled_effects & EFFECT_SSR) != 0); - const bool holdout = (ob->base_flag & BASE_HOLDOUT) != 0; + /* Depth prepass. */ + if (use_gpumat && (use_alpha_clip || use_alpha_hash)) { + GPUMaterial *gpumat_depth = EEVEE_material_hair_depth_get(scene, ma, use_alpha_hash, false); - shgrp = DRW_shgroup_hair_create(ob, psys, md, psl->depth_pass, e_data.default_hair_prepass_sh); + eGPUMaterialStatus status_mat_depth = GPU_material_status(gpumat_depth); - shgrp = DRW_shgroup_hair_create( - ob, psys, md, psl->depth_pass_clip, e_data.default_hair_prepass_clip_sh); + if (status_mat_depth != GPU_MAT_SUCCESS) { + /* Mixing both flags. If depth shader fails, show it to the user by not using + * the surface shader. */ + status_mat_surface = status_mat_depth; + } + else { + const bool use_diffuse = GPU_material_flag_get(gpumat_depth, GPU_MATFLAG_DIFFUSE); + const bool use_glossy = GPU_material_flag_get(gpumat_depth, GPU_MATFLAG_GLOSSY); + const bool use_refract = GPU_material_flag_get(gpumat_depth, GPU_MATFLAG_REFRACT); + + for (int i = 0; i < 2; i++) { + DRWPass *pass = (i == 0) ? psl->depth_pass : psl->depth_pass_clip; + + shgrp = DRW_shgroup_material_hair_create(ob, psys, md, pass, gpumat_depth); + + add_standard_uniforms(shgrp, + sldata, + vedata, + NULL, + NULL, + use_diffuse, + use_glossy, + use_refract, + false, + false, + DEFAULT_RENDER_PASS_FLAG); + + /* Unfortunately needed for correctness but not 99% of the time not needed. + * TODO detect when needed? */ + DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo); + DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo); + DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo); + DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo); + DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo); + DRW_shgroup_uniform_block( + shgrp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex); + + if (use_alpha_clip) { + DRW_shgroup_uniform_float(shgrp, "alphaThreshold", &ma->alpha_threshold, 1); + } + } + } + } + + /* Fallback to default shader */ + if (shgrp == NULL) { + for (int i = 0; i < 2; i++) { + DRWPass *depth_pass = (i == 0) ? psl->depth_pass : psl->depth_pass_clip; + struct GPUShader *depth_sh = (i == 0) ? e_data.default_hair_prepass_sh : + e_data.default_hair_prepass_clip_sh; + DRW_shgroup_hair_create(ob, psys, md, depth_pass, depth_sh); + } + } shgrp = NULL; - if (ma->use_nodes && ma->nodetree && !holdout) { + if (gpumat) { static int ssr_id; ssr_id = (use_ssr) ? 1 : -1; static float half = 0.5f; static float error_col[3] = {1.0f, 0.0f, 1.0f}; static float compile_col[3] = {0.5f, 0.5f, 0.5f}; - struct GPUMaterial *gpumat = EEVEE_material_hair_get(scene, ma); - switch (GPU_material_status(gpumat)) { + switch (status_mat_surface) { case GPU_MAT_SUCCESS: { bool use_diffuse = GPU_material_flag_get(gpumat, GPU_MATFLAG_DIFFUSE); bool use_glossy = GPU_material_flag_get(gpumat, GPU_MATFLAG_GLOSSY); @@ -1793,28 +1896,29 @@ static void eevee_hair_cache_populate(EEVEE_Data *vedata, DEFAULT_RENDER_PASS_FLAG); /* Add the hair to all the render_passes that are enabled */ - RENDER_PASS_ITER_BEGIN(stl->g_data->render_passes, render_pass_index, render_pass_flag) - shgrp = DRW_shgroup_material_hair_create( - ob, psys, md, psl->material_accum_pass[render_pass_index], gpumat); - if (!use_diffuse && !use_glossy && !use_refract) { - /* Small hack to avoid issue when utilTex is needed for - * world_normals_get and none of the bsdfs that need it are present. - * This binds `utilTex` even if not needed. */ - DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex); - } + RENDER_PASS_ITER_BEGIN (stl->g_data->render_passes, render_pass_index, render_pass_flag) { + shgrp = DRW_shgroup_material_hair_create( + ob, psys, md, psl->material_accum_pass[render_pass_index], gpumat); + if (!use_diffuse && !use_glossy && !use_refract) { + /* Small hack to avoid issue when utilTex is needed for + * world_normals_get and none of the bsdfs that need it are present. + * This binds `utilTex` even if not needed. */ + DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex); + } - add_standard_uniforms(shgrp, - sldata, - vedata, - &ssr_id, - NULL, - use_diffuse, - use_glossy, - use_refract, - false, - false, - render_pass_flag); - RENDER_PASS_ITER_END(render_pass_index) + add_standard_uniforms(shgrp, + sldata, + vedata, + &ssr_id, + NULL, + use_diffuse, + use_glossy, + use_refract, + false, + false, + render_pass_flag); + } + RENDER_PASS_ITER_END(render_pass_index); break; } @@ -1840,28 +1944,59 @@ static void eevee_hair_cache_populate(EEVEE_Data *vedata, DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1); DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1); - RENDER_PASS_ITER_BEGIN(stl->g_data->render_passes, render_pass_index, render_pass_flag) - shgrp = EEVEE_default_hair_render_pass_shading_group_get( - sldata, - vedata, - ob, - psys, - md, - holdout, - use_ssr, - psl->material_accum_pass[render_pass_index], - render_pass_flag); - - DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1); - DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1); - DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1); - DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1); - RENDER_PASS_ITER_END(render_pass_index) + RENDER_PASS_ITER_BEGIN (stl->g_data->render_passes, render_pass_index, render_pass_flag) { + shgrp = EEVEE_default_hair_render_pass_shading_group_get( + sldata, + vedata, + ob, + psys, + md, + holdout, + use_ssr, + psl->material_accum_pass[render_pass_index], + render_pass_flag); + + DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1); + DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1); + DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1); + DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1); + } + RENDER_PASS_ITER_END(render_pass_index); } /* Shadows */ - DRW_shgroup_hair_create(ob, psys, md, psl->shadow_pass, e_data.default_hair_prepass_sh); - *cast_shadow = true; + char blend_shadow = use_gpumat ? ma->blend_shadow : MA_BS_SOLID; + const bool shadow_alpha_hash = (blend_shadow == MA_BS_HASHED); + switch (blend_shadow) { + case MA_BS_SOLID: + DRW_shgroup_hair_create(ob, psys, md, psl->shadow_pass, e_data.default_hair_prepass_sh); + *cast_shadow = true; + break; + case MA_BS_CLIP: + case MA_BS_HASHED: + gpumat = EEVEE_material_hair_depth_get(scene, ma, shadow_alpha_hash, true); + shgrp = DRW_shgroup_material_hair_create(ob, psys, md, psl->shadow_pass, gpumat); + /* Unfortunately needed for correctness but not 99% of the time not needed. + * TODO detect when needed? */ + DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo); + DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo); + DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo); + DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo); + DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo); + DRW_shgroup_uniform_block( + shgrp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex); + + if (!shadow_alpha_hash) { + DRW_shgroup_uniform_float(shgrp, "alphaThreshold", &ma->alpha_threshold, 1); + } + *cast_shadow = true; + break; + case MA_BS_NONE: + default: + break; + } } void EEVEE_materials_cache_populate(EEVEE_Data *vedata, diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index 255c6c50c2d..076738dcbdf 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -135,9 +135,8 @@ bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph * float winmat[4][4], viewmat[4][4], viewinv[4][4]; /* TODO(sergey): Shall render hold pointer to an evaluated camera instead? */ struct Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re)); - float frame = BKE_scene_frame_get(scene); - RE_GetCameraWindow(engine->re, ob_camera_eval, frame, winmat); + RE_GetCameraWindow(engine->re, ob_camera_eval, winmat); RE_GetCameraWindowWithOverscan(engine->re, winmat, g_data->overscan); RE_GetCameraModelMatrix(engine->re, ob_camera_eval, viewinv); diff --git a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl index 6b06aab34d2..c42f905cf7e 100644 --- a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl @@ -9,6 +9,14 @@ out vec3 worldNormal; out vec3 viewNormal; #endif +#ifdef HAIR_SHADER +out vec3 hairTangent; +out float hairThickTime; +out float hairThickness; +out float hairTime; +flat out int hairStrandID; +#endif + void main() { #ifdef GPU_INTEL @@ -18,13 +26,34 @@ void main() gl_Position.x = float(gl_VertexID); #endif +#ifdef HAIR_SHADER + hairStrandID = hair_get_strand_id(); + vec3 world_pos, binor; + hair_get_pos_tan_binor_time((ProjectionMatrix[3][3] == 0.0), + ModelMatrixInverse, + ViewMatrixInverse[3].xyz, + ViewMatrixInverse[2].xyz, + world_pos, + hairTangent, + binor, + hairTime, + hairThickness, + hairThickTime); + + worldNormal = cross(hairTangent, binor); +#else vec3 world_pos = point_object_to_world(pos); +#endif + gl_Position = point_world_to_ndc(world_pos); #ifdef MESH_SHADER worldPosition = world_pos; viewPosition = point_world_to_view(worldPosition); +# ifndef HAIR_SHADER worldNormal = normalize(normal_object_to_world(nor)); +# endif + /* No need to normalize since this is just a rotation. */ viewNormal = normal_world_to_view(worldNormal); # ifdef USE_ATTR diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c index a5f67b7831e..f8f55843a29 100644 --- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c @@ -314,12 +314,12 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd, break; case eGplBlendMode_Multiply: case eGplBlendMode_Divide: - case eGplBlendMode_Overlay: + case eGplBlendMode_HardLight: state |= DRW_STATE_BLEND_MUL; break; } - if (ELEM(gpl->blend_mode, eGplBlendMode_Subtract, eGplBlendMode_Overlay)) { + if (ELEM(gpl->blend_mode, eGplBlendMode_Subtract, eGplBlendMode_HardLight)) { /* For these effect to propagate, we need a signed floating point buffer. */ pd->use_signed_fb = true; } @@ -336,7 +336,7 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd, DRW_shgroup_stencil_mask(grp, 0xFF); DRW_shgroup_call_procedural_triangles(grp, NULL, 1); - if (gpl->blend_mode == eGplBlendMode_Overlay) { + if (gpl->blend_mode == eGplBlendMode_HardLight) { /* We cannot do custom blending on MultiTarget framebuffers. * Workaround by doing 2 passes. */ grp = DRW_shgroup_create(sh, tgp_layer->blend_ps); diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index 7ffa02189e2..9ebd20eb539 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -905,7 +905,8 @@ void GPENCIL_draw_scene(void *ved) float clear_cols[2][4] = {{0.0f, 0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}; /* Fade 3D objects. */ - if ((!pd->is_render) && (pd->fade_3d_object_opacity > -1.0f)) { + if ((!pd->is_render) && (pd->fade_3d_object_opacity > -1.0f) && (pd->obact != NULL) && + (pd->obact->type == OB_GPENCIL)) { float background_color[3]; ED_view3d_background_color_get(pd->scene, pd->v3d, background_color); /* Blend color. */ diff --git a/source/blender/draw/engines/gpencil/gpencil_render.c b/source/blender/draw/engines/gpencil/gpencil_render.c index 496122c0483..bb91bdbe396 100644 --- a/source/blender/draw/engines/gpencil/gpencil_render.c +++ b/source/blender/draw/engines/gpencil/gpencil_render.c @@ -51,8 +51,7 @@ void GPENCIL_render_init(GPENCIL_Data *vedata, float winmat[4][4], viewmat[4][4], viewinv[4][4]; struct Object *camera = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re)); - float frame = BKE_scene_frame_get(scene); - RE_GetCameraWindow(engine->re, camera, frame, winmat); + RE_GetCameraWindow(engine->re, camera, winmat); RE_GetCameraModelMatrix(engine->re, camera, viewinv); invert_m4_m4(viewmat, viewinv); diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl index cb34515a960..54b2369b32b 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl @@ -77,12 +77,12 @@ layout(std140) uniform gpLightBlock /* Must match eGPLayerBlendModes */ #define MODE_REGULAR 0 -#define MODE_OVERLAY 1 +#define MODE_HARDLIGHT 1 #define MODE_ADD 2 #define MODE_SUB 3 #define MODE_MULTIPLY 4 #define MODE_DIVIDE 5 -#define MODE_OVERLAY_SECOND_PASS 999 +#define MODE_HARDLIGHT_SECOND_PASS 999 void blend_mode_output( int blend_mode, vec4 color, float opacity, out vec4 frag_color, out vec4 frag_revealage) @@ -104,7 +104,7 @@ void blend_mode_output( color.a *= opacity; frag_revealage = frag_color = clamp(1.0 / max(vec4(1e-6), 1.0 - color * color.a), 0.0, 1e18); break; - case MODE_OVERLAY: + case MODE_HARDLIGHT: /* Reminder: Blending func is multiply blend (dst.rgba * src.rgba).*/ /** * We need to separate the overlay equation into 2 term (one mul and one add). @@ -120,11 +120,13 @@ void blend_mode_output( color = mix(vec4(0.5), color, color.a * opacity); vec4 s = step(-0.5, -color); frag_revealage = frag_color = 2.0 * s + 2.0 * color * (1.0 - s * 2.0); + frag_revealage = max(vec4(0.0), frag_revealage); break; - case MODE_OVERLAY_SECOND_PASS: + case MODE_HARDLIGHT_SECOND_PASS: /* Reminder: Blending func is additive blend (dst.rgba + src.rgba).*/ color = mix(vec4(0.5), color, color.a * opacity); frag_revealage = frag_color = (-1.0 + 2.0 * color) * step(-0.5, -color); + frag_revealage = max(vec4(0.0), frag_revealage); break; case MODE_SUB: case MODE_ADD: @@ -572,6 +574,7 @@ void fill_vertex() finalUvs = rot_scale * uv1.xy + loc; # endif + strokeHardeness = 1.0; strokeThickness = 1e18; strokeAspect = vec2(1.0); strokePt1 = strokePt2 = vec2(0.0); diff --git a/source/blender/draw/engines/overlay/overlay_antialiasing.c b/source/blender/draw/engines/overlay/overlay_antialiasing.c index 0b7637aa098..efd2f6588ba 100644 --- a/source/blender/draw/engines/overlay/overlay_antialiasing.c +++ b/source/blender/draw/engines/overlay/overlay_antialiasing.c @@ -113,16 +113,6 @@ void OVERLAY_antialiasing_init(OVERLAY_Data *vedata) GPU_ATTACHMENT_TEXTURE(color_tex), GPU_ATTACHMENT_TEXTURE(line_tex), }); - - if (pd->xray_enabled) { - DRW_texture_ensure_fullscreen_2d(&txl->temp_depth_tx, GPU_DEPTH24_STENCIL8, 0); - - GPU_framebuffer_ensure_config(&fbl->overlay_xray_depth_copy_fb, - { - GPU_ATTACHMENT_TEXTURE(txl->temp_depth_tx), - GPU_ATTACHMENT_NONE, - }); - } } void OVERLAY_antialiasing_cache_init(OVERLAY_Data *vedata) @@ -168,6 +158,7 @@ void OVERLAY_antialiasing_cache_finish(OVERLAY_Data *vedata) { OVERLAY_FramebufferList *fbl = vedata->fbl; OVERLAY_TextureList *txl = vedata->txl; + OVERLAY_PassList *psl = vedata->psl; OVERLAY_PrivateData *pd = vedata->stl->pd; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); @@ -191,6 +182,24 @@ void OVERLAY_antialiasing_cache_finish(OVERLAY_Data *vedata) GPU_ATTACHMENT_TEXTURE(dtxl->color_overlay), GPU_ATTACHMENT_TEXTURE(txl->overlay_line_tx)}); } + + pd->antialiasing.do_depth_copy = !(psl->wireframe_ps == NULL || + DRW_pass_is_empty(psl->wireframe_ps)) || + (pd->xray_enabled && pd->xray_opacity > 0.0f); + pd->antialiasing.do_depth_infront_copy = !(psl->wireframe_xray_ps == NULL || + DRW_pass_is_empty(psl->wireframe_xray_ps)); + + const bool do_wireframe = pd->antialiasing.do_depth_copy || + pd->antialiasing.do_depth_infront_copy; + if (pd->xray_enabled || do_wireframe) { + DRW_texture_ensure_fullscreen_2d(&txl->temp_depth_tx, GPU_DEPTH24_STENCIL8, 0); + + GPU_framebuffer_ensure_config(&fbl->overlay_xray_depth_copy_fb, + { + GPU_ATTACHMENT_TEXTURE(txl->temp_depth_tx), + GPU_ATTACHMENT_NONE, + }); + } } void OVERLAY_antialiasing_start(OVERLAY_Data *vedata) @@ -217,18 +226,31 @@ void OVERLAY_xray_depth_copy(OVERLAY_Data *vedata) OVERLAY_FramebufferList *fbl = vedata->fbl; OVERLAY_PrivateData *pd = vedata->stl->pd; + if (DRW_state_is_fbo() && pd->antialiasing.do_depth_copy) { + /* We copy the depth of the rendered geometry to be able to compare to the overlays depth. */ + GPU_framebuffer_blit( + fbl->overlay_default_fb, 0, fbl->overlay_xray_depth_copy_fb, 0, GPU_DEPTH_BIT); + } + if (DRW_state_is_fbo() && pd->xray_enabled) { - if (pd->xray_opacity > 0.0f) { - /* We copy the depth of the rendered geometry to be able to compare to the overlays depth. */ - GPU_framebuffer_blit( - fbl->overlay_default_fb, 0, fbl->overlay_xray_depth_copy_fb, 0, GPU_DEPTH_BIT); - } /* We then clear to not occlude the overlays directly. */ GPU_framebuffer_bind(fbl->overlay_default_fb); GPU_framebuffer_clear_depth(fbl->overlay_default_fb, 1.0f); } } +void OVERLAY_xray_depth_infront_copy(OVERLAY_Data *vedata) +{ + OVERLAY_FramebufferList *fbl = vedata->fbl; + OVERLAY_PrivateData *pd = vedata->stl->pd; + + if (DRW_state_is_fbo() && pd->antialiasing.do_depth_infront_copy) { + /* We copy the depth of the rendered geometry to be able to compare to the overlays depth. */ + GPU_framebuffer_blit( + fbl->overlay_in_front_fb, 0, fbl->overlay_xray_depth_copy_fb, 0, GPU_DEPTH_BIT); + } +} + void OVERLAY_xray_fade_draw(OVERLAY_Data *vedata) { OVERLAY_PassList *psl = vedata->psl; diff --git a/source/blender/draw/engines/overlay/overlay_engine.c b/source/blender/draw/engines/overlay/overlay_engine.c index adbcd3c7f28..97f6b91b7a9 100644 --- a/source/blender/draw/engines/overlay/overlay_engine.c +++ b/source/blender/draw/engines/overlay/overlay_engine.c @@ -466,6 +466,8 @@ static void OVERLAY_draw_scene(void *vedata) OVERLAY_xray_fade_draw(vedata); OVERLAY_grid_draw(vedata); + OVERLAY_xray_depth_infront_copy(vedata); + if (DRW_state_is_fbo()) { GPU_framebuffer_bind(fbl->overlay_line_in_front_fb); } diff --git a/source/blender/draw/engines/overlay/overlay_image.c b/source/blender/draw/engines/overlay/overlay_image.c index f81c51f0883..057ab4990dd 100644 --- a/source/blender/draw/engines/overlay/overlay_image.c +++ b/source/blender/draw/engines/overlay/overlay_image.c @@ -244,7 +244,7 @@ static void image_camera_background_matrix_get(const Camera *cam, unit_m4(scale); unit_m4(translate); - /* Normalized Object space camera frame corners. */ + /* Normalized Object space camera frame corners. */ float cam_corners[4][3]; BKE_camera_view_frame(draw_ctx->scene, cam, cam_corners); float cam_width = fabsf(cam_corners[0][0] - cam_corners[3][0]); diff --git a/source/blender/draw/engines/overlay/overlay_outline.c b/source/blender/draw/engines/overlay/overlay_outline.c index 0395f6890bd..142421f58d8 100644 --- a/source/blender/draw/engines/overlay/overlay_outline.c +++ b/source/blender/draw/engines/overlay/overlay_outline.c @@ -102,14 +102,18 @@ void OVERLAY_outline_init(OVERLAY_Data *vedata) if (pd->antialiasing.enabled) { GPU_framebuffer_ensure_config(&fbl->outlines_resolve_fb, - {GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(txl->overlay_color_tx), - GPU_ATTACHMENT_TEXTURE(txl->overlay_line_tx)}); + { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(txl->overlay_color_tx), + GPU_ATTACHMENT_TEXTURE(txl->overlay_line_tx), + }); } else { - GPU_framebuffer_ensure_config( - &fbl->outlines_resolve_fb, - {GPU_ATTACHMENT_TEXTURE(txl->temp_depth_tx), GPU_ATTACHMENT_TEXTURE(dtxl->color)}); + GPU_framebuffer_ensure_config(&fbl->outlines_resolve_fb, + { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(dtxl->color_overlay), + }); } } } diff --git a/source/blender/draw/engines/overlay/overlay_paint.c b/source/blender/draw/engines/overlay/overlay_paint.c index bb0b124f2ae..4a1aa270de0 100644 --- a/source/blender/draw/engines/overlay/overlay_paint.c +++ b/source/blender/draw/engines/overlay/overlay_paint.c @@ -28,6 +28,34 @@ #include "overlay_private.h" +/* Check if the given object is rendered (partially) transparent */ +static bool paint_object_is_rendered_transparent(View3D *v3d, Object *ob) +{ + if (v3d->shading.type == OB_WIRE) { + return true; + } + else if (v3d->shading.type == OB_SOLID) { + if (v3d->shading.flag & V3D_SHADING_XRAY) { + return true; + } + + if (ob && v3d->shading.color_type == V3D_SHADING_OBJECT_COLOR) { + return ob->color[3] < 1.0f; + } + else if (ob && ob->type == OB_MESH && ob->data && + v3d->shading.color_type == V3D_SHADING_MATERIAL_COLOR) { + Mesh *me = ob->data; + for (int i = 0; i < me->totcol; i++) { + Material *mat = me->mat[i]; + if (mat && mat->a < 1.0f) { + return true; + } + } + } + } + return false; +} + void OVERLAY_paint_init(OVERLAY_Data *vedata) { OVERLAY_StorageList *stl = vedata->stl; @@ -35,6 +63,8 @@ void OVERLAY_paint_init(OVERLAY_Data *vedata) const DRWContextState *draw_ctx = DRW_context_state_get(); pd->painting.in_front = draw_ctx->obact && (draw_ctx->obact->dtx & OB_DRAWXRAY); + pd->painting.alpha_blending = paint_object_is_rendered_transparent(draw_ctx->v3d, + draw_ctx->obact); } void OVERLAY_paint_cache_init(OVERLAY_Data *vedata) @@ -46,9 +76,10 @@ void OVERLAY_paint_cache_init(OVERLAY_Data *vedata) DRWShadingGroup *grp; DRWState state; - const bool use_alpha_blending = (draw_ctx->v3d->shading.type == OB_WIRE); const bool draw_contours = (pd->overlay.wpaint_flag & V3D_OVERLAY_WPAINT_CONTOURS) != 0; float opacity = 0.0f; + pd->paint_depth_grp = NULL; + psl->paint_depth_ps = NULL; switch (pd->ctx_mode) { case CTX_MODE_POSE: @@ -56,16 +87,23 @@ void OVERLAY_paint_cache_init(OVERLAY_Data *vedata) opacity = pd->overlay.weight_paint_mode_opacity; if (opacity > 0.0f) { state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL; - state |= use_alpha_blending ? DRW_STATE_BLEND_ALPHA : DRW_STATE_BLEND_MUL; + state |= pd->painting.alpha_blending ? DRW_STATE_BLEND_ALPHA : DRW_STATE_BLEND_MUL; DRW_PASS_CREATE(psl->paint_color_ps, state | pd->clipping_state); sh = OVERLAY_shader_paint_weight(); pd->paint_surf_grp = grp = DRW_shgroup_create(sh, psl->paint_color_ps); DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); DRW_shgroup_uniform_bool_copy(grp, "drawContours", draw_contours); - DRW_shgroup_uniform_bool_copy(grp, "useAlphaBlend", use_alpha_blending); + DRW_shgroup_uniform_bool_copy(grp, "useAlphaBlend", pd->painting.alpha_blending); DRW_shgroup_uniform_float_copy(grp, "opacity", opacity); DRW_shgroup_uniform_texture(grp, "colorramp", G_draw.weight_ramp); + + if (pd->painting.alpha_blending) { + state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; + DRW_PASS_CREATE(psl->paint_depth_ps, state); + sh = OVERLAY_shader_depth_only(); + pd->paint_depth_grp = DRW_shgroup_create(sh, psl->paint_depth_ps); + } } break; } @@ -73,13 +111,13 @@ void OVERLAY_paint_cache_init(OVERLAY_Data *vedata) opacity = pd->overlay.vertex_paint_mode_opacity; if (opacity > 0.0f) { state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL; - state |= use_alpha_blending ? DRW_STATE_BLEND_ALPHA : DRW_STATE_BLEND_MUL; + state |= pd->painting.alpha_blending ? DRW_STATE_BLEND_ALPHA : DRW_STATE_BLEND_MUL; DRW_PASS_CREATE(psl->paint_color_ps, state | pd->clipping_state); sh = OVERLAY_shader_paint_vertcol(); pd->paint_surf_grp = grp = DRW_shgroup_create(sh, psl->paint_color_ps); DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); - DRW_shgroup_uniform_bool_copy(grp, "useAlphaBlend", use_alpha_blending); + DRW_shgroup_uniform_bool_copy(grp, "useAlphaBlend", pd->painting.alpha_blending); DRW_shgroup_uniform_float_copy(grp, "opacity", opacity); } break; @@ -173,11 +211,15 @@ void OVERLAY_paint_vertex_cache_populate(OVERLAY_Data *vedata, Object *ob) const bool use_face_sel = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; const bool use_vert_sel = (me_orig->editflag & ME_EDIT_PAINT_VERT_SEL) != 0; - if (pd->paint_surf_grp) { - if (ob->mode == OB_MODE_WEIGHT_PAINT) { + if (ob->mode == OB_MODE_WEIGHT_PAINT) { + if (pd->paint_surf_grp) { geom = DRW_cache_mesh_surface_weights_get(ob); DRW_shgroup_call(pd->paint_surf_grp, geom, ob); } + if (pd->paint_depth_grp) { + geom = DRW_cache_mesh_surface_weights_get(ob); + DRW_shgroup_call(pd->paint_depth_grp, geom, ob); + } } if (use_face_sel || use_wire) { @@ -210,10 +252,13 @@ void OVERLAY_paint_draw(OVERLAY_Data *vedata) DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); if (DRW_state_is_fbo()) { - /* Pain overlay needs final color because of multiply blend mode. */ + /* Paint overlay needs final color because of multiply blend mode. */ GPU_framebuffer_bind(pd->painting.in_front ? dfbl->in_front_fb : dfbl->default_fb); } + if (psl->paint_depth_ps) { + DRW_draw_pass(psl->paint_depth_ps); + } if (psl->paint_color_ps) { DRW_draw_pass(psl->paint_color_ps); } diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h index 47c52c885b2..bd9583c6a5f 100644 --- a/source/blender/draw/engines/overlay/overlay_private.h +++ b/source/blender/draw/engines/overlay/overlay_private.h @@ -93,6 +93,7 @@ typedef struct OVERLAY_PassList { DRWPass *outlines_detect_ps; DRWPass *outlines_resolve_ps; DRWPass *paint_color_ps; + DRWPass *paint_depth_ps; DRWPass *paint_overlay_ps; DRWPass *particle_ps; DRWPass *pointcloud_ps; @@ -245,6 +246,7 @@ typedef struct OVERLAY_PrivateData { DRWShadingGroup *motion_path_points_grp; DRWShadingGroup *outlines_grp; DRWShadingGroup *outlines_gpencil_grp; + DRWShadingGroup *paint_depth_grp; DRWShadingGroup *paint_surf_grp; DRWShadingGroup *paint_wire_grp; DRWShadingGroup *paint_wire_selected_grp; @@ -291,6 +293,8 @@ typedef struct OVERLAY_PrivateData { struct { bool enabled; + bool do_depth_copy; + bool do_depth_infront_copy; } antialiasing; struct { bool show_handles; @@ -318,6 +322,7 @@ typedef struct OVERLAY_PrivateData { } armature; struct { bool in_front; + bool alpha_blending; } painting; struct { DRWCallBuffer *handle[2]; @@ -408,6 +413,7 @@ void OVERLAY_antialiasing_start(OVERLAY_Data *vedata); void OVERLAY_antialiasing_end(OVERLAY_Data *vedata); void OVERLAY_xray_fade_draw(OVERLAY_Data *vedata); void OVERLAY_xray_depth_copy(OVERLAY_Data *vedata); +void OVERLAY_xray_depth_infront_copy(OVERLAY_Data *vedata); bool OVERLAY_armature_is_pose_mode(Object *ob, const struct DRWContextState *draw_ctx); void OVERLAY_armature_cache_init(OVERLAY_Data *vedata); @@ -610,7 +616,7 @@ GPUShader *OVERLAY_shader_particle_shape(void); GPUShader *OVERLAY_shader_pointcloud_dot(void); GPUShader *OVERLAY_shader_sculpt_mask(void); GPUShader *OVERLAY_shader_volume_velocity(bool use_needle); -GPUShader *OVERLAY_shader_wireframe(void); +GPUShader *OVERLAY_shader_wireframe(bool custom_bias); GPUShader *OVERLAY_shader_wireframe_select(void); GPUShader *OVERLAY_shader_xray_fade(void); diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c index 0b2f98294ec..8b70a0982af 100644 --- a/source/blender/draw/engines/overlay/overlay_shader.c +++ b/source/blender/draw/engines/overlay/overlay_shader.c @@ -192,7 +192,7 @@ typedef struct OVERLAY_Shaders { GPUShader *volume_velocity_needle_sh; GPUShader *volume_velocity_sh; GPUShader *wireframe_select; - GPUShader *wireframe; + GPUShader *wireframe[2]; GPUShader *xray_fade; } OVERLAY_Shaders; @@ -1372,24 +1372,29 @@ GPUShader *OVERLAY_shader_wireframe_select(void) return sh_data->wireframe_select; } -GPUShader *OVERLAY_shader_wireframe(void) +GPUShader *OVERLAY_shader_wireframe(bool custom_bias) { const DRWContextState *draw_ctx = DRW_context_state_get(); const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; - if (!sh_data->wireframe) { - sh_data->wireframe = GPU_shader_create_from_arrays({ + if (!sh_data->wireframe[custom_bias]) { + sh_data->wireframe[custom_bias] = GPU_shader_create_from_arrays({ .vert = (const char *[]){sh_cfg->lib, datatoc_common_view_lib_glsl, datatoc_common_globals_lib_glsl, datatoc_gpu_shader_common_obinfos_lib_glsl, datatoc_wireframe_vert_glsl, NULL}, - .frag = (const char *[]){datatoc_common_view_lib_glsl, datatoc_wireframe_frag_glsl, NULL}, - .defs = (const char *[]){sh_cfg->def, NULL}, + .frag = (const char *[]){datatoc_common_view_lib_glsl, + datatoc_common_globals_lib_glsl, + datatoc_wireframe_frag_glsl, + NULL}, + .defs = (const char *[]){sh_cfg->def, + custom_bias ? "#define CUSTOM_DEPTH_BIAS\n" : NULL, + NULL}, }); } - return sh_data->wireframe; + return sh_data->wireframe[custom_bias]; } GPUShader *OVERLAY_shader_xray_fade(void) diff --git a/source/blender/draw/engines/overlay/overlay_wireframe.c b/source/blender/draw/engines/overlay/overlay_wireframe.c index 17b412b143c..27f3f4ae9af 100644 --- a/source/blender/draw/engines/overlay/overlay_wireframe.c +++ b/source/blender/draw/engines/overlay/overlay_wireframe.c @@ -51,6 +51,7 @@ void OVERLAY_wireframe_init(OVERLAY_Data *vedata) void OVERLAY_wireframe_cache_init(OVERLAY_Data *vedata) { OVERLAY_PassList *psl = vedata->psl; + OVERLAY_TextureList *txl = vedata->txl; OVERLAY_PrivateData *pd = vedata->stl->pd; const DRWContextState *draw_ctx = DRW_context_state_get(); DRWShadingGroup *grp = NULL; @@ -66,12 +67,14 @@ void OVERLAY_wireframe_cache_init(OVERLAY_Data *vedata) const bool use_select = (DRW_state_is_select() || DRW_state_is_depth()); GPUShader *wires_sh = use_select ? OVERLAY_shader_wireframe_select() : - OVERLAY_shader_wireframe(); + OVERLAY_shader_wireframe(pd->antialiasing.enabled); for (int xray = 0; xray < (is_material_shmode ? 1 : 2); xray++) { DRWState state = DRW_STATE_FIRST_VERTEX_CONVENTION | DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; DRWPass *pass; + GPUTexture **depth_tx = (pd->xray_enabled || pd->xray_opacity > 0.0f) ? &txl->temp_depth_tx : + &txl->dummy_depth_tx; if (xray == 0) { DRW_PASS_CREATE(psl->wireframe_ps, state | pd->clipping_state); @@ -85,6 +88,7 @@ void OVERLAY_wireframe_cache_init(OVERLAY_Data *vedata) for (int use_coloring = 0; use_coloring < 2; use_coloring++) { pd->wires_grp[xray][use_coloring] = grp = DRW_shgroup_create(wires_sh, pass); DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tx); DRW_shgroup_uniform_float_copy(grp, "wireStepParam", pd->shdata.wire_step_param); DRW_shgroup_uniform_bool_copy(grp, "useColoring", use_coloring); DRW_shgroup_uniform_bool_copy(grp, "isTransform", (G.moving & G_TRANSFORM_OBJ) != 0); @@ -92,10 +96,12 @@ void OVERLAY_wireframe_cache_init(OVERLAY_Data *vedata) DRW_shgroup_uniform_bool_copy(grp, "isRandomColor", is_random_color); pd->wires_all_grp[xray][use_coloring] = grp = DRW_shgroup_create(wires_sh, pass); + DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tx); DRW_shgroup_uniform_float_copy(grp, "wireStepParam", 1.0f); } pd->wires_sculpt_grp[xray] = grp = DRW_shgroup_create(wires_sh, pass); + DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tx); DRW_shgroup_uniform_float_copy(grp, "wireStepParam", 10.0f); DRW_shgroup_uniform_bool_copy(grp, "useColoring", false); } diff --git a/source/blender/draw/engines/overlay/shaders/edit_gpencil_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_gpencil_vert.glsl index 3a52e0c73b7..732e392ffe0 100644 --- a/source/blender/draw/engines/overlay/shaders/edit_gpencil_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/edit_gpencil_vert.glsl @@ -21,11 +21,11 @@ void discard_vert() gl_Position = vec4(0.0, 0.0, -3e36, 0.0); } -#define GP_EDIT_POINT_SELECTED (1u << 0u) -#define GP_EDIT_STROKE_SELECTED (1u << 1u) -#define GP_EDIT_MULTIFRAME (1u << 2u) -#define GP_EDIT_STROKE_START (1u << 3u) -#define GP_EDIT_STROKE_END (1u << 4u) +#define GP_EDIT_POINT_SELECTED 1u /* 1 << 0 */ +#define GP_EDIT_STROKE_SELECTED 2u /* 1 << 1 */ +#define GP_EDIT_MULTIFRAME 4u /* 1 << 2 */ +#define GP_EDIT_STROKE_START 8u /* 1 << 3 */ +#define GP_EDIT_STROKE_END 16u /* 1 << 4 */ #ifdef USE_POINTS # define colorUnselect colorGpencilVertex diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_common_lib.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_common_lib.glsl index b79bae45f23..195d2a5a7b7 100644 --- a/source/blender/draw/engines/overlay/shaders/edit_mesh_common_lib.glsl +++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_common_lib.glsl @@ -20,7 +20,7 @@ vec4 EDIT_MESH_edge_color_inner(int edge_flag) color = ((edge_flag & EDGE_SELECTED) != 0) ? color_select : color; color = ((edge_flag & EDGE_ACTIVE) != 0) ? colorEditMeshActive : color; - color.a = (selectEdges || (edge_flag & (EDGE_SELECTED | EDGE_ACTIVE)) != 0) ? 1.0 : 0.4; + color.a = (selectEdges || (edge_flag & (EDGE_SELECTED | EDGE_ACTIVE)) != 0) ? 1.0 : 0.7; return color; } @@ -32,7 +32,7 @@ vec4 EDIT_MESH_edge_vertex_color(int vertex_flag) bool edge_selected = (vertex_flag & (VERT_ACTIVE | VERT_SELECTED)) != 0; color = (edge_selected) ? color_select : color; - color.a = (selectEdges || edge_selected) ? 1.0 : 0.4; + color.a = (selectEdges || edge_selected) ? 1.0 : 0.7; return color; } diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl index 8833490e818..fd37bc8c534 100644 --- a/source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl @@ -40,7 +40,7 @@ void main() } else { nor = norAndFlag.xyz; - if (all(equal(nor, vec3(0.0)))) { + if (all(equal(nor, vec3(0)))) { finalColor = vec4(0.0); return; } diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl index 768b0596d17..203f6cb1901 100644 --- a/source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl @@ -48,10 +48,10 @@ void main() gl_PointSize = sizeVertex * 2.0; /* Make selected and active vertex always on top. */ if ((data.x & VERT_SELECTED) != 0) { - gl_Position.z -= 1e-7; + gl_Position.z -= 5e-7 * abs(gl_Position.w); } if ((data.x & VERT_ACTIVE) != 0) { - gl_Position.z -= 1e-7; + gl_Position.z -= 5e-7 * abs(gl_Position.w); } bool occluded = test_occlusion(); @@ -69,6 +69,10 @@ void main() float bweight = float(m_data.w) / 255.0; finalColorOuter = EDIT_MESH_edge_color_outer(m_data.y, m_data.x, crease, bweight); + if (finalColorOuter.a > 0.0) { + gl_Position.z -= 5e-7 * abs(gl_Position.w); + } + bool occluded = false; /* Done in fragment shader */ #elif defined(FACE) diff --git a/source/blender/draw/engines/overlay/shaders/wireframe_frag.glsl b/source/blender/draw/engines/overlay/shaders/wireframe_frag.glsl index edfe720da0c..b5442dc1b0b 100644 --- a/source/blender/draw/engines/overlay/shaders/wireframe_frag.glsl +++ b/source/blender/draw/engines/overlay/shaders/wireframe_frag.glsl @@ -1,4 +1,7 @@ +/* Scene Depth texture copy for manual depth test. */ +uniform sampler2D depthTex; + flat in vec2 edgeStart; #ifndef SELECT_EDGES @@ -21,5 +24,32 @@ void main() lineOutput = pack_line_data(gl_FragCoord.xy, edgeStart, edgePos); fragColor.rgb = finalColor; fragColor.a = 1.0; + +# ifdef CUSTOM_DEPTH_BIAS + vec2 dir = lineOutput.xy * 2.0 - 1.0; + bool dir_horiz = abs(dir.x) > abs(dir.y); + + vec2 uv = gl_FragCoord.xy * sizeViewportInv.xy; + float depth_occluder = texture(depthTex, uv).r; + float depth_min = depth_occluder; + + if (dir_horiz) { + depth_min = min(depth_min, texture(depthTex, uv + vec2(-sizeViewportInv.x, 0.0)).r); + depth_min = min(depth_min, texture(depthTex, uv + vec2(sizeViewportInv.x, 0.0)).r); + } + else { + depth_min = min(depth_min, texture(depthTex, uv + vec2(0, -sizeViewportInv.y)).r); + depth_min = min(depth_min, texture(depthTex, uv + vec2(0, sizeViewportInv.y)).r); + } + + float delta = abs(depth_occluder - depth_min); + + if (gl_FragCoord.z < (depth_occluder + delta) && gl_FragCoord.z > depth_occluder) { + gl_FragDepth = depth_occluder; + } + else { + gl_FragDepth = gl_FragCoord.z; + } +# endif #endif } diff --git a/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl b/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl index 1abac302cda..3fefe2cc0bf 100644 --- a/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl @@ -110,19 +110,22 @@ void main() vec3 V = (is_persp) ? normalize(ViewMatrixInverse[3].xyz - wpos) : ViewMatrixInverse[2].xyz; float facing = dot(wnor, V); + + gl_Position = point_world_to_ndc(wpos); + +#ifndef CUSTOM_DEPTH_BIAS float facing_ratio = clamp(1.0 - facing * facing, 0.0, 1.0); float flip = sign(facing); /* Flip when not facing the normal (i.e.: backfacing). */ float curvature = (1.0 - wd * 0.75); /* Avoid making things worse for curvy areas. */ vec3 wofs = wnor * (facing_ratio * curvature * flip); wofs = normal_world_to_view(wofs); - gl_Position = point_world_to_ndc(wpos); - /* Push vertex half a pixel (maximum) in normal direction. */ gl_Position.xy += wofs.xy * sizeViewportInv.xy * gl_Position.w; /* Push the vertex towards the camera. Helps a bit. */ - gl_Position.z -= facing_ratio * curvature * 4.0e-5; + gl_Position.z -= facing_ratio * curvature * 1.0e-6 * gl_Position.w; +#endif /* Convert to screen position [0..sizeVp]. */ edgeStart = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy; diff --git a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c index 3050093062f..a0db09e9273 100644 --- a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c +++ b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c @@ -168,9 +168,9 @@ void workbench_antialiasing_engine_init(WORKBENCH_Data *vedata) wpd->view = NULL; - /* reset complete drawing when navigating. */ + /* reset complete drawing when navigating or during viewport playback. */ if (wpd->taa_sample != 0) { - if (wpd->is_navigating) { + if (wpd->is_navigating || wpd->is_playback) { wpd->taa_sample = 0; } } @@ -422,6 +422,8 @@ void workbench_antialiasing_draw_pass(WORKBENCH_Data *vedata) * If TAA accumulation is finished, we only blit the result. */ + const bool last_sample = wpd->taa_sample + 1 == wpd->taa_sample_len; + const bool taa_finished = wpd->taa_sample >= wpd->taa_sample_len; if (wpd->taa_sample == 0) { /* In playback mode, we are sure the next redraw will not use the same viewmatrix. * In this case no need to save the depth buffer. */ @@ -432,9 +434,11 @@ void workbench_antialiasing_draw_pass(WORKBENCH_Data *vedata) } } else { - /* Accumulate result to the TAA buffer. */ - GPU_framebuffer_bind(fbl->antialiasing_fb); - DRW_draw_pass(psl->aa_accum_ps); + if (!taa_finished) { + /* Accumulate result to the TAA buffer. */ + GPU_framebuffer_bind(fbl->antialiasing_fb); + DRW_draw_pass(psl->aa_accum_ps); + } /* Copy back the saved depth buffer for correct overlays. */ GPU_framebuffer_blit(fbl->antialiasing_fb, 0, dfbl->default_fb, 0, GPU_DEPTH_BIT); if (workbench_in_front_history_needed(vedata)) { @@ -442,10 +446,10 @@ void workbench_antialiasing_draw_pass(WORKBENCH_Data *vedata) } } - if (!DRW_state_is_image_render() || wpd->taa_sample + 1 == wpd->taa_sample_len) { + if (!DRW_state_is_image_render() || last_sample) { /* After a certain point SMAA is no longer necessary. */ wpd->smaa_mix_factor = 1.0f - clamp_f(wpd->taa_sample / 4.0f, 0.0f, 1.0f); - wpd->taa_sample_inv = 1.0f / (wpd->taa_sample + 1); + wpd->taa_sample_inv = 1.0f / min_ii(wpd->taa_sample + 1, wpd->taa_sample_len); if (wpd->smaa_mix_factor > 0.0f) { GPU_framebuffer_bind(fbl->smaa_edge_fb); @@ -459,7 +463,9 @@ void workbench_antialiasing_draw_pass(WORKBENCH_Data *vedata) DRW_draw_pass(psl->aa_resolve_ps); } - wpd->taa_sample++; + if (!taa_finished) { + wpd->taa_sample++; + } if (!DRW_state_is_image_render() && wpd->taa_sample < wpd->taa_sample_len) { DRW_viewport_request_redraw(); diff --git a/source/blender/draw/engines/workbench/workbench_effect_dof.c b/source/blender/draw/engines/workbench/workbench_effect_dof.c index 9716ccd4b44..e13f7bfdd92 100644 --- a/source/blender/draw/engines/workbench/workbench_effect_dof.c +++ b/source/blender/draw/engines/workbench/workbench_effect_dof.c @@ -326,7 +326,7 @@ void workbench_dof_cache_init(WORKBENCH_Data *vedata) /* We reuse the same noise texture. Ensure it is up to date. */ workbench_cavity_samples_ubo_ensure(wpd); - float offset = wpd->taa_sample / wpd->taa_sample_len; + float offset = wpd->taa_sample / (float)max_ii(1, wpd->taa_sample_len); DRWShadingGroup *grp = DRW_shgroup_create(blur1_sh, psl->dof_blur1_ps); DRW_shgroup_uniform_block(grp, "dofSamplesBlock", wpd->vldata->dof_sample_ubo); DRW_shgroup_uniform_texture(grp, "noiseTex", wpd->vldata->cavity_jitter_tx); diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c index 45f14c52ec5..a2abecb679f 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.c +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -267,7 +267,7 @@ DRWShadingGroup *workbench_image_setup_ex(WORKBENCH_PrivateData *wpd, } if (tex == NULL) { - printf("Image not foudn\n"); + printf("Image not found\n"); tex = wpd->dummy_image_tx; } diff --git a/source/blender/draw/engines/workbench/workbench_render.c b/source/blender/draw/engines/workbench/workbench_render.c index 5a315e80a47..9e66bcb07f4 100644 --- a/source/blender/draw/engines/workbench/workbench_render.c +++ b/source/blender/draw/engines/workbench/workbench_render.c @@ -52,14 +52,12 @@ static void workbench_render_cache(void *vedata, static void workbench_render_matrices_init(RenderEngine *engine, Depsgraph *depsgraph) { /* TODO(sergey): Shall render hold pointer to an evaluated camera instead? */ - Scene *scene = DEG_get_evaluated_scene(depsgraph); struct Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re)); - float frame = BKE_scene_frame_get(scene); /* Set the persective, view and window matrix. */ float winmat[4][4], viewmat[4][4], viewinv[4][4]; - RE_GetCameraWindow(engine->re, ob_camera_eval, frame, winmat); + RE_GetCameraWindow(engine->re, ob_camera_eval, winmat); RE_GetCameraModelMatrix(engine->re, ob_camera_eval, viewinv); invert_m4_m4(viewmat, viewinv); diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c index 54e745102f0..f54fef63c82 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.c +++ b/source/blender/draw/intern/draw_cache_extract_mesh.c @@ -191,7 +191,17 @@ static MeshRenderData *mesh_render_data_create(Mesh *me, else { mr->me = me; mr->edit_bmesh = NULL; - mr->extract_type = MR_EXTRACT_MESH; + + bool use_mapped = mr->me && !mr->me->runtime.is_original; + if (use_mapped) { + mr->v_origindex = CustomData_get_layer(&mr->me->vdata, CD_ORIGINDEX); + mr->e_origindex = CustomData_get_layer(&mr->me->edata, CD_ORIGINDEX); + mr->p_origindex = CustomData_get_layer(&mr->me->pdata, CD_ORIGINDEX); + + use_mapped = (mr->v_origindex || mr->e_origindex || mr->p_origindex); + } + + mr->extract_type = use_mapped ? MR_EXTRACT_MAPPED : MR_EXTRACT_MESH; } if (mr->extract_type != MR_EXTRACT_BMESH) { @@ -924,10 +934,14 @@ static void extract_lines_paint_mask_loop_mesh(const MeshRenderData *mr, void *_data) { MeshExtract_LinePaintMask_Data *data = (MeshExtract_LinePaintMask_Data *)_data; - if (!(mr->use_hide && (mpoly->flag & ME_HIDE))) { + const int edge_idx = mloop->e; + const MEdge *medge = &mr->medge[edge_idx]; + if (!((mr->use_hide && (medge->flag & ME_HIDE)) || + ((mr->extract_type == MR_EXTRACT_MAPPED) && + (mr->e_origindex[edge_idx] == ORIGINDEX_NONE)))) { + int loopend = mpoly->totloop + mpoly->loopstart - 1; int other_loop = (l == loopend) ? mpoly->loopstart : (l + 1); - int edge_idx = mloop->e; if (mpoly->flag & ME_FACE_SEL) { if (BLI_BITMAP_TEST_AND_SET_ATOMIC(data->select_map, edge_idx)) { /* Hide edge as it has more than 2 selected loop. */ @@ -945,6 +959,9 @@ static void extract_lines_paint_mask_loop_mesh(const MeshRenderData *mr, } } } + else { + GPU_indexbuf_set_line_restart(&data->elb, edge_idx); + } } static void extract_lines_paint_mask_finish(const MeshRenderData *UNUSED(mr), void *ibo, @@ -1500,7 +1517,8 @@ static void extract_pos_nor_loop_mesh(const MeshRenderData *mr, copy_v3_v3(vert->pos, mvert->co); vert->nor = data->packed_nor[mloop->v]; /* Flag for paint mode overlay. */ - if (mpoly->flag & ME_HIDE || mvert->flag & ME_HIDE) { + if (mpoly->flag & ME_HIDE || mvert->flag & ME_HIDE || + ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex[mloop->v] == ORIGINDEX_NONE))) { vert->nor.w = -1; } else if (mvert->flag & SELECT) { @@ -1617,24 +1635,27 @@ static void extract_lnor_hq_loop_bmesh(const MeshRenderData *mr, int l, BMLoop * static void extract_lnor_hq_loop_mesh( const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *data) { + gpuHQNor *lnor_data = &((gpuHQNor *)data)[l]; if (mr->loop_normals) { - normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, mr->loop_normals[l]); + normal_float_to_short_v3(&lnor_data->x, mr->loop_normals[l]); } else if (mpoly->flag & ME_SMOOTH) { - copy_v3_v3_short(&((gpuHQNor *)data)[l].x, mr->mvert[mloop->v].no); + copy_v3_v3_short(&lnor_data->x, mr->mvert[mloop->v].no); } else { - normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, mr->poly_normals[p]); + normal_float_to_short_v3(&lnor_data->x, mr->poly_normals[p]); } + /* Flag for paint mode overlay. */ - if (mpoly->flag & ME_HIDE) { - ((gpuHQNor *)data)[l].w = -1; + if (mpoly->flag & ME_HIDE || + (mr->extract_type == MR_EXTRACT_MAPPED && mr->v_origindex[mloop->v] == ORIGINDEX_NONE)) { + lnor_data->w = -1; } else if (mpoly->flag & ME_FACE_SEL) { - ((gpuHQNor *)data)[l].w = 1; + lnor_data->w = 1; } else { - ((gpuHQNor *)data)[l].w = 0; + lnor_data->w = 0; } } @@ -1690,24 +1711,27 @@ static void extract_lnor_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loo static void extract_lnor_loop_mesh( const MeshRenderData *mr, int l, const MLoop *mloop, int p, const MPoly *mpoly, void *data) { + GPUPackedNormal *lnor_data = &((GPUPackedNormal *)data)[l]; if (mr->loop_normals) { - ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(mr->loop_normals[l]); + *lnor_data = GPU_normal_convert_i10_v3(mr->loop_normals[l]); } else if (mpoly->flag & ME_SMOOTH) { - ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_s3(mr->mvert[mloop->v].no); + *lnor_data = GPU_normal_convert_i10_s3(mr->mvert[mloop->v].no); } else { - ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(mr->poly_normals[p]); + *lnor_data = GPU_normal_convert_i10_v3(mr->poly_normals[p]); } + /* Flag for paint mode overlay. */ - if (mpoly->flag & ME_HIDE) { - ((GPUPackedNormal *)data)[l].w = -1; + if (mpoly->flag & ME_HIDE || + (mr->extract_type == MR_EXTRACT_MAPPED && mr->v_origindex[mloop->v] == ORIGINDEX_NONE)) { + lnor_data->w = -1; } else if (mpoly->flag & ME_FACE_SEL) { - ((GPUPackedNormal *)data)[l].w = 1; + lnor_data->w = 1; } else { - ((GPUPackedNormal *)data)[l].w = 0; + lnor_data->w = 0; } } @@ -3890,7 +3914,8 @@ static void extract_fdots_nor_finish(const MeshRenderData *mr, void *buf, void * for (int f = 0; f < mr->poly_len; f++) { efa = BM_face_at_index(mr->bm, f); const bool is_face_hidden = BM_elem_flag_test(efa, BM_ELEM_HIDDEN); - if (is_face_hidden) { + if (is_face_hidden || + (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex[f] == ORIGINDEX_NONE)) { nor[f] = GPU_normal_convert_i10_v3(invalid_normal); nor[f].w = NOR_AND_FLAG_HIDDEN; } @@ -3906,7 +3931,9 @@ static void extract_fdots_nor_finish(const MeshRenderData *mr, void *buf, void * else { for (int f = 0; f < mr->poly_len; f++) { efa = bm_original_face_get(mr, f); - if (!efa || BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + const bool is_face_hidden = efa && BM_elem_flag_test(efa, BM_ELEM_HIDDEN); + if (is_face_hidden || + (mr->extract_type == MR_EXTRACT_MAPPED && mr->p_origindex[f] == ORIGINDEX_NONE)) { nor[f] = GPU_normal_convert_i10_v3(invalid_normal); nor[f].w = NOR_AND_FLAG_HIDDEN; } diff --git a/source/blender/draw/intern/draw_cache_impl_displist.c b/source/blender/draw/intern/draw_cache_impl_displist.c index 04889463447..f1e5dbcc3cb 100644 --- a/source/blender/draw/intern/draw_cache_impl_displist.c +++ b/source/blender/draw/intern/draw_cache_impl_displist.c @@ -406,7 +406,7 @@ static void displist_vertbuf_attr_set_tri_pos_nor_uv(GPUVertBufRaw *pos_step, } } -#define SURFACE_QUAD_ITER_START(dl) \ +#define SURFACE_QUAD_ITER_BEGIN(dl) \ { \ uint quad[4]; \ int quad_index = 0; \ @@ -446,8 +446,7 @@ static void displist_surf_fnors_ensure(const DispList *dl, float (**fnors)[3]) float(*nor_flat)[3] = MEM_mallocN(sizeof(float) * 3 * u_len * v_len, __func__); *fnors = nor_flat; - SURFACE_QUAD_ITER_START(dl) - { + SURFACE_QUAD_ITER_BEGIN (dl) { normal_quad_v3(*nor_flat, verts[quad[0]], verts[quad[1]], verts[quad[2]], verts[quad[3]]); nor_flat++; } @@ -570,8 +569,7 @@ void DRW_displist_vertbuf_create_loop_pos_and_nor_and_uv_and_tan(ListBase *lb, BKE_displist_tangent_calc(dl, fnors, &tangents); } - SURFACE_QUAD_ITER_START(dl) - { + SURFACE_QUAD_ITER_BEGIN (dl) { if (vbo_uv) { surf_uv_quad(dl, quad, uv); } diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c index 349eb6b00ae..3cbcdc1ede6 100644 --- a/source/blender/draw/intern/draw_cache_impl_gpencil.c +++ b/source/blender/draw/intern/draw_cache_impl_gpencil.c @@ -62,8 +62,6 @@ typedef struct GpencilBatchCache { /** Cache is dirty */ bool is_dirty; - /** Edit mode flag */ - bool is_editmode; /** Last cache frame */ int cache_frame; } GpencilBatchCache; @@ -71,21 +69,17 @@ typedef struct GpencilBatchCache { static bool gpencil_batch_cache_valid(GpencilBatchCache *cache, bGPdata *gpd, int cfra) { bool valid = true; + if (cache == NULL) { return false; } - cache->is_editmode = GPENCIL_ANY_EDIT_MODE(gpd); if (cfra != cache->cache_frame) { valid = false; } else if (gpd->flag & GP_DATA_CACHE_IS_DIRTY) { valid = false; } - else if (gpd->flag & GP_DATA_PYTHON_UPDATED) { - gpd->flag &= ~GP_DATA_PYTHON_UPDATED; - valid = false; - } else if (cache->is_dirty) { valid = false; } @@ -106,7 +100,6 @@ static GpencilBatchCache *gpencil_batch_cache_init(Object *ob, int cfra) memset(cache, 0, sizeof(*cache)); } - cache->is_editmode = GPENCIL_ANY_EDIT_MODE(gpd); cache->is_dirty = true; cache->cache_frame = cfra; return cache; @@ -542,9 +535,8 @@ static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_stroke, bool do_ /* Get origin to reproject points. */ float origin[3]; - bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); ToolSettings *ts = scene->toolsettings; - ED_gpencil_drawing_reference_get(scene, ob, gpl, ts->gpencil_v3d_align, origin); + ED_gpencil_drawing_reference_get(scene, ob, ts->gpencil_v3d_align, origin); for (int i = 0; i < vert_len; i++) { ED_gpencil_tpoint_to_point(region, origin, &tpoints[i], &gps->points[i]); diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index aedc86c2eae..fb0423a87a6 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -436,8 +436,7 @@ static void mesh_batch_cache_check_vertex_group(MeshBatchCache *cache, const struct DRW_MeshWeightState *wstate) { if (!drw_mesh_weight_state_compare(&cache->weight_state, wstate)) { - FOREACH_MESH_BUFFER_CACHE(cache, mbufcache) - { + FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) { GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.weights); } GPU_BATCH_CLEAR_SAFE(cache->batch.surface_weights); @@ -460,8 +459,7 @@ static void mesh_batch_cache_discard_shaded_batches(MeshBatchCache *cache) static void mesh_batch_cache_discard_shaded_tri(MeshBatchCache *cache) { - FOREACH_MESH_BUFFER_CACHE(cache, mbufcache) - { + FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) { GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.pos_nor); GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.uv); GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.tan); @@ -478,8 +476,7 @@ static void mesh_batch_cache_discard_shaded_tri(MeshBatchCache *cache) static void mesh_batch_cache_discard_uvedit(MeshBatchCache *cache) { - FOREACH_MESH_BUFFER_CACHE(cache, mbufcache) - { + FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) { GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.stretch_angle); GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.stretch_area); GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.uv); @@ -517,8 +514,7 @@ static void mesh_batch_cache_discard_uvedit(MeshBatchCache *cache) static void mesh_batch_cache_discard_uvedit_select(MeshBatchCache *cache) { - FOREACH_MESH_BUFFER_CACHE(cache, mbufcache) - { + FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) { GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.edituv_data); GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.fdots_edituv_data); GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.edituv_tris); @@ -544,8 +540,7 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode) } switch (mode) { case BKE_MESH_BATCH_DIRTY_SELECT: - FOREACH_MESH_BUFFER_CACHE(cache, mbufcache) - { + FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) { GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.edit_data); GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.fdots_nor); } @@ -568,8 +563,7 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode) case BKE_MESH_BATCH_DIRTY_SELECT_PAINT: /* Paint mode selection flag is packed inside the nor attrib. * Note that it can be slow if auto smooth is enabled. (see T63946) */ - FOREACH_MESH_BUFFER_CACHE(cache, mbufcache) - { + FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) { GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.lines_paint_mask); GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.pos_nor); GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.lnor); @@ -595,8 +589,7 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode) mesh_batch_cache_discard_uvedit(cache); break; case BKE_MESH_BATCH_DIRTY_UVEDIT_SELECT: - FOREACH_MESH_BUFFER_CACHE(cache, mbufcache) - { + FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) { GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.edituv_data); GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.fdots_edituv_data); } @@ -619,8 +612,7 @@ static void mesh_batch_cache_clear(Mesh *me) if (!cache) { return; } - FOREACH_MESH_BUFFER_CACHE(cache, mbufcache) - { + FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) { GPUVertBuf **vbos = (GPUVertBuf **)&mbufcache->vbo; GPUIndexBuf **ibos = (GPUIndexBuf **)&mbufcache->ibo; for (int i = 0; i < sizeof(mbufcache->vbo) / sizeof(void *); i++) { @@ -1060,8 +1052,7 @@ void DRW_mesh_batch_cache_create_requested( * index ranges initialized. So discard ibo.tris in order to recreate it. * This needs to happen before saved_elem_ranges is populated. */ if ((batch_requested & MBC_SURF_PER_MAT) != 0 && (cache->batch_ready & MBC_SURF_PER_MAT) == 0) { - FOREACH_MESH_BUFFER_CACHE(cache, mbuffercache) - { + FOREACH_MESH_BUFFER_CACHE (cache, mbuffercache) { GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.tris); } /* Clear all batches that reference ibo.tris. */ @@ -1098,8 +1089,7 @@ void DRW_mesh_batch_cache_create_requested( * material. */ bool cd_overlap = mesh_cd_layers_type_overlap(cache->cd_used, cache->cd_needed); if (cd_overlap == false) { - FOREACH_MESH_BUFFER_CACHE(cache, mbuffercache) - { + FOREACH_MESH_BUFFER_CACHE (cache, mbuffercache) { if ((cache->cd_used.uv & cache->cd_needed.uv) != cache->cd_needed.uv) { GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.uv); cd_uv_update = true; @@ -1145,8 +1135,7 @@ void DRW_mesh_batch_cache_create_requested( const bool is_uvsyncsel = ts && (ts->uv_flag & UV_SYNC_SELECTION); if (cd_uv_update || (cache->is_uvsyncsel != is_uvsyncsel)) { cache->is_uvsyncsel = is_uvsyncsel; - FOREACH_MESH_BUFFER_CACHE(cache, mbuffercache) - { + FOREACH_MESH_BUFFER_CACHE (cache, mbuffercache) { GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.edituv_data); GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.fdots_uv); GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.edituv_tris); diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c index 3055e45a4a5..048adccc4e6 100644 --- a/source/blender/draw/intern/draw_hair.c +++ b/source/blender/draw/intern/draw_hair.c @@ -168,6 +168,10 @@ static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object, BLI_assert(0); } + if (shgrp == NULL) { + return NULL; + } + /* TODO optimize this. Only bind the ones GPUMaterial needs. */ for (int i = 0; i < hair_cache->num_uv_layers; i++) { for (int n = 0; n < MAX_LAYER_NAME_CT && hair_cache->uv_layer_names[i][n][0] != '\0'; n++) { diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index 5a92058001f..94a3e9e8343 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -884,6 +884,11 @@ static float sculpt_debug_colors[9][4] = { static void sculpt_draw_cb(DRWSculptCallbackData *scd, GPU_PBVH_Buffers *buffers) { + + if (scd->use_mask && !GPU_pbvh_buffers_has_overlays(buffers)) { + return; + } + GPUBatch *geom = GPU_pbvh_buffers_batch_get(buffers, scd->fast_mode, scd->use_wire); short index = 0; diff --git a/source/blender/draw/intern/shaders/common_smaa_lib.glsl b/source/blender/draw/intern/shaders/common_smaa_lib.glsl index 45d9f54d943..a3f592ba5dd 100644 --- a/source/blender/draw/intern/shaders/common_smaa_lib.glsl +++ b/source/blender/draw/intern/shaders/common_smaa_lib.glsl @@ -529,8 +529,9 @@ # define SMAATexturePass2D(tex) tex # define SMAASampleLevelZero(tex, coord) tex2Dlod(tex, float4(coord, 0.0, 0.0)) # define SMAASampleLevelZeroPoint(tex, coord) tex2Dlod(tex, float4(coord, 0.0, 0.0)) -# define SMAASampleLevelZeroOffset(tex, coord, offset) \ - tex2Dlod(tex, float4(coord + offset * SMAA_RT_METRICS.xy, 0.0, 0.0)) +/* clang-format off */ +# define SMAASampleLevelZeroOffset(tex, coord, offset) tex2Dlod(tex, float4(coord + offset * SMAA_RT_METRICS.xy, 0.0, 0.0)) +/* clang-format on */ # define SMAASample(tex, coord) tex2D(tex, coord) # define SMAASamplePoint(tex, coord) tex2D(tex, coord) # define SMAASampleOffset(tex, coord, offset) tex2D(tex, coord + offset * SMAA_RT_METRICS.xy) @@ -554,8 +555,9 @@ SamplerState PointSampler # define SMAATexturePass2D(tex) tex # define SMAASampleLevelZero(tex, coord) tex.SampleLevel(LinearSampler, coord, 0) # define SMAASampleLevelZeroPoint(tex, coord) tex.SampleLevel(PointSampler, coord, 0) -# define SMAASampleLevelZeroOffset(tex, coord, offset) \ - tex.SampleLevel(LinearSampler, coord, 0, offset) +/* clang-format off */ +# define SMAASampleLevelZeroOffset(tex, coord, offset) tex.SampleLevel(LinearSampler, coord, 0, offset) +/* clang-format on */ # define SMAASample(tex, coord) tex.Sample(LinearSampler, coord) # define SMAASamplePoint(tex, coord) tex.Sample(PointSampler, coord) # define SMAASampleOffset(tex, coord, offset) tex.Sample(LinearSampler, coord, offset) @@ -597,10 +599,11 @@ SamplerState PointSampler # define bool4 bvec4 #endif -#if !defined(SMAA_HLSL_3) && !defined(SMAA_HLSL_4) && !defined(SMAA_HLSL_4_1) && \ - !defined(SMAA_GLSL_3) && !defined(SMAA_GLSL_4) && !defined(SMAA_CUSTOM_SL) +/* clang-format off */ +#if !defined(SMAA_HLSL_3) && !defined(SMAA_HLSL_4) && !defined(SMAA_HLSL_4_1) && !defined(SMAA_GLSL_3) && !defined(SMAA_GLSL_4) && !defined(SMAA_CUSTOM_SL) # error you must define the shading language: SMAA_HLSL_*, SMAA_GLSL_* or SMAA_CUSTOM_SL #endif +/* clang-format on */ //----------------------------------------------------------------------------- // Misc functions diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 77399880b8d..96fd2e94a5e 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -441,12 +441,45 @@ static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, flo min_coord = min_ff(min_coord, prev_bezt->vec[1][1]); } else { - float step_size = (bezt->vec[1][0] - prev_bezt->vec[1][0]) / resol; - for (int j = 0; j <= resol; j++) { - float eval_time = prev_bezt->vec[1][0] + step_size * j; - float eval_value = evaluate_fcurve_only_curve(fcu, eval_time); - max_coord = max_ff(max_coord, eval_value); - min_coord = min_ff(min_coord, eval_value); + if (!ELEM(prev_bezt->ipo, BEZT_IPO_BACK, BEZT_IPO_ELASTIC)) { + /* Calculate min/max using bezier forward differencing. */ + float data[120]; + float v1[2], v2[2], v3[2], v4[2]; + + v1[0] = prev_bezt->vec[1][0]; + v1[1] = prev_bezt->vec[1][1]; + v2[0] = prev_bezt->vec[2][0]; + v2[1] = prev_bezt->vec[2][1]; + + v3[0] = bezt->vec[0][0]; + v3[1] = bezt->vec[0][1]; + v4[0] = bezt->vec[1][0]; + v4[1] = bezt->vec[1][1]; + + correct_bezpart(v1, v2, v3, v4); + + BKE_curve_forward_diff_bezier( + v1[0], v2[0], v3[0], v4[0], data, resol, sizeof(float) * 3); + BKE_curve_forward_diff_bezier( + v1[1], v2[1], v3[1], v4[1], data + 1, resol, sizeof(float) * 3); + + for (int j = 0; j <= resol; ++j) { + const float *fp = &data[j * 3]; + max_coord = max_ff(max_coord, fp[1]); + min_coord = min_ff(min_coord, fp[1]); + } + } + else { + /* Calculate min/max using full fcurve evaluation. + * [slower than bezier forward differencing but evaluates Back/Elastic interpolation + * as well].*/ + float step_size = (bezt->vec[1][0] - prev_bezt->vec[1][0]) / resol; + for (int j = 0; j <= resol; j++) { + float eval_time = prev_bezt->vec[1][0] + step_size * j; + float eval_value = evaluate_fcurve_only_curve(fcu, eval_time); + max_coord = max_ff(max_coord, eval_value); + min_coord = min_ff(min_coord, eval_value); + } } } } @@ -515,7 +548,7 @@ float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short flag return 1.0f; } -static bool find_prev_next_keyframes(struct bContext *C, int *nextfra, int *prevfra) +static bool find_prev_next_keyframes(struct bContext *C, int *r_nextfra, int *r_prevfra) { Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); @@ -594,17 +627,17 @@ static bool find_prev_next_keyframes(struct bContext *C, int *nextfra, int *prev /* any success? */ if (doneprev || donenext) { if (doneprev) { - *prevfra = cfraprev; + *r_prevfra = cfraprev; } else { - *prevfra = CFRA - (cfranext - CFRA); + *r_prevfra = CFRA - (cfranext - CFRA); } if (donenext) { - *nextfra = cfranext; + *r_nextfra = cfranext; } else { - *nextfra = CFRA + (CFRA - cfraprev); + *r_nextfra = CFRA + (CFRA - cfraprev); } return true; diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 2215021ce1a..8b0e9b22ce8 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -197,7 +197,7 @@ int ED_markers_find_nearest_marker_time(ListBase *markers, float x) return (nearest) ? (nearest->frame) : round_fl_to_int(x); } -void ED_markers_get_minmax(ListBase *markers, short sel, float *first, float *last) +void ED_markers_get_minmax(ListBase *markers, short sel, float *r_first, float *r_last) { TimeMarker *marker; float min, max; @@ -205,8 +205,8 @@ void ED_markers_get_minmax(ListBase *markers, short sel, float *first, float *la /* sanity check */ // printf("markers = %p - %p, %p\n", markers, markers->first, markers->last); if (ELEM(NULL, markers, markers->first, markers->last)) { - *first = 0.0f; - *last = 0.0f; + *r_first = 0.0f; + *r_last = 0.0f; return; } @@ -224,8 +224,8 @@ void ED_markers_get_minmax(ListBase *markers, short sel, float *first, float *la } /* set the min/max values */ - *first = min; - *last = max; + *r_first = min; + *r_last = max; } /** @@ -235,6 +235,9 @@ void ED_markers_get_minmax(ListBase *markers, short sel, float *first, float *la static bool ED_operator_markers_region_active(bContext *C) { ScrArea *sa = CTX_wm_area(C); + if (sa == NULL) { + return false; + } switch (sa->spacetype) { case SPACE_ACTION: { diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c index e87040279af..1105633f47e 100644 --- a/source/blender/editors/armature/armature_add.c +++ b/source/blender/editors/armature/armature_add.c @@ -742,7 +742,7 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op) } } - /* Find the selected bones and duplicate them as needed, with mirrored name */ + /* Find the selected bones and duplicate them as needed, with mirrored name. */ for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) { if (EBONE_VISIBLE(arm, ebone_iter) && (ebone_iter->flag & BONE_SELECTED) && @@ -765,7 +765,7 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op) } } - /* Run through the list and fix the pointers */ + /* Run through the list and fix the pointers. */ for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe; ebone_iter = ebone_iter->next) { if (ebone_iter->temp.ebone) { @@ -1116,7 +1116,7 @@ static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op) ED_armature_edit_deselect_all(obedit); - /* Create a bone */ + /* Create a bone. */ bone = ED_armature_ebone_add(obedit->data, name); copy_v3_v3(bone->head, curs); diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c index 4285c7779d7..9a640952253 100644 --- a/source/blender/editors/armature/armature_edit.c +++ b/source/blender/editors/armature/armature_edit.c @@ -61,7 +61,10 @@ #include "armature_intern.h" -/* ************************** Object Tools Exports ******************************* */ +/* -------------------------------------------------------------------- */ +/** \name Object Tools Public API + * \{ */ + /* NOTE: these functions are exported to the Object module to be called from the tools there */ /** @@ -178,7 +181,11 @@ void ED_armature_origin_set( } } -/* ********************************* Roll ******************************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Bone Roll Calculate Operator + * \{ */ /* adjust bone roll to align Z axis with vector * vec is in local space and is normalized @@ -549,7 +556,11 @@ void ARMATURE_OT_roll_clear(wmOperatorType *ot) DEG2RADF(360.0f)); } -/* ******************************** Chain-Based Tools ********************************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Chain-Based Tool Utilities + * \{ */ /* temporary data-structure for merge/fill bones */ typedef struct EditBonePoint { @@ -616,7 +627,11 @@ static void chains_find_tips(ListBase *edbo, ListBase *list) } } -/* --------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Fill Operator + * \{ */ static void fill_add_joint(EditBone *ebo, short eb_tail, ListBase *points) { @@ -871,216 +886,15 @@ void ARMATURE_OT_fill(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* --------------------- */ - -/* this function merges between two bones, removes them and those in-between, - * and adjusts the parent relationships for those in-between - */ -static void bones_merge( - Object *obedit, EditBone *start, EditBone *end, EditBone *endchild, ListBase *chains) -{ - bArmature *arm = obedit->data; - EditBone *ebo, *ebone, *newbone; - LinkData *chain; - float head[3], tail[3]; - - /* check if same bone */ - if (start == end) { - if (G.debug & G_DEBUG) { - printf("Error: same bone!\n"); - printf("\tstart = %s, end = %s\n", start->name, end->name); - } - } - - /* step 1: add a new bone - * - head = head/tail of start (default head) - * - tail = head/tail of end (default tail) - * - parent = parent of start - */ - if ((start->flag & BONE_TIPSEL) && (start->flag & BONE_SELECTED) == 0) { - copy_v3_v3(head, start->tail); - } - else { - copy_v3_v3(head, start->head); - } - if ((end->flag & BONE_ROOTSEL) && (end->flag & BONE_SELECTED) == 0) { - copy_v3_v3(tail, end->head); - } - else { - copy_v3_v3(tail, end->tail); - } - newbone = add_points_bone(obedit, head, tail); - newbone->parent = start->parent; - - /* TODO, copy more things to the new bone */ - newbone->flag = start->flag & (BONE_HINGE | BONE_NO_DEFORM | BONE_NO_CYCLICOFFSET | - BONE_NO_LOCAL_LOCATION | BONE_DONE); - - newbone->inherit_scale_mode = start->inherit_scale_mode; - - /* Step 2a: reparent any side chains which may be parented to any bone in the chain - * of bones to merge - potentially several tips for side chains leading to some tree exist. - */ - for (chain = chains->first; chain; chain = chain->next) { - /* Traverse down chain until we hit the bottom or if we run into the tip of the chain of bones - * we're merging (need to stop in this case to avoid corrupting this chain too!). - */ - for (ebone = chain->data; (ebone) && (ebone != end); ebone = ebone->parent) { - short found = 0; - - /* Check if this bone is parented to one in the merging chain - * ! WATCHIT: must only go check until end of checking chain - */ - for (ebo = end; (ebo) && (ebo != start->parent); ebo = ebo->parent) { - /* side-chain found? --> remap parent to new bone, then we're done with this chain :) */ - if (ebone->parent == ebo) { - ebone->parent = newbone; - found = 1; - break; - } - } - - /* carry on to the next tip now */ - if (found) { - break; - } - } - } - - /* step 2b: parent child of end to newbone (child from this chain) */ - if (endchild) { - endchild->parent = newbone; - } - - /* step 3: delete all bones between and including start and end */ - for (ebo = end; ebo; ebo = ebone) { - ebone = (ebo == start) ? (NULL) : (ebo->parent); - bone_free(arm, ebo); - } - - newbone->flag |= (BONE_ROOTSEL | BONE_TIPSEL | BONE_SELECTED); - ED_armature_edit_sync_selection(arm->edbo); -} - -static int armature_merge_exec(bContext *C, wmOperator *op) -{ - ViewLayer *view_layer = CTX_data_view_layer(C); - const short type = RNA_enum_get(op->ptr, "type"); - - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &objects_len); - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - bArmature *arm = obedit->data; - - /* for now, there's only really one type of merging that's performed... */ - if (type == 1) { - /* go down chains, merging bones */ - ListBase chains = {NULL, NULL}; - LinkData *chain, *nchain; - EditBone *ebo; - - armature_tag_select_mirrored(arm); - - /* get chains (ends on chains) */ - chains_find_tips(arm->edbo, &chains); - if (BLI_listbase_is_empty(&chains)) { - continue; - } - - /* each 'chain' is the last bone in the chain (with no children) */ - for (chain = chains.first; chain; chain = nchain) { - EditBone *bstart = NULL, *bend = NULL; - EditBone *bchild = NULL, *child = NULL; - - /* temporarily remove chain from list of chains */ - nchain = chain->next; - BLI_remlink(&chains, chain); - - /* only consider bones that are visible and selected */ - for (ebo = chain->data; ebo; child = ebo, ebo = ebo->parent) { - /* check if visible + selected */ - if (EBONE_VISIBLE(arm, ebo) && ((ebo->flag & BONE_CONNECTED) || (ebo->parent == NULL)) && - (ebo->flag & BONE_SELECTED)) { - /* set either end or start (end gets priority, unless it is already set) */ - if (bend == NULL) { - bend = ebo; - bchild = child; - } - else { - bstart = ebo; - } - } - else { - /* chain is broken... merge any continuous segments then clear */ - if (bstart && bend) { - bones_merge(obedit, bstart, bend, bchild, &chains); - } - - bstart = NULL; - bend = NULL; - bchild = NULL; - } - } - - /* merge from bstart to bend if something not merged */ - if (bstart && bend) { - bones_merge(obedit, bstart, bend, bchild, &chains); - } - - /* put back link */ - BLI_insertlinkbefore(&chains, nchain, chain); - } - - armature_tag_unselect(arm); - - BLI_freelistN(&chains); - } - - /* updates */ - ED_armature_edit_sync_selection(arm->edbo); - ED_armature_edit_refresh_layer_used(arm); - WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit); - DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE); - } - MEM_freeN(objects); - - return OPERATOR_FINISHED; -} - -void ARMATURE_OT_merge(wmOperatorType *ot) -{ - static const EnumPropertyItem merge_types[] = { - {1, "WITHIN_CHAIN", 0, "Within Chains", ""}, - {0, NULL, 0, NULL, NULL}, - }; - - /* identifiers */ - ot->name = "Merge Bones"; - ot->idname = "ARMATURE_OT_merge"; - ot->description = "Merge continuous chains of selected bones"; - - /* callbacks */ - ot->invoke = WM_menu_invoke; - ot->exec = armature_merge_exec; - ot->poll = ED_operator_editarmature; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - ot->prop = RNA_def_enum(ot->srna, "type", merge_types, 0, "Type", ""); -} - -/* --------------------- */ +/** \} */ -/* Switch Direction operator: +/* -------------------------------------------------------------------- */ +/** \name Switch Direction Operator + * * Currently, this does not use context loops, as context loops do not make it * easy to retrieve any hierarchical/chain relationships which are necessary for * this to be done easily. - */ + * \{ */ /* helper to clear BONE_TRANSFORM flags */ static void armature_clear_swap_done_flags(bArmature *arm) @@ -1210,7 +1024,11 @@ void ARMATURE_OT_switch_direction(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ********************************* Align ******************************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Align Operator + * \{ */ /* helper to fix a ebone position if its parent has moved due to alignment*/ static void fix_connected_bone(EditBone *ebone) @@ -1354,7 +1172,11 @@ void ARMATURE_OT_align(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ********************************* Split ******************************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Split Operator + * \{ */ static int armature_split_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -1400,7 +1222,11 @@ void ARMATURE_OT_split(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ********************************* Delete ******************************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete Operator + * \{ */ static bool armature_delete_ebone_cb(const char *bone_name, void *arm_p) { @@ -1658,7 +1484,11 @@ void ARMATURE_OT_dissolve(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ********************************* Show/Hide ******************************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Hide Operator + * \{ */ static int armature_hide_exec(bContext *C, wmOperator *op) { @@ -1719,6 +1549,12 @@ void ARMATURE_OT_hide(wmOperatorType *ot) RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Reveal Operator + * \{ */ + static int armature_reveal_exec(bContext *C, wmOperator *op) { ViewLayer *view_layer = CTX_data_view_layer(C); @@ -1771,3 +1607,5 @@ void ARMATURE_OT_reveal(wmOperatorType *ot) RNA_def_boolean(ot->srna, "select", true, "Select", ""); } + +/** \} */ diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h index fa562ab0f44..37f0c7197a9 100644 --- a/source/blender/editors/armature/armature_intern.h +++ b/source/blender/editors/armature/armature_intern.h @@ -59,6 +59,7 @@ void ARMATURE_OT_select_mirror(struct wmOperatorType *ot); void ARMATURE_OT_select_more(struct wmOperatorType *ot); void ARMATURE_OT_select_less(struct wmOperatorType *ot); void ARMATURE_OT_select_hierarchy(struct wmOperatorType *ot); +void ARMATURE_OT_select_linked_pick(struct wmOperatorType *ot); void ARMATURE_OT_select_linked(struct wmOperatorType *ot); void ARMATURE_OT_select_similar(struct wmOperatorType *ot); void ARMATURE_OT_shortest_path_pick(struct wmOperatorType *ot); @@ -72,7 +73,6 @@ void ARMATURE_OT_hide(struct wmOperatorType *ot); void ARMATURE_OT_reveal(struct wmOperatorType *ot); void ARMATURE_OT_click_extrude(struct wmOperatorType *ot); void ARMATURE_OT_fill(struct wmOperatorType *ot); -void ARMATURE_OT_merge(struct wmOperatorType *ot); void ARMATURE_OT_separate(struct wmOperatorType *ot); void ARMATURE_OT_split(struct wmOperatorType *ot); diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c index a29d0f5f158..b304ce92a54 100644 --- a/source/blender/editors/armature/armature_ops.c +++ b/source/blender/editors/armature/armature_ops.c @@ -56,6 +56,7 @@ void ED_operatortypes_armature(void) WM_operatortype_append(ARMATURE_OT_select_less); WM_operatortype_append(ARMATURE_OT_select_hierarchy); WM_operatortype_append(ARMATURE_OT_select_linked); + WM_operatortype_append(ARMATURE_OT_select_linked_pick); WM_operatortype_append(ARMATURE_OT_select_similar); WM_operatortype_append(ARMATURE_OT_shortest_path_pick); @@ -68,7 +69,6 @@ void ED_operatortypes_armature(void) WM_operatortype_append(ARMATURE_OT_reveal); WM_operatortype_append(ARMATURE_OT_click_extrude); WM_operatortype_append(ARMATURE_OT_fill); - WM_operatortype_append(ARMATURE_OT_merge); WM_operatortype_append(ARMATURE_OT_separate); WM_operatortype_append(ARMATURE_OT_split); diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c index 2c2bf3cd283..4580d2c30ae 100644 --- a/source/blender/editors/armature/armature_relations.c +++ b/source/blender/editors/armature/armature_relations.c @@ -280,7 +280,7 @@ int join_armature_exec(bContext *C, wmOperator *op) float mat[4][4], oimat[4][4]; bool ok = false; - /* Ensure we're not in editmode and that the active object is an armature*/ + /* Ensure we're not in edit-mode and that the active object is an armature. */ if (!ob_active || ob_active->type != OB_ARMATURE) { return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index 21eccd2ca1f..99dcd5bb42b 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -59,7 +59,9 @@ #define EBONE_PREV_FLAG_GET(ebone) ((void)0, (ebone)->temp.i) #define EBONE_PREV_FLAG_SET(ebone, val) ((ebone)->temp.i = val) -/* **************** PoseMode & EditMode Selection Buffer Queries *************************** */ +/* -------------------------------------------------------------------- */ +/** \name Select Buffer Queries for PoseMode & EditMode + * \{ */ Base *ED_armature_base_and_ebone_from_select_buffer(Base **bases, uint bases_len, @@ -293,104 +295,245 @@ void *get_nearest_bone(bContext *C, const int xy[2], bool findunsel, Base **r_ba return NULL; } -/* **************** EditMode stuff ********************** */ +/** \} */ -static int armature_select_linked_invoke(bContext *C, wmOperator *op, const wmEvent *event) +/* -------------------------------------------------------------------- */ +/** \name Select Linked Implementation + * + * Shared logic for select linked all/pick. + * + * Use #BONE_DONE flag to select linked. + * \{ */ + +/** + * \param all_forks: Control how chains are stepped over. + * true: select all connected bones traveling up & down forks. + * false: select all parents and all children, but not the children of the root bone. + */ +static bool armature_select_linked_impl(Object *ob, const bool select, const bool all_forks) { - bArmature *arm; - EditBone *bone, *curBone, *next; - const bool sel = !RNA_boolean_get(op->ptr, "deselect"); + bool changed = false; + bArmature *arm = ob->data; - view3d_operator_needs_opengl(C); - BKE_object_update_select_id(CTX_data_main(C)); + /* Implementation note, this flood-fills selected bones with the 'TOUCH' flag, + * even though this is a loop-within a loop, walking up the parent chain only touches new bones. + * Bones that have been touched are skipped, so the complexity is OK. */ - Base *base = NULL; - bone = get_nearest_bone(C, event->mval, true, &base); + enum { + /* Bone has been walked over, it's LINK value can be read. */ + TOUCH = (1 << 0), + /* When TOUCH has been set, this flag can be checked to see if the bone is connected. */ + LINK = (1 << 1), + }; - if (!bone) { - return OPERATOR_CANCELLED; +#define CHECK_PARENT(ebone) \ + (((ebone)->flag & BONE_CONNECTED) && \ + ((ebone)->parent ? EBONE_SELECTABLE(arm, (ebone)->parent) : false)) + + for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) { + ebone->temp.i = 0; } - arm = base->object->data; + /* Select parents. */ + for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) { + if (ebone_iter->temp.i & TOUCH) { + continue; + } + if ((ebone_iter->flag & BONE_DONE) == 0) { + continue; + } + + ebone_iter->temp.i |= TOUCH | LINK; - /* Select parents */ - for (curBone = bone; curBone; curBone = next) { - if ((curBone->flag & BONE_UNSELECTABLE) == 0) { - if (sel) { - curBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + /* We have an un-touched link. */ + for (EditBone *ebone = ebone_iter; ebone; ebone = CHECK_PARENT(ebone) ? ebone->parent : NULL) { + ED_armature_ebone_select_set(ebone, select); + changed = true; + + if (all_forks) { + ebone->temp.i |= (TOUCH | LINK); } else { - curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + ebone->temp.i |= TOUCH; + } + /* Don't walk onto links (messes up 'all_forks' logic). */ + if (ebone->parent && ebone->parent->temp.i & LINK) { + break; } } + } - if (curBone->flag & BONE_CONNECTED) { - next = curBone->parent; + /* Select children. */ + for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) { + /* No need to 'touch' this bone as it won't be walked over when scanning up the chain. */ + if (!CHECK_PARENT(ebone_iter)) { + continue; } - else { - next = NULL; + if (ebone_iter->temp.i & TOUCH) { + continue; } - } - /* Select children */ - while (bone) { - for (curBone = arm->edbo->first; curBone; curBone = next) { - next = curBone->next; - if ((curBone->parent == bone) && (curBone->flag & BONE_UNSELECTABLE) == 0) { - if (curBone->flag & BONE_CONNECTED) { - if (sel) { - curBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - } - else { - curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - } - bone = curBone; - break; - } - else { - bone = NULL; - break; + /* First check if we're marked. */ + EditBone *ebone_touched_parent = NULL; + for (EditBone *ebone = ebone_iter; ebone; ebone = CHECK_PARENT(ebone) ? ebone->parent : NULL) { + if (ebone->temp.i & TOUCH) { + ebone_touched_parent = ebone; + break; + } + ebone->temp.i |= TOUCH; + } + + if ((ebone_touched_parent != NULL) && (ebone_touched_parent->temp.i & LINK)) { + for (EditBone *ebone = ebone_iter; ebone != ebone_touched_parent; ebone = ebone->parent) { + if ((ebone->temp.i & LINK) == 0) { + ebone->temp.i |= LINK; + ED_armature_ebone_select_set(ebone, select); + changed = true; } } } - if (!curBone) { - bone = NULL; + } + +#undef CHECK_PARENT + + if (changed) { + ED_armature_edit_sync_selection(arm->edbo); + DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE); + WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, ob); + } + + return changed; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Linked Operator + * \{ */ + +static int armature_select_linked_exec(bContext *C, wmOperator *op) +{ + const bool all_forks = RNA_boolean_get(op->ptr, "all_forks"); + + bool changed_multi = false; + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( + view_layer, CTX_wm_view3d(C), &objects_len); + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *ob = objects[ob_index]; + bArmature *arm = ob->data; + + bool found = false; + for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) { + if (EBONE_VISIBLE(arm, ebone) && + (ebone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL))) { + ebone->flag |= BONE_DONE; + found = true; + } + else { + ebone->flag &= ~BONE_DONE; + } + } + + if (found) { + if (armature_select_linked_impl(ob, true, all_forks)) { + changed_multi = true; + } } } + MEM_freeN(objects); - ED_outliner_select_sync_from_edit_bone_tag(C); + if (changed_multi) { + ED_outliner_select_sync_from_edit_bone_tag(C); + } + return OPERATOR_FINISHED; +} - ED_armature_edit_sync_selection(arm->edbo); +void ARMATURE_OT_select_linked(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Linked All"; + ot->idname = "ARMATURE_OT_select_linked"; + ot->description = "Select all bones linked by parent/child connections to the current selection"; + + /* api callbacks */ + ot->exec = armature_select_linked_exec; + ot->poll = ED_operator_editarmature; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* Leave disabled by default as this matches pose mode. */ + RNA_def_boolean(ot->srna, "all_forks", 0, "All Forks", "Follow forks in the parents chain"); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Linked (Cursor Pick) Operator + * \{ */ - WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, base->object); - DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE); +static int armature_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + const bool select = !RNA_boolean_get(op->ptr, "deselect"); + const bool all_forks = RNA_boolean_get(op->ptr, "all_forks"); + + view3d_operator_needs_opengl(C); + BKE_object_update_select_id(CTX_data_main(C)); + + Base *base = NULL; + EditBone *ebone_active = get_nearest_bone(C, event->mval, true, &base); + bArmature *arm = base->object->data; + + if (ebone_active == NULL || !EBONE_SELECTABLE(arm, ebone_active)) { + return OPERATOR_CANCELLED; + } + + /* Initialize flags. */ + for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) { + ebone->flag &= ~BONE_DONE; + } + ebone_active->flag |= BONE_DONE; + + if (armature_select_linked_impl(base->object, select, all_forks)) { + ED_outliner_select_sync_from_edit_bone_tag(C); + } return OPERATOR_FINISHED; } -static bool armature_select_linked_poll(bContext *C) +static bool armature_select_linked_pick_poll(bContext *C) { return (ED_operator_view3d_active(C) && ED_operator_editarmature(C)); } -void ARMATURE_OT_select_linked(wmOperatorType *ot) +void ARMATURE_OT_select_linked_pick(wmOperatorType *ot) { /* identifiers */ - ot->name = "Select Connected"; - ot->idname = "ARMATURE_OT_select_linked"; - ot->description = "Select bones related to selected ones by parent/child relationships"; + ot->name = "Select Linked"; + ot->idname = "ARMATURE_OT_select_linked_pick"; + ot->description = "(De)select bones linked by parent/child connections under the mouse cursor"; /* api callbacks */ /* leave 'exec' unset */ - ot->invoke = armature_select_linked_invoke; - ot->poll = armature_select_linked_poll; + ot->invoke = armature_select_linked_pick_invoke; + ot->poll = armature_select_linked_pick_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", ""); + /* Leave disabled by default as this matches pose mode. */ + RNA_def_boolean(ot->srna, "all_forks", 0, "All Forks", "Follow forks in the parents chain"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Buffer Queries EditMode + * \{ */ + /* utility function for get_nearest_editbonepoint */ static int selectbuffer_ret_hits_12(unsigned int *UNUSED(buffer), const int hits12) { @@ -595,6 +738,12 @@ cache_end: return NULL; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Utility Functions + * \{ */ + bool ED_armature_edit_deselect_all(Object *obedit) { bArmature *arm = obedit->data; @@ -661,6 +810,12 @@ bool ED_armature_edit_deselect_all_visible_multi(bContext *C) return changed_multi; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Cursor Picking API + * \{ */ + /* accounts for connected parents */ static int ebone_select_flag(EditBone *ebone) { @@ -800,6 +955,8 @@ bool ED_armature_edit_select_pick( return false; } +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Select Op From Tagged * @@ -984,7 +1141,9 @@ bool ED_armature_edit_select_op_from_tagged(bArmature *arm, const int sel_op) /** \} */ -/* **************** Selections ******************/ +/* -------------------------------------------------------------------- */ +/** \name (De)Select All Operator + * \{ */ static int armature_de_select_all_exec(bContext *C, wmOperator *op) { @@ -1003,7 +1162,7 @@ static int armature_de_select_all_exec(bContext *C, wmOperator *op) CTX_DATA_END; } - /* Set the flags */ + /* Set the flags. */ CTX_DATA_BEGIN (C, EditBone *, ebone, visible_bones) { /* ignore bone if selection can't change */ switch (action) { @@ -1063,7 +1222,11 @@ void ARMATURE_OT_select_all(wmOperatorType *ot) WM_operator_properties_select_all(ot); } -/**************** Select more/less **************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select More/Less Implementation + * \{ */ static void armature_select_more(bArmature *arm, EditBone *ebone) { @@ -1150,6 +1313,12 @@ static void armature_select_more_less(Object *ob, bool more) ED_armature_edit_sync_selection(arm->edbo); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select More Operator + * \{ */ + static int armature_de_select_more_exec(bContext *C, wmOperator *UNUSED(op)) { ViewLayer *view_layer = CTX_data_view_layer(C); @@ -1183,6 +1352,12 @@ void ARMATURE_OT_select_more(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Less Operator + * \{ */ + static int armature_de_select_less_exec(bContext *C, wmOperator *UNUSED(op)) { ViewLayer *view_layer = CTX_data_view_layer(C); @@ -1216,6 +1391,12 @@ void ARMATURE_OT_select_less(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Similar + * \{ */ + enum { SIMEDBONE_CHILDREN = 1, SIMEDBONE_CHILDREN_IMMEDIATE, @@ -1631,7 +1812,11 @@ void ARMATURE_OT_select_similar(wmOperatorType *ot) RNA_def_float(ot->srna, "threshold", 0.1f, 0.0f, 1.0f, "Threshold", "", 0.0f, 1.0f); } -/* ********************* select hierarchy operator ************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Hierarchy Operator + * \{ */ /* No need to convert to multi-objects. Just like we keep the non-active bones * selected we then keep the non-active objects untouched (selected/unselected). */ @@ -1737,7 +1922,11 @@ void ARMATURE_OT_select_hierarchy(wmOperatorType *ot) RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection"); } -/****************** Mirror Select ****************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Mirror Operator + * \{ */ /** * \note clone of #pose_select_mirror_exec keep in sync @@ -1822,7 +2011,11 @@ void ARMATURE_OT_select_mirror(wmOperatorType *ot) RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection"); } -/****************** Select Path ****************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Path Operator + * \{ */ static bool armature_shortest_path_select( bArmature *arm, EditBone *ebone_parent, EditBone *ebone_child, bool use_parent, bool is_test) @@ -1948,3 +2141,5 @@ void ARMATURE_OT_shortest_path_pick(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } + +/** \} */ diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c index 76361f6785b..58ceef5b7db 100644 --- a/source/blender/editors/armature/armature_utils.c +++ b/source/blender/editors/armature/armature_utils.c @@ -562,7 +562,7 @@ static EditBone *make_boneList_rec(ListBase *edbo, BLI_addtail(edbo, eBone); - /* Add children if necessary */ + /* Add children if necessary. */ if (curBone->childbase.first) { eBoneTest = make_boneList_rec(edbo, &curBone->childbase, eBone, actBone); if (eBoneTest) { @@ -721,7 +721,7 @@ void ED_armature_from_edit(Main *bmain, bArmature *arm) } } - /* Copy the bones from the editData into the armature */ + /* Copy the bones from the edit-data into the armature. */ for (eBone = arm->edbo->first; eBone; eBone = eBone->next) { newBone = MEM_callocN(sizeof(Bone), "bone"); eBone->temp.bone = newBone; /* Associate the real Bones with the EditBones */ @@ -819,7 +819,7 @@ void ED_armature_edit_free(struct bArmature *arm) { EditBone *eBone; - /* Clear the editbones list */ + /* Clear the edit-bones list. */ if (arm->edbo) { if (arm->edbo->first) { for (eBone = arm->edbo->first; eBone; eBone = eBone->next) { diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c index 07be2baf1ae..475640fa37c 100644 --- a/source/blender/editors/armature/pose_select.c +++ b/source/blender/editors/armature/pose_select.c @@ -497,7 +497,7 @@ static int pose_de_select_all_exec(bContext *C, wmOperator *op) Object *ob_prev = NULL; - /* Set the flags */ + /* Set the flags. */ CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, visible_pose_bones, Object *, ob) { bArmature *arm = ob->data; pose_do_bone_select(pchan, action); diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt index 1b147663a7e..1bc0465424d 100644 --- a/source/blender/editors/datafiles/CMakeLists.txt +++ b/source/blender/editors/datafiles/CMakeLists.txt @@ -766,8 +766,6 @@ set_property(GLOBAL PROPERTY ICON_GEOM_NAMES ) data_to_c_simple(../../../../release/datafiles/bfont.pfb SRC) -data_to_c_simple(../../../../release/datafiles/bfont.ttf SRC) -data_to_c_simple(../../../../release/datafiles/bmonofont.ttf SRC) if(WITH_BLENDER) # blender only (not player) diff --git a/source/blender/editors/gpencil/annotate_draw.c b/source/blender/editors/gpencil/annotate_draw.c index 5c396ca9041..fc62defd757 100644 --- a/source/blender/editors/gpencil/annotate_draw.c +++ b/source/blender/editors/gpencil/annotate_draw.c @@ -209,7 +209,6 @@ static void annotation_calc_2d_stroke_fxy( /* draw a given stroke - just a single dot (only one point) */ static void annotation_draw_stroke_point(const bGPDspoint *points, short thickness, - short UNUSED(dflag), short sflag, int offsx, int offsy, @@ -252,12 +251,8 @@ static void annotation_draw_stroke_point(const bGPDspoint *points, } /* draw a given stroke in 3d (i.e. in 3d-space), using simple ogl lines */ -static void annotation_draw_stroke_3d(const bGPDspoint *points, - int totpoints, - short thickness, - short UNUSED(sflag), - const float ink[4], - bool cyclic) +static void annotation_draw_stroke_3d( + const bGPDspoint *points, int totpoints, short thickness, const float ink[4], bool cyclic) { float curpressure = points[0].pressure; float cyclic_fpt[3]; @@ -550,9 +545,7 @@ static bool annotation_can_draw_stroke(const bGPDstroke *gps, const int dflag) } /* draw a set of strokes */ -static void annotation_draw_strokes(bGPdata *UNUSED(gpd), - bGPDlayer *UNUSED(gpl), - const bGPDframe *gpf, +static void annotation_draw_strokes(const bGPDframe *gpf, int offsx, int offsy, int winx, @@ -587,11 +580,11 @@ static void annotation_draw_strokes(bGPdata *UNUSED(gpd), /* 3D Lines - OpenGL primitives-based */ if (gps->totpoints == 1) { annotation_draw_stroke_point( - gps->points, lthick, dflag, gps->flag, offsx, offsy, winx, winy, color); + gps->points, lthick, gps->flag, offsx, offsy, winx, winy, color); } else { annotation_draw_stroke_3d( - gps->points, gps->totpoints, lthick, gps->flag, color, gps->flag & GP_STROKE_CYCLIC); + gps->points, gps->totpoints, lthick, color, gps->flag & GP_STROKE_CYCLIC); } if (no_xray) { @@ -605,7 +598,7 @@ static void annotation_draw_strokes(bGPdata *UNUSED(gpd), /* 2D Strokes... */ if (gps->totpoints == 1) { annotation_draw_stroke_point( - gps->points, lthick, dflag, gps->flag, offsx, offsy, winx, winy, color); + gps->points, lthick, gps->flag, offsx, offsy, winx, winy, color); } else { annotation_draw_stroke_2d(gps->points, @@ -626,15 +619,13 @@ static void annotation_draw_strokes(bGPdata *UNUSED(gpd), } /* Draw selected verts for strokes being edited */ -static void annotation_draw_strokes_edit(bGPdata *UNUSED(gpd), - bGPDlayer *gpl, +static void annotation_draw_strokes_edit(bGPDlayer *gpl, const bGPDframe *gpf, int offsx, int offsy, int winx, int winy, short dflag, - short UNUSED(lflag), float alpha) { /* if alpha 0 do not draw */ @@ -754,15 +745,8 @@ static void annotation_draw_strokes_edit(bGPdata *UNUSED(gpd), /* ----- General Drawing ------ */ /* draw onion-skinning for a layer */ -static void annotation_draw_onionskins(bGPdata *gpd, - bGPDlayer *gpl, - bGPDframe *gpf, - int offsx, - int offsy, - int winx, - int winy, - int UNUSED(cfra), - int dflag) +static void annotation_draw_onionskins( + bGPDlayer *gpl, bGPDframe *gpf, int offsx, int offsy, int winx, int winy, int dflag) { const float alpha = 1.0f; float color[4]; @@ -781,8 +765,7 @@ static void annotation_draw_onionskins(bGPdata *gpd, /* alpha decreases with distance from curframe index */ fac = 1.0f - ((float)(gpf->framenum - gf->framenum) / (float)(gpl->gstep + 1)); color[3] = alpha * fac * 0.66f; - annotation_draw_strokes( - gpd, gpl, gf, offsx, offsy, winx, winy, dflag, gpl->thickness, color); + annotation_draw_strokes(gf, offsx, offsy, winx, winy, dflag, gpl->thickness, color); } else { break; @@ -793,8 +776,7 @@ static void annotation_draw_onionskins(bGPdata *gpd, /* draw the strokes for the ghost frames (at half of the alpha set by user) */ if (gpf->prev) { color[3] = (alpha / 7); - annotation_draw_strokes( - gpd, gpl, gpf->prev, offsx, offsy, winx, winy, dflag, gpl->thickness, color); + annotation_draw_strokes(gpf->prev, offsx, offsy, winx, winy, dflag, gpl->thickness, color); } } else { @@ -815,8 +797,7 @@ static void annotation_draw_onionskins(bGPdata *gpd, /* alpha decreases with distance from curframe index */ fac = 1.0f - ((float)(gf->framenum - gpf->framenum) / (float)(gpl->gstep_next + 1)); color[3] = alpha * fac * 0.66f; - annotation_draw_strokes( - gpd, gpl, gf, offsx, offsy, winx, winy, dflag, gpl->thickness, color); + annotation_draw_strokes(gf, offsx, offsy, winx, winy, dflag, gpl->thickness, color); } else { break; @@ -827,8 +808,7 @@ static void annotation_draw_onionskins(bGPdata *gpd, /* draw the strokes for the ghost frames (at half of the alpha set by user) */ if (gpf->next) { color[3] = (alpha / 4); - annotation_draw_strokes( - gpd, gpl, gpf->next, offsx, offsy, winx, winy, dflag, gpl->thickness, color); + annotation_draw_strokes(gpf->next, offsx, offsy, winx, winy, dflag, gpl->thickness, color); } } else { @@ -875,11 +855,11 @@ static void annotation_draw_data_layers( /* Draw 'onionskins' (frame left + right) */ if (gpl->onion_flag & GP_LAYER_ONIONSKIN) { - annotation_draw_onionskins(gpd, gpl, gpf, offsx, offsy, winx, winy, cfra, dflag); + annotation_draw_onionskins(gpl, gpf, offsx, offsy, winx, winy, dflag); } /* draw the strokes already in active frame */ - annotation_draw_strokes(gpd, gpl, gpf, offsx, offsy, winx, winy, dflag, lthick, ink); + annotation_draw_strokes(gpf, offsx, offsy, winx, winy, dflag, lthick, ink); /* Draw verts of selected strokes: * - when doing OpenGL renders, we don't want to be showing these, as that ends up flickering @@ -892,8 +872,7 @@ static void annotation_draw_data_layers( /* XXX: perhaps we don't want to show these when users are drawing... */ if ((G.f & G_FLAG_RENDER_VIEWPORT) == 0 && (gpl->flag & GP_LAYER_LOCKED) == 0 && (gpd->flag & GP_DATA_STROKE_EDITMODE)) { - annotation_draw_strokes_edit( - gpd, gpl, gpf, offsx, offsy, winx, winy, dflag, gpl->flag, alpha); + annotation_draw_strokes_edit(gpl, gpf, offsx, offsy, winx, winy, dflag, alpha); } /* Check if may need to draw the active stroke cache, only if this layer is the active layer diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c index 9f2c4070b18..53ada341cc9 100644 --- a/source/blender/editors/gpencil/annotate_paint.c +++ b/source/blender/editors/gpencil/annotate_paint.c @@ -816,7 +816,6 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, bGPDframe *gpf, bGPDstroke *gps, const float mval[2], - const float mvalo[2], const int radius, const rcti *rect) { @@ -885,7 +884,7 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, * eraser region (either within stroke painted, or on its lines) * - this assumes that linewidth is irrelevant */ - if (gp_stroke_inside_circle(mval, mvalo, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { + if (gp_stroke_inside_circle(mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { if ((gp_stroke_eraser_is_occluded(p, pt1, pc1[0], pc1[1]) == false) || (gp_stroke_eraser_is_occluded(p, pt2, pc2[0], pc2[1]) == false)) { /* Edge is affected - Check individual points now */ @@ -938,7 +937,7 @@ static void gp_stroke_doeraser(tGPsdata *p) * (e.g. 2D space strokes in the 3D view, if the same datablock is shared) */ if (ED_gpencil_stroke_can_use_direct(p->sa, gps)) { - gp_stroke_eraser_dostroke(p, gpf, gps, p->mval, p->mvalo, p->radius, &rect); + gp_stroke_eraser_dostroke(p, gpf, gps, p->mval, p->radius, &rect); } } } diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index 896ef7a9ad3..6d41e9bddbe 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -114,13 +114,6 @@ typedef enum eDrawStrokeFlags { /* ----- Tool Buffer Drawing ------ */ /* helper functions to set color of buffer point */ -static void gp_set_point_uniform_color(const bGPDspoint *pt, const float ink[4]) -{ - float alpha = ink[3] * pt->strength; - CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f); - immUniformColor3fvAlpha(ink, alpha); -} - static void gp_set_point_varying_color(const bGPDspoint *pt, const float ink[4], uint attr_id, @@ -134,74 +127,8 @@ static void gp_set_point_varying_color(const bGPDspoint *pt, immAttr4ub(attr_id, F2UB(ink[0]), F2UB(ink[1]), F2UB(ink[2]), F2UB(alpha)); } -/* --------- 2D Stroke Drawing Helpers --------- */ -/* change in parameter list */ -static void gp_calc_2d_stroke_fxy( - const float pt[3], short sflag, int offsx, int offsy, int winx, int winy, float r_co[2]) -{ - if (sflag & GP_STROKE_2DSPACE) { - r_co[0] = pt[0]; - r_co[1] = pt[1]; - } - else if (sflag & GP_STROKE_2DIMAGE) { - const float x = (float)((pt[0] * winx) + offsx); - const float y = (float)((pt[1] * winy) + offsy); - - r_co[0] = x; - r_co[1] = y; - } - else { - const float x = (float)(pt[0] / 100 * winx) + offsx; - const float y = (float)(pt[1] / 100 * winy) + offsy; - - r_co[0] = x; - r_co[1] = y; - } -} /* ----------- Volumetric Strokes --------------- */ -/* draw a 2D strokes in "volumetric" style */ -static void gp_draw_stroke_volumetric_2d(const bGPDspoint *points, - int totpoints, - short thickness, - short UNUSED(dflag), - short sflag, - int offsx, - int offsy, - int winx, - int winy, - const float diff_mat[4][4], - const float ink[4]) -{ - GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - uint size = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - uint color = GPU_vertformat_attr_add( - format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - - immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR); - GPU_program_point_size(true); - immBegin(GPU_PRIM_POINTS, totpoints); - - const bGPDspoint *pt = points; - for (int i = 0; i < totpoints; i++, pt++) { - /* transform position to 2D */ - float co[2]; - float fpt[3]; - - mul_v3_m4v3(fpt, diff_mat, &pt->x); - gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, co); - - gp_set_point_varying_color(pt, ink, color, false); - immAttr1f(size, pt->pressure * thickness); /* TODO: scale based on view transform */ - immVertex2f(pos, co[0], co[1]); - } - - immEnd(); - immUnbindProgram(); - GPU_program_point_size(false); -} - /* draw a 3D stroke in "volumetric" style */ static void gp_draw_stroke_volumetric_3d(const bGPDspoint *points, int totpoints, @@ -232,136 +159,8 @@ static void gp_draw_stroke_volumetric_3d(const bGPDspoint *points, GPU_program_point_size(false); } -/* --------------- Stroke Fills ----------------- */ -/* add a new fill point and texture coordinates to vertex buffer */ -static void gp_add_filldata_tobuffer(const bGPDspoint *pt, - uint pos, - uint texcoord, - short flag, - int offsx, - int offsy, - int winx, - int winy, - const float diff_mat[4][4]) -{ - float fpt[3]; - float co[2]; - - mul_v3_m4v3(fpt, diff_mat, &pt->x); - /* if 2d, need conversion */ - if (!(flag & GP_STROKE_3DSPACE)) { - gp_calc_2d_stroke_fxy(fpt, flag, offsx, offsy, winx, winy, co); - copy_v2_v2(fpt, co); - fpt[2] = 0.0f; /* 2d always is z=0.0f */ - } - - immAttr2f(texcoord, pt->uv_fill[0], pt->uv_fill[1]); /* texture coordinates */ - immVertex3fv(pos, fpt); /* position */ -} - -/* draw fills for shapes */ -static void gp_draw_stroke_fill(bGPdata *gpd, - bGPDstroke *gps, - int offsx, - int offsy, - int winx, - int winy, - const float diff_mat[4][4], - const float color[4]) -{ - BLI_assert(gps->totpoints >= 3); - BLI_assert(gps->tot_triangles >= 1); - const bool use_mat = (gpd->mat != NULL); - - Material *ma = (use_mat) ? gpd->mat[gps->mat_nr] : BKE_material_default_gpencil(); - MaterialGPencilStyle *gp_style = (ma) ? ma->gp_style : NULL; - - GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - uint texcoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_GPENCIL_FILL); - - immUniformColor4fv(color); - immUniform4fv("color2", gp_style->mix_rgba); - immUniform1i("fill_type", gp_style->fill_style); - immUniform1f("mix_factor", gp_style->mix_factor); - - immUniform1f("texture_angle", gp_style->texture_angle); - immUniform2fv("texture_scale", gp_style->texture_scale); - immUniform2fv("texture_offset", gp_style->texture_offset); - immUniform1f("texture_opacity", gp_style->texture_opacity); - immUniform1i("t_mix", (gp_style->flag & GP_MATERIAL_FILL_TEX_MIX) != 0); - immUniform1i("t_flip", (gp_style->flag & GP_MATERIAL_FLIP_FILL) != 0); - - /* Draw all triangles for filling the polygon (cache must be calculated before) */ - immBegin(GPU_PRIM_TRIS, gps->tot_triangles * 3); - /* TODO: use batch instead of immediate mode, to share vertices */ - - const bGPDtriangle *stroke_triangle = gps->triangles; - for (int i = 0; i < gps->tot_triangles; i++, stroke_triangle++) { - for (int j = 0; j < 3; j++) { - gp_add_filldata_tobuffer(&gps->points[stroke_triangle->verts[j]], - pos, - texcoord, - gps->flag, - offsx, - offsy, - winx, - winy, - diff_mat); - } - } - - immEnd(); - immUnbindProgram(); -} - /* ----- Existing Strokes Drawing (3D and Point) ------ */ -/* draw a given stroke - just a single dot (only one point) */ -static void gp_draw_stroke_point(const bGPDspoint *points, - short thickness, - short UNUSED(dflag), - short sflag, - int offsx, - int offsy, - int winx, - int winy, - const float diff_mat[4][4], - const float ink[4]) -{ - const bGPDspoint *pt = points; - - /* get final position using parent matrix */ - float fpt[3]; - mul_v3_m4v3(fpt, diff_mat, &pt->x); - - GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - - if (sflag & GP_STROKE_3DSPACE) { - immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); - } - else { - immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); - - /* get 2D coordinates of point */ - float co[3] = {0.0f}; - gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, co); - copy_v3_v3(fpt, co); - } - - gp_set_point_uniform_color(pt, ink); - /* set point thickness (since there's only one of these) */ - immUniform1f("size", (float)(thickness + 2) * pt->pressure); - - immBegin(GPU_PRIM_POINTS, 1); - immVertex3fv(pos, fpt); - immEnd(); - - immUnbindProgram(); -} - /* draw a given stroke in 3d (i.e. in 3d-space) */ static void gp_draw_stroke_3d(tGPDdraw *tgpw, short thickness, const float ink[4], bool cyclic) { @@ -454,200 +253,6 @@ static void gp_draw_stroke_3d(tGPDdraw *tgpw, short thickness, const float ink[4 immUnbindProgram(); } -/* ----- Fancy 2D-Stroke Drawing ------ */ - -/* draw a given stroke in 2d */ -static void gp_draw_stroke_2d(const bGPDspoint *points, - int totpoints, - short thickness_s, - short dflag, - short sflag, - bool UNUSED(debug), - int offsx, - int offsy, - int winx, - int winy, - const float diff_mat[4][4], - const float ink[4]) -{ - /* otherwise thickness is twice that of the 3D view */ - float thickness = (float)thickness_s * 0.5f; - - /* strokes in Image Editor need a scale factor, since units there are not pixels! */ - float scalefac = 1.0f; - if ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)) { - scalefac = 0.001f; - } - - /* TODO: fancy++ with the magic of shaders */ - - /* tessellation code - draw stroke as series of connected quads (triangle strips in fact) - * with connection edges rotated to minimize shrinking artifacts, and rounded endcaps. - */ - { - const bGPDspoint *pt1, *pt2; - float s0[2], s1[2]; /* segment 'center' points */ - float pm[2]; /* normal from previous segment. */ - int i; - float fpt[3]; - - GPUVertFormat *format = immVertexFormat(); - const struct { - uint pos, color; - } attr_id = { - .pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT), - .color = GPU_vertformat_attr_add( - format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT), - }; - - immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); - immBegin(GPU_PRIM_TRI_STRIP, totpoints * 2 + 4); - - /* get x and y coordinates from first point */ - mul_v3_m4v3(fpt, diff_mat, &points->x); - gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, s0); - - for (i = 0, pt1 = points, pt2 = points + 1; i < (totpoints - 1); i++, pt1++, pt2++) { - float t0[2], t1[2]; /* tessellated coordinates */ - float m1[2], m2[2]; /* gradient and normal */ - float mt[2], sc[2]; /* gradient for thickness, point for end-cap */ - float pthick; /* thickness at segment point */ - - /* Get x and y coordinates from point2 - * (point1 has already been computed in previous iteration). */ - mul_v3_m4v3(fpt, diff_mat, &pt2->x); - gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, s1); - - /* calculate gradient and normal - 'angle'=(ny/nx) */ - m1[1] = s1[1] - s0[1]; - m1[0] = s1[0] - s0[0]; - normalize_v2(m1); - m2[1] = -m1[0]; - m2[0] = m1[1]; - - /* always use pressure from first point here */ - pthick = (pt1->pressure * thickness * scalefac); - - /* color of point */ - gp_set_point_varying_color(pt1, ink, attr_id.color, false); - - /* if the first segment, start of segment is segment's normal */ - if (i == 0) { - /* draw start cap first - * - make points slightly closer to center (about halfway across) - */ - mt[0] = m2[0] * pthick * 0.5f; - mt[1] = m2[1] * pthick * 0.5f; - sc[0] = s0[0] - (m1[0] * pthick * 0.75f); - sc[1] = s0[1] - (m1[1] * pthick * 0.75f); - - t0[0] = sc[0] - mt[0]; - t0[1] = sc[1] - mt[1]; - t1[0] = sc[0] + mt[0]; - t1[1] = sc[1] + mt[1]; - - /* First two points of cap. */ - immVertex2fv(attr_id.pos, t0); - immVertex2fv(attr_id.pos, t1); - - /* calculate points for start of segment */ - mt[0] = m2[0] * pthick; - mt[1] = m2[1] * pthick; - - t0[0] = s0[0] - mt[0]; - t0[1] = s0[1] - mt[1]; - t1[0] = s0[0] + mt[0]; - t1[1] = s0[1] + mt[1]; - - /* Last two points of start cap (and first two points of first segment). */ - immVertex2fv(attr_id.pos, t0); - immVertex2fv(attr_id.pos, t1); - } - /* if not the first segment, use bisector of angle between segments */ - else { - float mb[2]; /* bisector normal */ - float athick, dfac; /* actual thickness, difference between thicknesses */ - - /* calculate gradient of bisector (as average of normals) */ - mb[0] = (pm[0] + m2[0]) / 2; - mb[1] = (pm[1] + m2[1]) / 2; - normalize_v2(mb); - - /* calculate gradient to apply - * - as basis, use just pthick * bisector gradient - * - if cross-section not as thick as it should be, add extra padding to fix it - */ - mt[0] = mb[0] * pthick; - mt[1] = mb[1] * pthick; - athick = len_v2(mt); - dfac = pthick - (athick * 2); - - if (((athick * 2.0f) < pthick) && (IS_EQF(athick, pthick) == 0)) { - mt[0] += (mb[0] * dfac); - mt[1] += (mb[1] * dfac); - } - - /* calculate points for start of segment */ - t0[0] = s0[0] - mt[0]; - t0[1] = s0[1] - mt[1]; - t1[0] = s0[0] + mt[0]; - t1[1] = s0[1] + mt[1]; - - /* Last two points of previous segment, and first two points of current segment. */ - immVertex2fv(attr_id.pos, t0); - immVertex2fv(attr_id.pos, t1); - } - - /* if last segment, also draw end of segment (defined as segment's normal) */ - if (i == totpoints - 2) { - /* for once, we use second point's pressure (otherwise it won't be drawn) */ - pthick = (pt2->pressure * thickness * scalefac); - - /* color of point */ - gp_set_point_varying_color(pt2, ink, attr_id.color, false); - - /* calculate points for end of segment */ - mt[0] = m2[0] * pthick; - mt[1] = m2[1] * pthick; - - t0[0] = s1[0] - mt[0]; - t0[1] = s1[1] - mt[1]; - t1[0] = s1[0] + mt[0]; - t1[1] = s1[1] + mt[1]; - - /* Last two points of last segment (and first two points of end cap). */ - immVertex2fv(attr_id.pos, t0); - immVertex2fv(attr_id.pos, t1); - - /* draw end cap as last step - * - make points slightly closer to center (about halfway across) - */ - mt[0] = m2[0] * pthick * 0.5f; - mt[1] = m2[1] * pthick * 0.5f; - sc[0] = s1[0] + (m1[0] * pthick * 0.75f); - sc[1] = s1[1] + (m1[1] * pthick * 0.75f); - - t0[0] = sc[0] - mt[0]; - t0[1] = sc[1] - mt[1]; - t1[0] = sc[0] + mt[0]; - t1[1] = sc[1] + mt[1]; - - /* Last two points of end cap. */ - immVertex2fv(attr_id.pos, t0); - immVertex2fv(attr_id.pos, t1); - } - - /* store computed point2 coordinates as point1 ones of next segment. */ - copy_v2_v2(s0, s1); - /* store stroke's 'natural' normal for next stroke to use */ - copy_v2_v2(pm, m2); - } - - immEnd(); - immUnbindProgram(); - } -} - /* ----- Strokes Drawing ------ */ /* Helper for doing all the checks on whether a stroke can be drawn */ @@ -691,7 +296,6 @@ static bool gp_can_draw_stroke(const bGPDstroke *gps, const int dflag) static void gp_draw_strokes(tGPDdraw *tgpw) { float tcolor[4]; - float tfill[4]; short sthickness; float ink[4]; const bool is_unique = (tgpw->gps != NULL); @@ -748,37 +352,6 @@ static void gp_draw_strokes(tGPDdraw *tgpw) bglPolygonOffset(1.0f, 1.0f); } - /* 3D Fill */ - // if ((dflag & GP_DRAWDATA_FILL) && (gps->totpoints >= 3)) { - if ((gps->totpoints >= 3) && (tgpw->disable_fill != 1)) { - /* set color using material, tint color and opacity */ - interp_v3_v3v3(tfill, gp_style->fill_rgba, tgpw->tintcolor, tgpw->tintcolor[3]); - tfill[3] = gp_style->fill_rgba[3] * tgpw->opacity; - if ((tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (gp_style->fill_style > 0)) { - const float *color; - if (!tgpw->onion) { - color = tfill; - } - else { - if (tgpw->custonion) { - color = tgpw->tintcolor; - } - else { - ARRAY_SET_ITEMS(tfill, UNPACK3(gp_style->fill_rgba), tgpw->tintcolor[3]); - color = tfill; - } - } - gp_draw_stroke_fill(tgpw->gpd, - gps, - tgpw->offsx, - tgpw->offsy, - tgpw->winx, - tgpw->winy, - tgpw->diff_mat, - color); - } - } - /* 3D Stroke */ /* set color using material tint color and opacity */ if (!tgpw->onion) { @@ -811,21 +384,7 @@ static void gp_draw_strokes(tGPDdraw *tgpw) } else { /* 3D Lines - OpenGL primitives-based */ - if (gps->totpoints == 1) { - if (tgpw->disable_fill != 1) { - gp_draw_stroke_point(gps->points, - sthickness, - tgpw->dflag, - gps->flag, - tgpw->offsx, - tgpw->offsy, - tgpw->winx, - tgpw->winy, - tgpw->diff_mat, - ink); - } - } - else { + if (gps->totpoints > 1) { tgpw->gps = gps; gp_draw_stroke_3d(tgpw, sthickness, ink, gps->flag & GP_STROKE_CYCLIC); } @@ -837,97 +396,6 @@ static void gp_draw_strokes(tGPDdraw *tgpw) bglPolygonOffset(0.0, 0.0); } } - else { - /* 2D - Fill */ - if (gps->totpoints >= 3) { - /* set color using material, tint color and opacity */ - interp_v3_v3v3(tfill, gp_style->fill_rgba, tgpw->tintcolor, tgpw->tintcolor[3]); - tfill[3] = gp_style->fill_rgba[3] * tgpw->opacity; - if ((tfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (gp_style->fill_style > 0)) { - const float *color; - if (!tgpw->onion) { - color = tfill; - } - else { - if (tgpw->custonion) { - color = tgpw->tintcolor; - } - else { - ARRAY_SET_ITEMS(tfill, UNPACK3(gp_style->fill_rgba), tgpw->tintcolor[3]); - color = tfill; - } - } - gp_draw_stroke_fill(tgpw->gpd, - gps, - tgpw->offsx, - tgpw->offsy, - tgpw->winx, - tgpw->winy, - tgpw->diff_mat, - color); - } - } - - /* 2D Strokes... */ - /* set color using material, tint color and opacity */ - if (!tgpw->onion) { - interp_v3_v3v3(tcolor, gp_style->stroke_rgba, tgpw->tintcolor, tgpw->tintcolor[3]); - tcolor[3] = gp_style->stroke_rgba[3] * tgpw->opacity; - copy_v4_v4(ink, tcolor); - } - else { - if (tgpw->custonion) { - copy_v4_v4(ink, tgpw->tintcolor); - } - else { - ARRAY_SET_ITEMS(tcolor, UNPACK3(gp_style->stroke_rgba), tgpw->opacity); - copy_v4_v4(ink, tcolor); - } - } - if (gp_style->mode == GP_MATERIAL_MODE_DOT) { - /* blob/disk-based "volumetric" drawing */ - gp_draw_stroke_volumetric_2d(gps->points, - gps->totpoints, - sthickness, - tgpw->dflag, - gps->flag, - tgpw->offsx, - tgpw->offsy, - tgpw->winx, - tgpw->winy, - tgpw->diff_mat, - ink); - } - else { - /* normal 2D strokes */ - if (gps->totpoints == 1) { - gp_draw_stroke_point(gps->points, - sthickness, - tgpw->dflag, - gps->flag, - tgpw->offsx, - tgpw->offsy, - tgpw->winx, - tgpw->winy, - tgpw->diff_mat, - ink); - } - else { - gp_draw_stroke_2d(gps->points, - gps->totpoints, - sthickness, - tgpw->dflag, - gps->flag, - false, - tgpw->offsx, - tgpw->offsy, - tgpw->winx, - tgpw->winy, - tgpw->diff_mat, - ink); - } - } - } /* if only one stroke, exit from loop */ if (is_unique) { break; diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index 1c55c3b5a8f..8470fcad9d7 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -152,7 +152,6 @@ static const EnumPropertyItem *rna_GPConvert_mode_items(bContext *UNUSED(C), * - assumes that the active space is the 3D-View */ static void gp_strokepoint_convertcoords(bContext *C, - bGPdata *UNUSED(gpd), bGPDlayer *gpl, bGPDstroke *gps, bGPDspoint *source_pt, @@ -633,7 +632,6 @@ static void gp_stroke_to_path_add_point(tGpTimingData *gtd, } static void gp_stroke_to_path(bContext *C, - bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, @@ -708,7 +706,7 @@ static void gp_stroke_to_path(bContext *C, bp = &nu->bp[old_nbp - 1]; /* First point */ - gp_strokepoint_convertcoords(C, gpd, gpl, gps, gps->points, p, subrect); + gp_strokepoint_convertcoords(C, gpl, gps, gps->points, p, subrect); if (prev_bp) { interp_v3_v3v3(p1, bp->vec, prev_bp->vec, -GAP_DFAC); if (do_gtd) { @@ -737,7 +735,7 @@ static void gp_stroke_to_path(bContext *C, /* Second point */ /* Note dt2 is always negative, which marks the gap. */ if (gps->totpoints > 1) { - gp_strokepoint_convertcoords(C, gpd, gpl, gps, gps->points + 1, next_p, subrect); + gp_strokepoint_convertcoords(C, gpl, gps, gps->points + 1, next_p, subrect); interp_v3_v3v3(p2, p, next_p, -GAP_DFAC); if (do_gtd) { dt2 = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC); @@ -759,9 +757,9 @@ static void gp_stroke_to_path(bContext *C, float p[3], next_p[3]; float dt = 0.0f; - gp_strokepoint_convertcoords(C, gpd, gpl, gps, gps->points, p, subrect); + gp_strokepoint_convertcoords(C, gpl, gps, gps->points, p, subrect); if (gps->totpoints > 1) { - gp_strokepoint_convertcoords(C, gpd, gpl, gps, gps->points + 1, next_p, subrect); + gp_strokepoint_convertcoords(C, gpl, gps, gps->points + 1, next_p, subrect); interp_v3_v3v3(p, p, next_p, -GAP_DFAC); if (do_gtd) { dt = interpf(gps->points[1].time, gps->points[0].time, -GAP_DFAC); @@ -794,7 +792,7 @@ static void gp_stroke_to_path(bContext *C, float width = pt->pressure * (gps->thickness + gpl->line_change) * WIDTH_CORR_FAC; /* get coordinates to add at */ - gp_strokepoint_convertcoords(C, gpd, gpl, gps, pt, p, subrect); + gp_strokepoint_convertcoords(C, gpl, gps, pt, p, subrect); gp_stroke_to_path_add_point(gtd, bp, @@ -882,7 +880,6 @@ static void gp_stroke_to_bezier_add_point(tGpTimingData *gtd, } static void gp_stroke_to_bezier(bContext *C, - bGPdata *gpd, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, @@ -934,13 +931,12 @@ static void gp_stroke_to_bezier(bContext *C, /* get initial coordinates */ pt = gps->points; if (tot) { - gp_strokepoint_convertcoords(C, gpd, gpl, gps, pt, (stitch) ? p3d_prev : p3d_cur, subrect); + gp_strokepoint_convertcoords(C, gpl, gps, pt, (stitch) ? p3d_prev : p3d_cur, subrect); if (tot > 1) { - gp_strokepoint_convertcoords( - C, gpd, gpl, gps, pt + 1, (stitch) ? p3d_cur : p3d_next, subrect); + gp_strokepoint_convertcoords(C, gpl, gps, pt + 1, (stitch) ? p3d_cur : p3d_next, subrect); } if (stitch && tot > 2) { - gp_strokepoint_convertcoords(C, gpd, gpl, gps, pt + 2, p3d_next, subrect); + gp_strokepoint_convertcoords(C, gpl, gps, pt + 2, p3d_next, subrect); } } @@ -1106,7 +1102,7 @@ static void gp_stroke_to_bezier(bContext *C, copy_v3_v3(p3d_cur, p3d_next); if (i + 2 < tot) { - gp_strokepoint_convertcoords(C, gpd, gpl, gps, pt + 2, p3d_next, subrect); + gp_strokepoint_convertcoords(C, gpl, gps, pt + 2, p3d_next, subrect); } prev_bezt = bezt; @@ -1334,7 +1330,6 @@ static void gp_layer_to_curve(bContext *C, switch (mode) { case GP_STROKECONVERT_PATH: gp_stroke_to_path(C, - gpd, gpl, gps, cu, @@ -1350,7 +1345,6 @@ static void gp_layer_to_curve(bContext *C, case GP_STROKECONVERT_CURVE: case GP_STROKECONVERT_POLY: /* convert after */ gp_stroke_to_bezier(C, - gpd, gpl, gps, cu, @@ -1755,7 +1749,7 @@ void GPENCIL_OT_convert(wmOperatorType *ot) static bool image_to_gpencil_poll(bContext *C) { SpaceLink *sl = CTX_wm_space_data(C); - if (sl->spacetype == SPACE_IMAGE) { + if ((sl != NULL) && (sl->spacetype == SPACE_IMAGE)) { return true; } diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index 627bc46d06c..898facb86e8 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -214,6 +214,7 @@ static int gp_layer_add_exec(bContext *C, wmOperator *op) PointerRNA gpd_owner = {NULL}; Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); bGPdata *gpd = NULL; if (is_annotation) { @@ -238,7 +239,13 @@ static int gp_layer_add_exec(bContext *C, wmOperator *op) Object *ob = CTX_data_active_object(C); if ((ob != NULL) && (ob->type == OB_GPENCIL)) { gpd = (bGPdata *)ob->data; - BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true); + bGPDlayer *gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true); + ScrArea *sa = CTX_wm_area(C); + + /* In dopesheet add a new frame. */ + if ((gpl != NULL) && (sa->spacetype == SPACE_ACTION)) { + gpl->actframe = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_NEW); + } } } diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 83ecb3ab42f..dc7bbfb99fa 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -1379,7 +1379,8 @@ void GPENCIL_OT_copy(wmOperatorType *ot) static bool gp_strokes_paste_poll(bContext *C) { - if (CTX_wm_area(C)->spacetype != SPACE_VIEW3D) { + ScrArea *sa = CTX_wm_area(C); + if (!((sa != NULL) && (sa->spacetype == SPACE_VIEW3D))) { return false; } /* 1) Must have GP datablock to paste to @@ -3545,7 +3546,7 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op) GP_REPROJECT_TOP, GP_REPROJECT_CURSOR)) { if (mode != GP_REPROJECT_CURSOR) { - ED_gpencil_drawing_reference_get(scene, ob, gpl, ts->gpencil_v3d_align, origin); + ED_gpencil_drawing_reference_get(scene, ob, ts->gpencil_v3d_align, origin); } else { copy_v3_v3(origin, scene->cursor.location); @@ -4248,7 +4249,7 @@ static int gp_stroke_separate_exec(bContext *C, wmOperator *op) if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { continue; } - /* separate selected strokes */ + /* Separate selected strokes. */ if (gps->flag & GP_STROKE_SELECT) { /* add layer if not created before */ if (gpl_dst == NULL) { @@ -4421,7 +4422,7 @@ static int gp_stroke_split_exec(bContext *C, wmOperator *UNUSED(op)) if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { continue; } - /* split selected strokes */ + /* Split selected strokes. */ if (gps->flag & GP_STROKE_SELECT) { /* make copy of source stroke */ bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps, true); diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index f61572fffca..e56017d0bed 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -1143,7 +1143,6 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf) gp_stroke_convertcoords_tpoint(tgpf->scene, tgpf->region, tgpf->ob, - tgpf->gpl, point2D, tgpf->depth_arr ? tgpf->depth_arr + i : NULL, &pt->x); @@ -1186,8 +1185,7 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf) if ((tgpf->lock_axis > GP_LOCKAXIS_VIEW) && ((ts->gpencil_v3d_align & GP_PROJECT_DEPTH_VIEW) == 0)) { float origin[3]; - ED_gpencil_drawing_reference_get( - tgpf->scene, tgpf->ob, tgpf->gpl, ts->gpencil_v3d_align, origin); + ED_gpencil_drawing_reference_get(tgpf->scene, tgpf->ob, ts->gpencil_v3d_align, origin); ED_gp_project_stroke_to_plane( tgpf->scene, tgpf->ob, tgpf->rv3d, gps, origin, tgpf->lock_axis - 1); } diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index 79f672274a7..61bca235d17 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -257,8 +257,7 @@ typedef struct GP_SpaceConversion { float mat[4][4]; /* transform matrix on the strokes (introduced in [b770964]) */ } GP_SpaceConversion; -bool gp_stroke_inside_circle( - const float mval[2], const float UNUSED(mvalo[2]), int rad, int x0, int y0, int x1, int y1); +bool gp_stroke_inside_circle(const float mval[2], int rad, int x0, int y0, int x1, int y1); void gp_point_conversion_init(struct bContext *C, GP_SpaceConversion *r_gsc); @@ -304,7 +303,6 @@ bool gp_point_xy_to_3d(const GP_SpaceConversion *gsc, void gp_stroke_convertcoords_tpoint(struct Scene *scene, struct ARegion *region, struct Object *ob, - bGPDlayer *gpl, const struct tGPspoint *point2D, float *depth, float out[3]); diff --git a/source/blender/editors/gpencil/gpencil_ops_versioning.c b/source/blender/editors/gpencil/gpencil_ops_versioning.c index df094ff5bd0..96146c60acb 100644 --- a/source/blender/editors/gpencil/gpencil_ops_versioning.c +++ b/source/blender/editors/gpencil/gpencil_ops_versioning.c @@ -134,7 +134,6 @@ static int gpencil_convert_old_files_exec(bContext *C, wmOperator *op) ARRAY_SET_ITEMS(gp_style->mix_rgba, 1.0f, 1.0f, 1.0f, 0.2f); ARRAY_SET_ITEMS(gp_style->gradient_scale, 1.0f, 1.0f); ARRAY_SET_ITEMS(gp_style->texture_scale, 1.0f, 1.0f); - gp_style->texture_opacity = 1.0f; gp_style->texture_pixsize = 100.0f; gp_style->flag |= GP_MATERIAL_STROKE_SHOW; diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 01b0fe80dfc..1a169f9ec89 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -30,6 +30,7 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" +#include "BLI_hash.h" #include "BLI_math.h" #include "BLI_math_geom.h" #include "BLI_rand.h" @@ -353,7 +354,7 @@ static void gp_get_3d_reference(tGPsdata *p, float vec[3]) if (p->ownerPtr.type == &RNA_Object) { ob = (Object *)p->ownerPtr.data; } - ED_gpencil_drawing_reference_get(p->scene, ob, p->gpl, *p->align_flag, vec); + ED_gpencil_drawing_reference_get(p->scene, ob, *p->align_flag, vec); } /* Stroke Editing ---------------------------- */ @@ -486,6 +487,7 @@ static void gp_stroke_convertcoords(tGPsdata *p, const float mval[2], float out[ /* Apply jitter to stroke point. */ static void gp_brush_jitter(bGPdata *gpd, tGPspoint *pt, const float amplitude) { + const float axis[2] = {0.0f, 1.0f}; /* Jitter is applied perpendicular to the mouse movement vector (2D space). */ float mvec[2]; /* Mouse movement in ints -> floats. */ @@ -493,16 +495,15 @@ static void gp_brush_jitter(bGPdata *gpd, tGPspoint *pt, const float amplitude) tGPspoint *pt_prev = pt - 1; sub_v2_v2v2(mvec, &pt->x, &pt_prev->x); normalize_v2(mvec); + /* Rotate mvec by 90 degrees... */ + float angle = angle_v2v2(mvec, axis); + /* Reduce noise in the direction of the stroke. */ + mvec[0] *= cos(angle); + mvec[1] *= sin(angle); + + /* Scale by displacement amount, and apply. */ + madd_v2_v2fl(&pt->x, mvec, amplitude * 10.0f); } - else { - mvec[0] = 0.0f; - mvec[1] = 0.0f; - } - /* Rotate mvec by 90 degrees... */ - SWAP(float, mvec[0], mvec[1]); - mvec[0] -= mvec[0]; - /* Scale by displacement amount, and apply. */ - madd_v2_v2fl(&pt->x, mvec, amplitude); } /* apply pressure change depending of the angle of the stroke to simulate a pen with shape */ @@ -788,8 +789,10 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure } /* apply randomness to uv texture rotation */ if (brush_settings->uv_random > 0.0f) { - float rand = BLI_rng_get_float(p->rng) * 2.0f - 1.0f; - pt->uv_rot += rand * M_PI * brush_settings->uv_random; + float rand = BLI_hash_int_01(BLI_hash_int_2d((int)pt->x, gpd->runtime.sbuffer_used)) * + 2.0f - + 1.0f; + pt->uv_rot += rand * M_PI_2 * brush_settings->uv_random; CLAMP(pt->uv_rot, -M_PI_2, M_PI_2); } /* apply randomness to color strength */ @@ -1356,7 +1359,6 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, bGPDframe *gpf, bGPDstroke *gps, const float mval[2], - const float mvalo[2], const int radius, const rcti *rect) { @@ -1475,7 +1477,7 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, * eraser region (either within stroke painted, or on its lines) * - this assumes that linewidth is irrelevant */ - if (gp_stroke_inside_circle(mval, mvalo, radius, pc0[0], pc0[1], pc2[0], pc2[1])) { + if (gp_stroke_inside_circle(mval, radius, pc0[0], pc0[1], pc2[0], pc2[1])) { if ((gp_stroke_eraser_is_occluded(p, pt0, pc0[0], pc0[1]) == false) || (gp_stroke_eraser_is_occluded(p, pt1, pc1[0], pc1[1]) == false) || (gp_stroke_eraser_is_occluded(p, pt2, pc2[0], pc2[1]) == false)) { @@ -1632,7 +1634,7 @@ static void gp_stroke_doeraser(tGPsdata *p) * (e.g. 2D space strokes in the 3D view, if the same datablock is shared) */ if (ED_gpencil_stroke_can_use_direct(p->sa, gps)) { - gp_stroke_eraser_dostroke(p, gpf, gps, p->mval, p->mvalo, calc_radius, &rect); + gp_stroke_eraser_dostroke(p, gpf, gps, p->mval, calc_radius, &rect); } } } @@ -3142,7 +3144,7 @@ static void gpencil_add_arc_points(tGPsdata *p, float mval[2], int segments) if (gpd->runtime.sbuffer_used < 3) { return; } - + BrushGpencilSettings *brush_settings = p->brush->gpencil_settings; int idx_prev = gpd->runtime.sbuffer_used; /* Add space for new arc points. */ @@ -3207,6 +3209,27 @@ static void gpencil_add_arc_points(tGPsdata *p, float mval[2], int segments) pt->pressure = pt_prev->pressure; pt->strength = pt_prev->strength; + /* Apply randomness to pressure. */ + if (brush_settings->draw_random_press > 0.0f) { + float rand = BLI_rng_get_float(p->rng) * 2.0f - 1.0f; + pt->pressure *= 1.0 + rand * 2.0 * brush_settings->draw_random_press; + CLAMP(pt->pressure, GPENCIL_STRENGTH_MIN, 1.0f); + } + /* Apply randomness to color strength. */ + if (brush_settings->draw_random_strength) { + float rand = BLI_rng_get_float(p->rng) * 2.0f - 1.0f; + pt->strength *= 1.0 + rand * brush_settings->draw_random_strength; + CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); + } + /* Apply randomness to uv texture rotation. */ + if (brush_settings->uv_random > 0.0f) { + float rand = BLI_hash_int_01(BLI_hash_int_2d((int)pt->x, gpd->runtime.sbuffer_used + i)) * + 2.0f - + 1.0f; + pt->uv_rot += rand * M_PI_2 * brush_settings->uv_random; + CLAMP(pt->uv_rot, -M_PI_2, M_PI_2); + } + a += step; } } diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index 2b30a415086..dfd11484d22 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -954,8 +954,7 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) /* get origin to reproject point */ float origin[3]; - ED_gpencil_drawing_reference_get( - tgpi->scene, tgpi->ob, tgpi->gpl, ts->gpencil_v3d_align, origin); + ED_gpencil_drawing_reference_get(tgpi->scene, tgpi->ob, ts->gpencil_v3d_align, origin); /* reproject current */ ED_gpencil_tpoint_to_point(tgpi->region, origin, tpt, &spt); ED_gp_project_point_to_plane( @@ -987,13 +986,8 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) } /* convert screen-coordinates to 3D coordinates */ - gp_stroke_convertcoords_tpoint(tgpi->scene, - tgpi->region, - tgpi->ob, - tgpi->gpl, - p2d, - depth_arr ? depth_arr + i : NULL, - &pt->x); + gp_stroke_convertcoords_tpoint( + tgpi->scene, tgpi->region, tgpi->ob, p2d, depth_arr ? depth_arr + i : NULL, &pt->x); pt->pressure = pressure; pt->strength = strength; @@ -1019,15 +1013,14 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) for (int i = 0; i < tgpi->gpd->runtime.tot_cp_points; i++) { bGPDcontrolpoint *cp = &cps[i]; gp_stroke_convertcoords_tpoint( - tgpi->scene, tgpi->region, tgpi->ob, tgpi->gpl, (tGPspoint *)cp, NULL, &cp->x); + tgpi->scene, tgpi->region, tgpi->ob, (tGPspoint *)cp, NULL, &cp->x); } } /* reproject to plane */ if (!is_depth) { float origin[3]; - ED_gpencil_drawing_reference_get( - tgpi->scene, tgpi->ob, tgpi->gpl, ts->gpencil_v3d_align, origin); + ED_gpencil_drawing_reference_get(tgpi->scene, tgpi->ob, ts->gpencil_v3d_align, origin); ED_gp_project_stroke_to_plane( tgpi->scene, tgpi->ob, tgpi->rv3d, gps, origin, ts->gp_sculpt.lock_axis - 1); } diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c index 59b14a47d1d..8f3fc5fa268 100644 --- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c +++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c @@ -1495,8 +1495,7 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso, * brush region (either within stroke painted, or on its lines) * - this assumes that linewidth is irrelevant */ - if (gp_stroke_inside_circle( - gso->mval, gso->mval_prev, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { + if (gp_stroke_inside_circle(gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { /* Apply operation to these points */ bool ok = false; diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index 6194b82fed9..97f0a578d9d 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -919,13 +919,12 @@ static bool gp_stroke_do_circle_sel(bGPdata *UNUSED(gpd), if (((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) || ((!ELEM(V2D_IS_CLIPPED, x1, y1)) && BLI_rcti_isect_pt(rect, x1, y1))) { float mval[2] = {(float)mx, (float)my}; - float mvalo[2] = {(float)mx, (float)my}; /* dummy - this isn't used... */ /* check if point segment of stroke had anything to do with * eraser region (either within stroke painted, or on its lines) * - this assumes that linewidth is irrelevant */ - if (gp_stroke_inside_circle(mval, mvalo, radius, x0, y0, x1, y1)) { + if (gp_stroke_inside_circle(mval, radius, x0, y0, x1, y1)) { /* change selection of stroke, and then of both points * (as the last point otherwise wouldn't get selected * as we only do n-1 loops through). @@ -1052,8 +1051,7 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op) rect.ymax = my + radius; /* find visible strokes, and select if hit */ - GP_EVALUATED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps) - { + GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { changed |= gp_stroke_do_circle_sel(gpd, gpl, gps, @@ -1164,7 +1162,7 @@ static int gpencil_generic_select_exec(bContext *C, gp_point_conversion_init(C, &gsc); /* deselect all strokes first? */ - if (SEL_OP_USE_PRE_DESELECT(sel_op)) { + if (SEL_OP_USE_PRE_DESELECT(sel_op) || (GPENCIL_PAINT_MODE(gpd))) { CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) { bGPDspoint *pt; @@ -1180,8 +1178,7 @@ static int gpencil_generic_select_exec(bContext *C, } /* select/deselect points */ - GP_EVALUATED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps) - { + GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps; bGPDspoint *pt; @@ -1248,7 +1245,7 @@ static int gpencil_generic_select_exec(bContext *C, GP_EVALUATED_STROKES_END(gpstroke_iter); /* if paint mode,delete selected points */ - if (gpd->flag & GP_DATA_STROKE_PAINTMODE) { + if (GPENCIL_PAINT_MODE(gpd)) { gp_delete_selected_point_wrap(C); changed = true; DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); @@ -1473,8 +1470,7 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) /* First Pass: Find stroke point which gets hit */ /* XXX: maybe we should go from the top of the stack down instead... */ - GP_EVALUATED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps) - { + GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps; bGPDspoint *pt; int i; diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 276be071e0b..312cb1b50c0 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -494,8 +494,7 @@ const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(bContext *C, * \param x0, y0: The screen-space x and y coordinates of the start of the stroke segment * \param x1, y1: The screen-space x and y coordinates of the end of the stroke segment */ -bool gp_stroke_inside_circle( - const float mval[2], const float UNUSED(mvalo[2]), int rad, int x0, int y0, int x1, int y1) +bool gp_stroke_inside_circle(const float mval[2], int rad, int x0, int y0, int x1, int y1) { /* simple within-radius check for now */ const float screen_co_a[2] = {x0, y0}; @@ -869,8 +868,7 @@ bool gp_point_xy_to_3d(const GP_SpaceConversion *gsc, const RegionView3D *rv3d = gsc->region->regiondata; float rvec[3]; - ED_gpencil_drawing_reference_get( - scene, gsc->ob, gsc->gpl, scene->toolsettings->gpencil_v3d_align, rvec); + ED_gpencil_drawing_reference_get(scene, gsc->ob, scene->toolsettings->gpencil_v3d_align, rvec); float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL); @@ -905,7 +903,6 @@ bool gp_point_xy_to_3d(const GP_SpaceConversion *gsc, void gp_stroke_convertcoords_tpoint(Scene *scene, ARegion *region, Object *ob, - bGPDlayer *gpl, const tGPspoint *point2D, float *depth, float r_out[3]) @@ -929,7 +926,7 @@ void gp_stroke_convertcoords_tpoint(Scene *scene, /* Current method just converts each point in screen-coordinates to * 3D-coordinates using the 3D-cursor as reference. */ - ED_gpencil_drawing_reference_get(scene, ob, gpl, ts->gpencil_v3d_align, rvec); + ED_gpencil_drawing_reference_get(scene, ob, ts->gpencil_v3d_align, rvec); zfac = ED_view3d_calc_zfac(region->regiondata, rvec, NULL); if (ED_view3d_project_float_global(region, rvec, mval_prj, V3D_PROJ_TEST_NOP) == @@ -948,8 +945,10 @@ void gp_stroke_convertcoords_tpoint(Scene *scene, * Get drawing reference point for conversion or projection of the stroke * \param[out] r_vec : Reference point found */ -void ED_gpencil_drawing_reference_get( - const Scene *scene, const Object *ob, bGPDlayer *UNUSED(gpl), char align_flag, float r_vec[3]) +void ED_gpencil_drawing_reference_get(const Scene *scene, + const Object *ob, + char align_flag, + float r_vec[3]) { const float *fp = scene->cursor.location; diff --git a/source/blender/editors/gpencil/gpencil_uv.c b/source/blender/editors/gpencil/gpencil_uv.c index 1da32dcc537..5f15a6f5411 100644 --- a/source/blender/editors/gpencil/gpencil_uv.c +++ b/source/blender/editors/gpencil/gpencil_uv.c @@ -176,8 +176,7 @@ static bool gpencil_uv_transform_init(bContext *C, wmOperator *op, const bool is float center[3] = {0.0f}; int i = 0; /* Need use evaluated to get the viewport final position. */ - GP_EVALUATED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps) - { + GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { if (gps->flag & GP_STROKE_SELECT) { float r_center[3]; gpencil_stroke_center(gps, r_center); diff --git a/source/blender/editors/gpencil/gpencil_vertex_paint.c b/source/blender/editors/gpencil/gpencil_vertex_paint.c index 0c3b29ab1ea..10867bd1e0d 100644 --- a/source/blender/editors/gpencil/gpencil_vertex_paint.c +++ b/source/blender/editors/gpencil/gpencil_vertex_paint.c @@ -897,8 +897,7 @@ static void gp_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, * brush region (either within stroke painted, or on its lines) * - this assumes that linewidth is irrelevant */ - if (gp_stroke_inside_circle( - gso->mval, gso->mval_prev, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { + if (gp_stroke_inside_circle(gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { /* To each point individually... */ pt = &gps->points[i]; diff --git a/source/blender/editors/gpencil/gpencil_weight_paint.c b/source/blender/editors/gpencil/gpencil_weight_paint.c index 51d5df1f405..2ebf1aba353 100644 --- a/source/blender/editors/gpencil/gpencil_weight_paint.c +++ b/source/blender/editors/gpencil/gpencil_weight_paint.c @@ -449,8 +449,7 @@ static void gp_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso, * brush region (either within stroke painted, or on its lines) * - this assumes that linewidth is irrelevant */ - if (gp_stroke_inside_circle( - gso->mval, gso->mval_prev, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { + if (gp_stroke_inside_circle(gso->mval, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { /* To each point individually... */ pt = &gps->points[i]; diff --git a/source/blender/editors/include/ED_datafiles.h b/source/blender/editors/include/ED_datafiles.h index a2ad343da37..b6f9593c261 100644 --- a/source/blender/editors/include/ED_datafiles.h +++ b/source/blender/editors/include/ED_datafiles.h @@ -60,12 +60,6 @@ extern char datatoc_splash_2x_png[]; extern int datatoc_bfont_pfb_size; extern char datatoc_bfont_pfb[]; -extern int datatoc_bfont_ttf_size; -extern char datatoc_bfont_ttf[]; - -extern int datatoc_bmonofont_ttf_size; -extern char datatoc_bmonofont_ttf[]; - /* Brush icon datafiles */ /* TODO: this could be simplified by putting all * the brush icons in one file */ diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index 66aa301f08c..511e892f29a 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -233,7 +233,6 @@ void ED_gp_project_point_to_plane(const struct Scene *scene, struct bGPDspoint *pt); void ED_gpencil_drawing_reference_get(const struct Scene *scene, const struct Object *ob, - struct bGPDlayer *gpl, char align_flag, float vec[3]); void ED_gpencil_project_stroke_to_view(struct bContext *C, diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h index 1c260bb826a..910cf362a37 100644 --- a/source/blender/editors/include/ED_image.h +++ b/source/blender/editors/include/ED_image.h @@ -65,14 +65,14 @@ int ED_space_image_get_display_channel_mask(struct ImBuf *ibuf); void ED_space_image_release_buffer(struct SpaceImage *sima, struct ImBuf *ibuf, void *lock); bool ED_space_image_has_buffer(struct SpaceImage *sima); -void ED_space_image_get_size(struct SpaceImage *sima, int *width, int *height); -void ED_space_image_get_size_fl(struct SpaceImage *sima, float size[2]); -void ED_space_image_get_aspect(struct SpaceImage *sima, float *aspx, float *aspy); +void ED_space_image_get_size(struct SpaceImage *sima, int *r_width, int *r_height); +void ED_space_image_get_size_fl(struct SpaceImage *sima, float r_size[2]); +void ED_space_image_get_aspect(struct SpaceImage *sima, float *r_aspx, float *r_aspy); void ED_space_image_get_zoom(struct SpaceImage *sima, struct ARegion *region, - float *zoomx, - float *zoomy); -void ED_space_image_get_uv_aspect(struct SpaceImage *sima, float *aspx, float *aspy); + float *r_zoomx, + float *r_zoomy); +void ED_space_image_get_uv_aspect(struct SpaceImage *sima, float *r_aspx, float *r_aspy); void ED_space_image_scopes_update(const struct bContext *C, struct SpaceImage *sima, @@ -83,14 +83,17 @@ void ED_space_image_paint_update(struct Main *bmain, struct wmWindowManager *wm, struct Scene *scene); -void ED_image_get_uv_aspect(struct Image *ima, struct ImageUser *iuser, float *aspx, float *aspy); +void ED_image_get_uv_aspect(struct Image *ima, + struct ImageUser *iuser, + float *r_aspx, + float *r_aspy); void ED_image_mouse_pos(struct SpaceImage *sima, struct ARegion *region, const int mval[2], float co[2]); void ED_image_view_center_to_point(struct SpaceImage *sima, float x, float y); void ED_image_point_pos( - struct SpaceImage *sima, struct ARegion *region, float x, float y, float *xr, float *yr); + struct SpaceImage *sima, struct ARegion *region, float x, float y, float *r_x, float *r_y); void ED_image_point_pos__reverse(struct SpaceImage *sima, struct ARegion *region, const float co[2], diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h index 6abefa98c1a..7d314c0c462 100644 --- a/source/blender/editors/include/ED_mask.h +++ b/source/blender/editors/include/ED_mask.h @@ -36,6 +36,13 @@ struct bContext; struct wmKeyConfig; /* mask_edit.c */ +void ED_mask_deselect_all(const struct bContext *C); + +void ED_operatortypes_mask(void); +void ED_keymap_mask(struct wmKeyConfig *keyconf); +void ED_operatormacros_mask(void); + +/* mask_query.c */ void ED_mask_get_size(struct ScrArea *sa, int *width, int *height); void ED_mask_zoom(struct ScrArea *sa, struct ARegion *region, float *zoomx, float *zoomy); void ED_mask_get_aspect(struct ScrArea *sa, struct ARegion *region, float *aspx, float *aspy); @@ -54,12 +61,6 @@ void ED_mask_point_pos__reverse( void ED_mask_cursor_location_get(struct ScrArea *sa, float cursor[2]); bool ED_mask_selected_minmax(const struct bContext *C, float min[2], float max[2]); -void ED_mask_deselect_all(const struct bContext *C); - -void ED_operatortypes_mask(void); -void ED_keymap_mask(struct wmKeyConfig *keyconf); -void ED_operatormacros_mask(void); - /* mask_draw.c */ void ED_mask_draw(const struct bContext *C, const char draw_flag, const char draw_type); void ED_mask_draw_region(struct Depsgraph *depsgraph, diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h index 511b33bacc5..8c565536c71 100644 --- a/source/blender/editors/include/ED_uvedit.h +++ b/source/blender/editors/include/ED_uvedit.h @@ -188,7 +188,7 @@ bool ED_uvedit_nearest_uv_multi(const struct Scene *scene, float r_uv[2]); void ED_uvedit_get_aspect( - const struct Scene *scene, struct Object *ob, struct BMesh *em, float *aspx, float *aspy); + const struct Scene *scene, struct Object *ob, struct BMesh *em, float *r_aspx, float *r_aspy); /* uvedit_unwrap_ops.c */ void ED_uvedit_live_unwrap_begin(struct Scene *scene, struct Object *obedit); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 06de4705ac6..bb065ee0008 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -674,8 +674,10 @@ bool ED_view3d_distance_set_from_location(struct RegionView3D *rv3d, const float dist_co[3], const float dist_min); -float ED_scene_grid_scale(const struct Scene *scene, const char **grid_unit); -float ED_view3d_grid_scale(const struct Scene *scene, struct View3D *v3d, const char **grid_unit); +float ED_scene_grid_scale(const struct Scene *scene, const char **r_grid_unit); +float ED_view3d_grid_scale(const struct Scene *scene, + struct View3D *v3d, + const char **r_grid_unit); void ED_view3d_grid_steps(const struct Scene *scene, struct View3D *v3d, struct RegionView3D *rv3d, @@ -683,7 +685,7 @@ void ED_view3d_grid_steps(const struct Scene *scene, float ED_view3d_grid_view_scale(struct Scene *scene, struct View3D *v3d, struct RegionView3D *rv3d, - const char **grid_unit); + const char **r_grid_unit); void ED_scene_draw_fps(const struct Scene *scene, int xoffset, int *yoffset); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index bb2edef8adc..1fa6e5b12c1 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -2362,7 +2362,7 @@ void UI_drop_color_copy(struct wmDrag *drag, struct wmDropBox *drop); bool UI_drop_color_poll(struct bContext *C, struct wmDrag *drag, const struct wmEvent *event, - const char **tooltip); + const char **r_tooltip); bool UI_context_copy_to_selected_list(struct bContext *C, struct PointerRNA *ptr, diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c index f69dbb94f19..5fd1cef6451 100644 --- a/source/blender/editors/interface/interface_eyedropper.c +++ b/source/blender/editors/interface/interface_eyedropper.c @@ -54,14 +54,14 @@ wmKeyMap *eyedropper_modal_keymap(wmKeyConfig *keyconf) {0, NULL, 0, NULL, NULL}, }; - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Eyedropper Modal Map"); + wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Eyedropper Modal Map"); /* this function is called for each spacetype, only needs to add map once */ if (keymap && keymap->modal_items) { return NULL; } - keymap = WM_modalkeymap_add(keyconf, "Eyedropper Modal Map", modal_items); + keymap = WM_modalkeymap_ensure(keyconf, "Eyedropper Modal Map", modal_items); /* assign to operators */ WM_modalkeymap_assign(keymap, "UI_OT_eyedropper_colorramp"); @@ -84,12 +84,12 @@ wmKeyMap *eyedropper_colorband_modal_keymap(wmKeyConfig *keyconf) {0, NULL, 0, NULL, NULL}, }; - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Eyedropper ColorRamp PointSampling Map"); + wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Eyedropper ColorRamp PointSampling Map"); if (keymap && keymap->modal_items) { return keymap; } - keymap = WM_modalkeymap_add( + keymap = WM_modalkeymap_ensure( keyconf, "Eyedropper ColorRamp PointSampling Map", modal_items_point); /* assign to operators */ diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 2dfa29f5646..d378613c035 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -3739,12 +3739,7 @@ static void ui_do_but_textedit( if (utf8_buf && utf8_buf[0]) { int utf8_buf_len = BLI_str_utf8_size(utf8_buf); - /* keep this printf until utf8 is well tested */ - if (utf8_buf_len != 1) { - printf("%s: utf8 char '%.*s'\n", __func__, utf8_buf_len, utf8_buf); - } - - // strcpy(utf8_buf, "12345"); + BLI_assert(utf8_buf_len != -1); changed = ui_textedit_insert_buf(but, data, event->utf8_buf, utf8_buf_len); } else { @@ -9694,15 +9689,9 @@ static int ui_handle_menu_event(bContext *C, /* Apply scroll operation. */ if (scrolltype == MENU_SCROLL_DOWN) { but = ui_but_next(but); - if (but == NULL) { - but = ui_but_first(block); - } } else if (scrolltype == MENU_SCROLL_UP) { but = ui_but_prev(but); - if (but == NULL) { - but = ui_but_last(block); - } } else if (scrolltype == MENU_SCROLL_TOP) { but = ui_but_first(block); @@ -9712,6 +9701,20 @@ static int ui_handle_menu_event(bContext *C, } } + if (!but) { + /* wrap button or no active button*/ + uiBut *but_wrap = NULL; + if (ELEM(scrolltype, MENU_SCROLL_UP, MENU_SCROLL_BOTTOM)) { + but_wrap = ui_but_last(block); + } + else if (ELEM(scrolltype, MENU_SCROLL_DOWN, MENU_SCROLL_TOP)) { + but_wrap = ui_but_first(block); + } + if (but_wrap) { + but = but_wrap; + } + } + if (but) { ui_handle_button_activate(C, region, but, BUTTON_ACTIVATE); ui_menu_scroll_to_but(region, block, but); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index fed35ccff59..6c856a0e8dd 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -2771,7 +2771,7 @@ static uiBut *ui_item_menu(uiLayout *layout, } else if (icon) { but = uiDefIconMenuBut(block, func, arg, icon, 0, 0, w, h, tip); - if (force_menu) { + if (force_menu && name[0]) { UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT); } } diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 7533ebd4397..519ba4cbbdf 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -1251,7 +1251,7 @@ static bool ui_editsource_uibut_match(uiBut *but_a, uiBut *but_b) void UI_editsource_active_but_test(uiBut *but) { - extern void PyC_FileAndNum_Safe(const char **filename, int *lineno); + extern void PyC_FileAndNum_Safe(const char **r_filename, int *r_lineno); struct uiEditSourceButStore *but_store = MEM_callocN(sizeof(uiEditSourceButStore), __func__); @@ -1703,7 +1703,7 @@ static void UI_OT_button_string_clear(wmOperatorType *ot) bool UI_drop_color_poll(struct bContext *C, wmDrag *drag, const wmEvent *UNUSED(event), - const char **UNUSED(tooltip)) + const char **UNUSED(r_tooltip)) { /* should only return true for regions that include buttons, for now * return true always */ diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c index fa1f222d27f..63fc7825b26 100644 --- a/source/blender/editors/interface/interface_style.c +++ b/source/blender/editors/interface/interface_style.c @@ -422,8 +422,6 @@ void uiStyleInit(void) { uiFont *font; uiStyle *style = U.uistyles.first; - int monofont_size = datatoc_bmonofont_ttf_size; - uchar *monofont_ttf = (uchar *)datatoc_bmonofont_ttf; /* recover from uninitialized dpi */ if (U.dpi == 0) { @@ -463,39 +461,15 @@ void uiStyleInit(void) } for (font = U.uifonts.first; font; font = font->next) { + const bool unique = false; if (font->uifont_id == UIFONT_DEFAULT) { -#ifdef WITH_INTERNATIONAL - int font_size = datatoc_bfont_ttf_size; - uchar *font_ttf = (uchar *)datatoc_bfont_ttf; - static int last_font_size = 0; - - /* use unicode font for translation */ - if (U.transopts & USER_DOTRANSLATE) { - font_ttf = BLF_get_unifont(&font_size); - - if (!font_ttf) { - /* fall back if not found */ - font_size = datatoc_bfont_ttf_size; - font_ttf = (uchar *)datatoc_bfont_ttf; - } - } - - /* relload only if needed */ - if (last_font_size != font_size) { - BLF_unload("default"); - last_font_size = font_size; - } - - font->blf_id = BLF_load_mem("default", font_ttf, font_size); -#else - font->blf_id = BLF_load_mem("default", (uchar *)datatoc_bfont_ttf, datatoc_bfont_ttf_size); -#endif + font->blf_id = BLF_load_default(unique); } else { font->blf_id = BLF_load(font->filename); if (font->blf_id == -1) { - font->blf_id = BLF_load_mem("default", (uchar *)datatoc_bfont_ttf, datatoc_bfont_ttf_size); + font->blf_id = BLF_load_default(unique); } } @@ -521,27 +495,17 @@ void uiStyleInit(void) ui_style_new(&U.uistyles, "Default Style", UIFONT_DEFAULT); } -#ifdef WITH_INTERNATIONAL - /* use unicode font for text editor and interactive console */ - if (U.transopts & USER_DOTRANSLATE) { - monofont_ttf = BLF_get_unifont_mono(&monofont_size); - - if (!monofont_ttf) { - /* fall back if not found */ - monofont_size = datatoc_bmonofont_ttf_size; - monofont_ttf = (uchar *)datatoc_bmonofont_ttf; - } - } -#endif - /* XXX, this should be moved into a style, * but for now best only load the monospaced font once. */ BLI_assert(blf_mono_font == -1); + /* Use unique font loading to avoid thread safety issues with mono font + * used for render metadata stamp in threads. */ if (U.font_path_ui_mono[0]) { blf_mono_font = BLF_load_unique(U.font_path_ui_mono); } if (blf_mono_font == -1) { - blf_mono_font = BLF_load_mem_unique("monospace", monofont_ttf, monofont_size); + const bool unique = true; + blf_mono_font = BLF_load_mono_default(unique); } BLF_size(blf_mono_font, 12 * U.pixelsize, 72); @@ -584,7 +548,8 @@ void uiStyleInit(void) * keep for now though, since without this there is no way to display many unicode chars. */ if (blf_mono_font_render == -1) { - blf_mono_font_render = BLF_load_mem_unique("monospace", monofont_ttf, monofont_size); + const bool unique = true; + blf_mono_font_render = BLF_load_mono_default(unique); } BLF_size(blf_mono_font_render, 12 * U.pixelsize, 72); diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 7e6ef11518a..fa4a0a1e07d 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -2520,6 +2520,13 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle, } } else if (but->drawflag & UI_BUT_TEXT_LEFT) { + + /* Reduce the left padding for labels without an icon. */ + if ((but->type == UI_BTYPE_LABEL) && !(but->flag & UI_HAS_ICON) && + !ui_block_is_menu(but->block)) { + text_padding /= 2; + } + rect->xmin += text_padding; } else if (but->drawflag & UI_BUT_TEXT_RIGHT) { diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index a93c80f02d2..adf0d6e372c 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -67,8 +67,8 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas BLI_INLINE int clamp_float_to_int(const float f) { - const float min = INT_MIN; - const float max = INT_MAX; + const float min = (float)INT_MIN; + const float max = (float)INT_MAX; if (UNLIKELY(f < min)) { return min; diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 17af0cff23a..2adf441514b 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -62,7 +62,7 @@ static bool view2d_poll(bContext *C) /** \} */ /* -------------------------------------------------------------------- */ -/** \name View Pan Operator +/** \name View Pan Shared Utilities * \{ */ /** @@ -74,9 +74,9 @@ static bool view2d_poll(bContext *C) * - `deltax, deltay` - define how much to move view by (relative to zoom-correction factor) */ -/* ------------------ Shared 'core' stuff ---------------------- */ - -/* temp customdata for operator */ +/** + * Temporary custom-data for operator. + */ typedef struct v2dViewPanData { /** screen where view pan was initiated */ bScreen *sc; @@ -209,7 +209,11 @@ static void view_pan_exit(wmOperator *op) } } -/* ------------------ Modal Drag Version (1) ---------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Pan Operator (modal drag-pan) + * \{ */ /* for 'redo' only, with no user input */ static int view_pan_exec(bContext *C, wmOperator *op) @@ -350,7 +354,11 @@ static void VIEW2D_OT_pan(wmOperatorType *ot) RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX); } -/* ------------------ Scrollwheel Versions (2) ---------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Pan Operator (single step) + * \{ */ /* this operator only needs this single callback, where it calls the view_pan_*() methods */ static int view_scrollright_exec(bContext *C, wmOperator *op) @@ -541,7 +549,7 @@ static void VIEW2D_OT_scroll_up(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ -/** \name View Zoom Operator (single-step) +/** \name View Zoom Shared Utilities * \{ */ /** @@ -558,9 +566,9 @@ static void VIEW2D_OT_scroll_up(wmOperatorType *ot) * amount to enlarge 'cur' by. */ -/* ------------------ 'Shared' stuff ------------------------ */ - -/* temp customdata for operator */ +/** + * Temporary custom-data for operator. + */ typedef struct v2dViewZoomData { View2D *v2d; /* view2d we're operating in */ ARegion *region; @@ -768,7 +776,11 @@ static void view_zoomstep_apply(bContext *C, wmOperator *op) C, vzd, zoom_to_pos, RNA_float_get(op->ptr, "zoomfacx"), RNA_float_get(op->ptr, "zoomfacy")); } -/* --------------- Individual Operators ------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Zoom Operator (single step) + * \{ */ /* cleanup temp customdata */ static void view_zoomstep_exit(wmOperator *op) @@ -1400,6 +1412,12 @@ static void VIEW2D_OT_zoom_border(wmOperatorType *ot) WM_operator_properties_gesture_box_zoom(ot); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name NDOF Pan/Zoom Operator + * \{ */ + #ifdef WITH_INPUT_NDOF static int view2d_ndof_invoke(bContext *C, wmOperator *op, const wmEvent *event) { @@ -1731,8 +1749,6 @@ enum { SCROLLHANDLE_MAX_OUTSIDE, } /*eV2DScrollerHandle_Zone*/; -/* ------------------------ */ - /** * Check if mouse is within scroller handle. * diff --git a/source/blender/editors/mask/CMakeLists.txt b/source/blender/editors/mask/CMakeLists.txt index 81c861ab4e4..66c055d9426 100644 --- a/source/blender/editors/mask/CMakeLists.txt +++ b/source/blender/editors/mask/CMakeLists.txt @@ -40,6 +40,7 @@ set(SRC mask_edit.c mask_editaction.c mask_ops.c + mask_query.c mask_relationships.c mask_select.c mask_shapekey.c diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index 80716195121..9945383211a 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -29,7 +29,6 @@ #include "BKE_mask.h" #include "DEG_depsgraph.h" -#include "DEG_depsgraph_query.h" #include "DNA_mask_types.h" #include "DNA_scene_types.h" @@ -47,158 +46,6 @@ #include "mask_intern.h" /* own include */ -bool ED_mask_find_nearest_diff_point(const bContext *C, - struct Mask *mask_orig, - const float normal_co[2], - int threshold, - bool feather, - float tangent[2], - const bool use_deform, - const bool use_project, - MaskLayer **mask_layer_r, - MaskSpline **spline_r, - MaskSplinePoint **point_r, - float *u_r, - float *score_r) -{ - ScrArea *sa = CTX_wm_area(C); - ARegion *region = CTX_wm_region(C); - - MaskLayer *point_mask_layer; - MaskSpline *point_spline; - MaskSplinePoint *point = NULL; - float dist_best_sq = FLT_MAX, co[2]; - int width, height; - float u = 0.0f; - float scalex, scaley; - - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_orig->id); - - ED_mask_get_size(sa, &width, &height); - ED_mask_pixelspace_factor(sa, region, &scalex, &scaley); - - co[0] = normal_co[0] * scalex; - co[1] = normal_co[1] * scaley; - - for (MaskLayer *mask_layer_orig = mask_orig->masklayers.first, - *mask_layer_eval = mask_eval->masklayers.first; - mask_layer_orig != NULL; - mask_layer_orig = mask_layer_orig->next, mask_layer_eval = mask_layer_eval->next) { - if (mask_layer_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { - continue; - } - - for (MaskSpline *spline_orig = mask_layer_orig->splines.first, - *spline_eval = mask_layer_eval->splines.first; - spline_orig != NULL; - spline_orig = spline_orig->next, spline_eval = spline_eval->next) { - int i; - MaskSplinePoint *cur_point_eval; - - for (i = 0, cur_point_eval = use_deform ? spline_eval->points_deform : spline_eval->points; - i < spline_eval->tot_point; - i++, cur_point_eval++) { - unsigned int tot_diff_point; - float *diff_points = BKE_mask_point_segment_diff( - spline_eval, cur_point_eval, width, height, &tot_diff_point); - - if (diff_points) { - int j, tot_point; - unsigned int tot_feather_point; - float *feather_points = NULL, *points; - - if (feather) { - feather_points = BKE_mask_point_segment_feather_diff( - spline_eval, cur_point_eval, width, height, &tot_feather_point); - - points = feather_points; - tot_point = tot_feather_point; - } - else { - points = diff_points; - tot_point = tot_diff_point; - } - - for (j = 0; j < tot_point - 1; j++) { - float dist_sq, a[2], b[2]; - - a[0] = points[2 * j] * scalex; - a[1] = points[2 * j + 1] * scaley; - - b[0] = points[2 * j + 2] * scalex; - b[1] = points[2 * j + 3] * scaley; - - dist_sq = dist_squared_to_line_segment_v2(co, a, b); - - if (dist_sq < dist_best_sq) { - if (tangent) { - sub_v2_v2v2(tangent, &diff_points[2 * j + 2], &diff_points[2 * j]); - } - - point_mask_layer = mask_layer_orig; - point_spline = spline_orig; - point = use_deform ? - &spline_orig->points[(cur_point_eval - spline_eval->points_deform)] : - &spline_orig->points[(cur_point_eval - spline_eval->points)]; - dist_best_sq = dist_sq; - u = (float)j / tot_point; - } - } - - if (feather_points != NULL) { - MEM_freeN(feather_points); - } - MEM_freeN(diff_points); - } - } - } - } - - if (point && dist_best_sq < threshold) { - if (mask_layer_r) { - *mask_layer_r = point_mask_layer; - } - - if (spline_r) { - *spline_r = point_spline; - } - - if (point_r) { - *point_r = point; - } - - if (u_r) { - /* TODO(sergey): Projection fails in some weirdo cases.. */ - if (use_project) { - u = BKE_mask_spline_project_co(point_spline, point, u, normal_co, MASK_PROJ_ANY); - } - - *u_r = u; - } - - if (score_r) { - *score_r = dist_best_sq; - } - - return true; - } - - if (mask_layer_r) { - *mask_layer_r = NULL; - } - - if (spline_r) { - *spline_r = NULL; - } - - if (point_r) { - *point_r = NULL; - } - - return false; -} - /******************** add vertex *********************/ static void setup_vertex_point(Mask *mask, diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index a532ff9e1f0..2fda383ebb7 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -54,8 +54,6 @@ #include "DEG_depsgraph_query.h" -#include "mask_intern.h" /* own include */ - static void mask_spline_color_get(MaskLayer *mask_layer, MaskSpline *spline, const bool is_sel, diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c index 1606d079462..e696cc37bd3 100644 --- a/source/blender/editors/mask/mask_edit.c +++ b/source/blender/editors/mask/mask_edit.c @@ -21,12 +21,9 @@ * \ingroup edmask */ -#include "BLI_math.h" - #include "BKE_context.h" #include "BKE_mask.h" -#include "DNA_mask_types.h" #include "DNA_scene_types.h" #include "WM_api.h" @@ -34,20 +31,16 @@ #include "ED_clip.h" #include "ED_image.h" -#include "ED_mask.h" /* own include */ -#include "ED_object.h" /* ED_keymap_proportional_maskmode only */ -#include "ED_screen.h" -#include "ED_select_utils.h" +#include "ED_mask.h" /* own include */ #include "ED_sequencer.h" -#include "ED_transform.h" - -#include "UI_view2d.h" #include "RNA_access.h" #include "mask_intern.h" /* own include */ -/********************** generic poll functions *********************/ +/* -------------------------------------------------------------------- */ +/** \name Poll Functions + * \{ */ bool ED_maskedit_poll(bContext *C) { @@ -81,344 +74,11 @@ bool ED_maskedit_mask_poll(bContext *C) return false; } -/********************** registration *********************/ - -/* takes event->mval */ -void ED_mask_mouse_pos(ScrArea *sa, ARegion *region, const int mval[2], float co[2]) -{ - if (sa) { - switch (sa->spacetype) { - case SPACE_CLIP: { - SpaceClip *sc = sa->spacedata.first; - ED_clip_mouse_pos(sc, region, mval, co); - BKE_mask_coord_from_movieclip(sc->clip, &sc->user, co, co); - break; - } - case SPACE_SEQ: { - UI_view2d_region_to_view(®ion->v2d, mval[0], mval[1], &co[0], &co[1]); - break; - } - case SPACE_IMAGE: { - SpaceImage *sima = sa->spacedata.first; - ED_image_mouse_pos(sima, region, mval, co); - BKE_mask_coord_from_image(sima->image, &sima->iuser, co, co); - break; - } - default: - /* possible other spaces from which mask editing is available */ - BLI_assert(0); - zero_v2(co); - break; - } - } - else { - BLI_assert(0); - zero_v2(co); - } -} - -/* input: x/y - mval space - * output: xr/yr - mask point space */ -void ED_mask_point_pos(ScrArea *sa, ARegion *region, float x, float y, float *xr, float *yr) -{ - float co[2]; - - if (sa) { - switch (sa->spacetype) { - case SPACE_CLIP: { - SpaceClip *sc = sa->spacedata.first; - ED_clip_point_stable_pos(sc, region, x, y, &co[0], &co[1]); - BKE_mask_coord_from_movieclip(sc->clip, &sc->user, co, co); - break; - } - case SPACE_SEQ: - zero_v2(co); /* MASKTODO */ - break; - case SPACE_IMAGE: { - SpaceImage *sima = sa->spacedata.first; - ED_image_point_pos(sima, region, x, y, &co[0], &co[1]); - BKE_mask_coord_from_image(sima->image, &sima->iuser, co, co); - break; - } - default: - /* possible other spaces from which mask editing is available */ - BLI_assert(0); - zero_v2(co); - break; - } - } - else { - BLI_assert(0); - zero_v2(co); - } - - *xr = co[0]; - *yr = co[1]; -} - -void ED_mask_point_pos__reverse( - ScrArea *sa, ARegion *region, float x, float y, float *xr, float *yr) -{ - float co[2]; - - if (sa) { - switch (sa->spacetype) { - case SPACE_CLIP: { - SpaceClip *sc = sa->spacedata.first; - co[0] = x; - co[1] = y; - BKE_mask_coord_to_movieclip(sc->clip, &sc->user, co, co); - ED_clip_point_stable_pos__reverse(sc, region, co, co); - break; - } - case SPACE_SEQ: - zero_v2(co); /* MASKTODO */ - break; - case SPACE_IMAGE: { - SpaceImage *sima = sa->spacedata.first; - co[0] = x; - co[1] = y; - BKE_mask_coord_to_image(sima->image, &sima->iuser, co, co); - ED_image_point_pos__reverse(sima, region, co, co); - break; - } - default: - /* possible other spaces from which mask editing is available */ - BLI_assert(0); - zero_v2(co); - break; - } - } - else { - BLI_assert(0); - zero_v2(co); - } - - *xr = co[0]; - *yr = co[1]; -} - -void ED_mask_get_size(ScrArea *sa, int *width, int *height) -{ - if (sa && sa->spacedata.first) { - switch (sa->spacetype) { - case SPACE_CLIP: { - SpaceClip *sc = sa->spacedata.first; - ED_space_clip_get_size(sc, width, height); - break; - } - case SPACE_SEQ: { - // Scene *scene = CTX_data_scene(C); - // *width = (scene->r.size * scene->r.xsch) / 100; - // *height = (scene->r.size * scene->r.ysch) / 100; - break; - } - case SPACE_IMAGE: { - SpaceImage *sima = sa->spacedata.first; - ED_space_image_get_size(sima, width, height); - break; - } - default: - /* possible other spaces from which mask editing is available */ - BLI_assert(0); - *width = 0; - *height = 0; - break; - } - } - else { - BLI_assert(0); - *width = 0; - *height = 0; - } -} - -void ED_mask_zoom(ScrArea *sa, ARegion *region, float *zoomx, float *zoomy) -{ - if (sa && sa->spacedata.first) { - switch (sa->spacetype) { - case SPACE_CLIP: { - SpaceClip *sc = sa->spacedata.first; - ED_space_clip_get_zoom(sc, region, zoomx, zoomy); - break; - } - case SPACE_SEQ: { - *zoomx = *zoomy = 1.0f; - break; - } - case SPACE_IMAGE: { - SpaceImage *sima = sa->spacedata.first; - ED_space_image_get_zoom(sima, region, zoomx, zoomy); - break; - } - default: - /* possible other spaces from which mask editing is available */ - BLI_assert(0); - *zoomx = *zoomy = 1.0f; - break; - } - } - else { - BLI_assert(0); - *zoomx = *zoomy = 1.0f; - } -} - -void ED_mask_get_aspect(ScrArea *sa, ARegion *UNUSED(region), float *aspx, float *aspy) -{ - if (sa && sa->spacedata.first) { - switch (sa->spacetype) { - case SPACE_CLIP: { - SpaceClip *sc = sa->spacedata.first; - ED_space_clip_get_aspect(sc, aspx, aspy); - break; - } - case SPACE_SEQ: { - *aspx = *aspy = 1.0f; /* MASKTODO - render aspect? */ - break; - } - case SPACE_IMAGE: { - SpaceImage *sima = sa->spacedata.first; - ED_space_image_get_aspect(sima, aspx, aspy); - break; - } - default: - /* possible other spaces from which mask editing is available */ - BLI_assert(0); - *aspx = *aspy = 1.0f; - break; - } - } - else { - BLI_assert(0); - *aspx = *aspy = 1.0f; - } -} - -void ED_mask_pixelspace_factor(ScrArea *sa, ARegion *region, float *scalex, float *scaley) -{ - if (sa && sa->spacedata.first) { - switch (sa->spacetype) { - case SPACE_CLIP: { - SpaceClip *sc = sa->spacedata.first; - float aspx, aspy; - - UI_view2d_scale_get(®ion->v2d, scalex, scaley); - ED_space_clip_get_aspect(sc, &aspx, &aspy); +/** \} */ - *scalex *= aspx; - *scaley *= aspy; - break; - } - case SPACE_SEQ: { - *scalex = *scaley = 1.0f; /* MASKTODO? */ - break; - } - case SPACE_IMAGE: { - SpaceImage *sima = sa->spacedata.first; - float aspx, aspy; - - UI_view2d_scale_get(®ion->v2d, scalex, scaley); - ED_space_image_get_aspect(sima, &aspx, &aspy); - - *scalex *= aspx; - *scaley *= aspy; - break; - } - default: - /* possible other spaces from which mask editing is available */ - BLI_assert(0); - *scalex = *scaley = 1.0f; - break; - } - } - else { - BLI_assert(0); - *scalex = *scaley = 1.0f; - } -} - -void ED_mask_cursor_location_get(ScrArea *sa, float cursor[2]) -{ - if (sa) { - switch (sa->spacetype) { - case SPACE_CLIP: { - SpaceClip *space_clip = sa->spacedata.first; - copy_v2_v2(cursor, space_clip->cursor); - break; - } - case SPACE_SEQ: { - zero_v2(cursor); - break; - } - case SPACE_IMAGE: { - SpaceImage *space_image = sa->spacedata.first; - copy_v2_v2(cursor, space_image->cursor); - break; - } - default: - /* possible other spaces from which mask editing is available */ - BLI_assert(0); - zero_v2(cursor); - break; - } - } - else { - BLI_assert(0); - zero_v2(cursor); - } -} - -bool ED_mask_selected_minmax(const bContext *C, float min[2], float max[2]) -{ - Mask *mask = CTX_data_edit_mask(C); - bool ok = false; - - if (mask == NULL) { - return ok; - } - - INIT_MINMAX2(min, max); - for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer != NULL; - mask_layer = mask_layer->next) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { - continue; - } - for (MaskSpline *spline = mask_layer->splines.first; spline != NULL; spline = spline->next) { - MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); - for (int i = 0; i < spline->tot_point; i++) { - MaskSplinePoint *point = &spline->points[i]; - MaskSplinePoint *deform_point = &points_array[i]; - BezTriple *bezt = &point->bezt; - float handle[2]; - if (!MASKPOINT_ISSEL_ANY(point)) { - continue; - } - if (bezt->f2 & SELECT) { - minmax_v2v2_v2(min, max, deform_point->bezt.vec[1]); - } - if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) { - BKE_mask_point_handle(deform_point, MASK_WHICH_HANDLE_STICK, handle); - minmax_v2v2_v2(min, max, handle); - } - else { - if ((bezt->f1 & SELECT) && (bezt->h1 != HD_VECT)) { - BKE_mask_point_handle(deform_point, MASK_WHICH_HANDLE_LEFT, handle); - minmax_v2v2_v2(min, max, handle); - } - if ((bezt->f3 & SELECT) && (bezt->h2 != HD_VECT)) { - BKE_mask_point_handle(deform_point, MASK_WHICH_HANDLE_RIGHT, handle); - minmax_v2v2_v2(min, max, handle); - } - } - ok = true; - } - } - } - return ok; -} - -/********************** registration *********************/ +/* -------------------------------------------------------------------- */ +/** \name Registration + * \{ */ void ED_operatortypes_mask(void) { @@ -522,3 +182,5 @@ void ED_operatormacros_mask(void) RNA_boolean_set(otmacro->ptr, "use_proportional_edit", false); RNA_boolean_set(otmacro->ptr, "mirror", false); } + +/** \} */ diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h index 091cf4937ae..6a45af4d2a6 100644 --- a/source/blender/editors/mask/mask_intern.h +++ b/source/blender/editors/mask/mask_intern.h @@ -31,20 +31,6 @@ struct wmOperatorType; /* internal exports only */ /* mask_add.c */ -bool ED_mask_find_nearest_diff_point(const struct bContext *C, - struct Mask *mask, - const float normal_co[2], - int threshold, - bool feather, - float tangent[2], - const bool use_deform, - const bool use_project, - struct MaskLayer **mask_layer_r, - struct MaskSpline **spline_r, - struct MaskSplinePoint **point_r, - float *u_r, - float *score_r); - void MASK_OT_add_vertex(struct wmOperatorType *ot); void MASK_OT_add_feather_vertex(struct wmOperatorType *ot); void MASK_OT_primitive_circle_add(struct wmOperatorType *ot); @@ -72,25 +58,6 @@ void MASK_OT_normals_make_consistent(struct wmOperatorType *ot); void MASK_OT_handle_type_set(struct wmOperatorType *ot); -bool ED_mask_feather_find_nearest(const struct bContext *C, - struct Mask *mask, - const float normal_co[2], - const float threshold, - struct MaskLayer **mask_layer_r, - struct MaskSpline **spline_r, - struct MaskSplinePoint **point_r, - struct MaskSplinePointUW **uw_r, - float *score); - -struct MaskSplinePoint *ED_mask_point_find_nearest(const struct bContext *C, - struct Mask *mask, - const float normal_co[2], - const float threshold, - struct MaskLayer **mask_layer_r, - struct MaskSpline **spline_r, - eMaskWhichHandle *which_handle_r, - float *score); - void MASK_OT_layer_move(struct wmOperatorType *ot); void MASK_OT_duplicate(struct wmOperatorType *ot); @@ -126,6 +93,38 @@ void ED_mask_select_flush_all(struct Mask *mask); bool ED_maskedit_poll(struct bContext *C); bool ED_maskedit_mask_poll(struct bContext *C); +/* mask_query.c */ +bool ED_mask_find_nearest_diff_point(const struct bContext *C, + struct Mask *mask, + const float normal_co[2], + int threshold, + bool feather, + float tangent[2], + const bool use_deform, + const bool use_project, + struct MaskLayer **r_mask_layer, + struct MaskSpline **r_spline, + struct MaskSplinePoint **r_point, + float *r_u, + float *r_score); +bool ED_mask_feather_find_nearest(const struct bContext *C, + struct Mask *mask, + const float normal_co[2], + const float threshold, + struct MaskLayer **r_mask_layer, + struct MaskSpline **r_spline, + struct MaskSplinePoint **r_point, + struct MaskSplinePointUW **r_uw, + float *r_score); +struct MaskSplinePoint *ED_mask_point_find_nearest(const struct bContext *C, + struct Mask *mask, + const float normal_co[2], + const float threshold, + struct MaskLayer **r_mask_layer, + struct MaskSpline **r_spline, + eMaskWhichHandle *r_which_handle, + float *r_score); + /* mask_shapekey.c */ void MASK_OT_shape_key_insert(struct wmOperatorType *ot); void MASK_OT_shape_key_clear(struct wmOperatorType *ot); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 5e7d94dd567..c4e3763dd94 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -31,7 +31,6 @@ #include "BKE_mask.h" #include "DEG_depsgraph.h" -#include "DEG_depsgraph_query.h" #include "DNA_mask_types.h" #include "DNA_object_types.h" /* SELECT */ @@ -52,298 +51,6 @@ #include "mask_intern.h" /* own include */ -/******************** utility functions *********************/ - -static void mask_point_scaled_handle(/*const*/ MaskSplinePoint *point, - /*const*/ eMaskWhichHandle which_handle, - const float scalex, - const float scaley, - float handle[2]) -{ - BKE_mask_point_handle(point, which_handle, handle); - handle[0] *= scalex; - handle[1] *= scaley; -} - -MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, - Mask *mask_orig, - const float normal_co[2], - const float threshold, - MaskLayer **mask_layer_r, - MaskSpline **spline_r, - eMaskWhichHandle *which_handle_r, - float *score) -{ - ScrArea *sa = CTX_wm_area(C); - ARegion *region = CTX_wm_region(C); - - MaskLayer *point_mask_layer = NULL; - MaskSpline *point_spline = NULL; - MaskSplinePoint *point = NULL; - float co[2]; - const float threshold_sq = threshold * threshold; - float len_sq = FLT_MAX, scalex, scaley; - eMaskWhichHandle which_handle = MASK_WHICH_HANDLE_NONE; - int width, height; - - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_orig->id); - - ED_mask_get_size(sa, &width, &height); - ED_mask_pixelspace_factor(sa, region, &scalex, &scaley); - - co[0] = normal_co[0] * scalex; - co[1] = normal_co[1] * scaley; - - for (MaskLayer *mask_layer_orig = mask_orig->masklayers.first, - *mask_layer_eval = mask_eval->masklayers.first; - mask_layer_orig != NULL; - mask_layer_orig = mask_layer_orig->next, mask_layer_eval = mask_layer_eval->next) { - - if (mask_layer_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { - continue; - } - - for (MaskSpline *spline_orig = mask_layer_orig->splines.first, - *spline_eval = mask_layer_eval->splines.first; - spline_orig != NULL; - spline_orig = spline_orig->next, spline_eval = spline_eval->next) { - MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline_eval); - - for (int i = 0; i < spline_orig->tot_point; i++) { - MaskSplinePoint *cur_point_orig = &spline_orig->points[i]; - MaskSplinePoint *cur_point_deform_eval = &points_array[i]; - eMaskWhichHandle cur_which_handle = MASK_WHICH_HANDLE_NONE; - BezTriple *bezt = &cur_point_deform_eval->bezt; - float cur_len_sq, vec[2]; - - vec[0] = bezt->vec[1][0] * scalex; - vec[1] = bezt->vec[1][1] * scaley; - - cur_len_sq = len_squared_v2v2(co, vec); - - if (cur_len_sq < len_sq) { - point_spline = spline_orig; - point_mask_layer = mask_layer_orig; - point = cur_point_orig; - len_sq = cur_len_sq; - which_handle = MASK_WHICH_HANDLE_NONE; - } - - if (BKE_mask_point_handles_mode_get(cur_point_deform_eval) == MASK_HANDLE_MODE_STICK) { - float handle[2]; - mask_point_scaled_handle( - cur_point_deform_eval, MASK_WHICH_HANDLE_STICK, scalex, scaley, handle); - cur_len_sq = len_squared_v2v2(co, handle); - cur_which_handle = MASK_WHICH_HANDLE_STICK; - } - else { - float handle_left[2], handle_right[2]; - float len_left_sq, len_right_sq; - mask_point_scaled_handle( - cur_point_deform_eval, MASK_WHICH_HANDLE_LEFT, scalex, scaley, handle_left); - mask_point_scaled_handle( - cur_point_deform_eval, MASK_WHICH_HANDLE_RIGHT, scalex, scaley, handle_right); - - len_left_sq = len_squared_v2v2(co, handle_left); - len_right_sq = len_squared_v2v2(co, handle_right); - if (i == 0) { - if (len_left_sq <= len_right_sq) { - if (bezt->h1 != HD_VECT) { - cur_which_handle = MASK_WHICH_HANDLE_LEFT; - cur_len_sq = len_left_sq; - } - } - else if (bezt->h2 != HD_VECT) { - cur_which_handle = MASK_WHICH_HANDLE_RIGHT; - cur_len_sq = len_right_sq; - } - } - else { - if (len_right_sq <= len_left_sq) { - if (bezt->h2 != HD_VECT) { - cur_which_handle = MASK_WHICH_HANDLE_RIGHT; - cur_len_sq = len_right_sq; - } - } - else if (bezt->h1 != HD_VECT) { - cur_which_handle = MASK_WHICH_HANDLE_LEFT; - cur_len_sq = len_left_sq; - } - } - } - - if (cur_len_sq <= len_sq && cur_which_handle != MASK_WHICH_HANDLE_NONE) { - point_mask_layer = mask_layer_orig; - point_spline = spline_orig; - point = cur_point_orig; - len_sq = cur_len_sq; - which_handle = cur_which_handle; - } - } - } - } - - if (len_sq < threshold_sq) { - if (mask_layer_r) { - *mask_layer_r = point_mask_layer; - } - - if (spline_r) { - *spline_r = point_spline; - } - - if (which_handle_r) { - *which_handle_r = which_handle; - } - - if (score) { - *score = sqrtf(len_sq); - } - - return point; - } - - if (mask_layer_r) { - *mask_layer_r = NULL; - } - - if (spline_r) { - *spline_r = NULL; - } - - if (which_handle_r) { - *which_handle_r = MASK_WHICH_HANDLE_NONE; - } - - return NULL; -} - -bool ED_mask_feather_find_nearest(const bContext *C, - Mask *mask_orig, - const float normal_co[2], - const float threshold, - MaskLayer **mask_layer_r, - MaskSpline **spline_r, - MaskSplinePoint **point_r, - MaskSplinePointUW **uw_r, - float *score) -{ - ScrArea *sa = CTX_wm_area(C); - ARegion *region = CTX_wm_region(C); - - MaskLayer *point_mask_layer = NULL; - MaskSpline *point_spline = NULL; - MaskSplinePoint *point = NULL; - MaskSplinePointUW *uw = NULL; - const float threshold_sq = threshold * threshold; - float len = FLT_MAX, co[2]; - float scalex, scaley; - int width, height; - - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_orig->id); - - ED_mask_get_size(sa, &width, &height); - ED_mask_pixelspace_factor(sa, region, &scalex, &scaley); - - co[0] = normal_co[0] * scalex; - co[1] = normal_co[1] * scaley; - - for (MaskLayer *mask_layer_orig = mask_orig->masklayers.first, - *mask_layer_eval = mask_eval->masklayers.first; - mask_layer_orig != NULL; - mask_layer_orig = mask_layer_orig->next, mask_layer_eval = mask_layer_eval->next) { - - for (MaskSpline *spline_orig = mask_layer_orig->splines.first, - *spline_eval = mask_layer_eval->splines.first; - spline_orig != NULL; - spline_orig = spline_orig->next, spline_eval = spline_eval->next) { - // MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); - - int i, tot_feather_point; - float(*feather_points)[2], (*fp)[2]; - - if (mask_layer_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { - continue; - } - - feather_points = fp = BKE_mask_spline_feather_points(spline_eval, &tot_feather_point); - - for (i = 0; i < spline_orig->tot_point; i++) { - int j; - MaskSplinePoint *cur_point_orig = &spline_orig->points[i]; - MaskSplinePoint *cur_point_eval = &spline_eval->points[i]; - - for (j = 0; j <= cur_point_eval->tot_uw; j++) { - float cur_len_sq, vec[2]; - - vec[0] = (*fp)[0] * scalex; - vec[1] = (*fp)[1] * scaley; - - cur_len_sq = len_squared_v2v2(vec, co); - - if (point == NULL || cur_len_sq < len) { - if (j == 0) { - uw = NULL; - } - else { - uw = &cur_point_orig->uw[j - 1]; - } - - point_mask_layer = mask_layer_orig; - point_spline = spline_orig; - point = cur_point_orig; - len = cur_len_sq; - } - - fp++; - } - } - - MEM_freeN(feather_points); - } - } - - if (len < threshold_sq) { - if (mask_layer_r) { - *mask_layer_r = point_mask_layer; - } - - if (spline_r) { - *spline_r = point_spline; - } - - if (point_r) { - *point_r = point; - } - - if (uw_r) { - *uw_r = uw; - } - - if (score) { - *score = sqrtf(len); - } - - return true; - } - - if (mask_layer_r) { - *mask_layer_r = NULL; - } - - if (spline_r) { - *spline_r = NULL; - } - - if (point_r) { - *point_r = NULL; - } - - return false; -} - /******************** create new mask *********************/ Mask *ED_mask_new(bContext *C, const char *name) @@ -549,8 +256,8 @@ static void mask_point_undistort_pos(SpaceClip *sc, float r_co[2], const float c static bool spline_under_mouse_get(const bContext *C, Mask *mask, const float co[2], - MaskLayer **mask_layer_r, - MaskSpline **mask_spline_r) + MaskLayer **r_mask_layer, + MaskSpline **r_mask_spline) { const float threshold = 19.0f; ScrArea *sa = CTX_wm_area(C); @@ -561,8 +268,8 @@ static bool spline_under_mouse_get(const bContext *C, MaskLayer *closest_layer = NULL; MaskSpline *closest_spline = NULL; bool undistort = false; - *mask_layer_r = NULL; - *mask_spline_r = NULL; + *r_mask_layer = NULL; + *r_mask_spline = NULL; ED_mask_get_size(sa, &width, &height); pixel_co[0] = co[0] * width; pixel_co[1] = co[1] * height; @@ -634,8 +341,8 @@ static bool spline_under_mouse_get(const bContext *C, } } - *mask_layer_r = closest_layer; - *mask_spline_r = closest_spline; + *r_mask_layer = closest_layer; + *r_mask_spline = closest_spline; return true; } return false; diff --git a/source/blender/editors/mask/mask_query.c b/source/blender/editors/mask/mask_query.c new file mode 100644 index 00000000000..8caf5f2ed7b --- /dev/null +++ b/source/blender/editors/mask/mask_query.c @@ -0,0 +1,833 @@ +/* + * 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) 2012 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup edmask + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_mask.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + +#include "DNA_mask_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" + +#include "ED_clip.h" +#include "ED_image.h" +#include "ED_mask.h" /* own include */ + +#include "UI_view2d.h" + +#include "mask_intern.h" /* own include */ + +/* -------------------------------------------------------------------- */ +/** \name Spatial Queries + * \{ */ + +bool ED_mask_find_nearest_diff_point(const bContext *C, + struct Mask *mask_orig, + const float normal_co[2], + int threshold, + bool feather, + float tangent[2], + const bool use_deform, + const bool use_project, + MaskLayer **r_mask_layer, + MaskSpline **r_spline, + MaskSplinePoint **r_point, + float *r_u, + float *r_score) +{ + ScrArea *sa = CTX_wm_area(C); + ARegion *region = CTX_wm_region(C); + + MaskLayer *point_mask_layer; + MaskSpline *point_spline; + MaskSplinePoint *point = NULL; + float dist_best_sq = FLT_MAX, co[2]; + int width, height; + float u = 0.0f; + float scalex, scaley; + + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_orig->id); + + ED_mask_get_size(sa, &width, &height); + ED_mask_pixelspace_factor(sa, region, &scalex, &scaley); + + co[0] = normal_co[0] * scalex; + co[1] = normal_co[1] * scaley; + + for (MaskLayer *mask_layer_orig = mask_orig->masklayers.first, + *mask_layer_eval = mask_eval->masklayers.first; + mask_layer_orig != NULL; + mask_layer_orig = mask_layer_orig->next, mask_layer_eval = mask_layer_eval->next) { + if (mask_layer_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + for (MaskSpline *spline_orig = mask_layer_orig->splines.first, + *spline_eval = mask_layer_eval->splines.first; + spline_orig != NULL; + spline_orig = spline_orig->next, spline_eval = spline_eval->next) { + int i; + MaskSplinePoint *cur_point_eval; + + for (i = 0, cur_point_eval = use_deform ? spline_eval->points_deform : spline_eval->points; + i < spline_eval->tot_point; + i++, cur_point_eval++) { + unsigned int tot_diff_point; + float *diff_points = BKE_mask_point_segment_diff( + spline_eval, cur_point_eval, width, height, &tot_diff_point); + + if (diff_points) { + int j, tot_point; + unsigned int tot_feather_point; + float *feather_points = NULL, *points; + + if (feather) { + feather_points = BKE_mask_point_segment_feather_diff( + spline_eval, cur_point_eval, width, height, &tot_feather_point); + + points = feather_points; + tot_point = tot_feather_point; + } + else { + points = diff_points; + tot_point = tot_diff_point; + } + + for (j = 0; j < tot_point - 1; j++) { + float dist_sq, a[2], b[2]; + + a[0] = points[2 * j] * scalex; + a[1] = points[2 * j + 1] * scaley; + + b[0] = points[2 * j + 2] * scalex; + b[1] = points[2 * j + 3] * scaley; + + dist_sq = dist_squared_to_line_segment_v2(co, a, b); + + if (dist_sq < dist_best_sq) { + if (tangent) { + sub_v2_v2v2(tangent, &diff_points[2 * j + 2], &diff_points[2 * j]); + } + + point_mask_layer = mask_layer_orig; + point_spline = spline_orig; + point = use_deform ? + &spline_orig->points[(cur_point_eval - spline_eval->points_deform)] : + &spline_orig->points[(cur_point_eval - spline_eval->points)]; + dist_best_sq = dist_sq; + u = (float)j / tot_point; + } + } + + if (feather_points != NULL) { + MEM_freeN(feather_points); + } + MEM_freeN(diff_points); + } + } + } + } + + if (point && dist_best_sq < threshold) { + if (r_mask_layer) { + *r_mask_layer = point_mask_layer; + } + + if (r_spline) { + *r_spline = point_spline; + } + + if (r_point) { + *r_point = point; + } + + if (r_u) { + /* TODO(sergey): Projection fails in some weirdo cases.. */ + if (use_project) { + u = BKE_mask_spline_project_co(point_spline, point, u, normal_co, MASK_PROJ_ANY); + } + + *r_u = u; + } + + if (r_score) { + *r_score = dist_best_sq; + } + + return true; + } + + if (r_mask_layer) { + *r_mask_layer = NULL; + } + + if (r_spline) { + *r_spline = NULL; + } + + if (r_point) { + *r_point = NULL; + } + + return false; +} + +static void mask_point_scaled_handle(const MaskSplinePoint *point, + const eMaskWhichHandle which_handle, + const float scalex, + const float scaley, + float handle[2]) +{ + BKE_mask_point_handle(point, which_handle, handle); + handle[0] *= scalex; + handle[1] *= scaley; +} + +MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, + Mask *mask_orig, + const float normal_co[2], + const float threshold, + MaskLayer **r_mask_layer, + MaskSpline **r_spline, + eMaskWhichHandle *r_which_handle, + float *r_score) +{ + ScrArea *sa = CTX_wm_area(C); + ARegion *region = CTX_wm_region(C); + + MaskLayer *point_mask_layer = NULL; + MaskSpline *point_spline = NULL; + MaskSplinePoint *point = NULL; + float co[2]; + const float threshold_sq = threshold * threshold; + float len_sq = FLT_MAX, scalex, scaley; + eMaskWhichHandle which_handle = MASK_WHICH_HANDLE_NONE; + int width, height; + + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_orig->id); + + ED_mask_get_size(sa, &width, &height); + ED_mask_pixelspace_factor(sa, region, &scalex, &scaley); + + co[0] = normal_co[0] * scalex; + co[1] = normal_co[1] * scaley; + + for (MaskLayer *mask_layer_orig = mask_orig->masklayers.first, + *mask_layer_eval = mask_eval->masklayers.first; + mask_layer_orig != NULL; + mask_layer_orig = mask_layer_orig->next, mask_layer_eval = mask_layer_eval->next) { + + if (mask_layer_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + for (MaskSpline *spline_orig = mask_layer_orig->splines.first, + *spline_eval = mask_layer_eval->splines.first; + spline_orig != NULL; + spline_orig = spline_orig->next, spline_eval = spline_eval->next) { + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline_eval); + + for (int i = 0; i < spline_orig->tot_point; i++) { + MaskSplinePoint *cur_point_orig = &spline_orig->points[i]; + const MaskSplinePoint *cur_point_deform_eval = &points_array[i]; + eMaskWhichHandle cur_which_handle = MASK_WHICH_HANDLE_NONE; + const BezTriple *bezt = &cur_point_deform_eval->bezt; + float cur_len_sq, vec[2]; + + vec[0] = bezt->vec[1][0] * scalex; + vec[1] = bezt->vec[1][1] * scaley; + + cur_len_sq = len_squared_v2v2(co, vec); + + if (cur_len_sq < len_sq) { + point_spline = spline_orig; + point_mask_layer = mask_layer_orig; + point = cur_point_orig; + len_sq = cur_len_sq; + which_handle = MASK_WHICH_HANDLE_NONE; + } + + if (BKE_mask_point_handles_mode_get(cur_point_deform_eval) == MASK_HANDLE_MODE_STICK) { + float handle[2]; + mask_point_scaled_handle( + cur_point_deform_eval, MASK_WHICH_HANDLE_STICK, scalex, scaley, handle); + cur_len_sq = len_squared_v2v2(co, handle); + cur_which_handle = MASK_WHICH_HANDLE_STICK; + } + else { + float handle_left[2], handle_right[2]; + float len_left_sq, len_right_sq; + mask_point_scaled_handle( + cur_point_deform_eval, MASK_WHICH_HANDLE_LEFT, scalex, scaley, handle_left); + mask_point_scaled_handle( + cur_point_deform_eval, MASK_WHICH_HANDLE_RIGHT, scalex, scaley, handle_right); + + len_left_sq = len_squared_v2v2(co, handle_left); + len_right_sq = len_squared_v2v2(co, handle_right); + if (i == 0) { + if (len_left_sq <= len_right_sq) { + if (bezt->h1 != HD_VECT) { + cur_which_handle = MASK_WHICH_HANDLE_LEFT; + cur_len_sq = len_left_sq; + } + } + else if (bezt->h2 != HD_VECT) { + cur_which_handle = MASK_WHICH_HANDLE_RIGHT; + cur_len_sq = len_right_sq; + } + } + else { + if (len_right_sq <= len_left_sq) { + if (bezt->h2 != HD_VECT) { + cur_which_handle = MASK_WHICH_HANDLE_RIGHT; + cur_len_sq = len_right_sq; + } + } + else if (bezt->h1 != HD_VECT) { + cur_which_handle = MASK_WHICH_HANDLE_LEFT; + cur_len_sq = len_left_sq; + } + } + } + + if (cur_len_sq <= len_sq && cur_which_handle != MASK_WHICH_HANDLE_NONE) { + point_mask_layer = mask_layer_orig; + point_spline = spline_orig; + point = cur_point_orig; + len_sq = cur_len_sq; + which_handle = cur_which_handle; + } + } + } + } + + if (len_sq < threshold_sq) { + if (r_mask_layer) { + *r_mask_layer = point_mask_layer; + } + + if (r_spline) { + *r_spline = point_spline; + } + + if (r_which_handle) { + *r_which_handle = which_handle; + } + + if (r_score) { + *r_score = sqrtf(len_sq); + } + + return point; + } + + if (r_mask_layer) { + *r_mask_layer = NULL; + } + + if (r_spline) { + *r_spline = NULL; + } + + if (r_which_handle) { + *r_which_handle = MASK_WHICH_HANDLE_NONE; + } + + return NULL; +} + +bool ED_mask_feather_find_nearest(const bContext *C, + Mask *mask_orig, + const float normal_co[2], + const float threshold, + MaskLayer **r_mask_layer, + MaskSpline **r_spline, + MaskSplinePoint **r_point, + MaskSplinePointUW **r_uw, + float *r_score) +{ + ScrArea *sa = CTX_wm_area(C); + ARegion *region = CTX_wm_region(C); + + MaskLayer *point_mask_layer = NULL; + MaskSpline *point_spline = NULL; + MaskSplinePoint *point = NULL; + MaskSplinePointUW *uw = NULL; + const float threshold_sq = threshold * threshold; + float len = FLT_MAX, co[2]; + float scalex, scaley; + int width, height; + + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_orig->id); + + ED_mask_get_size(sa, &width, &height); + ED_mask_pixelspace_factor(sa, region, &scalex, &scaley); + + co[0] = normal_co[0] * scalex; + co[1] = normal_co[1] * scaley; + + for (MaskLayer *mask_layer_orig = mask_orig->masklayers.first, + *mask_layer_eval = mask_eval->masklayers.first; + mask_layer_orig != NULL; + mask_layer_orig = mask_layer_orig->next, mask_layer_eval = mask_layer_eval->next) { + + for (MaskSpline *spline_orig = mask_layer_orig->splines.first, + *spline_eval = mask_layer_eval->splines.first; + spline_orig != NULL; + spline_orig = spline_orig->next, spline_eval = spline_eval->next) { + // MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + + int i, tot_feather_point; + float(*feather_points)[2], (*fp)[2]; + + if (mask_layer_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + feather_points = fp = BKE_mask_spline_feather_points(spline_eval, &tot_feather_point); + + for (i = 0; i < spline_orig->tot_point; i++) { + int j; + MaskSplinePoint *cur_point_orig = &spline_orig->points[i]; + MaskSplinePoint *cur_point_eval = &spline_eval->points[i]; + + for (j = 0; j <= cur_point_eval->tot_uw; j++) { + float cur_len_sq, vec[2]; + + vec[0] = (*fp)[0] * scalex; + vec[1] = (*fp)[1] * scaley; + + cur_len_sq = len_squared_v2v2(vec, co); + + if (point == NULL || cur_len_sq < len) { + if (j == 0) { + uw = NULL; + } + else { + uw = &cur_point_orig->uw[j - 1]; + } + + point_mask_layer = mask_layer_orig; + point_spline = spline_orig; + point = cur_point_orig; + len = cur_len_sq; + } + + fp++; + } + } + + MEM_freeN(feather_points); + } + } + + if (len < threshold_sq) { + if (r_mask_layer) { + *r_mask_layer = point_mask_layer; + } + + if (r_spline) { + *r_spline = point_spline; + } + + if (r_point) { + *r_point = point; + } + + if (r_uw) { + *r_uw = uw; + } + + if (r_score) { + *r_score = sqrtf(len); + } + + return true; + } + + if (r_mask_layer) { + *r_mask_layer = NULL; + } + + if (r_spline) { + *r_spline = NULL; + } + + if (r_point) { + *r_point = NULL; + } + + return false; +} + +/* takes event->mval */ +void ED_mask_mouse_pos(ScrArea *sa, ARegion *region, const int mval[2], float co[2]) +{ + if (sa) { + switch (sa->spacetype) { + case SPACE_CLIP: { + SpaceClip *sc = sa->spacedata.first; + ED_clip_mouse_pos(sc, region, mval, co); + BKE_mask_coord_from_movieclip(sc->clip, &sc->user, co, co); + break; + } + case SPACE_SEQ: { + UI_view2d_region_to_view(®ion->v2d, mval[0], mval[1], &co[0], &co[1]); + break; + } + case SPACE_IMAGE: { + SpaceImage *sima = sa->spacedata.first; + ED_image_mouse_pos(sima, region, mval, co); + BKE_mask_coord_from_image(sima->image, &sima->iuser, co, co); + break; + } + default: + /* possible other spaces from which mask editing is available */ + BLI_assert(0); + zero_v2(co); + break; + } + } + else { + BLI_assert(0); + zero_v2(co); + } +} + +/* input: x/y - mval space + * output: xr/yr - mask point space */ +void ED_mask_point_pos(ScrArea *sa, ARegion *region, float x, float y, float *xr, float *yr) +{ + float co[2]; + + if (sa) { + switch (sa->spacetype) { + case SPACE_CLIP: { + SpaceClip *sc = sa->spacedata.first; + ED_clip_point_stable_pos(sc, region, x, y, &co[0], &co[1]); + BKE_mask_coord_from_movieclip(sc->clip, &sc->user, co, co); + break; + } + case SPACE_SEQ: + zero_v2(co); /* MASKTODO */ + break; + case SPACE_IMAGE: { + SpaceImage *sima = sa->spacedata.first; + ED_image_point_pos(sima, region, x, y, &co[0], &co[1]); + BKE_mask_coord_from_image(sima->image, &sima->iuser, co, co); + break; + } + default: + /* possible other spaces from which mask editing is available */ + BLI_assert(0); + zero_v2(co); + break; + } + } + else { + BLI_assert(0); + zero_v2(co); + } + + *xr = co[0]; + *yr = co[1]; +} + +void ED_mask_point_pos__reverse( + ScrArea *sa, ARegion *region, float x, float y, float *xr, float *yr) +{ + float co[2]; + + if (sa) { + switch (sa->spacetype) { + case SPACE_CLIP: { + SpaceClip *sc = sa->spacedata.first; + co[0] = x; + co[1] = y; + BKE_mask_coord_to_movieclip(sc->clip, &sc->user, co, co); + ED_clip_point_stable_pos__reverse(sc, region, co, co); + break; + } + case SPACE_SEQ: + zero_v2(co); /* MASKTODO */ + break; + case SPACE_IMAGE: { + SpaceImage *sima = sa->spacedata.first; + co[0] = x; + co[1] = y; + BKE_mask_coord_to_image(sima->image, &sima->iuser, co, co); + ED_image_point_pos__reverse(sima, region, co, co); + break; + } + default: + /* possible other spaces from which mask editing is available */ + BLI_assert(0); + zero_v2(co); + break; + } + } + else { + BLI_assert(0); + zero_v2(co); + } + + *xr = co[0]; + *yr = co[1]; +} + +bool ED_mask_selected_minmax(const bContext *C, float min[2], float max[2]) +{ + Mask *mask = CTX_data_edit_mask(C); + bool ok = false; + + if (mask == NULL) { + return ok; + } + + INIT_MINMAX2(min, max); + for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer != NULL; + mask_layer = mask_layer->next) { + if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + for (MaskSpline *spline = mask_layer->splines.first; spline != NULL; spline = spline->next) { + MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); + for (int i = 0; i < spline->tot_point; i++) { + const MaskSplinePoint *point = &spline->points[i]; + const MaskSplinePoint *deform_point = &points_array[i]; + const BezTriple *bezt = &point->bezt; + float handle[2]; + if (!MASKPOINT_ISSEL_ANY(point)) { + continue; + } + if (bezt->f2 & SELECT) { + minmax_v2v2_v2(min, max, deform_point->bezt.vec[1]); + } + if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) { + BKE_mask_point_handle(deform_point, MASK_WHICH_HANDLE_STICK, handle); + minmax_v2v2_v2(min, max, handle); + } + else { + if ((bezt->f1 & SELECT) && (bezt->h1 != HD_VECT)) { + BKE_mask_point_handle(deform_point, MASK_WHICH_HANDLE_LEFT, handle); + minmax_v2v2_v2(min, max, handle); + } + if ((bezt->f3 & SELECT) && (bezt->h2 != HD_VECT)) { + BKE_mask_point_handle(deform_point, MASK_WHICH_HANDLE_RIGHT, handle); + minmax_v2v2_v2(min, max, handle); + } + } + ok = true; + } + } + } + return ok; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Generic 2D View Queries + * \{ */ + +void ED_mask_get_size(ScrArea *sa, int *width, int *height) +{ + if (sa && sa->spacedata.first) { + switch (sa->spacetype) { + case SPACE_CLIP: { + SpaceClip *sc = sa->spacedata.first; + ED_space_clip_get_size(sc, width, height); + break; + } + case SPACE_SEQ: { + // Scene *scene = CTX_data_scene(C); + // *width = (scene->r.size * scene->r.xsch) / 100; + // *height = (scene->r.size * scene->r.ysch) / 100; + break; + } + case SPACE_IMAGE: { + SpaceImage *sima = sa->spacedata.first; + ED_space_image_get_size(sima, width, height); + break; + } + default: + /* possible other spaces from which mask editing is available */ + BLI_assert(0); + *width = 0; + *height = 0; + break; + } + } + else { + BLI_assert(0); + *width = 0; + *height = 0; + } +} + +void ED_mask_zoom(ScrArea *sa, ARegion *region, float *zoomx, float *zoomy) +{ + if (sa && sa->spacedata.first) { + switch (sa->spacetype) { + case SPACE_CLIP: { + SpaceClip *sc = sa->spacedata.first; + ED_space_clip_get_zoom(sc, region, zoomx, zoomy); + break; + } + case SPACE_SEQ: { + *zoomx = *zoomy = 1.0f; + break; + } + case SPACE_IMAGE: { + SpaceImage *sima = sa->spacedata.first; + ED_space_image_get_zoom(sima, region, zoomx, zoomy); + break; + } + default: + /* possible other spaces from which mask editing is available */ + BLI_assert(0); + *zoomx = *zoomy = 1.0f; + break; + } + } + else { + BLI_assert(0); + *zoomx = *zoomy = 1.0f; + } +} + +void ED_mask_get_aspect(ScrArea *sa, ARegion *UNUSED(region), float *aspx, float *aspy) +{ + if (sa && sa->spacedata.first) { + switch (sa->spacetype) { + case SPACE_CLIP: { + SpaceClip *sc = sa->spacedata.first; + ED_space_clip_get_aspect(sc, aspx, aspy); + break; + } + case SPACE_SEQ: { + *aspx = *aspy = 1.0f; /* MASKTODO - render aspect? */ + break; + } + case SPACE_IMAGE: { + SpaceImage *sima = sa->spacedata.first; + ED_space_image_get_aspect(sima, aspx, aspy); + break; + } + default: + /* possible other spaces from which mask editing is available */ + BLI_assert(0); + *aspx = *aspy = 1.0f; + break; + } + } + else { + BLI_assert(0); + *aspx = *aspy = 1.0f; + } +} + +void ED_mask_pixelspace_factor(ScrArea *sa, ARegion *region, float *scalex, float *scaley) +{ + if (sa && sa->spacedata.first) { + switch (sa->spacetype) { + case SPACE_CLIP: { + SpaceClip *sc = sa->spacedata.first; + float aspx, aspy; + + UI_view2d_scale_get(®ion->v2d, scalex, scaley); + ED_space_clip_get_aspect(sc, &aspx, &aspy); + + *scalex *= aspx; + *scaley *= aspy; + break; + } + case SPACE_SEQ: { + *scalex = *scaley = 1.0f; /* MASKTODO? */ + break; + } + case SPACE_IMAGE: { + SpaceImage *sima = sa->spacedata.first; + float aspx, aspy; + + UI_view2d_scale_get(®ion->v2d, scalex, scaley); + ED_space_image_get_aspect(sima, &aspx, &aspy); + + *scalex *= aspx; + *scaley *= aspy; + break; + } + default: + /* possible other spaces from which mask editing is available */ + BLI_assert(0); + *scalex = *scaley = 1.0f; + break; + } + } + else { + BLI_assert(0); + *scalex = *scaley = 1.0f; + } +} + +void ED_mask_cursor_location_get(ScrArea *sa, float cursor[2]) +{ + if (sa) { + switch (sa->spacetype) { + case SPACE_CLIP: { + SpaceClip *space_clip = sa->spacedata.first; + copy_v2_v2(cursor, space_clip->cursor); + break; + } + case SPACE_SEQ: { + zero_v2(cursor); + break; + } + case SPACE_IMAGE: { + SpaceImage *space_image = sa->spacedata.first; + copy_v2_v2(cursor, space_image->cursor); + break; + } + default: + /* possible other spaces from which mask editing is available */ + BLI_assert(0); + zero_v2(cursor); + break; + } + } + else { + BLI_assert(0); + zero_v2(cursor); + } +} + +/** \} */ diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index 53ef398ccd6..b21d20b360a 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -38,7 +38,6 @@ #include "ED_clip.h" #include "ED_mask.h" /* own include */ -#include "ED_screen.h" #include "ED_select_utils.h" #include "RNA_access.h" diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index 987447c3663..3d20b58b905 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -493,8 +493,10 @@ void paintvert_tag_select_update(struct bContext *C, struct Object *ob) WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data); } -/* note: if the caller passes false to flush_flags, - * then they will need to run paintvert_flush_flags(ob) themselves */ +/** + * \note if the caller passes false to flush_flags, + * then they will need to run #paintvert_flush_flags(ob) themselves. + */ bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags) { Mesh *me; diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index 10c290e2be9..e91aaea91e0 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -690,14 +690,14 @@ wmKeyMap *bevel_modal_keymap(wmKeyConfig *keyconf) {0, NULL, 0, NULL, NULL}, }; - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Bevel Modal Map"); + wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Bevel Modal Map"); /* This function is called for each spacetype, only needs to add map once */ if (keymap && keymap->modal_items) { return NULL; } - keymap = WM_modalkeymap_add(keyconf, "Bevel Modal Map", modal_items); + keymap = WM_modalkeymap_ensure(keyconf, "Bevel Modal Map", modal_items); WM_modalkeymap_assign(keymap, "MESH_OT_bevel"); diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c index 1ea1501fc66..23f622ac359 100644 --- a/source/blender/editors/mesh/editmesh_extrude.c +++ b/source/blender/editors/mesh/editmesh_extrude.c @@ -274,11 +274,27 @@ static bool edbm_extrude_ex(Object *obedit, static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op) { - RegionView3D *rv3d = CTX_wm_region_view3d(C); + + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "offset"); const int steps = RNA_int_get(op->ptr, "steps"); - const float offs = RNA_float_get(op->ptr, "offset"); - float dvec[3], tmat[3][3], bmat[3][3]; - short a; + const float scale_offset = RNA_float_get(op->ptr, "scale_offset"); + float offset[3]; + + if (!RNA_property_is_set(op->ptr, prop)) { + RegionView3D *rv3d = CTX_wm_region_view3d(C); + if (rv3d != NULL) { + normalize_v3_v3(offset, rv3d->persinv[2]); + } + else { + copy_v3_v3(offset, (const float[3]){0, 0, 1}); + } + RNA_property_float_set_array(op->ptr, prop, offset); + } + else { + RNA_property_float_get_array(op->ptr, prop, offset); + } + + mul_v3_fl(offset, scale_offset); ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; @@ -286,22 +302,19 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op) view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + float offset_local[3], tmat[3][3]; Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); - /* dvec */ - normalize_v3_v3_length(dvec, rv3d->persinv[2], offs); + copy_m3_m4(tmat, obedit->obmat); + invert_m3(tmat); + mul_v3_m3v3(offset_local, tmat, offset); - /* base correction */ - copy_m3_m4(bmat, obedit->obmat); - invert_m3_m3(tmat, bmat); - mul_m3_v3(tmat, dvec); - - for (a = 0; a < steps; a++) { - edbm_extrude_ex(obedit, em, BM_ALL_NOLOOP, BM_ELEM_SELECT, false, false, false); - - BMO_op_callf(em->bm, BMO_FLAG_DEFAULTS, "translate vec=%v verts=%hv", dvec, BM_ELEM_SELECT); + for (int a = 0; a < steps; a++) { + edbm_extrude_ex(obedit, em, BM_ALL_NOLOOP, BM_ELEM_SELECT, false, false, true); + BMO_op_callf( + em->bm, BMO_FLAG_DEFAULTS, "translate vec=%v verts=%hv", offset_local, BM_ELEM_SELECT); } EDBM_mesh_normals_update(em); @@ -317,20 +330,23 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op) void MESH_OT_extrude_repeat(wmOperatorType *ot) { /* identifiers */ - ot->name = "Extrude Repeat Mesh"; + ot->name = "Extrude Repeat"; ot->description = "Extrude selected vertices, edges or faces repeatedly"; ot->idname = "MESH_OT_extrude_repeat"; /* api callbacks */ ot->exec = edbm_extrude_repeat_exec; - ot->poll = ED_operator_editmesh_view3d; + ot->poll = ED_operator_editmesh; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* props */ - RNA_def_float_distance(ot->srna, "offset", 2.0f, 0.0f, 1e12f, "Offset", "", 0.0f, 100.0f); RNA_def_int(ot->srna, "steps", 10, 0, 1000000, "Steps", "", 0, 180); + PropertyRNA *prop = RNA_def_float_vector_xyz( + ot->srna, "offset", 3, NULL, -100000, 100000, "Offset", "Offset vector", -1000.0f, 1000.0f); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + RNA_def_float(ot->srna, "scale_offset", 1.0f, 0.0f, 1e12f, "Scale Offset", "", 0.0f, 100.0f); } /** \} */ diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 6230eacba94..373dfc811ec 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -2824,14 +2824,14 @@ wmKeyMap *knifetool_modal_keymap(wmKeyConfig *keyconf) {0, NULL, 0, NULL, NULL}, }; - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Knife Tool Modal Map"); + wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Knife Tool Modal Map"); /* this function is called for each spacetype, only needs to add map once */ if (keymap && keymap->modal_items) { return NULL; } - keymap = WM_modalkeymap_add(keyconf, "Knife Tool Modal Map", modal_items); + keymap = WM_modalkeymap_ensure(keyconf, "Knife Tool Modal Map", modal_items); WM_modalkeymap_assign(keymap, "MESH_OT_knife_tool"); diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index b52f63e0a1b..5a04822613e 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -1771,8 +1771,93 @@ void MESH_OT_face_make_planar(wmOperatorType *ot) /** \name Split Edge Operator * \{ */ +static bool edbm_edge_split_selected_edges(wmOperator *op, Object *obedit, BMEditMesh *em) +{ + BMesh *bm = em->bm; + if (bm->totedgesel == 0) { + return false; + } + if (!EDBM_op_call_and_selectf( + em, op, "edges.out", false, "split_edges edges=%he", BM_ELEM_SELECT)) { + return false; + } + + EDBM_select_flush(em); + EDBM_update_generic(obedit->data, true, true); + + return true; +} + +static bool edbm_edge_split_selected_verts(wmOperator *op, Object *obedit, BMEditMesh *em) +{ + BMesh *bm = em->bm; + + /* Note that tracking vertices through the 'split_edges' operator is complicated. + * Instead, tag loops for selection. */ + if (bm->totvertsel == 0) { + return false; + } + + /* Flush from vertices to edges. */ + BMIter iter; + BMEdge *eed; + BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) { + BM_elem_flag_disable(eed, BM_ELEM_TAG); + if (eed->l != NULL) { + if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && + (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) || + BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))) { + BM_elem_flag_enable(eed, BM_ELEM_TAG); + } + /* Store selection in loop tags. */ + BMLoop *l_iter = eed->l; + do { + BM_elem_flag_set(l_iter, BM_ELEM_TAG, BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)); + } while ((l_iter = l_iter->radial_next) != eed->l); + } + } + + if (!EDBM_op_callf(em, + op, + "split_edges edges=%he verts=%hv use_verts=%b", + BM_ELEM_TAG, + BM_ELEM_SELECT, + true)) { + return false; + } + + BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { + if (eed->l != NULL) { + BMLoop *l_iter = eed->l; + do { + if (BM_elem_flag_test(l_iter, BM_ELEM_TAG)) { + BM_vert_select_set(em->bm, l_iter->v, true); + } + } while ((l_iter = l_iter->radial_next) != eed->l); + } + else { + /* Split out wire. */ + for (int i = 0; i < 2; i++) { + BMVert *v = *(&eed->v1 + i); + if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { + if (eed != BM_DISK_EDGE_NEXT(eed, v)) { + BM_vert_separate(bm, v, &eed, 1, true, NULL, NULL); + } + } + } + } + } + + EDBM_select_flush(em); + EDBM_update_generic(obedit->data, true, true); + + return true; +} + static int edbm_edge_split_exec(bContext *C, wmOperator *op) { + const int type = RNA_enum_get(op->ptr, "type"); + ViewLayer *view_layer = CTX_data_view_layer(C); uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( @@ -1780,20 +1865,21 @@ static int edbm_edge_split_exec(bContext *C, wmOperator *op) for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); - if (em->bm->totedgesel == 0) { - continue; - } - if (!EDBM_op_call_and_selectf( - em, op, "edges.out", false, "split_edges edges=%he", BM_ELEM_SELECT)) { - continue; - } - - if (em->selectmode == SCE_SELECT_FACE) { - EDBM_select_flush(em); + switch (type) { + case BM_VERT: + if (!edbm_edge_split_selected_verts(op, obedit, em)) { + continue; + } + break; + case BM_EDGE: + if (!edbm_edge_split_selected_edges(op, obedit, em)) { + continue; + } + break; + default: + BLI_assert(0); } - - EDBM_update_generic(obedit->data, true, true); } MEM_freeN(objects); @@ -1813,6 +1899,20 @@ void MESH_OT_edge_split(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + static const EnumPropertyItem merge_type_items[] = { + {BM_EDGE, "EDGE", 0, "Edges", "Split along selected edges"}, + {BM_VERT, + "VERT", + 0, + "Edges from Vertices", + "Split all edges connected to selected vertices"}, + {0, NULL, 0, NULL, NULL}, + }; + + ot->prop = RNA_def_enum( + ot->srna, "type", merge_type_items, BM_EDGE, "Type", "Method to use for splitting"); } /** \} */ @@ -7694,14 +7794,14 @@ wmKeyMap *point_normals_modal_keymap(wmKeyConfig *keyconf) }; static const char *keymap_name = "Custom Normals Modal Map"; - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, keymap_name); + wmKeyMap *keymap = WM_modalkeymap_find(keyconf, keymap_name); /* We only need to add map once */ if (keymap && keymap->modal_items) { return NULL; } - keymap = WM_modalkeymap_add(keyconf, keymap_name, modal_items); + keymap = WM_modalkeymap_ensure(keyconf, keymap_name, modal_items); WM_modalkeymap_assign(keymap, "MESH_OT_point_normals"); diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index d9fb48afcbf..ba641fb2a39 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -76,7 +76,9 @@ #include "object_intern.h" -/* -------------- Get Active Constraint Data ---------------------- */ +/* ------------------------------------------------------------------- */ +/** \name Constraint Data Accessors + * \{ */ /* if object in posemode, active bone constraints, else object constraints */ ListBase *get_active_constraints(Object *ob) @@ -146,9 +148,13 @@ bConstraint *get_active_constraint(Object *ob) return BKE_constraints_active_get(get_active_constraints(ob)); } -/* -------------- Constraint Management (Add New, Remove, Rename) -------------------- */ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name PyConstraints (Unused) + * \{ */ + #ifdef WITH_PYTHON -/* ------------- PyConstraints ------------------ */ /* this callback sets the text-file to be used for selected menu item */ static void validate_pyconstraint_cb(Main *bmain, void *arg1, void *arg2) @@ -231,6 +237,12 @@ static void update_pyconstraint_cb(void *arg1, void *arg2) } #endif // UNUSED +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Add Constraint Utilities + * \{ */ + /* helper function for add_constriant - sets the last target for the active constraint */ static void set_constraint_nth_target(bConstraint *con, Object *target, @@ -272,7 +284,11 @@ static void set_constraint_nth_target(bConstraint *con, } } -/* ------------- Constraint Sanity Testing ------------------- */ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Constraint Sanity Testing + * \{ */ static void test_constraint( Main *bmain, Object *owner, bPoseChannel *pchan, bConstraint *con, int type) @@ -626,7 +642,11 @@ static void object_test_constraint(Main *bmain, Object *owner, bConstraint *con) } } -/*** generic functions for operators using constraint names and data context *********************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Generic Functions for Operators Using Constraint Names and Data Context + * \{ */ #define EDIT_CONSTRAINT_OWNER_OBJECT 0 #define EDIT_CONSTRAINT_OWNER_BONE 1 @@ -766,10 +786,13 @@ static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int return con; } -/* ********************** CONSTRAINT-SPECIFIC STUFF ********************* */ +/** \} */ -/* ---------- Distance-Dependent Constraints ---------- */ -/* StretchTo, Limit Distance */ +/* ------------------------------------------------------------------- */ +/** \name Stretch-To/Limit-Distance Constraint (Reset Original Length Operator) + * + * For Stretch-To & Limit-Distance constraints. + * \{ */ static int stretchto_reset_exec(bContext *C, wmOperator *op) { @@ -820,6 +843,14 @@ void CONSTRAINT_OT_stretchto_reset(wmOperatorType *ot) edit_constraint_properties(ot); } +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Distance Constraint (Reset Operator) + * + * For Limit-Distance constraint. + * \{ */ + static int limitdistance_reset_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -869,7 +900,11 @@ void CONSTRAINT_OT_limitdistance_reset(wmOperatorType *ot) edit_constraint_properties(ot); } -/* ------------- Child-Of Constraint ------------------ */ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Child-Of Constraint (Set Inverse Operator) + * \{ */ /* Force evaluation so that the 'set inverse' flag is handled. * No-op when the constraint is enabled, as in such cases the evaluation will happen anyway. @@ -996,7 +1031,11 @@ void CONSTRAINT_OT_childof_clear_inverse(wmOperatorType *ot) edit_constraint_properties(ot); } -/* --------------- Follow Path Constraint ------------------ */ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Follow Path Constraint (Auto Animate Path Operator) + * \{ */ static int followpath_path_animate_exec(bContext *C, wmOperator *op) { @@ -1138,7 +1177,11 @@ void CONSTRAINT_OT_followpath_path_animate(wmOperatorType *ot) MAXFRAME); } -/* ------------- Object Solver Constraint ------------------ */ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Object Solver Constraint (Set Inverse Operator) + * \{ */ static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op) { @@ -1198,6 +1241,12 @@ void CONSTRAINT_OT_objectsolver_set_inverse(wmOperatorType *ot) edit_constraint_properties(ot); } +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Object Solver Constraint (Clear Inverse Operator) + * \{ */ + static int objectsolver_clear_inverse_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -1250,7 +1299,11 @@ void CONSTRAINT_OT_objectsolver_clear_inverse(wmOperatorType *ot) edit_constraint_properties(ot); } -/***************************** BUTTONS ****************************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Constraint Management Utilities + * \{ */ void ED_object_constraint_set_active(Object *ob, bConstraint *con) { @@ -1344,6 +1397,12 @@ static bool constraint_poll(bContext *C) return (ptr.owner_id && ptr.data); } +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Delete Constraint Operator + * \{ */ + static int constraint_delete_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); @@ -1388,6 +1447,12 @@ void CONSTRAINT_OT_delete(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Move Down Constraint Operator + * \{ */ + static int constraint_move_down_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_active_context(C); @@ -1438,6 +1503,12 @@ void CONSTRAINT_OT_move_down(wmOperatorType *ot) edit_constraint_properties(ot); } +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Move Up Constraint Operator + * \{ */ + static int constraint_move_up_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_active_context(C); @@ -1486,9 +1557,11 @@ void CONSTRAINT_OT_move_up(wmOperatorType *ot) edit_constraint_properties(ot); } -/***************************** OPERATORS ****************************/ +/** \} */ -/************************ remove constraint operators *********************/ +/* ------------------------------------------------------------------- */ +/** \name Clear Pose Constraints Operator + * \{ */ static int pose_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -1549,6 +1622,12 @@ static int object_constraints_clear_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Clear Object Constraints Operator + * \{ */ + void OBJECT_OT_constraints_clear(wmOperatorType *ot) { /* identifiers */ @@ -1561,7 +1640,11 @@ void OBJECT_OT_constraints_clear(wmOperatorType *ot) ot->poll = ED_operator_object_active_editable; } -/************************ copy all constraints operators *********************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Copy Pose Constraints Operator + * \{ */ static int pose_constraint_copy_exec(bContext *C, wmOperator *op) { @@ -1616,6 +1699,12 @@ void POSE_OT_constraints_copy(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Copy Object Constraints Operator + * \{ */ + static int object_constraint_copy_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); @@ -1655,7 +1744,11 @@ void OBJECT_OT_constraints_copy(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/************************ add constraint operators *********************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Add Constraints Operator + * \{ */ /* get the Object and/or PoseChannel to use as target */ static bool get_new_constraint_target( @@ -2013,6 +2106,12 @@ void OBJECT_OT_constraint_add(wmOperatorType *ot) ot->prop = prop; } +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Add Constraints With Targets Operator + * \{ */ + void OBJECT_OT_constraint_add_with_targets(wmOperatorType *ot) { PropertyRNA *prop; @@ -2078,8 +2177,14 @@ void POSE_OT_constraint_add_with_targets(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_constraint_type_items, 0, "Type", ""); } -/************************ IK Constraint operators *********************/ -/* NOTE: only for Pose-Channels */ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Add IK to Bone Operator + * + * \note Only for pose-channels. + * \{ */ + // TODO: should these be here, or back in editors/armature/poseobject.c again? /* present menu with options + validation for targets to use */ @@ -2178,9 +2283,14 @@ void POSE_OT_ik_add(wmOperatorType *ot) "Assign IK Constraint with targets derived from the select bones/objects"); } -/* ------------------ */ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Clear IK from Bone Operator + * + * Remove IK constraints from selected bones. + * \{ */ -/* remove IK constraints from selected bones */ static int pose_ik_clear_exec(bContext *C, wmOperator *UNUSED(op)) { Object *prev_ob = NULL; @@ -2228,3 +2338,5 @@ void POSE_OT_ik_clear(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } + +/** \} */ diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index f2629b0b02f..0de2f114b94 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -94,7 +94,9 @@ static void modifier_skin_customdata_delete(struct Object *ob); -/******************************** API ****************************/ +/* ------------------------------------------------------------------- */ +/** \name Public Api + * \{ */ static void object_force_modifier_update_for_bind(Depsgraph *depsgraph, Object *ob) { @@ -841,7 +843,11 @@ int ED_object_modifier_copy(ReportList *UNUSED(reports), Object *ob, ModifierDat return 1; } -/************************ add modifier operator *********************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Add Modifier Operator + * \{ */ static int modifier_add_exec(bContext *C, wmOperator *op) { @@ -933,7 +939,13 @@ void OBJECT_OT_modifier_add(wmOperatorType *ot) ot->prop = prop; } -/********** generic functions for operators using mod names and data context *********************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Generic Functions For Operators + * + * Using modifier names and data context. + * \{ */ bool edit_modifier_poll_generic(bContext *C, StructRNA *rna_type, @@ -1015,7 +1027,11 @@ ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type) return md; } -/************************ remove modifier operator *********************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Remove Modifier Operator + * \{ */ static int modifier_remove_exec(bContext *C, wmOperator *op) { @@ -1067,7 +1083,11 @@ void OBJECT_OT_modifier_remove(wmOperatorType *ot) edit_modifier_properties(ot); } -/************************ move up modifier operator *********************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Move Up Modifier Operator + * \{ */ static int modifier_move_up_exec(bContext *C, wmOperator *op) { @@ -1109,7 +1129,11 @@ void OBJECT_OT_modifier_move_up(wmOperatorType *ot) edit_modifier_properties(ot); } -/************************ move down modifier operator *********************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Move Down Modifier Operator + * \{ */ static int modifier_move_down_exec(bContext *C, wmOperator *op) { @@ -1151,7 +1175,11 @@ void OBJECT_OT_modifier_move_down(wmOperatorType *ot) edit_modifier_properties(ot); } -/************************ apply modifier operator *********************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Apply Modifier Operator + * \{ */ static bool modifier_apply_poll(bContext *C) { @@ -1164,7 +1192,7 @@ static bool modifier_apply_poll(bContext *C) Object *ob = (ptr.owner_id != NULL) ? (Object *)ptr.owner_id : ED_object_active_context(C); ModifierData *md = ptr.data; /* May be NULL. */ - if (ID_REAL_USERS(ob->data) > 1) { + if ((ob->data != NULL) && ID_REAL_USERS(ob->data) > 1) { CTX_wm_operator_poll_msg_set(C, "Modifiers cannot be applied to multi-user data"); return false; } @@ -1241,7 +1269,11 @@ void OBJECT_OT_modifier_apply(wmOperatorType *ot) edit_modifier_properties(ot); } -/************************ convert modifier operator *********************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Convert Modifier Operator + * \{ */ static int modifier_convert_exec(bContext *C, wmOperator *op) { @@ -1288,7 +1320,11 @@ void OBJECT_OT_modifier_convert(wmOperatorType *ot) edit_modifier_properties(ot); } -/************************ copy modifier operator *********************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Copy Modifier Operator + * \{ */ static int modifier_copy_exec(bContext *C, wmOperator *op) { @@ -1330,7 +1366,11 @@ void OBJECT_OT_modifier_copy(wmOperatorType *ot) edit_modifier_properties(ot); } -/************* multires delete higher levels operator ****************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Multires Delete Higher Levels Operator + * \{ */ static bool multires_poll(bContext *C) { @@ -1385,7 +1425,11 @@ void OBJECT_OT_multires_higher_levels_delete(wmOperatorType *ot) edit_modifier_properties(ot); } -/****************** multires subdivide operator *********************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Multires Subdivide Operator + * \{ */ static int multires_subdivide_exec(bContext *C, wmOperator *op) { @@ -1438,7 +1482,11 @@ void OBJECT_OT_multires_subdivide(wmOperatorType *ot) edit_modifier_properties(ot); } -/****************** multires reshape operator *********************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Multires Reshape Operator + * \{ */ static int multires_reshape_exec(bContext *C, wmOperator *op) { @@ -1505,7 +1553,11 @@ void OBJECT_OT_multires_reshape(wmOperatorType *ot) edit_modifier_properties(ot); } -/****************** multires save external operator *********************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Multires Save External Operator + * \{ */ static int multires_external_save_exec(bContext *C, wmOperator *op) { @@ -1594,7 +1646,11 @@ void OBJECT_OT_multires_external_save(wmOperatorType *ot) edit_modifier_properties(ot); } -/****************** multires pack operator *********************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Multires Pack Operator + * \{ */ static int multires_external_pack_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -1624,7 +1680,12 @@ void OBJECT_OT_multires_external_pack(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/********************* multires apply base ***********************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Multires Apply Base + * \{ */ + static int multires_base_apply_exec(bContext *C, wmOperator *op) { Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); @@ -1669,7 +1730,11 @@ void OBJECT_OT_multires_base_apply(wmOperatorType *ot) edit_modifier_properties(ot); } -/************************** skin modifier ***********************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Skin Modifier + * \{ */ static void modifier_skin_customdata_delete(Object *ob) { @@ -2041,7 +2106,11 @@ void OBJECT_OT_skin_armature_create(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; edit_modifier_properties(ot); } -/************************ delta mush bind operator *********************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Delta Mesh Bind Operator + * \{ */ static bool correctivesmooth_poll(bContext *C) { @@ -2119,7 +2188,11 @@ void OBJECT_OT_correctivesmooth_bind(wmOperatorType *ot) edit_modifier_properties(ot); } -/************************ mdef bind operator *********************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Mesh Deform Bind Operator + * \{ */ static bool meshdeform_poll(bContext *C) { @@ -2192,7 +2265,11 @@ void OBJECT_OT_meshdeform_bind(wmOperatorType *ot) edit_modifier_properties(ot); } -/****************** explode refresh operator *********************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Explode Refresh Operator + * \{ */ static bool explode_poll(bContext *C) { @@ -2242,7 +2319,11 @@ void OBJECT_OT_explode_refresh(wmOperatorType *ot) edit_modifier_properties(ot); } -/****************** ocean bake operator *********************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Ocean Bake Operator + * \{ */ static bool ocean_bake_poll(bContext *C) { @@ -2444,7 +2525,11 @@ void OBJECT_OT_ocean_bake(wmOperatorType *ot) RNA_def_boolean(ot->srna, "free", false, "Free", "Free the bake, rather than generating it"); } -/************************ LaplacianDeform bind operator *********************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Laplaciandeform Bind Operator + * \{ */ static bool laplaciandeform_poll(bContext *C) { @@ -2519,7 +2604,11 @@ void OBJECT_OT_laplaciandeform_bind(wmOperatorType *ot) edit_modifier_properties(ot); } -/************************ sdef bind operator *********************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Surface Deform Bind Operator + * \{ */ static bool surfacedeform_bind_poll(bContext *C) { @@ -2583,3 +2672,5 @@ void OBJECT_OT_surfacedeform_bind(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; edit_modifier_properties(ot); } + +/** \} */ diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 7c8a9750b36..3166c9ddea1 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -115,7 +115,9 @@ #include "object_intern.h" -/*********************** Make Vertex Parent Operator ************************/ +/* ------------------------------------------------------------------- */ +/** \name Make Vertex Parent Operator + * \{ */ static bool vertex_parent_set_poll(bContext *C) { @@ -331,7 +333,11 @@ void OBJECT_OT_vertex_parent_set(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/********************** Make Proxy Operator *************************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Make Proxy Operator + * \{ */ /* set the object to proxify */ static int make_proxy_invoke(bContext *C, wmOperator *op, const wmEvent *event) @@ -411,7 +417,12 @@ static int make_proxy_exec(bContext *C, wmOperator *op) * TODO(sergey): We really need to get rid of this bi-directional links * in proxies with something like library overrides. */ - newob->proxy->proxy_from = newob; + if (newob->proxy != NULL) { + newob->proxy->proxy_from = newob; + } + else { + BKE_report(op->reports, RPT_ERROR, "Unable to assign proxy"); + } /* depsgraph flushes are needed for the new data */ DEG_relations_tag_update(bmain); @@ -485,7 +496,11 @@ void OBJECT_OT_proxy_make(wmOperatorType *ot) ot->prop = prop; } -/********************** Clear Parent Operator ******************* */ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Clear Parent Operator + * \{ */ EnumPropertyItem prop_clear_parent_types[] = { {CLEAR_PARENT_ALL, @@ -619,7 +634,11 @@ void OBJECT_OT_parent_clear(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_clear_parent_types, CLEAR_PARENT_ALL, "Type", ""); } -/* ******************** Make Parent Operator *********************** */ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Make Parent Operator + * \{ */ void ED_object_parent(Object *ob, Object *par, const int type, const char *substr) { @@ -1138,7 +1157,11 @@ void OBJECT_OT_parent_set(wmOperatorType *ot) "Apply transformation before parenting"); } -/* ************ Make Parent Without Inverse Operator ******************* */ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Make Parent Without Inverse Operator + * \{ */ static int parent_noinv_set_exec(bContext *C, wmOperator *op) { @@ -1191,7 +1214,11 @@ void OBJECT_OT_parent_no_inverse_set(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ******************** Clear Track Operator ******************* */ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Clear Track Operator + * \{ */ enum { CLEAR_TRACK = 1, @@ -1267,7 +1294,11 @@ void OBJECT_OT_track_clear(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_clear_track_types, 0, "Type", ""); } -/************************** Make Track Operator *****************************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Make Track Operator + * \{ */ enum { CREATE_TRACK_DAMPTRACK = 1, @@ -1386,7 +1417,11 @@ void OBJECT_OT_track_set(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_make_track_types, 0, "Type", ""); } -/************************** Link to Scene Operator *****************************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Link to Scene Operator + * \{ */ #if 0 static void link_to_scene(Main *UNUSED(bmain), unsigned short UNUSED(nr)) @@ -1702,7 +1737,11 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", make_links_items, 0, "Type", ""); } -/**************************** Make Single User ********************************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Make Single User Operator + * \{ */ static void libblock_relink_collection(Collection *collection, const bool do_collection) { @@ -2084,7 +2123,11 @@ void ED_object_single_users(Main *bmain, DEG_relations_tag_update(bmain); } -/******************************* Make Local ***********************************/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Make Local Operator + * \{ */ enum { MAKE_LOCAL_SELECT_OB = 1, @@ -2324,6 +2367,12 @@ void OBJECT_OT_make_local(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", ""); } +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Make Library Override Operator + * \{ */ + static void make_override_library_tag_object(Object *obact, Object *ob) { if (ob == obact) { @@ -2585,6 +2634,12 @@ void OBJECT_OT_make_override_library(wmOperatorType *ot) ot->prop = prop; } +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Make Single User Operator + * \{ */ + enum { MAKE_SINGLE_USER_ALL = 1, MAKE_SINGLE_USER_SELECTED = 2, @@ -2673,6 +2728,12 @@ void OBJECT_OT_make_single_user(wmOperatorType *ot) ot->srna, "animation", 0, "Object Animation", "Make animation data local to each object"); } +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Drop Named Material on Object Operator + * \{ */ + static int drop_named_material_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Main *bmain = CTX_data_main(C); @@ -2716,6 +2777,12 @@ void OBJECT_OT_drop_named_material(wmOperatorType *ot) RNA_def_string(ot->srna, "name", "Material", MAX_ID_NAME - 2, "Name", "Material name to assign"); } +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Unlink Object Operator + * \{ */ + static int object_unlink_data_exec(bContext *C, wmOperator *op) { ID *id; @@ -2766,3 +2833,5 @@ void OBJECT_OT_unlink_data(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_INTERNAL; } + +/** \} */ diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 62a078bedb7..e1fa4caafbd 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -814,14 +814,16 @@ void WORLD_OT_new(wmOperatorType *ot) /********************** render layer operators *********************/ -static int view_layer_add_exec(bContext *C, wmOperator *UNUSED(op)) +static int view_layer_add_exec(bContext *C, wmOperator *op) { wmWindow *win = CTX_wm_window(C); Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = BKE_view_layer_add(scene, NULL); + ViewLayer *view_layer_current = WM_window_get_active_view_layer(win); + ViewLayer *view_layer_new = BKE_view_layer_add( + scene, view_layer_current->name, view_layer_current, RNA_enum_get(op->ptr, "type")); if (win) { - WM_window_set_active_view_layer(win, view_layer); + WM_window_set_active_view_layer(win, view_layer_new); } DEG_id_tag_update(&scene->id, 0); @@ -833,6 +835,17 @@ static int view_layer_add_exec(bContext *C, wmOperator *UNUSED(op)) void SCENE_OT_view_layer_add(wmOperatorType *ot) { + static EnumPropertyItem type_items[] = { + {VIEWLAYER_ADD_NEW, "NEW", 0, "New", "Add a new view layer"}, + {VIEWLAYER_ADD_COPY, "COPY", 0, "Copy Settings", "Copy settings of current view layer"}, + {VIEWLAYER_ADD_EMPTY, + "EMPTY", + 0, + "Blank", + "Add a new view layer with all collections disabled"}, + {0, NULL, 0, NULL, NULL}, + }; + /* identifiers */ ot->name = "Add View Layer"; ot->idname = "SCENE_OT_view_layer_add"; @@ -840,9 +853,13 @@ void SCENE_OT_view_layer_add(wmOperatorType *ot) /* api callbacks */ ot->exec = view_layer_add_exec; + ot->invoke = WM_menu_invoke; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", ""); } static bool view_layer_remove_poll(bContext *C) diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index f25f685f2e1..0151a0fcb0d 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -1666,7 +1666,7 @@ Scene *ED_screen_scene_find_with_window(const bScreen *screen, } } - BLI_assert(0); + /* Can by NULL when accessing a screen that isn't active. */ return NULL; } diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 2506c7472e3..ae8dd829d8d 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -3142,7 +3142,7 @@ static void SCREEN_OT_screen_set(wmOperatorType *ot) ot->poll = ED_operator_screenactive; /* rna */ - RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX); + RNA_def_int(ot->srna, "delta", 1, -1, 1, "Delta", "", -1, 1); } /** \} */ @@ -4796,10 +4796,10 @@ static void SCREEN_OT_box_select(wmOperatorType *ot) /* -------------------------------------------------------------------- */ /** \name Full Screen Back Operator + * + * Use for generic full-screen 'back' button. * \{ */ -/* *********************** generic fullscreen 'back' button *************** */ - static int fullscreen_back_exec(bContext *C, wmOperator *op) { bScreen *screen = CTX_wm_screen(C); @@ -5517,7 +5517,7 @@ static void keymap_modal_set(wmKeyConfig *keyconf) wmKeyMap *keymap; /* Standard Modal keymap ------------------------------------------------ */ - keymap = WM_modalkeymap_add(keyconf, "Standard Modal Map", modal_items); + keymap = WM_modalkeymap_ensure(keyconf, "Standard Modal Map", modal_items); WM_modalkeymap_assign(keymap, "SCREEN_OT_area_move"); } @@ -5525,7 +5525,7 @@ static void keymap_modal_set(wmKeyConfig *keyconf) static bool blend_file_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), - const char **UNUSED(tooltip)) + const char **UNUSED(r_tooltip)) { if (drag->type == WM_DRAG_PATH) { if (drag->icon == ICON_FILE_BLEND) { diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c index ce5a80585b0..69ca86efa9d 100644 --- a/source/blender/editors/sculpt_paint/paint_hide.c +++ b/source/blender/editors/sculpt_paint/paint_hide.c @@ -403,6 +403,9 @@ static int hide_show_exec(bContext *C, wmOperator *op) BKE_mesh_flush_hidden_from_verts(me); } + SCULPT_visibility_sync_all_vertex_to_face_sets(ob->sculpt); + + DEG_id_tag_update(&ob->id, ID_RECALC_SHADING); ED_region_tag_redraw(region); return OPERATOR_FINISHED; diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c index fc56c5cb6c6..73c099c9407 100644 --- a/source/blender/editors/sculpt_paint/paint_image_2d.c +++ b/source/blender/editors/sculpt_paint/paint_image_2d.c @@ -1609,7 +1609,9 @@ void paint_2d_stroke(void *ps, copy_v2_v2(last_uv, old_uv); } - float uv_brush_size[2] = {base_size / s->tiles[0].size[0], base_size / s->tiles[0].size[1]}; + const float uv_brush_size[2] = { + (s->symmetry & PAINT_TILE_X) ? FLT_MAX : base_size / s->tiles[0].size[0], + (s->symmetry & PAINT_TILE_Y) ? FLT_MAX : base_size / s->tiles[0].size[1]}; for (int i = 0; i < s->num_tiles; i++) { ImagePaintTile *tile = &s->tiles[i]; @@ -1640,7 +1642,8 @@ void paint_2d_stroke(void *ps, paint_2d_uv_to_coord(tile, last_uv, tile->last_paintpos); /* Second check in pixel coordinates. */ - const float pixel_brush_size[] = {size, size}; + const float pixel_brush_size[] = {(s->symmetry & PAINT_TILE_X) ? FLT_MAX : size, + (s->symmetry & PAINT_TILE_Y) ? FLT_MAX : size}; if (!(is_inside_tile(tile->size, new_coord, pixel_brush_size) || is_inside_tile(tile->size, old_coord, pixel_brush_size))) { continue; diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 8362a4a576a..c56ce8fd183 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -64,6 +64,7 @@ #include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_customdata.h" +#include "BKE_global.h" #include "BKE_idprop.h" #include "BKE_image.h" #include "BKE_lib_id.h" @@ -6201,11 +6202,12 @@ void PAINT_OT_project_image(wmOperatorType *ot) static bool texture_paint_image_from_view_poll(bContext *C) { - if (BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_VIEW3D, 0) == NULL) { + bScreen *screen = CTX_wm_screen(C); + if (!(screen && BKE_screen_find_big_area(screen, SPACE_VIEW3D, 0))) { CTX_wm_operator_poll_msg_set(C, "No 3D viewport found to create image from"); return false; } - if (!GPU_is_initialized()) { + if (G.background || !GPU_is_initialized()) { return false; } return true; @@ -6754,7 +6756,7 @@ void PAINT_OT_add_texture_paint_slot(wmOperatorType *ot) /* api callbacks */ ot->invoke = texture_paint_add_texture_paint_slot_invoke; ot->exec = texture_paint_add_texture_paint_slot_exec; - ot->poll = ED_operator_object_active; + ot->poll = ED_operator_object_active_editable_mesh; /* flags */ ot->flag = OPTYPE_UNDO; diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index 59a0c50d402..cc848b80bb3 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -303,7 +303,7 @@ static void PALETTE_OT_color_delete(wmOperatorType *ot) static bool palette_extract_img_poll(bContext *C) { SpaceLink *sl = CTX_wm_space_data(C); - if (sl->spacetype == SPACE_IMAGE) { + if ((sl != NULL) && (sl->spacetype == SPACE_IMAGE)) { return true; } @@ -716,7 +716,8 @@ static bool brush_generic_tool_set(bContext *C, brush = brush_tool_cycle(bmain, paint, brush_orig, tool); } - if (!brush && brush_tool(brush_orig, paint->runtime.tool_offset) != tool && create_missing) { + if (((brush == NULL) && create_missing) && + ((brush_orig == NULL) || brush_tool(brush_orig, paint->runtime.tool_offset) != tool)) { brush = BKE_brush_add(bmain, tool_name, paint->runtime.ob_mode); id_us_min(&brush->id); /* fake user only */ brush_tool_set(brush, paint->runtime.tool_offset, tool); @@ -778,6 +779,9 @@ static int brush_select_exec(bContext *C, wmOperator *op) } Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode); + if (paint == NULL) { + return OPERATOR_CANCELLED; + } const EnumPropertyItem *items = BKE_paint_get_tool_enum_from_paintmode(paint_mode); RNA_enum_name_from_value(items, tool, &tool_name); diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 01a0e8ddd5b..935b9ef9506 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -1103,11 +1103,11 @@ struct wmKeyMap *paint_stroke_modal_keymap(struct wmKeyConfig *keyconf) static const char *name = "Paint Stroke Modal"; - struct wmKeyMap *keymap = WM_modalkeymap_get(keyconf, name); + struct wmKeyMap *keymap = WM_modalkeymap_find(keyconf, name); /* this function is called for each spacetype, only needs to add map once */ if (!keymap) { - keymap = WM_modalkeymap_add(keyconf, name, modal_items); + keymap = WM_modalkeymap_ensure(keyconf, name, modal_items); } return keymap; diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index bec44242931..6ccd197c908 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -196,21 +196,15 @@ float SCULPT_vertex_mask_get(SculptSession *ss, int index) return 0.0f; } -static int SCULPT_active_vertex_get(SculptSession *ss) +int SCULPT_active_vertex_get(SculptSession *ss) { - switch (BKE_pbvh_type(ss->pbvh)) { - case PBVH_FACES: - return ss->active_vertex_index; - case PBVH_BMESH: - return ss->active_vertex_index; - case PBVH_GRIDS: - return ss->active_vertex_index; + if (ELEM(BKE_pbvh_type(ss->pbvh), PBVH_FACES, PBVH_BMESH, PBVH_GRIDS)) { + return ss->active_vertex_index; } - return 0; } -static const float *SCULPT_active_vertex_co_get(SculptSession *ss) +const float *SCULPT_active_vertex_co_get(SculptSession *ss) { return SCULPT_vertex_co_get(ss, SCULPT_active_vertex_get(ss)); } @@ -292,6 +286,14 @@ static void SCULPT_face_sets_visibility_all_set(SculptSession *ss, bool visible) switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: for (int i = 0; i < ss->totpoly; i++) { + + /* This can run on geometry without a face set assigned, so its ID sign can't be changed to + * modify the visibility. Force that geometry to the ID 1 to enable changing the visibility + * here. */ + if (ss->face_sets[i] == SCULPT_FACE_SET_NONE) { + ss->face_sets[i] = 1; + } + if (visible) { ss->face_sets[i] = abs(ss->face_sets[i]); } @@ -365,7 +367,7 @@ static void SCULPT_vertex_face_set_set(SculptSession *ss, int index, int face_se } } -static int SCULPT_vertex_face_set_get(SculptSession *ss, int index) +int SCULPT_vertex_face_set_get(SculptSession *ss, int index) { switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: { @@ -386,7 +388,7 @@ static int SCULPT_vertex_face_set_get(SculptSession *ss, int index) return 0; } -static bool SCULPT_vertex_has_face_set(SculptSession *ss, int index, int face_set) +bool SCULPT_vertex_has_face_set(SculptSession *ss, int index, int face_set) { switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: { @@ -418,7 +420,8 @@ void SCULPT_visibility_sync_all_face_sets_to_vertices(SculptSession *ss) } } -static void sculpt_visibility_sync_vertex_to_face_sets(SculptSession *ss, int index) +static void UNUSED_FUNCTION(sculpt_visibility_sync_vertex_to_face_sets)(SculptSession *ss, + int index) { MeshElemMap *vert_map = &ss->pmap[index]; const bool visible = SCULPT_vertex_visible_get(ss, index); @@ -435,12 +438,27 @@ static void sculpt_visibility_sync_vertex_to_face_sets(SculptSession *ss, int in void SCULPT_visibility_sync_all_vertex_to_face_sets(SculptSession *ss) { - for (int i = 0; i < ss->totvert; i++) { - sculpt_visibility_sync_vertex_to_face_sets(ss, i); + if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) { + for (int i = 0; i < ss->totpoly; i++) { + MPoly *poly = &ss->mpoly[i]; + bool poly_visible = true; + for (int l = 0; l < poly->totloop; l++) { + MLoop *loop = &ss->mloop[poly->loopstart + l]; + if (!SCULPT_vertex_visible_get(ss, (int)loop->v)) { + poly_visible = false; + } + } + if (poly_visible) { + ss->face_sets[i] = abs(ss->face_sets[i]); + } + else { + ss->face_sets[i] = -abs(ss->face_sets[i]); + } + } } } -static bool sculpt_vertex_has_unique_face_set(SculptSession *ss, int index) +bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, int index) { switch (BKE_pbvh_type(ss->pbvh)) { case PBVH_FACES: { @@ -543,18 +561,18 @@ static void sculpt_vertex_neighbors_get_faces(SculptSession *ss, int index, SculptVertexNeighborIter *iter) { - MeshElemMap *vert_map = &ss->pmap[(int)index]; + MeshElemMap *vert_map = &ss->pmap[index]; iter->size = 0; iter->num_duplicates = 0; iter->capacity = SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY; iter->neighbors = iter->neighbors_fixed; - for (int i = 0; i < ss->pmap[(int)index].count; i++) { + for (int i = 0; i < ss->pmap[index].count; i++) { const MPoly *p = &ss->mpoly[vert_map->indices[i]]; uint f_adj_v[2]; - if (poly_get_adj_loops_from_vert(p, ss->mloop, (int)index, f_adj_v) != -1) { + if (poly_get_adj_loops_from_vert(p, ss->mloop, index, f_adj_v) != -1) { for (int j = 0; j < ARRAY_SIZE(f_adj_v); j += 1) { - if (f_adj_v[j] != (int)index) { + if (f_adj_v[j] != index) { sculpt_vertex_neighbor_add(iter, f_adj_v[j]); } } @@ -795,11 +813,35 @@ void SCULPT_floodfill_init(SculptSession *ss, SculptFloodFill *flood) flood->visited_vertices = MEM_callocN(vertex_count * sizeof(char), "visited vertices"); } -static void sculpt_floodfill_add_initial(SculptFloodFill *flood, int index) +void sculpt_floodfill_add_initial(SculptFloodFill *flood, int index) { BLI_gsqueue_push(flood->queue, &index); } +void SCULPT_floodfill_add_initial_with_symmetry( + Sculpt *sd, Object *ob, SculptSession *ss, SculptFloodFill *flood, int index, float radius) +{ + /* Add active vertex and symmetric vertices to the queue. */ + const char symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL; + for (char i = 0; i <= symm; ++i) { + if (SCULPT_is_symmetry_iteration_valid(i, symm)) { + int v = -1; + if (i == 0) { + v = index; + } + else if (radius > 0.0f) { + float radius_squared = (radius == FLT_MAX) ? FLT_MAX : radius * radius; + float location[3]; + flip_v3_v3(location, SCULPT_vertex_co_get(ss, index), i); + v = SCULPT_nearest_vertex_get(sd, ob, location, radius_squared, false); + } + if (v != -1) { + sculpt_floodfill_add_initial(flood, v); + } + } + } +} + void SCULPT_floodfill_add_active( Sculpt *sd, Object *ob, SculptSession *ss, SculptFloodFill *flood, float radius) { @@ -834,8 +876,7 @@ void SCULPT_floodfill_execute( int from_v; BLI_gsqueue_pop(flood->queue, &from_v); SculptVertexNeighborIter ni; - sculpt_vertex_duplicates_and_neighbors_iter_begin(ss, from_v, ni) - { + SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, from_v, ni) { const int to_v = ni.index; if (flood->visited_vertices[to_v] == 0 && SCULPT_vertex_visible_get(ss, to_v)) { flood->visited_vertices[to_v] = 1; @@ -845,7 +886,7 @@ void SCULPT_floodfill_execute( } } } - sculpt_vertex_neighbors_iter_end(ni); + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); } } @@ -891,6 +932,7 @@ static bool sculpt_tool_needs_original(const char sculpt_tool) SCULPT_TOOL_LAYER, SCULPT_TOOL_DRAW_SHARP, SCULPT_TOOL_ELASTIC_DEFORM, + SCULPT_TOOL_SMOOTH, SCULPT_TOOL_POSE); } @@ -1277,6 +1319,8 @@ void SCULPT_brush_test_init(SculptSession *ss, SculptBrushTest *test) test->radius_squared = ss->cache ? ss->cache->radius_squared : ss->cursor_radius * ss->cursor_radius; + test->radius = sqrtf(test->radius_squared); + if (ss->cache) { copy_v3_v3(test->location, ss->cache->location); test->mirror_symmetry_pass = ss->cache->mirror_symmetry_pass; @@ -1659,13 +1703,12 @@ static float *sculpt_boundary_edges_automasking_init(Object *ob, for (int i = 0; i < totvert; i++) { if (edge_distance[i] == EDGE_DISTANCE_INF) { SculptVertexNeighborIter ni; - sculpt_vertex_neighbors_iter_begin(ss, i, ni) - { + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, i, ni) { if (edge_distance[ni.index] == propagation_it) { edge_distance[i] = propagation_it + 1; } } - sculpt_vertex_neighbors_iter_end(ni); + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); } } } @@ -1843,6 +1886,7 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata, if (!(ss->cache && data->brush->sculpt_tool == SCULPT_TOOL_LAYER)) { test_radius *= data->brush->normal_radius_factor; } + normal_test.radius = test_radius; normal_test.radius_squared = test_radius * test_radius; } @@ -1863,6 +1907,7 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata, test_radius *= data->brush->normal_radius_factor; } } + area_test.radius = test_radius; area_test.radius_squared = test_radius * test_radius; } @@ -1896,10 +1941,26 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata, flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); if (use_area_cos && area_test_r) { + /* Weight the coordinates towards the center. */ + float p = 1.0f - (sqrtf(area_test.dist) / area_test.radius); + float afactor = 3.0f * p * p - 2.0f * p * p * p; + CLAMP(afactor, 0.0f, 1.0f); + + float disp[3]; + sub_v3_v3v3(disp, co, area_test.location); + mul_v3_fl(disp, 1.0f - afactor); + add_v3_v3v3(co, area_test.location, disp); add_v3_v3(anctd->area_cos[flip_index], co); + anctd->count_co[flip_index] += 1; } if (use_area_nos && normal_test_r) { + /* Weight the normals towards the center. */ + float p = 1.0f - (sqrtf(normal_test.dist) / normal_test.radius); + float nfactor = 3.0f * p * p - 2.0f * p * p * p; + CLAMP(nfactor, 0.0f, 1.0f); + mul_v3_fl(no, nfactor); + add_v3_v3(anctd->area_nos[flip_index], no); anctd->count_no[flip_index] += 1; } @@ -1909,54 +1970,73 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata, else { BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - const float *co; + float co[3]; + /* For bm_vert only. */ - const short *no_s; + short no_s[3]; if (use_original) { if (unode->bm_entry) { - BM_log_original_vert_data(ss->bm_log, vd.bm_vert, &co, &no_s); + const float *temp_co; + const short *temp_no_s; + BM_log_original_vert_data(ss->bm_log, vd.bm_vert, &temp_co, &temp_no_s); + copy_v3_v3(co, temp_co); + copy_v3_v3_short(no_s, temp_no_s); } else { - co = unode->co[vd.i]; - no_s = unode->no[vd.i]; + copy_v3_v3(co, unode->co[vd.i]); + copy_v3_v3_short(no_s, unode->no[vd.i]); } } else { - co = vd.co; + copy_v3_v3(co, vd.co); } normal_test_r = sculpt_brush_normal_test_sq_fn(&normal_test, co); area_test_r = sculpt_brush_area_test_sq_fn(&area_test, co); if (normal_test_r || area_test_r) { - float no_buf[3]; - const float *no; + float no[3]; int flip_index; data->any_vertex_sampled = true; if (use_original) { - normal_short_to_float_v3(no_buf, no_s); - no = no_buf; + normal_short_to_float_v3(no, no_s); } else { if (vd.no) { - normal_short_to_float_v3(no_buf, vd.no); - no = no_buf; + normal_short_to_float_v3(no, vd.no); } else { - no = vd.fno; + copy_v3_v3(no, vd.fno); } } flip_index = (dot_v3v3(ss->cache ? ss->cache->view_normal : ss->cursor_view_normal, no) <= 0.0f); + if (use_area_cos && area_test_r) { + /* Weight the coordinates towards the center. */ + float p = 1.0f - (sqrtf(area_test.dist) / area_test.radius); + float afactor = 3.0f * p * p - 2.0f * p * p * p; + CLAMP(afactor, 0.0f, 1.0f); + + float disp[3]; + sub_v3_v3v3(disp, co, area_test.location); + mul_v3_fl(disp, 1.0f - afactor); + add_v3_v3v3(co, area_test.location, disp); + add_v3_v3(anctd->area_cos[flip_index], co); anctd->count_co[flip_index] += 1; } if (use_area_nos && normal_test_r) { + /* Weight the normals towards the center. */ + float p = 1.0f - (sqrtf(normal_test.dist) / normal_test.radius); + float nfactor = 3.0f * p * p - 2.0f * p * p * p; + CLAMP(nfactor, 0.0f, 1.0f); + mul_v3_fl(no, nfactor); + add_v3_v3(anctd->area_nos[flip_index], no); anctd->count_no[flip_index] += 1; } @@ -2836,18 +2916,17 @@ static float bmesh_neighbor_average_mask(BMVert *v, const int cd_vert_mask_offse } } -static void grids_neighbor_average(SculptSession *ss, float result[3], int index) +static void SCULPT_neighbor_coords_average(SculptSession *ss, float result[3], int index) { float avg[3] = {0.0f, 0.0f, 0.0f}; int total = 0; SculptVertexNeighborIter ni; - sculpt_vertex_neighbors_iter_begin(ss, index, ni) - { + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, index, ni) { add_v3_v3(avg, SCULPT_vertex_co_get(ss, ni.index)); total++; } - sculpt_vertex_neighbors_iter_end(ni); + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); if (total > 0) { mul_v3_v3fl(result, avg, 1.0f / (float)total); @@ -2863,12 +2942,11 @@ static float grids_neighbor_average_mask(SculptSession *ss, int index) int total = 0; SculptVertexNeighborIter ni; - sculpt_vertex_neighbors_iter_begin(ss, index, ni) - { + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, index, ni) { avg += SCULPT_vertex_mask_get(ss, ni.index); total++; } - sculpt_vertex_neighbors_iter_end(ni); + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); if (total > 0) { return avg / (float)total; @@ -3132,7 +3210,7 @@ static void do_smooth_brush_multires_task_cb_ex(void *__restrict userdata, } else { float avg[3], val[3]; - grids_neighbor_average(ss, avg, vd.index); + SCULPT_neighbor_coords_average(ss, avg, vd.index); sub_v3_v3v3(val, avg, vd.co); madd_v3_v3v3fl(val, vd.co, val, fade); sculpt_clip(sd, ss, vd.co, val); @@ -3231,6 +3309,152 @@ static void do_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod SculptSession *ss = ob->sculpt; smooth(sd, ob, nodes, totnode, ss->cache->bstrength, false); } +/* HC Smooth Algorithm. */ +/* From: Improved Laplacian Smoothing of Noisy Surface Meshes */ + +static void surface_smooth_laplacian_step(SculptSession *ss, + float *disp, + const float co[3], + float (*laplacian_disp)[3], + const int v_index, + const float origco[3], + const float alpha) +{ + float laplacian_smooth_co[3]; + float weigthed_o[3], weigthed_q[3], d[3]; + SCULPT_neighbor_coords_average(ss, laplacian_smooth_co, v_index); + + mul_v3_v3fl(weigthed_o, origco, alpha); + mul_v3_v3fl(weigthed_q, co, 1.0f - alpha); + add_v3_v3v3(d, weigthed_o, weigthed_q); + sub_v3_v3v3(laplacian_disp[v_index], laplacian_smooth_co, d); + + sub_v3_v3v3(disp, laplacian_smooth_co, co); +} + +static void surface_smooth_displace_step(SculptSession *ss, + float *co, + float (*laplacian_disp)[3], + const int v_index, + const float beta, + const float fade) +{ + float b_avg[3] = {0.0f, 0.0f, 0.0f}; + float b_current_vertex[3]; + int total = 0; + SculptVertexNeighborIter ni; + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, v_index, ni) { + add_v3_v3(b_avg, laplacian_disp[ni.index]); + total++; + } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); + if (total > 0) { + mul_v3_v3fl(b_current_vertex, b_avg, (1.0f - beta) / (float)total); + madd_v3_v3fl(b_current_vertex, laplacian_disp[v_index], beta); + mul_v3_fl(b_current_vertex, clamp_f(fade, 0.0f, 1.0f)); + sub_v3_v3(co, b_current_vertex); + } +} + +static void do_surface_smooth_brush_laplacian_task_cb_ex(void *__restrict userdata, + const int n, + const TaskParallelTLS *__restrict tls) +{ + SculptThreadedTaskData *data = userdata; + SculptSession *ss = data->ob->sculpt; + const Brush *brush = data->brush; + const float bstrength = ss->cache->bstrength; + float alpha = brush->surface_smooth_shape_preservation; + + PBVHVertexIter vd; + SculptOrigVertData orig_data; + + SculptBrushTest test; + SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( + ss, &test, data->brush->falloff_shape); + + SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]); + + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) + { + SCULPT_orig_vert_data_update(&orig_data, &vd); + if (sculpt_brush_test_sq_fn(&test, vd.co)) { + const float fade = + bstrength * + SCULPT_brush_strength_factor( + ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, tls->thread_id); + + float disp[3]; + surface_smooth_laplacian_step(ss, + disp, + vd.co, + ss->cache->surface_smooth_laplacian_disp, + vd.index, + orig_data.co, + alpha); + madd_v3_v3fl(vd.co, disp, clamp_f(fade, 0.0f, 1.0f)); + } + BKE_pbvh_vertex_iter_end; + } +} + +static void do_surface_smooth_brush_displace_task_cb_ex(void *__restrict userdata, + const int n, + const TaskParallelTLS *__restrict tls) +{ + SculptThreadedTaskData *data = userdata; + SculptSession *ss = data->ob->sculpt; + const Brush *brush = data->brush; + const float bstrength = ss->cache->bstrength; + const float beta = brush->surface_smooth_current_vertex; + + PBVHVertexIter vd; + + SculptBrushTest test; + SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( + ss, &test, data->brush->falloff_shape); + + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) + { + if (sculpt_brush_test_sq_fn(&test, vd.co)) { + const float fade = + bstrength * + SCULPT_brush_strength_factor( + ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, tls->thread_id); + surface_smooth_displace_step( + ss, vd.co, ss->cache->surface_smooth_laplacian_disp, vd.index, beta, fade); + } + } + BKE_pbvh_vertex_iter_end; +} + +static void do_surface_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) +{ + Brush *brush = BKE_paint_brush(&sd->paint); + SculptSession *ss = ob->sculpt; + + if (ss->cache->mirror_symmetry_pass == 0 && ss->cache->radial_symmetry_pass == 0) { + ss->cache->surface_smooth_laplacian_disp = MEM_callocN( + SCULPT_vertex_count_get(ss) * 3 * sizeof(float), "HC smooth laplacian b"); + } + + /* Threaded loop over nodes. */ + SculptThreadedTaskData data = { + .sd = sd, + .ob = ob, + .brush = brush, + .nodes = nodes, + }; + + PBVHParallelSettings settings; + BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); + for (int i = 0; i < brush->surface_smooth_iterations; i++) { + BKE_pbvh_parallel_range( + 0, totnode, &data, do_surface_smooth_brush_laplacian_task_cb_ex, &settings); + BKE_pbvh_parallel_range( + 0, totnode, &data, do_surface_smooth_brush_displace_task_cb_ex, &settings); + } +} static void do_mask_brush_draw_task_cb_ex(void *__restrict userdata, const int n, @@ -3433,7 +3657,7 @@ static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_sq_fn(&test, vd.co)) { - if (relax_face_sets != sculpt_vertex_has_unique_face_set(ss, vd.index)) { + if (relax_face_sets != SCULPT_vertex_has_unique_face_set(ss, vd.index)) { const float fade = bstrength * SCULPT_brush_strength_factor(ss, brush, vd.co, @@ -3615,8 +3839,7 @@ static void do_topology_slide_task_cb_ex(void *__restrict userdata, normalize_v3_v3(current_disp_norm, current_disp); mul_v3_v3fl(current_disp, current_disp_norm, ss->cache->bstrength); SculptVertexNeighborIter ni; - sculpt_vertex_neighbors_iter_begin(ss, vd.index, ni) - { + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) { float vertex_disp[3]; float vertex_disp_norm[3]; sub_v3_v3v3(vertex_disp, SCULPT_vertex_co_get(ss, ni.index), vd.co); @@ -3625,7 +3848,7 @@ static void do_topology_slide_task_cb_ex(void *__restrict userdata, madd_v3_v3fl(final_disp, vertex_disp_norm, dot_v3v3(current_disp, vertex_disp)); } } - sculpt_vertex_neighbors_iter_end(ni); + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); mul_v3_v3fl(proxy[vd.i], final_disp, fade); @@ -3649,15 +3872,14 @@ void SCULPT_relax_vertex(SculptSession *ss, zero_v3(smooth_pos); SculptVertexNeighborIter ni; - sculpt_vertex_neighbors_iter_begin(ss, vd->index, ni) - { + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd->index, ni) { if (!filter_boundary_face_sets || - (filter_boundary_face_sets && !sculpt_vertex_has_unique_face_set(ss, ni.index))) { + (filter_boundary_face_sets && !SCULPT_vertex_has_unique_face_set(ss, ni.index))) { add_v3_v3(smooth_pos, SCULPT_vertex_co_get(ss, ni.index)); count++; } } - sculpt_vertex_neighbors_iter_end(ni); + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); if (count > 0) { mul_v3_fl(smooth_pos, 1.0f / (float)count); @@ -5599,10 +5821,10 @@ static void do_clay_thumb_brush_task_cb_ex(void *__restrict userdata, static float sculpt_clay_thumb_get_stabilized_pressure(StrokeCache *cache) { float final_pressure = 0.0f; - for (int i = 0; i < CLAY_STABILIZER_LEN; i++) { + for (int i = 0; i < SCULPT_CLAY_STABILIZER_LEN; i++) { final_pressure += cache->clay_pressure_stabilizer[i]; } - return final_pressure / (float)CLAY_STABILIZER_LEN; + return final_pressure / (float)SCULPT_CLAY_STABILIZER_LEN; } static void do_clay_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) @@ -5987,7 +6209,12 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe do_draw_brush(sd, ob, nodes, totnode); break; case SCULPT_TOOL_SMOOTH: - do_smooth_brush(sd, ob, nodes, totnode); + if (brush->smooth_deform_type == BRUSH_SMOOTH_DEFORM_LAPLACIAN) { + do_smooth_brush(sd, ob, nodes, totnode); + } + else if (brush->smooth_deform_type == BRUSH_SMOOTH_DEFORM_SURFACE) { + do_surface_smooth_brush(sd, ob, nodes, totnode); + } break; case SCULPT_TOOL_CREASE: do_crease_brush(sd, ob, nodes, totnode); @@ -7072,7 +7299,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, Po /* Clay stabilized pressure. */ if (brush->sculpt_tool == SCULPT_TOOL_CLAY_THUMB) { if (ss->cache->first_time) { - for (int i = 0; i < CLAY_STABILIZER_LEN; i++) { + for (int i = 0; i < SCULPT_CLAY_STABILIZER_LEN; i++) { ss->cache->clay_pressure_stabilizer[i] = 0.0f; } ss->cache->clay_pressure_stabilizer_index = 0; @@ -7080,7 +7307,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, Po else { cache->clay_pressure_stabilizer[cache->clay_pressure_stabilizer_index] = cache->pressure; cache->clay_pressure_stabilizer_index += 1; - if (cache->clay_pressure_stabilizer_index >= CLAY_STABILIZER_LEN) { + if (cache->clay_pressure_stabilizer_index >= SCULPT_CLAY_STABILIZER_LEN) { cache->clay_pressure_stabilizer_index = 0; } } @@ -8128,6 +8355,22 @@ static void sculpt_dynamic_topology_disable_ex( } else { BKE_sculptsession_bm_to_me(ob, true); + + /* Reset Face Sets as they are no longer valid. */ + if (!CustomData_has_layer(&me->pdata, CD_SCULPT_FACE_SETS)) { + CustomData_add_layer(&me->pdata, CD_SCULPT_FACE_SETS, CD_CALLOC, NULL, me->totpoly); + } + ss->face_sets = CustomData_get_layer(&me->pdata, CD_SCULPT_FACE_SETS); + for (int i = 0; i < me->totpoly; i++) { + ss->face_sets[i] = 1; + } + me->face_sets_color_default = 1; + + /* Sync the visibility to vertices manually as the pmap is still not initialized. */ + for (int i = 0; i < me->totvert; i++) { + me->mvert[i].flag &= ~ME_HIDE; + me->mvert[i].flag |= ME_VERT_PBVH_UPDATE; + } } /* Clear data. */ @@ -8853,12 +9096,11 @@ static void sample_detail_voxel(bContext *C, ViewContext *vc, int mx, int my) float edge_length = 0.0f; int tot = 0; SculptVertexNeighborIter ni; - sculpt_vertex_neighbors_iter_begin(ss, active_vertex, ni) - { + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, active_vertex, ni) { edge_length += len_v3v3(active_vertex_co, SCULPT_vertex_co_get(ss, ni.index)); tot += 1; } - sculpt_vertex_neighbors_iter_end(ni); + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); if (tot > 0) { mesh->remesh_voxel_size = edge_length / (float)tot; } @@ -9155,7 +9397,9 @@ static void sculpt_filter_cache_free(SculptSession *ss) if (ss->filter_cache->automask) { MEM_freeN(ss->filter_cache->automask); } - + if (ss->filter_cache->surface_smooth_laplacian_disp) { + MEM_freeN(ss->filter_cache->surface_smooth_laplacian_disp); + } MEM_freeN(ss->filter_cache); ss->filter_cache = NULL; } @@ -9168,6 +9412,7 @@ typedef enum eSculptMeshFilterTypes { MESH_FILTER_RANDOM = 4, MESH_FILTER_RELAX = 5, MESH_FILTER_RELAX_FACE_SETS = 6, + MESH_FILTER_SURFACE_SMOOTH = 7, } eSculptMeshFilterTypes; static EnumPropertyItem prop_mesh_filter_types[] = { @@ -9182,6 +9427,11 @@ static EnumPropertyItem prop_mesh_filter_types[] = { 0, "Relax Face Sets", "Smooth the edges of all the Face Sets"}, + {MESH_FILTER_SURFACE_SMOOTH, + "SURFACE_SMOOTH", + 0, + "Surface Smooth", + "Smooth the surface of the mesh, preserving the volume"}, {0, NULL, 0, NULL, NULL}, }; @@ -9198,9 +9448,13 @@ static EnumPropertyItem prop_mesh_filter_deform_axis_items[] = { {0, NULL, 0, NULL, NULL}, }; -static bool sculpt_mesh_filter_needs_pmap(int filter_type) +static bool sculpt_mesh_filter_needs_pmap(int filter_type, bool use_face_sets) { - return ELEM(filter_type, MESH_FILTER_SMOOTH, MESH_FILTER_RELAX, MESH_FILTER_RELAX_FACE_SETS); + return use_face_sets || ELEM(filter_type, + MESH_FILTER_SMOOTH, + MESH_FILTER_RELAX, + MESH_FILTER_RELAX_FACE_SETS, + MESH_FILTER_SURFACE_SMOOTH); } static void mesh_filter_task_cb(void *__restrict userdata, @@ -9242,7 +9496,7 @@ static void mesh_filter_task_cb(void *__restrict userdata, /* Skip the edges of the face set when relaxing or smoothing. There is a relax face set * option to relax the boindaries independently. */ if (filter_type == MESH_FILTER_RELAX) { - if (!sculpt_vertex_has_unique_face_set(ss, vd.index)) { + if (!SCULPT_vertex_has_unique_face_set(ss, vd.index)) { continue; } } @@ -9256,7 +9510,7 @@ static void mesh_filter_task_cb(void *__restrict userdata, } if (filter_type == MESH_FILTER_RELAX_FACE_SETS) { - if (relax_face_sets == sculpt_vertex_has_unique_face_set(ss, vd.index)) { + if (relax_face_sets == SCULPT_vertex_has_unique_face_set(ss, vd.index)) { continue; } } @@ -9272,7 +9526,7 @@ static void mesh_filter_task_cb(void *__restrict userdata, bmesh_neighbor_average(avg, vd.bm_vert); break; case PBVH_GRIDS: - grids_neighbor_average(ss, avg, vd.index); + SCULPT_neighbor_coords_average(ss, avg, vd.index); break; } sub_v3_v3v3(val, avg, orig_co); @@ -9333,6 +9587,16 @@ static void mesh_filter_task_cb(void *__restrict userdata, sub_v3_v3v3(disp, val, vd.co); break; } + case MESH_FILTER_SURFACE_SMOOTH: { + surface_smooth_laplacian_step(ss, + disp, + vd.co, + ss->filter_cache->surface_smooth_laplacian_disp, + vd.index, + orig_data.co, + ss->filter_cache->surface_smooth_shape_preservation); + break; + } } for (int it = 0; it < 3; it++) { @@ -9341,7 +9605,12 @@ static void mesh_filter_task_cb(void *__restrict userdata, } } - add_v3_v3v3(final_pos, orig_co, disp); + if (filter_type == MESH_FILTER_SURFACE_SMOOTH) { + madd_v3_v3v3fl(final_pos, vd.co, disp, clamp_f(fade, 0.0f, 1.0f)); + } + else { + add_v3_v3v3(final_pos, orig_co, disp); + } copy_v3_v3(vd.co, final_pos); if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; @@ -9352,6 +9621,32 @@ static void mesh_filter_task_cb(void *__restrict userdata, BKE_pbvh_node_mark_update(node); } +static void mesh_filter_surface_smooth_displace_task_cb( + void *__restrict userdata, const int i, const TaskParallelTLS *__restrict UNUSED(tls)) +{ + SculptThreadedTaskData *data = userdata; + SculptSession *ss = data->ob->sculpt; + PBVHNode *node = data->nodes[i]; + PBVHVertexIter vd; + + BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE) + { + float fade = vd.mask ? *vd.mask : 0.0f; + fade = 1.0f - fade; + fade *= data->filter_strength; + if (fade == 0.0f) { + continue; + } + surface_smooth_displace_step(ss, + vd.co, + ss->filter_cache->surface_smooth_laplacian_disp, + vd.index, + ss->filter_cache->surface_smooth_current_vertex, + clamp_f(fade, 0.0f, 1.0f)); + } + BKE_pbvh_vertex_iter_end; +} + static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent *event) { Object *ob = CTX_data_active_object(C); @@ -9360,6 +9655,7 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent * Sculpt *sd = CTX_data_tool_settings(C)->sculpt; int filter_type = RNA_enum_get(op->ptr, "type"); float filter_strength = RNA_float_get(op->ptr, "strength"); + const bool use_face_sets = RNA_boolean_get(op->ptr, "use_face_sets"); if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { sculpt_filter_cache_free(ss); @@ -9377,7 +9673,7 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent * SCULPT_vertex_random_access_init(ss); - bool needs_pmap = sculpt_mesh_filter_needs_pmap(filter_type); + bool needs_pmap = sculpt_mesh_filter_needs_pmap(filter_type, use_face_sets); BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_pmap, false); SculptThreadedTaskData data = { @@ -9393,6 +9689,14 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent * &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); BKE_pbvh_parallel_range(0, ss->filter_cache->totnode, &data, mesh_filter_task_cb, &settings); + if (filter_type == MESH_FILTER_SURFACE_SMOOTH) { + BKE_pbvh_parallel_range(0, + ss->filter_cache->totnode, + &data, + mesh_filter_surface_smooth_displace_task_cb, + &settings); + } + ss->filter_cache->iteration_count++; if (ss->deform_modifiers_active || ss->shapekey_active) { @@ -9432,9 +9736,11 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false); } + const bool use_face_sets = RNA_boolean_get(op->ptr, "use_face_sets"); + SCULPT_vertex_random_access_init(ss); - bool needs_pmap = sculpt_mesh_filter_needs_pmap(filter_type); + bool needs_pmap = sculpt_mesh_filter_needs_pmap(filter_type, use_face_sets); BKE_sculpt_update_object_for_edit(depsgraph, ob, needs_pmap, false); if (BKE_pbvh_type(pbvh) == PBVH_FACES && needs_pmap && !ob->sculpt->pmap) { @@ -9445,7 +9751,7 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent sculpt_filter_cache_init(ob, sd); - if (RNA_boolean_get(op->ptr, "use_face_sets")) { + if (use_face_sets) { ss->filter_cache->active_face_set = SCULPT_vertex_face_set_get(ss, SCULPT_active_vertex_get(ss)); } @@ -9453,6 +9759,15 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent ss->filter_cache->active_face_set = SCULPT_FACE_SET_NONE; } + if (RNA_enum_get(op->ptr, "type") == MESH_FILTER_SURFACE_SMOOTH) { + ss->filter_cache->surface_smooth_laplacian_disp = MEM_mallocN( + 3 * sizeof(float) * SCULPT_vertex_count_get(ss), "surface smooth disp"); + ss->filter_cache->surface_smooth_shape_preservation = RNA_float_get( + op->ptr, "surface_smooth_shape_preservation"); + ss->filter_cache->surface_smooth_current_vertex = RNA_float_get( + op->ptr, "surface_smooth_current_vertex"); + } + ss->filter_cache->enabled_axis[0] = deform_axis & MESH_FILTER_DEFORM_X; ss->filter_cache->enabled_axis[1] = deform_axis & MESH_FILTER_DEFORM_Y; ss->filter_cache->enabled_axis[2] = deform_axis & MESH_FILTER_DEFORM_Z; @@ -9505,6 +9820,26 @@ static void SCULPT_OT_mesh_filter(struct wmOperatorType *ot) false, "Use Face Sets", "Apply the filter only to the Face Mask under the cursor"); + + /* Surface Smooth Mesh Filter properties. */ + RNA_def_float(ot->srna, + "surface_smooth_shape_preservation", + 0.5f, + 0.0f, + 1.0f, + "Shape Preservation", + "How much of the original shape is preserved when smoothing", + 0.0f, + 1.0f); + RNA_def_float(ot->srna, + "surface_smooth_current_vertex", + 0.5f, + 0.0f, + 1.0f, + "Per Vertex Displacement", + "How much the position of each individual vertex influences the final result", + 0.0f, + 1.0f); } typedef enum eSculptMaskFilterTypes { @@ -9596,26 +9931,24 @@ static void mask_filter_task_cb(void *__restrict userdata, } case MASK_FILTER_GROW: max = 0.0f; - sculpt_vertex_neighbors_iter_begin(ss, vd.index, ni) - { + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) { float vmask_f = data->prev_mask[ni.index]; if (vmask_f > max) { max = vmask_f; } } - sculpt_vertex_neighbors_iter_end(ni); + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); *vd.mask = max; break; case MASK_FILTER_SHRINK: min = 1.0f; - sculpt_vertex_neighbors_iter_begin(ss, vd.index, ni) - { + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) { float vmask_f = data->prev_mask[ni.index]; if (vmask_f < min) { min = vmask_f; } } - sculpt_vertex_neighbors_iter_end(ni); + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); *vd.mask = min; break; case MASK_FILTER_CONTRAST_INCREASE: @@ -9766,15 +10099,14 @@ static float neighbor_dirty_mask(SculptSession *ss, PBVHVertexIter *vd) zero_v3(avg); SculptVertexNeighborIter ni; - sculpt_vertex_neighbors_iter_begin(ss, vd->index, ni) - { + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd->index, ni) { float normalized[3]; sub_v3_v3v3(normalized, SCULPT_vertex_co_get(ss, ni.index), vd->co); normalize_v3(normalized); add_v3_v3(avg, normalized); total++; } - sculpt_vertex_neighbors_iter_end(ni); + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); if (total > 0) { mul_v3_fl(avg, 1.0f / total); @@ -10323,11 +10655,10 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent for (int i = 0; i < vertex_count; i++) { float avg = 0.0f; SculptVertexNeighborIter ni; - sculpt_vertex_neighbors_iter_begin(ss, i, ni) - { + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, i, ni) { avg += ss->filter_cache->normal_factor[ni.index]; } - sculpt_vertex_neighbors_iter_end(ni); + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); ss->filter_cache->normal_factor[i] = avg / ni.size; } } @@ -10452,8 +10783,7 @@ void SCULPT_geometry_preview_lines_update(bContext *C, SculptSession *ss, float int from_v; BLI_gsqueue_pop(not_visited_vertices, &from_v); SculptVertexNeighborIter ni; - sculpt_vertex_neighbors_iter_begin(ss, from_v, ni) - { + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, from_v, ni) { if (totpoints + (ni.size * 2) < max_preview_vertices) { int to_v = ni.index; ss->preview_vert_index_list[totpoints] = from_v; @@ -10469,7 +10799,7 @@ void SCULPT_geometry_preview_lines_update(bContext *C, SculptSession *ss, float } } } - sculpt_vertex_neighbors_iter_end(ni); + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); } BLI_gsqueue_free(not_visited_vertices); @@ -10798,6 +11128,7 @@ typedef enum eSculptFaceGroupsCreateModes { SCULPT_FACE_SET_MASKED = 0, SCULPT_FACE_SET_VISIBLE = 1, SCULPT_FACE_SET_ALL = 2, + SCULPT_FACE_SET_SELECTION = 3, } eSculptFaceGroupsCreateModes; static EnumPropertyItem prop_sculpt_face_set_create_types[] = { @@ -10822,6 +11153,13 @@ static EnumPropertyItem prop_sculpt_face_set_create_types[] = { "Face Set Full Mesh", "Create an unique Face Set with all faces in the sculpt", }, + { + SCULPT_FACE_SET_SELECTION, + "SELECTION", + 0, + "Face Set From Edit Mode Selection", + "Create an Face Set corresponding to the Edit Mode face selection", + }, {0, NULL, 0, NULL, NULL}, }; @@ -10880,6 +11218,31 @@ static int sculpt_face_set_create_invoke(bContext *C, wmOperator *op, const wmEv } } + if (mode == SCULPT_FACE_SET_SELECTION) { + Mesh *mesh = ob->data; + BMesh *bm; + const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh); + bm = BM_mesh_create(&allocsize, + &((struct BMeshCreateParams){ + .use_toolflags = true, + })); + + BM_mesh_bm_from_me(bm, + mesh, + (&(struct BMeshFromMeshParams){ + .calc_face_normal = true, + })); + + BMIter iter; + BMFace *f; + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { + ss->face_sets[BM_elem_index_get(f)] = next_face_set; + } + } + BM_mesh_free(bm); + } + for (int i = 0; i < totnode; i++) { BKE_pbvh_node_mark_redraw(nodes[i]); } @@ -10911,6 +11274,349 @@ static void SCULPT_OT_face_sets_create(wmOperatorType *ot) ot->srna, "mode", prop_sculpt_face_set_create_types, SCULPT_FACE_SET_MASKED, "Mode", ""); } +typedef enum eSculptFaceSetsInitMode { + SCULPT_FACE_SETS_FROM_LOOSE_PARTS = 0, + SCULPT_FACE_SETS_FROM_MATERIALS = 1, + SCULPT_FACE_SETS_FROM_NORMALS = 2, + SCULPT_FACE_SETS_FROM_UV_SEAMS = 3, + SCULPT_FACE_SETS_FROM_CREASES = 4, + SCULPT_FACE_SETS_FROM_SHARP_EDGES = 5, + SCULPT_FACE_SETS_FROM_BEVEL_WEIGHT = 6, + SCULPT_FACE_SETS_FROM_FACE_MAPS = 7, +} eSculptFaceSetsInitMode; + +static EnumPropertyItem prop_sculpt_face_sets_init_types[] = { + { + SCULPT_FACE_SETS_FROM_LOOSE_PARTS, + "LOOSE_PARTS", + 0, + "Face Sets From Loose Parts", + "Create a Face Set per loose part in the mesh", + }, + { + SCULPT_FACE_SETS_FROM_MATERIALS, + "MATERIALS", + 0, + "Face Sets From Material Slots", + "Create a Face Set per Material Slot", + }, + { + SCULPT_FACE_SETS_FROM_NORMALS, + "NORMALS", + 0, + "Face Sets From Mesh Normals", + "Create Face Sets for Faces that have similar normal", + }, + { + SCULPT_FACE_SETS_FROM_UV_SEAMS, + "UV_SEAMS", + 0, + "Face Sets From UV Seams", + "Create Face Sets using UV Seams as boundaries", + }, + { + SCULPT_FACE_SETS_FROM_CREASES, + "CREASES", + 0, + "Face Sets From Edge Creases", + "Create Face Sets using Edge Creases as boundaries", + }, + { + SCULPT_FACE_SETS_FROM_BEVEL_WEIGHT, + "BEVEL_WEIGHT", + 0, + "Face Sets From Bevel Weight", + "Create Face Sets using Bevel Weights as boundaries", + }, + { + SCULPT_FACE_SETS_FROM_SHARP_EDGES, + "SHARP_EDGES", + 0, + "Face Sets From Sharp Edges", + "Create Face Sets using Sharp Edges as boundaries", + }, + { + SCULPT_FACE_SETS_FROM_FACE_MAPS, + "FACE_MAPS", + 0, + "Face Sets From Face Maps", + "Create a Face Set per Face Map", + }, + {0, NULL, 0, NULL, NULL}, +}; + +typedef bool (*face_sets_flood_fill_test)( + BMesh *bm, BMFace *from_f, BMEdge *from_e, BMFace *to_f, const float threshold); + +static bool sculpt_face_sets_init_loose_parts_test(BMesh *UNUSED(bm), + BMFace *UNUSED(from_f), + BMEdge *UNUSED(from_e), + BMFace *UNUSED(to_f), + const float UNUSED(threshold)) +{ + return true; +} + +static bool sculpt_face_sets_init_normals_test( + BMesh *UNUSED(bm), BMFace *from_f, BMEdge *UNUSED(from_e), BMFace *to_f, const float threshold) +{ + return fabsf(dot_v3v3(from_f->no, to_f->no)) > threshold; +} + +static bool sculpt_face_sets_init_uv_seams_test(BMesh *UNUSED(bm), + BMFace *UNUSED(from_f), + BMEdge *from_e, + BMFace *UNUSED(to_f), + const float UNUSED(threshold)) +{ + return !BM_elem_flag_test(from_e, BM_ELEM_SEAM); +} + +static bool sculpt_face_sets_init_crease_test( + BMesh *bm, BMFace *UNUSED(from_f), BMEdge *from_e, BMFace *UNUSED(to_f), const float threshold) +{ + return BM_elem_float_data_get(&bm->edata, from_e, CD_CREASE) < threshold; +} + +static bool sculpt_face_sets_init_bevel_weight_test( + BMesh *bm, BMFace *UNUSED(from_f), BMEdge *from_e, BMFace *UNUSED(to_f), const float threshold) +{ + return BM_elem_float_data_get(&bm->edata, from_e, CD_BWEIGHT) < threshold; +} + +static bool sculpt_face_sets_init_sharp_edges_test(BMesh *UNUSED(bm), + BMFace *UNUSED(from_f), + BMEdge *from_e, + BMFace *UNUSED(to_f), + const float UNUSED(threshold)) +{ + return BM_elem_flag_test(from_e, BM_ELEM_SMOOTH); +} + +static void sculpt_face_sets_init_flood_fill(Object *ob, + face_sets_flood_fill_test test, + const float threshold) +{ + SculptSession *ss = ob->sculpt; + Mesh *mesh = ob->data; + BMesh *bm; + const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh); + bm = BM_mesh_create(&allocsize, + &((struct BMeshCreateParams){ + .use_toolflags = true, + })); + + BM_mesh_bm_from_me(bm, + mesh, + (&(struct BMeshFromMeshParams){ + .calc_face_normal = true, + })); + + bool *visited_faces = MEM_callocN(sizeof(bool) * mesh->totpoly, "visited faces"); + const int totfaces = mesh->totpoly; + + int *face_sets = ss->face_sets; + + BM_mesh_elem_table_init(bm, BM_FACE); + BM_mesh_elem_table_ensure(bm, BM_FACE); + + int next_face_set = 1; + + for (int i = 0; i < totfaces; i++) { + if (!visited_faces[i]) { + GSQueue *queue; + queue = BLI_gsqueue_new(sizeof(int)); + + face_sets[i] = next_face_set; + visited_faces[i] = true; + BLI_gsqueue_push(queue, &i); + + while (!BLI_gsqueue_is_empty(queue)) { + int from_f; + BLI_gsqueue_pop(queue, &from_f); + + BMFace *f, *f_neighbor; + BMEdge *ed; + BMIter iter_a, iter_b; + + f = BM_face_at_index(bm, from_f); + + BM_ITER_ELEM (ed, &iter_a, f, BM_EDGES_OF_FACE) { + BM_ITER_ELEM (f_neighbor, &iter_b, ed, BM_FACES_OF_EDGE) { + if (f_neighbor != f) { + int neighbor_face_index = BM_elem_index_get(f_neighbor); + if (!visited_faces[neighbor_face_index]) { + if (test(bm, f, ed, f_neighbor, threshold)) { + face_sets[neighbor_face_index] = next_face_set; + visited_faces[neighbor_face_index] = true; + BLI_gsqueue_push(queue, &neighbor_face_index); + } + } + } + } + } + } + + next_face_set += 1; + + BLI_gsqueue_free(queue); + } + } + + MEM_SAFE_FREE(visited_faces); + + BM_mesh_free(bm); +} + +static void sculpt_face_sets_init_loop(Object *ob, const int mode) +{ + Mesh *mesh = ob->data; + SculptSession *ss = ob->sculpt; + BMesh *bm; + const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh); + bm = BM_mesh_create(&allocsize, + &((struct BMeshCreateParams){ + .use_toolflags = true, + })); + + BM_mesh_bm_from_me(bm, + mesh, + (&(struct BMeshFromMeshParams){ + .calc_face_normal = true, + })); + BMIter iter; + BMFace *f; + + const int cd_fmaps_offset = CustomData_get_offset(&bm->pdata, CD_FACEMAP); + + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + if (mode == SCULPT_FACE_SETS_FROM_MATERIALS) { + ss->face_sets[BM_elem_index_get(f)] = (int)(f->mat_nr + 1); + } + else if (mode == SCULPT_FACE_SETS_FROM_FACE_MAPS) { + if (cd_fmaps_offset != -1) { + ss->face_sets[BM_elem_index_get(f)] = BM_ELEM_CD_GET_INT(f, cd_fmaps_offset) + 2; + } + else { + ss->face_sets[BM_elem_index_get(f)] = 1; + } + } + } + BM_mesh_free(bm); +} + +static int sculpt_face_set_init_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + Object *ob = CTX_data_active_object(C); + SculptSession *ss = ob->sculpt; + ARegion *region = CTX_wm_region(C); + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + + const int mode = RNA_enum_get(op->ptr, "mode"); + + /* Dyntopo and Multires not supported for now. */ + if (BKE_pbvh_type(ss->pbvh) != PBVH_FACES) { + return OPERATOR_CANCELLED; + } + + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false); + + PBVH *pbvh = ob->sculpt->pbvh; + PBVHNode **nodes; + int totnode; + BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode); + + if (!nodes) { + return OPERATOR_CANCELLED; + } + + SCULPT_undo_push_begin("face set change"); + SCULPT_undo_push_node(ob, nodes[0], SCULPT_UNDO_FACE_SETS); + + const float threshold = RNA_float_get(op->ptr, "threshold"); + + switch (mode) { + case SCULPT_FACE_SETS_FROM_LOOSE_PARTS: + sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_loose_parts_test, threshold); + break; + case SCULPT_FACE_SETS_FROM_MATERIALS: + sculpt_face_sets_init_loop(ob, SCULPT_FACE_SETS_FROM_MATERIALS); + break; + case SCULPT_FACE_SETS_FROM_NORMALS: + sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_normals_test, threshold); + break; + case SCULPT_FACE_SETS_FROM_UV_SEAMS: + sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_uv_seams_test, threshold); + break; + case SCULPT_FACE_SETS_FROM_CREASES: + sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_crease_test, threshold); + break; + case SCULPT_FACE_SETS_FROM_SHARP_EDGES: + sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_sharp_edges_test, threshold); + break; + case SCULPT_FACE_SETS_FROM_BEVEL_WEIGHT: + sculpt_face_sets_init_flood_fill(ob, sculpt_face_sets_init_bevel_weight_test, threshold); + break; + case SCULPT_FACE_SETS_FROM_FACE_MAPS: + sculpt_face_sets_init_loop(ob, SCULPT_FACE_SETS_FROM_FACE_MAPS); + break; + } + + SCULPT_undo_push_end(); + + /* Sync face sets visibility and vertex visibility as now all Face Sets are visible. */ + SCULPT_visibility_sync_all_face_sets_to_vertices(ss); + + for (int i = 0; i < totnode; i++) { + BKE_pbvh_node_mark_update_visibility(nodes[i]); + } + + BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateVisibility); + + MEM_SAFE_FREE(nodes); + + if (BKE_pbvh_type(pbvh) == PBVH_FACES) { + BKE_mesh_flush_hidden_from_verts(ob->data); + } + + ED_region_tag_redraw(region); + DEG_id_tag_update(&ob->id, ID_RECALC_SHADING); + + View3D *v3d = CTX_wm_view3d(C); + if (!BKE_sculptsession_use_pbvh_draw(ob, v3d)) { + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + } + + return OPERATOR_FINISHED; +} + +static void SCULPT_OT_face_sets_init(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Init Face Sets"; + ot->idname = "SCULPT_OT_face_sets_init"; + ot->description = "Initializes all Face Sets in the mesh"; + + /* api callbacks */ + ot->invoke = sculpt_face_set_init_invoke; + ot->poll = SCULPT_mode_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_enum( + ot->srna, "mode", prop_sculpt_face_sets_init_types, SCULPT_FACE_SET_MASKED, "Mode", ""); + RNA_def_float( + ot->srna, + "threshold", + 0.5f, + 0.0f, + 1.0f, + "Threshold", + "Minimum value to consider a certain atribute a boundary when creating the Face Sets", + 0.0f, + 1.0f); +} + typedef enum eSculptFaceGroupVisibilityModes { SCULPT_FACE_SET_VISIBILITY_TOGGLE = 0, SCULPT_FACE_SET_VISIBILITY_SHOW_ACTIVE = 1, @@ -10996,19 +11702,25 @@ static int sculpt_face_sets_change_visibility_invoke(bContext *C, if (mode == SCULPT_FACE_SET_VISIBILITY_TOGGLE) { bool hidden_vertex = false; - for (int i = 0; i < tot_vert; i++) { - if (!SCULPT_vertex_visible_get(ss, i)) { - hidden_vertex = true; - break; + + /* This can fail with regular meshes with non-manifold geometry as the visibility state can't + * be synced from face sets to non-manifold vertices. */ + if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) { + for (int i = 0; i < tot_vert; i++) { + if (!SCULPT_vertex_visible_get(ss, i)) { + hidden_vertex = true; + break; + } } } for (int i = 0; i < ss->totpoly; i++) { - if (ss->face_sets[i] < 0) { + if (ss->face_sets[i] <= 0) { hidden_vertex = true; break; } } + if (hidden_vertex) { SCULPT_face_sets_visibility_all_set(ss, true); } @@ -11179,4 +11891,5 @@ void ED_operatortypes_sculpt(void) WM_operatortype_append(SCULPT_OT_face_sets_create); WM_operatortype_append(SCULPT_OT_face_sets_change_visibility); WM_operatortype_append(SCULPT_OT_face_sets_randomize_colors); + WM_operatortype_append(SCULPT_OT_face_sets_init); } diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c index a1ccae7b5ab..b1cc6d02bbb 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.c +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c @@ -145,12 +145,11 @@ static void do_cloth_brush_build_constraints_task_cb_ex( int tot_indices = 0; build_indices[tot_indices] = vd.index; tot_indices++; - sculpt_vertex_neighbors_iter_begin(ss, vd.index, ni) - { + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) { build_indices[tot_indices] = ni.index; tot_indices++; } - sculpt_vertex_neighbors_iter_end(ni); + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); /* As we don't know the order of the neighbor vertices, we create all possible combinations * between the neighbor and the original vertex as length constraints. */ @@ -446,7 +445,14 @@ static void cloth_brush_satisfy_constraints(SculptSession *ss, const float constraint_distance = constraint->length + (cloth_sim->length_constraint_tweak[v1] * 0.5f) + (cloth_sim->length_constraint_tweak[v2] * 0.5f); - mul_v3_v3fl(correction_vector, v1_to_v2, 1.0f - (constraint_distance / current_distance)); + + if (current_distance > 0.0f) { + mul_v3_v3fl(correction_vector, v1_to_v2, 1.0f - (constraint_distance / current_distance)); + } + else { + copy_v3_v3(correction_vector, v1_to_v2); + } + mul_v3_v3fl(correction_vector_half, correction_vector, 0.5f); const float mask_v1 = (1.0f - SCULPT_vertex_mask_get(ss, v1)) * diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index b8235dc5c95..fe56283dbcb 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -102,7 +102,7 @@ void SCULPT_vertex_neighbors_get(struct SculptSession *ss, SculptVertexNeighborIter *iter); /* Iterator over neighboring vertices. */ -#define sculpt_vertex_neighbors_iter_begin(ss, v_index, neighbor_iterator) \ +#define SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN(ss, v_index, neighbor_iterator) \ SCULPT_vertex_neighbors_get(ss, v_index, false, &neighbor_iterator); \ for (neighbor_iterator.i = 0; neighbor_iterator.i < neighbor_iterator.size; \ neighbor_iterator.i++) { \ @@ -110,7 +110,7 @@ void SCULPT_vertex_neighbors_get(struct SculptSession *ss, /* Iterate over neighboring and duplicate vertices (for PBVH_GRIDS). Duplicates come * first since they are nearest for floodfill. */ -#define sculpt_vertex_duplicates_and_neighbors_iter_begin(ss, v_index, neighbor_iterator) \ +#define SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN(ss, v_index, neighbor_iterator) \ SCULPT_vertex_neighbors_get(ss, v_index, true, &neighbor_iterator); \ for (neighbor_iterator.i = neighbor_iterator.size - 1; neighbor_iterator.i >= 0; \ neighbor_iterator.i--) { \ @@ -118,13 +118,16 @@ void SCULPT_vertex_neighbors_get(struct SculptSession *ss, neighbor_iterator.is_duplicate = (ni.i >= \ neighbor_iterator.size - neighbor_iterator.num_duplicates); -#define sculpt_vertex_neighbors_iter_end(neighbor_iterator) \ +#define SCULPT_VERTEX_NEIGHBORS_ITER_END(neighbor_iterator) \ } \ if (neighbor_iterator.neighbors != neighbor_iterator.neighbors_fixed) { \ MEM_freeN(neighbor_iterator.neighbors); \ } \ ((void)0) +int SCULPT_active_vertex_get(SculptSession *ss); +const float *SCULPT_active_vertex_co_get(SculptSession *ss); + /* Sculpt Original Data */ typedef struct { struct BMLog *bm_log; @@ -143,6 +146,11 @@ typedef struct { void SCULPT_orig_vert_data_init(SculptOrigVertData *data, Object *ob, PBVHNode *node); void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter *iter); +/* Face Sets */ +int SCULPT_vertex_face_set_get(SculptSession *ss, int index); +bool SCULPT_vertex_has_face_set(SculptSession *ss, int index, int face_set); +bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, int index); + /* Dynamic topology */ void sculpt_pbvh_clear(Object *ob); void sculpt_dyntopo_node_layers_add(struct SculptSession *ss); @@ -196,6 +204,13 @@ void SCULPT_floodfill_add_active(struct Sculpt *sd, struct SculptSession *ss, SculptFloodFill *flood, float radius); +void SCULPT_floodfill_add_initial_with_symmetry(struct Sculpt *sd, + struct Object *ob, + struct SculptSession *ss, + SculptFloodFill *flood, + int index, + float radius); +void sculpt_floodfill_add_initial(SculptFloodFill *flood, int index); void SCULPT_floodfill_execute( struct SculptSession *ss, SculptFloodFill *flood, @@ -441,6 +456,7 @@ typedef struct SculptThreadedTaskData { /*************** Brush testing declarations ****************/ typedef struct SculptBrushTest { float radius_squared; + float radius; float location[3]; float dist; int mirror_symmetry_pass; @@ -517,7 +533,7 @@ bool SCULPT_pbvh_calc_area_normal(const struct Brush *brush, * For descriptions of these settings, check the operator properties. */ -#define CLAY_STABILIZER_LEN 10 +#define SCULPT_CLAY_STABILIZER_LEN 10 typedef struct StrokeCache { /* Invariants */ @@ -608,7 +624,7 @@ typedef struct StrokeCache { /* Angle of the front tilting plane of the brush to simulate clay accumulation. */ float clay_thumb_front_angle; /* Stores pressure samples to get an stabilized strength and radius variation. */ - float clay_pressure_stabilizer[CLAY_STABILIZER_LEN]; + float clay_pressure_stabilizer[SCULPT_CLAY_STABILIZER_LEN]; int clay_pressure_stabilizer_index; /* Cloth brush */ @@ -618,6 +634,10 @@ typedef struct StrokeCache { float initial_normal[3]; float true_initial_normal[3]; + /* Surface Smooth Brush */ + /* Stores the displacement produced by the laplacian step of HC smooth. */ + float (*surface_smooth_laplacian_disp)[3]; + float vertex_rotation; /* amount to rotate the vertices when using rotate brush */ struct Dial *dial; @@ -650,6 +670,11 @@ typedef struct FilterCache { * achieve certain effects. */ int iteration_count; + /* Stores the displacement produced by the laplacian step of HC smooth. */ + float (*surface_smooth_laplacian_disp)[3]; + float surface_smooth_shape_preservation; + float surface_smooth_current_vertex; + /* unmasked nodes */ PBVHNode **nodes; int totnode; diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.c b/source/blender/editors/sculpt_paint/sculpt_pose.c index f1c884f9897..fde4a9d1d23 100644 --- a/source/blender/editors/sculpt_paint/sculpt_pose.c +++ b/source/blender/editors/sculpt_paint/sculpt_pose.c @@ -209,12 +209,11 @@ static void pose_brush_grow_factor_task_cb_ex(void *__restrict userdata, float max = 0.0f; /* Grow the factor. */ - sculpt_vertex_neighbors_iter_begin(ss, vd.index, ni) - { + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) { float vmask_f = data->prev_mask[ni.index]; max = MAX2(vmask_f, max); } - sculpt_vertex_neighbors_iter_end(ni); + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); /* Keep the count of the vertices that where added to the factors in this grow iteration. */ if (max > data->prev_mask[vd.index]) { @@ -352,9 +351,29 @@ typedef struct PoseFloodFillData { float *pose_factor; float pose_origin[3]; int tot_co; + + int current_face_set; + int next_face_set; + int prev_face_set; + int next_vertex; + + bool next_face_set_found; + + /* Store the visited face sets to avoid going back when calculating the chain. */ + GSet *visited_face_sets; + + /* In face sets origin mode, each vertex can only be assigned to one face set. */ + bool *is_weighted; + + bool is_first_iteration; + + /* Fallback origin. If we can't find any face set to continue, use the position of all vertices + * that have the current face set. */ + float fallback_origin[3]; + int fallback_count; } PoseFloodFillData; -static bool pose_floodfill_cb( +static bool pose_topology_floodfill_cb( SculptSession *ss, int UNUSED(from_v), int to_v, bool is_duplicate, void *userdata) { PoseFloodFillData *data = userdata; @@ -378,6 +397,100 @@ static bool pose_floodfill_cb( return false; } +static bool pose_face_sets_floodfill_cb( + SculptSession *ss, int UNUSED(from_v), int to_v, bool is_duplicate, void *userdata) +{ + PoseFloodFillData *data = userdata; + + const int index = to_v; + bool visit_next = false; + + const float *co = SCULPT_vertex_co_get(ss, index); + const bool symmetry_check = SCULPT_check_vertex_pivot_symmetry( + co, data->pose_initial_co, data->symm) && + !is_duplicate; + + /* First iteration. Continue expanding using topology until a vertex is outside the brush radius + * to determine the first face set. */ + if (data->current_face_set == SCULPT_FACE_SET_NONE) { + + data->pose_factor[index] = 1.0f; + data->is_weighted[index] = true; + + if (sculpt_pose_brush_is_vertex_inside_brush_radius( + co, data->pose_initial_co, data->radius, data->symm)) { + const int visited_face_set = SCULPT_vertex_face_set_get(ss, index); + BLI_gset_add(data->visited_face_sets, POINTER_FROM_INT(visited_face_set)); + } + else if (symmetry_check) { + data->current_face_set = SCULPT_vertex_face_set_get(ss, index); + BLI_gset_add(data->visited_face_sets, POINTER_FROM_INT(data->current_face_set)); + } + return true; + } + + /* We already have a current face set, so we can start checking the face sets of the vertices. */ + /* In the first iteration we need to check all face sets we already visited as the flood fill may + * still not be finished in some of them. */ + bool is_vertex_valid = false; + if (data->is_first_iteration) { + GSetIterator gs_iter; + GSET_ITER (gs_iter, data->visited_face_sets) { + const int visited_face_set = POINTER_AS_INT(BLI_gsetIterator_getKey(&gs_iter)); + is_vertex_valid |= SCULPT_vertex_has_face_set(ss, index, visited_face_set); + } + } + else { + is_vertex_valid = SCULPT_vertex_has_face_set(ss, index, data->current_face_set); + } + + if (is_vertex_valid) { + + if (!data->is_weighted[index]) { + data->pose_factor[index] = 1.0f; + data->is_weighted[index] = true; + visit_next = true; + } + + /* Fallback origin accumulation. */ + if (symmetry_check) { + add_v3_v3(data->fallback_origin, SCULPT_vertex_co_get(ss, index)); + data->fallback_count++; + } + + if (symmetry_check && !SCULPT_vertex_has_unique_face_set(ss, index)) { + + /* We only add coordinates for calculating the origin when it is possible to go from this + * vertex to another vertex in a valid face set for the next iteration. */ + bool count_as_boundary = false; + + SculptVertexNeighborIter ni; + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, index, ni) { + int next_face_set_candidate = SCULPT_vertex_face_set_get(ss, ni.index); + + /* Check if we can get a valid face set for the next iteration from this neighbor. */ + if (SCULPT_vertex_has_unique_face_set(ss, ni.index) && + !BLI_gset_haskey(data->visited_face_sets, POINTER_FROM_INT(next_face_set_candidate))) { + if (!data->next_face_set_found) { + data->next_face_set = next_face_set_candidate; + data->next_vertex = ni.index; + data->next_face_set_found = true; + } + count_as_boundary = true; + } + } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); + + /* Origin accumulation. */ + if (count_as_boundary) { + add_v3_v3(data->pose_origin, SCULPT_vertex_co_get(ss, index)); + data->tot_co++; + } + } + } + return visit_next; +} + /* Public functions. */ /* Calculate the pose origin and (Optionaly the pose factor) that is used when using the pose brush @@ -408,7 +521,7 @@ void SCULPT_pose_calc_pose_data(Sculpt *sd, }; zero_v3(fdata.pose_origin); copy_v3_v3(fdata.pose_initial_co, initial_location); - SCULPT_floodfill_execute(ss, &flood, pose_floodfill_cb, &fdata); + SCULPT_floodfill_execute(ss, &flood, pose_topology_floodfill_cb, &fdata); SCULPT_floodfill_free(&flood); if (fdata.tot_co > 0) { @@ -442,12 +555,11 @@ static void pose_brush_init_task_cb_ex(void *__restrict userdata, SculptVertexNeighborIter ni; float avg = 0.0f; int total = 0; - sculpt_vertex_neighbors_iter_begin(ss, vd.index, ni) - { + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) { avg += data->pose_factor[ni.index]; total++; } - sculpt_vertex_neighbors_iter_end(ni); + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); if (total > 0) { data->pose_factor[vd.index] = avg / total; @@ -456,12 +568,47 @@ static void pose_brush_init_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_end; } -SculptPoseIKChain *SCULPT_pose_ik_chain_init(Sculpt *sd, - Object *ob, - SculptSession *ss, - Brush *br, - const float initial_location[3], - const float radius) +/* Init the IK chain with empty weights. */ +static SculptPoseIKChain *pose_ik_chain_new(const int totsegments, const int totverts) +{ + SculptPoseIKChain *ik_chain = MEM_callocN(sizeof(SculptPoseIKChain), "Pose IK Chain"); + ik_chain->tot_segments = totsegments; + ik_chain->segments = MEM_callocN(totsegments * sizeof(SculptPoseIKChainSegment), + "Pose IK Chain Segments"); + for (int i = 0; i < totsegments; i++) { + ik_chain->segments[i].weights = MEM_callocN(totverts * sizeof(float), "Pose IK weights"); + } + return ik_chain; +} + +/* Init the origin/head pairs of all the segments from the calculated origins. */ +static void pose_ik_chain_origin_heads_init(SculptPoseIKChain *ik_chain, + const float initial_location[3]) +{ + float origin[3]; + float head[3]; + for (int i = 0; i < ik_chain->tot_segments; i++) { + if (i == 0) { + copy_v3_v3(head, initial_location); + copy_v3_v3(origin, ik_chain->segments[i].orig); + } + else { + copy_v3_v3(head, ik_chain->segments[i - 1].orig); + copy_v3_v3(origin, ik_chain->segments[i].orig); + } + copy_v3_v3(ik_chain->segments[i].orig, origin); + copy_v3_v3(ik_chain->segments[i].initial_orig, origin); + copy_v3_v3(ik_chain->segments[i].initial_head, head); + ik_chain->segments[i].len = len_v3v3(head, origin); + } +} + +static SculptPoseIKChain *pose_ik_chain_init_topology(Sculpt *sd, + Object *ob, + SculptSession *ss, + Brush *br, + const float initial_location[3], + const float radius) { const float chain_segment_len = radius * (1.0f + br->pose_offset); @@ -482,14 +629,7 @@ SculptPoseIKChain *SCULPT_pose_ik_chain_init(Sculpt *sd, pose_factor_grow[nearest_vertex_index] = 1.0f; - /* Init the IK chain with empty weights. */ - SculptPoseIKChain *ik_chain = MEM_callocN(sizeof(SculptPoseIKChain), "Pose IK Chain"); - ik_chain->tot_segments = br->pose_ik_segments; - ik_chain->segments = MEM_callocN(ik_chain->tot_segments * sizeof(SculptPoseIKChainSegment), - "Pose IK Chain Segments"); - for (int i = 0; i < br->pose_ik_segments; i++) { - ik_chain->segments[i].weights = MEM_callocN(totvert * sizeof(float), "Pose IK weights"); - } + SculptPoseIKChain *ik_chain = pose_ik_chain_new(br->pose_ik_segments, totvert); /* Calculate the first segment in the chain using the brush radius and the pose origin offset. */ copy_v3_v3(next_chain_segment_target, initial_location); @@ -534,30 +674,102 @@ SculptPoseIKChain *SCULPT_pose_ik_chain_init(Sculpt *sd, } } - /* Init the origin/head pairs of all the segments from the calculated origins. */ - float origin[3]; - float head[3]; - for (int i = 0; i < ik_chain->tot_segments; i++) { - if (i == 0) { - copy_v3_v3(head, initial_location); - copy_v3_v3(origin, ik_chain->segments[i].orig); + pose_ik_chain_origin_heads_init(ik_chain, initial_location); + + MEM_freeN(pose_factor_grow); + MEM_freeN(pose_factor_grow_prev); + + return ik_chain; +} + +static SculptPoseIKChain *pose_ik_chain_init_face_sets( + Sculpt *sd, Object *ob, SculptSession *ss, Brush *br, const float radius) +{ + + int totvert = SCULPT_vertex_count_get(ss); + + SculptPoseIKChain *ik_chain = pose_ik_chain_new(br->pose_ik_segments, totvert); + + GSet *visited_face_sets = BLI_gset_int_new_ex("visited_face_sets", ik_chain->tot_segments); + + bool *is_weighted = MEM_callocN(sizeof(bool) * totvert, "weighted"); + + int current_face_set = SCULPT_FACE_SET_NONE; + int prev_face_set = SCULPT_FACE_SET_NONE; + + int current_vertex = SCULPT_active_vertex_get(ss); + + for (int s = 0; s < ik_chain->tot_segments; s++) { + + SculptFloodFill flood; + SCULPT_floodfill_init(ss, &flood); + SCULPT_floodfill_add_initial_with_symmetry(sd, ob, ss, &flood, current_vertex, FLT_MAX); + + BLI_gset_add(visited_face_sets, POINTER_FROM_INT(current_face_set)); + + PoseFloodFillData fdata = { + .radius = radius, + .symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL, + .pose_factor = ik_chain->segments[s].weights, + .tot_co = 0, + .fallback_count = 0, + .current_face_set = current_face_set, + .prev_face_set = prev_face_set, + .visited_face_sets = visited_face_sets, + .is_weighted = is_weighted, + .next_face_set_found = false, + .is_first_iteration = s == 0, + }; + zero_v3(fdata.pose_origin); + zero_v3(fdata.fallback_origin); + copy_v3_v3(fdata.pose_initial_co, SCULPT_vertex_co_get(ss, current_vertex)); + SCULPT_floodfill_execute(ss, &flood, pose_face_sets_floodfill_cb, &fdata); + SCULPT_floodfill_free(&flood); + + if (fdata.tot_co > 0) { + mul_v3_fl(fdata.pose_origin, 1.0f / (float)fdata.tot_co); + copy_v3_v3(ik_chain->segments[s].orig, fdata.pose_origin); + } + else if (fdata.fallback_count > 0) { + mul_v3_fl(fdata.fallback_origin, 1.0f / (float)fdata.fallback_count); + copy_v3_v3(ik_chain->segments[s].orig, fdata.fallback_origin); } else { - copy_v3_v3(head, ik_chain->segments[i - 1].orig); - copy_v3_v3(origin, ik_chain->segments[i].orig); + zero_v3(ik_chain->segments[s].orig); } - copy_v3_v3(ik_chain->segments[i].orig, origin); - copy_v3_v3(ik_chain->segments[i].initial_orig, origin); - copy_v3_v3(ik_chain->segments[i].initial_head, head); - ik_chain->segments[i].len = len_v3v3(head, origin); + + prev_face_set = fdata.current_face_set; + current_face_set = fdata.next_face_set; + current_vertex = fdata.next_vertex; } - MEM_freeN(pose_factor_grow); - MEM_freeN(pose_factor_grow_prev); + BLI_gset_free(visited_face_sets, NULL); + + pose_ik_chain_origin_heads_init(ik_chain, SCULPT_active_vertex_co_get(ss)); + + MEM_SAFE_FREE(is_weighted); return ik_chain; } +SculptPoseIKChain *SCULPT_pose_ik_chain_init(Sculpt *sd, + Object *ob, + SculptSession *ss, + Brush *br, + const float initial_location[3], + const float radius) +{ + switch (br->pose_origin_type) { + case BRUSH_POSE_ORIGIN_TOPOLOGY: + return pose_ik_chain_init_topology(sd, ob, ss, br, initial_location, radius); + break; + case BRUSH_POSE_ORIGIN_FACE_SETS: + return pose_ik_chain_init_face_sets(sd, ob, ss, br, radius); + break; + } + return NULL; +} + void SCULPT_pose_brush_init(Sculpt *sd, Object *ob, SculptSession *ss, Brush *br) { PBVHNode **nodes; diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h index b66f7605f41..4dc8d367f2b 100644 --- a/source/blender/editors/space_clip/clip_intern.h +++ b/source/blender/editors/space_clip/clip_intern.h @@ -178,7 +178,7 @@ void clip_draw_sfra_efra(struct View2D *v2d, struct Scene *scene); /* tracking_ops.c */ struct MovieTrackingTrack *tracking_marker_check_slide( - struct bContext *C, const struct wmEvent *event, int *area_r, int *action_r, int *corner_r); + struct bContext *C, const struct wmEvent *event, int *r_area, int *r_action, int *r_corner); void CLIP_OT_add_marker(struct wmOperatorType *ot); void CLIP_OT_add_marker_at_click(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index efc8c3bb7dd..4e5c6513695 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -1315,8 +1315,8 @@ typedef struct ProxyThread { static unsigned char *proxy_thread_next_frame(ProxyQueue *queue, MovieClip *clip, - size_t *size_r, - int *cfra_r) + size_t *r_size, + int *r_cfra) { unsigned char *mem = NULL; @@ -1353,8 +1353,8 @@ static unsigned char *proxy_thread_next_frame(ProxyQueue *queue, return NULL; } - *size_r = size; - *cfra_r = queue->cfra; + *r_size = size; + *r_cfra = queue->cfra; queue->cfra++; close(file); diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index a273487eee9..4b9c872ffce 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -605,7 +605,7 @@ static int clip_context(const bContext *C, const char *member, bContextDataResul static bool clip_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), - const char **UNUSED(tooltip)) + const char **UNUSED(r_tooltip)) { if (drag->type == WM_DRAG_PATH) { /* rule might not work? */ diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index f88f6113b54..739701b5595 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -544,7 +544,7 @@ static bool slide_check_corners(float (*corners)[2]) } MovieTrackingTrack *tracking_marker_check_slide( - bContext *C, const wmEvent *event, int *area_r, int *action_r, int *corner_r) + bContext *C, const wmEvent *event, int *r_area, int *r_action, int *r_corner) { const float distance_clip_squared = 12.0f * 12.0f; SpaceClip *sc = CTX_wm_space_clip(C); @@ -657,14 +657,14 @@ MovieTrackingTrack *tracking_marker_check_slide( } if (global_min_distance_squared < distance_clip_squared / sc->zoom) { - if (area_r) { - *area_r = min_area; + if (r_area) { + *r_area = min_area; } - if (action_r) { - *action_r = min_action; + if (r_action) { + *r_action = min_action; } - if (corner_r) { - *corner_r = min_corner; + if (r_corner) { + *r_corner = min_corner; } return min_track; } diff --git a/source/blender/editors/space_clip/tracking_ops_plane.c b/source/blender/editors/space_clip/tracking_ops_plane.c index 0cf0e85929c..3c5646911a3 100644 --- a/source/blender/editors/space_clip/tracking_ops_plane.c +++ b/source/blender/editors/space_clip/tracking_ops_plane.c @@ -122,7 +122,7 @@ static float mouse_to_plane_slide_zone_distance_squared(const float co[2], static MovieTrackingPlaneTrack *tracking_plane_marker_check_slide(bContext *C, const wmEvent *event, - int *corner_r) + int *r_corner) { const float distance_clip_squared = 12.0f * 12.0f; SpaceClip *sc = CTX_wm_space_clip(C); @@ -162,8 +162,8 @@ static MovieTrackingPlaneTrack *tracking_plane_marker_check_slide(bContext *C, } if (min_distance_squared < distance_clip_squared / sc->zoom) { - if (corner_r != NULL) { - *corner_r = min_corner; + if (r_corner != NULL) { + *r_corner = min_corner; } return min_plane_track; } diff --git a/source/blender/editors/space_clip/tracking_ops_track.c b/source/blender/editors/space_clip/tracking_ops_track.c index c14895f8483..05623347366 100644 --- a/source/blender/editors/space_clip/tracking_ops_track.c +++ b/source/blender/editors/space_clip/tracking_ops_track.c @@ -86,7 +86,7 @@ static int track_count_markers(SpaceClip *sc, MovieClip *clip, int framenr) return tot; } -static void track_init_markers(SpaceClip *sc, MovieClip *clip, int framenr, int *frames_limit_r) +static void track_init_markers(SpaceClip *sc, MovieClip *clip, int framenr, int *r_frames_limit) { ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking); int frames_limit = 0; @@ -109,7 +109,7 @@ static void track_init_markers(SpaceClip *sc, MovieClip *clip, int framenr, int } } } - *frames_limit_r = frames_limit; + *r_frames_limit = frames_limit; } static bool track_markers_check_direction(int backwards, int curfra, int efra) diff --git a/source/blender/editors/space_clip/tracking_select.c b/source/blender/editors/space_clip/tracking_select.c index 2166cff4883..67c453825f7 100644 --- a/source/blender/editors/space_clip/tracking_select.c +++ b/source/blender/editors/space_clip/tracking_select.c @@ -52,7 +52,7 @@ #include "clip_intern.h" /* own include */ #include "tracking_ops_intern.h" /* own include */ -static float dist_to_crns(float co[2], float pos[2], float crns[4][2]); +static float dist_to_crns(const float co[2], const float pos[2], const float crns[4][2]); /********************** mouse select operator *********************/ @@ -70,8 +70,12 @@ static int mouse_on_side( return (co[0] >= x1 - epsx && co[0] <= x2 + epsx) && (co[1] >= y1 - epsy && co[1] <= y2 + epsy); } -static int mouse_on_rect( - const float co[2], float pos[2], float min[2], float max[2], float epsx, float epsy) +static int mouse_on_rect(const float co[2], + const float pos[2], + const float min[2], + const float max[2], + float epsx, + float epsy) { return mouse_on_side( co, pos[0] + min[0], pos[1] + min[1], pos[0] + max[0], pos[1] + min[1], epsx, epsy) || @@ -83,14 +87,15 @@ static int mouse_on_rect( co, pos[0] + max[0], pos[1] + min[1], pos[0] + max[0], pos[1] + max[1], epsx, epsy); } -static int mouse_on_crns(float co[2], float pos[2], float crns[4][2], float epsx, float epsy) +static int mouse_on_crns( + const float co[2], const float pos[2], const float crns[4][2], float epsx, float epsy) { float dist = dist_to_crns(co, pos, crns); return dist < max_ff(epsx, epsy); } -static int track_mouse_area(const bContext *C, float co[2], MovieTrackingTrack *track) +static int track_mouse_area(const bContext *C, const float co[2], MovieTrackingTrack *track) { SpaceClip *sc = CTX_wm_space_clip(C); int framenr = ED_space_clip_get_clip_frame_number(sc); @@ -142,7 +147,10 @@ static int track_mouse_area(const bContext *C, float co[2], MovieTrackingTrack * return TRACK_AREA_NONE; } -static float dist_to_rect(float co[2], float pos[2], float min[2], float max[2]) +static float dist_to_rect(const float co[2], + const float pos[2], + const float min[2], + const float max[2]) { float d1, d2, d3, d4; float p[2] = {co[0] - pos[0], co[1] - pos[1]}; @@ -158,7 +166,7 @@ static float dist_to_rect(float co[2], float pos[2], float min[2], float max[2]) } /* Distance to quad defined by it's corners, corners are relative to pos */ -static float dist_to_crns(float co[2], float pos[2], float crns[4][2]) +static float dist_to_crns(const float co[2], const float pos[2], const float crns[4][2]) { float d1, d2, d3, d4; float p[2] = {co[0] - pos[0], co[1] - pos[1]}; @@ -174,7 +182,7 @@ static float dist_to_crns(float co[2], float pos[2], float crns[4][2]) } /* Same as above, but all the coordinates are absolute */ -static float dist_to_crns_abs(float co[2], float corners[4][2]) +static float dist_to_crns_abs(const float co[2], const float corners[4][2]) { float d1, d2, d3, d4; const float *v1 = corners[0], *v2 = corners[1]; @@ -190,8 +198,8 @@ static float dist_to_crns_abs(float co[2], float corners[4][2]) static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, ListBase *tracksbase, - float co[2], - float *distance_r) + const float co[2], + float *r_distance) { MovieTrackingTrack *track = NULL, *cur; float mindist = 0.0f; @@ -231,15 +239,15 @@ static MovieTrackingTrack *find_nearest_track(SpaceClip *sc, cur = cur->next; } - *distance_r = mindist; + *r_distance = mindist; return track; } static MovieTrackingPlaneTrack *find_nearest_plane_track(SpaceClip *sc, ListBase *plane_tracks_base, - float co[2], - float *distance_r) + const float co[2], + float *r_distance) { MovieTrackingPlaneTrack *plane_track = NULL, *current_plane_track; float min_distance = 0.0f; @@ -259,7 +267,7 @@ static MovieTrackingPlaneTrack *find_nearest_plane_track(SpaceClip *sc, } } - *distance_r = min_distance; + *r_distance = min_distance; return plane_track; } @@ -281,7 +289,7 @@ void ed_tracking_deselect_all_plane_tracks(ListBase *plane_tracks_base) } } -static int mouse_select(bContext *C, float co[2], const bool extend, const bool deselect_all) +static int mouse_select(bContext *C, const float co[2], const bool extend, const bool deselect_all) { SpaceClip *sc = CTX_wm_space_clip(C); MovieClip *clip = ED_space_clip_get_clip(sc); diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h index 6ef35132087..b7e8d35ffee 100644 --- a/source/blender/editors/space_file/file_intern.h +++ b/source/blender/editors/space_file/file_intern.h @@ -75,14 +75,6 @@ void FILE_OT_smoothscroll(struct wmOperatorType *ot); void FILE_OT_filepath_drop(struct wmOperatorType *ot); void FILE_OT_start_filter(struct wmOperatorType *ot); -int file_exec(bContext *C, struct wmOperator *exec_op); -int file_cancel_exec(bContext *C, struct wmOperator *unused); -int file_parent_exec(bContext *C, struct wmOperator *unused); -int file_previous_exec(bContext *C, struct wmOperator *unused); -int file_next_exec(bContext *C, struct wmOperator *unused); -int file_directory_new_exec(bContext *C, struct wmOperator *unused); -int file_delete_exec(bContext *C, struct wmOperator *unused); - void file_directory_enter_handle(bContext *C, void *arg_unused, void *arg_but); void file_filename_enter_handle(bContext *C, void *arg_unused, void *arg_but); diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index c17ca31a7df..5258892d55d 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -68,7 +68,10 @@ #include <stdlib.h> #include <string.h> -/* ---------- FILE SELECTION ------------ */ +/* -------------------------------------------------------------------- */ +/** \name File Selection Utilities + * \{ */ + static FileSelection find_file_mouse_rect(SpaceFile *sfile, ARegion *region, const rcti *rect_region) @@ -344,6 +347,12 @@ static FileSelect file_select( return retval; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Box Select Operator + * \{ */ + static int file_box_select_find_last_selected(SpaceFile *sfile, ARegion *region, const FileSelection *sel, @@ -484,6 +493,12 @@ void FILE_OT_select_box(wmOperatorType *ot) WM_operator_properties_select_operation_simple(ot); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Pick Operator + * \{ */ + static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ARegion *region = CTX_wm_region(C); @@ -577,6 +592,12 @@ void FILE_OT_select(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Walk Operator + * \{ */ + /** * \returns true if selection has changed */ @@ -822,6 +843,12 @@ void FILE_OT_select_walk(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select All Operator + * \{ */ + static int file_select_all_exec(bContext *C, wmOperator *op) { ScrArea *sa = CTX_wm_area(C); @@ -893,7 +920,11 @@ void FILE_OT_select_all(wmOperatorType *ot) WM_operator_properties_select_all(ot); } -/* ---------- BOOKMARKS ----------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Bookmark Operator + * \{ */ /* Note we could get rid of this one, but it's used by some addon so... * Does not hurt keeping it around for now. */ @@ -936,6 +967,12 @@ void FILE_OT_select_bookmark(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Add Bookmark Operator + * \{ */ + static int bookmark_add_exec(bContext *C, wmOperator *UNUSED(op)) { ScrArea *sa = CTX_wm_area(C); @@ -972,6 +1009,12 @@ void FILE_OT_bookmark_add(wmOperatorType *ot) ot->poll = ED_operator_file_active; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete Bookmark Operator + * \{ */ + static int bookmark_delete_exec(bContext *C, wmOperator *op) { ScrArea *sa = CTX_wm_area(C); @@ -1024,6 +1067,12 @@ void FILE_OT_bookmark_delete(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Cleanup Bookmark Operator + * \{ */ + static int bookmark_cleanup_exec(bContext *C, wmOperator *UNUSED(op)) { ScrArea *sa = CTX_wm_area(C); @@ -1074,6 +1123,12 @@ void FILE_OT_bookmark_cleanup(wmOperatorType *ot) /* properties */ } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Reorder Bookmark Operator + * \{ */ + enum { FILE_BOOKMARK_MOVE_TOP = -2, FILE_BOOKMARK_MOVE_UP = -1, @@ -1165,6 +1220,12 @@ void FILE_OT_bookmark_move(wmOperatorType *ot) "Direction to move the active bookmark towards"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Reset Recent Blend Files Operator + * \{ */ + static int reset_recent_exec(bContext *C, wmOperator *UNUSED(op)) { ScrArea *sa = CTX_wm_area(C); @@ -1196,6 +1257,12 @@ void FILE_OT_reset_recent(wmOperatorType *ot) ot->poll = ED_operator_file_active; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Highlight File Operator + * \{ */ + int file_highlight_set(SpaceFile *sfile, ARegion *region, int mx, int my) { View2D *v2d = ®ion->v2d; @@ -1263,6 +1330,12 @@ void FILE_OT_highlight(struct wmOperatorType *ot) ot->poll = ED_operator_file_active; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Sort from Column Operator + * \{ */ + static int file_column_sort_ui_context_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) @@ -1310,18 +1383,11 @@ void FILE_OT_sort_column_ui_context(wmOperatorType *ot) ot->flag = OPTYPE_INTERNAL; } -int file_cancel_exec(bContext *C, wmOperator *UNUSED(unused)) -{ - wmWindowManager *wm = CTX_wm_manager(C); - SpaceFile *sfile = CTX_wm_space_file(C); - wmOperator *op = sfile->op; - - sfile->op = NULL; - - WM_event_fileselect_event(wm, op, EVT_FILESELECT_CANCEL); +/** \} */ - return OPERATOR_FINISHED; -} +/* -------------------------------------------------------------------- */ +/** \name Cancel File Selector Operator + * \{ */ static bool file_operator_poll(bContext *C) { @@ -1335,6 +1401,19 @@ static bool file_operator_poll(bContext *C) return poll; } +static int file_cancel_exec(bContext *C, wmOperator *UNUSED(unused)) +{ + wmWindowManager *wm = CTX_wm_manager(C); + SpaceFile *sfile = CTX_wm_space_file(C); + wmOperator *op = sfile->op; + + sfile->op = NULL; + + WM_event_fileselect_event(wm, op, EVT_FILESELECT_CANCEL); + + return OPERATOR_FINISHED; +} + void FILE_OT_cancel(struct wmOperatorType *ot) { /* identifiers */ @@ -1347,6 +1426,12 @@ void FILE_OT_cancel(struct wmOperatorType *ot) ot->poll = file_operator_poll; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Operator Utilities + * \{ */ + void file_sfile_to_operator_ex(bContext *C, wmOperator *op, SpaceFile *sfile, char *filepath) { Main *bmain = CTX_data_main(C); @@ -1521,7 +1606,13 @@ bool file_draw_check_exists(SpaceFile *sfile) return false; } -int file_exec(bContext *C, wmOperator *exec_op) +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Execute File Window Operator + * \{ */ + +static int file_exec(bContext *C, wmOperator *exec_op) { Main *bmain = CTX_data_main(C); wmWindowManager *wm = CTX_wm_manager(C); @@ -1543,7 +1634,9 @@ int file_exec(bContext *C, wmOperator *exec_op) BLI_path_append(sfile->params->dir, sizeof(sfile->params->dir) - 1, file->relpath); BLI_add_slash(sfile->params->dir); } - + if (file->redirection_path) { + STRNCPY(sfile->params->dir, file->redirection_path); + } ED_file_change_dir(C); } /* opening file - sends events now, so things get handled on windowqueue level */ @@ -1612,7 +1705,50 @@ void FILE_OT_execute(struct wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -int file_parent_exec(bContext *C, wmOperator *UNUSED(unused)) +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Refresh File List Operator + * \{ */ + +static int file_refresh_exec(bContext *C, wmOperator *UNUSED(unused)) +{ + wmWindowManager *wm = CTX_wm_manager(C); + SpaceFile *sfile = CTX_wm_space_file(C); + struct FSMenu *fsmenu = ED_fsmenu_get(); + + ED_fileselect_clear(wm, CTX_data_scene(C), sfile); + + /* refresh system directory menu */ + fsmenu_refresh_system_category(fsmenu); + + /* Update bookmarks 'valid' state. */ + fsmenu_refresh_bookmarks_status(wm, fsmenu); + + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); + + return OPERATOR_FINISHED; +} + +void FILE_OT_refresh(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Refresh Filelist"; + ot->description = "Refresh the file list"; + ot->idname = "FILE_OT_refresh"; + + /* api callbacks */ + ot->exec = file_refresh_exec; + ot->poll = ED_operator_file_active; /* <- important, handler is on window level */ +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Navigate Parent Operator + * \{ */ + +static int file_parent_exec(bContext *C, wmOperator *UNUSED(unused)) { Main *bmain = CTX_data_main(C); SpaceFile *sfile = CTX_wm_space_file(C); @@ -1645,20 +1781,27 @@ void FILE_OT_parent(struct wmOperatorType *ot) ot->poll = ED_operator_file_active; /* <- important, handler is on window level */ } -static int file_refresh_exec(bContext *C, wmOperator *UNUSED(unused)) +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Navigate Previous Operator + * \{ */ + +static int file_previous_exec(bContext *C, wmOperator *UNUSED(op)) { - wmWindowManager *wm = CTX_wm_manager(C); SpaceFile *sfile = CTX_wm_space_file(C); - struct FSMenu *fsmenu = ED_fsmenu_get(); - ED_fileselect_clear(wm, CTX_data_scene(C), sfile); - - /* refresh system directory menu */ - fsmenu_refresh_system_category(fsmenu); + if (sfile->params) { + if (!sfile->folders_next) { + sfile->folders_next = folderlist_new(); + } - /* Update bookmarks 'valid' state. */ - fsmenu_refresh_bookmarks_status(wm, fsmenu); + folderlist_pushdir(sfile->folders_next, sfile->params->dir); + folderlist_popdir(sfile->folders_prev, sfile->params->dir); + folderlist_pushdir(sfile->folders_next, sfile->params->dir); + ED_file_change_dir(C); + } WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); return OPERATOR_FINISHED; @@ -1676,18 +1819,25 @@ void FILE_OT_previous(struct wmOperatorType *ot) ot->poll = ED_operator_file_active; /* <- important, handler is on window level */ } -int file_previous_exec(bContext *C, wmOperator *UNUSED(unused)) +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Navigate Next Operator + * \{ */ + +static int file_next_exec(bContext *C, wmOperator *UNUSED(unused)) { SpaceFile *sfile = CTX_wm_space_file(C); - if (sfile->params) { if (!sfile->folders_next) { sfile->folders_next = folderlist_new(); } - folderlist_pushdir(sfile->folders_next, sfile->params->dir); - folderlist_popdir(sfile->folders_prev, sfile->params->dir); - folderlist_pushdir(sfile->folders_next, sfile->params->dir); + folderlist_pushdir(sfile->folders_prev, sfile->params->dir); + folderlist_popdir(sfile->folders_next, sfile->params->dir); + + // update folders_prev so we can check for it in folderlist_clear_next() + folderlist_pushdir(sfile->folders_prev, sfile->params->dir); ED_file_change_dir(C); } @@ -1708,26 +1858,11 @@ void FILE_OT_next(struct wmOperatorType *ot) ot->poll = ED_operator_file_active; /* <- important, handler is on window level */ } -int file_next_exec(bContext *C, wmOperator *UNUSED(unused)) -{ - SpaceFile *sfile = CTX_wm_space_file(C); - if (sfile->params) { - if (!sfile->folders_next) { - sfile->folders_next = folderlist_new(); - } - - folderlist_pushdir(sfile->folders_prev, sfile->params->dir); - folderlist_popdir(sfile->folders_next, sfile->params->dir); - - // update folders_prev so we can check for it in folderlist_clear_next() - folderlist_pushdir(sfile->folders_prev, sfile->params->dir); - - ED_file_change_dir(C); - } - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); +/** \} */ - return OPERATOR_FINISHED; -} +/* -------------------------------------------------------------------- */ +/** \name Smooth Scroll Operator + * \{ */ /* only meant for timer usage */ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) @@ -1916,6 +2051,12 @@ void FILE_OT_smoothscroll(wmOperatorType *ot) ot->poll = ED_operator_file_active; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name File Selector Drop Operator + * \{ */ + static int filepath_drop_exec(bContext *C, wmOperator *op) { SpaceFile *sfile = CTX_wm_space_file(C); @@ -1954,6 +2095,12 @@ void FILE_OT_filepath_drop(wmOperatorType *ot) RNA_def_string_file_path(ot->srna, "filepath", "Path", FILE_MAX, "", ""); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name New Directory Operator + * \{ */ + /** * Create a new, non-existing folder name, returns 1 if successful, 0 if name couldn't be created. * The actual name is returned in 'name', 'folder' contains the complete path, @@ -1978,7 +2125,7 @@ static int new_folder_path(const char *parent, char *folder, char *name) return (len < FILE_MAXFILE); } -int file_directory_new_exec(bContext *C, wmOperator *op) +static int file_directory_new_exec(bContext *C, wmOperator *op) { char name[FILE_MAXFILE]; char path[FILE_MAX]; @@ -2085,6 +2232,12 @@ void FILE_OT_directory_new(struct wmOperatorType *ot) WM_operator_properties_confirm_or_exec(ot); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Refresh File List Operator + * \{ */ + /* TODO This should go to BLI_path_utils. */ static void file_expand_directory(bContext *C) { @@ -2284,17 +2437,11 @@ void file_filename_enter_handle(bContext *C, void *UNUSED(arg_unused), void *arg } } -void FILE_OT_refresh(struct wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Refresh Filelist"; - ot->description = "Refresh the file list"; - ot->idname = "FILE_OT_refresh"; +/** \} */ - /* api callbacks */ - ot->exec = file_refresh_exec; - ot->poll = ED_operator_file_active; /* <- important, handler is on window level */ -} +/* -------------------------------------------------------------------- */ +/** \name Toggle Show Hidden Files Operator + * \{ */ static int file_hidedot_exec(bContext *C, wmOperator *UNUSED(unused)) { @@ -2322,6 +2469,12 @@ void FILE_OT_hidedot(struct wmOperatorType *ot) ot->poll = ED_operator_file_active; /* <- important, handler is on window level */ } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Increment Filename Operator + * \{ */ + static bool file_filenum_poll(bContext *C) { SpaceFile *sfile = CTX_wm_space_file(C); @@ -2396,6 +2549,12 @@ void FILE_OT_filenum(struct wmOperatorType *ot) RNA_def_int(ot->srna, "increment", 1, -100, 100, "Increment", "", -100, 100); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Rename File/Directory Operator + * \{ */ + static void file_rename_state_activate(SpaceFile *sfile, int file_idx, bool require_selected) { const int numfiles = filelist_files_ensure(sfile->files); @@ -2454,6 +2613,12 @@ void FILE_OT_rename(struct wmOperatorType *ot) ot->poll = ED_operator_file_active; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete File Operator + * \{ */ + static bool file_delete_poll(bContext *C) { bool poll = ED_operator_file_active(C); @@ -2484,7 +2649,7 @@ static bool file_delete_poll(bContext *C) return poll; } -int file_delete_exec(bContext *C, wmOperator *op) +static int file_delete_exec(bContext *C, wmOperator *op) { wmWindowManager *wm = CTX_wm_manager(C); SpaceFile *sfile = CTX_wm_space_file(C); @@ -2535,6 +2700,12 @@ void FILE_OT_delete(struct wmOperatorType *ot) ot->poll = file_delete_poll; /* <- important, handler is on window level */ } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Enter Filter Text Operator + * \{ */ + static int file_start_filter_exec(bContext *C, wmOperator *UNUSED(op)) { ScrArea *sa = CTX_wm_area(C); @@ -2557,6 +2728,12 @@ void FILE_OT_start_filter(struct wmOperatorType *ot) ot->poll = ED_operator_file_active; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Macro Operators + * \{ */ + void ED_operatormacros_file(void) { // wmOperatorType *ot; @@ -2564,3 +2741,5 @@ void ED_operatormacros_file(void) /* future macros */ } + +/** \} */ diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index cb062cc212a..dec38501d38 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -210,12 +210,13 @@ typedef struct FileListInternEntry { int blentype; char *relpath; + /** Optional argument for shortcuts, aliases etc. */ + char *redirection_path; /** not strictly needed, but used during sorting, avoids to have to recompute it there... */ char *name; /** Defined in BLI_fileops.h */ eFileAttributes attributes; - BLI_stat_t st; } FileListInternEntry; @@ -961,12 +962,12 @@ ImBuf *filelist_getimage(struct FileList *filelist, const int index) return file->image; } -static ImBuf *filelist_geticon_image_ex(const unsigned int typeflag, const char *relpath) +static ImBuf *filelist_geticon_image_ex(FileDirEntry *file) { ImBuf *ibuf = NULL; - if (typeflag & FILE_TYPE_DIR) { - if (FILENAME_IS_PARENT(relpath)) { + if (file->typeflag & FILE_TYPE_DIR) { + if (FILENAME_IS_PARENT(file->relpath)) { ibuf = gSpecialFileImages[SPECIAL_IMG_PARENT]; } else { @@ -983,8 +984,7 @@ static ImBuf *filelist_geticon_image_ex(const unsigned int typeflag, const char ImBuf *filelist_geticon_image(struct FileList *filelist, const int index) { FileDirEntry *file = filelist_geticon_get_file(filelist, index); - - return filelist_geticon_image_ex(file->typeflag, file->relpath); + return filelist_geticon_image_ex(file); } static int filelist_geticon_ex(FileDirEntry *file, @@ -1170,6 +1170,9 @@ static void filelist_entry_clear(FileDirEntry *entry) if (entry->relpath) { MEM_freeN(entry->relpath); } + if (entry->redirection_path) { + MEM_freeN(entry->redirection_path); + } if (entry->image) { IMB_freeImBuf(entry->image); } @@ -1239,6 +1242,9 @@ static void filelist_intern_entry_free(FileListInternEntry *entry) if (entry->relpath) { MEM_freeN(entry->relpath); } + if (entry->redirection_path) { + MEM_freeN(entry->redirection_path); + } if (entry->name) { MEM_freeN(entry->name); } @@ -1690,6 +1696,9 @@ static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int in ret->blentype = entry->blentype; ret->typeflag = entry->typeflag; ret->attributes = entry->attributes; + if (entry->redirection_path) { + ret->redirection_path = BLI_strdup(entry->redirection_path); + } BLI_addtail(&cache->cached_entries, ret); return ret; } @@ -2436,9 +2445,9 @@ void filelist_entry_parent_select_set(FileList *filelist, } /* WARNING! dir must be FILE_MAX_LIBEXTRA long! */ -bool filelist_islibrary(struct FileList *filelist, char *dir, char **group) +bool filelist_islibrary(struct FileList *filelist, char *dir, char **r_group) { - return BLO_library_path_explode(filelist->filelist.root, dir, group, NULL); + return BLO_library_path_explode(filelist->filelist.root, dir, r_group, NULL); } static int groupname_to_code(const char *group) @@ -2523,6 +2532,16 @@ static int filelist_readjob_list_dir(const char *root, /* Set file attributes. */ entry->attributes = BLI_file_attributes(path); + if (entry->attributes & FILE_ATTR_ALIAS) { + entry->redirection_path = MEM_callocN(FILE_MAXDIR, __func__); + if (BLI_file_alias_target(entry->redirection_path, path)) { + if (BLI_is_dir(entry->redirection_path)) { + entry->typeflag = FILE_TYPE_DIR; + } + else + entry->typeflag = ED_path_extension_type(entry->redirection_path); + } + } #ifndef WIN32 /* Set linux-style dot files hidden too. */ diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h index e39594bf1da..e90a8659417 100644 --- a/source/blender/editors/space_file/filelist.h +++ b/source/blender/editors/space_file/filelist.h @@ -125,7 +125,7 @@ void filelist_entry_parent_select_set(struct FileList *filelist, void filelist_setrecursion(struct FileList *filelist, const int recursion_level); struct BlendHandle *filelist_lib(struct FileList *filelist); -bool filelist_islibrary(struct FileList *filelist, char *dir, char **group); +bool filelist_islibrary(struct FileList *filelist, char *dir, char **r_group); void filelist_freelib(struct FileList *filelist); void filelist_readjob_start(struct FileList *filelist, const struct bContext *C); diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index c3159d38e7e..1574dbbeb76 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -663,7 +663,7 @@ static void file_ui_region_listener(wmWindow *UNUSED(win), static bool filepath_drop_poll(bContext *C, wmDrag *drag, const wmEvent *UNUSED(event), - const char **UNUSED(tooltip)) + const char **UNUSED(r_tooltip)) { if (drag->type == WM_DRAG_PATH) { SpaceFile *sfile = CTX_wm_space_file(C); diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c index 8da67effc94..7f911113b7c 100644 --- a/source/blender/editors/space_image/image_edit.c +++ b/source/blender/editors/space_image/image_edit.c @@ -212,7 +212,7 @@ bool ED_space_image_has_buffer(SpaceImage *sima) return has_buffer; } -void ED_space_image_get_size(SpaceImage *sima, int *width, int *height) +void ED_space_image_get_size(SpaceImage *sima, int *r_width, int *r_height) { Scene *scene = sima->iuser.scene; ImBuf *ibuf; @@ -222,94 +222,94 @@ void ED_space_image_get_size(SpaceImage *sima, int *width, int *height) ibuf = ED_space_image_acquire_buffer(sima, &lock, 0); if (ibuf && ibuf->x > 0 && ibuf->y > 0) { - *width = ibuf->x; - *height = ibuf->y; + *r_width = ibuf->x; + *r_height = ibuf->y; } else if (sima->image && sima->image->type == IMA_TYPE_R_RESULT && scene) { /* not very important, just nice */ - *width = (scene->r.xsch * scene->r.size) / 100; - *height = (scene->r.ysch * scene->r.size) / 100; + *r_width = (scene->r.xsch * scene->r.size) / 100; + *r_height = (scene->r.ysch * scene->r.size) / 100; if ((scene->r.mode & R_BORDER) && (scene->r.mode & R_CROP)) { - *width *= BLI_rctf_size_x(&scene->r.border); - *height *= BLI_rctf_size_y(&scene->r.border); + *r_width *= BLI_rctf_size_x(&scene->r.border); + *r_height *= BLI_rctf_size_y(&scene->r.border); } } /* I know a bit weak... but preview uses not actual image size */ - // XXX else if (image_preview_active(sima, width, height)); + // XXX else if (image_preview_active(sima, r_width, r_height)); else { - *width = IMG_SIZE_FALLBACK; - *height = IMG_SIZE_FALLBACK; + *r_width = IMG_SIZE_FALLBACK; + *r_height = IMG_SIZE_FALLBACK; } ED_space_image_release_buffer(sima, ibuf, lock); } -void ED_space_image_get_size_fl(SpaceImage *sima, float size[2]) +void ED_space_image_get_size_fl(SpaceImage *sima, float r_size[2]) { int size_i[2]; ED_space_image_get_size(sima, &size_i[0], &size_i[1]); - size[0] = size_i[0]; - size[1] = size_i[1]; + r_size[0] = size_i[0]; + r_size[1] = size_i[1]; } -void ED_space_image_get_aspect(SpaceImage *sima, float *aspx, float *aspy) +void ED_space_image_get_aspect(SpaceImage *sima, float *r_aspx, float *r_aspy) { Image *ima = sima->image; if ((ima == NULL) || (ima->aspx == 0.0f || ima->aspy == 0.0f)) { - *aspx = *aspy = 1.0; + *r_aspx = *r_aspy = 1.0; } else { - BKE_image_get_aspect(ima, aspx, aspy); + BKE_image_get_aspect(ima, r_aspx, r_aspy); } } -void ED_space_image_get_zoom(SpaceImage *sima, ARegion *region, float *zoomx, float *zoomy) +void ED_space_image_get_zoom(SpaceImage *sima, ARegion *region, float *r_zoomx, float *r_zoomy) { int width, height; ED_space_image_get_size(sima, &width, &height); - *zoomx = (float)(BLI_rcti_size_x(®ion->winrct) + 1) / - (float)(BLI_rctf_size_x(®ion->v2d.cur) * width); - *zoomy = (float)(BLI_rcti_size_y(®ion->winrct) + 1) / - (float)(BLI_rctf_size_y(®ion->v2d.cur) * height); + *r_zoomx = (float)(BLI_rcti_size_x(®ion->winrct) + 1) / + (float)(BLI_rctf_size_x(®ion->v2d.cur) * width); + *r_zoomy = (float)(BLI_rcti_size_y(®ion->winrct) + 1) / + (float)(BLI_rctf_size_y(®ion->v2d.cur) * height); } -void ED_space_image_get_uv_aspect(SpaceImage *sima, float *aspx, float *aspy) +void ED_space_image_get_uv_aspect(SpaceImage *sima, float *r_aspx, float *r_aspy) { int w, h; - ED_space_image_get_aspect(sima, aspx, aspy); + ED_space_image_get_aspect(sima, r_aspx, r_aspy); ED_space_image_get_size(sima, &w, &h); - *aspx *= (float)w; - *aspy *= (float)h; + *r_aspx *= (float)w; + *r_aspy *= (float)h; - if (*aspx < *aspy) { - *aspy = *aspy / *aspx; - *aspx = 1.0f; + if (*r_aspx < *r_aspy) { + *r_aspy = *r_aspy / *r_aspx; + *r_aspx = 1.0f; } else { - *aspx = *aspx / *aspy; - *aspy = 1.0f; + *r_aspx = *r_aspx / *r_aspy; + *r_aspy = 1.0f; } } -void ED_image_get_uv_aspect(Image *ima, ImageUser *iuser, float *aspx, float *aspy) +void ED_image_get_uv_aspect(Image *ima, ImageUser *iuser, float *r_aspx, float *r_aspy) { if (ima) { int w, h; - BKE_image_get_aspect(ima, aspx, aspy); + BKE_image_get_aspect(ima, r_aspx, r_aspy); BKE_image_get_size(ima, iuser, &w, &h); - *aspx *= (float)w; - *aspy *= (float)h; + *r_aspx *= (float)w; + *r_aspy *= (float)h; } else { - *aspx = 1.0f; - *aspy = 1.0f; + *r_aspx = 1.0f; + *r_aspy = 1.0f; } } @@ -340,7 +340,8 @@ void ED_image_view_center_to_point(SpaceImage *sima, float x, float y) sima->yof = (y - 0.5f) * height * aspy; } -void ED_image_point_pos(SpaceImage *sima, ARegion *region, float x, float y, float *xr, float *yr) +void ED_image_point_pos( + SpaceImage *sima, ARegion *region, float x, float y, float *r_x, float *r_y) { int sx, sy, width, height; float zoomx, zoomy; @@ -350,8 +351,8 @@ void ED_image_point_pos(SpaceImage *sima, ARegion *region, float x, float y, flo UI_view2d_view_to_region(®ion->v2d, 0.0f, 0.0f, &sx, &sy); - *xr = ((x - sx) / zoomx) / width; - *yr = ((y - sy) / zoomy) / height; + *r_x = ((x - sx) / zoomx) / width; + *r_y = ((y - sy) / zoomy) / height; } void ED_image_point_pos__reverse(SpaceImage *sima, diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 672f32f3c9c..7bd1b8e8291 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -4064,7 +4064,9 @@ void IMAGE_OT_clear_render_border(wmOperatorType *ot) /** \} */ -/* ********************* Add tile operator ****************** */ +/* -------------------------------------------------------------------- */ +/** \name Add Tile Operator + * \{ */ static bool do_fill_tile(PointerRNA *ptr, Image *ima, ImageTile *tile) { @@ -4287,7 +4289,11 @@ void IMAGE_OT_tile_add(wmOperatorType *ot) def_fill_tile(ot->srna); } -/* ********************* Remove tile operator ****************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Remove Tile Operator + * \{ */ static bool tile_remove_poll(bContext *C) { @@ -4328,7 +4334,11 @@ void IMAGE_OT_tile_remove(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ********************* Fill tile operator ****************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Fill Tile Operator + * \{ */ static bool tile_fill_poll(bContext *C) { diff --git a/source/blender/editors/space_image/image_undo.c b/source/blender/editors/space_image/image_undo.c index 1394c05d7bc..8f9f4189c8a 100644 --- a/source/blender/editors/space_image/image_undo.c +++ b/source/blender/editors/space_image/image_undo.c @@ -714,7 +714,7 @@ static UndoImageBuf *ubuf_lookup_from_reference(ImageUndoStep *us_prev, int tile_number, const UndoImageBuf *ubuf) { - /* Use name lookup because because the pointer is cleared for previous steps. */ + /* Use name lookup because the pointer is cleared for previous steps. */ UndoImageHandle *uh_prev = uhandle_lookup_by_name(&us_prev->handles, image, tile_number); if (uh_prev != NULL) { UndoImageBuf *ubuf_reference = uhandle_lookup_ubuf(uh_prev, image, ubuf->ibuf_name); diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index a9cbebc5655..12a1dce3a5f 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -265,7 +265,7 @@ static void image_keymap(struct wmKeyConfig *keyconf) static bool image_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, - const char **UNUSED(tooltip)) + const char **UNUSED(r_tooltip)) { ScrArea *area = CTX_wm_area(C); if (ED_region_overlap_isect_any_xy(area, &event->x)) { diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c index 19ada4779a0..c842fa8b4ac 100644 --- a/source/blender/editors/space_info/textview.c +++ b/source/blender/editors/space_info/textview.c @@ -102,28 +102,29 @@ static void textview_draw_sel(const char *str, } /** - * \warning Allocated memory for 'offsets' must be freed by caller. + * \warning Allocated memory for 'r_offsets' must be freed by caller. * \return The length in bytes. */ -static int textview_wrap_offsets(const char *str, int len, int width, int *lines, int **offsets) +static int textview_wrap_offsets( + const char *str, int len, int width, int *r_lines, int **r_offsets) { int i, end; /* Offset as unicode code-point. */ int j; /* Offset as bytes. */ - *lines = 1; + *r_lines = 1; - *offsets = MEM_callocN( - sizeof(**offsets) * + *r_offsets = MEM_callocN( + sizeof(**r_offsets) * (len * BLI_UTF8_WIDTH_MAX / MAX2(1, width - (BLI_UTF8_WIDTH_MAX - 1)) + 1), __func__); - (*offsets)[0] = 0; + (*r_offsets)[0] = 0; for (i = 0, end = width, j = 0; j < len && str[j]; j += BLI_str_utf8_size_safe(str + j)) { int columns = BLI_str_utf8_char_width_safe(str + j); if (i + columns > end) { - (*offsets)[*lines] = j; - (*lines)++; + (*r_offsets)[*r_lines] = j; + (*r_lines)++; end = i + width; } diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 9d81994bb0b..e50f5a818aa 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -819,7 +819,7 @@ static int edit_node_invoke_properties(bContext *C, wmOperator *op) } static void edit_node_properties_get( - wmOperator *op, bNodeTree *ntree, bNode **rnode, bNodeSocket **rsock, int *rin_out) + wmOperator *op, bNodeTree *ntree, bNode **r_node, bNodeSocket **r_sock, int *r_in_out) { bNode *node; bNodeSocket *sock = NULL; @@ -842,14 +842,14 @@ static void edit_node_properties_get( break; } - if (rnode) { - *rnode = node; + if (r_node) { + *r_node = node; } - if (rsock) { - *rsock = sock; + if (r_sock) { + *r_sock = sock; } - if (rin_out) { - *rin_out = in_out; + if (r_in_out) { + *r_in_out = in_out; } } #endif diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index 8c7c490b181..42439e88c96 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -271,7 +271,7 @@ extern const char *node_context_dir[]; #define NODE_SOCKDY (0.08f * U.widget_unit) #define NODE_WIDTH(node) (node->width * UI_DPI_FAC) #define NODE_HEIGHT(node) (node->height * UI_DPI_FAC) -#define NODE_MARGIN_X (0.75f * U.widget_unit) +#define NODE_MARGIN_X (0.95f * U.widget_unit) #define NODE_SOCKSIZE (0.25f * U.widget_unit) #define NODE_RESIZE_MARGIN (0.20f * U.widget_unit) #define NODE_LINK_RESOL 12 diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index ce351595522..32007d5b971 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -635,7 +635,7 @@ static void node_main_region_draw(const bContext *C, ARegion *region) static bool node_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), - const char **UNUSED(tooltip)) + const char **UNUSED(r_tooltip)) { if (drag->type == WM_DRAG_PATH) { /* rule might not work? */ @@ -649,7 +649,7 @@ static bool node_ima_drop_poll(bContext *UNUSED(C), static bool node_mask_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), - const char **UNUSED(tooltip)) + const char **UNUSED(r_tooltip)) { return WM_drag_ID(drag, ID_MSK) != NULL; } diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c index 8da085f436d..8563b7d8c24 100644 --- a/source/blender/editors/space_outliner/outliner_collections.c +++ b/source/blender/editors/space_outliner/outliner_collections.c @@ -53,6 +53,8 @@ #include "outliner_intern.h" /* own include */ /* -------------------------------------------------------------------- */ +/** \name Utility API + * \{ */ bool outliner_is_collection_tree_element(const TreeElement *te) { @@ -133,8 +135,30 @@ TreeTraversalAction outliner_find_selected_objects(TreeElement *te, void *custom return TRAVERSE_CONTINUE; } +/** + * Populates the \param objects: ListBase with all the outliner selected objects + * We store it as (Object *)LinkData->data + * \param objects: expected to be empty + */ +void ED_outliner_selected_objects_get(const bContext *C, ListBase *objects) +{ + SpaceOutliner *soops = CTX_wm_space_outliner(C); + struct IDsSelectedData data = {{NULL}}; + outliner_tree_traverse( + soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_objects, &data); + LISTBASE_FOREACH (LinkData *, link, &data.selected_array) { + TreeElement *ten_selected = (TreeElement *)link->data; + Object *ob = (Object *)TREESTORE(ten_selected)->id; + BLI_addtail(objects, BLI_genericNodeN(ob)); + } + BLI_freelistN(&data.selected_array); +} + +/** \} */ + /* -------------------------------------------------------------------- */ -/* Poll functions. */ +/** \name Poll Functions + * \{ */ bool ED_outliner_collections_editor_poll(bContext *C) { @@ -148,7 +172,11 @@ static bool outliner_view_layer_collections_editor_poll(bContext *C) return (so != NULL) && (so->outlinevis == SO_VIEW_LAYER); } -/********************************* New Collection ****************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name New Collection + * \{ */ struct CollectionNewData { bool error; @@ -237,7 +265,11 @@ void OUTLINER_OT_collection_new(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -/**************************** Delete Collection ******************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete Collection + * \{ */ struct CollectionEditData { Scene *scene; @@ -369,7 +401,11 @@ void OUTLINER_OT_collection_delete(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -/****************************** Select Objects *******************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select/Deselect Collection Objects + * \{ */ struct CollectionObjectsSelectData { bool error; @@ -457,7 +493,11 @@ void OUTLINER_OT_collection_objects_deselect(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/************************** Duplicate Collection *****************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Duplicate Collection + * \{ */ struct CollectionDuplicateData { TreeElement *te; @@ -578,7 +618,11 @@ void OUTLINER_OT_collection_duplicate(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/**************************** Link Collection ******************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Link Collection + * \{ */ static int collection_link_exec(bContext *C, wmOperator *op) { @@ -636,7 +680,11 @@ void OUTLINER_OT_collection_link(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/************************** Instance Collection ******************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Instance Collection + * \{ */ static int collection_instance_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -703,7 +751,11 @@ void OUTLINER_OT_collection_instance(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/************************** Exclude Collection ******************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Exclude Collection + * \{ */ static TreeTraversalAction layer_collection_find_data_to_edit(TreeElement *te, void *customdata) { @@ -945,7 +997,11 @@ void OUTLINER_OT_collection_indirect_only_clear(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/************************** Visibility Operators ******************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Visibility for Collection Operators + * \{ */ static int collection_isolate_exec(bContext *C, wmOperator *op) { @@ -1129,6 +1185,12 @@ void OUTLINER_OT_collection_hide_inside(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Enable/Disable Collection Operators + * \{ */ + static bool collection_flag_poll(bContext *C, bool clear, int flag) { if (!ED_outliner_collections_editor_poll(C)) { @@ -1310,6 +1372,12 @@ struct OutlinerHideEditData { GSet *bases_to_edit; }; +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Visibility for Collection & Object Operators + * \{ */ + static TreeTraversalAction outliner_hide_find_data_to_edit(TreeElement *te, void *customdata) { struct OutlinerHideEditData *data = customdata; @@ -1433,21 +1501,4 @@ void OUTLINER_OT_unhide_all(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/** - * Populates the \param objects: ListBase with all the outliner selected objects - * We store it as (Object *)LinkData->data - * \param objects: expected to be empty - */ -void ED_outliner_selected_objects_get(const bContext *C, ListBase *objects) -{ - SpaceOutliner *soops = CTX_wm_space_outliner(C); - struct IDsSelectedData data = {{NULL}}; - outliner_tree_traverse( - soops, &soops->tree, 0, TSE_SELECTED, outliner_find_selected_objects, &data); - LISTBASE_FOREACH (LinkData *, link, &data.selected_array) { - TreeElement *ten_selected = (TreeElement *)link->data; - Object *ob = (Object *)TREESTORE(ten_selected)->id; - BLI_addtail(objects, BLI_genericNodeN(ob)); - } - BLI_freelistN(&data.selected_array); -} +/** \} */ diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.c b/source/blender/editors/space_outliner/outliner_dragdrop.c index 8aeeef277f7..6f071ca128e 100644 --- a/source/blender/editors/space_outliner/outliner_dragdrop.c +++ b/source/blender/editors/space_outliner/outliner_dragdrop.c @@ -291,7 +291,7 @@ static bool allow_parenting_without_modifier_key(SpaceOutliner *soops) static bool parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, - const char **UNUSED(tooltip)) + const char **UNUSED(r_tooltip)) { SpaceOutliner *soops = CTX_wm_space_outliner(C); @@ -430,7 +430,7 @@ void OUTLINER_OT_parent_drop(wmOperatorType *ot) static bool parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *event, - const char **UNUSED(tooltip)) + const char **UNUSED(r_tooltip)) { SpaceOutliner *soops = CTX_wm_space_outliner(C); @@ -516,7 +516,7 @@ void OUTLINER_OT_parent_clear(wmOperatorType *ot) static bool scene_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, - const char **UNUSED(tooltip)) + const char **UNUSED(r_tooltip)) { /* Ensure item under cursor is valid drop target */ Object *ob = (Object *)WM_drag_ID(drag, ID_OB); @@ -585,7 +585,7 @@ void OUTLINER_OT_scene_drop(wmOperatorType *ot) static bool material_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, - const char **UNUSED(tooltip)) + const char **UNUSED(r_tooltip)) { /* Ensure item under cursor is valid drop target */ Material *ma = (Material *)WM_drag_ID(drag, ID_MA); @@ -721,7 +721,7 @@ static bool collection_drop_init(bContext *C, static bool collection_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, - const char **tooltip) + const char **r_tooltip) { SpaceOutliner *soops = CTX_wm_space_outliner(C); ARegion *region = CTX_wm_region(C); @@ -734,7 +734,7 @@ static bool collection_drop_poll(bContext *C, if (!data.from || event->ctrl) { tselem->flag |= TSE_DRAG_INTO; changed = true; - *tooltip = TIP_("Link inside Collection"); + *r_tooltip = TIP_("Link inside Collection"); } else { switch (data.insert_type) { @@ -742,26 +742,26 @@ static bool collection_drop_poll(bContext *C, tselem->flag |= TSE_DRAG_BEFORE; changed = true; if (te->prev && outliner_is_collection_tree_element(te->prev)) { - *tooltip = TIP_("Move between collections"); + *r_tooltip = TIP_("Move between collections"); } else { - *tooltip = TIP_("Move before collection"); + *r_tooltip = TIP_("Move before collection"); } break; case TE_INSERT_AFTER: tselem->flag |= TSE_DRAG_AFTER; changed = true; if (te->next && outliner_is_collection_tree_element(te->next)) { - *tooltip = TIP_("Move between collections"); + *r_tooltip = TIP_("Move between collections"); } else { - *tooltip = TIP_("Move after collection"); + *r_tooltip = TIP_("Move after collection"); } break; case TE_INSERT_INTO: tselem->flag |= TSE_DRAG_INTO; changed = true; - *tooltip = TIP_("Move inside collection (Ctrl to link, Shift to parent)"); + *r_tooltip = TIP_("Move inside collection (Ctrl to link, Shift to parent)"); break; } } diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 058d41ab294..0766996c00b 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -1368,68 +1368,68 @@ static void seq_prefetch_wm_notify(const bContext *C, Scene *scene) } static void *sequencer_OCIO_transform_ibuf( - const bContext *C, ImBuf *ibuf, bool *glsl_used, int *format, int *type) + const bContext *C, ImBuf *ibuf, bool *r_glsl_used, int *r_format, int *r_type) { void *display_buffer; void *cache_handle = NULL; bool force_fallback = false; - *glsl_used = false; + *r_glsl_used = false; force_fallback |= (ED_draw_imbuf_method(ibuf) != IMAGE_DRAW_METHOD_GLSL); force_fallback |= (ibuf->dither != 0.0f); if (force_fallback) { /* Fallback to CPU based color space conversion */ - *glsl_used = false; - *format = GL_RGBA; - *type = GL_UNSIGNED_BYTE; + *r_glsl_used = false; + *r_format = GL_RGBA; + *r_type = GL_UNSIGNED_BYTE; display_buffer = NULL; } else if (ibuf->rect_float) { display_buffer = ibuf->rect_float; if (ibuf->channels == 4) { - *format = GL_RGBA; + *r_format = GL_RGBA; } else if (ibuf->channels == 3) { - *format = GL_RGB; + *r_format = GL_RGB; } else { BLI_assert(!"Incompatible number of channels for float buffer in sequencer"); - *format = GL_RGBA; + *r_format = GL_RGBA; display_buffer = NULL; } - *type = GL_FLOAT; + *r_type = GL_FLOAT; if (ibuf->float_colorspace) { - *glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx( + *r_glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx( C, ibuf->float_colorspace, ibuf->dither, true); } else { - *glsl_used = IMB_colormanagement_setup_glsl_draw_ctx(C, ibuf->dither, true); + *r_glsl_used = IMB_colormanagement_setup_glsl_draw_ctx(C, ibuf->dither, true); } } else if (ibuf->rect) { display_buffer = ibuf->rect; - *format = GL_RGBA; - *type = GL_UNSIGNED_BYTE; + *r_format = GL_RGBA; + *r_type = GL_UNSIGNED_BYTE; - *glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx( + *r_glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx( C, ibuf->rect_colorspace, ibuf->dither, false); } else { - *format = GL_RGBA; - *type = GL_UNSIGNED_BYTE; + *r_format = GL_RGBA; + *r_type = GL_UNSIGNED_BYTE; display_buffer = NULL; } /* there's a data to be displayed, but GLSL is not initialized * properly, in this case we fallback to CPU-based display transform */ - if ((ibuf->rect || ibuf->rect_float) && !*glsl_used) { + if ((ibuf->rect || ibuf->rect_float) && !*r_glsl_used) { display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); - *format = GL_RGBA; - *type = GL_UNSIGNED_BYTE; + *r_format = GL_RGBA; + *r_type = GL_UNSIGNED_BYTE; } if (cache_handle) { IMB_display_buffer_release(cache_handle); @@ -1968,6 +1968,7 @@ typedef struct CacheDrawData { struct View2D *v2d; float stripe_offs; float stripe_ht; + int cache_flag; GPUVertBuf *raw_vbo; GPUVertBuf *preprocessed_vbo; GPUVertBuf *composite_vbo; @@ -1979,7 +1980,25 @@ typedef struct CacheDrawData { } CacheDrawData; /* Called as a callback */ -static bool draw_cache_view_cb( +static bool draw_cache_view_init_cb(void *userdata, size_t item_count) +{ + if (item_count == 0) { + return true; + } + + CacheDrawData *drawdata = userdata; + /* We can not get item count per cache type, so using total item count is safe. */ + size_t max_vert_count = item_count * 6; + GPU_vertbuf_data_alloc(drawdata->raw_vbo, max_vert_count); + GPU_vertbuf_data_alloc(drawdata->preprocessed_vbo, max_vert_count); + GPU_vertbuf_data_alloc(drawdata->composite_vbo, max_vert_count); + GPU_vertbuf_data_alloc(drawdata->final_out_vbo, max_vert_count); + + return false; +} + +/* Called as a callback */ +static bool draw_cache_view_iter_cb( void *userdata, struct Sequence *seq, int nfra, int cache_type, float UNUSED(cost)) { CacheDrawData *drawdata = userdata; @@ -1987,44 +2006,43 @@ static bool draw_cache_view_cb( float stripe_bot, stripe_top, stripe_offs, stripe_ht; GPUVertBuf *vbo; size_t *vert_count; - switch (cache_type) { - case SEQ_CACHE_STORE_FINAL_OUT: - stripe_ht = UI_view2d_region_to_view_y(v2d, 4.0f * UI_DPI_FAC * U.pixelsize) - v2d->cur.ymin; - stripe_bot = UI_view2d_region_to_view_y(v2d, V2D_SCROLL_HANDLE_HEIGHT); - stripe_top = stripe_bot + stripe_ht; - vbo = drawdata->final_out_vbo; - vert_count = &drawdata->final_out_vert_count; - break; - - case SEQ_CACHE_STORE_RAW: - stripe_offs = drawdata->stripe_offs; - stripe_ht = drawdata->stripe_ht; - stripe_bot = seq->machine + SEQ_STRIP_OFSBOTTOM + stripe_offs; - stripe_top = stripe_bot + stripe_ht; - vbo = drawdata->raw_vbo; - vert_count = &drawdata->raw_vert_count; - break; - case SEQ_CACHE_STORE_PREPROCESSED: - stripe_offs = drawdata->stripe_offs; - stripe_ht = drawdata->stripe_ht; - stripe_bot = seq->machine + SEQ_STRIP_OFSBOTTOM + (stripe_offs + stripe_ht) + stripe_offs; - stripe_top = stripe_bot + stripe_ht; - vbo = drawdata->preprocessed_vbo; - vert_count = &drawdata->preprocessed_vert_count; - break; - - case SEQ_CACHE_STORE_COMPOSITE: - stripe_offs = drawdata->stripe_offs; - stripe_ht = drawdata->stripe_ht; - stripe_top = seq->machine + SEQ_STRIP_OFSTOP - stripe_offs; - stripe_bot = stripe_top - stripe_ht; - vbo = drawdata->composite_vbo; - vert_count = &drawdata->composite_vert_count; - break; - - default: - return true; + if ((cache_type & SEQ_CACHE_STORE_FINAL_OUT) && + (drawdata->cache_flag & SEQ_CACHE_VIEW_FINAL_OUT)) { + stripe_ht = UI_view2d_region_to_view_y(v2d, 4.0f * UI_DPI_FAC * U.pixelsize) - v2d->cur.ymin; + stripe_bot = UI_view2d_region_to_view_y(v2d, V2D_SCROLL_HANDLE_HEIGHT); + stripe_top = stripe_bot + stripe_ht; + vbo = drawdata->final_out_vbo; + vert_count = &drawdata->final_out_vert_count; + } + else if ((cache_type & SEQ_CACHE_STORE_RAW) && (drawdata->cache_flag & SEQ_CACHE_VIEW_RAW)) { + stripe_offs = drawdata->stripe_offs; + stripe_ht = drawdata->stripe_ht; + stripe_bot = seq->machine + SEQ_STRIP_OFSBOTTOM + stripe_offs; + stripe_top = stripe_bot + stripe_ht; + vbo = drawdata->raw_vbo; + vert_count = &drawdata->raw_vert_count; + } + else if ((cache_type & SEQ_CACHE_STORE_PREPROCESSED) && + (drawdata->cache_flag & SEQ_CACHE_VIEW_PREPROCESSED)) { + stripe_offs = drawdata->stripe_offs; + stripe_ht = drawdata->stripe_ht; + stripe_bot = seq->machine + SEQ_STRIP_OFSBOTTOM + (stripe_offs + stripe_ht) + stripe_offs; + stripe_top = stripe_bot + stripe_ht; + vbo = drawdata->preprocessed_vbo; + vert_count = &drawdata->preprocessed_vert_count; + } + else if ((cache_type & SEQ_CACHE_STORE_COMPOSITE) && + (drawdata->cache_flag & SEQ_CACHE_VIEW_COMPOSITE)) { + stripe_offs = drawdata->stripe_offs; + stripe_ht = drawdata->stripe_ht; + stripe_top = seq->machine + SEQ_STRIP_OFSTOP - stripe_offs; + stripe_bot = stripe_top - stripe_ht; + vbo = drawdata->composite_vbo; + vert_count = &drawdata->composite_vert_count; + } + else { + return false; } int cfra = seq->start + nfra; @@ -2048,10 +2066,10 @@ static void draw_cache_view_batch( GPUVertBuf *vbo, size_t vert_count, float col_r, float col_g, float col_b, float col_a) { GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO); - GPU_vertbuf_data_len_set(vbo, vert_count); - GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR); - GPU_batch_uniform_4f(batch, "color", col_r, col_g, col_b, col_a); if (vert_count > 0) { + GPU_vertbuf_data_len_set(vbo, vert_count); + GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_UNIFORM_COLOR); + GPU_batch_uniform_4f(batch, "color", col_r, col_g, col_b, col_a); GPU_batch_draw(batch); } GPU_batch_discard(batch); @@ -2127,42 +2145,32 @@ static void draw_cache_view(const bContext *C) immUnbindProgram(); - size_t cache_num_items = BKE_sequencer_cache_get_num_items(scene); - - if (cache_num_items > 0) { - GPUVertFormat format = {0}; - GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - CacheDrawData userdata; - userdata.v2d = v2d; - userdata.stripe_offs = stripe_offs; - userdata.stripe_ht = stripe_ht; - userdata.raw_vert_count = 0; - userdata.preprocessed_vert_count = 0; - userdata.composite_vert_count = 0; - userdata.final_out_vert_count = 0; - userdata.raw_vbo = GPU_vertbuf_create_with_format(&format); - userdata.preprocessed_vbo = GPU_vertbuf_create_with_format(&format); - userdata.composite_vbo = GPU_vertbuf_create_with_format(&format); - userdata.final_out_vbo = GPU_vertbuf_create_with_format(&format); - - /* We can not get item count per cache type, so using total item count is safe. */ - size_t max_vert_count = cache_num_items * 6; - GPU_vertbuf_data_alloc(userdata.raw_vbo, max_vert_count); - GPU_vertbuf_data_alloc(userdata.preprocessed_vbo, max_vert_count); - GPU_vertbuf_data_alloc(userdata.composite_vbo, max_vert_count); - GPU_vertbuf_data_alloc(userdata.final_out_vbo, max_vert_count); - - BKE_sequencer_cache_iterate(scene, &userdata, draw_cache_view_cb); - - draw_cache_view_batch(userdata.raw_vbo, userdata.raw_vert_count, 1.0f, 0.1f, 0.02f, 0.4f); - draw_cache_view_batch( - userdata.preprocessed_vbo, userdata.preprocessed_vert_count, 0.1f, 0.1f, 0.75f, 0.4f); - draw_cache_view_batch( - userdata.composite_vbo, userdata.composite_vert_count, 1.0f, 0.6f, 0.0f, 0.4f); - draw_cache_view_batch( - userdata.final_out_vbo, userdata.final_out_vert_count, 1.0f, 0.4f, 0.2f, 0.4f); - } + GPUVertFormat format = {0}; + GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + + CacheDrawData userdata; + userdata.v2d = v2d; + userdata.stripe_offs = stripe_offs; + userdata.stripe_ht = stripe_ht; + userdata.cache_flag = scene->ed->cache_flag; + userdata.raw_vert_count = 0; + userdata.preprocessed_vert_count = 0; + userdata.composite_vert_count = 0; + userdata.final_out_vert_count = 0; + userdata.raw_vbo = GPU_vertbuf_create_with_format(&format); + userdata.preprocessed_vbo = GPU_vertbuf_create_with_format(&format); + userdata.composite_vbo = GPU_vertbuf_create_with_format(&format); + userdata.final_out_vbo = GPU_vertbuf_create_with_format(&format); + + BKE_sequencer_cache_iterate(scene, &userdata, draw_cache_view_init_cb, draw_cache_view_iter_cb); + + draw_cache_view_batch(userdata.raw_vbo, userdata.raw_vert_count, 1.0f, 0.1f, 0.02f, 0.4f); + draw_cache_view_batch( + userdata.preprocessed_vbo, userdata.preprocessed_vert_count, 0.1f, 0.1f, 0.75f, 0.4f); + draw_cache_view_batch( + userdata.composite_vbo, userdata.composite_vert_count, 1.0f, 0.6f, 0.0f, 0.4f); + draw_cache_view_batch( + userdata.final_out_vbo, userdata.final_out_vert_count, 1.0f, 0.4f, 0.2f, 0.4f); GPU_blend(false); } diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 3f36c844f30..71e63547eae 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -551,15 +551,15 @@ bool ED_space_sequencer_check_show_strip(SpaceSeq *sseq) int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, - Sequence **selseq1, - Sequence **selseq2, - Sequence **selseq3, - const char **error_str) + Sequence **r_selseq1, + Sequence **r_selseq2, + Sequence **r_selseq3, + const char **r_error_str) { Editing *ed = BKE_sequencer_editing_get(scene, false); Sequence *seq1 = NULL, *seq2 = NULL, *seq3 = NULL, *seq; - *error_str = NULL; + *r_error_str = NULL; if (!activeseq) { seq2 = BKE_sequencer_active_get(scene); @@ -568,7 +568,7 @@ int seq_effect_find_selected(Scene *scene, for (seq = ed->seqbasep->first; seq; seq = seq->next) { if (seq->flag & SELECT) { if (seq->type == SEQ_TYPE_SOUND_RAM && BKE_sequence_effect_get_num_inputs(type) != 0) { - *error_str = N_("Cannot apply effects to audio sequence strips"); + *r_error_str = N_("Cannot apply effects to audio sequence strips"); return 0; } if ((seq != activeseq) && (seq != seq2)) { @@ -582,7 +582,7 @@ int seq_effect_find_selected(Scene *scene, seq3 = seq; } else { - *error_str = N_("Cannot apply effect to more than 3 sequence strips"); + *r_error_str = N_("Cannot apply effect to more than 3 sequence strips"); return 0; } } @@ -599,11 +599,11 @@ int seq_effect_find_selected(Scene *scene, switch (BKE_sequence_effect_get_num_inputs(type)) { case 0: - *selseq1 = *selseq2 = *selseq3 = NULL; + *r_selseq1 = *r_selseq2 = *r_selseq3 = NULL; return 1; /* success */ case 1: if (seq2 == NULL) { - *error_str = N_("At least one selected sequence strip is needed"); + *r_error_str = N_("At least one selected sequence strip is needed"); return 0; } if (seq1 == NULL) { @@ -615,7 +615,7 @@ int seq_effect_find_selected(Scene *scene, ATTR_FALLTHROUGH; case 2: if (seq1 == NULL || seq2 == NULL) { - *error_str = N_("2 selected sequence strips are needed"); + *r_error_str = N_("2 selected sequence strips are needed"); return 0; } if (seq3 == NULL) { @@ -625,13 +625,13 @@ int seq_effect_find_selected(Scene *scene, } if (seq1 == NULL && seq2 == NULL && seq3 == NULL) { - *error_str = N_("TODO: in what cases does this happen?"); + *r_error_str = N_("TODO: in what cases does this happen?"); return 0; } - *selseq1 = seq1; - *selseq2 = seq2; - *selseq3 = seq3; + *r_selseq1 = seq1; + *r_selseq2 = seq2; + *r_selseq3 = seq3; return 1; } diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h index fe3170e10e0..f70bc06caf7 100644 --- a/source/blender/editors/space_sequencer/sequencer_intern.h +++ b/source/blender/editors/space_sequencer/sequencer_intern.h @@ -83,10 +83,10 @@ void recurs_sel_seq(struct Sequence *seqm); int seq_effect_find_selected(struct Scene *scene, struct Sequence *activeseq, int type, - struct Sequence **selseq1, - struct Sequence **selseq2, - struct Sequence **selseq3, - const char **error_str); + struct Sequence **r_selseq1, + struct Sequence **r_selseq2, + struct Sequence **r_selseq3, + const char **r_error_str); /* operator helpers */ bool sequencer_edit_poll(struct bContext *C); diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 1aa2a0c9c44..447bf27099d 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -363,7 +363,7 @@ static void sequencer_listener(wmWindow *UNUSED(win), static bool image_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, - const char **UNUSED(tooltip)) + const char **UNUSED(r_tooltip)) { ARegion *region = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); @@ -383,7 +383,7 @@ static bool image_drop_poll(bContext *C, static bool movie_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, - const char **UNUSED(tooltip)) + const char **UNUSED(r_tooltip)) { ARegion *region = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); @@ -402,7 +402,7 @@ static bool movie_drop_poll(bContext *C, static bool sound_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, - const char **UNUSED(tooltip)) + const char **UNUSED(r_tooltip)) { ARegion *region = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); @@ -679,19 +679,18 @@ static void sequencer_preview_region_draw(const bContext *C, ARegion *region) SpaceSeq *sseq = sa->spacedata.first; Scene *scene = CTX_data_scene(C); wmWindowManager *wm = CTX_wm_manager(C); - const bool show_split = (scene->ed && (scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) && - (sseq->mainb == SEQ_DRAW_IMG_IMBUF)); + const bool draw_overlay = (scene->ed && (scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW)); /* XXX temp fix for wrong setting in sseq->mainb */ if (sseq->mainb == SEQ_DRAW_SEQUENCE) { sseq->mainb = SEQ_DRAW_IMG_IMBUF; } - if (!show_split || sseq->overlay_type != SEQ_DRAW_OVERLAY_REFERENCE) { + if (!draw_overlay || sseq->overlay_type != SEQ_DRAW_OVERLAY_REFERENCE) { sequencer_draw_preview(C, scene, region, sseq, scene->r.cfra, 0, false, false); } - if (show_split && sseq->overlay_type != SEQ_DRAW_OVERLAY_CURRENT) { + if (draw_overlay && sseq->overlay_type != SEQ_DRAW_OVERLAY_CURRENT) { int over_cfra; if (scene->ed->over_flag & SEQ_EDIT_OVERLAY_ABS) { diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index 92b084a8d0d..d5379a4e76d 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -328,7 +328,7 @@ static void text_cursor(wmWindow *win, ScrArea *sa, ARegion *region) static bool text_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), - const char **UNUSED(tooltip)) + const char **UNUSED(r_tooltip)) { if (drag->type == WM_DRAG_PATH) { /* rule might not work? */ @@ -348,7 +348,7 @@ static void text_drop_copy(wmDrag *drag, wmDropBox *drop) static bool text_drop_paste_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), - const char **UNUSED(tooltip)) + const char **UNUSED(r_tooltip)) { return (drag->type == WM_DRAG_ID); } diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index eb245ae0766..13c5bddd3bf 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -471,7 +471,7 @@ static bool view3d_drop_id_in_main_region_poll(bContext *C, static bool view3d_ob_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, - const char **UNUSED(tooltip)) + const char **UNUSED(r_tooltip)) { return view3d_drop_id_in_main_region_poll(C, drag, event, ID_OB); } @@ -479,7 +479,7 @@ static bool view3d_ob_drop_poll(bContext *C, static bool view3d_collection_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, - const char **UNUSED(tooltip)) + const char **UNUSED(r_tooltip)) { return view3d_drop_id_in_main_region_poll(C, drag, event, ID_GR); } @@ -487,7 +487,7 @@ static bool view3d_collection_drop_poll(bContext *C, static bool view3d_mat_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, - const char **UNUSED(tooltip)) + const char **UNUSED(r_tooltip)) { return view3d_drop_id_in_main_region_poll(C, drag, event, ID_MA); } @@ -495,7 +495,7 @@ static bool view3d_mat_drop_poll(bContext *C, static bool view3d_ima_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, - const char **UNUSED(tooltip)) + const char **UNUSED(r_tooltip)) { if (ED_region_overlap_isect_any_xy(CTX_wm_area(C), &event->x)) { return false; @@ -524,9 +524,9 @@ static bool view3d_ima_bg_is_camera_view(bContext *C) static bool view3d_ima_bg_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, - const char **tooltip) + const char **r_tooltip) { - if (!view3d_ima_drop_poll(C, drag, event, tooltip)) { + if (!view3d_ima_drop_poll(C, drag, event, r_tooltip)) { return false; } @@ -540,9 +540,9 @@ static bool view3d_ima_bg_drop_poll(bContext *C, static bool view3d_ima_empty_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, - const char **tooltip) + const char **r_tooltip) { - if (!view3d_ima_drop_poll(C, drag, event, tooltip)) { + if (!view3d_ima_drop_poll(C, drag, event, r_tooltip)) { return false; } @@ -562,7 +562,7 @@ static bool view3d_ima_empty_drop_poll(bContext *C, static bool view3d_volume_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event), - const char **UNUSED(tooltip)) + const char **UNUSED(r_tooltip)) { return (drag->type == WM_DRAG_PATH) && (drag->icon == ICON_FILE_VOLUME); } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 8af651c7309..694cb7ee7d4 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -881,7 +881,7 @@ void ED_view3d_draw_depth(Depsgraph *depsgraph, ARegion *region, View3D *v3d, bo /* ******************** other elements ***************** */ /** could move this elsewhere, but tied into #ED_view3d_grid_scale */ -float ED_scene_grid_scale(const Scene *scene, const char **grid_unit) +float ED_scene_grid_scale(const Scene *scene, const char **r_grid_unit) { /* apply units */ if (scene->unit.system) { @@ -892,8 +892,8 @@ float ED_scene_grid_scale(const Scene *scene, const char **grid_unit) if (usys) { int i = bUnit_GetBaseUnit(usys); - if (grid_unit) { - *grid_unit = bUnit_GetNameDisplay(usys, i); + if (r_grid_unit) { + *r_grid_unit = bUnit_GetNameDisplay(usys, i); } return (float)bUnit_GetScaler(usys, i) / scene->unit.scale_length; } @@ -902,9 +902,9 @@ float ED_scene_grid_scale(const Scene *scene, const char **grid_unit) return 1.0f; } -float ED_view3d_grid_scale(const Scene *scene, View3D *v3d, const char **grid_unit) +float ED_view3d_grid_scale(const Scene *scene, View3D *v3d, const char **r_grid_unit) { - return v3d->grid * ED_scene_grid_scale(scene, grid_unit); + return v3d->grid * ED_scene_grid_scale(scene, r_grid_unit); } #define STEPS_LEN 8 @@ -958,7 +958,7 @@ void ED_view3d_grid_steps(const Scene *scene, float ED_view3d_grid_view_scale(Scene *scene, View3D *v3d, RegionView3D *rv3d, - const char **grid_unit) + const char **r_grid_unit) { float grid_scale; if (!rv3d->is_persp && RV3D_VIEW_IS_AXIS(rv3d->view)) { @@ -977,18 +977,18 @@ float ED_view3d_grid_view_scale(Scene *scene, } } - if (grid_unit) { + if (r_grid_unit) { const void *usys; int len; bUnit_GetSystem(scene->unit.system, B_UNIT_LENGTH, &usys, &len); if (usys) { - *grid_unit = bUnit_GetNameDisplay(usys, len - i - 1); + *r_grid_unit = bUnit_GetNameDisplay(usys, len - i - 1); } } } else { - grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit); + grid_scale = ED_view3d_grid_scale(scene, v3d, r_grid_unit); } return grid_scale; diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 67dacca85ba..e650f5581ff 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -627,14 +627,14 @@ void viewrotate_modal_keymap(wmKeyConfig *keyconf) {0, NULL, 0, NULL, NULL}, }; - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Rotate Modal"); + wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Rotate Modal"); /* this function is called for each spacetype, only needs to add map once */ if (keymap && keymap->modal_items) { return; } - keymap = WM_modalkeymap_add(keyconf, "View3D Rotate Modal", modal_items); + keymap = WM_modalkeymap_ensure(keyconf, "View3D Rotate Modal", modal_items); /* disabled mode switching for now, can re-implement better, later on */ #if 0 @@ -1702,14 +1702,14 @@ void viewmove_modal_keymap(wmKeyConfig *keyconf) {0, NULL, 0, NULL, NULL}, }; - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Move Modal"); + wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Move Modal"); /* this function is called for each spacetype, only needs to add map once */ if (keymap && keymap->modal_items) { return; } - keymap = WM_modalkeymap_add(keyconf, "View3D Move Modal", modal_items); + keymap = WM_modalkeymap_ensure(keyconf, "View3D Move Modal", modal_items); /* items for modal map */ WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM); @@ -1901,14 +1901,14 @@ void viewzoom_modal_keymap(wmKeyConfig *keyconf) {0, NULL, 0, NULL, NULL}, }; - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Zoom Modal"); + wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Zoom Modal"); /* this function is called for each spacetype, only needs to add map once */ if (keymap && keymap->modal_items) { return; } - keymap = WM_modalkeymap_add(keyconf, "View3D Zoom Modal", modal_items); + keymap = WM_modalkeymap_ensure(keyconf, "View3D Zoom Modal", modal_items); /* disabled mode switching for now, can re-implement better, later on */ #if 0 @@ -2472,14 +2472,14 @@ void viewdolly_modal_keymap(wmKeyConfig *keyconf) {0, NULL, 0, NULL, NULL}, }; - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Dolly Modal"); + wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Dolly Modal"); /* this function is called for each spacetype, only needs to add map once */ if (keymap && keymap->modal_items) { return; } - keymap = WM_modalkeymap_add(keyconf, "View3D Dolly Modal", modal_items); + keymap = WM_modalkeymap_ensure(keyconf, "View3D Dolly Modal", modal_items); /* disabled mode switching for now, can re-implement better, later on */ #if 0 diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index 563e1afa67e..06d1a033a0d 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -125,14 +125,14 @@ void fly_modal_keymap(wmKeyConfig *keyconf) {0, NULL, 0, NULL, NULL}, }; - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Fly Modal"); + wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Fly Modal"); /* this function is called for each spacetype, only needs to add map once */ if (keymap && keymap->modal_items) { return; } - keymap = WM_modalkeymap_add(keyconf, "View3D Fly Modal", modal_items); + keymap = WM_modalkeymap_ensure(keyconf, "View3D Fly Modal", modal_items); /* assign map to operators */ WM_modalkeymap_assign(keymap, "VIEW3D_OT_fly"); diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 6e1533e50fd..30587e6084d 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -1557,7 +1557,7 @@ void VIEW3D_OT_localview_remove_from(wmOperatorType *ot) static uint free_localcollection_bit(Main *bmain, unsigned short local_collections_uuid, - bool *reset) + bool *r_reset) { ScrArea *sa; bScreen *sc; @@ -1587,7 +1587,7 @@ static uint free_localcollection_bit(Main *bmain, /* Otherwise get the first free available. */ for (int i = 0; i < 16; i++) { if ((local_view_bits & (1 << i)) == 0) { - *reset = true; + *r_reset = true; return (1 << i); } } diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index 89b5618075a..8ee52756f27 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -160,14 +160,14 @@ void walk_modal_keymap(wmKeyConfig *keyconf) {0, NULL, 0, NULL, NULL}, }; - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Walk Modal"); + wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Walk Modal"); /* this function is called for each spacetype, only needs to add map once */ if (keymap && keymap->modal_items) { return; } - keymap = WM_modalkeymap_add(keyconf, "View3D Walk Modal", modal_items); + keymap = WM_modalkeymap_ensure(keyconf, "View3D Walk Modal", modal_items); /* assign map to operators */ WM_modalkeymap_assign(keymap, "VIEW3D_OT_walk"); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 0ea355e9b6e..a9eaad6868e 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -770,9 +770,9 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf) {0, NULL, 0, NULL, NULL}, }; - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Transform Modal Map"); + wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Transform Modal Map"); - keymap = WM_modalkeymap_add(keyconf, "Transform Modal Map", modal_items); + keymap = WM_modalkeymap_ensure(keyconf, "Transform Modal Map", modal_items); keymap->poll_modal_item = transform_modal_item_poll; return keymap; diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index 09ee9081baf..1049db74a75 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -96,7 +96,9 @@ void transform_around_single_fallback(TransInfo *t) } } -/* ************************** Functions *************************** */ +/* -------------------------------------------------------------------- */ +/** \name Proportional Editing + * \{ */ static int trans_data_compare_dist(const void *a, const void *b) { @@ -333,7 +335,11 @@ static void set_prop_dist(TransInfo *t, const bool with_dist) MEM_freeN(td_table); } -/* ********************* pose mode ************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Pose Mode + * \{ */ static short apply_targetless_ik(Object *ob) { @@ -453,15 +459,20 @@ int count_set_pose_transflags(Object *ob, for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { bone = pchan->bone; - bone->flag &= ~(BONE_TRANSFORM | BONE_TRANSFORM_MIRROR); if (PBONE_VISIBLE(arm, bone)) { if ((bone->flag & BONE_SELECTED)) { bone->flag |= BONE_TRANSFORM; } + else { + bone->flag &= ~BONE_TRANSFORM; + } bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM; bone->flag &= ~BONE_TRANSFORM_CHILD; } + else { + bone->flag &= ~BONE_TRANSFORM; + } } /* make sure no bone can be transformed when a parent is transformed */ @@ -506,7 +517,11 @@ int count_set_pose_transflags(Object *ob, return total; } -/* -------- Auto-IK ---------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Pose Mode (Auto-IK) + * \{ */ /* adjust pose-channel's auto-ik chainlen */ static bool pchan_autoik_adjust(bPoseChannel *pchan, short chainlen) @@ -631,7 +646,11 @@ static void pose_grab_with_ik_clear(Main *bmain, Object *ob) } } -/* ********************* curve/surface ********* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Curve Surface + * \{ */ void calc_distanceCurveVerts(TransData *head, TransData *tail) { @@ -701,7 +720,11 @@ TransDataCurveHandleFlags *initTransDataCurveHandles(TransData *td, struct BezTr return hdata; } -/* ********************* UV ****************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name UV Coordinates + * \{ */ bool clipUVTransform(TransInfo *t, float vec[2], const bool resize) { @@ -787,7 +810,11 @@ void clipUVData(TransInfo *t) } } -/* ********************* ANIMATION EDITORS (GENERAL) ************************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Animation Editors (General) + * \{ */ /** * For modal operation: `t->center_global` may not have been set yet. @@ -828,7 +855,11 @@ bool FrameOnMouseSide(char side, float frame, float cframe) } } -/* ********************* ACTION EDITOR ****************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Animation Editor + * \{ */ static int masklay_shape_cmp_frame(void *thunk, const void *a, const void *b) { @@ -1088,7 +1119,11 @@ static void posttrans_action_clean(bAnimContext *ac, bAction *act) ANIM_animdata_freelist(&anim_data); } -/* ********************* GRAPH EDITOR ************************* */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Graph Editor + * \{ */ /* struct for use in re-sorting BezTriples during Graph Editor transform */ typedef struct BeztMap { @@ -1259,6 +1294,12 @@ static void beztmap_to_data(TransInfo *t, FCurve *fcu, BeztMap *bezms, int totve MEM_freeN(adjusted); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Transform Utilities + * \{ */ + /* This function is called by recalcData during the Transform loop to recalculate * the handles of curves and sort the keyframes so that the curves draw correctly. * It is only called if some keyframes have moved out of order. @@ -1297,8 +1338,6 @@ void remake_graph_transdata(TransInfo *t, ListBase *anim_data) } } -/* *********************** Transform data ******************* */ - /* Little helper function for ObjectToTransData used to give certain * constraints (ChildOf, FollowPath, and others that may be added) * inverse corrections for transform, so that they aren't in CrazySpace. @@ -1384,6 +1423,12 @@ bool constraints_list_needinv(TransInfo *t, ListBase *list) return false; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Transform (Auto-Keyframing) + * \{ */ + /** * Auto-keyframing feature - for objects * @@ -1541,147 +1586,156 @@ void autokeyframe_pose(bContext *C, Scene *scene, Object *ob, int tmode, short t FCurve *fcu; // TODO: this should probably be done per channel instead... - if (autokeyframe_cfra_can_key(scene, id)) { - ReportList *reports = CTX_wm_reports(C); - ToolSettings *ts = scene->toolsettings; - KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene); - ListBase nla_cache = {NULL, NULL}; - float cfra = (float)CFRA; - eInsertKeyFlags flag = 0; + if (!autokeyframe_cfra_can_key(scene, id)) { + /* tag channels that should have unkeyed data */ + for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { + if (pchan->bone->flag & BONE_TRANSFORM) { + /* tag this channel */ + pchan->bone->flag |= BONE_UNKEYED; + } + } + return; + } - /* flag is initialized from UserPref keyframing settings - * - special exception for targetless IK - INSERTKEY_MATRIX keyframes should get - * visual keyframes even if flag not set, as it's not that useful otherwise - * (for quick animation recording) - */ - flag = ANIM_get_keyframing_flags(scene, true); + ReportList *reports = CTX_wm_reports(C); + ToolSettings *ts = scene->toolsettings; + KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene); + ListBase nla_cache = {NULL, NULL}; + float cfra = (float)CFRA; + eInsertKeyFlags flag = 0; + + /* flag is initialized from UserPref keyframing settings + * - special exception for targetless IK - INSERTKEY_MATRIX keyframes should get + * visual keyframes even if flag not set, as it's not that useful otherwise + * (for quick animation recording) + */ + flag = ANIM_get_keyframing_flags(scene, true); - if (targetless_ik) { - flag |= INSERTKEY_MATRIX; + if (targetless_ik) { + flag |= INSERTKEY_MATRIX; + } + + for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { + if ((pchan->bone->flag & BONE_TRANSFORM) == 0 && + !((pose->flag & POSE_MIRROR_EDIT) && (pchan->bone->flag & BONE_TRANSFORM_MIRROR))) { + continue; } - for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { - if ((pchan->bone->flag & BONE_TRANSFORM) || - ((pose->flag & POSE_MIRROR_EDIT) && (pchan->bone->flag & BONE_TRANSFORM_MIRROR))) { - ListBase dsources = {NULL, NULL}; - - /* clear any 'unkeyed' flag it may have */ - pchan->bone->flag &= ~BONE_UNKEYED; - - /* add datasource override for the camera object */ - ANIM_relative_keyingset_add_source(&dsources, id, &RNA_PoseBone, pchan); - - /* only insert into active keyingset? */ - if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (active_ks)) { - /* run the active Keying Set on the current datasource */ - ANIM_apply_keyingset(C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra); - } - /* only insert into available channels? */ - else if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL)) { - if (act) { - for (fcu = act->curves.first; fcu; fcu = fcu->next) { - /* only insert keyframes for this F-Curve if it affects the current bone */ - if (strstr(fcu->rna_path, "bones")) { - char *pchanName = BLI_str_quoted_substrN(fcu->rna_path, "bones["); - - /* only if bone name matches too... - * NOTE: this will do constraints too, but those are ok to do here too? - */ - if (pchanName && STREQ(pchanName, pchan->name)) { - insert_keyframe(bmain, - reports, - id, - act, - ((fcu->grp) ? (fcu->grp->name) : (NULL)), - fcu->rna_path, - fcu->array_index, - cfra, - ts->keyframe_type, - &nla_cache, - flag); - } - - if (pchanName) { - MEM_freeN(pchanName); - } - } - } - } - } - /* only insert keyframe if needed? */ - else if (IS_AUTOKEY_FLAG(scene, INSERTNEEDED)) { - bool do_loc = false, do_rot = false, do_scale = false; + ListBase dsources = {NULL, NULL}; - /* Filter the conditions when this happens - * (assume that 'curarea->spacetype == SPACE_VIEW3D'). */ - if (tmode == TFM_TRANSLATION) { - if (targetless_ik) { - do_rot = true; - } - else { - do_loc = true; - } - } - else if (ELEM(tmode, TFM_ROTATION, TFM_TRACKBALL)) { - if (ELEM(scene->toolsettings->transform_pivot_point, - V3D_AROUND_CURSOR, - V3D_AROUND_ACTIVE)) { - do_loc = true; - } + /* clear any 'unkeyed' flag it may have */ + pchan->bone->flag &= ~BONE_UNKEYED; - if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) { - do_rot = true; - } - } - else if (tmode == TFM_RESIZE) { - if (ELEM(scene->toolsettings->transform_pivot_point, - V3D_AROUND_CURSOR, - V3D_AROUND_ACTIVE)) { - do_loc = true; - } + /* add datasource override for the camera object */ + ANIM_relative_keyingset_add_source(&dsources, id, &RNA_PoseBone, pchan); - if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) { - do_scale = true; - } + /* only insert into active keyingset? */ + if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (active_ks)) { + /* run the active Keying Set on the current datasource */ + ANIM_apply_keyingset(C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra); + } + /* only insert into available channels? */ + else if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL)) { + if (act) { + for (fcu = act->curves.first; fcu; fcu = fcu->next) { + /* only insert keyframes for this F-Curve if it affects the current bone */ + if (strstr(fcu->rna_path, "bones") == NULL) { + continue; } + char *pchanName = BLI_str_quoted_substrN(fcu->rna_path, "bones["); - if (do_loc) { - KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID); - ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); - } - if (do_rot) { - KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID); - ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); + /* only if bone name matches too... + * NOTE: this will do constraints too, but those are ok to do here too? + */ + if (pchanName && STREQ(pchanName, pchan->name)) { + insert_keyframe(bmain, + reports, + id, + act, + ((fcu->grp) ? (fcu->grp->name) : (NULL)), + fcu->rna_path, + fcu->array_index, + cfra, + ts->keyframe_type, + &nla_cache, + flag); } - if (do_scale) { - KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_SCALING_ID); - ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); + + if (pchanName) { + MEM_freeN(pchanName); } } - /* insert keyframe in all (transform) channels */ + } + } + /* only insert keyframe if needed? */ + else if (IS_AUTOKEY_FLAG(scene, INSERTNEEDED)) { + bool do_loc = false, do_rot = false, do_scale = false; + + /* Filter the conditions when this happens + * (assume that 'curarea->spacetype == SPACE_VIEW3D'). */ + if (tmode == TFM_TRANSLATION) { + if (targetless_ik) { + do_rot = true; + } else { - KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOC_ROT_SCALE_ID); - ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); + do_loc = true; + } + } + else if (ELEM(tmode, TFM_ROTATION, TFM_TRACKBALL)) { + if (ELEM(scene->toolsettings->transform_pivot_point, + V3D_AROUND_CURSOR, + V3D_AROUND_ACTIVE)) { + do_loc = true; } - /* free temp info */ - BLI_freelistN(&dsources); + if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) { + do_rot = true; + } } - } + else if (tmode == TFM_RESIZE) { + if (ELEM(scene->toolsettings->transform_pivot_point, + V3D_AROUND_CURSOR, + V3D_AROUND_ACTIVE)) { + do_loc = true; + } - BKE_animsys_free_nla_keyframing_context_cache(&nla_cache); - } - else { - /* tag channels that should have unkeyed data */ - for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { - if (pchan->bone->flag & BONE_TRANSFORM) { - /* tag this channel */ - pchan->bone->flag |= BONE_UNKEYED; + if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) { + do_scale = true; + } + } + + if (do_loc) { + KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID); + ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); + } + if (do_rot) { + KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID); + ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); + } + if (do_scale) { + KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_SCALING_ID); + ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); } } + /* insert keyframe in all (transform) channels */ + else { + KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOC_ROT_SCALE_ID); + ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); + } + + /* free temp info */ + BLI_freelistN(&dsources); } + + BKE_animsys_free_nla_keyframing_context_cache(&nla_cache); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Transform (After-Transform Update) + * \{ */ + /* Return if we need to update motion paths, only if they already exist, * and we will insert a keyframe at the end of transform. */ bool motionpath_need_update_pose(Scene *scene, Object *ob) @@ -2383,6 +2437,10 @@ int special_transform_moving(TransInfo *t) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Transform Data Create + * \{ */ + static int countAndCleanTransDataContainer(TransInfo *t) { BLI_assert(ELEM(t->data_len_all, 0, -1)); @@ -2777,3 +2835,5 @@ void createTransData(bContext *C, TransInfo *t) BLI_assert((!(t->flag & T_EDIT)) == (!(t->obedit_type != -1))); } + +/** \} */ diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c index 4e8e0cc2369..53dd54d4b53 100644 --- a/source/blender/editors/transform/transform_convert_armature.c +++ b/source/blender/editors/transform/transform_convert_armature.c @@ -530,6 +530,12 @@ void pose_transform_mirror_update(TransInfo *t, TransDataContainer *tc, Object * unit_m4(flip_mtx); flip_mtx[0][0] = -1; + for (bPoseChannel *pchan_orig = ob->pose->chanbase.first; pchan_orig; + pchan_orig = pchan_orig->next) { + /* Clear the MIRROR flag from previous runs. */ + pchan_orig->bone->flag &= ~BONE_TRANSFORM_MIRROR; + } + bPose *pose = ob->pose; PoseInitData_Mirror *pid = NULL; if ((t->mode != TFM_BONESIZE) && (pose->flag & POSE_MIRROR_RELATIVE)) { @@ -565,6 +571,9 @@ void pose_transform_mirror_update(TransInfo *t, TransDataContainer *tc, Object * } BKE_pchan_apply_mat4(pchan, pchan_mtx_final, false); + /* Set flag to let autokeyframe know to keyframe the mirrred bone. */ + pchan->bone->flag |= BONE_TRANSFORM_MIRROR; + /* In this case we can do target-less IK grabbing. */ if (t->mode == TFM_TRANSLATION) { bKinematicConstraint *data = has_targetless_ik(pchan); diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c index f6dc9b9c412..f2d0f4dfc43 100644 --- a/source/blender/editors/transform/transform_convert_sequencer.c +++ b/source/blender/editors/transform/transform_convert_sequencer.c @@ -47,7 +47,7 @@ * seq->depth must be set before running this function so we know if the strips * are root level or not */ -static void SeqTransInfo(TransInfo *t, Sequence *seq, int *recursive, int *count, int *flag) +static void SeqTransInfo(TransInfo *t, Sequence *seq, int *r_recursive, int *r_count, int *r_flag) { /* for extend we need to do some tricks */ if (t->mode == TFM_TIME_EXTEND) { @@ -60,51 +60,51 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *recursive, int *count int right = BKE_sequence_tx_get_final_right(seq, true); if (seq->depth == 0 && ((seq->flag & SELECT) == 0 || (seq->flag & SEQ_LOCK))) { - *recursive = false; - *count = 0; - *flag = 0; + *r_recursive = false; + *r_count = 0; + *r_flag = 0; } else if (seq->type == SEQ_TYPE_META) { /* for meta's we only ever need to extend their children, no matter what depth * just check the meta's are in the bounds */ if (t->frame_side == 'R' && right <= cfra) { - *recursive = false; + *r_recursive = false; } else if (t->frame_side == 'L' && left >= cfra) { - *recursive = false; + *r_recursive = false; } else { - *recursive = true; + *r_recursive = true; } - *count = 1; - *flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL); + *r_count = 1; + *r_flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL); } else { - *recursive = false; /* not a meta, so no thinking here */ - *count = 1; /* unless its set to 0, extend will never set 2 handles at once */ - *flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL); + *r_recursive = false; /* not a meta, so no thinking here */ + *r_count = 1; /* unless its set to 0, extend will never set 2 handles at once */ + *r_flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL); if (t->frame_side == 'R') { if (right <= cfra) { - *count = *flag = 0; + *r_count = *r_flag = 0; } /* ignore */ else if (left > cfra) { } /* keep the selection */ else { - *flag |= SEQ_RIGHTSEL; + *r_flag |= SEQ_RIGHTSEL; } } else { if (left >= cfra) { - *count = *flag = 0; + *r_count = *r_flag = 0; } /* ignore */ else if (right < cfra) { } /* keep the selection */ else { - *flag |= SEQ_LEFTSEL; + *r_flag |= SEQ_LEFTSEL; } } } @@ -121,28 +121,28 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *recursive, int *count /* Non nested strips (resect selection and handles) */ if ((seq->flag & SELECT) == 0 || (seq->flag & SEQ_LOCK)) { - *recursive = false; - *count = 0; - *flag = 0; + *r_recursive = false; + *r_count = 0; + *r_flag = 0; } else { if ((seq->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) == (SEQ_LEFTSEL | SEQ_RIGHTSEL)) { - *flag = seq->flag; - *count = 2; /* we need 2 transdata's */ + *r_flag = seq->flag; + *r_count = 2; /* we need 2 transdata's */ } else { - *flag = seq->flag; - *count = 1; /* selected or with a handle selected */ + *r_flag = seq->flag; + *r_count = 1; /* selected or with a handle selected */ } /* Recursive */ if ((seq->type == SEQ_TYPE_META) && ((seq->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) == 0)) { /* if any handles are selected, don't recurse */ - *recursive = true; + *r_recursive = true; } else { - *recursive = false; + *r_recursive = false; } } } @@ -150,23 +150,23 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *recursive, int *count /* Nested, different rules apply */ #ifdef SEQ_TX_NESTED_METAS - *flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL); - *count = 1; /* ignore the selection for nested */ - *recursive = (seq->type == SEQ_TYPE_META); + *r_flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL); + *r_count = 1; /* ignore the selection for nested */ + *r_recursive = (seq->type == SEQ_TYPE_META); #else if (seq->type == SEQ_TYPE_META) { /* Meta's can only directly be moved between channels since they * don't have their start and length set directly (children affect that) * since this Meta is nested we don't need any of its data in fact. * BKE_sequence_calc() will update its settings when run on the top-level meta. */ - *flag = 0; - *count = 0; - *recursive = true; + *r_flag = 0; + *r_count = 0; + *r_recursive = true; } else { - *flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL); - *count = 1; /* ignore the selection for nested */ - *recursive = false; + *r_flag = (seq->flag | SELECT) & ~(SEQ_LEFTSEL | SEQ_RIGHTSEL); + *r_count = 1; /* ignore the selection for nested */ + *r_recursive = false; } #endif } diff --git a/source/blender/editors/transform/transform_gizmo_2d.c b/source/blender/editors/transform/transform_gizmo_2d.c index dce2625e8a1..e85b9f0bee1 100644 --- a/source/blender/editors/transform/transform_gizmo_2d.c +++ b/source/blender/editors/transform/transform_gizmo_2d.c @@ -300,7 +300,7 @@ static void gizmo2d_xform_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup /* set up widget data */ RNA_float_set(gz->ptr, "length", 0.8f); float axis[3] = {0.0f}; - axis[(i + 1) % 2] = 1.0f; + axis[i] = 1.0f; WM_gizmo_set_matrix_rotation_from_z_axis(gz, axis); float offset[3] = {0, 0, 0}; @@ -336,8 +336,8 @@ static void gizmo2d_xform_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup /* Assign operator. */ PointerRNA *ptr = WM_gizmo_operator_set(gz, 0, ot_translate, NULL); if (i < 2) { - bool constraint[3] = {0}; - constraint[(i + 1) % 2] = 1; + bool constraint[3] = {false}; + constraint[i] = true; if (RNA_struct_find_property(ptr, "constraint_axis")) { RNA_boolean_set_array(ptr, "constraint_axis", constraint); } diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c index 75463dcb7db..078020e932e 100644 --- a/source/blender/editors/transform/transform_input.c +++ b/source/blender/editors/transform/transform_input.c @@ -35,13 +35,17 @@ #include "MEM_guardedalloc.h" -/* ************************** INPUT FROM MOUSE *************************** */ +/* -------------------------------------------------------------------- */ +/** \name Callbacks for #MouseInput.apply + * \{ */ +/** Callback for #INPUT_VECTOR */ static void InputVector(TransInfo *t, MouseInput *mi, const double mval[2], float output[3]) { convertViewVec(t, output, mval[0] - mi->imval[0], mval[1] - mi->imval[1]); } +/** Callback for #INPUT_SPRING */ static void InputSpring(TransInfo *UNUSED(t), MouseInput *mi, const double mval[2], @@ -57,6 +61,7 @@ static void InputSpring(TransInfo *UNUSED(t), output[0] = ratio; } +/** Callback for #INPUT_SPRING_FLIP */ static void InputSpringFlip(TransInfo *t, MouseInput *mi, const double mval[2], float output[3]) { InputSpring(t, mi, mval, output); @@ -70,12 +75,14 @@ static void InputSpringFlip(TransInfo *t, MouseInput *mi, const double mval[2], } } +/** Callback for #INPUT_SPRING_DELTA */ static void InputSpringDelta(TransInfo *t, MouseInput *mi, const double mval[2], float output[3]) { InputSpring(t, mi, mval, output); output[0] -= 1.0f; } +/** Callback for #INPUT_TRACKBALL */ static void InputTrackBall(TransInfo *UNUSED(t), MouseInput *mi, const double mval[2], @@ -88,6 +95,7 @@ static void InputTrackBall(TransInfo *UNUSED(t), output[1] *= mi->factor; } +/** Callback for #INPUT_HORIZONTAL_RATIO */ static void InputHorizontalRatio(TransInfo *t, MouseInput *mi, const double mval[2], @@ -98,6 +106,7 @@ static void InputHorizontalRatio(TransInfo *t, output[0] = ((mval[0] - mi->imval[0]) / winx) * 2.0f; } +/** Callback for #INPUT_HORIZONTAL_ABSOLUTE */ static void InputHorizontalAbsolute(TransInfo *t, MouseInput *mi, const double mval[2], @@ -119,6 +128,7 @@ static void InputVerticalRatio(TransInfo *t, MouseInput *mi, const double mval[2 output[0] = ((mval[1] - mi->imval[1]) / winy) * -2.0f; } +/** Callback for #INPUT_VERTICAL_ABSOLUTE */ static void InputVerticalAbsolute(TransInfo *t, MouseInput *mi, const double mval[2], @@ -133,38 +143,7 @@ static void InputVerticalAbsolute(TransInfo *t, output[0] = dot_v3v3(t->viewinv[1], vec) * -2.0f; } -void setCustomPoints(TransInfo *UNUSED(t), - MouseInput *mi, - const int mval_start[2], - const int mval_end[2]) -{ - int *data; - - mi->data = MEM_reallocN(mi->data, sizeof(int) * 4); - - data = mi->data; - - data[0] = mval_start[0]; - data[1] = mval_start[1]; - data[2] = mval_end[0]; - data[3] = mval_end[1]; -} - -void setCustomPointsFromDirection(TransInfo *t, MouseInput *mi, const float dir[2]) -{ - BLI_ASSERT_UNIT_V2(dir); - const int win_axis = t->region ? ((abs((int)(t->region->winx * dir[0])) + - abs((int)(t->region->winy * dir[1]))) / - 2) : - 1; - const int mval_start[2] = { - mi->imval[0] + dir[0] * win_axis, - mi->imval[1] + dir[1] * win_axis, - }; - const int mval_end[2] = {mi->imval[0], mi->imval[1]}; - setCustomPoints(t, mi, mval_start, mval_end); -} - +/** Callback for #INPUT_CUSTOM_RATIO_FLIP */ static void InputCustomRatioFlip(TransInfo *UNUSED(t), MouseInput *mi, const double mval[2], @@ -191,6 +170,7 @@ static void InputCustomRatioFlip(TransInfo *UNUSED(t), } } +/** Callback for #INPUT_CUSTOM_RATIO */ static void InputCustomRatio(TransInfo *t, MouseInput *mi, const double mval[2], float output[3]) { InputCustomRatioFlip(t, mi, mval, output); @@ -202,6 +182,7 @@ struct InputAngle_Data { double mval_prev[2]; }; +/** Callback for #INPUT_ANGLE */ static void InputAngle(TransInfo *UNUSED(t), MouseInput *mi, const double mval[2], float output[3]) { struct InputAngle_Data *data = mi->data; @@ -270,6 +251,53 @@ static void InputAngleSpring(TransInfo *t, MouseInput *mi, const double mval[2], output[1] = toutput[0]; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Custom 2D Start/End Coordinate API + * + * - #INPUT_CUSTOM_RATIO + * - #INPUT_CUSTOM_RATIO_FLIP + * \{ */ + +void setCustomPoints(TransInfo *UNUSED(t), + MouseInput *mi, + const int mval_start[2], + const int mval_end[2]) +{ + int *data; + + mi->data = MEM_reallocN(mi->data, sizeof(int) * 4); + + data = mi->data; + + data[0] = mval_start[0]; + data[1] = mval_start[1]; + data[2] = mval_end[0]; + data[3] = mval_end[1]; +} + +void setCustomPointsFromDirection(TransInfo *t, MouseInput *mi, const float dir[2]) +{ + BLI_ASSERT_UNIT_V2(dir); + const int win_axis = t->region ? ((abs((int)(t->region->winx * dir[0])) + + abs((int)(t->region->winy * dir[1]))) / + 2) : + 1; + const int mval_start[2] = { + mi->imval[0] + dir[0] * win_axis, + mi->imval[1] + dir[1] * win_axis, + }; + const int mval_end[2] = {mi->imval[0], mi->imval[1]}; + setCustomPoints(t, mi, mval_start, mval_end); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Setup & Handle Mouse Input + * \{ */ + void initMouseInput(TransInfo *UNUSED(t), MouseInput *mi, const float center[2], @@ -494,3 +522,5 @@ eRedrawFlag handleMouseInput(TransInfo *t, MouseInput *mi, const wmEvent *event) return redraw; } + +/** \} */ diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c index 326fb791de3..31aae4f5b05 100644 --- a/source/blender/editors/transform/transform_mode.c +++ b/source/blender/editors/transform/transform_mode.c @@ -61,7 +61,9 @@ bool transdata_check_local_center(TransInfo *t, short around) (t->options & (CTX_MOVIECLIP | CTX_MASK | CTX_PAINT_CURVE)))); } -/* ************************** TRANSFORM LOCKS **************************** */ +/* -------------------------------------------------------------------- */ +/** \name Transform Locks + * \{ */ void protectedTransBits(short protectflag, float vec[3]) { @@ -211,7 +213,11 @@ static void protectedSizeBits(short protectflag, float size[3]) } } -/* ******************* TRANSFORM LIMITS ********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Transform Limits + * \{ */ void constraintTransLim(TransInfo *t, TransData *td) { @@ -1104,9 +1110,7 @@ void doAnimEdit_SnapFrame( /** \} */ /* -------------------------------------------------------------------- */ -/* Transform Mode API */ - -/** \name Transform Frame Utils +/** \name Transform Mode Initialization * \{ */ void transform_mode_init(TransInfo *t, wmOperator *op, const int mode) diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index aaf7fbc3108..7e56b34af2f 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -1031,7 +1031,7 @@ static void TRANSFORM_OT_bbone_resize(struct wmOperatorType *ot) ot->exec = transform_exec; ot->modal = transform_modal; ot->cancel = transform_cancel; - ot->poll = ED_operator_screenactive; + ot->poll = ED_operator_editarmature; ot->poll_property = transform_poll_property; RNA_def_float_translation( diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c index 3c0d0beebe3..be1319c37dd 100644 --- a/source/blender/editors/util/numinput.c +++ b/source/blender/editors/util/numinput.c @@ -340,6 +340,21 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event) } } +#ifdef USE_FAKE_EDIT + /* XXX Hack around keyboards without direct access to '=' nor '*'... */ + if (ELEM(event->ascii, '=', '*')) { + if (!(n->flag & NUM_EDIT_FULL)) { + n->flag |= NUM_EDIT_FULL; + n->val_flag[idx] |= NUM_EDITED; + return true; + } + else if (event->ctrl) { + n->flag &= ~NUM_EDIT_FULL; + return true; + } + } +#endif + switch (event->type) { case EVT_MODAL_MAP: if (ELEM(event->val, NUM_MODAL_INCREMENT_UP, NUM_MODAL_INCREMENT_DOWN)) { @@ -523,21 +538,6 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event) ascii[0] = event->ascii; } -#ifdef USE_FAKE_EDIT - /* XXX Hack around keyboards without direct access to '=' nor '*'... */ - if (ELEM(ascii[0], '=', '*')) { - if (!(n->flag & NUM_EDIT_FULL)) { - n->flag |= NUM_EDIT_FULL; - n->val_flag[idx] |= NUM_EDITED; - return true; - } - else if (event->ctrl) { - n->flag &= ~NUM_EDIT_FULL; - return true; - } - } -#endif - /* Up to this point, if we have a ctrl modifier, skip. * This allows to still access most of modals' shortcuts even in numinput mode. */ diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index e3504e20464..1e576f6fea4 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -478,9 +478,9 @@ static void draw_uvs(SpaceImage *sima, } static void draw_uv_shadows_get( - SpaceImage *sima, Object *ob, Object *obedit, bool *show_shadow, bool *show_texpaint) + SpaceImage *sima, Object *ob, Object *obedit, bool *r_show_shadow, bool *r_show_texpaint) { - *show_shadow = *show_texpaint = false; + *r_show_shadow = *r_show_texpaint = false; if (ED_space_image_show_render(sima) || (sima->flag & SI_NO_DRAW_TEXPAINT)) { return; @@ -489,10 +489,10 @@ static void draw_uv_shadows_get( if ((sima->mode == SI_MODE_PAINT) && obedit && obedit->type == OB_MESH) { struct BMEditMesh *em = BKE_editmesh_from_object(obedit); - *show_shadow = EDBM_uv_check(em); + *r_show_shadow = EDBM_uv_check(em); } - *show_texpaint = (ob && ob->type == OB_MESH && ob->mode == OB_MODE_TEXTURE_PAINT); + *r_show_texpaint = (ob && ob->type == OB_MESH && ob->mode == OB_MODE_TEXTURE_PAINT); } void ED_uvedit_draw_main(SpaceImage *sima, diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c index 5a36c83b62e..936ba750266 100644 --- a/source/blender/editors/uvedit/uvedit_parametrizer.c +++ b/source/blender/editors/uvedit/uvedit_parametrizer.c @@ -347,7 +347,7 @@ static PHashLink *phash_next(PHash *ph, PHashKey key, PHashLink *link) /* Geometry */ -static float p_vec_angle_cos(float *v1, float *v2, float *v3) +static float p_vec_angle_cos(const float v1[3], const float v2[3], const float v3[3]) { float d1[3], d2[3]; @@ -365,7 +365,7 @@ static float p_vec_angle_cos(float *v1, float *v2, float *v3) return d1[0] * d2[0] + d1[1] * d2[1] + d1[2] * d2[2]; } -static float p_vec_angle(float *v1, float *v2, float *v3) +static float p_vec_angle(const float v1[3], const float v2[3], const float v3[3]) { float dot = p_vec_angle_cos(v1, v2, v3); @@ -380,7 +380,7 @@ static float p_vec_angle(float *v1, float *v2, float *v3) } } -static float p_vec2_angle(float *v1, float *v2, float *v3) +static float p_vec2_angle(const float v1[2], const float v2[2], const float v3[2]) { float u1[3], u2[3], u3[3]; @@ -397,19 +397,20 @@ static float p_vec2_angle(float *v1, float *v2, float *v3) return p_vec_angle(u1, u2, u3); } -static void p_triangle_angles(float *v1, float *v2, float *v3, float *a1, float *a2, float *a3) +static void p_triangle_angles( + const float v1[3], const float v2[3], const float v3[3], float *r_a1, float *r_a2, float *r_a3) { - *a1 = p_vec_angle(v3, v1, v2); - *a2 = p_vec_angle(v1, v2, v3); - *a3 = (float)M_PI - *a2 - *a1; + *r_a1 = p_vec_angle(v3, v1, v2); + *r_a2 = p_vec_angle(v1, v2, v3); + *r_a3 = (float)M_PI - *r_a2 - *r_a1; } -static void p_face_angles(PFace *f, float *a1, float *a2, float *a3) +static void p_face_angles(PFace *f, float *r_a1, float *r_a2, float *r_a3) { PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next; PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert; - p_triangle_angles(v1->co, v2->co, v3->co, a1, a2, a3); + p_triangle_angles(v1->co, v2->co, v3->co, r_a1, r_a2, r_a3); } static float p_face_area(PFace *f) @@ -420,7 +421,7 @@ static float p_face_area(PFace *f) return area_tri_v3(v1->co, v2->co, v3->co); } -static float p_area_signed(float *v1, float *v2, float *v3) +static float p_area_signed(const float v1[2], const float v2[2], const float v3[2]) { return 0.5f * (((v2[0] - v1[0]) * (v3[1] - v1[1])) - ((v3[0] - v1[0]) * (v2[1] - v1[1]))); } @@ -527,7 +528,11 @@ static void UNUSED_FUNCTION(p_chart_uv_from_array)(PChart *chart, float (*points } } -static PBool p_intersect_line_2d_dir(float *v1, float *dir1, float *v2, float *dir2, float *isect) +static PBool p_intersect_line_2d_dir(const float v1[2], + const float dir1[2], + const float v2[2], + const float dir2[2], + float r_isect[2]) { float lmbda, div; @@ -538,14 +543,18 @@ static PBool p_intersect_line_2d_dir(float *v1, float *dir1, float *v2, float *d } lmbda = ((v1[1] - v2[1]) * dir1[0] - (v1[0] - v2[0]) * dir1[1]) / div; - isect[0] = v1[0] + lmbda * dir2[0]; - isect[1] = v1[1] + lmbda * dir2[1]; + r_isect[0] = v1[0] + lmbda * dir2[0]; + r_isect[1] = v1[1] + lmbda * dir2[1]; return P_TRUE; } #if 0 -static PBool p_intersect_line_2d(float *v1, float *v2, float *v3, float *v4, float *isect) +static PBool p_intersect_line_2d(const float v1[2], + const float v2[2], + const float v3[2], + const float v4[2], + const float r_isect[2]) { float dir1[2], dir2[2]; @@ -892,7 +901,7 @@ static PBool p_edge_implicit_seam(PEdge *e, PEdge *ep) return P_FALSE; } -static PBool p_edge_has_pair(PHandle *handle, PEdge *e, PEdge **pair, PBool impl) +static PBool p_edge_has_pair(PHandle *handle, PEdge *e, PBool impl, PEdge **r_pair) { PHashKey key; PEdge *pe; @@ -906,7 +915,7 @@ static PBool p_edge_has_pair(PHandle *handle, PEdge *e, PEdge **pair, PBool impl key = PHASH_edge(key1, key2); pe = (PEdge *)phash_lookup(handle->hash_edges, key); - *pair = NULL; + *r_pair = NULL; while (pe) { if (pe != e) { @@ -917,34 +926,34 @@ static PBool p_edge_has_pair(PHandle *handle, PEdge *e, PEdge **pair, PBool impl ((v1->u.key == key2) && (v2->u.key == key1))) { /* don't connect seams and t-junctions */ - if ((pe->flag & PEDGE_SEAM) || *pair || (impl && p_edge_implicit_seam(e, pe))) { - *pair = NULL; + if ((pe->flag & PEDGE_SEAM) || *r_pair || (impl && p_edge_implicit_seam(e, pe))) { + *r_pair = NULL; return P_FALSE; } - *pair = pe; + *r_pair = pe; } } pe = (PEdge *)phash_next(handle->hash_edges, key, (PHashLink *)pe); } - if (*pair && (e->vert == (*pair)->vert)) { - if ((*pair)->next->pair || (*pair)->next->next->pair) { + if (*r_pair && (e->vert == (*r_pair)->vert)) { + if ((*r_pair)->next->pair || (*r_pair)->next->next->pair) { /* non unfoldable, maybe mobius ring or klein bottle */ - *pair = NULL; + *r_pair = NULL; return P_FALSE; } } - return (*pair != NULL); + return (*r_pair != NULL); } -static PBool p_edge_connect_pair(PHandle *handle, PEdge *e, PEdge ***stack, PBool impl) +static PBool p_edge_connect_pair(PHandle *handle, PEdge *e, PBool impl, PEdge ***stack) { PEdge *pair = NULL; - if (!e->pair && p_edge_has_pair(handle, e, &pair, impl)) { + if (!e->pair && p_edge_has_pair(handle, e, impl, &pair)) { if (e->vert == pair->vert) { p_face_flip(pair->face); } @@ -992,13 +1001,13 @@ static int p_connect_pairs(PHandle *handle, PBool impl) /* assign verts to charts so we can sort them later */ f->u.chart = ncharts; - if (!p_edge_connect_pair(handle, e, &stack, impl)) { + if (!p_edge_connect_pair(handle, e, impl, &stack)) { e->vert->edge = e; } - if (!p_edge_connect_pair(handle, e1, &stack, impl)) { + if (!p_edge_connect_pair(handle, e1, impl, &stack)) { e1->vert->edge = e1; } - if (!p_edge_connect_pair(handle, e2, &stack, impl)) { + if (!p_edge_connect_pair(handle, e2, impl, &stack)) { e2->vert->edge = e2; } } @@ -1255,16 +1264,16 @@ static PBool p_quad_split_direction(PHandle *handle, float **co, PHashKey *vkeys /* Construction: boundary filling */ -static void p_chart_boundaries(PChart *chart, int *nboundaries, PEdge **outer) +static void p_chart_boundaries(PChart *chart, int *r_nboundaries, PEdge **r_outer) { PEdge *e, *be; float len, maxlen = -1.0; - if (nboundaries) { - *nboundaries = 0; + if (r_nboundaries) { + *r_nboundaries = 0; } - if (outer) { - *outer = NULL; + if (r_outer) { + *r_outer = NULL; } for (e = chart->edges; e; e = e->nextlink) { @@ -1272,8 +1281,8 @@ static void p_chart_boundaries(PChart *chart, int *nboundaries, PEdge **outer) continue; } - if (nboundaries) { - (*nboundaries)++; + if (r_nboundaries) { + (*r_nboundaries)++; } len = 0.0f; @@ -1285,8 +1294,8 @@ static void p_chart_boundaries(PChart *chart, int *nboundaries, PEdge **outer) be = be->next->vert->edge; } while (be != e); - if (outer && (len > maxlen)) { - *outer = e; + if (r_outer && (len > maxlen)) { + *r_outer = e; maxlen = len; } } @@ -1427,7 +1436,7 @@ static void p_chart_fill_boundaries(PChart *chart, PEdge *outer) #if 0 /* Polygon kernel for inserting uv's non overlapping */ -static int p_polygon_point_in(float *cp1, float *cp2, float *p) +static int p_polygon_point_in(const float cp1[2], const float cp2[2], const float p[2]) { if ((cp1[0] == p[0]) && (cp1[1] == p[1])) { return 2; @@ -1443,43 +1452,43 @@ static int p_polygon_point_in(float *cp1, float *cp2, float *p) static void p_polygon_kernel_clip(float (*oldpoints)[2], int noldpoints, float (*newpoints)[2], - int *nnewpoints, - float *cp1, - float *cp2) + int *r_nnewpoints, + const float cp1[2], + const float cp2[2]) { float *p2, *p1, isect[2]; int i, p2in, p1in; p1 = oldpoints[noldpoints - 1]; p1in = p_polygon_point_in(cp1, cp2, p1); - *nnewpoints = 0; + *r_nnewpoints = 0; for (i = 0; i < noldpoints; i++) { p2 = oldpoints[i]; p2in = p_polygon_point_in(cp1, cp2, p2); if ((p2in >= 2) || (p1in && p2in)) { - newpoints[*nnewpoints][0] = p2[0]; - newpoints[*nnewpoints][1] = p2[1]; - (*nnewpoints)++; + newpoints[*r_nnewpoints][0] = p2[0]; + newpoints[*r_nnewpoints][1] = p2[1]; + (*r_nnewpoints)++; } else if (p1in && !p2in) { if (p1in != 3) { p_intersect_line_2d(p1, p2, cp1, cp2, isect); - newpoints[*nnewpoints][0] = isect[0]; - newpoints[*nnewpoints][1] = isect[1]; - (*nnewpoints)++; + newpoints[*r_nnewpoints][0] = isect[0]; + newpoints[*r_nnewpoints][1] = isect[1]; + (*r_nnewpoints)++; } } else if (!p1in && p2in) { p_intersect_line_2d(p1, p2, cp1, cp2, isect); - newpoints[*nnewpoints][0] = isect[0]; - newpoints[*nnewpoints][1] = isect[1]; - (*nnewpoints)++; + newpoints[*r_nnewpoints][0] = isect[0]; + newpoints[*r_nnewpoints][1] = isect[1]; + (*r_nnewpoints)++; - newpoints[*nnewpoints][0] = p2[0]; - newpoints[*nnewpoints][1] = p2[1]; - (*nnewpoints)++; + newpoints[*r_nnewpoints][0] = p2[0]; + newpoints[*r_nnewpoints][1] = p2[1]; + (*r_nnewpoints)++; } p1in = p2in; @@ -1556,7 +1565,7 @@ static void p_polygon_kernel_center(float (*points)[2], int npoints, float *cent int NCOLLAPSE = 1; int NCOLLAPSEX = 0; -static float p_vert_cotan(float *v1, float *v2, float *v3) +static float p_vert_cotan(const float v1[3], const float v2[3], const float v3[3]) { float a[3], b[3], c[3], clen; @@ -1733,16 +1742,16 @@ static void p_vert_fix_edge_pointer(PVert *v) } } -static void p_collapsing_verts(PEdge *edge, PEdge *pair, PVert **newv, PVert **keepv) +static void p_collapsing_verts(PEdge *edge, PEdge *pair, PVert **r_newv, PVert **r_keepv) { /* the two vertices that are involved in the collapse */ if (edge) { - *newv = edge->vert; - *keepv = edge->next->vert; + *r_newv = edge->vert; + *r_keepv = edge->next->vert; } else { - *newv = pair->next->vert; - *keepv = pair->vert; + *r_newv = pair->next->vert; + *r_keepv = pair->vert; } } @@ -2107,20 +2116,20 @@ static float p_collapse_cost(PEdge *edge, PEdge *pair) return cost; } -static void p_collapse_cost_vertex(PVert *vert, float *mincost, PEdge **mine) +static void p_collapse_cost_vertex(PVert *vert, float *r_mincost, PEdge **r_mine) { PEdge *e, *enext, *pair; - *mine = NULL; - *mincost = 0.0f; + *r_mine = NULL; + *r_mincost = 0.0f; e = vert->edge; do { if (p_collapse_allowed(e, e->pair)) { float cost = p_collapse_cost(e, e->pair); - if ((*mine == NULL) || (cost < *mincost)) { - *mincost = cost; - *mine = e; + if ((*r_mine == NULL) || (cost < *r_mincost)) { + *r_mincost = cost; + *r_mine = e; } } @@ -2133,9 +2142,9 @@ static void p_collapse_cost_vertex(PVert *vert, float *mincost, PEdge **mine) if (p_collapse_allowed(NULL, pair)) { float cost = p_collapse_cost(NULL, pair); - if ((*mine == NULL) || (cost < *mincost)) { - *mincost = cost; - *mine = pair; + if ((*r_mine == NULL) || (cost < *r_mincost)) { + *r_mincost = cost; + *r_mine = pair; } } @@ -3549,7 +3558,7 @@ static int p_compare_geometric_uv(const void *a, const void *b) } } -static PBool p_chart_convex_hull(PChart *chart, PVert ***verts, int *nverts, int *right) +static PBool p_chart_convex_hull(PChart *chart, PVert ***r_verts, int *r_nverts, int *r_right) { /* Graham algorithm, taken from: * http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/117225 */ @@ -3608,9 +3617,9 @@ static PBool p_chart_convex_hull(PChart *chart, PVert ***verts, int *nverts, int *p = L[i]; } - *verts = points; - *nverts = npoints; - *right = ulen - 1; + *r_verts = points; + *r_nverts = npoints; + *r_right = ulen - 1; MEM_freeN(U); MEM_freeN(L); diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index 84d38a88902..8ded2c16be8 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -77,6 +77,10 @@ #include "uvedit_intern.h" #include "uvedit_parametrizer.h" +/* -------------------------------------------------------------------- */ +/** \name Utility Functions + * \{ */ + static void modifier_unwrap_state(Object *obedit, const Scene *scene, bool *r_use_subsurf) { ModifierData *md; @@ -133,13 +137,21 @@ static bool ED_uvedit_ensure_uvs(Object *obedit) return 1; } -/****************** Parametrizer Conversion ***************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Parametrizer Conversion + * \{ */ typedef struct UnwrapOptions { - bool topology_from_uvs; /* Connectivity based on UV coordinates instead of seams. */ - bool only_selected; /* Only affect selected faces. */ - bool fill_holes; /* Fill holes to better preserve shape. */ - bool correct_aspect; /* Correct for mapped image texture aspect ratio. */ + /** Connectivity based on UV coordinates instead of seams. */ + bool topology_from_uvs; + /** Only affect selected faces. */ + bool only_selected; + /** Fill holes to better preserve shape. */ + bool fill_holes; + /** Correct for mapped image texture aspect ratio. */ + bool correct_aspect; } UnwrapOptions; static bool uvedit_have_selection(const Scene *scene, BMEditMesh *em, const UnwrapOptions *options) @@ -199,7 +211,7 @@ static bool uvedit_have_selection_multi(const Scene *scene, } void ED_uvedit_get_aspect( - const Scene *UNUSED(scene), Object *ob, BMesh *bm, float *aspx, float *aspy) + const Scene *UNUSED(scene), Object *ob, BMesh *bm, float *r_aspx, float *r_aspy) { bool sloppy = true; bool selected = false; @@ -211,11 +223,11 @@ void ED_uvedit_get_aspect( if (efa) { ED_object_get_active_image(ob, efa->mat_nr + 1, &ima, NULL, NULL, NULL); - ED_image_get_uv_aspect(ima, NULL, aspx, aspy); + ED_image_get_uv_aspect(ima, NULL, r_aspx, r_aspy); } else { - *aspx = 1.0f; - *aspy = 1.0f; + *r_aspx = 1.0f; + *r_aspy = 1.0f; } } @@ -410,21 +422,21 @@ static ParamHandle *construct_param_handle_multi(const Scene *scene, return handle; } -static void texface_from_original_index(BMFace *efa, +static void texface_from_original_index(const Scene *scene, + const int cd_loop_uv_offset, + BMFace *efa, int index, - float **uv, - ParamBool *pin, - ParamBool *select, - const Scene *scene, - const int cd_loop_uv_offset) + float **r_uv, + ParamBool *r_pin, + ParamBool *r_select) { BMLoop *l; BMIter liter; MLoopUV *luv; - *uv = NULL; - *pin = 0; - *select = 1; + *r_uv = NULL; + *r_pin = 0; + *r_select = 1; if (index == ORIGINDEX_NONE) { return; @@ -433,9 +445,9 @@ static void texface_from_original_index(BMFace *efa, BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { if (BM_elem_index_get(l->v) == index) { luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - *uv = luv->uv; - *pin = (luv->flag & MLOOPUV_PINNED) ? 1 : 0; - *select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset); + *r_uv = luv->uv; + *r_pin = (luv->flag & MLOOPUV_PINNED) ? 1 : 0; + *r_select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset); break; } } @@ -583,34 +595,34 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene, /* This is where all the magic is done. * If the vertex exists in the, we pass the original uv pointer to the solver, thus * flushing the solution to the edit mesh. */ - texface_from_original_index(origFace, + texface_from_original_index(scene, + cd_loop_uv_offset, + origFace, origVertIndices[mloop[0].v], &uv[0], &pin[0], - &select[0], - scene, - cd_loop_uv_offset); - texface_from_original_index(origFace, + &select[0]); + texface_from_original_index(scene, + cd_loop_uv_offset, + origFace, origVertIndices[mloop[1].v], &uv[1], &pin[1], - &select[1], - scene, - cd_loop_uv_offset); - texface_from_original_index(origFace, + &select[1]); + texface_from_original_index(scene, + cd_loop_uv_offset, + origFace, origVertIndices[mloop[2].v], &uv[2], &pin[2], - &select[2], - scene, - cd_loop_uv_offset); - texface_from_original_index(origFace, + &select[2]); + texface_from_original_index(scene, + cd_loop_uv_offset, + origFace, origVertIndices[mloop[3].v], &uv[3], &pin[3], - &select[3], - scene, - cd_loop_uv_offset); + &select[3]); param_face_add(handle, key, 4, vkeys, co, uv, pin, select); } @@ -635,7 +647,11 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene, return handle; } -/* ******************** Minimize Stretch operator **************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Minimize Stretch Operator + * \{ */ typedef struct MinStretch { const Scene *scene; @@ -908,7 +924,11 @@ void UV_OT_minimize_stretch(wmOperatorType *ot) 100); } -/* ******************** Pack Islands operator **************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Pack UV Islands Operator + * \{ */ static void uvedit_pack_islands(const Scene *scene, Object *ob, BMesh *bm) { @@ -1006,7 +1026,11 @@ void UV_OT_pack_islands(wmOperatorType *ot) ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f); } -/* ******************** Average Islands Scale operator **************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Average UV Islands Scale Operator + * \{ */ static int average_islands_scale_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -1065,7 +1089,11 @@ void UV_OT_average_islands_scale(wmOperatorType *ot) ot->poll = ED_operator_uvedit; } -/**************** Live Unwrap *****************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Live UV Unwrap + * \{ */ static struct { ParamHandle **handles; @@ -1144,7 +1172,11 @@ void ED_uvedit_live_unwrap_end(short cancel) } } -/*************** UV Map Common Transforms *****************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name UV Map Common Transforms + * \{ */ #define VIEW_ON_EQUATOR 0 #define VIEW_ON_POLES 1 @@ -1427,7 +1459,18 @@ static void correct_uv_aspect(const Scene *scene, Object *ob, BMEditMesh *em) } } -/******************** Map Clip & Correct ******************/ +#undef VIEW_ON_EQUATOR +#undef VIEW_ON_POLES +#undef ALIGN_TO_OBJECT + +#undef POLAR_ZX +#undef POLAR_ZY + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name UV Map Clip & Correct + * \{ */ static void uv_map_clip_correct_properties(wmOperatorType *ot) { @@ -1542,7 +1585,11 @@ static void uv_map_clip_correct(const Scene *scene, Object *ob, wmOperator *op) uv_map_clip_correct_multi(scene, &ob, 1, op); } -/* ******************** Unwrap operator **************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name UV Unwrap Operator + * \{ */ /* Assumes UV Map exists, doesn't run update funcs. */ static void uvedit_unwrap(const Scene *scene, Object *obedit, const UnwrapOptions *options) @@ -1783,7 +1830,12 @@ void UV_OT_unwrap(wmOperatorType *ot) ot->srna, "margin", 0.001f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f); } -/**************** Project From View operator **************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Project UV From View Operator + * \{ */ + static int uv_from_view_exec(bContext *C, wmOperator *op); static int uv_from_view_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) @@ -1969,7 +2021,11 @@ void UV_OT_project_from_view(wmOperatorType *ot) uv_map_clip_correct_properties(ot); } -/********************** Reset operator ********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Reset UV Operator + * \{ */ static int reset_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -2017,7 +2073,11 @@ void UV_OT_reset(wmOperatorType *ot) ot->poll = ED_operator_uvmap; } -/****************** Sphere Project operator ***************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Sphere UV Project Operator + * \{ */ static void uv_sphere_project(float target[2], const float source[3], @@ -2144,7 +2204,11 @@ void UV_OT_sphere_project(wmOperatorType *ot) uv_map_clip_correct_properties(ot); } -/***************** Cylinder Project operator **************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Cylinder UV Project Operator + * \{ */ static void uv_cylinder_project(float target[2], const float source[3], @@ -2238,7 +2302,9 @@ void UV_OT_cylinder_project(wmOperatorType *ot) uv_map_clip_correct_properties(ot); } -/******************* Cube Project operator ****************/ +/* -------------------------------------------------------------------- */ +/** \name Cube UV Project Operator + * \{ */ static void uvedit_unwrap_cube_project(BMesh *bm, float cube_size, @@ -2367,7 +2433,11 @@ void UV_OT_cube_project(wmOperatorType *ot) uv_map_clip_correct_properties(ot); } -/************************* Simple UVs for texture painting *****************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Simple UVs for Texture Painting + * \{ */ void ED_uvedit_add_simple_uvs(Main *bmain, const Scene *scene, Object *ob) { @@ -2403,3 +2473,5 @@ void ED_uvedit_add_simple_uvs(Main *bmain, const Scene *scene, Object *ob) scene->toolsettings->uv_flag |= UV_SYNC_SELECTION; } } + +/** \} */ diff --git a/source/blender/freestyle/FRS_freestyle.h b/source/blender/freestyle/FRS_freestyle.h index dc8a0c79072..876f40b211f 100644 --- a/source/blender/freestyle/FRS_freestyle.h +++ b/source/blender/freestyle/FRS_freestyle.h @@ -48,9 +48,7 @@ void FRS_set_context(struct bContext *C); int FRS_is_freestyle_enabled(struct ViewLayer *view_layer); void FRS_init_stroke_renderer(struct Render *re); void FRS_begin_stroke_rendering(struct Render *re); -struct Render *FRS_do_stroke_rendering(struct Render *re, - struct ViewLayer *view_layer, - int render); +void FRS_do_stroke_rendering(struct Render *re, struct ViewLayer *view_layer); void FRS_end_stroke_rendering(struct Render *re); void FRS_free_view_map_cache(void); void FRS_composite_result(struct Render *re, diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp index c88d5f24b5d..a61bad7cf8a 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -32,19 +32,19 @@ extern "C" { #include "DNA_camera_types.h" #include "DNA_collection_types.h" -#include "DNA_listBase.h" #include "DNA_linestyle_types.h" +#include "DNA_listBase.h" #include "DNA_material_types.h" -#include "DNA_meshdata_types.h" #include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" #include "DNA_object_types.h" -#include "DNA_screen_types.h" #include "DNA_scene_types.h" +#include "DNA_screen_types.h" #include "BKE_collection.h" #include "BKE_customdata.h" -#include "BKE_idprop.h" #include "BKE_global.h" +#include "BKE_idprop.h" #include "BKE_layer.h" #include "BKE_lib_id.h" /* free_libblock */ #include "BKE_material.h" @@ -76,7 +76,16 @@ const char *BlenderStrokeRenderer::uvNames[] = {"along_stroke", "along_stroke_ti BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : StrokeRenderer() { - freestyle_bmain = re->freestyle_bmain; + freestyle_bmain = BKE_main_new(); + + /* We use the same window manager for freestyle bmain as + * real bmain uses. This is needed because freestyle's + * bmain could be used to tag scenes for update, which + * implies call of ED_render_scene_update in some cases + * and that function requires proper window manager + * to present (sergey) + */ + freestyle_bmain->wm = re->main->wm; // for stroke mesh generation _width = re->winx; @@ -170,50 +179,18 @@ BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : Str BlenderStrokeRenderer::~BlenderStrokeRenderer() { - // The freestyle_scene object is not released here. Instead, - // the scene is released in free_all_freestyle_renders() in - // source/blender/render/intern/source/pipeline.c, after the - // compositor has finished. - - // release objects and data blocks - Base *base_next = NULL; - ViewLayer *view_layer = (ViewLayer *)freestyle_scene->view_layers.first; - for (Base *b = (Base *)view_layer->object_bases.first; b; b = base_next) { - base_next = b->next; - Object *ob = b->object; - char *name = ob->id.name; -#if 0 - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "removing " << name[0] << name[1] << ":" << (name + 2) << endl; - } -#endif - switch (ob->type) { - case OB_CAMERA: - freestyle_scene->camera = NULL; - ATTR_FALLTHROUGH; - case OB_MESH: - BKE_scene_collections_object_remove(freestyle_bmain, freestyle_scene, ob, true); - break; - default: - cerr << "Warning: unexpected object in the scene: " << name[0] << name[1] << ":" - << (name + 2) << endl; - } - } - - // release materials - Link *lnk = (Link *)freestyle_bmain->materials.first; - - while (lnk) { - Material *ma = (Material *)lnk; - lnk = lnk->next; - BKE_id_free(freestyle_bmain, ma); - } - BLI_ghash_free(_nodetree_hash, NULL, NULL); DEG_graph_free(freestyle_depsgraph); FreeStrokeGroups(); + + /* detach the window manager from freestyle bmain (see comments + * in add_freestyle() for more detail) + */ + BLI_listbase_clear(&freestyle_bmain->wm); + + BKE_main_free(freestyle_bmain); } float BlenderStrokeRenderer::get_stroke_vertex_z(void) const diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp index 0877107a240..0f4263162a6 100644 --- a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp +++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp @@ -637,14 +637,8 @@ void FRS_begin_stroke_rendering(Render *re) init_camera(re); } -Render *FRS_do_stroke_rendering(Render *re, ViewLayer *view_layer, int render) +void FRS_do_stroke_rendering(Render *re, ViewLayer *view_layer) { - Render *freestyle_render = NULL; - - if (!render) { - return controller->RenderStrokes(re, false); - } - RenderMonitor monitor(re); controller->setRenderMonitor(&monitor); controller->setViewMapCache( @@ -685,6 +679,7 @@ Render *FRS_do_stroke_rendering(Render *re, ViewLayer *view_layer, int render) re->i.infostr = NULL; g_freestyle.scene = DEG_get_evaluated_scene(depsgraph); int strokeCount = controller->DrawStrokes(); + Render *freestyle_render = NULL; if (strokeCount > 0) { freestyle_render = controller->RenderStrokes(re, true); } @@ -694,15 +689,12 @@ Render *FRS_do_stroke_rendering(Render *re, ViewLayer *view_layer, int render) // composite result if (freestyle_render) { FRS_composite_result(re, view_layer, freestyle_render); - RE_FreeRenderResult(freestyle_render->result); - freestyle_render->result = NULL; + RE_FreeRender(freestyle_render); } } } DEG_graph_free(depsgraph); - - return freestyle_render; } void FRS_end_stroke_rendering(Render * /*re*/) diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c index 3263b78ba85..435559f4881 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c @@ -116,7 +116,7 @@ static void reduce_stroke_points(bGPDstroke *gps, { bGPDspoint *new_points = MEM_callocN(sizeof(bGPDspoint) * num_points, __func__); MDeformVert *new_dvert = NULL; - if (gps->dvert != NULL) { + if ((gps->dvert != NULL) && (num_points > 0)) { new_dvert = MEM_callocN(sizeof(MDeformVert) * num_points, __func__); } @@ -130,7 +130,7 @@ static void reduce_stroke_points(bGPDstroke *gps, { /* copy over point data */ memcpy(new_points, gps->points, sizeof(bGPDspoint) * num_points); - if (gps->dvert != NULL) { + if ((gps->dvert != NULL) && (num_points > 0)) { memcpy(new_dvert, gps->dvert, sizeof(MDeformVert) * num_points); /* free unused point weights */ @@ -151,7 +151,7 @@ static void reduce_stroke_points(bGPDstroke *gps, /* copy over point data */ memcpy(new_points, gps->points + offset, sizeof(bGPDspoint) * num_points); - if (gps->dvert != NULL) { + if ((gps->dvert != NULL) && (num_points > 0)) { memcpy(new_dvert, gps->dvert + offset, sizeof(MDeformVert) * num_points); /* free unused weights */ diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index cf1d449ad3b..a8a0288f895 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -146,8 +146,6 @@ data_to_c_simple(shaders/gpu_shader_uniform_color_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_checker_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_diag_stripes_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_simple_lighting_frag.glsl SRC) -data_to_c_simple(shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl SRC) -data_to_c_simple(shaders/gpu_shader_simple_lighting_smooth_color_alpha_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_flat_color_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_flat_color_alpha_test_0_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_flat_id_frag.glsl SRC) @@ -165,7 +163,6 @@ data_to_c_simple(shaders/gpu_shader_2D_line_dashed_uniform_color_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_2D_line_dashed_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_2D_smooth_color_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_2D_smooth_color_frag.glsl SRC) -data_to_c_simple(shaders/gpu_shader_2D_smooth_color_dithered_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_2D_image_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_2D_image_rect_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_2D_image_multi_rect_vert.glsl SRC) @@ -179,16 +176,12 @@ data_to_c_simple(shaders/gpu_shader_image_modulate_alpha_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_image_alpha_color_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_image_color_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_image_varying_color_frag.glsl SRC) -data_to_c_simple(shaders/gpu_shader_image_depth_linear_frag.glsl SRC) -data_to_c_simple(shaders/gpu_shader_image_depth_copy_frag.glsl SRC) -data_to_c_simple(shaders/gpu_shader_image_multisample_resolve_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_image_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_normal_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_flat_color_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_line_dashed_uniform_color_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_smooth_color_vert.glsl SRC) -data_to_c_simple(shaders/gpu_shader_3D_normal_smooth_color_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_smooth_color_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_passthrough_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_clipped_uniform_color_vert.glsl SRC) diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h index 9d17b199722..9d91fd79137 100644 --- a/source/blender/gpu/GPU_buffers.h +++ b/source/blender/gpu/GPU_buffers.h @@ -113,7 +113,7 @@ struct GPUBatch *GPU_pbvh_buffers_batch_get(GPU_PBVH_Buffers *buffers, bool fast short GPU_pbvh_buffers_material_index_get(GPU_PBVH_Buffers *buffers); -bool GPU_pbvh_buffers_has_mask(GPU_PBVH_Buffers *buffers); +bool GPU_pbvh_buffers_has_overlays(GPU_PBVH_Buffers *buffers); #ifdef __cplusplus } diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index 334e295c636..bb26f5d41a3 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -107,10 +107,6 @@ typedef enum eGPUBuiltinShader { GPU_SHADER_TEXT, GPU_SHADER_KEYFRAME_DIAMOND, GPU_SHADER_SIMPLE_LIGHTING, - GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR, - GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR, - GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR_ALPHA, - /* for simple 2D drawing */ /** * Take a single color for all the vertices and a 2D position for each vertex. @@ -133,7 +129,6 @@ typedef enum eGPUBuiltinShader { * \param pos: in vec2 */ GPU_SHADER_2D_SMOOTH_COLOR, - GPU_SHADER_2D_SMOOTH_COLOR_DITHER, GPU_SHADER_2D_IMAGE, GPU_SHADER_2D_IMAGE_COLOR, GPU_SHADER_2D_IMAGE_DESATURATE_COLOR, @@ -141,14 +136,6 @@ typedef enum eGPUBuiltinShader { GPU_SHADER_2D_IMAGE_ALPHA, GPU_SHADER_2D_IMAGE_RECT_COLOR, GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR, - GPU_SHADER_2D_IMAGE_MULTISAMPLE_2, - GPU_SHADER_2D_IMAGE_MULTISAMPLE_4, - GPU_SHADER_2D_IMAGE_MULTISAMPLE_8, - GPU_SHADER_2D_IMAGE_MULTISAMPLE_16, - GPU_SHADER_2D_IMAGE_MULTISAMPLE_2_DEPTH_TEST, - GPU_SHADER_2D_IMAGE_MULTISAMPLE_4_DEPTH_TEST, - GPU_SHADER_2D_IMAGE_MULTISAMPLE_8_DEPTH_TEST, - GPU_SHADER_2D_IMAGE_MULTISAMPLE_16_DEPTH_TEST, GPU_SHADER_2D_CHECKER, GPU_SHADER_2D_DIAG_STRIPES, /* for simple 3D drawing */ @@ -159,8 +146,6 @@ typedef enum eGPUBuiltinShader { * \param pos: in vec3 */ GPU_SHADER_3D_UNIFORM_COLOR, - /* Sets Z-depth to 1.0 (draw onto background). */ - GPU_SHADER_3D_UNIFORM_COLOR_BACKGROUND, /** * Take a 3D position and color for each vertex without color interpolation. * @@ -196,18 +181,6 @@ typedef enum eGPUBuiltinShader { * \param pos: in vec3 */ GPU_SHADER_3D_IMAGE_MODULATE_ALPHA, - /** - * Draw linearized depth texture relate to near and far distances. - * Take a 3D position and a 2D texture coordinate for each vertex. - * - * \param znear: uniform float - * \param zfar: uniform float - * \param image: uniform sampler2D - * \param texCoord: in vec2 - * \param pos: in vec3 - */ - GPU_SHADER_3D_IMAGE_DEPTH, - GPU_SHADER_3D_IMAGE_DEPTH_COPY, /* points */ /** * Draw round points with a hardcoded size. diff --git a/source/blender/gpu/GPU_shader_interface.h b/source/blender/gpu/GPU_shader_interface.h index 8b0d25e51a3..7a8900997d0 100644 --- a/source/blender/gpu/GPU_shader_interface.h +++ b/source/blender/gpu/GPU_shader_interface.h @@ -88,6 +88,8 @@ typedef struct GPUShaderInterface { char *name_buffer; struct GPUBatch **batches; /* references to batches using this interface */ uint batches_len; + /** All enabled attribs in this shader. Used to set default values for unbound attribs. */ + uint16_t enabled_attrib_mask; } GPUShaderInterface; GPUShaderInterface *GPU_shaderinterface_create(int32_t program_id); diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c index 6bc3cd27130..fcfa4b7f0af 100644 --- a/source/blender/gpu/intern/gpu_batch.c +++ b/source/blender/gpu/intern/gpu_batch.c @@ -42,6 +42,8 @@ #include <stdlib.h> #include <string.h> +static GLuint g_default_attrib_vbo = 0; + static void batch_update_program_bindings(GPUBatch *batch, uint i_first); void GPU_batch_vao_cache_clear(GPUBatch *batch) @@ -414,6 +416,7 @@ void gpu_batch_remove_interface_ref(GPUBatch *batch, const GPUShaderInterface *i static void create_bindings(GPUVertBuf *verts, const GPUShaderInterface *interface, + uint16_t *attrib_mask, uint v_first, const bool use_instancing) { @@ -446,6 +449,8 @@ static void create_bindings(GPUVertBuf *verts, continue; } + *attrib_mask &= ~(1 << input->location); + if (a->comp_len == 16 || a->comp_len == 12 || a->comp_len == 8) { #if TRUST_NO_ONE assert(a->fetch_mode == GPU_FETCH_FLOAT); @@ -487,17 +492,35 @@ static void create_bindings(GPUVertBuf *verts, static void batch_update_program_bindings(GPUBatch *batch, uint i_first) { + uint16_t attrib_mask = batch->interface->enabled_attrib_mask; + /* Reverse order so first vbos have more prevalence (in term of attrib override). */ for (int v = GPU_BATCH_VBO_MAX_LEN - 1; v > -1; v--) { if (batch->verts[v] != NULL) { - create_bindings(batch->verts[v], batch->interface, 0, false); + create_bindings(batch->verts[v], batch->interface, &attrib_mask, 0, false); } } + for (int v = GPU_BATCH_INST_VBO_MAX_LEN - 1; v > -1; v--) { if (batch->inst[v]) { - create_bindings(batch->inst[v], batch->interface, i_first, true); + create_bindings(batch->inst[v], batch->interface, &attrib_mask, i_first, true); + } + } + + if (attrib_mask != 0 && GLEW_ARB_vertex_attrib_binding) { + for (uint16_t mask = 1, a = 0; a < 16; a++, mask <<= 1) { + if (attrib_mask & mask) { + /* This replaces glVertexAttrib4f(a, 0.0f, 0.0f, 0.0f, 1.0f); with a more modern style. + * Fix issues for some drivers (see T75069). */ + glBindVertexBuffer(a, g_default_attrib_vbo, (intptr_t)0, (intptr_t)0); + + glEnableVertexAttribArray(a); + glVertexAttribFormat(a, 4, GL_FLOAT, GL_FALSE, 0); + glVertexAttribBinding(a, a); + } } } + if (batch->elem) { GPU_indexbuf_use(batch->elem); } @@ -1002,11 +1025,23 @@ void GPU_batch_program_set_imm_shader(GPUBatch *batch) void gpu_batch_init(void) { + if (g_default_attrib_vbo == 0) { + g_default_attrib_vbo = GPU_buf_alloc(); + + float default_attrib_data[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + glBindBuffer(GL_ARRAY_BUFFER, g_default_attrib_vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 4, default_attrib_data, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + gpu_batch_presets_init(); } void gpu_batch_exit(void) { + GPU_buf_free(g_default_attrib_vbo); + g_default_attrib_vbo = 0; + gpu_batch_presets_exit(); } diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index c377d196eb5..168a3c83a91 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -92,7 +92,7 @@ struct GPU_PBVH_Buffers { * smooth-shaded or all faces are flat-shaded */ bool smooth; - bool show_mask; + bool show_overlay; }; static struct { @@ -116,7 +116,7 @@ void gpu_pbvh_init() &g_vbo_id.format, "nor", GPU_COMP_I16, 3, GPU_FETCH_INT_TO_FLOAT_UNIT); /* TODO: Do not allocate these `.msk` and `.col` when they are not used. */ g_vbo_id.msk = GPU_vertformat_attr_add( - &g_vbo_id.format, "msk", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + &g_vbo_id.format, "msk", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); g_vbo_id.col = GPU_vertformat_attr_add( &g_vbo_id.format, "ac", GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); g_vbo_id.fset = GPU_vertformat_attr_add( @@ -206,6 +206,15 @@ static void face_set_overlay_color_get(const int face_set, const int seed, uchar rgba_float_to_uchar(r_color, rgba); } +static bool gpu_pbvh_is_looptri_visible(const MLoopTri *lt, + const MVert *mvert, + const MLoop *mloop, + const int *sculpt_face_sets) +{ + return (!paint_is_face_hidden(lt, mvert, mloop) && sculpt_face_sets && + sculpt_face_sets[lt->poly] > SCULPT_FACE_SET_NONE); +} + /* Threaded - do not call any functions that use OpenGL calls! */ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers, const MVert *mvert, @@ -224,6 +233,7 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers, const bool show_face_sets = sculpt_face_sets && (update_flags & GPU_PBVH_BUFFERS_SHOW_SCULPT_FACE_SETS) != 0; bool empty_mask = true; + bool default_face_set = true; { int totelem = (buffers->smooth ? totvert : (buffers->tot_tri * 3)); @@ -254,15 +264,15 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers, copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), v->co); copy_v3_v3_short(GPU_vertbuf_raw_step(&nor_step), v->no); - float mask; + uchar mask; if (show_mask) { - mask = vmask[vidx]; + mask = (uchar)(vmask[vidx] * 255); } else { mask = 0.0f; } - *(float *)GPU_vertbuf_raw_step(&msk_step) = mask; - empty_mask = empty_mask && (mask == 0.0f); + *(uchar *)GPU_vertbuf_raw_step(&msk_step) = mask; + empty_mask = empty_mask && (mask == 0); } /* Face Sets. */ @@ -275,6 +285,7 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers, /* Skip for the default color Face Set to render it white. */ if (fset != face_sets_color_default) { face_set_overlay_color_get(fset, face_sets_color_seed, face_set_color); + default_face_set = false; } } for (int j = 0; j < 3; j++) { @@ -313,11 +324,7 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers, buffers->mloop[lt->tri[2]].v, }; - if (paint_is_face_hidden(lt, mvert, buffers->mloop)) { - continue; - } - - if (sculpt_face_sets[lt->poly] <= 0) { + if (!gpu_pbvh_is_looptri_visible(lt, mvert, buffers->mloop, sculpt_face_sets)) { continue; } @@ -336,12 +343,15 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers, /* Skip for the default color Face Set to render it white. */ if (fset != face_sets_color_default) { face_set_overlay_color_get(fset, face_sets_color_seed, face_set_color); + default_face_set = false; } } float fmask = 0.0f; + uchar cmask = 0; if (show_mask) { fmask = (vmask[vtri[0]] + vmask[vtri[1]] + vmask[vtri[2]]) / 3.0f; + cmask = (uchar)(fmask * 255); } for (uint j = 0; j < 3; j++) { @@ -349,8 +359,8 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers, copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), v->co); copy_v3_v3_short(GPU_vertbuf_raw_step(&nor_step), no); - *(float *)GPU_vertbuf_raw_step(&msk_step) = fmask; - empty_mask = empty_mask && (fmask == 0.0f); + *(uchar *)GPU_vertbuf_raw_step(&msk_step) = cmask; + empty_mask = empty_mask && (cmask == 0); /* Face Sets. */ memcpy(GPU_vertbuf_raw_step(&fset_step), face_set_color, sizeof(uchar) * 3); @@ -377,19 +387,10 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers, const MPoly *mp = &buffers->mpoly[lt->poly]; buffers->material_index = mp->mat_nr; - buffers->show_mask = !empty_mask; + buffers->show_overlay = !empty_mask || !default_face_set; buffers->mvert = mvert; } -static bool gpu_pbvh_is_looptri_visible(const MLoopTri *lt, - const MVert *mvert, - const MLoop *mloop, - const int *sculpt_face_sets) -{ - return (!paint_is_face_hidden(lt, mvert, mloop) && sculpt_face_sets && - sculpt_face_sets[lt->poly] > 0); -} - /* Threaded - do not call any functions that use OpenGL calls! */ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const int (*face_vert_indices)[3], const MPoly *mpoly, @@ -410,7 +411,7 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const int (*face_vert_indices)[3], /* smooth or flat for all */ buffers->smooth = mpoly[looptri[face_indices[0]].poly].flag & ME_SMOOTH; - buffers->show_mask = false; + buffers->show_overlay = false; /* Count the number of visible triangles */ for (i = 0, tottri = 0; i < face_indices_len; i++) { @@ -731,8 +732,9 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers, if (has_mask && show_mask) { float fmask = *CCG_elem_mask(key, elem); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index, &fmask); - empty_mask = empty_mask && (fmask == 0.0f); + uchar cmask = (uchar)(fmask * 255); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index, &cmask); + empty_mask = empty_mask && (cmask == 0); } if (show_vcol) { @@ -780,14 +782,15 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers, GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index + 3, no_short); if (has_mask && show_mask) { - float fsets = (*CCG_elem_mask(key, elems[0]) + *CCG_elem_mask(key, elems[1]) + + float fmask = (*CCG_elem_mask(key, elems[0]) + *CCG_elem_mask(key, elems[1]) + *CCG_elem_mask(key, elems[2]) + *CCG_elem_mask(key, elems[3])) * 0.25f; - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index + 0, &fsets); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index + 1, &fsets); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index + 2, &fsets); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index + 3, &fsets); - empty_mask = empty_mask && (fsets == 0.0f); + uchar cmask = (uchar)(fmask * 255); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index + 0, &cmask); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index + 1, &cmask); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index + 2, &cmask); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index + 3, &cmask); + empty_mask = empty_mask && (cmask == 0); } ushort vcol[4] = {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX}; @@ -820,7 +823,7 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers, buffers->totgrid = totgrid; buffers->grid_flag_mats = grid_flag_mats; buffers->gridkey = *key; - buffers->show_mask = !empty_mask; + buffers->show_overlay = !empty_mask; } /* Threaded - do not call any functions that use OpenGL calls! */ @@ -832,7 +835,7 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(int totgrid, BLI_bitmap **grid_hid buffers->grid_hidden = grid_hidden; buffers->totgrid = totgrid; - buffers->show_mask = false; + buffers->show_overlay = false; return buffers; } @@ -868,8 +871,9 @@ static void gpu_bmesh_vert_to_buffer_copy(BMVert *v, if (show_mask) { float effective_mask = fmask ? *fmask : BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset); - GPU_vertbuf_attr_set(vert_buf, g_vbo_id.msk, v_index, &effective_mask); - *empty_mask = *empty_mask && (effective_mask == 0.0f); + uchar cmask = (uchar)(effective_mask * 255); + GPU_vertbuf_attr_set(vert_buf, g_vbo_id.msk, v_index, &cmask); + *empty_mask = *empty_mask && (cmask == 0); } if (show_vcol) { @@ -1095,7 +1099,7 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers, /* Get material index from the last face we iterated on. */ buffers->material_index = (f) ? f->mat_nr : 0; - buffers->show_mask = !empty_mask; + buffers->show_overlay = !empty_mask; gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS); } @@ -1114,7 +1118,7 @@ GPU_PBVH_Buffers *GPU_pbvh_bmesh_buffers_build(bool smooth_shading) buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers"); buffers->use_bmesh = true; buffers->smooth = smooth_shading; - buffers->show_mask = true; + buffers->show_overlay = true; return buffers; } @@ -1129,9 +1133,9 @@ GPUBatch *GPU_pbvh_buffers_batch_get(GPU_PBVH_Buffers *buffers, bool fast, bool } } -bool GPU_pbvh_buffers_has_mask(GPU_PBVH_Buffers *buffers) +bool GPU_pbvh_buffers_has_overlays(GPU_PBVH_Buffers *buffers) { - return buffers->show_mask; + return buffers->show_overlay; } short GPU_pbvh_buffers_material_index_get(GPU_PBVH_Buffers *buffers) diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index c6ffcfa2d86..1a0daf4ac41 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -54,9 +54,6 @@ extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; extern char datatoc_gpu_shader_checker_frag_glsl[]; extern char datatoc_gpu_shader_diag_stripes_frag_glsl[]; extern char datatoc_gpu_shader_simple_lighting_frag_glsl[]; -extern char datatoc_gpu_shader_simple_lighting_flat_color_frag_glsl[]; -extern char datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl[]; -extern char datatoc_gpu_shader_simple_lighting_smooth_color_alpha_frag_glsl[]; extern char datatoc_gpu_shader_flat_color_frag_glsl[]; extern char datatoc_gpu_shader_flat_color_alpha_test_0_frag_glsl[]; extern char datatoc_gpu_shader_flat_id_frag_glsl[]; @@ -67,7 +64,6 @@ extern char datatoc_gpu_shader_2D_flat_color_vert_glsl[]; extern char datatoc_gpu_shader_2D_smooth_color_uniform_alpha_vert_glsl[]; extern char datatoc_gpu_shader_2D_smooth_color_vert_glsl[]; extern char datatoc_gpu_shader_2D_smooth_color_frag_glsl[]; -extern char datatoc_gpu_shader_2D_smooth_color_dithered_frag_glsl[]; extern char datatoc_gpu_shader_2D_image_vert_glsl[]; extern char datatoc_gpu_shader_2D_image_rect_vert_glsl[]; extern char datatoc_gpu_shader_2D_image_multi_rect_vert_glsl[]; @@ -89,15 +85,10 @@ extern char datatoc_gpu_shader_image_alpha_color_frag_glsl[]; extern char datatoc_gpu_shader_image_shuffle_color_frag_glsl[]; extern char datatoc_gpu_shader_image_mask_uniform_color_frag_glsl[]; extern char datatoc_gpu_shader_image_modulate_alpha_frag_glsl[]; -extern char datatoc_gpu_shader_image_depth_linear_frag_glsl[]; -extern char datatoc_gpu_shader_image_depth_copy_frag_glsl[]; -extern char datatoc_gpu_shader_image_multisample_resolve_frag_glsl[]; extern char datatoc_gpu_shader_3D_vert_glsl[]; extern char datatoc_gpu_shader_3D_normal_vert_glsl[]; extern char datatoc_gpu_shader_3D_flat_color_vert_glsl[]; extern char datatoc_gpu_shader_3D_smooth_color_vert_glsl[]; -extern char datatoc_gpu_shader_3D_normal_flat_color_vert_glsl[]; -extern char datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl[]; extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[]; extern char datatoc_gpu_shader_3D_passthrough_vert_glsl[]; extern char datatoc_gpu_shader_3D_clipped_uniform_color_vert_glsl[]; @@ -884,23 +875,6 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = { .vert = datatoc_gpu_shader_3D_normal_vert_glsl, .frag = datatoc_gpu_shader_simple_lighting_frag_glsl, }, - /* Use 'USE_FLAT_NORMAL' to make flat shader from smooth */ - [GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR] = - { - .vert = datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl, - .frag = datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl, - .defs = "#define USE_FLAT_NORMAL\n", - }, - [GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR] = - { - .vert = datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl, - .frag = datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl, - }, - [GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR_ALPHA] = - { - .vert = datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl, - .frag = datatoc_gpu_shader_simple_lighting_smooth_color_alpha_frag_glsl, - }, [GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR] = { @@ -912,69 +886,6 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = { .vert = datatoc_gpu_shader_3D_image_vert_glsl, .frag = datatoc_gpu_shader_image_modulate_alpha_frag_glsl, }, - [GPU_SHADER_3D_IMAGE_DEPTH] = - { - .vert = datatoc_gpu_shader_3D_image_vert_glsl, - .frag = datatoc_gpu_shader_image_depth_linear_frag_glsl, - }, - [GPU_SHADER_3D_IMAGE_DEPTH_COPY] = - { - .vert = datatoc_gpu_shader_3D_image_vert_glsl, - .frag = datatoc_gpu_shader_image_depth_copy_frag_glsl, - }, - [GPU_SHADER_2D_IMAGE_MULTISAMPLE_2] = - { - .vert = datatoc_gpu_shader_2D_vert_glsl, - .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl, - .defs = "#define SAMPLES 2\n", - }, - [GPU_SHADER_2D_IMAGE_MULTISAMPLE_4] = - { - .vert = datatoc_gpu_shader_2D_vert_glsl, - .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl, - .defs = "#define SAMPLES 4\n", - }, - [GPU_SHADER_2D_IMAGE_MULTISAMPLE_8] = - { - .vert = datatoc_gpu_shader_2D_vert_glsl, - .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl, - .defs = "#define SAMPLES 8\n", - }, - [GPU_SHADER_2D_IMAGE_MULTISAMPLE_16] = - { - .vert = datatoc_gpu_shader_2D_vert_glsl, - .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl, - .defs = "#define SAMPLES 16\n", - }, - [GPU_SHADER_2D_IMAGE_MULTISAMPLE_2_DEPTH_TEST] = - { - .vert = datatoc_gpu_shader_2D_vert_glsl, - .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl, - .defs = "#define SAMPLES 2\n" - "#define USE_DEPTH\n", - }, - [GPU_SHADER_2D_IMAGE_MULTISAMPLE_4_DEPTH_TEST] = - { - .vert = datatoc_gpu_shader_2D_vert_glsl, - .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl, - .defs = "#define SAMPLES 4\n" - "#define USE_DEPTH\n", - }, - [GPU_SHADER_2D_IMAGE_MULTISAMPLE_8_DEPTH_TEST] = - { - .vert = datatoc_gpu_shader_2D_vert_glsl, - .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl, - .defs = "#define SAMPLES 8\n" - "#define USE_DEPTH\n", - }, - [GPU_SHADER_2D_IMAGE_MULTISAMPLE_16_DEPTH_TEST] = - { - .vert = datatoc_gpu_shader_2D_vert_glsl, - .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl, - .defs = "#define SAMPLES 16\n" - "#define USE_DEPTH\n", - }, - [GPU_SHADER_2D_CHECKER] = { .vert = datatoc_gpu_shader_2D_vert_glsl, @@ -1002,11 +913,6 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = { .vert = datatoc_gpu_shader_2D_smooth_color_vert_glsl, .frag = datatoc_gpu_shader_2D_smooth_color_frag_glsl, }, - [GPU_SHADER_2D_SMOOTH_COLOR_DITHER] = - { - .vert = datatoc_gpu_shader_2D_smooth_color_vert_glsl, - .frag = datatoc_gpu_shader_2D_smooth_color_dithered_frag_glsl, - }, [GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE] = { .vert = datatoc_gpu_shader_2D_image_vert_glsl, @@ -1058,12 +964,6 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = { .vert = datatoc_gpu_shader_3D_vert_glsl, .frag = datatoc_gpu_shader_uniform_color_frag_glsl, }, - [GPU_SHADER_3D_UNIFORM_COLOR_BACKGROUND] = - { - .vert = datatoc_gpu_shader_3D_vert_glsl, - .frag = datatoc_gpu_shader_uniform_color_frag_glsl, - .defs = "#define USE_BACKGROUND\n", - }, [GPU_SHADER_3D_FLAT_COLOR] = { .vert = datatoc_gpu_shader_3D_flat_color_vert_glsl, diff --git a/source/blender/gpu/intern/gpu_shader_interface.c b/source/blender/gpu/intern/gpu_shader_interface.c index f23a0a438d6..349a7217456 100644 --- a/source/blender/gpu/intern/gpu_shader_interface.c +++ b/source/blender/gpu/intern/gpu_shader_interface.c @@ -236,6 +236,7 @@ GPUShaderInterface *GPU_shaderinterface_create(int32_t program) shaderface->name_buffer = MEM_mallocN(name_buffer_len, "name_buffer"); /* Attributes */ + shaderface->enabled_attrib_mask = 0; for (uint32_t i = 0; i < attr_len; i++) { GPUShaderInput *input = MEM_mallocN(sizeof(GPUShaderInput), "GPUShaderInput Attr"); GLsizei remaining_buffer = name_buffer_len - shaderface->name_buffer_offset; @@ -255,6 +256,8 @@ GPUShaderInterface *GPU_shaderinterface_create(int32_t program) input->location = glGetAttribLocation(program, name); + shaderface->enabled_attrib_mask |= (1 << input->location); + set_input_name(shaderface, input, name, name_len); shader_input_to_bucket(input, shaderface->attr_buckets); diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c index 088cf912d6a..075a8e8aeb5 100644 --- a/source/blender/gpu/intern/gpu_texture.c +++ b/source/blender/gpu/intern/gpu_texture.c @@ -82,7 +82,7 @@ struct GPUTexture { eGPUTextureFormat format; eGPUTextureFormatFlag format_flag; - uint bytesize; /* number of byte for one pixel */ + int mipmaps; /* number of mipmaps */ int components; /* number of color/alpha channels */ int samples; /* number of samples for multisamples textures. 0 if not multisample target */ @@ -90,6 +90,8 @@ struct GPUTexture { GPUFrameBuffer *fb[GPU_TEX_MAX_FBO_ATTACHED]; }; +static uint gpu_get_bytesize(eGPUTextureFormat data_type); + /* ------ Memory Management ------- */ /* Records every texture allocation / free * to estimate the Texture Pool Memory consumption */ @@ -97,23 +99,39 @@ static uint memory_usage; static uint gpu_texture_memory_footprint_compute(GPUTexture *tex) { - int samp = max_ii(tex->samples, 1); + uint memsize; + const uint bytesize = gpu_get_bytesize(tex->format); + const int samp = max_ii(tex->samples, 1); switch (tex->target_base) { case GL_TEXTURE_1D: - return tex->bytesize * tex->w * samp; + case GL_TEXTURE_BUFFER: + memsize = bytesize * tex->w * samp; + break; case GL_TEXTURE_1D_ARRAY: case GL_TEXTURE_2D: - return tex->bytesize * tex->w * tex->h * samp; + memsize = bytesize * tex->w * tex->h * samp; + break; case GL_TEXTURE_2D_ARRAY: case GL_TEXTURE_3D: - return tex->bytesize * tex->w * tex->h * tex->d * samp; + memsize = bytesize * tex->w * tex->h * tex->d * samp; + break; case GL_TEXTURE_CUBE_MAP: - return tex->bytesize * 6 * tex->w * tex->h * samp; + memsize = bytesize * 6 * tex->w * tex->h * samp; + break; case GL_TEXTURE_CUBE_MAP_ARRAY_ARB: - return tex->bytesize * 6 * tex->w * tex->h * tex->d * samp; + memsize = bytesize * 6 * tex->w * tex->h * tex->d * samp; + break; default: + BLI_assert(0); return 0; } + if (tex->mipmaps != 0) { + /* Just to get an idea of the memory used here is computed + * as if the maximum number of mipmaps was generated. */ + memsize += memsize / 3; + } + + return memsize; } static void gpu_texture_memory_footprint_add(GPUTexture *tex) @@ -362,7 +380,7 @@ static uint gpu_get_bytesize(eGPUTextureFormat data_type) return 16; case GPU_RGB16F: return 12; - case GPU_DEPTH32F_STENCIL8: + case GPU_DEPTH32F_STENCIL8: /* 32-bit depth, 8 bits stencil, and 24 unused bits. */ return 8; case GPU_RG16F: case GPU_RG16I: @@ -396,65 +414,84 @@ static uint gpu_get_bytesize(eGPUTextureFormat data_type) } } -static GLenum gpu_get_gl_internalformat(eGPUTextureFormat format) +static GLenum gpu_format_to_gl_internalformat(eGPUTextureFormat format) { /* You can add any of the available type to this list * For available types see GPU_texture.h */ switch (format) { /* Formats texture & renderbuffer */ + case GPU_RGBA8UI: + return GL_RGBA8UI; + case GPU_RGBA8I: + return GL_RGBA8I; + case GPU_RGBA8: + return GL_RGBA8; + case GPU_RGBA32UI: + return GL_RGBA32UI; + case GPU_RGBA32I: + return GL_RGBA32I; case GPU_RGBA32F: return GL_RGBA32F; + case GPU_RGBA16UI: + return GL_RGBA16UI; + case GPU_RGBA16I: + return GL_RGBA16I; case GPU_RGBA16F: return GL_RGBA16F; case GPU_RGBA16: return GL_RGBA16; + case GPU_RG8UI: + return GL_RG8UI; + case GPU_RG8I: + return GL_RG8I; + case GPU_RG8: + return GL_RG8; + case GPU_RG32UI: + return GL_RG32UI; + case GPU_RG32I: + return GL_RG32I; case GPU_RG32F: return GL_RG32F; - case GPU_RGB16F: - return GL_RGB16F; - case GPU_RG16F: - return GL_RG16F; + case GPU_RG16UI: + return GL_RG16UI; case GPU_RG16I: return GL_RG16I; + case GPU_RG16F: + return GL_RGBA32F; case GPU_RG16: return GL_RG16; - case GPU_RGBA8: - return GL_RGBA8; - case GPU_RGBA8UI: - return GL_RGBA8UI; - case GPU_SRGB8_A8: - return GL_SRGB8_ALPHA8; - case GPU_R32F: - return GL_R32F; + case GPU_R8UI: + return GL_R8UI; + case GPU_R8I: + return GL_R8I; + case GPU_R8: + return GL_R8; case GPU_R32UI: return GL_R32UI; case GPU_R32I: return GL_R32I; - case GPU_R16F: - return GL_R16F; - case GPU_R16I: - return GL_R16I; + case GPU_R32F: + return GL_R32F; case GPU_R16UI: return GL_R16UI; - case GPU_RG8: - return GL_RG8; - case GPU_RG16UI: - return GL_RG16UI; + case GPU_R16I: + return GL_R16I; + case GPU_R16F: + return GL_R16F; case GPU_R16: return GL_R16; - case GPU_R8: - return GL_R8; - case GPU_R8UI: - return GL_R8UI; /* Special formats texture & renderbuffer */ case GPU_R11F_G11F_B10F: return GL_R11F_G11F_B10F; - case GPU_DEPTH24_STENCIL8: - return GL_DEPTH24_STENCIL8; case GPU_DEPTH32F_STENCIL8: return GL_DEPTH32F_STENCIL8; + case GPU_DEPTH24_STENCIL8: + return GL_DEPTH24_STENCIL8; + case GPU_SRGB8_A8: + return GL_SRGB8_ALPHA8; /* Texture only format */ - /* ** Add Format here */ + case GPU_RGB16F: + return GL_RGB16F; /* Special formats texture only */ /* ** Add Format here */ /* Depth Formats */ @@ -470,6 +507,99 @@ static GLenum gpu_get_gl_internalformat(eGPUTextureFormat format) } } +static eGPUTextureFormat gl_internalformat_to_gpu_format(const GLint glformat) +{ + /* You can add any of the available type to this list + * For available types see GPU_texture.h */ + switch (glformat) { + /* Formats texture & renderbuffer */ + case GL_RGBA8UI: + return GPU_RGBA8UI; + case GL_RGBA8I: + return GPU_RGBA8I; + case GL_RGBA8: + return GPU_RGBA8; + case GL_RGBA32UI: + return GPU_RGBA32UI; + case GL_RGBA32I: + return GPU_RGBA32I; + case GL_RGBA32F: + return GPU_RGBA32F; + case GL_RGBA16UI: + return GPU_RGBA16UI; + case GL_RGBA16I: + return GPU_RGBA16I; + case GL_RGBA16F: + return GPU_RGBA16F; + case GL_RGBA16: + return GPU_RGBA16; + case GL_RG8UI: + return GPU_RG8UI; + case GL_RG8I: + return GPU_RG8I; + case GL_RG8: + return GPU_RG8; + case GL_RG32UI: + return GPU_RG32UI; + case GL_RG32I: + return GPU_RG32I; + case GL_RG32F: + return GPU_RG32F; + case GL_RG16UI: + return GPU_RG16UI; + case GL_RG16I: + return GPU_RG16I; + case GL_RG16F: + return GPU_RGBA32F; + case GL_RG16: + return GPU_RG16; + case GL_R8UI: + return GPU_R8UI; + case GL_R8I: + return GPU_R8I; + case GL_R8: + return GPU_R8; + case GL_R32UI: + return GPU_R32UI; + case GL_R32I: + return GPU_R32I; + case GL_R32F: + return GPU_R32F; + case GL_R16UI: + return GPU_R16UI; + case GL_R16I: + return GPU_R16I; + case GL_R16F: + return GPU_R16F; + case GL_R16: + return GPU_R16; + /* Special formats texture & renderbuffer */ + case GL_R11F_G11F_B10F: + return GPU_R11F_G11F_B10F; + case GL_DEPTH32F_STENCIL8: + return GPU_DEPTH32F_STENCIL8; + case GL_DEPTH24_STENCIL8: + return GPU_DEPTH24_STENCIL8; + case GL_SRGB8_ALPHA8: + return GPU_SRGB8_A8; + /* Texture only format */ + case GL_RGB16F: + return GPU_RGB16F; + /* Special formats texture only */ + /* ** Add Format here */ + /* Depth Formats */ + case GL_DEPTH_COMPONENT32F: + return GPU_DEPTH_COMPONENT32F; + case GL_DEPTH_COMPONENT24: + return GPU_DEPTH_COMPONENT24; + case GL_DEPTH_COMPONENT16: + return GPU_DEPTH_COMPONENT16; + default: + BLI_assert(!"Internal format incorrect or unsupported\n"); + } + return -1; +} + static GLenum gpu_get_gl_datatype(eGPUDataFormat format) { switch (format) { @@ -690,7 +820,7 @@ GPUTexture *GPU_texture_create_nD(int w, tex->refcount = 1; tex->format = tex_format; tex->components = gpu_get_component_count(tex_format); - tex->bytesize = gpu_get_bytesize(tex_format); + tex->mipmaps = 0; tex->format_flag = 0; if (n == 2) { @@ -726,7 +856,7 @@ GPUTexture *GPU_texture_create_nD(int w, tex->target = GL_TEXTURE_2D_MULTISAMPLE; } - GLenum internalformat = gpu_get_gl_internalformat(tex_format); + GLenum internalformat = gpu_format_to_gl_internalformat(tex_format); GLenum data_format = gpu_get_gl_dataformat(tex_format, &tex->format_flag); GLenum data_type = gpu_get_gl_datatype(gpu_data_format); @@ -877,7 +1007,7 @@ GPUTexture *GPU_texture_cube_create(int w, tex->refcount = 1; tex->format = tex_format; tex->components = gpu_get_component_count(tex_format); - tex->bytesize = gpu_get_bytesize(tex_format); + tex->mipmaps = 0; tex->format_flag = GPU_FORMAT_CUBE; if (d == 0) { @@ -901,7 +1031,7 @@ GPUTexture *GPU_texture_cube_create(int w, } } - GLenum internalformat = gpu_get_gl_internalformat(tex_format); + GLenum internalformat = gpu_format_to_gl_internalformat(tex_format); GLenum data_format = gpu_get_gl_dataformat(tex_format, &tex->format_flag); GLenum data_type = gpu_get_gl_datatype(gpu_data_format); @@ -1008,9 +1138,9 @@ GPUTexture *GPU_texture_create_buffer(eGPUTextureFormat tex_format, const GLuint tex->components = gpu_get_component_count(tex_format); tex->format_flag = 0; tex->target_base = tex->target = GL_TEXTURE_BUFFER; - tex->bytesize = gpu_get_bytesize(tex_format); + tex->mipmaps = 0; - GLenum internalformat = gpu_get_gl_internalformat(tex_format); + GLenum internalformat = gpu_format_to_gl_internalformat(tex_format); gpu_get_gl_dataformat(tex_format, &tex->format_flag); @@ -1043,8 +1173,11 @@ GPUTexture *GPU_texture_create_buffer(eGPUTextureFormat tex_format, const GLuint glBindTexture(tex->target, tex->bindcode); glTexBuffer(tex->target, internalformat, buffer); + glGetTexLevelParameteriv(tex->target, 0, GL_TEXTURE_WIDTH, &tex->w); glBindTexture(tex->target, 0); + gpu_texture_memory_footprint_add(tex); + return tex; } @@ -1056,27 +1189,30 @@ GPUTexture *GPU_texture_from_bindcode(int textarget, int bindcode) tex->refcount = 1; tex->target = textarget; tex->target_base = textarget; - tex->format = -1; - tex->components = -1; tex->samples = 0; if (!glIsTexture(tex->bindcode)) { GPU_print_error_debug("Blender Texture Not Loaded"); } else { - GLint w, h; - - GLenum gettarget = textarget; - if (textarget == GL_TEXTURE_CUBE_MAP) { - gettarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X; - } + GLint w, h, gl_format; + GLenum gettarget; + gettarget = (textarget == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : textarget; glBindTexture(textarget, tex->bindcode); glGetTexLevelParameteriv(gettarget, 0, GL_TEXTURE_WIDTH, &w); glGetTexLevelParameteriv(gettarget, 0, GL_TEXTURE_HEIGHT, &h); + glGetTexLevelParameteriv(gettarget, 0, GL_TEXTURE_INTERNAL_FORMAT, &gl_format); tex->w = w; tex->h = h; + tex->format = gl_internalformat_to_gpu_format(gl_format); + tex->components = gpu_get_component_count(tex->format); glBindTexture(textarget, 0); + + /* Depending on how this bindcode was obtained, the memory used here could + * already have been computed. + * But that is not the case currently. */ + gpu_texture_memory_footprint_add(tex); } return tex; @@ -1261,10 +1397,11 @@ void GPU_texture_add_mipmap(GPUTexture *tex, { BLI_assert((int)tex->format > -1); BLI_assert(tex->components > -1); + BLI_assert(miplvl > tex->mipmaps); gpu_validate_data_format(tex->format, gpu_data_format); - GLenum internalformat = gpu_get_gl_internalformat(tex->format); + GLenum internalformat = gpu_format_to_gl_internalformat(tex->format); GLenum data_format = gpu_get_gl_dataformat(tex->format, &tex->format_flag); GLenum data_type = gpu_get_gl_datatype(gpu_data_format); @@ -1310,6 +1447,7 @@ void GPU_texture_add_mipmap(GPUTexture *tex, BLI_assert(!"tex->target mode not supported"); } + tex->mipmaps = miplvl; glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, miplvl); glBindTexture(tex->target, 0); @@ -1328,12 +1466,13 @@ void GPU_texture_update_sub(GPUTexture *tex, BLI_assert((int)tex->format > -1); BLI_assert(tex->components > -1); + const uint bytesize = gpu_get_bytesize(tex->format); GLenum data_format = gpu_get_gl_dataformat(tex->format, &tex->format_flag); GLenum data_type = gpu_get_gl_datatype(gpu_data_format); GLint alignment; /* The default pack size for textures is 4, which won't work for byte based textures */ - if (tex->bytesize == 1) { + if (bytesize == 1) { glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); } @@ -1367,7 +1506,7 @@ void GPU_texture_update_sub(GPUTexture *tex, BLI_assert(!"tex->target mode not supported"); } - if (tex->bytesize == 1) { + if (bytesize == 1) { glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); } @@ -1376,6 +1515,8 @@ void GPU_texture_update_sub(GPUTexture *tex, void *GPU_texture_read(GPUTexture *tex, eGPUDataFormat gpu_data_format, int miplvl) { + BLI_assert(miplvl <= tex->mipmaps); + int size[3] = {0, 0, 0}; GPU_texture_get_mipmap_size(tex, miplvl, size); @@ -1428,7 +1569,7 @@ void GPU_texture_clear(GPUTexture *tex, eGPUDataFormat gpu_data_format, const vo size_t buffer_len = gpu_texture_memory_footprint_compute(tex); unsigned char *pixels = MEM_mallocN(buffer_len, __func__); if (color) { - size_t bytesize = tex->bytesize; + const size_t bytesize = (size_t)gpu_get_bytesize(tex->format); for (size_t byte = 0; byte < buffer_len; byte += bytesize) { memcpy(&pixels[byte], color, bytesize); } @@ -1547,6 +1688,9 @@ void GPU_texture_generate_mipmap(GPUTexture *tex) { WARN_NOT_BOUND(tex); + gpu_texture_memory_footprint_remove(tex); + int levels = 1 + floor(log2(max_ii(tex->w, tex->h))); + glActiveTexture(GL_TEXTURE0 + tex->number); if (GPU_texture_depth(tex)) { @@ -1554,7 +1698,6 @@ void GPU_texture_generate_mipmap(GPUTexture *tex) * In this case we just create a complete texture with mipmaps manually without down-sampling. * You must initialize the texture levels using other methods like * GPU_framebuffer_recursive_downsample(). */ - int levels = 1 + floor(log2(max_ii(tex->w, tex->h))); eGPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex->format); for (int i = 1; i < levels; i++) { GPU_texture_add_mipmap(tex, data_format, i, NULL); @@ -1564,6 +1707,9 @@ void GPU_texture_generate_mipmap(GPUTexture *tex) else { glGenerateMipmap(tex->target_base); } + + tex->mipmaps = levels; + gpu_texture_memory_footprint_add(tex); } void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare) diff --git a/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_dithered_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_dithered_frag.glsl deleted file mode 100644 index 181b1bf3fad..00000000000 --- a/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_dithered_frag.glsl +++ /dev/null @@ -1,18 +0,0 @@ - -noperspective in vec4 finalColor; -out vec4 fragColor; - -/* 4x4 bayer matrix prepared for 8bit UNORM precision error. */ -#define P(x) (((x + 0.5) * (1.0 / 16.0) - 0.5) * (1.0 / 255.0)) -const vec4 dither_mat4x4[4] = vec4[4](vec4(P(0.0), P(8.0), P(2.0), P(10.0)), - vec4(P(12.0), P(4.0), P(14.0), P(6.0)), - vec4(P(3.0), P(11.0), P(1.0), P(9.0)), - vec4(P(15.0), P(7.0), P(13.0), P(5.0))); - -void main() -{ - ivec2 tx1 = ivec2(gl_FragCoord.xy) % 4; - ivec2 tx2 = ivec2(gl_FragCoord.xy) % 2; - float dither_noise = dither_mat4x4[tx1.x][tx1.y]; - fragColor = finalColor + dither_noise; -} diff --git a/source/blender/gpu/shaders/gpu_shader_3D_normal_smooth_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_normal_smooth_color_vert.glsl deleted file mode 100644 index 7fa571343a2..00000000000 --- a/source/blender/gpu/shaders/gpu_shader_3D_normal_smooth_color_vert.glsl +++ /dev/null @@ -1,22 +0,0 @@ - -uniform mat4 ModelViewProjectionMatrix; -uniform mat3 NormalMatrix; - -in vec3 pos; -in vec3 nor; -in vec4 color; - -#ifdef USE_FLAT_NORMAL -flat out vec3 normal; -flat out vec4 finalColor; -#else -out vec3 normal; -out vec4 finalColor; -#endif - -void main() -{ - normal = normalize(NormalMatrix * nor); - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - finalColor = color; -} diff --git a/source/blender/gpu/shaders/gpu_shader_image_depth_copy_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_depth_copy_frag.glsl deleted file mode 100644 index 0f2749362b9..00000000000 --- a/source/blender/gpu/shaders/gpu_shader_image_depth_copy_frag.glsl +++ /dev/null @@ -1,12 +0,0 @@ - -in vec2 texCoord_interp; -out vec4 fragColor; - -uniform sampler2D image; - -void main() -{ - float depth = texture(image, texCoord_interp).r; - fragColor = vec4(depth); - gl_FragDepth = depth; -} diff --git a/source/blender/gpu/shaders/gpu_shader_image_depth_linear_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_depth_linear_frag.glsl deleted file mode 100644 index 017b21076c8..00000000000 --- a/source/blender/gpu/shaders/gpu_shader_image_depth_linear_frag.glsl +++ /dev/null @@ -1,16 +0,0 @@ - -in vec2 texCoord_interp; -out vec4 fragColor; - -uniform float znear; -uniform float zfar; -uniform sampler2D image; - -void main() -{ - float depth = texture(image, texCoord_interp).r; - - /* normalize */ - fragColor.rgb = vec3((2.0f * znear) / (zfar + znear - (depth * (zfar - znear)))); - fragColor.a = 1.0f; -} diff --git a/source/blender/gpu/shaders/gpu_shader_image_multisample_resolve_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_multisample_resolve_frag.glsl deleted file mode 100644 index ca425374a1b..00000000000 --- a/source/blender/gpu/shaders/gpu_shader_image_multisample_resolve_frag.glsl +++ /dev/null @@ -1,119 +0,0 @@ - -uniform sampler2DMS depthMulti; -uniform sampler2DMS colorMulti; - -out vec4 fragColor; - -#if SAMPLES > 16 -# error "Too many samples" -#endif - -void main() -{ - ivec2 texel = ivec2(gl_FragCoord.xy); - - bvec4 b1, b2, b3, b4; - vec4 w1, w2, w3, w4; - vec4 d1, d2, d3, d4; - vec4 c1, c2, c3, c4, c5, c6, c7, c8; - vec4 c9, c10, c11, c12, c13, c14, c15, c16; - d1 = d2 = d3 = d4 = vec4(0.5); - w1 = w2 = w3 = w4 = vec4(0.0); - c1 = c2 = c3 = c4 = c5 = c6 = c7 = c8 = vec4(0.0); - c9 = c10 = c11 = c12 = c13 = c14 = c15 = c16 = vec4(0.0); - -#ifdef USE_DEPTH - /* Depth */ - d1.x = texelFetch(depthMulti, texel, 0).r; - d1.y = texelFetch(depthMulti, texel, 1).r; -# if SAMPLES > 2 - d1.z = texelFetch(depthMulti, texel, 2).r; - d1.w = texelFetch(depthMulti, texel, 3).r; -# endif -# if SAMPLES > 4 - d2.x = texelFetch(depthMulti, texel, 4).r; - d2.y = texelFetch(depthMulti, texel, 5).r; - d2.z = texelFetch(depthMulti, texel, 6).r; - d2.w = texelFetch(depthMulti, texel, 7).r; -# endif -# if SAMPLES > 8 - d3.x = texelFetch(depthMulti, texel, 8).r; - d3.y = texelFetch(depthMulti, texel, 9).r; - d3.z = texelFetch(depthMulti, texel, 10).r; - d3.w = texelFetch(depthMulti, texel, 11).r; - d4.x = texelFetch(depthMulti, texel, 12).r; - d4.y = texelFetch(depthMulti, texel, 13).r; - d4.z = texelFetch(depthMulti, texel, 14).r; - d4.w = texelFetch(depthMulti, texel, 15).r; -# endif -#endif - - /* COLOR */ - b1 = notEqual(d1, vec4(1.0)); - if (any(b1)) { - c1 = texelFetch(colorMulti, texel, 0); - c2 = texelFetch(colorMulti, texel, 1); -#if SAMPLES > 2 - c3 = texelFetch(colorMulti, texel, 2); - c4 = texelFetch(colorMulti, texel, 3); -#endif - w1 = vec4(b1); - } -#if SAMPLES > 4 - b2 = notEqual(d2, vec4(1.0)); - if (any(b2)) { - c5 = texelFetch(colorMulti, texel, 4); - c6 = texelFetch(colorMulti, texel, 5); - c7 = texelFetch(colorMulti, texel, 6); - c8 = texelFetch(colorMulti, texel, 7); - w2 = vec4(b2); - } -#endif -#if SAMPLES > 8 - b3 = notEqual(d3, vec4(1.0)); - if (any(b3)) { - c9 = texelFetch(colorMulti, texel, 8); - c10 = texelFetch(colorMulti, texel, 9); - c11 = texelFetch(colorMulti, texel, 10); - c12 = texelFetch(colorMulti, texel, 11); - w3 = vec4(b3); - } - b4 = notEqual(d4, vec4(1.0)); - if (any(b4)) { - c13 = texelFetch(colorMulti, texel, 12); - c14 = texelFetch(colorMulti, texel, 13); - c15 = texelFetch(colorMulti, texel, 14); - c16 = texelFetch(colorMulti, texel, 15); - w4 = vec4(b4); - } -#endif - -#ifdef USE_DEPTH -# if SAMPLES > 8 - d1 = min(d1, min(d3, d4)); -# endif -# if SAMPLES > 4 - d1 = min(d1, d2); - d1 = min(d1, d2); -# endif -# if SAMPLES > 2 - d1.xy = min(d1.xy, d1.zw); -# endif - gl_FragDepth = min(d1.x, d1.y); -#endif - - c1 = c1 + c2; -#if SAMPLES > 2 - c1 += c3 + c4; -#endif -#if SAMPLES > 4 - c1 += c5 + c6 + c7 + c8; -#endif -#if SAMPLES > 8 - c1 += c9 + c10 + c11 + c12 + c13 + c14 + c15 + c16; -#endif - - const float inv_samples = 1.0 / float(SAMPLES); - - fragColor = c1 * inv_samples; -} diff --git a/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_alpha_frag.glsl b/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_alpha_frag.glsl deleted file mode 100644 index 2ed99be2bcf..00000000000 --- a/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_alpha_frag.glsl +++ /dev/null @@ -1,14 +0,0 @@ - -uniform vec3 light; -uniform float alpha; -uniform float global; - -in vec3 normal; -in vec4 finalColor; -out vec4 fragColor; - -void main() -{ - fragColor = finalColor * (global + (1.0 - global) * max(0.0, dot(normalize(normal), light))); - fragColor.a = alpha; -} diff --git a/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl deleted file mode 100644 index 738b0d84e51..00000000000 --- a/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl +++ /dev/null @@ -1,16 +0,0 @@ - -uniform vec3 light; - -#ifdef USE_FLAT_NORMAL -flat in vec3 normal; -flat in vec4 finalColor; -#else -in vec3 normal; -in vec4 finalColor; -#endif -out vec4 fragColor; - -void main() -{ - fragColor = finalColor * max(0.0, dot(normalize(normal), light)); -} diff --git a/source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl index cfa82572e87..d9f84964eb4 100644 --- a/source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl @@ -17,8 +17,4 @@ void main() #else fragColor = color; #endif - -#if defined(USE_BACKGROUND) - gl_FragDepth = 1.0; -#endif } diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 5f149f0ab71..1639fb4715f 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -199,8 +199,8 @@ void IMB_colormanagement_buffer_make_display_space( void IMB_colormanagement_display_settings_from_ctx( const struct bContext *C, - struct ColorManagedViewSettings **view_settings_r, - struct ColorManagedDisplaySettings **display_settings_r); + struct ColorManagedViewSettings **r_view_settings, + struct ColorManagedDisplaySettings **r_display_settings); const char *IMB_colormanagement_get_display_colorspace_name( const struct ColorManagedViewSettings *view_settings, diff --git a/source/blender/imbuf/IMB_moviecache.h b/source/blender/imbuf/IMB_moviecache.h index 175a18ef618..5fb158f0d8b 100644 --- a/source/blender/imbuf/IMB_moviecache.h +++ b/source/blender/imbuf/IMB_moviecache.h @@ -72,7 +72,7 @@ void IMB_moviecache_cleanup(struct MovieCache *cache, void *userdata); void IMB_moviecache_get_cache_segments( - struct MovieCache *cache, int proxy, int render_flags, int *totseg_r, int **points_r); + struct MovieCache *cache, int proxy, int render_flags, int *r_totseg, int **r_points); struct MovieCacheIter; struct MovieCacheIter *IMB_moviecacheIter_new(struct MovieCache *cache); diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index a95db5c1de4..c57ab70f4e6 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -789,18 +789,18 @@ void colormanage_cache_free(ImBuf *ibuf) void IMB_colormanagement_display_settings_from_ctx( const bContext *C, - ColorManagedViewSettings **view_settings_r, - ColorManagedDisplaySettings **display_settings_r) + ColorManagedViewSettings **r_view_settings, + ColorManagedDisplaySettings **r_display_settings) { Scene *scene = CTX_data_scene(C); SpaceImage *sima = CTX_wm_space_image(C); - *view_settings_r = &scene->view_settings; - *display_settings_r = &scene->display_settings; + *r_view_settings = &scene->view_settings; + *r_display_settings = &scene->display_settings; if (sima && sima->image) { if ((sima->image->flag & IMA_VIEW_AS_RENDER) == 0) { - *view_settings_r = NULL; + *r_view_settings = NULL; } } } diff --git a/source/blender/imbuf/intern/moviecache.c b/source/blender/imbuf/intern/moviecache.c index f3b76288831..96ecbdce9cc 100644 --- a/source/blender/imbuf/intern/moviecache.c +++ b/source/blender/imbuf/intern/moviecache.c @@ -479,10 +479,10 @@ void IMB_moviecache_cleanup(MovieCache *cache, /* get segments of cached frames. useful for debugging cache policies */ void IMB_moviecache_get_cache_segments( - MovieCache *cache, int proxy, int render_flags, int *totseg_r, int **points_r) + MovieCache *cache, int proxy, int render_flags, int *r_totseg, int **r_points) { - *totseg_r = 0; - *points_r = NULL; + *r_totseg = 0; + *r_points = NULL; if (!cache->getdatafp) { return; @@ -497,8 +497,8 @@ void IMB_moviecache_get_cache_segments( } if (cache->points) { - *totseg_r = cache->totseg; - *points_r = cache->points; + *r_totseg = cache->totseg; + *r_points = cache->points; } else { int totframe = BLI_ghash_len(cache->hash); @@ -555,8 +555,8 @@ void IMB_moviecache_get_cache_segments( } } - *totseg_r = totseg; - *points_r = points; + *r_totseg = totseg; + *r_points = points; cache->totseg = totseg; cache->points = points; diff --git a/source/blender/io/usd/intern/abstract_hierarchy_iterator.h b/source/blender/io/usd/intern/abstract_hierarchy_iterator.h index f7ba1a76bac..08b50e2560d 100644 --- a/source/blender/io/usd/intern/abstract_hierarchy_iterator.h +++ b/source/blender/io/usd/intern/abstract_hierarchy_iterator.h @@ -69,7 +69,7 @@ struct HierarchyContext { * have weak_export=true, this object (and by recursive reasoning all its descendants) will be * excluded from the export. * - * The export hierarchy is kept as close to the the hierarchy in Blender as possible. As such, an + * The export hierarchy is kept as close to the hierarchy in Blender as possible. As such, an * object that serves as a parent for another object, but which should NOT be exported itself, is * exported only as transform (i.e. as empty). This happens with objects that are part of a * holdout collection (which prevents them from being exported) but also parent of an exported diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 1fad828e887..95d9216f550 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -281,11 +281,21 @@ typedef enum eBrushClothDeformType { BRUSH_CLOTH_DEFORM_EXPAND = 6, } eBrushClothDeformType; +typedef enum eBrushSmoothDeformType { + BRUSH_SMOOTH_DEFORM_LAPLACIAN = 0, + BRUSH_SMOOTH_DEFORM_SURFACE = 1, +} eBrushSmoothDeformType; + typedef enum eBrushClothForceFalloffType { BRUSH_CLOTH_FORCE_FALLOFF_RADIAL = 0, BRUSH_CLOTH_FORCE_FALLOFF_PLANE = 1, } eBrushClothForceFalloffType; +typedef enum eBrushPoseOriginType { + BRUSH_POSE_ORIGIN_TOPOLOGY = 0, + BRUSH_POSE_ORIGIN_FACE_SETS = 1, +} eBrushPoseOriginType; + /* Gpencilsettings.Vertex_mode */ typedef enum eGp_Vertex_Mode { /* Affect to Stroke only. */ @@ -401,7 +411,7 @@ typedef struct Brush { /** Source for fill tool color gradient application. */ char gradient_fill_mode; - char _pad0[5]; + char _pad0[1]; /** Projection shape (sphere, circle). */ char falloff_shape; @@ -462,6 +472,7 @@ typedef struct Brush { float pose_offset; int pose_smooth_iterations; int pose_ik_segments; + int pose_origin_type; /* cloth */ int cloth_deform_type; @@ -473,6 +484,12 @@ typedef struct Brush { float cloth_sim_limit; float cloth_sim_falloff; + /* smooth */ + int smooth_deform_type; + float surface_smooth_shape_preservation; + float surface_smooth_current_vertex; + int surface_smooth_iterations; + /* multiplane scrape */ float multiplane_scrape_angle; diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index a90935bfe62..a3b1f315f04 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -468,7 +468,7 @@ typedef enum eGPDlayer_OnionFlag { /* layer blend_mode */ typedef enum eGPLayerBlendModes { eGplBlendMode_Regular = 0, - eGplBlendMode_Overlay = 1, + eGplBlendMode_HardLight = 1, eGplBlendMode_Add = 2, eGplBlendMode_Subtract = 3, eGplBlendMode_Multiply = 4, @@ -661,8 +661,6 @@ typedef enum eGPdata_Flag { /* Autolock not active layers */ GP_DATA_AUTOLOCK_LAYERS = (1 << 20), - /* Internal flag for python update */ - GP_DATA_PYTHON_UPDATED = (1 << 21), } eGPdata_Flag; /* gpd->onion_flag */ diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index f2e65ff9251..10a549edc17 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -87,7 +87,7 @@ typedef struct MaterialGPencilStyle { /** Factor to shift texture in 2d space. */ float texture_offset[2]; /** Texture opacity. */ - float texture_opacity; + float texture_opacity DNA_DEPRECATED; /** Pixel size for uv along the stroke. */ float texture_pixsize; /** Drawing mode (line or dots). */ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 13c5a0913c6..74cb72a1fae 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -1148,6 +1148,8 @@ typedef struct SolidifyModifierData { /** Name of vertex group to use, MAX_VGROUP_NAME. */ char defgrp_name[64]; + char shell_defgrp_name[64]; + char rim_defgrp_name[64]; /** New surface offset leve.l*/ float offset; /** Midpoint of the offset . */ @@ -1324,6 +1326,11 @@ typedef struct WarpModifierData { struct Object *object_from; struct Object *object_to; + /** Optional name of bone target, MAX_ID_NAME-2. */ + char bone_from[64]; + /** Optional name of bone target, MAX_ID_NAME-2. */ + char bone_to[64]; + struct CurveMapping *curfalloff; /** Optional vertexgroup name, MAX_VGROUP_NAME. */ char defgrp_name[64]; @@ -1397,7 +1404,8 @@ typedef struct WeightVGEditModifierData { /* WeightVGEdit flags. */ enum { - /* (1 << 0) and (1 << 1) are free for future use! */ + /* (1 << 0) is free for future use! */ + MOD_WVG_INVERT_FALLOFF = (1 << 1), MOD_WVG_EDIT_INVERT_VGROUP_MASK = (1 << 2), /** Add vertices with higher weight than threshold to vgroup. */ MOD_WVG_EDIT_ADD2VG = (1 << 3), @@ -1541,6 +1549,7 @@ enum { /* Use nearest faces of target obj, in MOD_WVG_PROXIMITY_GEOMETRY mode. */ MOD_WVG_PROXIMITY_GEOM_FACES = (1 << 2), MOD_WVG_PROXIMITY_INVERT_VGROUP_MASK = (1 << 3), + MOD_WVG_PROXIMITY_INVERT_FALLOFF = (1 << 4), }; /* Defines common to all WeightVG modifiers. */ @@ -2037,12 +2046,16 @@ typedef struct SurfaceDeformModifierData { unsigned int numverts, numpoly; int flags; float mat[4][4]; + float strength; + char _pad[4]; + char defgrp_name[64]; } SurfaceDeformModifierData; /* Surface Deform modifier flags */ enum { /* This indicates "do bind on next modifier evaluation" as well as "is bound". */ MOD_SDEF_BIND = (1 << 0), + MOD_SDEF_INVERT_VGROUP = (1 << 1) /* MOD_SDEF_USES_LOOPTRI = (1 << 1), */ /* UNUSED */ /* MOD_SDEF_HAS_CONCAVE = (1 << 2), */ /* UNUSED */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index c1a6265b53b..7837c1265ab 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -731,13 +731,12 @@ typedef struct RenderData { char seq_rend_type; /** Flag use for sequence render/draw. */ char seq_flag; - char _pad5[5]; + char _pad5[7]; /* render simplify */ short simplify_subsurf; short simplify_subsurf_render; short simplify_gpencil; - short simplify_smoke_ignore_highres; float simplify_particles; float simplify_particles_render; diff --git a/source/blender/makesdna/DNA_sound_types.h b/source/blender/makesdna/DNA_sound_types.h index 73f0e20efcb..04ac9d4e5be 100644 --- a/source/blender/makesdna/DNA_sound_types.h +++ b/source/blender/makesdna/DNA_sound_types.h @@ -26,9 +26,6 @@ #include "DNA_ID.h" #include "DNA_defs.h" -/* stupid... could easily be solved */ -#include "DNA_view2d_types.h" - struct Ipo; struct PackedFile; @@ -104,7 +101,7 @@ typedef enum eSound_Type { } eSound_Type; #endif -/* bSound->flags */ +/** #bSound.flags */ enum { #ifdef DNA_DEPRECATED_ALLOW /* deprecated! used for sound actuator loading */ @@ -114,13 +111,11 @@ enum { SOUND_FLAGS_MONO = (1 << 5), }; -/* bSound->tags */ +/** #bSound.tags */ enum { /* Do not free/reset waveform on sound load, only used by undo code. */ SOUND_TAGS_WAVEFORM_NO_RELOAD = 1 << 0, SOUND_TAGS_WAVEFORM_LOADING = (1 << 6), }; -/* to DNA_sound_types.h*/ - -#endif +#endif /* __DNA_SOUND_TYPES_H__ */ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index d3cce8d1510..3020e5a1708 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -955,7 +955,10 @@ typedef struct FileDirEntry { /** ID type, in case typeflag has FILE_TYPE_BLENDERLIB set. */ int blentype; + /* Path to item that is relative to current folder root. */ char *relpath; + /** Optional argument for shortcuts, aliases etc. */ + char *redirection_path; /** TODO: make this a real ID pointer? */ void *poin; diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index 0685fb270f1..a3a89db66be 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -662,6 +662,12 @@ static void rna_def_action_group(BlenderRNA *brna) prop, "Expanded in Graph Editor", "Action group is expanded in graph editor"); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + prop = RNA_def_property(srna, "use_pin", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", ADT_CURVES_ALWAYS_VISIBLE); + RNA_def_property_ui_text(prop, "Pin in Graph Editor", ""); + RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + /* color set */ rna_def_actionbone_group_common(srna, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); } diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c index 036bcfc6311..1ca1bf27156 100644 --- a/source/blender/makesrna/intern/rna_animation.c +++ b/source/blender/makesrna/intern/rna_animation.c @@ -1322,6 +1322,12 @@ static void rna_def_animdata(BlenderRNA *brna) prop, "Use NLA Tweak Mode", "Whether to enable or disable tweak mode in NLA"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, "rna_AnimData_update"); + prop = RNA_def_property(srna, "use_pin", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", ADT_CURVES_ALWAYS_VISIBLE); + RNA_def_property_ui_text(prop, "Pin in Graph Editor", ""); + RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + /* Animation Data API */ RNA_api_animdata(srna); } diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index a4091718487..75201322094 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -1794,6 +1794,35 @@ static void rna_def_brush(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}, }; + static const EnumPropertyItem brush_smooth_deform_type_items[] = { + {BRUSH_SMOOTH_DEFORM_LAPLACIAN, + "LAPLACIAN", + 0, + "Laplacian", + "Smooths the surface and the volume"}, + {BRUSH_SMOOTH_DEFORM_SURFACE, + "SURFACE", + 0, + "Surface", + "Smooths the surface of the mesh, preserving the volue"}, + {0, NULL, 0, NULL, NULL}, + }; + + static const EnumPropertyItem brush_pose_origin_type_items[] = { + {BRUSH_POSE_ORIGIN_TOPOLOGY, + "TOPOLOGY", + 0, + "Topology", + "Sets the rotation origin automatically using the topology and shape of the mesh as a " + "guide"}, + {BRUSH_POSE_ORIGIN_FACE_SETS, + "FACE_SETS", + 0, + "Face Sets", + "Creates a pose segment per face sets, starting from the active face set"}, + {0, NULL, 0, NULL, NULL}, + }; + srna = RNA_def_struct(brna, "Brush", "ID"); RNA_def_struct_ui_text( srna, "Brush", "Brush data-block for storing brush settings for painting and sculpting"); @@ -1909,6 +1938,18 @@ static void rna_def_brush(BlenderRNA *brna) prop, "Force Falloff", "Shape used in the brush to apply force to the cloth"); RNA_def_property_update(prop, 0, "rna_Brush_update"); + prop = RNA_def_property(srna, "smooth_deform_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, brush_smooth_deform_type_items); + RNA_def_property_ui_text(prop, "Deformation", "Deformation type that is used in the brush"); + RNA_def_property_update(prop, 0, "rna_Brush_update"); + + prop = RNA_def_property(srna, "pose_origin_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, brush_pose_origin_type_items); + RNA_def_property_ui_text(prop, + "Rotation Origins", + "Method to set the rotation origins for the segments of the brush"); + RNA_def_property_update(prop, 0, "rna_Brush_update"); + prop = RNA_def_property(srna, "jitter_unit", PROP_ENUM, PROP_NONE); /* as an enum */ RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); RNA_def_property_enum_items(prop, brush_jitter_unit_items); @@ -2101,6 +2142,29 @@ static void rna_def_brush(BlenderRNA *brna) prop, "Pose Origin Offset", "Offset of the pose origin in relation to the brush radius"); RNA_def_property_update(prop, 0, "rna_Brush_update"); + prop = RNA_def_property(srna, "surface_smooth_shape_preservation", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "surface_smooth_shape_preservation"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text( + prop, "Shape Preservation", "How much of the original shape is preserved when smoothing"); + RNA_def_property_update(prop, 0, "rna_Brush_update"); + + prop = RNA_def_property(srna, "surface_smooth_current_vertex", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "surface_smooth_current_vertex"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text( + prop, + "Per Vertex Displacement", + "How much the position of each individual vertex influences the final result"); + RNA_def_property_update(prop, 0, "rna_Brush_update"); + + prop = RNA_def_property(srna, "surface_smooth_iterations", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "surface_smooth_iterations"); + RNA_def_property_range(prop, 1, 10); + RNA_def_property_ui_range(prop, 1, 10, 1, 3); + RNA_def_property_ui_text(prop, "Iterations", "Number of smoothing iterations per brush step"); + RNA_def_property_update(prop, 0, "rna_Brush_update"); + prop = RNA_def_property(srna, "multiplane_scrape_angle", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "multiplane_scrape_angle"); RNA_def_property_range(prop, 0.0f, 160.0f); @@ -2135,7 +2199,7 @@ static void rna_def_brush(BlenderRNA *brna) prop = RNA_def_property(srna, "cloth_mass", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "cloth_mass"); RNA_def_property_range(prop, 0.01f, 2.0f); - RNA_def_property_ui_text(prop, "Cloth mass", "Mass of each simulation particle"); + RNA_def_property_ui_text(prop, "Cloth Mass", "Mass of each simulation particle"); RNA_def_property_update(prop, 0, "rna_Brush_update"); prop = RNA_def_property(srna, "cloth_damping", PROP_FLOAT, PROP_FACTOR); @@ -2322,7 +2386,8 @@ static void rna_def_brush(BlenderRNA *brna) prop = RNA_def_property(srna, "use_automasking_boundary_edges", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "automasking_flags", BRUSH_AUTOMASKING_BOUNDARY_EDGES); - RNA_def_property_ui_text(prop, "Edges Automasking", "Do not affect non manifold boundary edges"); + RNA_def_property_ui_text( + prop, "Mesh Boundary Auto-masking", "Do not affect non manifold boundary edges"); RNA_def_property_update(prop, 0, "rna_Brush_update"); prop = RNA_def_property(srna, "use_scene_spacing", PROP_ENUM, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index deacd8e1cfc..4afa467d2e3 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -114,7 +114,7 @@ static const EnumPropertyItem rna_enum_gplayer_move_type_items[] = { static const EnumPropertyItem rna_enum_layer_blend_modes_items[] = { {eGplBlendMode_Regular, "REGULAR", 0, "Regular", ""}, - {eGplBlendMode_Overlay, "OVERLAY", 0, "Overlay", ""}, + {eGplBlendMode_HardLight, "HARDLIGHT", 0, "Hard Light", ""}, {eGplBlendMode_Add, "ADD", 0, "Add", ""}, {eGplBlendMode_Subtract, "SUBTRACT", 0, "Subtract", ""}, {eGplBlendMode_Multiply, "MULTIPLY", 0, "Multiply", ""}, @@ -642,7 +642,6 @@ static void rna_GPencil_stroke_point_add( /* Calc geometry data. */ BKE_gpencil_stroke_geometry_update(stroke); - gpd->flag |= GP_DATA_PYTHON_UPDATED; DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); @@ -704,7 +703,6 @@ static void rna_GPencil_stroke_point_pop(ID *id, /* Calc geometry data. */ BKE_gpencil_stroke_geometry_update(stroke); - gpd->flag |= GP_DATA_PYTHON_UPDATED; DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL); diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index 31775a70af6..6c3f26003fa 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -73,6 +73,11 @@ const EnumPropertyItem rna_enum_object_greasepencil_modifier_type_items[] = { ICON_MOD_MIRROR, "Mirror", "Duplicate strokes like a mirror"}, + {eGpencilModifierType_Multiply, + "GP_MULTIPLY", + ICON_GP_MULTIFRAME_EDITING, + "Multiple Strokes", + "Produce multiple strokes along one stroke"}, {eGpencilModifierType_Simplify, "GP_SIMPLIFY", ICON_MOD_SIMPLIFY, @@ -83,11 +88,6 @@ const EnumPropertyItem rna_enum_object_greasepencil_modifier_type_items[] = { ICON_MOD_SUBSURF, "Subdivide", "Subdivide stroke adding more control points"}, - {eGpencilModifierType_Multiply, - "GP_MULTIPLY", - ICON_GP_MULTIFRAME_EDITING, - "Multiple Strokes", - "Produce multiple strokes along one stroke"}, {0, "", 0, N_("Deform"), ""}, {eGpencilModifierType_Armature, "GP_ARMATURE", @@ -1022,7 +1022,7 @@ static void rna_def_modifier_gpenciltint(BlenderRNA *brna) static EnumPropertyItem tint_mode_types_items[] = { {GPPAINT_MODE_STROKE, "STROKE", 0, "Stroke", "Vertex Color affects to Stroke only"}, {GPPAINT_MODE_FILL, "FILL", 0, "Fill", "Vertex Color affects to Fill only"}, - {GPPAINT_MODE_BOTH, "BOTH", 0, "Both", "Vertex Color affects to Stroke and Fill"}, + {GPPAINT_MODE_BOTH, "BOTH", 0, "Stroke and Fill", "Vertex Color affects to Stroke and Fill"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index 2797f3a2d84..73504200020 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -57,7 +57,7 @@ static const EnumPropertyItem image_source_items[] = { {IMA_SRC_MOVIE, "MOVIE", 0, "Movie", "Movie file"}, {IMA_SRC_GENERATED, "GENERATED", 0, "Generated", "Generated image"}, {IMA_SRC_VIEWER, "VIEWER", 0, "Viewer", "Compositing node viewer"}, - {IMA_SRC_TILED, "TILED", 0, "Tiled", "Tiled image texture"}, + {IMA_SRC_TILED, "TILED", 0, "UDIM Tiles", "Tiled UDIM image texture"}, {0, NULL, 0, NULL, NULL}, }; @@ -1001,7 +1001,7 @@ static void rna_def_image(BlenderRNA *brna) RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_generated_update"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - prop = RNA_def_property(srna, "generated_width", PROP_INT, PROP_NONE); + prop = RNA_def_property(srna, "generated_width", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "gen_x"); RNA_def_property_flag(prop, PROP_PROPORTIONAL); RNA_def_property_range(prop, 1, 65536); @@ -1009,7 +1009,7 @@ static void rna_def_image(BlenderRNA *brna) RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_generated_update"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - prop = RNA_def_property(srna, "generated_height", PROP_INT, PROP_NONE); + prop = RNA_def_property(srna, "generated_height", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "gen_y"); RNA_def_property_flag(prop, PROP_PROPORTIONAL); RNA_def_property_range(prop, 1, 65536); diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index 5c1697c70f4..127341e6801 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -520,13 +520,6 @@ static void rna_def_material_greasepencil(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Offset", "Shift Texture in 2d Space"); RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update"); - /* Texture opacity size */ - prop = RNA_def_property(srna, "texture_opacity", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "texture_opacity"); - RNA_def_property_range(prop, 0.0f, 1.0f); - RNA_def_property_ui_text(prop, "Opacity", "Texture Opacity"); - RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update"); - /* texture pixsize factor (used for UV along the stroke) */ prop = RNA_def_property(srna, "pixel_size", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "texture_pixsize"); diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index a91dd2e33c7..455fb1c50c9 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -93,7 +93,7 @@ const EnumPropertyItem rna_enum_object_modifier_type_items[] = { "UV_WARP", ICON_MOD_UVPROJECT, "UV Warp", - "Transform the UV map using the the difference between two objects"}, + "Transform the UV map using the difference between two objects"}, {eModifierType_WeightVGEdit, "VERTEX_WEIGHT_EDIT", ICON_MOD_VERTEX_WEIGHT, @@ -275,6 +275,7 @@ const EnumPropertyItem rna_enum_object_modifier_type_items[] = { ICON_MOD_EXPLODE, "Explode", "Break apart the mesh faces and let them follow particles"}, + {eModifierType_Fluid, "FLUID", ICON_MOD_FLUIDSIM, "Fluid Simulation", ""}, {eModifierType_Ocean, "OCEAN", ICON_MOD_OCEAN, "Ocean", "Generate a moving ocean surface"}, {eModifierType_ParticleInstance, "PARTICLE_INSTANCE", @@ -286,7 +287,6 @@ const EnumPropertyItem rna_enum_object_modifier_type_items[] = { ICON_MOD_PARTICLES, "Particle System", "Spawn particles from the shape"}, - {eModifierType_Fluid, "FLUID", ICON_MOD_FLUIDSIM, "Fluid Simulation", ""}, {eModifierType_Softbody, "SOFT_BODY", ICON_MOD_SOFT, "Soft Body", ""}, {eModifierType_Surface, "SURFACE", ICON_MODIFIER, "Surface", ""}, {0, NULL, 0, NULL, NULL}, @@ -797,6 +797,9 @@ RNA_MOD_VGROUP_NAME_SET(Shrinkwrap, vgroup_name); RNA_MOD_VGROUP_NAME_SET(SimpleDeform, vgroup_name); RNA_MOD_VGROUP_NAME_SET(Smooth, defgrp_name); RNA_MOD_VGROUP_NAME_SET(Solidify, defgrp_name); +RNA_MOD_VGROUP_NAME_SET(Solidify, shell_defgrp_name); +RNA_MOD_VGROUP_NAME_SET(Solidify, rim_defgrp_name); +RNA_MOD_VGROUP_NAME_SET(SurfaceDeform, defgrp_name); RNA_MOD_VGROUP_NAME_SET(UVWarp, vgroup_name); RNA_MOD_VGROUP_NAME_SET(Warp, defgrp_name); RNA_MOD_VGROUP_NAME_SET(Wave, defgrp_name); @@ -1795,17 +1798,29 @@ static void rna_def_modifier_warp(BlenderRNA *brna) RNA_def_struct_ui_icon(srna, ICON_MOD_WARP); prop = RNA_def_property(srna, "object_from", PROP_POINTER, PROP_NONE); - RNA_def_property_ui_text(prop, "From", "Object to transform from"); + RNA_def_property_pointer_sdna(prop, NULL, "object_from"); + RNA_def_property_ui_text(prop, "Object From", "Object to transform from"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); + prop = RNA_def_property(srna, "bone_from", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "bone_from"); + RNA_def_property_ui_text(prop, "Bone From", "Bone to transform from"); + RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); + prop = RNA_def_property(srna, "object_to", PROP_POINTER, PROP_NONE); - RNA_def_property_ui_text(prop, "To", "Object to transform to"); + RNA_def_property_pointer_sdna(prop, NULL, "object_to"); + RNA_def_property_ui_text(prop, "Object To", "Object to transform to"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); + prop = RNA_def_property(srna, "bone_to", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "bone_to"); + RNA_def_property_ui_text(prop, "Bone To", "Bone defining offset"); + RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); + prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); RNA_def_property_ui_range(prop, -100, 100, 10, 2); @@ -4437,6 +4452,22 @@ static void rna_def_modifier_solidify(BlenderRNA *brna) RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SolidifyModifier_defgrp_name_set"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "shell_vertex_group", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "shell_defgrp_name"); + RNA_def_property_ui_text(prop, + "Shell Vertex Group", + "Vertex group that the generated shell geometry will be weighted to"); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SolidifyModifier_shell_defgrp_name_set"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "rim_vertex_group", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "rim_defgrp_name"); + RNA_def_property_ui_text(prop, + "Rim Vertex Group", + "Vertex group that the generated rim geometry will be weighted to"); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SolidifyModifier_rim_defgrp_name_set"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "use_rim", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_SOLIDIFY_RIM); RNA_def_property_ui_text(prop, @@ -4507,14 +4538,14 @@ static void rna_def_modifier_screw(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); prop = RNA_def_property(srna, "steps", PROP_INT, PROP_UNSIGNED); - RNA_def_property_range(prop, 2, 10000); - RNA_def_property_ui_range(prop, 3, 512, 1, -1); + RNA_def_property_range(prop, 1, 10000); + RNA_def_property_ui_range(prop, 1, 512, 1, -1); RNA_def_property_ui_text(prop, "Steps", "Number of steps in the revolution"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); prop = RNA_def_property(srna, "render_steps", PROP_INT, PROP_UNSIGNED); - RNA_def_property_range(prop, 2, 10000); - RNA_def_property_ui_range(prop, 2, 512, 1, -1); + RNA_def_property_range(prop, 1, 10000); + RNA_def_property_ui_range(prop, 1, 512, 1, -1); RNA_def_property_ui_text(prop, "Render Steps", "Number of steps in the revolution"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); @@ -4802,6 +4833,16 @@ static void rna_def_modifier_weightvgedit(BlenderRNA *brna) RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */ RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "invert_falloff", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "edit_flags", MOD_WVG_INVERT_FALLOFF); + RNA_def_property_ui_text(prop, "Invert Falloff", "Invert the resulting falloff weight"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "map_curve", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "cmap_curve"); + RNA_def_property_ui_text(prop, "Mapping Curve", "Custom mapping curve"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "use_add", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "edit_flags", MOD_WVG_EDIT_ADD2VG); RNA_def_property_ui_text(prop, @@ -4827,11 +4868,6 @@ static void rna_def_modifier_weightvgedit(BlenderRNA *brna) "it is not in the vgroup"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - prop = RNA_def_property(srna, "map_curve", PROP_POINTER, PROP_NONE); - RNA_def_property_pointer_sdna(prop, NULL, "cmap_curve"); - RNA_def_property_ui_text(prop, "Mapping Curve", "Custom mapping curve"); - RNA_def_property_update(prop, 0, "rna_Modifier_update"); - prop = RNA_def_property(srna, "add_threshold", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "add_threshold"); RNA_def_property_range(prop, 0.0, 1.0); @@ -5060,6 +5096,11 @@ static void rna_def_modifier_weightvgproximity(BlenderRNA *brna) RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */ RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "invert_falloff", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "proximity_flags", MOD_WVG_PROXIMITY_INVERT_FALLOFF); + RNA_def_property_ui_text(prop, "Invert Falloff", "Invert the resulting falloff weight"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + /* Common masking properties. */ rna_def_modifier_weightvg_mask(brna, srna, @@ -6349,6 +6390,24 @@ static void rna_def_modifier_surfacedeform(BlenderRNA *brna) RNA_def_property_boolean_funcs(prop, "rna_SurfaceDeformModifier_is_bound_get", NULL); RNA_def_property_ui_text(prop, "Bound", "Whether geometry has been bound to target mesh"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); + + prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "defgrp_name"); + RNA_def_property_ui_text( + prop, "Vertex Group", "Vertex group name for selecting/weighting the affected areas"); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SurfaceDeformModifier_defgrp_name_set"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "invert_vertex_group", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_SDEF_INVERT_VGROUP); + RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, -100, 100); + RNA_def_property_ui_range(prop, -100, 100, 10, 2); + RNA_def_property_ui_text(prop, "Strength", "Strength of modifier deformations"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); } static void rna_def_modifier_weightednormal(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 959529450f0..112517a92e0 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -760,6 +760,24 @@ static PointerRNA rna_Object_active_vertex_group_get(PointerRNA *ptr) ptr, &RNA_VertexGroup, BLI_findlink(&ob->defbase, ob->actdef - 1)); } +static void rna_Object_active_vertex_group_set(PointerRNA *ptr, + PointerRNA value, + struct ReportList *reports) +{ + Object *ob = (Object *)ptr->owner_id; + int index = BLI_findindex(&ob->defbase, value.data); + if (index == -1) { + BKE_reportf(reports, + RPT_ERROR, + "VertexGroup '%s' not found in object '%s'", + ((bDeformGroup *)value.data)->name, + ob->id.name + 2); + return; + } + + ob->actdef = index + 1; +} + static int rna_Object_active_vertex_group_index_get(PointerRNA *ptr) { Object *ob = (Object *)ptr->owner_id; @@ -2333,6 +2351,7 @@ static void rna_def_object_vertex_groups(BlenderRNA *brna, PropertyRNA *cprop) "rna_Object_active_vertex_group_set", NULL, NULL); + RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Active Vertex Group", "Vertex groups of the object"); RNA_def_property_update(prop, NC_GEOM | ND_DATA, "rna_Object_internal_update_data"); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 932ac72324e..289c5eae869 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -2340,7 +2340,7 @@ static void rna_Stereo3dFormat_update(Main *bmain, Scene *UNUSED(scene), Pointer static ViewLayer *rna_ViewLayer_new(ID *id, Scene *UNUSED(sce), Main *bmain, const char *name) { Scene *scene = (Scene *)id; - ViewLayer *view_layer = BKE_view_layer_add(scene, name); + ViewLayer *view_layer = BKE_view_layer_add(scene, name, NULL, VIEWLAYER_ADD_NEW); DEG_id_tag_update(&scene->id, 0); DEG_relations_tag_update(bmain); @@ -2502,7 +2502,9 @@ static const EnumPropertyItem *rna_UnitSettings_itemf_wrapper(const int system, } } + RNA_enum_item_end(&items, &totitem); *r_free = true; + return items; } @@ -2553,6 +2555,11 @@ static char *rna_UnitSettings_path(PointerRNA *UNUSED(ptr)) return BLI_strdup("unit_settings"); } +static char *rna_FFmpegSettings_path(PointerRNA *UNUSED(ptr)) +{ + return BLI_strdup("render.ffmpeg"); +} + #else /* Grease Pencil Interpolation tool settings */ @@ -5459,6 +5466,7 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna) srna = RNA_def_struct(brna, "FFmpegSettings", NULL); RNA_def_struct_sdna(srna, "FFMpegCodecData"); + RNA_def_struct_path_func(srna, "rna_FFmpegSettings_path"); RNA_def_struct_ui_text(srna, "FFmpeg Settings", "FFmpeg related settings for the scene"); # ifdef WITH_FFMPEG @@ -6372,12 +6380,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna) 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, "use_simplify_smoke_highres", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "simplify_smoke_ignore_highres", 1); - RNA_def_property_ui_text( - prop, "Use High-resolution Smoke", "Display high-resolution smoke in the viewport"); - RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); - /* Grease Pencil - Simplify Options */ prop = RNA_def_property(srna, "simplify_gpencil", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "simplify_gpencil", SIMPLIFY_GPENCIL_ENABLE); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index cf85cc888f8..302495a72af 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -859,7 +859,12 @@ static void rna_SpaceView3D_use_local_camera_set(PointerRNA *ptr, bool value) if (!value) { Scene *scene = ED_screen_scene_find(sc, G_MAIN->wm.first); - v3d->camera = scene->camera; + /* NULL if the screen isn't in an active window (happens when setting from Python). + * This could be moved to the update function, in that case the scene wont relate to the screen + * so keep it working this way. */ + if (scene != NULL) { + v3d->camera = scene->camera; + } } } @@ -868,8 +873,13 @@ static float rna_View3DOverlay_GridScaleUnit_get(PointerRNA *ptr) View3D *v3d = (View3D *)(ptr->data); bScreen *screen = (bScreen *)ptr->owner_id; Scene *scene = ED_screen_scene_find(screen, G_MAIN->wm.first); - - return ED_view3d_grid_scale(scene, v3d, NULL); + if (scene != NULL) { + return ED_view3d_grid_scale(scene, v3d, NULL); + } + else { + /* When accessed from non-active screen. */ + return 1.0f; + } } static PointerRNA rna_SpaceView3D_region_3d_get(PointerRNA *ptr) diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c index df6abecd365..4bed8c7bb8c 100644 --- a/source/blender/makesrna/intern/rna_wm_api.c +++ b/source/blender/makesrna/intern/rna_wm_api.c @@ -392,16 +392,34 @@ static PointerRNA rna_KeyMap_item_match_event(ID *id, wmKeyMap *km, bContext *C, return kmi_ptr; } -static wmKeyMap *rna_keymap_new( - wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid, bool modal, bool tool) +static wmKeyMap *rna_keymap_new(wmKeyConfig *keyconf, + ReportList *reports, + const char *idname, + int spaceid, + int regionid, + bool modal, + bool tool) { + if (modal) { + /* Sanity check: Don't allow add-ons to override internal modal key-maps + * because this isn't supported, the restriction can be removed when + * add-ons can define modal key-maps. + * Currently this is only useful for add-ons to override built-in modal keymaps + * which is not the intended use for add-on keymaps. */ + wmWindowManager *wm = G_MAIN->wm.first; + if (keyconf == wm->addonconf) { + BKE_reportf(reports, RPT_ERROR, "Modal key-maps not supported for add-on key-config"); + return NULL; + } + } + wmKeyMap *keymap; if (modal == 0) { keymap = WM_keymap_ensure(keyconf, idname, spaceid, regionid); } else { - keymap = WM_modalkeymap_add(keyconf, idname, NULL); /* items will be lazy init */ + keymap = WM_modalkeymap_ensure(keyconf, idname, NULL); /* items will be lazy init */ } if (keymap && tool) { @@ -1180,6 +1198,7 @@ void RNA_api_keymaps(StructRNA *srna) PropertyRNA *parm; func = RNA_def_function(srna, "new", "rna_keymap_new"); /* add_keymap */ + RNA_def_function_flag(func, FUNC_USE_REPORTS); parm = RNA_def_string(func, "name", NULL, 0, "Name", ""); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); RNA_def_enum(func, "space_type", rna_enum_space_type_items, SPACE_EMPTY, "Space Type", ""); diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c index 3e78662da6c..275c16873a8 100644 --- a/source/blender/modifiers/intern/MOD_armature.c +++ b/source/blender/modifiers/intern/MOD_armature.c @@ -234,7 +234,7 @@ static void deformMatrices(ModifierData *md, amd->defgrp_name, NULL); - if (mesh_src != mesh) { + if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); } } diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c index ed4a53ba2f3..eb6292e5e46 100644 --- a/source/blender/modifiers/intern/MOD_cast.c +++ b/source/blender/modifiers/intern/MOD_cast.c @@ -513,7 +513,7 @@ static void deformVertsEM(ModifierData *md, sphere_do(cmd, ctx, ctx->object, mesh_src, vertexCos, numVerts); } - if (mesh_src != mesh) { + if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); } } diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c index af468cb2d27..e1595488d08 100644 --- a/source/blender/modifiers/intern/MOD_collision.c +++ b/source/blender/modifiers/intern/MOD_collision.c @@ -231,7 +231,7 @@ static void deformVerts(ModifierData *md, } } - if (mesh_src != mesh) { + if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); } } diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c index 4eea9092e10..52003f8b1d8 100644 --- a/source/blender/modifiers/intern/MOD_correctivesmooth.c +++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c @@ -740,7 +740,7 @@ static void deformVerts(ModifierData *md, correctivesmooth_modifier_do( md, ctx->depsgraph, ctx->object, mesh_src, vertexCos, (uint)numVerts, NULL); - if (mesh_src != mesh) { + if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); } } @@ -758,7 +758,7 @@ static void deformVertsEM(ModifierData *md, correctivesmooth_modifier_do( md, ctx->depsgraph, ctx->object, mesh_src, vertexCos, (uint)numVerts, editData); - if (mesh_src != mesh) { + if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); } } diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c index 742d100ac44..ad8e0a9f259 100644 --- a/source/blender/modifiers/intern/MOD_multires.c +++ b/source/blender/modifiers/intern/MOD_multires.c @@ -61,7 +61,7 @@ static void initData(ModifierData *md) mmd->totlvl = 0; mmd->uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_CORNERS; mmd->quality = 4; - mmd->flags |= eMultiresModifierFlag_UseCrease; + mmd->flags |= (eMultiresModifierFlag_UseCrease | eMultiresModifierFlag_ControlEdges); } static void copyData(const ModifierData *md_src, ModifierData *md_dst, const int flag) @@ -119,11 +119,17 @@ static Mesh *multires_as_mesh(MultiresModifierData *mmd, Mesh *result = mesh; const bool use_render_params = (ctx->flag & MOD_APPLY_RENDER); const bool ignore_simplify = (ctx->flag & MOD_APPLY_IGNORE_SIMPLIFY); + const bool ignore_control_edges = (ctx->flag & MOD_APPLY_TO_BASE_MESH); const Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph); Object *object = ctx->object; SubdivToMeshSettings mesh_settings; - BKE_multires_subdiv_mesh_settings_init( - &mesh_settings, scene, object, mmd, use_render_params, ignore_simplify); + BKE_multires_subdiv_mesh_settings_init(&mesh_settings, + scene, + object, + mmd, + use_render_params, + ignore_simplify, + ignore_control_edges); if (mesh_settings.resolution < 3) { return result; } diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c index e6229e27e4b..05bfe9aeff0 100644 --- a/source/blender/modifiers/intern/MOD_particlesystem.c +++ b/source/blender/modifiers/intern/MOD_particlesystem.c @@ -189,7 +189,7 @@ static void deformVerts(ModifierData *md, BKE_mesh_tessface_ensure(psmd->mesh_original); } - if (mesh_src != psmd->mesh_final && mesh_src != mesh) { + if (!ELEM(mesh_src, NULL, mesh, psmd->mesh_final)) { BKE_id_free(NULL, mesh_src); } diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c index 8921ddb894f..e832a23b4ed 100644 --- a/source/blender/modifiers/intern/MOD_screw.c +++ b/source/blender/modifiers/intern/MOD_screw.c @@ -352,12 +352,9 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes * Note! smaller then `FLT_EPSILON * 100` * gives problems with float precision so its never closed. */ if (fabsf(screw_ofs) <= (FLT_EPSILON * 100.0f) && - fabsf(fabsf(angle) - ((float)M_PI * 2.0f)) <= (FLT_EPSILON * 100.0f)) { + fabsf(fabsf(angle) - ((float)M_PI * 2.0f)) <= (FLT_EPSILON * 100.0f) && step_tot > 3) { close = 1; step_tot--; - if (step_tot < 3) { - step_tot = 3; - } maxVerts = totvert * step_tot; /* -1 because we're joining back up */ maxEdges = (totvert * step_tot) + /* these are the edges between new verts */ @@ -368,8 +365,8 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes } else { close = 0; - if (step_tot < 3) { - step_tot = 3; + if (step_tot < 2) { + step_tot = 2; } maxVerts = totvert * step_tot; /* -1 because we're joining back up */ diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c index 8ea0a602b65..0eed2335ed7 100644 --- a/source/blender/modifiers/intern/MOD_solidify.c +++ b/source/blender/modifiers/intern/MOD_solidify.c @@ -62,7 +62,8 @@ static void requiredDataMask(Object *UNUSED(ob), SolidifyModifierData *smd = (SolidifyModifierData *)md; /* ask for vertexgroups if we need them */ - if (smd->defgrp_name[0] != '\0') { + if (smd->defgrp_name[0] != '\0' || smd->shell_defgrp_name[0] != '\0' || + smd->rim_defgrp_name[0] != '\0') { r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT; } } @@ -70,11 +71,13 @@ static void requiredDataMask(Object *UNUSED(ob), static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { const SolidifyModifierData *smd = (SolidifyModifierData *)md; - if (smd->mode == MOD_SOLIDIFY_MODE_EXTRUDE) { - return MOD_solidify_extrude_applyModifier(md, ctx, mesh); - } - else if (smd->mode == MOD_SOLIDIFY_MODE_NONMANIFOLD) { - return MOD_solidify_nonmanifold_applyModifier(md, ctx, mesh); + switch (smd->mode) { + case MOD_SOLIDIFY_MODE_EXTRUDE: + return MOD_solidify_extrude_applyModifier(md, ctx, mesh); + case MOD_SOLIDIFY_MODE_NONMANIFOLD: + return MOD_solidify_nonmanifold_applyModifier(md, ctx, mesh); + default: + BLI_assert(0); } return mesh; } diff --git a/source/blender/modifiers/intern/MOD_solidify_extrude.c b/source/blender/modifiers/intern/MOD_solidify_extrude.c index 8febf78fef5..ecd62e5e1fe 100644 --- a/source/blender/modifiers/intern/MOD_solidify_extrude.c +++ b/source/blender/modifiers/intern/MOD_solidify_extrude.c @@ -240,6 +240,9 @@ Mesh *MOD_solidify_extrude_applyModifier(ModifierData *md, MDeformVert *dvert; const bool defgrp_invert = (smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0; int defgrp_index; + const int shell_defgrp_index = BKE_object_defgroup_name_index(ctx->object, + smd->shell_defgrp_name); + const int rim_defgrp_index = BKE_object_defgroup_name_index(ctx->object, smd->rim_defgrp_name); /* array size is doubled in case of using a shell */ const uint stride = do_shell ? 2 : 1; @@ -886,6 +889,36 @@ Mesh *MOD_solidify_extrude_applyModifier(ModifierData *md, } } + /* Add vertex weights for rim and shell vgroups. */ + if (shell_defgrp_index != -1 || rim_defgrp_index != -1) { + dvert = CustomData_duplicate_referenced_layer(&result->vdata, CD_MDEFORMVERT, result->totvert); + /* If no vertices were ever added to an object's vgroup, dvert might be NULL. */ + if (dvert == NULL) { + /* Add a valid data layer! */ + dvert = CustomData_add_layer( + &result->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, result->totvert); + } + /* Ultimate security check. */ + if (!dvert) { + return result; + } + result->dvert = dvert; + + if (rim_defgrp_index != -1) { + for (uint i = 0; i < rimVerts; i++) { + BKE_defvert_ensure_index(&result->dvert[new_vert_arr[i]], rim_defgrp_index)->weight = 1.0f; + BKE_defvert_ensure_index(&result->dvert[(do_shell ? new_vert_arr[i] : i) + numVerts], + rim_defgrp_index) + ->weight = 1.0f; + } + } + + if (shell_defgrp_index != -1) { + for (uint i = numVerts; i < result->totvert; i++) { + BKE_defvert_ensure_index(&result->dvert[i], shell_defgrp_index)->weight = 1.0f; + } + } + } if (smd->flag & MOD_SOLIDIFY_RIM) { uint i; diff --git a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c index 22fc56bdeaf..0f9f5952a26 100644 --- a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c +++ b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c @@ -178,6 +178,9 @@ Mesh *MOD_solidify_nonmanifold_applyModifier(ModifierData *md, MDeformVert *dvert; const bool defgrp_invert = (smd->flag & MOD_SOLIDIFY_VGROUP_INV) != 0; int defgrp_index; + const int shell_defgrp_index = BKE_object_defgroup_name_index(ctx->object, + smd->shell_defgrp_name); + const int rim_defgrp_index = BKE_object_defgroup_name_index(ctx->object, smd->rim_defgrp_name); MOD_get_vgroup(ctx->object, mesh, smd->defgrp_name, &dvert, &defgrp_index); @@ -1778,6 +1781,18 @@ Mesh *MOD_solidify_nonmanifold_applyModifier(ModifierData *md, int *origindex_edge = CustomData_get_layer(&result->edata, CD_ORIGINDEX); int *origindex_poly = CustomData_get_layer(&result->pdata, CD_ORIGINDEX); + /* Checks that result has dvert data. */ + if (shell_defgrp_index != -1 || rim_defgrp_index != -1) { + dvert = CustomData_duplicate_referenced_layer(&result->vdata, CD_MDEFORMVERT, result->totvert); + /* If no vertices were ever added to an object's vgroup, dvert might be NULL. */ + if (dvert == NULL) { + /* Add a valid data layer! */ + dvert = CustomData_add_layer( + &result->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, result->totvert); + } + result->dvert = dvert; + } + /* Make_new_verts. */ { gs_ptr = orig_vert_groups_arr; @@ -2101,12 +2116,20 @@ Mesh *MOD_solidify_nonmanifold_applyModifier(ModifierData *md, MEdge *open_face_edge; uint open_face_edge_index; if (!do_flip) { + if (rim_defgrp_index != -1) { + BKE_defvert_ensure_index(&result->dvert[medge[edge1->new_edge].v1], rim_defgrp_index) + ->weight = 1.0f; + } CustomData_copy_data(&mesh->ldata, &result->ldata, loop1, (int)loop_index, 1); mloop[loop_index].v = medge[edge1->new_edge].v1; mloop[loop_index++].e = edge1->new_edge; if (!v2_singularity) { open_face_edge_index = edge1->link_edge_groups[1]->open_face_edge; + if (rim_defgrp_index != -1) { + BKE_defvert_ensure_index(&result->dvert[medge[edge1->new_edge].v2], rim_defgrp_index) + ->weight = 1.0f; + } CustomData_copy_data(&mesh->ldata, &result->ldata, loop2, (int)loop_index, 1); mloop[loop_index].v = medge[edge1->new_edge].v2; open_face_edge = medge + open_face_edge_index; @@ -2118,12 +2141,20 @@ Mesh *MOD_solidify_nonmanifold_applyModifier(ModifierData *md, } } + if (rim_defgrp_index != -1) { + BKE_defvert_ensure_index(&result->dvert[medge[edge2->new_edge].v2], rim_defgrp_index) + ->weight = 1.0f; + } CustomData_copy_data(&mesh->ldata, &result->ldata, loop2, (int)loop_index, 1); mloop[loop_index].v = medge[edge2->new_edge].v2; mloop[loop_index++].e = edge2->new_edge; if (!v1_singularity) { open_face_edge_index = edge2->link_edge_groups[0]->open_face_edge; + if (rim_defgrp_index != -1) { + BKE_defvert_ensure_index(&result->dvert[medge[edge2->new_edge].v1], rim_defgrp_index) + ->weight = 1.0f; + } CustomData_copy_data(&mesh->ldata, &result->ldata, loop1, (int)loop_index, 1); mloop[loop_index].v = medge[edge2->new_edge].v1; open_face_edge = medge + open_face_edge_index; @@ -2138,6 +2169,10 @@ Mesh *MOD_solidify_nonmanifold_applyModifier(ModifierData *md, else { if (!v1_singularity) { open_face_edge_index = edge1->link_edge_groups[0]->open_face_edge; + if (rim_defgrp_index != -1) { + BKE_defvert_ensure_index(&result->dvert[medge[edge1->new_edge].v1], rim_defgrp_index) + ->weight = 1.0f; + } CustomData_copy_data(&mesh->ldata, &result->ldata, loop1, (int)loop_index, 1); mloop[loop_index].v = medge[edge1->new_edge].v1; open_face_edge = medge + open_face_edge_index; @@ -2149,12 +2184,20 @@ Mesh *MOD_solidify_nonmanifold_applyModifier(ModifierData *md, } } + if (rim_defgrp_index != -1) { + BKE_defvert_ensure_index(&result->dvert[medge[edge2->new_edge].v1], rim_defgrp_index) + ->weight = 1.0f; + } CustomData_copy_data(&mesh->ldata, &result->ldata, loop1, (int)loop_index, 1); mloop[loop_index].v = medge[edge2->new_edge].v1; mloop[loop_index++].e = edge2->new_edge; if (!v2_singularity) { open_face_edge_index = edge2->link_edge_groups[1]->open_face_edge; + if (rim_defgrp_index != -1) { + BKE_defvert_ensure_index(&result->dvert[medge[edge2->new_edge].v2], rim_defgrp_index) + ->weight = 1.0f; + } CustomData_copy_data(&mesh->ldata, &result->ldata, loop2, (int)loop_index, 1); mloop[loop_index].v = medge[edge2->new_edge].v2; open_face_edge = medge + open_face_edge_index; @@ -2166,6 +2209,10 @@ Mesh *MOD_solidify_nonmanifold_applyModifier(ModifierData *md, } } + if (rim_defgrp_index != -1) { + BKE_defvert_ensure_index(&result->dvert[medge[edge1->new_edge].v2], rim_defgrp_index) + ->weight = 1.0f; + } CustomData_copy_data(&mesh->ldata, &result->ldata, loop2, (int)loop_index, 1); mloop[loop_index].v = medge[edge1->new_edge].v2; mloop[loop_index++].e = edge1->new_edge; @@ -2243,6 +2290,10 @@ Mesh *MOD_solidify_nonmanifold_applyModifier(ModifierData *md, mpoly[poly_index].flag = fr->face->flag; if (fr->reversed != do_flip) { for (int l = (int)k - 1; l >= 0; l--) { + if (shell_defgrp_index != -1) { + BKE_defvert_ensure_index(&result->dvert[face_verts[l]], shell_defgrp_index) + ->weight = 1.0f; + } CustomData_copy_data( &mesh->ldata, &result->ldata, (int)face_loops[l], (int)loop_index, 1); mloop[loop_index].v = face_verts[l]; diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c index 56180564be2..b3bc5a66e8c 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.c +++ b/source/blender/modifiers/intern/MOD_subsurf.c @@ -58,7 +58,7 @@ static void initData(ModifierData *md) smd->renderLevels = 2; smd->uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_CORNERS; smd->quality = 3; - smd->flags |= eSubsurfModifierFlag_UseCrease; + smd->flags |= (eSubsurfModifierFlag_UseCrease | eSubsurfModifierFlag_ControlEdges); } static void copyData(const ModifierData *md, ModifierData *target, const int flag) @@ -148,7 +148,8 @@ static void subdiv_mesh_settings_init(SubdivToMeshSettings *settings, { const int level = subdiv_levels_for_modifier_get(smd, ctx); settings->resolution = (1 << level) + 1; - settings->use_optimal_display = (smd->flags & eSubsurfModifierFlag_ControlEdges); + settings->use_optimal_display = (smd->flags & eSubsurfModifierFlag_ControlEdges) && + !(ctx->flag & MOD_APPLY_TO_BASE_MESH); } static Mesh *subdiv_as_mesh(SubsurfModifierData *smd, diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c index 57e7e2fa98b..4ef1f32462a 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.c +++ b/source/blender/modifiers/intern/MOD_surfacedeform.c @@ -36,6 +36,8 @@ #include "BKE_mesh_runtime.h" #include "BKE_modifier.h" +#include "BKE_deform.h" + #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" @@ -110,6 +112,8 @@ typedef struct SDefDeformData { const SDefVert *const bind_verts; float (*const targetCos)[3]; float (*const vertexCos)[3]; + float(*const weights); + float const strength; } SDefDeformData; /* Bind result values */ @@ -136,6 +140,19 @@ static void initData(ModifierData *md) smd->verts = NULL; smd->flags = 0; smd->falloff = 4.0f; + smd->strength = 1.0f; +} + +static void requiredDataMask(Object *UNUSED(ob), + ModifierData *md, + CustomData_MeshMasks *r_cddata_masks) +{ + SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md; + + /* Ask for vertex groups if we need them. */ + if (smd->defgrp_name[0] != '\0') { + r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT; + } } static void freeData(ModifierData *md) @@ -1123,9 +1140,16 @@ static void deformVert(void *__restrict userdata, const SDefBind *sdbind = data->bind_verts[index].binds; const int num_binds = data->bind_verts[index].numbinds; float *const vertexCos = data->vertexCos[index]; - float norm[3], temp[3]; + float norm[3], temp[3], offset[3]; + const float weight = (data->weights != NULL) ? data->weights[index] : 1.0f; - zero_v3(vertexCos); + /* Check if this vertex will be deformed. If it is not deformed we return and avoid + * unnecessary calculations. */ + if (weight == 0.0f) { + return; + } + + zero_v3(offset); /* Allocate a `coords_buffer` that fits all the temp-data. */ int max_verts = 0; @@ -1170,8 +1194,13 @@ static void deformVert(void *__restrict userdata, /* Apply normal offset (generic for all modes) */ madd_v3_v3fl(temp, norm, sdbind->normal_dist); - madd_v3_v3fl(vertexCos, temp, sdbind->influence); + madd_v3_v3fl(offset, temp, sdbind->influence); } + /* Subtract the vertex coord to get the deformation offset. */ + sub_v3_v3(offset, vertexCos); + + /* Add the offset to start coord multiplied by the strength and weight values. */ + madd_v3_v3fl(vertexCos, offset, data->strength * weight); MEM_freeN(coords_buffer); } @@ -1179,7 +1208,8 @@ static void surfacedeformModifier_do(ModifierData *md, const ModifierEvalContext *ctx, float (*vertexCos)[3], uint numverts, - Object *ob) + Object *ob, + Mesh *mesh) { SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md; Mesh *target; @@ -1238,11 +1268,44 @@ static void surfacedeformModifier_do(ModifierData *md, return; } + /* Early out if modifier would not affect input at all - still *after* the sanity checks (and + * potential binding) above. + */ + if (smd->strength == 0.0f) { + return; + } + + int defgrp_index; + MDeformVert *dvert; + MOD_get_vgroup(ob, mesh, smd->defgrp_name, &dvert, &defgrp_index); + float *weights = NULL; + const bool invert_group = (smd->flags & MOD_SDEF_INVERT_VGROUP) != 0; + + if (defgrp_index != -1) { + dvert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MDEFORMVERT, mesh->totvert); + /* If no vertices were ever added to an object's vgroup, dvert might be NULL. */ + if (dvert == NULL) { + /* Add a valid data layer! */ + dvert = CustomData_add_layer(&mesh->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, mesh->totvert); + } + + if (dvert) { + weights = MEM_calloc_arrayN((size_t)numverts, sizeof(*weights), __func__); + MDeformVert *dv = dvert; + for (uint i = 0; i < numverts; i++, dv++) { + weights[i] = invert_group ? (1.0f - BKE_defvert_find_weight(dv, defgrp_index)) : + BKE_defvert_find_weight(dv, defgrp_index); + } + } + } + /* Actual vertex location update starts here */ SDefDeformData data = { .bind_verts = smd->verts, .targetCos = MEM_malloc_arrayN(tnumverts, sizeof(float[3]), "SDefTargetVertArray"), .vertexCos = vertexCos, + .weights = weights, + .strength = smd->strength, }; if (data.targetCos != NULL) { @@ -1259,25 +1322,51 @@ static void surfacedeformModifier_do(ModifierData *md, MEM_freeN(data.targetCos); } + + MEM_SAFE_FREE(weights); } static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, - Mesh *UNUSED(mesh), + Mesh *mesh, float (*vertexCos)[3], int numVerts) { - surfacedeformModifier_do(md, ctx, vertexCos, numVerts, ctx->object); + SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md; + Mesh *mesh_src = NULL; + + if (smd->defgrp_name[0] != '\0') { + /* Only need to use mesh_src when a vgroup is used. */ + mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false); + } + + surfacedeformModifier_do(md, ctx, vertexCos, numVerts, ctx->object, mesh_src); + + if (!ELEM(mesh_src, NULL, mesh)) { + BKE_id_free(NULL, mesh_src); + } } static void deformVertsEM(ModifierData *md, const ModifierEvalContext *ctx, - struct BMEditMesh *UNUSED(editData), - Mesh *UNUSED(mesh), + struct BMEditMesh *em, + Mesh *mesh, float (*vertexCos)[3], int numVerts) { - surfacedeformModifier_do(md, ctx, vertexCos, numVerts, ctx->object); + SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md; + Mesh *mesh_src = NULL; + + if (smd->defgrp_name[0] != '\0') { + /* Only need to use mesh_src when a vgroup is used. */ + mesh_src = MOD_deform_mesh_eval_get(ctx->object, em, mesh, NULL, numVerts, false, false); + } + + surfacedeformModifier_do(md, ctx, vertexCos, numVerts, ctx->object, mesh_src); + + if (!ELEM(mesh_src, NULL, mesh)) { + BKE_id_free(NULL, mesh_src); + } } static bool isDisabled(const Scene *UNUSED(scene), ModifierData *md, bool UNUSED(useRenderParams)) @@ -1309,7 +1398,7 @@ ModifierTypeInfo modifierType_SurfaceDeform = { /* applyModifier */ NULL, /* initData */ initData, - /* requiredDataMask */ NULL, + /* requiredDataMask */ requiredDataMask, /* freeData */ freeData, /* isDisabled */ isDisabled, /* updateDepsgraph */ updateDepsgraph, diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c index 4a98afbb91c..b8db14f610a 100644 --- a/source/blender/modifiers/intern/MOD_warp.c +++ b/source/blender/modifiers/intern/MOD_warp.c @@ -32,6 +32,7 @@ #include "BKE_colortools.h" #include "BKE_deform.h" +#include "BKE_action.h" /* BKE_pose_channel_find_name */ #include "BKE_editmesh.h" #include "BKE_lib_id.h" #include "BKE_lib_query.h" @@ -85,6 +86,19 @@ static void requiredDataMask(Object *UNUSED(ob), } } +static void matrix_from_obj_pchan(float mat[4][4], float obinv[4][4], Object *ob, const char *bonename) +{ + bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bonename); + if (pchan) { + float mat_bone_world[4][4]; + mul_m4_m4m4(mat_bone_world, ob->obmat, pchan->pose_mat); + mul_m4_m4m4(mat, obinv, mat_bone_world); + } + else { + mul_m4_m4m4(mat, obinv, ob->obmat); + } +} + static bool dependsOnTime(ModifierData *md) { WarpModifierData *wmd = (WarpModifierData *)md; @@ -135,15 +149,29 @@ static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void walk(userData, ob, md, "texture"); } +static void warp_deps_object_bone_new(struct DepsNodeHandle *node, + Object *object, + const char *bonename) +{ + if (bonename[0] && object->type == OB_ARMATURE) { + DEG_add_object_relation(node, object, DEG_OB_COMP_EVAL_POSE, "Warp Modifier"); + } + else { + DEG_add_object_relation(node, object, DEG_OB_COMP_TRANSFORM, "Warp Modifier"); + } +} + static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) { WarpModifierData *wmd = (WarpModifierData *)md; + if (wmd->object_from != NULL && wmd->object_to != NULL) { - DEG_add_modifier_to_transform_relation(ctx->node, "Warplace Modifier"); - DEG_add_object_relation( - ctx->node, wmd->object_from, DEG_OB_COMP_TRANSFORM, "Warp Modifier from"); - DEG_add_object_relation(ctx->node, wmd->object_to, DEG_OB_COMP_TRANSFORM, "Warp Modifier to"); + warp_deps_object_bone_new(ctx->node, wmd->object_from, wmd->bone_from); + warp_deps_object_bone_new(ctx->node, wmd->object_to, wmd->bone_to); + + DEG_add_modifier_to_transform_relation(ctx->node, "Warp Modifier"); } + if ((wmd->texmapping == MOD_DISP_MAP_OBJECT) && wmd->map_object != NULL) { DEG_add_object_relation( ctx->node, wmd->map_object, DEG_OB_COMP_TRANSFORM, "Warp Modifier map"); @@ -197,8 +225,9 @@ static void warpModifier_do(WarpModifierData *wmd, invert_m4_m4(obinv, ob->obmat); - mul_m4_m4m4(mat_from, obinv, wmd->object_from->obmat); - mul_m4_m4m4(mat_to, obinv, wmd->object_to->obmat); + /* Checks that the objects/bones are available. */ + matrix_from_obj_pchan(mat_from, obinv, wmd->object_from, wmd->bone_from); + matrix_from_obj_pchan(mat_to, obinv, wmd->object_to, wmd->bone_to); invert_m4_m4(tmat, mat_from); // swap? mul_m4_m4m4(mat_final, tmat, mat_to); diff --git a/source/blender/modifiers/intern/MOD_weightvg_util.c b/source/blender/modifiers/intern/MOD_weightvg_util.c index e93ab608498..23e4da32ed7 100644 --- a/source/blender/modifiers/intern/MOD_weightvg_util.c +++ b/source/blender/modifiers/intern/MOD_weightvg_util.c @@ -54,20 +54,22 @@ * mapping to the real vertex index (in case the weight tables do not cover the whole vertices...). * cmap might be NULL, in which case curve mapping mode will return unmodified data. */ -void weightvg_do_map(int num, float *new_w, short falloff_type, CurveMapping *cmap, RNG *rng) +void weightvg_do_map( + int num, float *new_w, short falloff_type, const bool do_invert, CurveMapping *cmap, RNG *rng) { int i; /* Return immediately, if we have nothing to do! */ /* Also security checks... */ - if (((falloff_type == MOD_WVG_MAPPING_CURVE) && (cmap == NULL)) || !ELEM(falloff_type, - MOD_WVG_MAPPING_CURVE, - MOD_WVG_MAPPING_SHARP, - MOD_WVG_MAPPING_SMOOTH, - MOD_WVG_MAPPING_ROOT, - MOD_WVG_MAPPING_SPHERE, - MOD_WVG_MAPPING_RANDOM, - MOD_WVG_MAPPING_STEP)) { + if (!do_invert && (((falloff_type == MOD_WVG_MAPPING_CURVE) && (cmap == NULL)) || + !ELEM(falloff_type, + MOD_WVG_MAPPING_CURVE, + MOD_WVG_MAPPING_SHARP, + MOD_WVG_MAPPING_SMOOTH, + MOD_WVG_MAPPING_ROOT, + MOD_WVG_MAPPING_SPHERE, + MOD_WVG_MAPPING_RANDOM, + MOD_WVG_MAPPING_STEP))) { return; } @@ -103,9 +105,14 @@ void weightvg_do_map(int num, float *new_w, short falloff_type, CurveMapping *cm case MOD_WVG_MAPPING_STEP: fac = (fac >= 0.5f) ? 1.0f : 0.0f; break; + case MOD_WVG_MAPPING_NONE: + BLI_assert(do_invert); + break; + default: + BLI_assert(0); } - new_w[i] = fac; + new_w[i] = do_invert ? 1.0f - fac : fac; } } diff --git a/source/blender/modifiers/intern/MOD_weightvg_util.h b/source/blender/modifiers/intern/MOD_weightvg_util.h index fa3c61a6b6f..bcd1076eac6 100644 --- a/source/blender/modifiers/intern/MOD_weightvg_util.h +++ b/source/blender/modifiers/intern/MOD_weightvg_util.h @@ -52,8 +52,12 @@ struct Tex; */ #define MOD_WVG_ZEROFLOOR 1.0e-32f -void weightvg_do_map( - int num, float *new_w, short mode, struct CurveMapping *cmap, struct RNG *rng); +void weightvg_do_map(int num, + float *new_w, + short mode, + const bool do_invert, + struct CurveMapping *cmap, + struct RNG *rng); void weightvg_do_mask(const ModifierEvalContext *ctx, const int num, diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c index 6acbbefe745..ba1745f7b5e 100644 --- a/source/blender/modifiers/intern/MOD_weightvgedit.c +++ b/source/blender/modifiers/intern/MOD_weightvgedit.c @@ -230,14 +230,15 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes } /* Do mapping. */ - if (wmd->falloff_type != MOD_WVG_MAPPING_NONE) { + const bool do_invert_mapping = (wmd->edit_flags & MOD_WVG_INVERT_FALLOFF) != 0; + if (do_invert_mapping || wmd->falloff_type != MOD_WVG_MAPPING_NONE) { RNG *rng = NULL; if (wmd->falloff_type == MOD_WVG_MAPPING_RANDOM) { rng = BLI_rng_new_srandom(BLI_ghashutil_strhash(ctx->object->id.name + 2)); } - weightvg_do_map(numVerts, new_w, wmd->falloff_type, wmd->cmap_curve, rng); + weightvg_do_map(numVerts, new_w, wmd->falloff_type, do_invert_mapping, wmd->cmap_curve, rng); if (rng) { BLI_rng_free(rng); diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index e2e8e732311..7c9242ed900 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -239,8 +239,13 @@ static float get_ob2ob_distance(const Object *ob, const Object *obr) /** * Maps distances to weights, with an optional "smoothing" mapping. */ -static void do_map( - Object *ob, float *weights, const int nidx, const float min_d, const float max_d, short mode) +static void do_map(Object *ob, + float *weights, + const int nidx, + const float min_d, + const float max_d, + short mode, + const bool do_invert_mapping) { const float range_inv = 1.0f / (max_d - min_d); /* invert since multiplication is faster */ uint i = nidx; @@ -276,14 +281,15 @@ static void do_map( } } - if (!ELEM(mode, MOD_WVG_MAPPING_NONE, MOD_WVG_MAPPING_CURVE)) { + BLI_assert(mode != MOD_WVG_MAPPING_CURVE); + if (do_invert_mapping || mode != MOD_WVG_MAPPING_NONE) { RNG *rng = NULL; if (mode == MOD_WVG_MAPPING_RANDOM) { rng = BLI_rng_new_srandom(BLI_ghashutil_strhash(ob->id.name + 2)); } - weightvg_do_map(nidx, weights, mode, NULL, rng); + weightvg_do_map(nidx, weights, mode, do_invert_mapping, NULL, rng); if (rng) { BLI_rng_free(rng); @@ -559,7 +565,13 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes } /* Map distances to weights. */ - do_map(ob, new_w, numIdx, wmd->min_dist, wmd->max_dist, wmd->falloff_type); + do_map(ob, + new_w, + numIdx, + wmd->min_dist, + wmd->max_dist, + wmd->falloff_type, + (wmd->proximity_flags & MOD_WVG_PROXIMITY_INVERT_FALLOFF) != 0); /* Do masking. */ struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph); diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c index b4b1c1d3698..bfef9341913 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c @@ -154,6 +154,12 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, /* equivalent to normal_world_to_object */ GPU_link(mat, "normal_transform_transposed_m4v3", vnor, ob_mat, &norm); + { + /* See SHD_PROJ_FLAT for explanation. */ + GPU_link(mat, "set_rgb", *texco, texco); + GPU_link(mat, "set_rgb", *texco, &input_coords); + in[0].link = input_coords; + } GPU_link( mat, gpu_node_name, *texco, norm, GPU_image(mat, ima, iuser), &col1, &col2, &col3); GPU_stack_link( diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index 35fff8699d1..9c84a4bb824 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -360,15 +360,15 @@ void PyC_StackSpit(void) } } -void PyC_FileAndNum(const char **filename, int *lineno) +void PyC_FileAndNum(const char **r_filename, int *r_lineno) { PyFrameObject *frame; - if (filename) { - *filename = NULL; + if (r_filename) { + *r_filename = NULL; } - if (lineno) { - *lineno = -1; + if (r_lineno) { + *r_lineno = -1; } if (!(frame = PyThreadState_GET()->frame)) { @@ -376,13 +376,13 @@ void PyC_FileAndNum(const char **filename, int *lineno) } /* when executing a script */ - if (filename) { - *filename = _PyUnicode_AsString(frame->f_code->co_filename); + if (r_filename) { + *r_filename = _PyUnicode_AsString(frame->f_code->co_filename); } /* when executing a module */ - if (filename && *filename == NULL) { - /* try an alternative method to get the filename - module based + if (r_filename && *r_filename == NULL) { + /* try an alternative method to get the r_filename - module based * references below are all borrowed (double checked) */ PyObject *mod_name = PyDict_GetItemString(PyEval_GetGlobals(), "__name__"); if (mod_name) { @@ -390,7 +390,7 @@ void PyC_FileAndNum(const char **filename, int *lineno) if (mod) { PyObject *mod_file = PyModule_GetFilenameObject(mod); if (mod_file) { - *filename = _PyUnicode_AsString(mod_name); + *r_filename = _PyUnicode_AsString(mod_name); Py_DECREF(mod_file); } else { @@ -399,24 +399,24 @@ void PyC_FileAndNum(const char **filename, int *lineno) } /* unlikely, fallback */ - if (*filename == NULL) { - *filename = _PyUnicode_AsString(mod_name); + if (*r_filename == NULL) { + *r_filename = _PyUnicode_AsString(mod_name); } } } - if (lineno) { - *lineno = PyFrame_GetLineNumber(frame); + if (r_lineno) { + *r_lineno = PyFrame_GetLineNumber(frame); } } -void PyC_FileAndNum_Safe(const char **filename, int *lineno) +void PyC_FileAndNum_Safe(const char **r_filename, int *r_lineno) { if (!PyC_IsInterpreterActive()) { return; } - PyC_FileAndNum(filename, lineno); + PyC_FileAndNum(r_filename, r_lineno); } /* Would be nice if python had this built in */ diff --git a/source/blender/python/generic/py_capi_utils.h b/source/blender/python/generic/py_capi_utils.h index 5fb5737e1f9..e8b2e8ff502 100644 --- a/source/blender/python/generic/py_capi_utils.h +++ b/source/blender/python/generic/py_capi_utils.h @@ -38,8 +38,8 @@ PyObject *PyC_Err_SetString_Prefix(PyObject *exception_type_prefix, const char * void PyC_Err_PrintWithFunc(PyObject *py_func); -void PyC_FileAndNum(const char **filename, int *lineno); -void PyC_FileAndNum_Safe(const char **filename, int *lineno); /* checks python is running */ +void PyC_FileAndNum(const char **r_filename, int *r_lineno); +void PyC_FileAndNum_Safe(const char **r_filename, int *r_lineno); /* checks python is running */ int PyC_AsArray_FAST(void *array, PyObject *value_fast, const Py_ssize_t length, diff --git a/source/blender/python/intern/bpy_app_translations.c b/source/blender/python/intern/bpy_app_translations.c index cf4550089ba..190d4eb1855 100644 --- a/source/blender/python/intern/bpy_app_translations.c +++ b/source/blender/python/intern/bpy_app_translations.c @@ -45,6 +45,10 @@ # include "BLI_string.h" #endif +/* ------------------------------------------------------------------- */ +/** \name Local Struct to Store Translation + * \{ */ + typedef struct { PyObject_HEAD /** The string used to separate context from actual message in PY_TRANSLATE RNA props. */ @@ -63,9 +67,14 @@ typedef struct { /* Our singleton instance pointer */ static BlenderAppTranslations *_translations = NULL; +/** \} */ + #ifdef WITH_INTERNATIONAL -/***** Helpers for ghash *****/ +/* ------------------------------------------------------------------- */ +/** \name Helpers for GHash + * \{ */ + typedef struct GHashKey { const char *msgctxt; const char *msgid; @@ -111,7 +120,11 @@ static void _ghashutil_keyfree(void *ptr) # define _ghashutil_valfree MEM_freeN -/***** Python's messages cache *****/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Python'S Messages Cache + * \{ */ /* We cache all messages available for a given locale from all py dicts into a single ghash. * Changing of locale is not so common, while looking for a message translation is, @@ -389,7 +402,12 @@ static PyObject *app_translations_py_messages_unregister(BlenderAppTranslations Py_RETURN_NONE; } -/***** C-defined contexts *****/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name C-defined Contexts + * \{ */ + /* This is always available (even when WITH_INTERNATIONAL is not defined). */ static PyTypeObject BlenderAppTranslationsContextsType; @@ -439,7 +457,11 @@ static PyObject *app_translations_contexts_make(void) return translations_contexts; } -/***** Main BlenderAppTranslations Py object definition *****/ +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Main #BlenderAppTranslations #PyObject Definition + * \{ */ PyDoc_STRVAR(app_translations_contexts_doc, "A named tuple containing all pre-defined translation contexts.\n" @@ -887,3 +909,5 @@ void BPY_app_translations_end(void) _clear_translations_cache(); #endif } + +/** \} */ diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index e80c972e8bc..9579f78be30 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -5092,23 +5092,23 @@ static PyObject *pyrna_prop_collection_find(BPy_PropertyRNA *self, PyObject *key static bool foreach_attr_type(BPy_PropertyRNA *self, const char *attr, /* Values to assign. */ - RawPropertyType *raw_type, - int *attr_tot, - bool *attr_signed) + RawPropertyType *r_raw_type, + int *r_attr_tot, + bool *r_attr_signed) { PropertyRNA *prop; bool attr_ok = true; - *raw_type = PROP_RAW_UNSET; - *attr_tot = 0; - *attr_signed = false; + *r_raw_type = PROP_RAW_UNSET; + *r_attr_tot = 0; + *r_attr_signed = false; /* Note: this is fail with zero length lists, so don't let this get caled in that case. */ RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) { prop = RNA_struct_find_property(&itemptr, attr); if (prop) { - *raw_type = RNA_property_raw_type(prop); - *attr_tot = RNA_property_array_length(&itemptr, prop); - *attr_signed = (RNA_property_subtype(prop) != PROP_UNSIGNED); + *r_raw_type = RNA_property_raw_type(prop); + *r_attr_tot = RNA_property_array_length(&itemptr, prop); + *r_attr_signed = (RNA_property_subtype(prop) != PROP_UNSIGNED); } else { attr_ok = false; @@ -5125,53 +5125,53 @@ static int foreach_parse_args(BPy_PropertyRNA *self, PyObject *args, /* Values to assign. */ - const char **attr, - PyObject **seq, - int *tot, - int *size, - RawPropertyType *raw_type, - int *attr_tot, - bool *attr_signed) + const char **r_attr, + PyObject **r_seq, + int *r_tot, + int *r_size, + RawPropertyType *r_raw_type, + int *r_attr_tot, + bool *r_attr_signed) { #if 0 int array_tot; int target_tot; #endif - *size = *attr_tot = 0; - *attr_signed = false; - *raw_type = PROP_RAW_UNSET; + *r_size = *r_attr_tot = 0; + *r_attr_signed = false; + *r_raw_type = PROP_RAW_UNSET; - if (!PyArg_ParseTuple(args, "sO:foreach_get/set", attr, seq)) { + if (!PyArg_ParseTuple(args, "sO:foreach_get/set", r_attr, r_seq)) { return -1; } - if (!PySequence_Check(*seq) && PyObject_CheckBuffer(*seq)) { + if (!PySequence_Check(*r_seq) && PyObject_CheckBuffer(*r_seq)) { PyErr_Format( PyExc_TypeError, "foreach_get/set expected second argument to be a sequence or buffer, not a %.200s", - Py_TYPE(*seq)->tp_name); + Py_TYPE(*r_seq)->tp_name); return -1; } /* TODO - buffer may not be a sequence! array.array() is though. */ - *tot = PySequence_Size(*seq); + *r_tot = PySequence_Size(*r_seq); - if (*tot > 0) { - if (!foreach_attr_type(self, *attr, raw_type, attr_tot, attr_signed)) { + if (*r_tot > 0) { + if (!foreach_attr_type(self, *r_attr, r_raw_type, r_attr_tot, r_attr_signed)) { PyErr_Format(PyExc_AttributeError, "foreach_get/set '%.200s.%200s[...]' elements have no attribute '%.200s'", RNA_struct_identifier(self->ptr.type), RNA_property_identifier(self->prop), - *attr); + *r_attr); return -1; } - *size = RNA_raw_type_sizeof(*raw_type); + *r_size = RNA_raw_type_sizeof(*r_raw_type); #if 0 /* Works fine, but not strictly needed. \ * we could allow RNA_property_collection_raw_* to do the checks */ - if ((*attr_tot) < 1) { - *attr_tot = 1; + if ((*r_attr_tot) < 1) { + *r_attr_tot = 1; } if (RNA_property_type(self->prop) == PROP_COLLECTION) { @@ -5181,23 +5181,23 @@ static int foreach_parse_args(BPy_PropertyRNA *self, array_tot = RNA_property_array_length(&self->ptr, self->prop); } - target_tot = array_tot * (*attr_tot); + target_tot = array_tot * (*r_attr_tot); /* rna_access.c - rna_raw_access(...) uses this same method. */ - if (target_tot != (*tot)) { + if (target_tot != (*r_tot)) { PyErr_Format(PyExc_TypeError, "foreach_get(attr, sequence) sequence length mismatch given %d, needed %d", - *tot, + *r_tot, target_tot); return -1; } #endif } - /* Check 'attr_tot' otherwise we don't know if any values were set. + /* Check 'r_attr_tot' otherwise we don't know if any values were set. * This isn't ideal because it means running on an empty list may * fail silently when it's not compatible. */ - if (*size == 0 && *attr_tot != 0) { + if (*r_size == 0 && *r_attr_tot != 0) { PyErr_SetString(PyExc_AttributeError, "attribute does not support foreach method"); return -1; } diff --git a/source/blender/python/intern/bpy_rna_array.c b/source/blender/python/intern/bpy_rna_array.c index 29e3a07625a..1e5b53b819e 100644 --- a/source/blender/python/intern/bpy_rna_array.c +++ b/source/blender/python/intern/bpy_rna_array.c @@ -262,7 +262,7 @@ static int validate_array_length(PyObject *rvalue, PointerRNA *ptr, PropertyRNA *prop, int lvalue_dim, - int *totitem, + int *r_totitem, const char *error_prefix) { int dimsize[MAX_ARRAY_DIMENSION]; @@ -296,7 +296,7 @@ static int validate_array_length(PyObject *rvalue, return -1; } #else - *totitem = tot; + *r_totitem = tot; return 0; #endif @@ -346,7 +346,7 @@ static int validate_array_length(PyObject *rvalue, } } - *totitem = len; + *r_totitem = len; return 0; } @@ -357,7 +357,7 @@ static int validate_array(PyObject *rvalue, int lvalue_dim, ItemTypeCheckFunc check_item_type, const char *item_type_str, - int *totitem, + int *r_totitem, const char *error_prefix) { int dimsize[MAX_ARRAY_DIMENSION]; @@ -405,7 +405,7 @@ static int validate_array(PyObject *rvalue, return -1; } else { - *totitem = dimsize[0] * dimsize[1]; + *r_totitem = dimsize[0] * dimsize[1]; return 0; } } @@ -425,7 +425,7 @@ static int validate_array(PyObject *rvalue, return -1; } - return validate_array_length(rvalue, ptr, prop, lvalue_dim, totitem, error_prefix); + return validate_array_length(rvalue, ptr, prop, lvalue_dim, r_totitem, error_prefix); } } diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 319d8b1c2ed..54296e16834 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -363,7 +363,7 @@ struct RenderPass *RE_pass_find_by_type(volatile struct RenderLayer *rl, #define RE_BAKE_DISPLACEMENT 1 #define RE_BAKE_AO 2 -void RE_GetCameraWindow(struct Render *re, struct Object *camera, int frame, float mat[4][4]); +void RE_GetCameraWindow(struct Render *re, struct Object *camera, float mat[4][4]); void RE_GetCameraWindowWithOverscan(struct Render *re, float mat[4][4], float overscan); void RE_GetCameraModelMatrix(struct Render *re, struct Object *camera, float r_mat[4][4]); struct Scene *RE_GetScene(struct Render *re); diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 1318e2498bb..3ae4b9c0b90 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -123,11 +123,6 @@ struct Render { Depsgraph *pipeline_depsgraph; Scene *pipeline_scene_eval; -#ifdef WITH_FREESTYLE - struct Main *freestyle_bmain; - ListBase freestyle_renders; -#endif - /* callbacks */ void (*display_init)(void *handle, RenderResult *rr); void *dih; diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c index 5a6ecfc3e20..138d95af055 100644 --- a/source/blender/render/intern/source/initrender.c +++ b/source/blender/render/intern/source/initrender.c @@ -211,9 +211,8 @@ void RE_SetCamera(Render *re, Object *cam_ob) re_camera_params_get(re, ¶ms); } -void RE_GetCameraWindow(struct Render *re, struct Object *camera, int frame, float mat[4][4]) +void RE_GetCameraWindow(struct Render *re, struct Object *camera, float mat[4][4]) { - re->r.cfra = frame; RE_SetCamera(re, camera); copy_m4_m4(mat, re->winmat); } diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 14a9ebcff5d..87568402df3 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -1149,14 +1149,6 @@ void RE_AddObject(Render *UNUSED(re), Object *UNUSED(ob)) } #endif -/* *************************************** */ - -#ifdef WITH_FREESTYLE -static void init_freestyle(Render *re); -static void add_freestyle(Render *re, int render); -static void free_all_freestyle_renders(void); -#endif - /* ************ This part uses API, for rendering Blender scenes ********** */ static void do_render_3d(Render *re) @@ -1365,87 +1357,6 @@ static void render_composit_stats(void *arg, const char *str) re->stats_draw(re->sdh, &i); } -#ifdef WITH_FREESTYLE -/* init Freestyle renderer */ -static void init_freestyle(Render *re) -{ - re->freestyle_bmain = BKE_main_new(); - - /* We use the same window manager for freestyle bmain as - * real bmain uses. This is needed because freestyle's - * bmain could be used to tag scenes for update, which - * implies call of ED_render_scene_update in some cases - * and that function requires proper window manager - * to present (sergey) - */ - re->freestyle_bmain->wm = re->main->wm; - - FRS_init_stroke_renderer(re); -} - -/* invokes Freestyle stroke rendering */ -static void add_freestyle(Render *re, int render) -{ - ViewLayer *view_layer, *active_view_layer; - LinkData *link; - Render *r; - - active_view_layer = BLI_findlink(&re->view_layers, re->active_view_layer); - - FRS_begin_stroke_rendering(re); - - for (view_layer = (ViewLayer *)re->view_layers.first; view_layer; - view_layer = view_layer->next) { - link = (LinkData *)MEM_callocN(sizeof(LinkData), "LinkData to Freestyle render"); - BLI_addtail(&re->freestyle_renders, link); - - if ((re->r.scemode & R_SINGLE_LAYER) && view_layer != active_view_layer) { - continue; - } - if (FRS_is_freestyle_enabled(view_layer)) { - r = FRS_do_stroke_rendering(re, view_layer, render); - link->data = (void *)r; - } - } - - FRS_end_stroke_rendering(re); -} - -/* releases temporary scenes and renders for Freestyle stroke rendering */ -static void free_all_freestyle_renders(void) -{ - Render *re1; - LinkData *link; - - for (re1 = RenderGlobal.renderlist.first; re1; re1 = re1->next) { - for (link = (LinkData *)re1->freestyle_renders.first; link; link = link->next) { - Render *freestyle_render = (Render *)link->data; - - if (freestyle_render) { - Scene *freestyle_scene = freestyle_render->scene; - RE_FreeRender(freestyle_render); - - if (freestyle_scene) { - BKE_libblock_unlink(re1->freestyle_bmain, freestyle_scene, false, false); - BKE_id_free(re1->freestyle_bmain, freestyle_scene); - } - } - } - BLI_freelistN(&re1->freestyle_renders); - - if (re1->freestyle_bmain) { - /* detach the window manager from freestyle bmain (see comments - * in add_freestyle() for more detail) - */ - BLI_listbase_clear(&re1->freestyle_bmain->wm); - - BKE_main_free(re1->freestyle_bmain); - re1->freestyle_bmain = NULL; - } - } -} -#endif - /* returns fully composited render-result on given time step (in RenderData) */ static void do_render_composite(Render *re) { @@ -1531,10 +1442,6 @@ static void do_render_composite(Render *re) } } -#ifdef WITH_FREESTYLE - free_all_freestyle_renders(); -#endif - /* weak... the display callback wants an active renderlayer pointer... */ if (re->result != NULL) { re->result->renlay = render_get_active_layer(re, re->result); @@ -2181,15 +2088,30 @@ void RE_RenderFreestyleStrokes(Render *re, Main *bmain, Scene *scene, int render void RE_RenderFreestyleExternal(Render *re) { - if (!re->test_break(re->tbh)) { - RenderView *rv; + if (re->test_break(re->tbh)) { + return; + } - init_freestyle(re); + FRS_init_stroke_renderer(re); + + for (RenderView *rv = re->result->views.first; rv; rv = rv->next) { + RE_SetActiveRenderView(re, rv->name); - for (rv = re->result->views.first; rv; rv = rv->next) { - RE_SetActiveRenderView(re, rv->name); - add_freestyle(re, 1); + ViewLayer *active_view_layer = BLI_findlink(&re->view_layers, re->active_view_layer); + FRS_begin_stroke_rendering(re); + + for (ViewLayer *view_layer = (ViewLayer *)re->view_layers.first; view_layer; + view_layer = view_layer->next) { + if ((re->r.scemode & R_SINGLE_LAYER) && view_layer != active_view_layer) { + continue; + } + + if (FRS_is_freestyle_enabled(view_layer)) { + FRS_do_stroke_rendering(re, view_layer); + } } + + FRS_end_stroke_rendering(re); } } #endif diff --git a/source/blender/windowmanager/WM_keymap.h b/source/blender/windowmanager/WM_keymap.h index 2cf71dcf165..ae2810dfb4d 100644 --- a/source/blender/windowmanager/WM_keymap.h +++ b/source/blender/windowmanager/WM_keymap.h @@ -135,10 +135,10 @@ char *WM_modalkeymap_operator_items_to_string_buf(struct wmOperatorType *ot, int *r_available_len, char **r_result); -wmKeyMap *WM_modalkeymap_add(struct wmKeyConfig *keyconf, - const char *idname, - const struct EnumPropertyItem *items); -wmKeyMap *WM_modalkeymap_get(struct wmKeyConfig *keyconf, const char *idname); +wmKeyMap *WM_modalkeymap_ensure(struct wmKeyConfig *keyconf, + const char *idname, + const struct EnumPropertyItem *items); +wmKeyMap *WM_modalkeymap_find(struct wmKeyConfig *keyconf, const char *idname); wmKeyMapItem *WM_modalkeymap_add_item( struct wmKeyMap *km, int type, int val, int modifier, int keymodifier, int value); wmKeyMapItem *WM_modalkeymap_add_item_str( diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c index ef270533855..b7fecb31f96 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c @@ -665,14 +665,14 @@ wmKeyMap *wm_gizmogroup_tweak_modal_keymap(wmKeyConfig *kc) }; STRNCPY(name, "Generic Gizmo Tweak Modal Map"); - keymap = WM_modalkeymap_get(kc, name); + keymap = WM_modalkeymap_find(kc, name); /* this function is called for each spacetype, only needs to add map once */ if (keymap && keymap->modal_items) { return NULL; } - keymap = WM_modalkeymap_add(kc, name, modal_items); + keymap = WM_modalkeymap_ensure(kc, name, modal_items); /* items for modal map */ WM_modalkeymap_add_item(keymap, EVT_ESCKEY, KM_PRESS, KM_ANY, 0, TWEAK_MODAL_CANCEL); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 6f133e063f7..1a794e9bf0b 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -870,6 +870,10 @@ static void wm_operator_reports(bContext *C, wmOperator *op, int retval, bool ca } } + /* Refresh Info Editor with reports immediately, even if op returned OPERATOR_CANCELLED. */ + if ((retval & OPERATOR_CANCELLED) && !BLI_listbase_is_empty(&op->reports->list)) { + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO_REPORT, NULL); + } /* if the caller owns them, handle this */ wm_add_reports(op->reports); } @@ -1864,6 +1868,8 @@ static wmKeyMapItem *wm_eventmatch_modal_keymap_items(const wmKeyMap *keymap, const wmEvent *event) { for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) { + /* Should already be handled by #wm_user_modal_keymap_set_items. */ + BLI_assert(kmi->propvalue_str[0] == '\0'); if (wm_eventmatch(event, kmi)) { if ((keymap->poll_modal_item == NULL) || (keymap->poll_modal_item(op, kmi->propvalue))) { return kmi; diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 3f4d082f9f7..fa59bad7a6b 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -1047,8 +1047,8 @@ void wm_homefile_read(bContext *C, } if (use_userdef) { - /* Clear keymaps because the current default keymap may have been initialized - * from user preferences, which have been reset. */ + /* Clear keymaps because the current default keymap may have been initialized + * from user preferences, which have been reset. */ for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) { if (wm->defaultconf) { wm->defaultconf->flag &= ~KEYCONF_INIT_DEFAULT; @@ -1532,7 +1532,7 @@ void wm_autosave_timer(Main *bmain, wmWindowManager *wm, wmTimer *UNUSED(wt)) } } else { - /* save as regular blend file */ + /* Save as regular blend file. */ int fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_HISTORY); ED_editors_flush_edits(bmain); @@ -1665,7 +1665,7 @@ static int wm_homefile_write_exec(bContext *C, wmOperator *op) ED_editors_flush_edits(bmain); - /* force save as regular blend file */ + /* Force save as regular blend file. */ fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_HISTORY); if (BLO_write_file(bmain, filepath, fileflags, op->reports, NULL) == 0) { diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c index c2c3b24469e..5acc8a5fbc6 100644 --- a/source/blender/windowmanager/intern/wm_files_link.c +++ b/source/blender/windowmanager/intern/wm_files_link.c @@ -74,7 +74,9 @@ #include "wm_files.h" -/* **************** link/append *************** */ +/* -------------------------------------------------------------------- */ +/** \name Link/Append Operator + * \{ */ static bool wm_link_append_poll(bContext *C) { @@ -618,10 +620,12 @@ void WM_OT_append(wmOperatorType *ot) "Localize all appended data, including those indirectly linked from other libraries"); } -/** \name Append single datablock and return it. +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Append Single Data-Block & Return it * * Used for appending workspace from startup files. - * * \{ */ ID *WM_file_append_datablock(Main *bmain, @@ -660,6 +664,10 @@ ID *WM_file_append_datablock(Main *bmain, /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Library Relocate Operator & Library Reload API + * \{ */ + static int wm_lib_relocate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Library *lib; diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index b640fdb59c9..17d697840a0 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -217,10 +217,10 @@ static void sound_jack_sync_callback(Main *bmain, int mode, float time) if (depsgraph == NULL) { continue; } - BKE_sound_lock_scene(scene); + BKE_sound_lock(); Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); BKE_sound_jack_scene_update(scene_eval, mode, time); - BKE_sound_unlock_scene(scene); + BKE_sound_unlock(); } } @@ -609,8 +609,6 @@ void WM_exit_ex(bContext *C, const bool do_python) } #ifdef WITH_INTERNATIONAL - BLF_free_unifont(); - BLF_free_unifont_mono(); BLT_lang_free(); #endif diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index c1a4595ec6b..890aeb71e1a 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -911,9 +911,9 @@ wmKeyMap *WM_keymap_find_all_spaceid_or_empty(wmWindowManager *wm, * and filter the keys before sending to #wmOperatorType.modal callback. * \{ */ -wmKeyMap *WM_modalkeymap_add(wmKeyConfig *keyconf, - const char *idname, - const EnumPropertyItem *items) +wmKeyMap *WM_modalkeymap_ensure(wmKeyConfig *keyconf, + const char *idname, + const EnumPropertyItem *items) { wmKeyMap *km = WM_keymap_ensure(keyconf, idname, 0, 0); km->flag |= KEYMAP_MODAL; @@ -937,7 +937,7 @@ wmKeyMap *WM_modalkeymap_add(wmKeyConfig *keyconf, return km; } -wmKeyMap *WM_modalkeymap_get(wmKeyConfig *keyconf, const char *idname) +wmKeyMap *WM_modalkeymap_find(wmKeyConfig *keyconf, const char *idname) { wmKeyMap *km; @@ -1900,6 +1900,8 @@ void WM_keyconfig_update(wmWindowManager *wm) addonmap = WM_keymap_list_find(&wm->addonconf->keymaps, km->idname, km->spaceid, km->regionid); usermap = WM_keymap_list_find(&U.user_keymaps, km->idname, km->spaceid, km->regionid); + /* For now only the default map defines modal key-maps, + * if we support modal keymaps for 'addonmap', these will need to be enabled too. */ wm_user_modal_keymap_set_items(wm, defaultmap); /* add */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 853da714f76..e782b802729 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3833,14 +3833,14 @@ static void gesture_circle_modal_keymap(wmKeyConfig *keyconf) }; /* WARNING - name is incorrect, use for non-3d views */ - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Gesture Circle"); + wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Gesture Circle"); /* this function is called for each spacetype, only needs to add map once */ if (keymap && keymap->modal_items) { return; } - keymap = WM_modalkeymap_add(keyconf, "View3D Gesture Circle", modal_items); + keymap = WM_modalkeymap_ensure(keyconf, "View3D Gesture Circle", modal_items); /* assign map to operators */ WM_modalkeymap_assign(keymap, "VIEW3D_OT_select_circle"); @@ -3863,14 +3863,14 @@ static void gesture_straightline_modal_keymap(wmKeyConfig *keyconf) {0, NULL, 0, NULL, NULL}, }; - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Gesture Straight Line"); + wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Gesture Straight Line"); /* this function is called for each spacetype, only needs to add map once */ if (keymap && keymap->modal_items) { return; } - keymap = WM_modalkeymap_add(keyconf, "Gesture Straight Line", modal_items); + keymap = WM_modalkeymap_ensure(keyconf, "Gesture Straight Line", modal_items); /* assign map to operators */ WM_modalkeymap_assign(keymap, "IMAGE_OT_sample_line"); @@ -3889,14 +3889,14 @@ static void gesture_box_modal_keymap(wmKeyConfig *keyconf) {0, NULL, 0, NULL, NULL}, }; - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Gesture Box"); + wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Gesture Box"); /* this function is called for each spacetype, only needs to add map once */ if (keymap && keymap->modal_items) { return; } - keymap = WM_modalkeymap_add(keyconf, "Gesture Box", modal_items); + keymap = WM_modalkeymap_ensure(keyconf, "Gesture Box", modal_items); /* assign map to operators */ WM_modalkeymap_assign(keymap, "ACTION_OT_select_box"); @@ -3940,14 +3940,14 @@ static void gesture_zoom_border_modal_keymap(wmKeyConfig *keyconf) {0, NULL, 0, NULL, NULL}, }; - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Gesture Zoom Border"); + wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "Gesture Zoom Border"); /* this function is called for each spacetype, only needs to add map once */ if (keymap && keymap->modal_items) { return; } - keymap = WM_modalkeymap_add(keyconf, "Gesture Zoom Border", modal_items); + keymap = WM_modalkeymap_ensure(keyconf, "Gesture Zoom Border", modal_items); /* assign map to operators */ WM_modalkeymap_assign(keymap, "VIEW2D_OT_zoom_border"); diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index c6eb1393ffe..8a872010ecc 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -1292,8 +1292,7 @@ static char *wm_main_playanim_intern(int argc, const char **argv) /* initialize the font */ BLF_init(); - ps.fontid = BLF_load_mem( - "monospace", (unsigned char *)datatoc_bmonofont_ttf, datatoc_bmonofont_ttf_size); + ps.fontid = BLF_load_mono_default(false); BLF_size(ps.fontid, 11, 72); ps.ibufx = ibuf->x; diff --git a/source/blender/windowmanager/intern/wm_toolsystem.c b/source/blender/windowmanager/intern/wm_toolsystem.c index 4cfd1d1e0c0..551250ec747 100644 --- a/source/blender/windowmanager/intern/wm_toolsystem.c +++ b/source/blender/windowmanager/intern/wm_toolsystem.c @@ -73,7 +73,7 @@ struct bToolRef *WM_toolsystem_ref_from_context(struct bContext *C) WorkSpace *workspace = CTX_wm_workspace(C); ViewLayer *view_layer = CTX_data_view_layer(C); ScrArea *sa = CTX_wm_area(C); - if (((1 << sa->spacetype) & WM_TOOLSYSTEM_SPACE_MASK) == 0) { + if ((sa == NULL) || ((1 << sa->spacetype) & WM_TOOLSYSTEM_SPACE_MASK) == 0) { return NULL; } const bToolKey tkey = { diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index a3e1814f8d2..505383d295f 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -414,7 +414,7 @@ void wm_quit_with_optional_confirmation_prompt(bContext *C, wmWindow *win) void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win) { wmWindow *win_other; - const bool is_dialog = GHOST_IsDialogWindow(win->ghostwin); + const bool is_dialog = (G.background == false) ? GHOST_IsDialogWindow(win->ghostwin) : false; /* First check if there is another main window remaining. */ for (win_other = wm->windows.first; win_other; win_other = win_other->next) { @@ -434,9 +434,13 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win) if (iter_win->parent == win) { wm_window_close(C, wm, iter_win); } - else if (is_dialog && iter_win != win && iter_win->parent && - (GHOST_GetWindowState(iter_win->ghostwin) != GHOST_kWindowStateMinimized)) { - wm_window_raise(iter_win); + else { + if (G.background == false) { + if (is_dialog && iter_win != win && iter_win->parent && + (GHOST_GetWindowState(iter_win->ghostwin) != GHOST_kWindowStateMinimized)) { + wm_window_raise(iter_win); + } + } } } diff --git a/source/blender/windowmanager/intern/wm_xr.c b/source/blender/windowmanager/intern/wm_xr.c index 95c0f353298..18c3b70ed01 100644 --- a/source/blender/windowmanager/intern/wm_xr.c +++ b/source/blender/windowmanager/intern/wm_xr.c @@ -300,7 +300,13 @@ static void wm_xr_draw_data_populate(const wmXrSessionState *state, wm_xr_base_pose_calc(scene, settings, &r_draw_data->base_pose); - if (position_tracking_toggled || !state->is_view_data_set) { + /* Set the eye position offset, it's used to offset the base pose when changing positional + * tracking. */ + if (!state->is_view_data_set) { + /* Always use the exact base pose with no offset when starting the session. */ + copy_v3_fl(r_draw_data->eye_position_ofs, 0.0f); + } + else if (position_tracking_toggled) { if (use_position_tracking) { copy_v3_fl(r_draw_data->eye_position_ofs, 0.0f); } @@ -748,8 +754,8 @@ void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata) * viewport buffers composited together and potentially color managed for display on screen. * It needs a bound frame-buffer to draw into, for which we simply reuse the GPUOffscreen one. * - * In a next step, Ghost-XR will use the the currently bound frame-buffer to retrieve the image - * to be submitted to the OpenXR swap-chain. So do not un-bind the offscreen yet! */ + * In a next step, Ghost-XR will use the currently bound frame-buffer to retrieve the image + * to be submitted to the OpenXR swap-chain. So do not un-bind the off-screen yet! */ GPU_offscreen_bind(surface_data->offscreen, false); diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index bbef3a4d52a..ced0532a8fa 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -304,12 +304,10 @@ if(WITH_MEM_JEMALLOC) ) endif() -if(WITH_INTERNATIONAL) - list(APPEND BLENDER_TEXT_FILES - ${CMAKE_SOURCE_DIR}/release/datafiles/LICENSE-droidsans.ttf.txt - ${CMAKE_SOURCE_DIR}/release/datafiles/LICENSE-bmonofont-i18n.ttf.txt - ) -endif() +list(APPEND BLENDER_TEXT_FILES + ${CMAKE_SOURCE_DIR}/release/datafiles/LICENSE-droidsans.ttf.txt + ${CMAKE_SOURCE_DIR}/release/datafiles/LICENSE-bmonofont-i18n.ttf.txt +) # ----------------------------------------------------------------------------- @@ -387,14 +385,15 @@ if(WITH_PYTHON) unset(FREESTYLE_EXCLUDE_CONDITIONAL) endif() +# fonts +install( + DIRECTORY + ${CMAKE_SOURCE_DIR}/release/datafiles/fonts + DESTINATION ${TARGETDIR_VER}/datafiles +) + # localization if(WITH_INTERNATIONAL) - install( - DIRECTORY - ${CMAKE_SOURCE_DIR}/release/datafiles/fonts - DESTINATION ${TARGETDIR_VER}/datafiles - ) - set(_locale_dir "${CMAKE_SOURCE_DIR}/release/datafiles/locale") set(_locale_target_dir ${TARGETDIR_VER}/datafiles/locale) @@ -922,6 +921,11 @@ elseif(APPLE) OUTPUT_STRIP_TRAILING_WHITESPACE) # Give the bundle actual creation/modification date + # + # Note that the directory might not yet exist, which happens when CMake is first run. + if(NOT EXISTS ${EXECUTABLE_OUTPUT_PATH}/Blender.app) + file(MAKE_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}/Blender.app) + endif() execute_process(COMMAND SetFile -d ${SETFILE_DATE} -m ${SETFILE_DATE} ${EXECUTABLE_OUTPUT_PATH}/Blender.app) diff --git a/source/creator/blender.map b/source/creator/blender.map index 4c34dea3338..3e447ec9e89 100644 --- a/source/creator/blender.map +++ b/source/creator/blender.map @@ -6,21 +6,71 @@ { global: - *; - *_boost*; + *; + *_boost*; local: - *default_error_condition*; - *llvm*; - *LLVM*; - decodeInstruction; - ForceStackAlign; - _Jv_RegisterClasses; - Name; - NumNamedVarArgParams; - X86CompilationCallback*; - *boost*; - *SDL*; - *embree*; - cu*; + al*; + *Alembic*; + av*; + blosc*; + *boost*; + *ceres*; + *cineon*; + *COLLADA*; + cu*; + decodeInstruction; + *default_error_condition*; + *dpx*; + *embree*; + ff_*; + fftw*; + FLAC*; + ForceStackAlign; + FT_*; + *GeneratedSaxParser*; + *google*; + gsm*; + Gsm*; + html*; + id3tag*; + *Iex*; + *Ilm*; + *Imath*; + *Imf*; + jack_*; + jpeg_*; + jsimd**; + _Jv_RegisterClasses; + lame_*; + *llvm*; + *LLVM*; + *MathML*; + *mkldnn*; + Name; + NumNamedVarArgParams; + oc_*; + ogg*; + *oidn*; + *OpenColorIO*; + *OpenImageIO*; + *OpenSubdiv*; + *openvdb*; + opj_*; + opus_*; + *OSL*; + png_*; + *SDL*; + *squish*; + *tbb*; + *TIFF*; + *tinyformat*; + vorbis*; + vp8*; + vp9*; + vpx*; + x264_*; + X86CompilationCallback*; + xml*; + xvid*; + *YAML*; }; - diff --git a/source/creator/creator.c b/source/creator/creator.c index a6c0e50e527..75523024aa4 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -108,7 +108,7 @@ #include "creator_intern.h" /* own include */ -/* Local Function prototypes */ +/* Local Function prototypes. */ #ifdef WITH_PYTHON_MODULE int main_python_enter(int argc, const char **argv); void main_python_exit(void); diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c index 7b5a448fc53..a5b9df166a4 100644 --- a/source/creator/creator_args.c +++ b/source/creator/creator_args.c @@ -619,7 +619,7 @@ static int arg_handle_print_help(int UNUSED(argc), const char **UNUSED(argv), vo printf("Misc Options:\n"); BLI_argsPrintArgDoc(ba, "--app-template"); BLI_argsPrintArgDoc(ba, "--factory-startup"); - BLI_argsPrintArgDoc(ba, "--enable-library-override"); + BLI_argsPrintArgDoc(ba, "--disable-library-override"); BLI_argsPrintArgDoc(ba, "--enable-event-simulate"); printf("\n"); BLI_argsPrintArgDoc(ba, "--env-system-datafiles"); diff --git a/source/creator/osx_locals.map b/source/creator/osx_locals.map index 3382ac954e2..908bfdae6cb 100644 --- a/source/creator/osx_locals.map +++ b/source/creator/osx_locals.map @@ -1,10 +1,66 @@ ## The symbols will be treated as if they were marked as __private_extern__ ## (aka visibility=hidden) and will not be global in the output file +al* +*Alembic* +av* +blosc* *boost* -*__ZNSt6vector* +*ceres* +*cineon* +*COLLADA* +cu* +decodeInstruction +*default_error_condition* +*dpx* +*embree* +ff_* +fftw* +FLAC* +ForceStackAlign +FT_* +*GeneratedSaxParser* +*google* +gsm* +Gsm* +html* +id3tag* +*Iex* +*Ilm* +*Imath* +*Imf* +jack_* +jpeg_* +jsimd** +_Jv_RegisterClasses +lame_* *llvm* *LLVM* +*MathML* +*mkldnn* +Name +NumNamedVarArgParams +oc_* +ogg* +*oidn* +*OpenColorIO* +*OpenImageIO* +*OpenSubdiv* +*openvdb* +opj_* +opus_* *OSL* -*embree* -cu* - +png_* +*SDL* +*squish* +*tbb* +*TIFF* +*tinyformat* +vorbis* +vp8* +vp9* +vpx* +x264_* +X86CompilationCallback* +xml* +xvid* +*YAML* diff --git a/source/tools b/source/tools -Subproject 603f076606f052adc97d937633bfeb9b268ec20 +Subproject 2afbb8ec472cac5102eb239f57b006f8c938768 |