Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2020-10-23 06:03:28 +0300
committerHans Goudey <h.goudey@me.com>2020-10-23 06:03:28 +0300
commit895f4620a032272844651444d42bda8a9978a38c (patch)
tree2999110eb07c4f74c3292b4c6637c114d2180236 /source
parentfafed6234b2d1d7a3ab897fb128f0d39776ece37 (diff)
parentc6281d5dc7c40c6fabef0873b3865eadcb09c63e (diff)
Merge branch 'master' into geometry-nodes
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenfont/BLF_api.h20
-rw-r--r--source/blender/blenfont/CMakeLists.txt1
-rw-r--r--source/blender/blenfont/intern/blf.c71
-rw-r--r--source/blender/blenfont/intern/blf_default.c90
-rw-r--r--source/blender/blenfont/intern/blf_internal.h2
-rw-r--r--source/blender/blenkernel/BKE_armature.h4
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h4
-rw-r--r--source/blender/blenkernel/BKE_multires.h11
-rw-r--r--source/blender/blenkernel/intern/appdir.c12
-rw-r--r--source/blender/blenkernel/intern/armature.c28
-rw-r--r--source/blender/blenkernel/intern/brush.c3
-rw-r--r--source/blender/blenkernel/intern/curve.c114
-rw-r--r--source/blender/blenkernel/intern/displist.c64
-rw-r--r--source/blender/blenkernel/intern/fcurve.c5
-rw-r--r--source/blender/blenkernel/intern/gpencil.c10
-rw-r--r--source/blender/blenkernel/intern/lib_id.c3
-rw-r--r--source/blender/blenkernel/intern/lib_override.c9
-rw-r--r--source/blender/blenkernel/intern/mesh.c44
-rw-r--r--source/blender/blenkernel/intern/multires.c866
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c4
-rw-r--r--source/blender/blenlib/intern/delaunay_2d.cc4
-rw-r--r--source/blender/blenloader/intern/versioning_250.c16
-rw-r--r--source/blender/blenloader/intern/versioning_290.c26
-rw-r--r--source/blender/blenloader/intern/versioning_legacy.c18
-rw-r--r--source/blender/blenloader/intern/versioning_userdef.c6
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c86
-rw-r--r--source/blender/compositor/CMakeLists.txt2
-rw-r--r--source/blender/compositor/nodes/COM_KeyingNode.cpp4
-rw-r--r--source/blender/compositor/operations/COM_KeyingSetAlphaOperation.cpp55
-rw-r--r--source/blender/compositor/operations/COM_KeyingSetAlphaOperation.h39
-rw-r--r--source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl14
-rw-r--r--source/blender/draw/engines/external/external_engine.c3
-rw-r--r--source/blender/editors/curve/editcurve.c199
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c20
-rw-r--r--source/blender/editors/gpencil/gpencil_mesh.c80
-rw-r--r--source/blender/editors/gpencil/gpencil_trace_utils.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c56
-rw-r--r--source/blender/editors/object/object_relations.c1
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c14
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c39
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_mask.c5
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c9
-rw-r--r--source/blender/editors/space_file/file_ops.c3
-rw-r--r--source/blender/editors/space_file/file_panels.c6
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c115
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c3
-rw-r--r--source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp17
-rw-r--r--source/blender/freestyle/intern/python/BPy_Id.cpp33
-rw-r--r--source/blender/freestyle/intern/python/BPy_Operators.cpp183
-rw-r--r--source/blender/freestyle/intern/python/BPy_SShape.cpp26
-rw-r--r--source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp24
-rw-r--r--source/blender/freestyle/intern/python/BPy_ViewShape.cpp14
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp32
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp15
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp35
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp30
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp13
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp14
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp28
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp32
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp14
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp14
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp14
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp14
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp95
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp8
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp12
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp14
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp10
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp60
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp8
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp8
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp8
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp9
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp9
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp9
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp9
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp9
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp9
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp9
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp9
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c5
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl2
-rw-r--r--source/blender/imbuf/intern/util_gpu.c9
-rw-r--r--source/blender/makesdna/DNA_brush_types.h1
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h2
-rw-r--r--source/blender/makesdna/DNA_gpencil_modifier_types.h2
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h4
-rw-r--r--source/blender/makesdna/DNA_meshdata_types.h50
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h4
-rw-r--r--source/blender/makesdna/DNA_shader_fx_types.h2
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h3
-rw-r--r--source/blender/makesdna/DNA_windowmanager_types.h13
-rw-r--r--source/blender/makesrna/intern/rna_brush.c6
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c14
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c4
-rw-r--r--source/blender/makesrna/intern/rna_wm_api.c5
-rw-r--r--source/blender/makesrna/intern/rna_wm_gizmo.c6
-rw-r--r--source/blender/modifiers/intern/MOD_datatransfer.c2
-rw-r--r--source/blender/modifiers/intern/MOD_hook.c8
-rw-r--r--source/blender/modifiers/intern/MOD_solidify.c5
-rw-r--r--source/blender/python/intern/bpy_app.c3
-rw-r--r--source/blender/python/mathutils/mathutils_noise.c4
-rw-r--r--source/blender/windowmanager/WM_types.h10
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c10
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c8
-rw-r--r--source/blender/windowmanager/intern/wm_gesture_ops.c12
-rw-r--r--source/blender/windowmanager/intern/wm_operator_props.c2
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c1
-rw-r--r--source/blender/windowmanager/wm_event_types.h3
-rw-r--r--source/creator/creator_args.c7
111 files changed, 1134 insertions, 2110 deletions
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h
index bf84f5c57b3..03877957f42 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -40,9 +40,6 @@ struct rcti;
int BLF_init(void);
void BLF_exit(void);
-void BLF_default_dpi(int dpi);
-void BLF_default_set(int fontid);
-int BLF_default(void); /* get default font ID so we can pass it to other functions */
void BLF_cache_clear(void);
@@ -98,13 +95,6 @@ void BLF_batch_draw_begin(void);
void BLF_batch_draw_flush(void);
void BLF_batch_draw_end(void);
-/* Draw the string using the default font, size and dpi. */
-void BLF_draw_default(float x, float y, float z, const char *str, size_t len) ATTR_NONNULL();
-void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t len) ATTR_NONNULL();
-
-/* Set size and DPI, and return default font ID. */
-int BLF_set_default(void);
-
/* Draw the string using the current font. */
void BLF_draw_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_info)
ATTR_NONNULL(2);
@@ -257,6 +247,16 @@ void BLF_thumb_preview(const char *filename,
int h,
int channels) ATTR_NONNULL();
+/* blf_default.c */
+void BLF_default_dpi(int dpi);
+void BLF_default_set(int fontid);
+int BLF_default(void); /* get default font ID so we can pass it to other functions */
+/* Draw the string using the default font, size and dpi. */
+void BLF_draw_default(float x, float y, float z, const char *str, size_t len) ATTR_NONNULL();
+void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t len) ATTR_NONNULL();
+/* Set size and DPI, and return default font ID. */
+int BLF_set_default(void);
+
/* blf_font_default.c */
int BLF_load_default(const bool unique);
int BLF_load_mono_default(const bool unique);
diff --git a/source/blender/blenfont/CMakeLists.txt b/source/blender/blenfont/CMakeLists.txt
index 3fd0dd95ef8..59a9072de57 100644
--- a/source/blender/blenfont/CMakeLists.txt
+++ b/source/blender/blenfont/CMakeLists.txt
@@ -38,6 +38,7 @@ set(INC_SYS
set(SRC
intern/blf.c
+ intern/blf_default.c
intern/blf_dir.c
intern/blf_font.c
intern/blf_font_default.c
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index c8940add738..48f283e67b9 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -37,10 +37,6 @@
#include "MEM_guardedalloc.h"
-#include "DNA_listBase.h"
-#include "DNA_userdef_types.h"
-#include "DNA_vec_types.h"
-
#include "BLI_math.h"
#include "BLI_threads.h"
@@ -48,9 +44,6 @@
#include "IMB_colormanagement.h"
-#include "UI_interface.h"
-
-#include "GPU_immediate.h"
#include "GPU_matrix.h"
#include "GPU_shader.h"
@@ -64,9 +57,6 @@
*/
#define BLF_MAX_FONT 16
-/* call BLF_default_set first! */
-#define ASSERT_DEFAULT_SET BLI_assert(global_font_default != -1)
-
#define BLF_RESULT_CHECK_INIT(r_info) \
if (r_info) { \
memset(r_info, 0, sizeof(*(r_info))); \
@@ -76,10 +66,6 @@
/* Font array. */
static FontBLF *global_font[BLF_MAX_FONT] = {NULL};
-/* Default size and dpi, for BLF_draw_default. */
-static int global_font_default = -1;
-static int global_font_dpi = 72;
-
/* XXX, should these be made into global_font_'s too? */
int blf_mono_font = -1;
int blf_mono_font_render = -1;
@@ -98,16 +84,11 @@ int BLF_init(void)
global_font[i] = NULL;
}
- global_font_dpi = 72;
+ BLF_default_dpi(72);
return blf_font_init();
}
-void BLF_default_dpi(int dpi)
-{
- global_font_dpi = dpi;
-}
-
void BLF_exit(void)
{
for (int i = 0; i < BLF_MAX_FONT; i++) {
@@ -132,6 +113,11 @@ void BLF_cache_clear(void)
}
}
+bool blf_font_id_is_valid(int fontid)
+{
+ return blf_get(fontid) != NULL;
+}
+
static int blf_search(const char *name)
{
for (int i = 0; i < BLF_MAX_FONT; i++) {
@@ -155,20 +141,6 @@ static int blf_search_available(void)
return -1;
}
-void BLF_default_set(int fontid)
-{
- FontBLF *font = blf_get(fontid);
- if (font || fontid == -1) {
- global_font_default = fontid;
- }
-}
-
-int BLF_default(void)
-{
- ASSERT_DEFAULT_SET;
- return global_font_default;
-}
-
bool BLF_has_glyph(int fontid, unsigned int unicode)
{
FontBLF *font = blf_get(fontid);
@@ -515,37 +487,6 @@ void BLF_batch_draw_end(void)
g_batch.enabled = false;
}
-void BLF_draw_default(float x, float y, float z, const char *str, size_t len)
-{
- ASSERT_DEFAULT_SET;
-
- const uiStyle *style = UI_style_get();
- BLF_size(global_font_default, style->widgetlabel.points, global_font_dpi);
- BLF_position(global_font_default, x, y, z);
- BLF_draw(global_font_default, str, len);
-}
-
-/* same as above but call 'BLF_draw_ascii' */
-void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t len)
-{
- ASSERT_DEFAULT_SET;
-
- const uiStyle *style = UI_style_get();
- BLF_size(global_font_default, style->widgetlabel.points, global_font_dpi);
- BLF_position(global_font_default, x, y, z);
- BLF_draw_ascii(global_font_default, str, len); /* XXX, use real length */
-}
-
-int BLF_set_default(void)
-{
- ASSERT_DEFAULT_SET;
-
- const uiStyle *style = UI_style_get();
- BLF_size(global_font_default, style->widgetlabel.points, global_font_dpi);
-
- return global_font_default;
-}
-
static void blf_draw_gl__start(FontBLF *font)
{
/*
diff --git a/source/blender/blenfont/intern/blf_default.c b/source/blender/blenfont/intern/blf_default.c
new file mode 100644
index 00000000000..7bbc865128d
--- /dev/null
+++ b/source/blender/blenfont/intern/blf_default.c
@@ -0,0 +1,90 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2009 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup blf
+ *
+ * Default API, that uses Blender's user preferences for the default size.
+ */
+
+#include "DNA_userdef_types.h"
+
+#include "BLI_assert.h"
+
+#include "BLF_api.h"
+
+#include "UI_interface.h"
+
+#include "blf_internal.h"
+
+/* call BLF_default_set first! */
+#define ASSERT_DEFAULT_SET BLI_assert(global_font_default != -1)
+
+/* Default size and dpi, for BLF_draw_default. */
+static int global_font_default = -1;
+static int global_font_dpi = 72;
+
+void BLF_default_dpi(int dpi)
+{
+ global_font_dpi = dpi;
+}
+
+void BLF_default_set(int fontid)
+{
+ if ((fontid == -1) || blf_font_id_is_valid(fontid)) {
+ global_font_default = fontid;
+ }
+}
+
+int BLF_default(void)
+{
+ ASSERT_DEFAULT_SET;
+ return global_font_default;
+}
+
+int BLF_set_default(void)
+{
+ ASSERT_DEFAULT_SET;
+
+ const uiStyle *style = UI_style_get();
+ BLF_size(global_font_default, style->widgetlabel.points, global_font_dpi);
+
+ return global_font_default;
+}
+
+void BLF_draw_default(float x, float y, float z, const char *str, size_t len)
+{
+ ASSERT_DEFAULT_SET;
+
+ const uiStyle *style = UI_style_get();
+ BLF_size(global_font_default, style->widgetlabel.points, global_font_dpi);
+ BLF_position(global_font_default, x, y, z);
+ BLF_draw(global_font_default, str, len);
+}
+
+/* same as above but call 'BLF_draw_ascii' */
+void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t len)
+{
+ ASSERT_DEFAULT_SET;
+
+ const uiStyle *style = UI_style_get();
+ BLF_size(global_font_default, style->widgetlabel.points, global_font_dpi);
+ BLF_position(global_font_default, x, y, z);
+ BLF_draw_ascii(global_font_default, str, len); /* XXX, use real length */
+}
diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h
index b616f47a897..ada772c53d2 100644
--- a/source/blender/blenfont/intern/blf_internal.h
+++ b/source/blender/blenfont/intern/blf_internal.h
@@ -43,6 +43,8 @@ char *blf_dir_metrics_search(const char *filename);
int blf_font_init(void);
void blf_font_exit(void);
+bool blf_font_id_is_valid(int fontid);
+
void blf_draw_buffer__start(struct FontBLF *font);
void blf_draw_buffer__end(void);
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index 4e8775aefb3..db44a771095 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -180,6 +180,10 @@ void BKE_pose_rebuild(struct Main *bmain,
struct Object *ob,
struct bArmature *arm,
const bool do_id_user);
+void BKE_pose_ensure(struct Main *bmain,
+ struct Object *ob,
+ struct bArmature *arm,
+ const bool do_id_user);
void BKE_pose_where_is(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob);
void BKE_pose_where_is_bone(struct Depsgraph *depsgraph,
struct Scene *scene,
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index aed4dad05ad..987b64c217e 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -31,7 +31,7 @@ extern "C" {
*/
/* Blender major and minor version. */
-#define BLENDER_VERSION 291
+#define BLENDER_VERSION 292
/* Blender patch version for bugfix releases. */
#define BLENDER_VERSION_PATCH 0
/** Blender release cycle stage: alpha/beta/rc/release. */
@@ -39,7 +39,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
-#define BLENDER_FILE_SUBVERSION 8
+#define BLENDER_FILE_SUBVERSION 0
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file
diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h
index fbdfc5b76a7..763011c8d92 100644
--- a/source/blender/blenkernel/BKE_multires.h
+++ b/source/blender/blenkernel/BKE_multires.h
@@ -36,7 +36,6 @@ struct DerivedMesh;
struct MDisps;
struct Mesh;
struct ModifierData;
-struct Multires;
struct MultiresModifierData;
struct Object;
struct Scene;
@@ -114,22 +113,12 @@ int multiresModifier_rebuild_subdiv(struct Depsgraph *depsgraph,
struct MultiresModifierData *mmd,
int rebuild_limit,
bool switch_view_to_lower_level);
-void multiresModifier_subdivide_legacy(struct MultiresModifierData *mmd,
- struct Scene *scene,
- struct Object *ob,
- int updateblock,
- int simple);
void multiresModifier_sync_levels_ex(struct Object *ob_dst,
struct MultiresModifierData *mmd_src,
struct MultiresModifierData *mmd_dst);
void multires_stitch_grids(struct Object *);
-/* Related to the old multires */
-void multires_free(struct Multires *mr);
-void multires_load_old(struct Object *ob, struct Mesh *me);
-void multires_load_old_250(struct Mesh *);
-
void multiresModifier_scale_disp(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob);
diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c
index 44fc608530b..2038079744d 100644
--- a/source/blender/blenkernel/intern/appdir.c
+++ b/source/blender/blenkernel/intern/appdir.c
@@ -109,6 +109,7 @@ static bool is_appdir_init = false;
void BKE_appdir_init(void)
{
#ifndef NDEBUG
+ BLI_assert(is_appdir_init == false);
is_appdir_init = true;
#endif
}
@@ -254,8 +255,12 @@ static bool test_path(char *targetpath,
}
/**
- * Puts the value of the specified environment variable into *path if it exists
- * and points at a directory. Returns true if this was done.
+ * Puts the value of the specified environment variable into \a path if it exists.
+ *
+ * \param check_is_dir: When true, checks if it points at a directory.
+ *
+ * \returns true when the value of the environment variable is stored
+ * at the address \a path points to.
*/
static bool test_env_path(char *path, const char *envvar, const bool check_is_dir)
{
@@ -266,13 +271,14 @@ static bool test_env_path(char *path, const char *envvar, const bool check_is_di
return false;
}
+ BLI_strncpy(path, env_path, FILE_MAX);
+
if (check_is_dir == false) {
CLOG_INFO(&LOG, 3, "using env '%s' without test: '%s'", envvar, env_path);
return true;
}
if (BLI_is_dir(env_path)) {
- BLI_strncpy(path, env_path, FILE_MAX);
CLOG_INFO(&LOG, 3, "env '%s' found: %s", envvar, env_path);
return true;
}
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index e0b12228162..4aa328fcb22 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -2540,6 +2540,13 @@ void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, const bool do_id_
for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
/* Find the custom B-Bone handles. */
BKE_pchan_rebuild_bbone_handles(pose, pchan);
+ /* Re-validate that we are still using a valid pchan form custom transform. */
+ /* Note that we could store pointers of freed pchan in a GSet to speed this up, however this is
+ * supposed to be a rarely used feature, so for now assuming that always building that GSet
+ * would be less optimal. */
+ if (pchan->custom_tx != NULL && BLI_findindex(&pose->chanbase, pchan->custom_tx) == -1) {
+ pchan->custom_tx = NULL;
+ }
}
/* printf("rebuild pose %s, %d bones\n", ob->id.name, counter); */
@@ -2566,6 +2573,19 @@ void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, const bool do_id_
}
}
+/**
+ * Ensures object's pose is rebuilt if needed.
+ *
+ * \param bmain: May be NULL, only used to tag depsgraph as being dirty...
+ */
+void BKE_pose_ensure(Main *bmain, Object *ob, bArmature *arm, const bool do_id_user)
+{
+ BLI_assert(!ELEM(NULL, arm, ob));
+ if ((ob->pose == NULL) || (ob->pose->flag & POSE_RECALC)) {
+ BKE_pose_rebuild(bmain, ob, arm, do_id_user);
+ }
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -2704,11 +2724,9 @@ void BKE_pose_where_is(struct Depsgraph *depsgraph, Scene *scene, Object *ob)
if (ELEM(NULL, arm, scene)) {
return;
}
- if ((ob->pose == NULL) || (ob->pose->flag & POSE_RECALC)) {
- /* WARNING! passing NULL bmain here means we won't tag depsgraph's as dirty -
- * hopefully this is OK. */
- BKE_pose_rebuild(NULL, ob, arm, true);
- }
+ /* WARNING! passing NULL bmain here means we won't tag depsgraph's as dirty -
+ * hopefully this is OK. */
+ BKE_pose_ensure(NULL, ob, arm, true);
ctime = BKE_scene_frame_get(scene); /* not accurate... */
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index da4d9ea485c..17243b328e8 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -1707,11 +1707,10 @@ void BKE_brush_sculpt_reset(Brush *br)
case SCULPT_TOOL_SCRAPE:
case SCULPT_TOOL_FILL:
br->alpha = 0.7f;
- br->area_radius_factor = 1.0f;
+ br->area_radius_factor = 0.5f;
br->spacing = 7;
br->flag |= BRUSH_ACCUMULATE;
br->flag |= BRUSH_INVERT_TO_SCRAPE_FILL;
- br->flag2 |= BRUSH_AREA_RADIUS_PRESSURE;
break;
case SCULPT_TOOL_ROTATE:
br->alpha = 1.0;
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 1eb374d1a08..7e9ee1ad153 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -569,10 +569,9 @@ void BKE_curve_texspace_get(Curve *cu, float r_loc[3], float r_size[3])
bool BKE_nurbList_index_get_co(ListBase *nurb, const int index, float r_co[3])
{
- Nurb *nu;
int tot = 0;
- for (nu = nurb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, nurb) {
int tot_nu;
if (nu->type == CU_BEZIER) {
tot_nu = nu->pntsu;
@@ -596,39 +595,33 @@ bool BKE_nurbList_index_get_co(ListBase *nurb, const int index, float r_co[3])
int BKE_nurbList_verts_count(ListBase *nurb)
{
- Nurb *nu;
int tot = 0;
- nu = nurb->first;
- while (nu) {
+ LISTBASE_FOREACH (Nurb *, nu, nurb) {
if (nu->bezt) {
tot += 3 * nu->pntsu;
}
else if (nu->bp) {
tot += nu->pntsu * nu->pntsv;
}
-
- nu = nu->next;
}
+
return tot;
}
int BKE_nurbList_verts_count_without_handles(ListBase *nurb)
{
- Nurb *nu;
int tot = 0;
- nu = nurb->first;
- while (nu) {
+ LISTBASE_FOREACH (Nurb *, nu, nurb) {
if (nu->bezt) {
tot += nu->pntsu;
}
else if (nu->bp) {
tot += nu->pntsu * nu->pntsv;
}
-
- nu = nu->next;
}
+
return tot;
}
@@ -636,7 +629,6 @@ int BKE_nurbList_verts_count_without_handles(ListBase *nurb)
void BKE_nurb_free(Nurb *nu)
{
-
if (nu == NULL) {
return;
}
@@ -664,17 +656,12 @@ void BKE_nurb_free(Nurb *nu)
void BKE_nurbList_free(ListBase *lb)
{
- Nurb *nu, *next;
-
if (lb == NULL) {
return;
}
- nu = lb->first;
- while (nu) {
- next = nu->next;
+ LISTBASE_FOREACH_MUTABLE (Nurb *, nu, lb) {
BKE_nurb_free(nu);
- nu = next;
}
BLI_listbase_clear(lb);
}
@@ -747,16 +734,11 @@ Nurb *BKE_nurb_copy(Nurb *src, int pntsu, int pntsv)
void BKE_nurbList_duplicate(ListBase *lb1, const ListBase *lb2)
{
- Nurb *nu, *nun;
-
BKE_nurbList_free(lb1);
- nu = lb2->first;
- while (nu) {
- nun = BKE_nurb_duplicate(nu);
- BLI_addtail(lb1, nun);
-
- nu = nu->next;
+ LISTBASE_FOREACH (const Nurb *, nu, lb2) {
+ Nurb *nurb_new = BKE_nurb_duplicate(nu);
+ BLI_addtail(lb1, nurb_new);
}
}
@@ -2625,9 +2607,7 @@ static void bevlist_firstlast_direction_calc_from_bpoint(Nurb *nu, BevList *bl)
void BKE_curve_bevelList_free(ListBase *bev)
{
- BevList *bl, *blnext;
- for (bl = bev->first; bl != NULL; bl = blnext) {
- blnext = bl->next;
+ LISTBASE_FOREACH_MUTABLE (BevList *, bl, bev) {
if (bl->seglen != NULL) {
MEM_freeN(bl->seglen);
}
@@ -2654,10 +2634,9 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
/* this function needs an object, because of tflag and upflag */
Curve *cu = ob->data;
- Nurb *nu;
BezTriple *bezt, *prevbezt;
BPoint *bp;
- BevList *bl, *blnew, *blnext;
+ BevList *blnew;
BevPoint *bevp2, *bevp1 = NULL, *bevp0;
const float treshold = 0.00001f;
float min, inp;
@@ -2685,12 +2664,11 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
/* STEP 1: MAKE POLYS */
BKE_curve_bevelList_free(&ob->runtime.curve_cache->bev);
- nu = nurbs->first;
if (cu->editnurb && ob->type != OB_FONT) {
is_editmode = 1;
}
- for (; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, nurbs) {
if (nu->hide && is_editmode) {
continue;
}
@@ -2706,7 +2684,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
/* check we are a single point? also check we are not a surface and that the orderu is sane,
* enforced in the UI but can go wrong possibly */
if (!BKE_nurb_check_valid_u(nu)) {
- bl = MEM_callocN(sizeof(BevList), "makeBevelList1");
+ BevList *bl = MEM_callocN(sizeof(BevList), "makeBevelList1");
bl->bevpoints = MEM_calloc_arrayN(1, sizeof(BevPoint), "makeBevelPoints1");
BLI_addtail(bev, bl);
bl->nr = 0;
@@ -2726,7 +2704,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
if (nu->type == CU_POLY) {
len = nu->pntsu;
- bl = MEM_callocN(sizeof(BevList), "makeBevelList2");
+ BevList *bl = MEM_callocN(sizeof(BevList), "makeBevelList2");
bl->bevpoints = MEM_calloc_arrayN(len, sizeof(BevPoint), "makeBevelPoints2");
if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) {
bl->seglen = MEM_malloc_arrayN(segcount, sizeof(float), "makeBevelList2_seglen");
@@ -2777,7 +2755,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
/* in case last point is not cyclic */
len = segcount * resolu + 1;
- bl = MEM_callocN(sizeof(BevList), "makeBevelBPoints");
+ BevList *bl = MEM_callocN(sizeof(BevList), "makeBevelBPoints");
bl->bevpoints = MEM_calloc_arrayN(len, sizeof(BevPoint), "makeBevelBPointsPoints");
if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) {
bl->seglen = MEM_malloc_arrayN(segcount, sizeof(float), "makeBevelBPoints_seglen");
@@ -2930,7 +2908,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
if (nu->pntsv == 1) {
len = (resolu * segcount);
- bl = MEM_callocN(sizeof(BevList), "makeBevelList3");
+ BevList *bl = MEM_callocN(sizeof(BevList), "makeBevelList3");
bl->bevpoints = MEM_calloc_arrayN(len, sizeof(BevPoint), "makeBevelPoints3");
if (need_seglen && (nu->flagu & CU_NURB_CYCLIC) == 0) {
bl->seglen = MEM_malloc_arrayN(segcount, sizeof(float), "makeBevelList3_seglen");
@@ -2989,8 +2967,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
}
/* STEP 2: DOUBLE POINTS AND AUTOMATIC RESOLUTION, REDUCE DATABLOCKS */
- bl = bev->first;
- while (bl) {
+ LISTBASE_FOREACH (BevList *, bl, bev) {
if (bl->nr) { /* null bevel items come from single points */
bool is_cyclic = bl->poly != -1;
nr = bl->nr;
@@ -3025,11 +3002,9 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
bevp1++;
}
}
- bl = bl->next;
}
- bl = bev->first;
- while (bl) {
- blnext = bl->next;
+
+ LISTBASE_FOREACH_MUTABLE (BevList *, bl, bev) {
if (bl->nr && bl->dupe_nr) {
nr = bl->nr - bl->dupe_nr + 1; /* +1 because vectorbezier sets flag too */
blnew = MEM_mallocN(sizeof(BevList), "makeBevelList4");
@@ -3043,7 +3018,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
blnew->seglen = bl->seglen;
blnew->nr = 0;
BLI_remlink(bev, bl);
- BLI_insertlinkbefore(bev, blnext, blnew); /* to make sure bevlijst is tuned with nurblist */
+ BLI_insertlinkbefore(bev, bl->next, blnew); /* to make sure bevlist is tuned with nurblist */
bevp0 = bl->bevpoints;
bevp1 = blnew->bevpoints;
nr = bl->nr;
@@ -3061,26 +3036,22 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
MEM_freeN(bl);
blnew->dupe_nr = 0;
}
- bl = blnext;
}
/* STEP 3: POLYS COUNT AND AUTOHOLE */
- bl = bev->first;
poly = 0;
- while (bl) {
+ LISTBASE_FOREACH (BevList *, bl, bev) {
if (bl->nr && bl->poly >= 0) {
poly++;
bl->poly = poly;
bl->hole = 0;
}
- bl = bl->next;
}
/* find extreme left points, also test (turning) direction */
if (poly > 0) {
sd = sortdata = MEM_malloc_arrayN(poly, sizeof(struct BevelSort), "makeBevelList5");
- bl = bev->first;
- while (bl) {
+ LISTBASE_FOREACH (BevList *, bl, bev) {
if (bl->poly > 0) {
BevPoint *bevp;
@@ -3125,14 +3096,12 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
sd++;
}
-
- bl = bl->next;
}
qsort(sortdata, poly, sizeof(struct BevelSort), vergxcobev);
sd = sortdata + 1;
for (a = 1; a < poly; a++, sd++) {
- bl = sd->bl; /* is bl a hole? */
+ BevList *bl = sd->bl; /* is bl a hole? */
sd1 = sortdata + (a - 1);
for (b = a - 1; b >= 0; b--, sd1--) { /* all polys to the left */
if (sd1->bl->charidx == bl->charidx) { /* for text, only check matching char */
@@ -3149,7 +3118,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
sd = sortdata;
for (a = 0; a < poly; a++, sd++) {
if (sd->bl->hole == sd->dir) {
- bl = sd->bl;
+ BevList *bl = sd->bl;
bevp1 = bl->bevpoints;
bevp2 = bevp1 + (bl->nr - 1);
nr = bl->nr / 2;
@@ -3167,7 +3136,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
/* STEP 4: 2D-COSINES or 3D ORIENTATION */
if ((cu->flag & CU_3D) == 0) {
/* 2D Curves */
- for (bl = bev->first; bl; bl = bl->next) {
+ LISTBASE_FOREACH (BevList *, bl, bev) {
if (bl->nr < 2) {
BevPoint *bevp = bl->bevpoints;
unit_qt(bevp->quat);
@@ -3182,7 +3151,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
}
else {
/* 3D Curves */
- for (bl = bev->first; bl; bl = bl->next) {
+ LISTBASE_FOREACH (BevList *, bl, bev) {
if (bl->nr < 2) {
BevPoint *bevp = bl->bevpoints;
unit_qt(bevp->quat);
@@ -4316,12 +4285,8 @@ void BKE_nurb_handles_autocalc(Nurb *nu, uint8_t flag)
void BKE_nurbList_handles_autocalc(ListBase *editnurb, uint8_t flag)
{
- Nurb *nu;
-
- nu = editnurb->first;
- while (nu) {
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
BKE_nurb_handles_autocalc(nu, flag);
- nu = nu->next;
}
}
@@ -4333,13 +4298,11 @@ void BKE_nurbList_handles_set(ListBase *editnurb, const char code)
/* code==4: sets icu flag to become IPO_AUTO_HORIZ, horizontal extremes on auto-handles */
/* code==5: Set align, like 3 but no toggle */
/* code==6: Clear align, like 3 but no toggle */
- Nurb *nu;
BezTriple *bezt;
int a;
if (ELEM(code, HD_AUTO, HD_VECT)) {
- nu = editnurb->first;
- while (nu) {
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
if (nu->type == CU_BEZIER) {
bezt = nu->bezt;
a = nu->pntsu;
@@ -4366,7 +4329,6 @@ void BKE_nurbList_handles_set(ListBase *editnurb, const char code)
/* like BKE_nurb_handles_calc but moves selected */
nurb_handles_calc__align_selected(nu);
}
- nu = nu->next;
}
}
else {
@@ -4381,7 +4343,7 @@ void BKE_nurbList_handles_set(ListBase *editnurb, const char code)
}
else {
/* Toggle */
- for (nu = editnurb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
if (nu->type == CU_BEZIER) {
bezt = nu->bezt;
a = nu->pntsu;
@@ -4397,7 +4359,7 @@ void BKE_nurbList_handles_set(ListBase *editnurb, const char code)
}
h_new = (h_new == HD_FREE) ? HD_ALIGN : HD_FREE;
}
- for (nu = editnurb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
if (nu->type == CU_BEZIER) {
bezt = nu->bezt;
a = nu->pntsu;
@@ -4423,11 +4385,10 @@ void BKE_nurbList_handles_recalculate(ListBase *editnurb,
const bool calc_length,
const uint8_t flag)
{
- Nurb *nu;
BezTriple *bezt;
int a;
- for (nu = editnurb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
if (nu->type == CU_BEZIER) {
bool changed = false;
@@ -4477,12 +4438,11 @@ void BKE_nurbList_handles_recalculate(ListBase *editnurb,
void BKE_nurbList_flag_set(ListBase *editnurb, uint8_t flag, bool set)
{
- Nurb *nu;
BezTriple *bezt;
BPoint *bp;
int a;
- for (nu = editnurb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
if (nu->type == CU_BEZIER) {
a = nu->pntsu;
bezt = nu->bezt;
@@ -4518,7 +4478,7 @@ bool BKE_nurbList_flag_set_from_flag(ListBase *editnurb, uint8_t from_flag, uint
{
bool changed = false;
- for (Nurb *nu = editnurb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
if (nu->type == CU_BEZIER) {
for (int i = 0; i < nu->pntsu; i++) {
BezTriple *bezt = &nu->bezt[i];
@@ -5232,12 +5192,11 @@ bool BKE_curve_minmax(Curve *cu, bool use_radius, float min[3], float max[3])
bool BKE_curve_center_median(Curve *cu, float cent[3])
{
ListBase *nurb_lb = BKE_curve_nurbs_get(cu);
- Nurb *nu;
int total = 0;
zero_v3(cent);
- for (nu = nurb_lb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, nurb_lb) {
int i;
if (nu->type == CU_BEZIER) {
@@ -5285,12 +5244,11 @@ void BKE_curve_transform_ex(Curve *cu,
const bool do_props,
const float unit_scale)
{
- Nurb *nu;
BPoint *bp;
BezTriple *bezt;
int i;
- for (nu = cu->nurb.first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
if (nu->type == CU_BEZIER) {
i = nu->pntsu;
for (bezt = nu->bezt; i--; bezt++) {
@@ -5320,7 +5278,7 @@ void BKE_curve_transform_ex(Curve *cu,
float *fp = kb->data;
int n = kb->totelem;
- for (nu = cu->nurb.first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
if (nu->type == CU_BEZIER) {
for (i = nu->pntsu; i && (n -= KEYELEM_ELEM_LEN_BEZTRIPLE) >= 0; i--) {
mul_m4_v3(mat, &fp[0]);
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index bcb467e1230..ff03731b2aa 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -92,17 +92,13 @@ void BKE_displist_free(ListBase *lb)
DispList *BKE_displist_find_or_create(ListBase *lb, int type)
{
- DispList *dl;
-
- dl = lb->first;
- while (dl) {
+ LISTBASE_FOREACH (DispList *, dl, lb) {
if (dl->type == type) {
return dl;
}
- dl = dl->next;
}
- dl = MEM_callocN(sizeof(DispList), "find_disp");
+ DispList *dl = MEM_callocN(sizeof(DispList), "find_disp");
dl->type = type;
BLI_addtail(lb, dl);
@@ -111,14 +107,10 @@ DispList *BKE_displist_find_or_create(ListBase *lb, int type)
DispList *BKE_displist_find(ListBase *lb, int type)
{
- DispList *dl;
-
- dl = lb->first;
- while (dl) {
+ LISTBASE_FOREACH (DispList *, dl, lb) {
if (dl->type == type) {
return dl;
}
- dl = dl->next;
}
return NULL;
@@ -126,9 +118,7 @@ DispList *BKE_displist_find(ListBase *lb, int type)
bool BKE_displist_has_faces(ListBase *lb)
{
- DispList *dl;
-
- for (dl = lb->first; dl; dl = dl->next) {
+ LISTBASE_FOREACH (DispList *, dl, lb) {
if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
return true;
}
@@ -139,13 +129,10 @@ bool BKE_displist_has_faces(ListBase *lb)
void BKE_displist_copy(ListBase *lbn, ListBase *lb)
{
- DispList *dln, *dl;
-
BKE_displist_free(lbn);
- dl = lb->first;
- while (dl) {
- dln = MEM_dupallocN(dl);
+ LISTBASE_FOREACH (const DispList *, dl, lb) {
+ DispList *dln = MEM_dupallocN(dl);
BLI_addtail(lbn, dln);
dln->verts = MEM_dupallocN(dl->verts);
dln->nors = MEM_dupallocN(dl->nors);
@@ -154,22 +141,18 @@ void BKE_displist_copy(ListBase *lbn, ListBase *lb)
if (dl->bevel_split) {
dln->bevel_split = MEM_dupallocN(dl->bevel_split);
}
-
- dl = dl->next;
}
}
void BKE_displist_normals_add(ListBase *lb)
{
- DispList *dl = NULL;
float *vdata, *ndata, nor[3];
float *v1, *v2, *v3, *v4;
float *n1, *n2, *n3, *n4;
int a, b, p1, p2, p3, p4;
- dl = lb->first;
+ LISTBASE_FOREACH (DispList *, dl, lb) {
- while (dl) {
if (dl->type == DL_INDEX3) {
if (dl->nors == NULL) {
dl->nors = MEM_callocN(sizeof(float[3]), "dlnors");
@@ -230,15 +213,12 @@ void BKE_displist_normals_add(ListBase *lb)
}
}
}
- dl = dl->next;
}
}
void BKE_displist_count(ListBase *lb, int *totvert, int *totface, int *tottri)
{
- DispList *dl;
-
- for (dl = lb->first; dl; dl = dl->next) {
+ LISTBASE_FOREACH (DispList *, dl, lb) {
int vert_tot = 0;
int face_tot = 0;
int tri_tot = 0;
@@ -318,7 +298,6 @@ static void curve_to_displist(Curve *cu,
ListBase *dispbase,
const bool for_render)
{
- Nurb *nu;
DispList *dl;
BezTriple *bezt, *prevbezt;
BPoint *bp;
@@ -326,8 +305,7 @@ static void curve_to_displist(Curve *cu,
int a, len, resolu;
const bool editmode = (!for_render && (cu->editnurb || cu->editfont));
- nu = nubase->first;
- while (nu) {
+ LISTBASE_FOREACH (Nurb *, nu, nubase) {
if (nu->hide == 0 || editmode == false) {
if (for_render && cu->resolu_ren != 0) {
resolu = cu->resolu_ren;
@@ -473,7 +451,6 @@ static void curve_to_displist(Curve *cu,
}
}
}
- nu = nu->next;
}
}
@@ -627,19 +604,17 @@ static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase)
{
const float z_up[3] = {0.0f, 0.0f, -1.0f};
ListBase front, back;
- DispList *dl, *dlnew;
float *fp, *fp1;
int a, dpoly;
BLI_listbase_clear(&front);
BLI_listbase_clear(&back);
- dl = dispbase->first;
- while (dl) {
+ LISTBASE_FOREACH (DispList *, dl, dispbase) {
if (dl->type == DL_SURF) {
if ((dl->flag & DL_CYCL_V) && (dl->flag & DL_CYCL_U) == 0) {
if ((cu->flag & CU_BACK) && (dl->flag & DL_BACK_CURVE)) {
- dlnew = MEM_callocN(sizeof(DispList), "filldisp");
+ DispList *dlnew = MEM_callocN(sizeof(DispList), "filldisp");
BLI_addtail(&front, dlnew);
dlnew->verts = fp1 = MEM_mallocN(sizeof(float[3]) * dl->parts, "filldisp1");
dlnew->nr = dl->parts;
@@ -660,7 +635,7 @@ static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase)
}
}
if ((cu->flag & CU_FRONT) && (dl->flag & DL_FRONT_CURVE)) {
- dlnew = MEM_callocN(sizeof(DispList), "filldisp");
+ DispList *dlnew = MEM_callocN(sizeof(DispList), "filldisp");
BLI_addtail(&back, dlnew);
dlnew->verts = fp1 = MEM_mallocN(sizeof(float[3]) * dl->parts, "filldisp1");
dlnew->nr = dl->parts;
@@ -682,7 +657,6 @@ static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase)
}
}
}
- dl = dl->next;
}
BKE_displist_fill(&front, dispbase, z_up, true);
@@ -939,18 +913,17 @@ static bool curve_calc_modifiers_pre(
static float (*displist_vert_coords_alloc(ListBase *dispbase, int *r_vert_len))[3]
{
- DispList *dl;
float(*allverts)[3], *fp;
*r_vert_len = 0;
- for (dl = dispbase->first; dl; dl = dl->next) {
+ LISTBASE_FOREACH (DispList *, dl, dispbase) {
*r_vert_len += (dl->type == DL_INDEX3) ? dl->nr : dl->parts * dl->nr;
}
allverts = MEM_mallocN(sizeof(float[3]) * (*r_vert_len), "displist_vert_coords_alloc allverts");
fp = (float *)allverts;
- for (dl = dispbase->first; dl; dl = dl->next) {
+ LISTBASE_FOREACH (DispList *, dl, dispbase) {
int offs = 3 * ((dl->type == DL_INDEX3) ? dl->nr : dl->parts * dl->nr);
memcpy(fp, dl->verts, sizeof(float) * offs);
fp += offs;
@@ -961,11 +934,10 @@ static float (*displist_vert_coords_alloc(ListBase *dispbase, int *r_vert_len))[
static void displist_vert_coords_apply(ListBase *dispbase, float (*allverts)[3])
{
- DispList *dl;
const float *fp;
fp = (float *)allverts;
- for (dl = dispbase->first; dl; dl = dl->next) {
+ LISTBASE_FOREACH (DispList *, dl, dispbase) {
int offs = 3 * ((dl->type == DL_INDEX3) ? dl->nr : dl->parts * dl->nr);
memcpy(dl->verts, fp, sizeof(float) * offs);
fp += offs;
@@ -1218,7 +1190,6 @@ void BKE_displist_make_surf(Depsgraph *depsgraph,
const bool for_orco)
{
ListBase nubase = {NULL, NULL};
- Nurb *nu;
Curve *cu = ob->data;
DispList *dl;
float *data;
@@ -1236,7 +1207,7 @@ void BKE_displist_make_surf(Depsgraph *depsgraph,
force_mesh_conversion = curve_calc_modifiers_pre(depsgraph, scene, ob, &nubase, for_render);
}
- for (nu = nubase.first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, &nubase) {
if ((for_render || nu->hide == 0) && BKE_nurb_check_valid_uv(nu)) {
int resolu = nu->resolu, resolv = nu->resolv;
@@ -1851,12 +1822,11 @@ void BKE_displist_make_curveTypes_forRender(Depsgraph *depsgraph,
void BKE_displist_minmax(ListBase *dispbase, float min[3], float max[3])
{
- DispList *dl;
const float *vert;
int a, tot = 0;
int doit = 0;
- for (dl = dispbase->first; dl; dl = dl->next) {
+ LISTBASE_FOREACH (DispList *, dl, dispbase) {
tot = (dl->type == DL_INDEX3) ? dl->nr : dl->nr * dl->parts;
vert = dl->verts;
for (a = 0; a < tot; a++, vert += 3) {
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index fafcbaec10f..dcf4c78dfd8 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -842,7 +842,8 @@ bool BKE_fcurve_calc_range(
void BKE_fcurve_active_keyframe_set(FCurve *fcu, const BezTriple *active_bezt)
{
/* The active keyframe should always be selected. */
- BLI_assert(active_bezt == NULL || (active_bezt->f2 & SELECT));
+ BLI_assert((active_bezt == NULL) ||
+ ((active_bezt->f1 | active_bezt->f2 | active_bezt->f3) & SELECT));
fcu->active_keyframe_index = (active_bezt == NULL) ? FCURVE_ACTIVE_KEYFRAME_NONE :
active_bezt - fcu->bezt;
}
@@ -861,7 +862,7 @@ int BKE_fcurve_active_keyframe_index(const FCurve *fcu)
}
const BezTriple *active_bezt = &fcu->bezt[active_keyframe_index];
- if ((active_bezt->f2 & SELECT) == 0) {
+ if (((active_bezt->f1 | active_bezt->f2 | active_bezt->f3) & SELECT) == 0) {
/* The active keyframe should always be selected. If it's not selected, it can't be active. */
return FCURVE_ACTIVE_KEYFRAME_NONE;
}
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 31cd812f8df..6c6ca996caa 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -2549,17 +2549,17 @@ void BKE_gpencil_visible_stroke_iter(ViewLayer *view_layer,
/* Use evaluated frame (with modifiers for active stroke)/ */
act_gpf = gpl->actframe;
if (act_gpf) {
+ act_gpf->runtime.onion_id = 0;
+ if (layer_cb) {
+ layer_cb(gpl, act_gpf, NULL, thunk);
+ }
+
/* If layer solo mode and Paint mode, only keyframes with data are displayed. */
if (GPENCIL_PAINT_MODE(gpd) && (gpl->flag & GP_LAYER_SOLO_MODE) &&
(act_gpf->framenum != cfra)) {
continue;
}
- act_gpf->runtime.onion_id = 0;
- if (layer_cb) {
- layer_cb(gpl, act_gpf, NULL, thunk);
- }
-
LISTBASE_FOREACH (bGPDstroke *, gps, &act_gpf->strokes) {
if (gps->totpoints == 0) {
continue;
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index 27422440cd5..ae6ee71da82 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -1884,6 +1884,9 @@ void BKE_library_make_local(Main *bmain,
if (id->lib == NULL) {
id->tag &= ~(LIB_TAG_EXTERN | LIB_TAG_INDIRECT | LIB_TAG_NEW);
id->flag &= ~LIB_INDIRECT_WEAK_LINK;
+ if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
+ BKE_lib_override_library_free(&id->override_library, true);
+ }
}
/* The check on the fourth line (LIB_TAG_PRE_EXISTING) is done so it's possible to tag data
* you don't want to be made local, used for appending data,
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c
index e008058ae39..3bac0cf6289 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -1422,6 +1422,15 @@ void BKE_lib_override_library_main_operations_create(Main *bmain, const bool for
FOREACH_MAIN_ID_BEGIN (bmain, id) {
if (ID_IS_OVERRIDE_LIBRARY_REAL(id) &&
(force_auto || (id->tag & LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH))) {
+ /* Usual issue with pose, it's quiet rare but sometimes they may not be up to date when this
+ * function is called. */
+ if (GS(id->name) == ID_OB) {
+ Object *ob = (Object *)id;
+ if (ob->type == OB_ARMATURE) {
+ BLI_assert(ob->data != NULL);
+ BKE_pose_ensure(bmain, ob, ob->data, true);
+ }
+ }
/* Only check overrides if we do have the real reference data available, and not some empty
* 'placeholder' for missing data (broken links). */
if ((id->override_library->reference->tag & LIB_TAG_MISSING) == 0) {
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 6ea83cf4330..97520654e7b 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -275,50 +275,6 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id)
mesh->totselect = 0;
}
- /* Multires data */
- BLO_read_data_address(reader, &mesh->mr);
- if (mesh->mr) {
- BLO_read_list(reader, &mesh->mr->levels);
- MultiresLevel *lvl = mesh->mr->levels.first;
-
- CustomData_blend_read(reader, &mesh->mr->vdata, lvl->totvert);
- BKE_defvert_blend_read(
- reader, lvl->totvert, CustomData_get(&mesh->mr->vdata, 0, CD_MDEFORMVERT));
- CustomData_blend_read(reader, &mesh->mr->fdata, lvl->totface);
-
- BLO_read_data_address(reader, &mesh->mr->edge_flags);
- BLO_read_data_address(reader, &mesh->mr->edge_creases);
-
- BLO_read_data_address(reader, &mesh->mr->verts);
-
- /* If mesh has the same number of vertices as the
- * highest multires level, load the current mesh verts
- * into multires and discard the old data. Needed
- * because some saved files either do not have a verts
- * array, or the verts array contains out-of-date
- * data. */
- if (mesh->totvert == ((MultiresLevel *)mesh->mr->levels.last)->totvert) {
- if (mesh->mr->verts) {
- MEM_freeN(mesh->mr->verts);
- }
- mesh->mr->verts = MEM_dupallocN(mesh->mvert);
- }
-
- for (; lvl; lvl = lvl->next) {
- BLO_read_data_address(reader, &lvl->verts);
- BLO_read_data_address(reader, &lvl->faces);
- BLO_read_data_address(reader, &lvl->edges);
- BLO_read_data_address(reader, &lvl->colfaces);
- }
- }
-
- /* if multires is present but has no valid vertex data,
- * there's no way to recover it; silently remove multires */
- if (mesh->mr && !mesh->mr->verts) {
- multires_free(mesh->mr);
- mesh->mr = NULL;
- }
-
if ((BLO_read_requires_endian_switch(reader)) && mesh->tface) {
TFace *tf = mesh->tface;
for (int i = 0; i < mesh->totface; i++, tf++) {
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 6e1168d8a16..d7ea662a5d6 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -63,7 +63,6 @@
#include <string.h>
/* MULTIRES MODIFIER */
-static const int multires_max_levels = 13;
static const int multires_grid_tot[] = {
0, 4, 9, 25, 81, 289, 1089, 4225, 16641, 66049, 263169, 1050625, 4198401, 16785409};
static const int multires_side_tot[] = {
@@ -76,7 +75,6 @@ typedef enum {
ADD_DISPLACEMENTS,
} DispOp;
-static void multires_mvert_to_ss(DerivedMesh *dm, MVert *mvert);
static void multiresModifier_disp_run(
DerivedMesh *dm, Mesh *me, DerivedMesh *dm2, DispOp op, CCGElem **oldGridData, int totlvl);
@@ -241,40 +239,6 @@ static void multires_mdisps_subdivide_hidden(MDisps *md, int new_level)
md->hidden = subd;
}
-static MDisps *multires_mdisps_init_hidden(Mesh *me, int level)
-{
- MDisps *mdisps = CustomData_add_layer(&me->ldata, CD_MDISPS, CD_CALLOC, NULL, me->totloop);
- int gridsize = BKE_ccg_gridsize(level);
- int gridarea = square_i(gridsize);
- int i, j;
-
- for (i = 0; i < me->totpoly; i++) {
- bool hide = false;
-
- for (j = 0; j < me->mpoly[i].totloop; j++) {
- if (me->mvert[me->mloop[me->mpoly[i].loopstart + j].v].flag & ME_HIDE) {
- hide = true;
- break;
- }
- }
-
- if (!hide) {
- continue;
- }
-
- for (j = 0; j < me->mpoly[i].totloop; j++) {
- MDisps *md = &mdisps[me->mpoly[i].loopstart + j];
-
- BLI_assert(!md->hidden);
-
- md->hidden = BLI_BITMAP_NEW(gridarea, "MDisps.hidden initialize");
- BLI_bitmap_set_all(md->hidden, true, gridarea);
- }
- }
-
- return mdisps;
-}
-
Mesh *BKE_multires_create_mesh(struct Depsgraph *depsgraph,
Object *object,
MultiresModifierData *mmd)
@@ -429,12 +393,6 @@ void multires_set_tot_level(Object *ob, MultiresModifierData *mmd, int lvl)
mmd->renderlvl = CLAMPIS(MAX2(mmd->renderlvl, lvl), 0, mmd->totlvl);
}
-static void multires_dm_mark_as_modified(DerivedMesh *dm, MultiresModifiedFlags flags)
-{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
- ccgdm->multires.modified_flags |= flags;
-}
-
static void multires_ccg_mark_as_modified(SubdivCCG *subdiv_ccg, MultiresModifiedFlags flags)
{
if (flags & MULTIRES_COORDS_MODIFIED) {
@@ -850,110 +808,6 @@ static DerivedMesh *subsurf_dm_create_local(Scene *scene,
return subsurf_make_derived_from_derived(dm, &smd, scene, NULL, flags);
}
-static void multires_subdivide_legacy(
- MultiresModifierData *mmd, Scene *scene, Object *ob, int totlvl, int updateblock, int simple)
-{
- Mesh *me = ob->data;
- MDisps *mdisps;
- const int lvl = mmd->totlvl;
-
- if ((totlvl > multires_max_levels) || (me->totpoly == 0)) {
- return;
- }
-
- BLI_assert(totlvl > lvl);
-
- multires_force_sculpt_rebuild(ob);
-
- mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
- if (!mdisps) {
- mdisps = multires_mdisps_init_hidden(me, totlvl);
- }
-
- if (mdisps->disps && !updateblock && lvl != 0) {
- /* upsample */
- DerivedMesh *lowdm, *cddm, *highdm;
- CCGElem **highGridData, **lowGridData, **subGridData;
- CCGKey highGridKey, lowGridKey;
- CCGSubSurf *ss;
- int i, numGrids, highGridSize;
- const bool has_mask = CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK);
-
- /* create subsurf DM from original mesh at high level */
- cddm = CDDM_from_mesh(me);
- DM_set_only_copy(cddm, &CD_MASK_BAREMESH);
- highdm = subsurf_dm_create_local(NULL,
- ob,
- cddm,
- totlvl,
- simple,
- 0,
- mmd->uv_smooth == SUBSURF_UV_SMOOTH_NONE,
- has_mask,
- false,
- SUBSURF_IGNORE_SIMPLIFY);
- ss = ((CCGDerivedMesh *)highdm)->ss;
-
- /* create multires DM from original mesh at low level */
- lowdm = multires_dm_create_local(
- scene, ob, cddm, lvl, lvl, simple, has_mask, MULTIRES_IGNORE_SIMPLIFY);
- BLI_assert(lowdm != cddm);
- cddm->release(cddm);
-
- /* copy subsurf grids and replace them with low displaced grids */
- numGrids = highdm->getNumGrids(highdm);
- highGridSize = highdm->getGridSize(highdm);
- highGridData = highdm->getGridData(highdm);
- highdm->getGridKey(highdm, &highGridKey);
- lowGridData = lowdm->getGridData(lowdm);
- lowdm->getGridKey(lowdm, &lowGridKey);
-
- subGridData = MEM_calloc_arrayN(numGrids, sizeof(float *), "subGridData*");
-
- for (i = 0; i < numGrids; i++) {
- /* backup subsurf grids */
- subGridData[i] = MEM_calloc_arrayN(
- highGridKey.elem_size, highGridSize * highGridSize, "subGridData");
- memcpy(subGridData[i], highGridData[i], highGridKey.elem_size * highGridSize * highGridSize);
-
- /* overwrite with current displaced grids */
- multires_copy_dm_grid(highGridData[i], lowGridData[i], &highGridKey, &lowGridKey);
- }
-
- /* low lower level dm no longer needed at this point */
- lowdm->release(lowdm);
-
- /* subsurf higher levels again with displaced data */
- ccgSubSurf_updateFromFaces(ss, lvl, NULL, 0);
- ccgSubSurf_updateLevels(ss, lvl, NULL, 0);
-
- /* reallocate displacements */
- multires_reallocate_mdisps(me->totloop, mdisps, totlvl);
-
- /* compute displacements */
- multiresModifier_disp_run(highdm, me, NULL, CALC_DISPLACEMENTS, subGridData, totlvl);
-
- /* free */
- highdm->release(highdm);
- for (i = 0; i < numGrids; i++) {
- MEM_freeN(subGridData[i]);
- }
- MEM_freeN(subGridData);
- }
- else {
- /* only reallocate, nothing to upsample */
- multires_reallocate_mdisps(me->totloop, mdisps, totlvl);
- }
-
- multires_set_tot_level(ob, mmd, totlvl);
-}
-
-void multiresModifier_subdivide_legacy(
- MultiresModifierData *mmd, Scene *scene, Object *ob, int updateblock, int simple)
-{
- multires_subdivide_legacy(mmd, scene, ob, mmd->totlvl + 1, updateblock, simple);
-}
-
static void grid_tangent(const CCGKey *key, int x, int y, int axis, CCGElem *grid, float t[3])
{
if (axis == 0) {
@@ -1449,9 +1303,6 @@ DerivedMesh *multires_make_derived_from_derived(
return result;
}
-/**** Old Multires code ****
- ***************************/
-
/* Adapted from sculptmode.c */
void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u, float v)
{
@@ -1506,723 +1357,6 @@ void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u,
add_v3_v3v3(out, d2[0], d2[1]);
}
-static void old_mdisps_rotate(
- int S, int UNUSED(newside), int oldside, int x, int y, float *u, float *v)
-{
- float offset = oldside * 0.5f - 0.5f;
-
- if (S == 1) {
- *u = offset + x;
- *v = offset - y;
- }
- if (S == 2) {
- *u = offset + y;
- *v = offset + x;
- }
- if (S == 3) {
- *u = offset - x;
- *v = offset + y;
- }
- if (S == 0) {
- *u = offset - y;
- *v = offset - x;
- }
-}
-
-static void old_mdisps_convert(MFace *mface, MDisps *mdisp)
-{
- int newlvl = log(sqrt(mdisp->totdisp) - 1) / M_LN2;
- int oldlvl = newlvl + 1;
- int oldside = multires_side_tot[oldlvl];
- int newside = multires_side_tot[newlvl];
- int nvert = (mface->v4) ? 4 : 3;
- int newtotdisp = multires_grid_tot[newlvl] * nvert;
- int x, y, S;
- float(*disps)[3], (*out)[3], u = 0.0f, v = 0.0f; /* Quite gcc barking. */
-
- disps = MEM_calloc_arrayN(newtotdisp, sizeof(float[3]), "multires disps");
-
- out = disps;
- for (S = 0; S < nvert; S++) {
- for (y = 0; y < newside; y++) {
- for (x = 0; x < newside; x++, out++) {
- old_mdisps_rotate(S, newside, oldside, x, y, &u, &v);
- old_mdisps_bilinear(*out, mdisp->disps, oldside, u, v);
-
- if (S == 1) {
- (*out)[1] = -(*out)[1];
- }
- else if (S == 2) {
- SWAP(float, (*out)[0], (*out)[1]);
- }
- else if (S == 3) {
- (*out)[0] = -(*out)[0];
- }
- else if (S == 0) {
- SWAP(float, (*out)[0], (*out)[1]);
- (*out)[0] = -(*out)[0];
- (*out)[1] = -(*out)[1];
- }
- }
- }
- }
-
- MEM_freeN(mdisp->disps);
-
- mdisp->totdisp = newtotdisp;
- mdisp->level = newlvl;
- mdisp->disps = disps;
-}
-
-void multires_load_old_250(Mesh *me)
-{
- MDisps *mdisps, *mdisps2;
- MFace *mf;
- int i, j, k;
-
- mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS);
-
- if (mdisps) {
- for (i = 0; i < me->totface; i++) {
- if (mdisps[i].totdisp) {
- old_mdisps_convert(&me->mface[i], &mdisps[i]);
- }
- }
-
- CustomData_add_layer(&me->ldata, CD_MDISPS, CD_CALLOC, NULL, me->totloop);
- mdisps2 = CustomData_get_layer(&me->ldata, CD_MDISPS);
-
- k = 0;
- mf = me->mface;
- for (i = 0; i < me->totface; i++, mf++) {
- int nvert = mf->v4 ? 4 : 3;
- int totdisp = mdisps[i].totdisp / nvert;
-
- for (j = 0; j < nvert; j++, k++) {
- mdisps2[k].disps = MEM_calloc_arrayN(
- totdisp, sizeof(float[3]), "multires disp in conversion");
- mdisps2[k].totdisp = totdisp;
- mdisps2[k].level = mdisps[i].level;
- memcpy(mdisps2[k].disps, mdisps[i].disps + totdisp * j, totdisp);
- }
- }
- }
-}
-
-/* Does not actually free lvl itself */
-static void multires_free_level(MultiresLevel *lvl)
-{
- if (lvl) {
- if (lvl->faces) {
- MEM_freeN(lvl->faces);
- }
- if (lvl->edges) {
- MEM_freeN(lvl->edges);
- }
- if (lvl->colfaces) {
- MEM_freeN(lvl->colfaces);
- }
- }
-}
-
-void multires_free(Multires *mr)
-{
- if (mr) {
- MultiresLevel *lvl = mr->levels.first;
-
- /* Free the first-level data */
- if (lvl) {
- CustomData_free(&mr->vdata, lvl->totvert);
- CustomData_free(&mr->fdata, lvl->totface);
- if (mr->edge_flags) {
- MEM_freeN(mr->edge_flags);
- }
- if (mr->edge_creases) {
- MEM_freeN(mr->edge_creases);
- }
- }
-
- while (lvl) {
- multires_free_level(lvl);
- lvl = lvl->next;
- }
-
- /* mr->verts may be NULL when loading old files,
- * see direct_link_mesh() in readfile.c, and T43560. */
- MEM_SAFE_FREE(mr->verts);
-
- BLI_freelistN(&mr->levels);
-
- MEM_freeN(mr);
- }
-}
-
-typedef struct IndexNode {
- struct IndexNode *next, *prev;
- int index;
-} IndexNode;
-
-static void create_old_vert_face_map(ListBase **map,
- IndexNode **mem,
- const MultiresFace *mface,
- const int totvert,
- const int totface)
-{
- int i, j;
- IndexNode *node = NULL;
-
- (*map) = MEM_calloc_arrayN(totvert, sizeof(ListBase), "vert face map");
- (*mem) = MEM_calloc_arrayN(totface, sizeof(IndexNode[4]), "vert face map mem");
- node = *mem;
-
- /* Find the users */
- for (i = 0; i < totface; i++) {
- for (j = 0; j < (mface[i].v[3] ? 4 : 3); j++, node++) {
- node->index = i;
- BLI_addtail(&(*map)[mface[i].v[j]], node);
- }
- }
-}
-
-static void create_old_vert_edge_map(ListBase **map,
- IndexNode **mem,
- const MultiresEdge *medge,
- const int totvert,
- const int totedge)
-{
- int i, j;
- IndexNode *node = NULL;
-
- (*map) = MEM_calloc_arrayN(totvert, sizeof(ListBase), "vert edge map");
- (*mem) = MEM_calloc_arrayN(totedge, sizeof(IndexNode[2]), "vert edge map mem");
- node = *mem;
-
- /* Find the users */
- for (i = 0; i < totedge; i++) {
- for (j = 0; j < 2; j++, node++) {
- node->index = i;
- BLI_addtail(&(*map)[medge[i].v[j]], node);
- }
- }
-}
-
-static MultiresFace *find_old_face(
- ListBase *map, MultiresFace *faces, int v1, int v2, int v3, int v4)
-{
- IndexNode *n1;
- int v[4], i, j;
-
- v[0] = v1;
- v[1] = v2;
- v[2] = v3;
- v[3] = v4;
-
- for (n1 = map[v1].first; n1; n1 = n1->next) {
- int fnd[4] = {0, 0, 0, 0};
-
- for (i = 0; i < 4; i++) {
- for (j = 0; j < 4; j++) {
- if (v[i] == faces[n1->index].v[j]) {
- fnd[i] = 1;
- }
- }
- }
-
- if (fnd[0] && fnd[1] && fnd[2] && fnd[3]) {
- return &faces[n1->index];
- }
- }
-
- return NULL;
-}
-
-static MultiresEdge *find_old_edge(ListBase *map, MultiresEdge *edges, int v1, int v2)
-{
- IndexNode *n1, *n2;
-
- for (n1 = map[v1].first; n1; n1 = n1->next) {
- for (n2 = map[v2].first; n2; n2 = n2->next) {
- if (n1->index == n2->index) {
- return &edges[n1->index];
- }
- }
- }
-
- return NULL;
-}
-
-static void multires_load_old_edges(
- ListBase **emap, MultiresLevel *lvl, int *vvmap, int dst, int v1, int v2, int mov)
-{
- int emid = find_old_edge(emap[2], lvl->edges, v1, v2)->mid;
- vvmap[dst + mov] = emid;
-
- if (lvl->next->next) {
- multires_load_old_edges(emap + 1, lvl->next, vvmap, dst + mov, v1, emid, mov / 2);
- multires_load_old_edges(emap + 1, lvl->next, vvmap, dst + mov, v2, emid, -mov / 2);
- }
-}
-
-static void multires_load_old_faces(ListBase **fmap,
- ListBase **emap,
- MultiresLevel *lvl,
- int *vvmap,
- int dst,
- int v1,
- int v2,
- int v3,
- int v4,
- int st2,
- int st3)
-{
- int fmid;
- int emid13, emid14, emid23, emid24;
-
- if (lvl && lvl->next) {
- fmid = find_old_face(fmap[1], lvl->faces, v1, v2, v3, v4)->mid;
- vvmap[dst] = fmid;
-
- emid13 = find_old_edge(emap[1], lvl->edges, v1, v3)->mid;
- emid14 = find_old_edge(emap[1], lvl->edges, v1, v4)->mid;
- emid23 = find_old_edge(emap[1], lvl->edges, v2, v3)->mid;
- emid24 = find_old_edge(emap[1], lvl->edges, v2, v4)->mid;
-
- multires_load_old_faces(fmap + 1,
- emap + 1,
- lvl->next,
- vvmap,
- dst + st2 * st3 + st3,
- fmid,
- v2,
- emid23,
- emid24,
- st2,
- st3 / 2);
-
- multires_load_old_faces(fmap + 1,
- emap + 1,
- lvl->next,
- vvmap,
- dst - st2 * st3 + st3,
- emid14,
- emid24,
- fmid,
- v4,
- st2,
- st3 / 2);
-
- multires_load_old_faces(fmap + 1,
- emap + 1,
- lvl->next,
- vvmap,
- dst + st2 * st3 - st3,
- emid13,
- emid23,
- v3,
- fmid,
- st2,
- st3 / 2);
-
- multires_load_old_faces(fmap + 1,
- emap + 1,
- lvl->next,
- vvmap,
- dst - st2 * st3 - st3,
- v1,
- fmid,
- emid13,
- emid14,
- st2,
- st3 / 2);
-
- if (lvl->next->next) {
- multires_load_old_edges(emap, lvl->next, vvmap, dst, emid24, fmid, st3);
- multires_load_old_edges(emap, lvl->next, vvmap, dst, emid13, fmid, -st3);
- multires_load_old_edges(emap, lvl->next, vvmap, dst, emid14, fmid, -st2 * st3);
- multires_load_old_edges(emap, lvl->next, vvmap, dst, emid23, fmid, st2 * st3);
- }
- }
-}
-
-static void multires_mvert_to_ss(DerivedMesh *dm, MVert *mvert)
-{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
- CCGSubSurf *ss = ccgdm->ss;
- CCGElem *vd;
- CCGKey key;
- int index;
- int totvert, totedge, totface;
- int gridSize = ccgSubSurf_getGridSize(ss);
- int edgeSize = ccgSubSurf_getEdgeSize(ss);
- int i = 0;
-
- dm->getGridKey(dm, &key);
-
- totface = ccgSubSurf_getNumFaces(ss);
- for (index = 0; index < totface; index++) {
- CCGFace *f = ccgdm->faceMap[index].face;
- int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
-
- vd = ccgSubSurf_getFaceCenterData(f);
- copy_v3_v3(CCG_elem_co(&key, vd), mvert[i].co);
- i++;
-
- for (S = 0; S < numVerts; S++) {
- for (x = 1; x < gridSize - 1; x++, i++) {
- vd = ccgSubSurf_getFaceGridEdgeData(ss, f, S, x);
- copy_v3_v3(CCG_elem_co(&key, vd), mvert[i].co);
- }
- }
-
- for (S = 0; S < numVerts; S++) {
- for (y = 1; y < gridSize - 1; y++) {
- for (x = 1; x < gridSize - 1; x++, i++) {
- vd = ccgSubSurf_getFaceGridData(ss, f, S, x, y);
- copy_v3_v3(CCG_elem_co(&key, vd), mvert[i].co);
- }
- }
- }
- }
-
- totedge = ccgSubSurf_getNumEdges(ss);
- for (index = 0; index < totedge; index++) {
- CCGEdge *e = ccgdm->edgeMap[index].edge;
- int x;
-
- for (x = 1; x < edgeSize - 1; x++, i++) {
- vd = ccgSubSurf_getEdgeData(ss, e, x);
- copy_v3_v3(CCG_elem_co(&key, vd), mvert[i].co);
- }
- }
-
- totvert = ccgSubSurf_getNumVerts(ss);
- for (index = 0; index < totvert; index++) {
- CCGVert *v = ccgdm->vertMap[index].vert;
-
- vd = ccgSubSurf_getVertData(ss, v);
- copy_v3_v3(CCG_elem_co(&key, vd), mvert[i].co);
- i++;
- }
-
- ccgSubSurf_updateToFaces(ss, 0, NULL, 0);
-}
-
-/* Loads a multires object stored in the old Multires struct into the new format */
-static void multires_load_old_dm(DerivedMesh *dm, Mesh *me, int totlvl)
-{
- MultiresLevel *lvl, *lvl1;
- Multires *mr = me->mr;
- MVert *vsrc, *vdst;
- unsigned int src, dst;
- int st_last = multires_side_tot[totlvl - 1] - 1;
- int extedgelen = multires_side_tot[totlvl] - 2;
- int *vvmap; // inorder for dst, map to src
- int crossedgelen;
- int s, x, tottri, totquad;
- unsigned int i, j, totvert;
-
- src = 0;
- vsrc = mr->verts;
- vdst = dm->getVertArray(dm);
- totvert = (unsigned int)dm->getNumVerts(dm);
- vvmap = MEM_calloc_arrayN(totvert, sizeof(int), "multires vvmap");
-
- if (!vvmap) {
- return;
- }
-
- lvl1 = mr->levels.first;
- /* Load base verts */
- for (i = 0; i < lvl1->totvert; i++) {
- vvmap[totvert - lvl1->totvert + i] = src;
- src++;
- }
-
- /* Original edges */
- dst = totvert - lvl1->totvert - extedgelen * lvl1->totedge;
- for (i = 0; i < lvl1->totedge; i++) {
- int ldst = dst + extedgelen * i;
- int lsrc = src;
- lvl = lvl1->next;
-
- for (j = 2; j <= mr->level_count; j++) {
- int base = multires_side_tot[totlvl - j + 1] - 2;
- int skip = multires_side_tot[totlvl - j + 2] - 1;
- int st = multires_side_tot[j - 1] - 1;
-
- for (x = 0; x < st; x++) {
- vvmap[ldst + base + x * skip] = lsrc + st * i + x;
- }
-
- lsrc += lvl->totvert - lvl->prev->totvert;
- lvl = lvl->next;
- }
- }
-
- /* Center points */
- dst = 0;
- for (i = 0; i < lvl1->totface; i++) {
- int sides = lvl1->faces[i].v[3] ? 4 : 3;
-
- vvmap[dst] = src + lvl1->totedge + i;
- dst += 1 + sides * (st_last - 1) * st_last;
- }
-
- /* The rest is only for level 3 and up */
- if (lvl1->next && lvl1->next->next) {
- ListBase **fmap, **emap;
- IndexNode **fmem, **emem;
-
- /* Face edge cross */
- tottri = totquad = 0;
- crossedgelen = multires_side_tot[totlvl - 1] - 2;
- dst = 0;
- for (i = 0; i < lvl1->totface; i++) {
- int sides = lvl1->faces[i].v[3] ? 4 : 3;
-
- lvl = lvl1->next->next;
- dst++;
-
- for (j = 3; j <= mr->level_count; j++) {
- int base = multires_side_tot[totlvl - j + 1] - 2;
- int skip = multires_side_tot[totlvl - j + 2] - 1;
- int st = pow(2, j - 2);
- int st2 = pow(2, j - 3);
- int lsrc = lvl->prev->totvert;
-
- /* Skip exterior edge verts */
- lsrc += lvl1->totedge * st;
-
- /* Skip earlier face edge crosses */
- lsrc += st2 * (tottri * 3 + totquad * 4);
-
- for (s = 0; s < sides; s++) {
- for (x = 0; x < st2; x++) {
- vvmap[dst + crossedgelen * (s + 1) - base - x * skip - 1] = lsrc;
- lsrc++;
- }
- }
-
- lvl = lvl->next;
- }
-
- dst += sides * (st_last - 1) * st_last;
-
- if (sides == 4) {
- totquad++;
- }
- else {
- tottri++;
- }
- }
-
- /* calculate vert to edge/face maps for each level (except the last) */
- fmap = MEM_calloc_arrayN((mr->level_count - 1), sizeof(ListBase *), "multires fmap");
- emap = MEM_calloc_arrayN((mr->level_count - 1), sizeof(ListBase *), "multires emap");
- fmem = MEM_calloc_arrayN((mr->level_count - 1), sizeof(IndexNode *), "multires fmem");
- emem = MEM_calloc_arrayN((mr->level_count - 1), sizeof(IndexNode *), "multires emem");
- lvl = lvl1;
- for (i = 0; i < (unsigned int)mr->level_count - 1; i++) {
- create_old_vert_face_map(fmap + i, fmem + i, lvl->faces, lvl->totvert, lvl->totface);
- create_old_vert_edge_map(emap + i, emem + i, lvl->edges, lvl->totvert, lvl->totedge);
- lvl = lvl->next;
- }
-
- /* Interior face verts */
- /* lvl = lvl1->next->next; */ /* UNUSED */
- dst = 0;
- for (j = 0; j < lvl1->totface; j++) {
- int sides = lvl1->faces[j].v[3] ? 4 : 3;
- int ldst = dst + 1 + sides * (st_last - 1);
-
- for (s = 0; s < sides; s++) {
- int st2 = multires_side_tot[totlvl - 1] - 2;
- int st3 = multires_side_tot[totlvl - 2] - 2;
- int st4 = st3 == 0 ? 1 : (st3 + 1) / 2;
- int mid = ldst + st2 * st3 + st3;
- int cv = lvl1->faces[j].v[s];
- int nv = lvl1->faces[j].v[s == sides - 1 ? 0 : s + 1];
- int pv = lvl1->faces[j].v[s == 0 ? sides - 1 : s - 1];
-
- multires_load_old_faces(fmap,
- emap,
- lvl1->next,
- vvmap,
- mid,
- vvmap[dst],
- cv,
- find_old_edge(emap[0], lvl1->edges, pv, cv)->mid,
- find_old_edge(emap[0], lvl1->edges, cv, nv)->mid,
- st2,
- st4);
-
- ldst += (st_last - 1) * (st_last - 1);
- }
-
- dst = ldst;
- }
-
- /*lvl = lvl->next;*/ /*UNUSED*/
-
- for (i = 0; i < (unsigned int)(mr->level_count - 1); i++) {
- MEM_freeN(fmap[i]);
- MEM_freeN(fmem[i]);
- MEM_freeN(emap[i]);
- MEM_freeN(emem[i]);
- }
-
- MEM_freeN(fmap);
- MEM_freeN(emap);
- MEM_freeN(fmem);
- MEM_freeN(emem);
- }
-
- /* Transfer verts */
- for (i = 0; i < totvert; i++) {
- copy_v3_v3(vdst[i].co, vsrc[vvmap[i]].co);
- }
-
- MEM_freeN(vvmap);
-
- multires_mvert_to_ss(dm, vdst);
-}
-
-/* Copy the first-level vcol data to the mesh, if it exists */
-/* Warning: higher-level vcol data will be lost */
-static void multires_load_old_vcols(Mesh *me)
-{
- MultiresLevel *lvl;
- MultiresColFace *colface;
- MCol *mcol;
- int i, j;
-
- if (!(lvl = me->mr->levels.first)) {
- return;
- }
-
- if (!(colface = lvl->colfaces)) {
- return;
- }
-
- /* older multires format never supported multiple vcol layers,
- * so we can assume the active vcol layer is the correct one */
- if (!(mcol = CustomData_get_layer(&me->fdata, CD_MCOL))) {
- return;
- }
-
- for (i = 0; i < me->totface; i++) {
- for (j = 0; j < 4; j++) {
- mcol[i * 4 + j].a = colface[i].col[j].a;
- mcol[i * 4 + j].r = colface[i].col[j].r;
- mcol[i * 4 + j].g = colface[i].col[j].g;
- mcol[i * 4 + j].b = colface[i].col[j].b;
- }
- }
-}
-
-/* Copy the first-level face-flag data to the mesh */
-static void multires_load_old_face_flags(Mesh *me)
-{
- MultiresLevel *lvl;
- MultiresFace *faces;
- int i;
-
- if (!(lvl = me->mr->levels.first)) {
- return;
- }
-
- if (!(faces = lvl->faces)) {
- return;
- }
-
- for (i = 0; i < me->totface; i++) {
- me->mface[i].flag = faces[i].flag;
- }
-}
-
-void multires_load_old(Object *ob, Mesh *me)
-{
- MultiresLevel *lvl;
- ModifierData *md;
- MultiresModifierData *mmd;
- DerivedMesh *dm, *orig;
- CustomDataLayer *l;
- int i;
-
- /* Load original level into the mesh */
- lvl = me->mr->levels.first;
- CustomData_free_layers(&me->vdata, CD_MVERT, lvl->totvert);
- CustomData_free_layers(&me->edata, CD_MEDGE, lvl->totedge);
- CustomData_free_layers(&me->fdata, CD_MFACE, lvl->totface);
- me->totvert = lvl->totvert;
- me->totedge = lvl->totedge;
- me->totface = lvl->totface;
- me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, me->totvert);
- me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, me->totedge);
- me->mface = CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, me->totface);
- memcpy(me->mvert, me->mr->verts, sizeof(MVert) * me->totvert);
- for (i = 0; i < me->totedge; i++) {
- me->medge[i].v1 = lvl->edges[i].v[0];
- me->medge[i].v2 = lvl->edges[i].v[1];
- }
- for (i = 0; i < me->totface; i++) {
- me->mface[i].v1 = lvl->faces[i].v[0];
- me->mface[i].v2 = lvl->faces[i].v[1];
- me->mface[i].v3 = lvl->faces[i].v[2];
- me->mface[i].v4 = lvl->faces[i].v[3];
- me->mface[i].mat_nr = lvl->faces[i].mat_nr;
- }
-
- /* Copy the first-level data to the mesh */
- /* XXX We must do this before converting tessfaces to polys/lopps! */
- for (i = 0, l = me->mr->vdata.layers; i < me->mr->vdata.totlayer; i++, l++) {
- CustomData_add_layer(&me->vdata, l->type, CD_REFERENCE, l->data, me->totvert);
- }
- for (i = 0, l = me->mr->fdata.layers; i < me->mr->fdata.totlayer; i++, l++) {
- CustomData_add_layer(&me->fdata, l->type, CD_REFERENCE, l->data, me->totface);
- }
- CustomData_reset(&me->mr->vdata);
- CustomData_reset(&me->mr->fdata);
-
- multires_load_old_vcols(me);
- multires_load_old_face_flags(me);
-
- /* multiresModifier_subdivide_legacy (actually, multires_subdivide_legacy) expects polys, not
- * tessfaces! */
- BKE_mesh_convert_mfaces_to_mpolys(me);
-
- /* Add a multires modifier to the object */
- md = ob->modifiers.first;
- while (md && BKE_modifier_get_info(md->type)->type == eModifierTypeType_OnlyDeform) {
- md = md->next;
- }
- mmd = (MultiresModifierData *)BKE_modifier_new(eModifierType_Multires);
- BLI_insertlinkbefore(&ob->modifiers, md, mmd);
-
- for (i = 0; i < me->mr->level_count - 1; i++) {
- multiresModifier_subdivide_legacy(mmd, NULL, ob, 1, 0);
- }
-
- mmd->lvl = mmd->totlvl;
- orig = CDDM_from_mesh(me);
- /* XXX We *must* alloc paint mask here, else we have some kind of mismatch in
- * multires_modifier_update_mdisps() (called by dm->release(dm)), which always creates the
- * reference subsurfed dm with this option, before calling multiresModifier_disp_run(),
- * which implicitly expects both subsurfs from its first dm and oldGridData parameters to
- * be of the same "format"! */
- dm = multires_make_derived_from_derived(orig, mmd, NULL, ob, 0);
-
- multires_load_old_dm(dm, me, mmd->totlvl + 1);
-
- multires_dm_mark_as_modified(dm, MULTIRES_COORDS_MODIFIED);
- dm->release(dm);
- orig->release(orig);
-
- /* Remove the old multires */
- multires_free(me->mr);
- me->mr = NULL;
-}
-
/* If 'ob_src' and 'ob_dst' both have multires modifiers, synchronize them
* such that 'ob_dst' has the same total number of levels as 'ob_src'. */
void multiresModifier_sync_levels_ex(Object *ob_dst,
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index 0c9ee61ca19..ae39b200b56 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -1548,8 +1548,8 @@ void BKE_shrinkwrap_remesh_target_project(Mesh *src_me, Mesh *target_me, Object
ssmd.shrinkMode = MOD_SHRINKWRAP_ON_SURFACE;
ssmd.shrinkOpts = MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR | MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR;
ssmd.keepDist = 0.0f;
-
- /* Tolerance value to prevent artifacts on sharp edges of a mesh.
+
+ /* Tolerance value to prevent artifacts on sharp edges of a mesh.
* This constant and based on experimenting with different values. */
const float projLimitTolerance = 5.0f;
ssmd.projLimit = target_me->remesh_voxel_size * projLimitTolerance;
diff --git a/source/blender/blenlib/intern/delaunay_2d.cc b/source/blender/blenlib/intern/delaunay_2d.cc
index ac3662284d0..60439f27b01 100644
--- a/source/blender/blenlib/intern/delaunay_2d.cc
+++ b/source/blender/blenlib/intern/delaunay_2d.cc
@@ -1308,8 +1308,8 @@ template<typename T> inline int tri_orient(const SymEdge<T> *t)
* For case (a), 'vert' will be the vertex, and lambda will be 0, and 'in' will be the #SymEdge
* from 'vert' that has as face the one that you go through to get to this vertex. If you go
* exactly along an edge then we set 'in' to NULL, since it won't be needed. The first crossing
- * will have 'in' = NULL. We set 'out' to the #SymEdge that has the face we go through to get to the
- * next crossing, or, if the next crossing is a case (a), then it is the edge that goes to that
+ * will have 'in' = NULL. We set 'out' to the #SymEdge that has the face we go through to get to
+ * the next crossing, or, if the next crossing is a case (a), then it is the edge that goes to that
* next vertex. 'out' will be NULL for the last one.
*
* For case (b), vert will be NULL at first, and later filled in with the created split vertex,
diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c
index 5046ee6aab1..f7592308023 100644
--- a/source/blender/blenloader/intern/versioning_250.c
+++ b/source/blender/blenloader/intern/versioning_250.c
@@ -799,20 +799,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain)
// BLI_freelistN(&pidlist);
- if (ob->type == OB_MESH) {
- Mesh *me = blo_do_versions_newlibadr(fd, lib, ob->data);
- void *olddata = ob->data;
- ob->data = me;
-
- /* XXX - library meshes crash on loading most yoFrankie levels,
- * the multires pointer gets invalid - Campbell */
- if (me && me->id.lib == NULL && me->mr && me->mr->level_count > 1) {
- multires_load_old(ob, me);
- }
-
- ob->data = olddata;
- }
-
if (ob->totcol && ob->matbits == NULL) {
int a;
@@ -1152,7 +1138,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain)
if (bmain->versionfile == 250 && bmain->subversionfile > 1) {
for (me = bmain->meshes.first; me; me = me->id.next) {
- multires_load_old_250(me);
+ CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface);
}
for (ob = bmain->objects.first; ob; ob = ob->id.next) {
diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c
index 2daa1d48f47..00085cb7d59 100644
--- a/source/blender/blenloader/intern/versioning_290.c
+++ b/source/blender/blenloader/intern/versioning_290.c
@@ -885,18 +885,7 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
- /**
- * Versioning code until next subversion bump goes here.
- *
- * \note Be sure to check when bumping the version:
- * - "versioning_userdef.c", #blo_do_versions_userdef
- * - "versioning_userdef.c", #do_versions_theme
- *
- * \note Keep this message at the bottom of the function.
- */
- {
- /* Keep this block, even when empty. */
-
+ if (!MAIN_VERSION_ATLEAST(bmain, 291, 9)) {
/* Remove options of legacy UV/Image editor */
for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
@@ -925,4 +914,17 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
}
+
+ /**
+ * Versioning code until next subversion bump goes here.
+ *
+ * \note Be sure to check when bumping the version:
+ * - "versioning_userdef.c", #blo_do_versions_userdef
+ * - "versioning_userdef.c", #do_versions_theme
+ *
+ * \note Keep this message at the bottom of the function.
+ */
+ {
+ /* Keep this block, even when empty. */
+ }
}
diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c
index 4acf98cc58b..9d858da266d 100644
--- a/source/blender/blenloader/intern/versioning_legacy.c
+++ b/source/blender/blenloader/intern/versioning_legacy.c
@@ -1959,7 +1959,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain)
Light *la;
Material *ma;
ParticleSettings *part;
- Mesh *me;
bNodeTree *ntree;
Tex *tex;
ModifierData *md;
@@ -2074,23 +2073,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain)
}
}
- /* Copy over old per-level multires vertex data
- * into a single vertex array in struct Multires */
- for (me = bmain->meshes.first; me; me = me->id.next) {
- if (me->mr && !me->mr->verts) {
- MultiresLevel *lvl = me->mr->levels.last;
- if (lvl) {
- me->mr->verts = lvl->verts;
- lvl->verts = NULL;
- /* Don't need the other vert arrays */
- for (lvl = lvl->prev; lvl; lvl = lvl->prev) {
- MEM_freeN(lvl->verts);
- lvl->verts = NULL;
- }
- }
- }
- }
-
if (bmain->versionfile != 245 || bmain->subversionfile < 1) {
for (la = bmain->lights.first; la; la = la->id.next) {
la->falloff_type = LA_FALLOFF_INVLINEAR;
diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c
index e81735c698d..6b6d226bd90 100644
--- a/source/blender/blenloader/intern/versioning_userdef.c
+++ b/source/blender/blenloader/intern/versioning_userdef.c
@@ -242,6 +242,10 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
copy_v3_v3_uchar(btheme->space_node.grid, btheme->space_node.back);
}
+ if (!USER_VERSION_ATLEAST(291, 9)) {
+ FROM_DEFAULT_V4_UCHAR(space_graph.vertex_active);
+ }
+
/**
* Versioning code until next subversion bump goes here.
*
@@ -253,8 +257,6 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
*/
{
/* Keep this block, even when empty. */
-
- FROM_DEFAULT_V4_UCHAR(space_graph.vertex_active);
}
#undef FROM_DEFAULT_V4_UCHAR
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index d5ebc73dc1e..df5e7aadc64 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -2343,60 +2343,60 @@ void bmesh_kernel_vert_separate(
BLI_assert(!BM_ELEM_API_FLAG_TEST(e_iter, EDGE_VISIT));
BM_ELEM_API_FLAG_ENABLE(e_iter, EDGE_VISIT);
} while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
- }
-
- while (true) {
- /* Considering only edges and faces incident on vertex v, walk
- * the edges & collect in the 'edges' list for splitting */
- BMEdge *e = v->e;
- BM_ELEM_API_FLAG_DISABLE(e, EDGE_VISIT);
+ while (true) {
+ /* Considering only edges and faces incident on vertex v, walk
+ * the edges & collect in the 'edges' list for splitting */
- do {
- BLI_assert(!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT));
- BLI_SMALLSTACK_PUSH(edges, e);
- edges_found += 1;
+ BMEdge *e = v->e;
+ BM_ELEM_API_FLAG_DISABLE(e, EDGE_VISIT);
- if (e->l) {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = e->l;
- do {
- BMLoop *l_adjacent = (l_iter->v == v) ? l_iter->prev : l_iter->next;
- BLI_assert(BM_vert_in_edge(l_adjacent->e, v));
- if (BM_ELEM_API_FLAG_TEST(l_adjacent->e, EDGE_VISIT)) {
- BM_ELEM_API_FLAG_DISABLE(l_adjacent->e, EDGE_VISIT);
- BLI_SMALLSTACK_PUSH(edges_search, l_adjacent->e);
- }
- } while ((l_iter = l_iter->radial_next) != l_first);
- }
- } while ((e = BLI_SMALLSTACK_POP(edges_search)));
+ do {
+ BLI_assert(!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT));
+ BLI_SMALLSTACK_PUSH(edges, e);
+ edges_found += 1;
+
+ if (e->l) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = e->l;
+ do {
+ BMLoop *l_adjacent = (l_iter->v == v) ? l_iter->prev : l_iter->next;
+ BLI_assert(BM_vert_in_edge(l_adjacent->e, v));
+ if (BM_ELEM_API_FLAG_TEST(l_adjacent->e, EDGE_VISIT)) {
+ BM_ELEM_API_FLAG_DISABLE(l_adjacent->e, EDGE_VISIT);
+ BLI_SMALLSTACK_PUSH(edges_search, l_adjacent->e);
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+ } while ((e = BLI_SMALLSTACK_POP(edges_search)));
- /* now we have all edges connected to 'v->e' */
+ /* now we have all edges connected to 'v->e' */
- BLI_assert(edges_found <= v_edges_num);
+ BLI_assert(edges_found <= v_edges_num);
- if (edges_found == v_edges_num) {
- /* We're done! The remaining edges in 'edges' form the last fan,
- * which can be left as is.
- * if 'edges' were alloc'd it'd be freed here. */
- break;
- }
+ if (edges_found == v_edges_num) {
+ /* We're done! The remaining edges in 'edges' form the last fan,
+ * which can be left as is.
+ * if 'edges' were alloc'd it'd be freed here. */
+ break;
+ }
- BMVert *v_new;
+ BMVert *v_new;
- v_new = BM_vert_create(bm, v->co, v, BM_CREATE_NOP);
- if (copy_select) {
- BM_elem_select_copy(bm, v_new, v);
- }
+ v_new = BM_vert_create(bm, v->co, v, BM_CREATE_NOP);
+ if (copy_select) {
+ BM_elem_select_copy(bm, v_new, v);
+ }
- while ((e = BLI_SMALLSTACK_POP(edges))) {
- bmesh_edge_vert_swap(e, v_new, v);
- }
+ while ((e = BLI_SMALLSTACK_POP(edges))) {
+ bmesh_edge_vert_swap(e, v_new, v);
+ }
- if (r_vout) {
- BLI_SMALLSTACK_PUSH(verts_new, v_new);
+ if (r_vout) {
+ BLI_SMALLSTACK_PUSH(verts_new, v_new);
+ }
+ verts_num += 1;
}
- verts_num += 1;
}
#undef EDGE_VISIT
diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt
index d524f4a0e1e..54dd121952b 100644
--- a/source/blender/compositor/CMakeLists.txt
+++ b/source/blender/compositor/CMakeLists.txt
@@ -353,6 +353,8 @@ set(SRC
operations/COM_KeyingDespillOperation.h
operations/COM_KeyingOperation.cpp
operations/COM_KeyingOperation.h
+ operations/COM_KeyingSetAlphaOperation.cpp
+ operations/COM_KeyingSetAlphaOperation.h
operations/COM_ColorSpillOperation.cpp
operations/COM_ColorSpillOperation.h
diff --git a/source/blender/compositor/nodes/COM_KeyingNode.cpp b/source/blender/compositor/nodes/COM_KeyingNode.cpp
index b75d06763b7..a0ccaf0b9da 100644
--- a/source/blender/compositor/nodes/COM_KeyingNode.cpp
+++ b/source/blender/compositor/nodes/COM_KeyingNode.cpp
@@ -32,7 +32,7 @@
#include "COM_DilateErodeOperation.h"
-#include "COM_SetAlphaOperation.h"
+#include "COM_KeyingSetAlphaOperation.h"
#include "COM_GaussianAlphaXBlurOperation.h"
#include "COM_GaussianAlphaYBlurOperation.h"
@@ -322,7 +322,7 @@ void KeyingNode::convertToOperations(NodeConverter &converter,
}
/* set alpha channel to output image */
- SetAlphaOperation *alphaOperation = new SetAlphaOperation();
+ KeyingSetAlphaOperation *alphaOperation = new KeyingSetAlphaOperation();
converter.addOperation(alphaOperation);
converter.mapInputSocket(inputImage, alphaOperation->getInputSocket(0));
diff --git a/source/blender/compositor/operations/COM_KeyingSetAlphaOperation.cpp b/source/blender/compositor/operations/COM_KeyingSetAlphaOperation.cpp
new file mode 100644
index 00000000000..dff88d49e80
--- /dev/null
+++ b/source/blender/compositor/operations/COM_KeyingSetAlphaOperation.cpp
@@ -0,0 +1,55 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2020, Blender Foundation.
+ */
+
+#include "COM_KeyingSetAlphaOperation.h"
+
+KeyingSetAlphaOperation::KeyingSetAlphaOperation() : NodeOperation()
+{
+ this->addInputSocket(COM_DT_COLOR);
+ this->addInputSocket(COM_DT_VALUE);
+ this->addOutputSocket(COM_DT_COLOR);
+
+ this->m_inputColor = NULL;
+ this->m_inputAlpha = NULL;
+}
+
+void KeyingSetAlphaOperation::initExecution()
+{
+ this->m_inputColor = getInputSocketReader(0);
+ this->m_inputAlpha = getInputSocketReader(1);
+}
+
+void KeyingSetAlphaOperation::executePixelSampled(float output[4],
+ float x,
+ float y,
+ PixelSampler sampler)
+{
+ float color_input[4];
+ float alpha_input[4];
+
+ this->m_inputColor->readSampled(color_input, x, y, sampler);
+ this->m_inputAlpha->readSampled(alpha_input, x, y, sampler);
+
+ mul_v4_v4fl(output, color_input, alpha_input[0]);
+}
+
+void KeyingSetAlphaOperation::deinitExecution()
+{
+ this->m_inputColor = NULL;
+ this->m_inputAlpha = NULL;
+}
diff --git a/source/blender/compositor/operations/COM_KeyingSetAlphaOperation.h b/source/blender/compositor/operations/COM_KeyingSetAlphaOperation.h
new file mode 100644
index 00000000000..b786240f215
--- /dev/null
+++ b/source/blender/compositor/operations/COM_KeyingSetAlphaOperation.h
@@ -0,0 +1,39 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2020, Blender Foundation.
+ */
+
+#pragma once
+
+#include "COM_NodeOperation.h"
+
+/**
+ * Operation which is used by keying node to modify image's alpha channels.
+ * It keeps color properly pre-multiplied.
+ */
+class KeyingSetAlphaOperation : public NodeOperation {
+ private:
+ SocketReader *m_inputColor;
+ SocketReader *m_inputAlpha;
+
+ public:
+ KeyingSetAlphaOperation();
+
+ void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+
+ void initExecution();
+ void deinitExecution();
+};
diff --git a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl
index cad1346609a..db3497bd043 100644
--- a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl
@@ -105,7 +105,9 @@ void prepare_raycast(vec3 ray_origin,
/* If the line is degenerate, make it cover at least one pixel
* to not have to handle zero-pixel extent as a special case later */
- ss_step.xy += vec2((dot(ss_step.xy, ss_step.xy) < 0.00001) ? 0.001 : 0.0);
+ if (dot(ss_step.xy, ss_step.xy) < 0.00001) {
+ ss_step.xy = vec2(0.0, 0.0001);
+ }
/* Make ss_step cover one pixel. */
ss_step /= max(abs(ss_step.x), abs(ss_step.y));
@@ -173,7 +175,8 @@ vec3 raycast(int index,
float iter;
for (iter = 1.0; !hit && (ray_time < max_time) && (iter < MAX_STEP); iter++) {
/* Minimum stride of 2 because we are using half res minmax zbuffer. */
- float stride = max(1.0, iter * trace_quality) * 2.0;
+ /* WORKAROUND: Factor is a bit higher than 2 to avoid some banding. To investigate. */
+ float stride = max(1.0, iter * trace_quality) * (2.0 + 0.05);
float lod = log2(stride * 0.5 * trace_quality) * lod_fac;
ray_time += stride;
@@ -234,9 +237,10 @@ vec3 raycast(int index,
#endif
}
- if (discard_backface) {
- /* Discard backface hits */
- hit = hit && (prev_delta > 0.0);
+ /* Discard backface hits. Only do this if the ray traveled enough to avoid loosing intricate
+ * contact reflections. This is only used for SSReflections. */
+ if (discard_backface && prev_delta < 0.0 && curr_time > 4.1) {
+ hit = false;
}
/* Reject hit if background. */
diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c
index bcdd0f9e3dc..bd97fd8a413 100644
--- a/source/blender/draw/engines/external/external_engine.c
+++ b/source/blender/draw/engines/external/external_engine.c
@@ -36,6 +36,7 @@
#include "GPU_matrix.h"
#include "GPU_shader.h"
+#include "GPU_state.h"
#include "GPU_viewport.h"
#include "external_engine.h" /* own include */
@@ -243,6 +244,8 @@ static void external_draw_scene_do(void *vedata)
type = rv3d->render_engine->type;
type->view_draw(rv3d->render_engine, draw_ctx->evil_C, draw_ctx->depsgraph);
+ GPU_bgl_end();
+
GPU_matrix_pop();
GPU_matrix_pop_projection();
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 85d86849140..49c75e0b4a1 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -476,19 +476,15 @@ static void keyIndex_switchDirection(EditNurb *editnurb, Nurb *nu)
static void switch_keys_direction(Curve *cu, Nurb *actnu)
{
- KeyBlock *currkey;
EditNurb *editnurb = cu->editnurb;
ListBase *nubase = &editnurb->nurbs;
- Nurb *nu;
float *fp;
int a;
- currkey = cu->key->block.first;
- while (currkey) {
+ LISTBASE_FOREACH (KeyBlock *, currkey, &cu->key->block) {
fp = currkey->data;
- nu = nubase->first;
- while (nu) {
+ LISTBASE_FOREACH (Nurb *, nu, nubase) {
if (nu->bezt) {
BezTriple *bezt = nu->bezt;
a = nu->pntsu;
@@ -522,11 +518,7 @@ static void switch_keys_direction(Curve *cu, Nurb *actnu)
fp += a * KEYELEM_FLOAT_LEN_BPOINT;
}
}
-
- nu = nu->next;
}
-
- currkey = currkey->next;
}
}
@@ -583,13 +575,11 @@ static void bezt_to_key(BezTriple *bezt, float *key)
static void calc_keyHandles(ListBase *nurb, float *key)
{
- Nurb *nu;
int a;
float *fp = key;
BezTriple *bezt;
- nu = nurb->first;
- while (nu) {
+ LISTBASE_FOREACH (Nurb *, nu, nurb) {
if (nu->bezt) {
BezTriple *prevp, *nextp;
BezTriple cur, prev, next;
@@ -649,8 +639,6 @@ static void calc_keyHandles(ListBase *nurb, float *key)
a = nu->pntsu * nu->pntsv;
fp += a * KEYELEM_FLOAT_LEN_BPOINT;
}
-
- nu = nu->next;
}
}
@@ -666,7 +654,7 @@ static void calc_shapeKeys(Object *obedit, ListBase *newnurbs)
KeyBlock *actkey = BLI_findlink(&cu->key->block, editnurb->shapenr - 1);
BezTriple *bezt, *oldbezt;
BPoint *bp, *oldbp;
- Nurb *nu, *newnu;
+ Nurb *newnu;
int totvert = BKE_keyblock_curve_element_count(&editnurb->nurbs);
float(*ofs)[3] = NULL;
@@ -678,8 +666,8 @@ static void calc_shapeKeys(Object *obedit, ListBase *newnurbs)
int totvec = 0;
/* Calculate needed memory to store offset */
- nu = editnurb->nurbs.first;
- while (nu) {
+ LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) {
+
if (nu->bezt) {
/* Three vects to store handles and one for tilt. */
totvec += nu->pntsu * 4;
@@ -687,14 +675,11 @@ static void calc_shapeKeys(Object *obedit, ListBase *newnurbs)
else {
totvec += 2 * nu->pntsu * nu->pntsv;
}
-
- nu = nu->next;
}
ofs = MEM_callocN(sizeof(float[3]) * totvec, "currkey->data");
- nu = editnurb->nurbs.first;
i = 0;
- while (nu) {
+ LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) {
if (nu->bezt) {
bezt = nu->bezt;
a = nu->pntsu;
@@ -731,8 +716,6 @@ static void calc_shapeKeys(Object *obedit, ListBase *newnurbs)
bp++;
}
}
-
- nu = nu->next;
}
}
}
@@ -745,7 +728,7 @@ static void calc_shapeKeys(Object *obedit, ListBase *newnurbs)
float *fp = newkey = MEM_callocN(cu->key->elemsize * totvert, "currkey->data");
ofp = oldkey = currkey->data;
- nu = editnurb->nurbs.first;
+ Nurb *nu = editnurb->nurbs.first;
/* We need to restore to original curve into newnurb, *not* editcurve's nurbs.
* Otherwise, in case we update obdata *without* leaving editmode (e.g. viewport render),
* we would invalidate editcurve. */
@@ -929,11 +912,10 @@ static void fcurve_path_rename(AnimData *adt,
ListBase *orig_curves,
ListBase *curves)
{
- FCurve *fcu, *nfcu, *nextfcu;
+ FCurve *nfcu;
int len = strlen(orig_rna_path);
- for (fcu = orig_curves->first; fcu; fcu = nextfcu) {
- nextfcu = fcu->next;
+ LISTBASE_FOREACH_MUTABLE (FCurve *, fcu, orig_curves) {
if (STREQLEN(fcu->rna_path, orig_rna_path, len)) {
char *spath, *suffix = fcu->rna_path + len;
nfcu = BKE_fcurve_copy(fcu);
@@ -977,16 +959,15 @@ static void fcurve_remove(AnimData *adt, ListBase *orig_curves, FCurve *fcu)
static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves)
{
- int nu_index = 0, a, pt_index;
+ int a, pt_index;
EditNurb *editnurb = cu->editnurb;
- Nurb *nu;
CVKeyIndex *keyIndex;
char rna_path[64], orig_rna_path[64];
AnimData *adt = BKE_animdata_from_id(&cu->id);
ListBase curves = {NULL, NULL};
- FCurve *fcu, *next;
- for (nu = editnurb->nurbs.first, nu_index = 0; nu != NULL; nu = nu->next, nu_index++) {
+ int nu_index = 0;
+ LISTBASE_FOREACH_INDEX (Nurb *, nu, &editnurb->nurbs, nu_index) {
if (nu->bezt) {
BezTriple *bezt = nu->bezt;
a = nu->pntsu;
@@ -1054,9 +1035,7 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves)
/* remove paths for removed control points
* need this to make further step with copying non-cv related curves copying
* not touching cv's f-curves */
- for (fcu = orig_curves->first; fcu; fcu = next) {
- next = fcu->next;
-
+ LISTBASE_FOREACH_MUTABLE (FCurve *, fcu, orig_curves) {
if (STREQLEN(fcu->rna_path, "splines", 7)) {
const char *ch = strchr(fcu->rna_path, '.');
@@ -1066,7 +1045,8 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves)
}
}
- for (nu = editnurb->nurbs.first, nu_index = 0; nu != NULL; nu = nu->next, nu_index++) {
+ nu_index = 0;
+ LISTBASE_FOREACH_INDEX (Nurb *, nu, &editnurb->nurbs, nu_index) {
keyIndex = NULL;
if (nu->pntsu) {
if (nu->bezt) {
@@ -1086,9 +1066,7 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves)
/* the remainders in orig_curves can be copied back (like follow path) */
/* (if it's not path to spline) */
- for (fcu = orig_curves->first; fcu; fcu = next) {
- next = fcu->next;
-
+ LISTBASE_FOREACH_MUTABLE (FCurve *, fcu, orig_curves) {
if (STREQLEN(fcu->rna_path, "splines", 7)) {
fcurve_remove(adt, orig_curves, fcu);
}
@@ -1141,13 +1119,11 @@ static int *init_index_map(Object *obedit, int *r_old_totvert)
{
Curve *curve = (Curve *)obedit->data;
EditNurb *editnurb = curve->editnurb;
- Nurb *nu;
CVKeyIndex *keyIndex;
int *old_to_new_map;
- int old_totvert;
- int vertex_index;
- for (nu = curve->nurb.first, old_totvert = 0; nu != NULL; nu = nu->next) {
+ int old_totvert = 0;
+ LISTBASE_FOREACH (Nurb *, nu, &curve->nurb) {
if (nu->bezt) {
old_totvert += nu->pntsu * 3;
}
@@ -1161,7 +1137,8 @@ static int *init_index_map(Object *obedit, int *r_old_totvert)
old_to_new_map[i] = -1;
}
- for (nu = editnurb->nurbs.first, vertex_index = 0; nu != NULL; nu = nu->next) {
+ int vertex_index = 0;
+ LISTBASE_FOREACH (Nurb *, nu, &curve->nurb) {
if (nu->bezt) {
BezTriple *bezt = nu->bezt;
int a = nu->pntsu;
@@ -1205,7 +1182,6 @@ static int *init_index_map(Object *obedit, int *r_old_totvert)
static void remap_hooks_and_vertex_parents(Main *bmain, Object *obedit)
{
- Object *object;
Curve *curve = (Curve *)obedit->data;
EditNurb *editnurb = curve->editnurb;
int *old_to_new_map = NULL;
@@ -1219,8 +1195,7 @@ static void remap_hooks_and_vertex_parents(Main *bmain, Object *obedit)
return;
}
- for (object = bmain->objects.first; object; object = object->id.next) {
- ModifierData *md;
+ LISTBASE_FOREACH (Object *, object, &bmain->objects) {
int index;
if ((object->parent) && (object->parent->data == curve) &&
ELEM(object->partype, PARVERT1, PARVERT3)) {
@@ -1248,7 +1223,7 @@ static void remap_hooks_and_vertex_parents(Main *bmain, Object *obedit)
}
}
if (object->data == curve) {
- for (md = object->modifiers.first; md; md = md->next) {
+ LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
if (md->type == eModifierType_Hook) {
HookModifierData *hmd = (HookModifierData *)md;
int i, j;
@@ -1290,13 +1265,12 @@ void ED_curve_editnurb_load(Main *bmain, Object *obedit)
if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
Curve *cu = obedit->data;
- Nurb *nu, *newnu;
ListBase newnurb = {NULL, NULL}, oldnurb = cu->nurb;
remap_hooks_and_vertex_parents(bmain, obedit);
- for (nu = editnurb->first; nu; nu = nu->next) {
- newnu = BKE_nurb_duplicate(nu);
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
+ Nurb *newnu = BKE_nurb_duplicate(nu);
BLI_addtail(&newnurb, newnu);
if (nu->type == CU_NURBS) {
@@ -1323,7 +1297,6 @@ void ED_curve_editnurb_make(Object *obedit)
{
Curve *cu = (Curve *)obedit->data;
EditNurb *editnurb = cu->editnurb;
- Nurb *nu, *newnu;
KeyBlock *actkey;
if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
@@ -1346,12 +1319,10 @@ void ED_curve_editnurb_make(Object *obedit)
cu->editnurb = editnurb;
}
- nu = cu->nurb.first;
- while (nu) {
- newnu = BKE_nurb_duplicate(nu);
+ LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
+ Nurb *newnu = BKE_nurb_duplicate(nu);
BKE_nurb_test_2d(newnu); /* after join, or any other creation of curve */
BLI_addtail(&editnurb->nurbs, newnu);
- nu = nu->next;
}
/* animation could be added in editmode even if there was no animdata in
@@ -1722,11 +1693,10 @@ static void rotateflagNurb(ListBase *editnurb,
const float rotmat[3][3])
{
/* all verts with (flag & 'flag') rotate */
- Nurb *nu;
BPoint *bp;
int a;
- for (nu = editnurb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
if (nu->type == CU_NURBS) {
bp = nu->bp;
a = nu->pntsu * nu->pntsv;
@@ -1746,12 +1716,11 @@ static void rotateflagNurb(ListBase *editnurb,
void ed_editnurb_translate_flag(ListBase *editnurb, uint8_t flag, const float vec[3])
{
/* all verts with ('flag' & flag) translate */
- Nurb *nu;
BezTriple *bezt;
BPoint *bp;
int a;
- for (nu = editnurb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
if (nu->type == CU_BEZIER) {
a = nu->pntsu;
bezt = nu->bezt;
@@ -1785,11 +1754,10 @@ void ed_editnurb_translate_flag(ListBase *editnurb, uint8_t flag, const float ve
static void weightflagNurb(ListBase *editnurb, short flag, float w)
{
- Nurb *nu;
BPoint *bp;
int a;
- for (nu = editnurb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
if (nu->type == CU_NURBS) {
a = nu->pntsu * nu->pntsv;
bp = nu->bp;
@@ -1808,16 +1776,12 @@ static void ed_surf_delete_selected(Object *obedit)
{
Curve *cu = obedit->data;
ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu, *next;
BPoint *bp, *bpn, *newbp;
int a, b, newu, newv;
BLI_assert(obedit->type == OB_SURF);
- nu = editnurb->first;
- while (nu) {
- next = nu->next;
-
+ LISTBASE_FOREACH_MUTABLE (Nurb *, nu, editnurb) {
/* is entire nurb selected */
bp = nu->bp;
a = nu->pntsu * nu->pntsv;
@@ -1903,7 +1867,6 @@ static void ed_surf_delete_selected(Object *obedit)
}
}
}
- nu = next;
}
}
@@ -1912,15 +1875,12 @@ static void ed_curve_delete_selected(Object *obedit, View3D *v3d)
Curve *cu = obedit->data;
EditNurb *editnurb = cu->editnurb;
ListBase *nubase = &editnurb->nurbs;
- Nurb *nu, *next;
BezTriple *bezt, *bezt1;
BPoint *bp, *bp1;
int a, type, nuindex = 0;
/* first loop, can we remove entire pieces? */
- nu = nubase->first;
- while (nu) {
- next = nu->next;
+ LISTBASE_FOREACH_MUTABLE (Nurb *, nu, nubase) {
if (nu->type == CU_BEZIER) {
bezt = nu->bezt;
a = nu->pntsu;
@@ -1981,13 +1941,10 @@ static void ed_curve_delete_selected(Object *obedit, View3D *v3d)
clamp_nurb_order_u(nu);
}
#endif
- nu = next;
nuindex++;
}
/* 2nd loop, delete small pieces: just for curves */
- nu = nubase->first;
- while (nu) {
- next = nu->next;
+ LISTBASE_FOREACH_MUTABLE (Nurb *, nu, nubase) {
type = 0;
if (nu->type == CU_BEZIER) {
bezt = nu->bezt;
@@ -2047,21 +2004,17 @@ static void ed_curve_delete_selected(Object *obedit, View3D *v3d)
BKE_nurb_order_clamp_u(nu);
BKE_nurb_knot_calc_u(nu);
}
- nu = next;
}
}
/* only for OB_SURF */
bool ed_editnurb_extrude_flag(EditNurb *editnurb, const uint8_t flag)
{
- Nurb *nu;
BPoint *bp, *bpn, *newbp;
int a, u, v, len;
bool ok = false;
- nu = editnurb->nurbs.first;
- while (nu) {
-
+ LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) {
if (nu->pntsv == 1) {
bp = nu->bp;
a = nu->pntsu;
@@ -2166,7 +2119,6 @@ bool ed_editnurb_extrude_flag(EditNurb *editnurb, const uint8_t flag)
}
}
}
- nu = nu->next;
}
return ok;
@@ -2197,14 +2149,15 @@ static void adduplicateflagNurb(
Object *obedit, View3D *v3d, ListBase *newnurb, const uint8_t flag, const bool split)
{
ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu, *newnu;
+ Nurb *newnu;
BezTriple *bezt, *bezt1;
BPoint *bp, *bp1, *bp2, *bp3;
Curve *cu = (Curve *)obedit->data;
- int a, b, c, starta, enda, diffa, cyclicu, cyclicv, newu, newv, i;
+ int a, b, c, starta, enda, diffa, cyclicu, cyclicv, newu, newv;
char *usel;
- for (i = 0, nu = editnurb->first; nu; i++, nu = nu->next) {
+ int i = 0;
+ LISTBASE_FOREACH_INDEX (Nurb *, nu, editnurb, i) {
cyclicu = cyclicv = 0;
if (nu->type == CU_BEZIER) {
for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
@@ -2569,7 +2522,7 @@ static void adduplicateflagNurb(
}
if (BLI_listbase_is_empty(newnurb) == false) {
- for (nu = newnurb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, newnurb) {
if (nu->type == CU_BEZIER) {
if (split) {
/* recalc first and last */
@@ -2619,10 +2572,9 @@ static int switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
}
EditNurb *editnurb = cu->editnurb;
- Nurb *nu;
- int i;
- for (nu = editnurb->nurbs.first, i = 0; nu; nu = nu->next, i++) {
+ int i = 0;
+ LISTBASE_FOREACH_INDEX (Nurb *, nu, &editnurb->nurbs, i) {
if (ED_curve_nurb_select_check(v3d, nu)) {
BKE_nurb_direction_switch(nu);
keyData_switchDirectionNurb(cu, nu);
@@ -2674,13 +2626,12 @@ static int set_goal_weight_exec(bContext *C, wmOperator *op)
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
BezTriple *bezt;
BPoint *bp;
float weight = RNA_float_get(op->ptr, "weight");
int a;
- for (nu = editnurb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
if (nu->bezt) {
for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) {
if (bezt->f2 & SELECT) {
@@ -2741,13 +2692,12 @@ static int set_radius_exec(bContext *C, wmOperator *op)
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
BezTriple *bezt;
BPoint *bp;
float radius = RNA_float_get(op->ptr, "radius");
int a;
- for (nu = editnurb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
if (nu->bezt) {
for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) {
if (bezt->f2 & SELECT) {
@@ -2853,12 +2803,11 @@ static int smooth_exec(bContext *C, wmOperator *UNUSED(op))
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
int a, a_end;
bool changed = false;
- for (nu = editnurb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
if (nu->bezt) {
/* duplicate the curve to use in weight calculation */
const BezTriple *bezt_orig = MEM_dupallocN(nu->bezt);
@@ -2960,7 +2909,6 @@ void CURVE_OT_smooth(wmOperatorType *ot)
static void curve_smooth_value(ListBase *editnurb, const int bezt_offsetof, const int bp_offset)
{
- Nurb *nu;
BezTriple *bezt;
BPoint *bp;
int a;
@@ -2970,7 +2918,7 @@ static void curve_smooth_value(ListBase *editnurb, const int bezt_offsetof, cons
int start_sel, end_sel; /* selection indices, inclusive */
float start_rad, end_rad, fac, range;
- for (nu = editnurb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
if (nu->bezt) {
#define BEZT_VALUE(bezt) (*((float *)((char *)(bezt) + bezt_offsetof)))
@@ -3289,12 +3237,11 @@ static int hide_exec(bContext *C, wmOperator *op)
}
ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
BPoint *bp;
BezTriple *bezt;
int a, sel;
- for (nu = editnurb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
if (nu->type == CU_BEZIER) {
bezt = nu->bezt;
a = nu->pntsu;
@@ -3385,13 +3332,12 @@ static int reveal_exec(bContext *C, wmOperator *op)
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
BPoint *bp;
BezTriple *bezt;
int a;
bool changed = false;
- for (nu = editnurb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
nu->hide = 0;
if (nu->type == CU_BEZIER) {
bezt = nu->bezt;
@@ -3462,7 +3408,6 @@ static void subdividenurb(Object *obedit, View3D *v3d, int number_cuts)
{
Curve *cu = obedit->data;
EditNurb *editnurb = cu->editnurb;
- Nurb *nu;
BezTriple *bezt, *beztnew, *beztn;
BPoint *bp, *prevbp, *bpnew, *bpn;
float vec[15];
@@ -3471,7 +3416,7 @@ static void subdividenurb(Object *obedit, View3D *v3d, int number_cuts)
// printf("*** subdivideNurb: entering subdivide\n");
- for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) {
amount = 0;
if (nu->type == CU_BEZIER) {
BezTriple *nextbezt;
@@ -3925,7 +3870,6 @@ static int set_spline_type_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
View3D *v3d = CTX_wm_view3d(C);
ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
bool changed = false;
bool changed_size = false;
const bool use_handles = RNA_boolean_get(op->ptr, "use_handles");
@@ -3936,7 +3880,7 @@ static int set_spline_type_exec(bContext *C, wmOperator *op)
continue;
}
- for (nu = editnurb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
if (ED_curve_nurb_select_check(v3d, nu)) {
const int pntsu_prev = nu->pntsu;
const char *err_msg = NULL;
@@ -4225,12 +4169,11 @@ static void make_selection_list_nurb(View3D *v3d, ListBase *editnurb, ListBase *
{
ListBase nbase = {NULL, NULL};
NurbSort *nus, *nustest, *headdo, *taildo;
- Nurb *nu;
BPoint *bp;
float dist, headdist, taildist;
int a;
- for (nu = editnurb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
if (ED_curve_nurb_select_check(v3d, nu)) {
nus = (NurbSort *)MEM_callocN(sizeof(NurbSort), "sort");
@@ -4996,7 +4939,6 @@ bool ed_editnurb_spin(
{
Curve *cu = (Curve *)obedit->data;
ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
float cmat[3][3], tmat[3][3], imat[3][3];
float bmat[3][3], rotmat[3][3], scalemat1[3][3], scalemat2[3][3];
float persmat[3][3], persinv[3][3];
@@ -5056,7 +4998,7 @@ bool ed_editnurb_spin(
}
if (ok) {
- for (nu = editnurb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
if (ED_curve_nurb_select_check(v3d, nu)) {
nu->orderv = 4;
nu->flagv |= CU_NURB_CYCLIC;
@@ -5427,8 +5369,6 @@ static int ed_editcurve_addvert(Curve *cu,
View3D *v3d,
const float location_init[3])
{
- Nurb *nu;
-
float center[3];
float temp[3];
uint verts_len;
@@ -5437,7 +5377,7 @@ static int ed_editcurve_addvert(Curve *cu,
zero_v3(center);
verts_len = 0;
- for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) {
int i;
if (nu->type == CU_BEZIER) {
BezTriple *bezt;
@@ -5472,7 +5412,7 @@ static int ed_editcurve_addvert(Curve *cu,
ofs[2] = 0.0f;
}
- for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) {
if (nu->type == CU_BEZIER) {
BezTriple *bezt;
for (i = 0, bezt = nu->bezt; i < nu->pntsu; i++, bezt++) {
@@ -5511,7 +5451,7 @@ static int ed_editcurve_addvert(Curve *cu,
}
/* nothing selected: create a new curve */
- nu = BKE_curve_nurb_active_get(cu);
+ Nurb *nu = BKE_curve_nurb_active_get(cu);
if (!nu || nu->type == CU_BEZIER) {
Nurb *nurb_new;
@@ -5764,8 +5704,7 @@ static int curve_extrude_exec(bContext *C, wmOperator *UNUSED(op))
/* First test: curve? */
if (obedit->type != OB_CURVE) {
- Nurb *nu;
- for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) {
if ((nu->pntsv == 1) && (ED_curve_nurb_select_count(v3d, nu) == 1)) {
as_curve = true;
break;
@@ -5819,13 +5758,12 @@ void CURVE_OT_extrude(wmOperatorType *ot)
static bool curve_toggle_cyclic(View3D *v3d, ListBase *editnurb, int direction)
{
- Nurb *nu;
BezTriple *bezt;
BPoint *bp;
int a;
bool changed = false;
- for (nu = editnurb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
if (nu->pntsu > 1 || nu->pntsv > 1) {
if (nu->type == CU_POLY) {
a = nu->pntsu;
@@ -5932,10 +5870,9 @@ static int toggle_cyclic_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS
ListBase *editnurb = object_editcurve_get(obedit);
uiPopupMenu *pup;
uiLayout *layout;
- Nurb *nu;
if (obedit->type == OB_SURF) {
- for (nu = editnurb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
if (nu->pntsu > 1 || nu->pntsv > 1) {
if (nu->type == CU_NURBS) {
pup = UI_popup_menu_begin(C, IFACE_("Direction"), ICON_NONE);
@@ -6064,12 +6001,12 @@ static bool curve_delete_segments(Object *obedit, View3D *v3d, const bool split)
Curve *cu = obedit->data;
EditNurb *editnurb = cu->editnurb;
ListBase *nubase = &editnurb->nurbs, newnurb = {NULL, NULL};
- Nurb *nu, *nu1;
+ Nurb *nu1;
BezTriple *bezt, *bezt1, *bezt2;
BPoint *bp, *bp1, *bp2;
int a, b, starta, enda, cut, cyclicut;
- for (nu = nubase->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, nubase) {
nu1 = NULL;
starta = enda = cut = -1;
cyclicut = 0;
@@ -6452,7 +6389,7 @@ static bool curve_delete_segments(Object *obedit, View3D *v3d, const bool split)
}
}
- for (nu = newnurb.first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, &newnurb) {
if (nu->type == CU_BEZIER) {
if (split) {
/* deselect for split operator */
@@ -6620,9 +6557,8 @@ static int curve_dissolve_exec(bContext *C, wmOperator *UNUSED(op))
}
ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- for (nu = editnurb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
if ((nu->type == CU_BEZIER) && (nu->pntsu > 2)) {
uint span_step[2] = {nu->pntsu, nu->pntsu};
uint span_len;
@@ -6766,9 +6702,8 @@ static int curve_decimate_exec(bContext *C, wmOperator *op)
{
ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- for (nu = editnurb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
if (nu->type == CU_BEZIER) {
if ((nu->pntsu > 2) && nurb_bezt_flag_any(nu, SELECT)) {
const int error_target_len = max_ii(2, nu->pntsu * ratio);
@@ -6917,7 +6852,6 @@ int ED_curve_join_objects_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Object *ob_active = CTX_data_active_object(C);
Curve *cu;
- Nurb *nu, *newnu;
BezTriple *bezt;
BPoint *bp;
ListBase tempbase;
@@ -6955,9 +6889,8 @@ int ED_curve_join_objects_exec(bContext *C, wmOperator *op)
/* watch it: switch order here really goes wrong */
mul_m4_m4m4(cmat, imat, ob_iter->obmat);
- nu = cu->nurb.first;
- while (nu) {
- newnu = BKE_nurb_duplicate(nu);
+ LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
+ Nurb *newnu = BKE_nurb_duplicate(nu);
if (ob_active->totcol) { /* TODO, merge material lists */
CLAMP(newnu->mat_nr, 0, ob_active->totcol - 1);
}
@@ -6983,7 +6916,6 @@ int ED_curve_join_objects_exec(bContext *C, wmOperator *op)
bp++;
}
}
- nu = nu->next;
}
}
@@ -7035,12 +6967,11 @@ static int clear_tilt_exec(bContext *C, wmOperator *UNUSED(op))
}
ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
BezTriple *bezt;
BPoint *bp;
int a;
- for (nu = editnurb->first; nu; nu = nu->next) {
+ LISTBASE_FOREACH (Nurb *, nu, editnurb) {
if (nu->bezt) {
bezt = nu->bezt;
a = nu->pntsu;
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index d54bdf552eb..7d79e748f75 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -4678,7 +4678,9 @@ typedef bool (*GPencilTestFn)(bGPDstroke *gps,
const float diff_mat[4][4],
void *user_data);
-static void gpencil_cutter_dissolve(bGPDlayer *hit_layer, bGPDstroke *hit_stroke)
+static void gpencil_cutter_dissolve(bGPDlayer *hit_layer,
+ bGPDstroke *hit_stroke,
+ const bool flat_caps)
{
bGPDspoint *pt = NULL;
bGPDspoint *pt1 = NULL;
@@ -4722,6 +4724,17 @@ static void gpencil_cutter_dissolve(bGPDlayer *hit_layer, bGPDstroke *hit_stroke
pt->flag &= ~GP_SPOINT_TAG;
}
}
+ /* If flat caps mode check extremes. */
+ if (flat_caps) {
+ if (hit_stroke->points[0].flag & GP_SPOINT_TAG) {
+ hit_stroke->caps[0] = GP_STROKE_CAP_FLAT;
+ }
+
+ if (hit_stroke->points[hit_stroke->totpoints - 1].flag & GP_SPOINT_TAG) {
+ hit_stroke->caps[1] = GP_STROKE_CAP_FLAT;
+ }
+ }
+
gpencil_stroke_delete_tagged_points(
hit_layer->actframe, hit_stroke, gpsn, GP_SPOINT_TAG, false, 1);
}
@@ -4736,6 +4749,7 @@ static int gpencil_cutter_lasso_select(bContext *C,
ScrArea *area = CTX_wm_area(C);
ToolSettings *ts = CTX_data_tool_settings(C);
const float scale = ts->gp_sculpt.isect_threshold;
+ const bool flat_caps = RNA_boolean_get(op->ptr, "flat_caps");
bGPDspoint *pt;
GP_SpaceConversion gsc = {NULL};
@@ -4810,7 +4824,7 @@ static int gpencil_cutter_lasso_select(bContext *C,
}
LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
if (gps->flag & GP_STROKE_SELECT) {
- gpencil_cutter_dissolve(gpl, gps);
+ gpencil_cutter_dissolve(gpl, gps, flat_caps);
}
}
}
@@ -4884,6 +4898,8 @@ void GPENCIL_OT_stroke_cutter(wmOperatorType *ot)
/* properties */
WM_operator_properties_gesture_lasso(ot);
+
+ RNA_def_boolean(ot->srna, "flat_caps", 0, "Flat Caps", "");
}
bool ED_object_gpencil_exit(struct Main *bmain, Object *ob)
diff --git a/source/blender/editors/gpencil/gpencil_mesh.c b/source/blender/editors/gpencil/gpencil_mesh.c
index e4862617d12..7cf4325d03b 100644
--- a/source/blender/editors/gpencil/gpencil_mesh.c
+++ b/source/blender/editors/gpencil/gpencil_mesh.c
@@ -25,12 +25,15 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
#include "BLI_math.h"
+#include "DNA_anim_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
+#include "BKE_anim_data.h"
#include "BKE_context.h"
#include "BKE_duplilist.h"
#include "BKE_global.h"
@@ -86,6 +89,35 @@ typedef struct GpBakeOb {
Object *ob;
} GpBakeOb;
+/* Get list of keyframes used by selected objects. */
+static void animdata_keyframe_list_get(ListBase *ob_list,
+ const bool only_selected,
+ GHash *r_keyframes)
+{
+ /* Loop all objects to get the list of keyframes used. */
+ LISTBASE_FOREACH (GpBakeOb *, elem, ob_list) {
+ Object *ob = elem->ob;
+ AnimData *adt = BKE_animdata_from_id(&ob->id);
+ if ((adt == NULL) || (adt->action == NULL)) {
+ continue;
+ }
+ LISTBASE_FOREACH (FCurve *, fcurve, &adt->action->curves) {
+ int i;
+ BezTriple *bezt;
+ for (i = 0, bezt = fcurve->bezt; i < fcurve->totvert; i++, bezt++) {
+ /* Keyframe number is x value of point. */
+ if ((bezt->f2 & SELECT) || (!only_selected)) {
+ /* Insert only one key for each keyframe number. */
+ int key = (int)bezt->vec[1][0];
+ if (!BLI_ghash_haskey(r_keyframes, POINTER_FROM_INT(key))) {
+ BLI_ghash_insert(r_keyframes, POINTER_FROM_INT(key), POINTER_FROM_INT(key));
+ }
+ }
+ }
+ }
+ }
+}
+
static void gpencil_bake_duplilist(Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *list)
{
GpBakeOb *elem = NULL;
@@ -161,13 +193,13 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
View3D *v3d = CTX_wm_view3d(C);
Object *ob_gpencil = NULL;
- ListBase list = {NULL, NULL};
- gpencil_bake_ob_list(C, depsgraph, scene, &list);
+ ListBase ob_selected_list = {NULL, NULL};
+ gpencil_bake_ob_list(C, depsgraph, scene, &ob_selected_list);
/* Cannot check this in poll because the active object changes. */
- if (list.first == NULL) {
+ if (ob_selected_list.first == NULL) {
BKE_report(op->reports, RPT_INFO, "No valid object selected");
- gpencil_bake_free_ob_list(&list);
+ gpencil_bake_free_ob_list(&ob_selected_list);
return OPERATOR_CANCELLED;
}
@@ -186,6 +218,7 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
const int thickness = RNA_int_get(op->ptr, "thickness");
const bool use_seams = RNA_boolean_get(op->ptr, "seams");
const bool use_faces = RNA_boolean_get(op->ptr, "faces");
+ const bool only_selected = RNA_boolean_get(op->ptr, "only_selected");
const float offset = RNA_float_get(op->ptr, "offset");
const int frame_offset = RNA_int_get(op->ptr, "frame_target") - frame_start;
char target[64];
@@ -206,7 +239,7 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
if ((ob_gpencil == NULL) || (ob_gpencil->type != OB_GPENCIL)) {
BKE_report(op->reports, RPT_ERROR, "Target grease pencil object not valid");
- gpencil_bake_free_ob_list(&list);
+ gpencil_bake_free_ob_list(&ob_selected_list);
return OPERATOR_CANCELLED;
}
@@ -237,6 +270,13 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
/* Loop all frame range. */
int oldframe = (int)DEG_get_ctime(depsgraph);
int key = -1;
+
+ /* Get list of keyframes. */
+ GHash *keyframe_list = BLI_ghash_int_new(__func__);
+ if (only_selected) {
+ animdata_keyframe_list_get(&ob_selected_list, only_selected, keyframe_list);
+ }
+
for (int i = frame_start; i < frame_end + 1; i++) {
key++;
/* Jump if not step limit but include last frame always. */
@@ -244,12 +284,17 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
continue;
}
+ /* Check if frame is in the list of frames to be exported. */
+ if ((only_selected) && (!BLI_ghash_haskey(keyframe_list, POINTER_FROM_INT(i)))) {
+ continue;
+ }
+
/* Move scene to new frame. */
CFRA = i;
BKE_scene_graph_update_for_newframe(depsgraph);
/* Loop all objects in the list. */
- LISTBASE_FOREACH (GpBakeOb *, elem, &list) {
+ LISTBASE_FOREACH (GpBakeOb *, elem, &ob_selected_list) {
Object *ob_eval = (Object *)DEG_get_evaluated_object(depsgraph, elem->ob);
/* Generate strokes. */
@@ -270,13 +315,14 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
if (project_type != GP_REPROJECT_KEEP) {
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
bGPDframe *gpf = gpl->actframe;
- if (gpf != NULL) {
- LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
- if ((gps->flag & GP_STROKE_TAG) == 0) {
- ED_gpencil_stroke_reproject(
- depsgraph, &gsc, sctx, gpl, gpf, gps, project_type, false);
- gps->flag |= GP_STROKE_TAG;
- }
+ if (gpf == NULL) {
+ continue;
+ }
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ if ((gps->flag & GP_STROKE_TAG) == 0) {
+ ED_gpencil_stroke_reproject(
+ depsgraph, &gsc, sctx, gpl, gpf, gps, project_type, false);
+ gps->flag |= GP_STROKE_TAG;
}
}
}
@@ -314,10 +360,14 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
}
/* Free memory. */
- gpencil_bake_free_ob_list(&list);
+ gpencil_bake_free_ob_list(&ob_selected_list);
if (sctx != NULL) {
ED_transform_snap_object_context_destroy(sctx);
}
+ /* Free temp hash table. */
+ if (keyframe_list != NULL) {
+ BLI_ghash_free(keyframe_list, NULL, NULL);
+ }
/* notifiers */
if (newob) {
@@ -394,6 +444,8 @@ void GPENCIL_OT_bake_mesh_animation(wmOperatorType *ot)
RNA_def_int(ot->srna, "thickness", 1, 1, 100, "Thickness", "", 1, 100);
RNA_def_boolean(ot->srna, "seams", 0, "Only Seam Edges", "Convert only seam edges");
RNA_def_boolean(ot->srna, "faces", 1, "Export Faces", "Export faces as filled strokes");
+ RNA_def_boolean(
+ ot->srna, "only_selected", 0, "Only Selected Keyframes", "Convert only selected keyframes");
RNA_def_float_distance(
ot->srna, "offset", 0.001f, 0.0, 100.0, "Offset", "Offset strokes from fill", 0.0, 100.00);
RNA_def_int(ot->srna, "frame_target", 1, 1, 100000, "Frame Target", "", 1, 100000);
diff --git a/source/blender/editors/gpencil/gpencil_trace_utils.c b/source/blender/editors/gpencil/gpencil_trace_utils.c
index 05973afe80c..544cb4fef1e 100644
--- a/source/blender/editors/gpencil/gpencil_trace_utils.c
+++ b/source/blender/editors/gpencil/gpencil_trace_utils.c
@@ -294,7 +294,7 @@ void ED_gpencil_trace_data_to_strokes(Main *bmain,
n = path->curve.n;
tag = path->curve.tag;
c = path->curve.c;
- int mat_idx = path->sign == '+' ? 0 : 1;
+ int mat_idx = path->sign == '+' ? mat_fill_idx : mat_mask_idx;
/* Create a new stroke. */
bGPDstroke *gps = BKE_gpencil_stroke_add(gpf, mat_idx, 0, thickness, false);
/* Last point that is equals to start point. */
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index 5a45afe9c5a..28a90a26a9d 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -2916,6 +2916,40 @@ void ED_gpencil_sbuffer_vertex_color_set(Depsgraph *depsgraph,
}
}
+/* Helper to get the bigger 2D bound box points. */
+static void gpencil_projected_2d_bound_box(GP_SpaceConversion *gsc,
+ bGPDstroke *gps,
+ const float diff_mat[4][4],
+ float r_min[2],
+ float r_max[2])
+{
+ float bounds[8][2];
+ BoundBox bb;
+ BKE_boundbox_init_from_minmax(&bb, gps->boundbox_min, gps->boundbox_max);
+
+ /* Project 8 vertices in 2D. */
+ for (int i = 0; i < 8; i++) {
+ bGPDspoint pt_dummy, pt_dummy_ps;
+ copy_v3_v3(&pt_dummy.x, bb.vec[i]);
+ gpencil_point_to_parent_space(&pt_dummy, diff_mat, &pt_dummy_ps);
+ gpencil_point_to_xy_fl(gsc, gps, &pt_dummy_ps, &bounds[i][0], &bounds[i][1]);
+ }
+
+ /* Take extremes. */
+ INIT_MINMAX2(r_min, r_max);
+ for (int i = 0; i < 8; i++) {
+ minmax_v2v2_v2(r_min, r_max, bounds[i]);
+ }
+
+ /* Ensure the bounding box is oriented to axis. */
+ if (r_max[0] < r_min[0]) {
+ SWAP(float, r_min[0], r_max[0]);
+ }
+ if (r_max[1] < r_min[1]) {
+ SWAP(float, r_min[1], r_max[1]);
+ }
+}
+
/* Check if the stroke collides with brush. */
bool ED_gpencil_stroke_check_collision(GP_SpaceConversion *gsc,
bGPDstroke *gps,
@@ -2924,31 +2958,15 @@ bool ED_gpencil_stroke_check_collision(GP_SpaceConversion *gsc,
const float diff_mat[4][4])
{
const int offset = (int)ceil(sqrt((radius * radius) * 2));
- bGPDspoint pt_dummy, pt_dummy_ps;
- float boundbox_min[2] = {0.0f};
- float boundbox_max[2] = {0.0f};
+ float boundbox_min[2];
+ float boundbox_max[2];
/* Check we have something to use (only for old files). */
if (is_zero_v3(gps->boundbox_min)) {
BKE_gpencil_stroke_boundingbox_calc(gps);
}
- /* Convert bound box to 2d */
- copy_v3_v3(&pt_dummy.x, gps->boundbox_min);
- gpencil_point_to_parent_space(&pt_dummy, diff_mat, &pt_dummy_ps);
- gpencil_point_to_xy_fl(gsc, gps, &pt_dummy_ps, &boundbox_min[0], &boundbox_min[1]);
-
- copy_v3_v3(&pt_dummy.x, gps->boundbox_max);
- gpencil_point_to_parent_space(&pt_dummy, diff_mat, &pt_dummy_ps);
- gpencil_point_to_xy_fl(gsc, gps, &pt_dummy_ps, &boundbox_max[0], &boundbox_max[1]);
-
- /* Ensure the bounding box is oriented to axis. */
- if (boundbox_max[0] < boundbox_min[0]) {
- SWAP(float, boundbox_min[0], boundbox_max[0]);
- }
- if (boundbox_max[1] < boundbox_min[1]) {
- SWAP(float, boundbox_min[1], boundbox_max[1]);
- }
+ gpencil_projected_2d_bound_box(gsc, gps, diff_mat, boundbox_min, boundbox_max);
rcti rect_stroke = {boundbox_min[0], boundbox_max[0], boundbox_min[1], boundbox_max[1]};
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 780ce487550..de3e5f3d5f9 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -1244,6 +1244,7 @@ static int parent_noinv_set_exec(bContext *C, wmOperator *op)
DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
+ WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index ef22766cd0c..2193a31f19b 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -248,6 +248,7 @@ typedef struct LassoGestureData {
typedef struct LineGestureData {
float true_plane[4];
float plane[4];
+ bool flip;
} LineGestureData;
struct SculptGestureOperation;
@@ -461,6 +462,8 @@ static SculptGestureContext *sculpt_gesture_init_from_line(bContext *C, wmOperat
line_points[1][0] = RNA_int_get(op->ptr, "xend");
line_points[1][1] = RNA_int_get(op->ptr, "yend");
+ sgcontext->line.flip = RNA_boolean_get(op->ptr, "flip");
+
float depth_point[3];
float plane_points[3][3];
@@ -481,6 +484,12 @@ static SculptGestureContext *sculpt_gesture_init_from_line(bContext *C, wmOperat
if (!sgcontext->vc.rv3d->is_persp) {
mul_v3_fl(normal, -1.0f);
}
+
+ /* Apply flip. */
+ if (sgcontext->line.flip) {
+ mul_v3_fl(normal, -1.0f);
+ }
+
mul_v3_mat3_m4v3(normal, sgcontext->vc.obact->imat, normal);
float plane_point_object_space[3];
mul_v3_m4v3(plane_point_object_space, sgcontext->vc.obact->imat, plane_points[0]);
@@ -648,8 +657,7 @@ static void sculpt_gesture_apply(bContext *C, SculptGestureContext *sgcontext)
SCULPT_undo_push_end();
- ED_region_tag_redraw(sgcontext->vc.region);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, sgcontext->vc.obact);
+ SCULPT_tag_update_overlays(C);
}
/* Face Set Gesture Operation. */
@@ -850,7 +858,7 @@ static EnumPropertyItem prop_trim_operation_types[] = {
"JOIN",
0,
"Join",
- "Join the new mesh as separate geometry, without preforming any boolean operation"},
+ "Join the new mesh as separate geometry, without performing any boolean operation"},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index adc62b23559..8e7935e821d 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -3805,20 +3805,33 @@ static void do_grab_brush_task_cb_ex(void *__restrict userdata,
ss, &test, data->brush->falloff_shape);
const int thread_id = BLI_task_parallel_thread_id(tls);
+ const bool grab_silhouette = brush->flag2 & BRUSH_GRAB_SILHOUETTE;
+
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, orig_data.co)) {
- const float fade = bstrength * SCULPT_brush_strength_factor(ss,
- brush,
- orig_data.co,
- sqrtf(test.dist),
- orig_data.no,
- NULL,
- vd.mask ? *vd.mask : 0.0f,
- vd.index,
- thread_id);
+ float fade = bstrength * SCULPT_brush_strength_factor(ss,
+ brush,
+ orig_data.co,
+ sqrtf(test.dist),
+ orig_data.no,
+ NULL,
+ vd.mask ? *vd.mask : 0.0f,
+ vd.index,
+ thread_id);
+
+ if (grab_silhouette) {
+ float silhouette_test_dir[3];
+ normalize_v3_v3(silhouette_test_dir, grab_delta);
+ if (dot_v3v3(ss->cache->initial_normal, ss->cache->grab_delta) < 0.0f) {
+ mul_v3_fl(silhouette_test_dir, -1.0f);
+ }
+ float vno[3];
+ normal_short_to_float_v3(vno, orig_data.no);
+ fade *= max_ff(dot_v3v3(vno, silhouette_test_dir), 0.0f);
+ }
mul_v3_v3fl(proxy[vd.i], grab_delta, fade);
@@ -5666,15 +5679,11 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
/* Check for unsupported features. */
PBVHType type = BKE_pbvh_type(ss->pbvh);
if (brush->sculpt_tool == SCULPT_TOOL_PAINT && type != PBVH_FACES) {
- if (!U.experimental.use_sculpt_vertex_colors) {
- return;
- }
+ return;
}
if (brush->sculpt_tool == SCULPT_TOOL_SMEAR && type != PBVH_FACES) {
- if (!U.experimental.use_sculpt_vertex_colors) {
- return;
- }
+ return;
}
/* Build a list of all nodes that are potentially within the brush's area of influence */
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c
index e764df78c88..8fa20aaae50 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c
@@ -192,7 +192,6 @@ static void mask_filter_task_cb(void *__restrict userdata,
static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
{
- ARegion *region = CTX_wm_region(C);
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
@@ -259,8 +258,8 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
SCULPT_undo_push_end();
- ED_region_tag_redraw(region);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ SCULPT_tag_update_overlays(C);
+
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index 0d1efcab125..60ce86740cd 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -1163,6 +1163,15 @@ static void buttons_panel_context_draw(const bContext *C, Panel *panel)
first = false;
}
+
+ uiLayout *pin_row = uiLayoutRow(row, false);
+ uiLayoutSetAlignment(pin_row, UI_LAYOUT_ALIGN_RIGHT);
+ uiItemSpacer(pin_row);
+ uiLayoutSetEmboss(pin_row, UI_EMBOSS_NONE);
+ uiItemO(pin_row,
+ "",
+ (sbuts->flag & SB_PIN_CONTEXT) ? ICON_PINNED : ICON_UNPINNED,
+ "BUTTONS_OT_toggle_pin");
}
void buttons_context_register(ARegionType *art)
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index 91653fb7785..7cfd749d013 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -2415,7 +2415,8 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN
WM_operator_properties_create_ptr(&ptr, ot);
RNA_string_set(&ptr, "directory", sfile->params->dir);
RNA_boolean_set(&ptr, "open", true);
- /* Enable confirmation prompt, else it's too easy to accidentally create new directories. */
+ /* Enable confirmation prompt, else it's too easy
+ * to accidentally create new directories. */
RNA_boolean_set(&ptr, "confirm", true);
if (lastdir) {
diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c
index ff9454cd922..a71dec99e61 100644
--- a/source/blender/editors/space_file/file_panels.c
+++ b/source/blender/editors/space_file/file_panels.c
@@ -181,11 +181,11 @@ static void file_panel_execution_buttons_draw(const bContext *C, Panel *panel)
if (params->flag & FILE_CHECK_EXISTING) {
but_extra_rna_ptr = UI_but_extra_operator_icon_add(
- but, "FILE_OT_filenum", WM_OP_EXEC_REGION_WIN, ICON_ADD);
- RNA_int_set(but_extra_rna_ptr, "increment", 1);
- but_extra_rna_ptr = UI_but_extra_operator_icon_add(
but, "FILE_OT_filenum", WM_OP_EXEC_REGION_WIN, ICON_REMOVE);
RNA_int_set(but_extra_rna_ptr, "increment", -1);
+ but_extra_rna_ptr = UI_but_extra_operator_icon_add(
+ but, "FILE_OT_filenum", WM_OP_EXEC_REGION_WIN, ICON_ADD);
+ RNA_int_set(but_extra_rna_ptr, "increment", 1);
}
/* check if this overrides a file and if the operator option is used */
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 09ccb950c18..5a789ee0b01 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -1935,8 +1935,14 @@ static void outliner_mode_toggle_fn(bContext *C, void *tselem_poin, void *UNUSED
return;
}
+ /* Check that the the item is actually an object. */
+ BLI_assert(tselem->id != NULL && GS(tselem->id->name) == ID_OB);
+
+ Object *ob = (Object *)tselem->id;
+ const bool object_data_shared = (ob->data == tvc.obact->data);
+
wmWindow *win = CTX_wm_window(C);
- const bool do_extend = win->eventstate->ctrl != 0;
+ const bool do_extend = win->eventstate->ctrl != 0 && !object_data_shared;
outliner_item_mode_toggle(C, &tvc, te, do_extend);
}
@@ -1947,60 +1953,69 @@ static void outliner_draw_mode_column_toggle(uiBlock *block,
TreeStoreElem *tselem,
const bool lock_object_modes)
{
- const int active_mode = tvc->obact->mode;
- bool draw_active_icon = true;
+ if (tselem->type != 0 || te->idcode != ID_OB) {
+ return;
+ }
- if (tselem->type == 0 && te->idcode == ID_OB) {
- Object *ob = (Object *)tselem->id;
+ Object *ob = (Object *)tselem->id;
+ Object *ob_active = tvc->obact;
- /* When not locking object modes, objects can remain in non-object modes. For modes that do not
- * allow multi-object editing, these other objects should still show be viewed as not in the
- * mode. Otherwise multiple objects show the same mode icon in the outliner even though only
- * one object is actually editable in the mode. */
- if (!lock_object_modes && ob != tvc->obact && !(tvc->ob_edit || tvc->ob_pose)) {
- draw_active_icon = false;
- }
+ /* Not all objects support particle systems. */
+ if (ob_active->mode == OB_MODE_PARTICLE_EDIT && !psys_get_current(ob)) {
+ return;
+ }
- if (ob->type == tvc->obact->type) {
- int icon;
- const char *tip;
+ /* Only for objects with the same type. */
+ if (ob->type != ob_active->type) {
+ return;
+ }
- if (draw_active_icon && ob->mode == tvc->obact->mode) {
- icon = UI_icon_from_object_mode(active_mode);
- tip = TIP_("Remove from the current mode");
- }
- else {
- /* Not all objects support particle systems */
- if (active_mode == OB_MODE_PARTICLE_EDIT && !psys_get_current(ob)) {
- return;
- }
- icon = ICON_DOT;
- tip = TIP_(
- "Change the object in the current mode\n"
- "* Ctrl to add to the current mode");
- }
+ bool draw_active_icon = ob->mode == ob_active->mode;
- uiBut *but = uiDefIconBut(block,
- UI_BTYPE_ICON_TOGGLE,
- 0,
- icon,
- 0,
- te->ys,
- UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- tip);
- UI_but_func_set(but, outliner_mode_toggle_fn, tselem, NULL);
- UI_but_flag_enable(but, UI_BUT_DRAG_LOCK);
-
- if (ID_IS_LINKED(&ob->id)) {
- UI_but_disable(but, TIP_("Can't edit external library data"));
- }
- }
+ /* When not locking object modes, objects can remain in non-object modes. For modes that do not
+ * allow multi-object editing, these other objects should still show be viewed as not in the
+ * mode. Otherwise multiple objects show the same mode icon in the outliner even though only
+ * one object is actually editable in the mode. */
+ if (!lock_object_modes && ob != ob_active && !(tvc->ob_edit || tvc->ob_pose)) {
+ draw_active_icon = false;
+ }
+
+ const bool object_data_shared = (ob->data == ob_active->data);
+ draw_active_icon = draw_active_icon || object_data_shared;
+
+ int icon;
+ const char *tip;
+ if (draw_active_icon) {
+ icon = UI_icon_from_object_mode(ob_active->mode);
+ tip = object_data_shared ? TIP_("Change the object in the current mode") :
+ TIP_("Remove from the current mode");
+ }
+ else {
+ icon = ICON_DOT;
+ tip = TIP_(
+ "Change the object in the current mode\n"
+ "* Ctrl to add to the current mode");
+ }
+
+ uiBut *but = uiDefIconBut(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ icon,
+ 0,
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ tip);
+ UI_but_func_set(but, outliner_mode_toggle_fn, tselem, NULL);
+ UI_but_flag_enable(but, UI_BUT_DRAG_LOCK);
+
+ if (ID_IS_LINKED(&ob->id)) {
+ UI_but_disable(but, TIP_("Can't edit external library data"));
}
}
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 3357b0b7346..cbdeb350ba4 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -730,6 +730,9 @@ static void id_local_fn(bContext *C,
BKE_main_id_clear_newpoins(bmain);
}
}
+ else if (ID_IS_OVERRIDE_LIBRARY_REAL(tselem->id)) {
+ BKE_lib_override_library_free(&tselem->id->override_library, true);
+ }
}
static void object_proxy_to_override_convert_fn(bContext *C,
diff --git a/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp b/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp
index dbf1c12fb01..3efabbfbdf5 100644
--- a/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp
+++ b/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp
@@ -55,21 +55,14 @@ PyDoc_STRVAR(
"Class defining a material.\n"
"\n"
".. method:: __init__()\n"
+ " __init__(brother)\n"
+ " __init__(line, diffuse, ambient, specular, emission, shininess, priority)\n"
"\n"
- " Default constructor.\n"
+ " Creates a :class:`FrsMaterial` using either default constructor,\n"
+ " copy constructor, or an overloaded constructor\n"
"\n"
- ".. method:: __init__(brother)\n"
- "\n"
- " Copy constructor.\n"
- "\n"
- " :arg brother: A Material object.\n"
+ " :arg brother: A Material object to be used as a copy constructor.\n"
" :type brother: :class:`Material`\n"
- "\n"
- ".. method:: __init__(line, diffuse, ambient, specular, emission, shininess, priority)\n"
- "\n"
- " Builds a Material from its line, diffuse, ambient, specular, emissive\n"
- " colors, a shininess coefficient and line color priority.\n"
- "\n"
" :arg line: The line color.\n"
" :type line: :class:`mathutils.Vector`, list or tuple of 4 float values\n"
" :arg diffuse: The diffuse color.\n"
diff --git a/source/blender/freestyle/intern/python/BPy_Id.cpp b/source/blender/freestyle/intern/python/BPy_Id.cpp
index eb0eb661e3d..8f61f7f3e14 100644
--- a/source/blender/freestyle/intern/python/BPy_Id.cpp
+++ b/source/blender/freestyle/intern/python/BPy_Id.cpp
@@ -46,24 +46,21 @@ int Id_Init(PyObject *module)
//------------------------INSTANCE METHODS ----------------------------------
-PyDoc_STRVAR(Id_doc,
- "Class for representing an object Id.\n"
- "\n"
- ".. method:: __init__(first=0, second=0)\n"
- "\n"
- " Build the Id from two numbers.\n"
- "\n"
- " :arg first: The first number.\n"
- " :type first: int\n"
- " :arg second: The second number.\n"
- " :type second: int\n"
- "\n"
- ".. method:: __init__(brother)\n"
- "\n"
- " Copy constructor.\n"
- "\n"
- " :arg brother: An Id object.\n"
- " :type brother: :class:`Id`");
+PyDoc_STRVAR(
+ Id_doc,
+ "Class for representing an object Id.\n"
+ "\n"
+ ".. method:: __init__(brother)\n"
+ " __init__(first=0, second=0)\n"
+ "\n"
+ " Build the Id from two numbers or another :class:`Id` using the copy constructor.\n"
+ "\n"
+ " :arg brother: An Id object.\n"
+ " :type brother: :class:`Id`"
+ " :arg first: The first number.\n"
+ " :type first: int\n"
+ " :arg second: The second number.\n"
+ " :type second: int\n");
static int Id_init(BPy_Id *self, PyObject *args, PyObject *kwds)
{
diff --git a/source/blender/freestyle/intern/python/BPy_Operators.cpp b/source/blender/freestyle/intern/python/BPy_Operators.cpp
index 56f95b8ecbb..1235786d5d3 100644
--- a/source/blender/freestyle/intern/python/BPy_Operators.cpp
+++ b/source/blender/freestyle/intern/python/BPy_Operators.cpp
@@ -101,6 +101,7 @@ static PyObject *Operators_select(BPy_Operators * /*self*/, PyObject *args, PyOb
PyDoc_STRVAR(Operators_chain_doc,
".. staticmethod:: chain(it, pred, modifier)\n"
+ " chain(it, pred)\n"
"\n"
" Builds a set of chains from the current set of ViewEdges. Each\n"
" ViewEdge of the current list starts a new chain. The chaining\n"
@@ -116,28 +117,9 @@ PyDoc_STRVAR(Operators_chain_doc,
" :type pred: :class:`UnaryPredicate1D`\n"
" :arg modifier: A function that takes a ViewEdge as argument and\n"
" that is used to modify the processed ViewEdge state (the\n"
- " timestamp incrementation is a typical illustration of such a\n"
- " modifier).\n"
- " :type modifier: :class:`UnaryFunction1DVoid`\n"
- "\n"
- ".. staticmethod:: chain(it, pred)\n"
- "\n"
- " Builds a set of chains from the current set of ViewEdges. Each\n"
- " ViewEdge of the current list starts a new chain. The chaining\n"
- " operator then iterates over the ViewEdges of the ViewMap using the\n"
- " user specified iterator. This operator only iterates using the\n"
- " increment operator and is therefore unidirectional. This chaining\n"
- " operator is different from the previous one because it doesn't take\n"
- " any modifier as argument. Indeed, the time stamp (insuring that a\n"
- " ViewEdge is processed one time) is automatically managed in this\n"
- " case.\n"
- "\n"
- " :arg it: The iterator on the ViewEdges of the ViewMap. It contains\n"
- " the chaining rule. \n"
- " :type it: :class:`ViewEdgeIterator`\n"
- " :arg pred: The predicate on the ViewEdge that expresses the\n"
- " stopping condition.\n"
- " :type pred: :class:`UnaryPredicate1D`");
+ " timestamp incrementation is a typical illustration of such a modifier).\n"
+ " If this argument is not given, the time stamp is automatically managed.\n"
+ " :type modifier: :class:`UnaryFunction1DVoid`\n");
static PyObject *Operators_chain(BPy_Operators * /*self*/, PyObject *args, PyObject *kwds)
{
@@ -195,6 +177,7 @@ static PyObject *Operators_chain(BPy_Operators * /*self*/, PyObject *args, PyObj
PyDoc_STRVAR(Operators_bidirectional_chain_doc,
".. staticmethod:: bidirectional_chain(it, pred)\n"
+ " bidirectional_chain(it)\n"
"\n"
" Builds a set of chains from the current set of ViewEdges. Each\n"
" ViewEdge of the current list potentially starts a new chain. The\n"
@@ -211,30 +194,10 @@ PyDoc_STRVAR(Operators_bidirectional_chain_doc,
" :arg it: The ChainingIterator on the ViewEdges of the ViewMap. It\n"
" contains the chaining rule.\n"
" :type it: :class:`ChainingIterator`\n"
- " :arg pred: The predicate on the ViewEdge that expresses the\n"
- " stopping condition.\n"
- " :type pred: :class:`UnaryPredicate1D`\n"
- "\n"
- ".. staticmethod:: bidirectional_chain(it)\n"
- "\n"
- " The only difference with the above bidirectional chaining algorithm\n"
- " is that we don't need to pass a stopping criterion. This might be\n"
- " desirable when the stopping criterion is already contained in the\n"
- " iterator definition. Builds a set of chains from the current set of\n"
- " ViewEdges. Each ViewEdge of the current list potentially starts a new\n"
- " chain. The chaining operator then iterates over the ViewEdges of the\n"
- " ViewMap using the user specified iterator. This operator iterates\n"
- " both using the increment and decrement operators and is therefore\n"
- " bidirectional. This operator works with a ChainingIterator which\n"
- " contains the chaining rules. It is this last one which can be told to\n"
- " chain only edges that belong to the selection or not to process twice\n"
- " a ViewEdge during the chaining. Each time a ViewEdge is added to a\n"
- " chain, its chaining time stamp is incremented. This allows you to\n"
- " keep track of the number of chains to which a ViewEdge belongs to.\n"
- "\n"
- " :arg it: The ChainingIterator on the ViewEdges of the ViewMap. It\n"
- " contains the chaining rule.\n"
- " :type it: :class:`ChainingIterator`");
+ " :arg pred: The predicate on the ViewEdge that expresses the stopping condition.\n"
+ " This parameter is optional, you make not want to pass a stopping criterion\n"
+ " when the stopping criterion is already contained in the iterator definition.\n"
+ " :type pred: :class:`UnaryPredicate1D`\n");
static PyObject *Operators_bidirectional_chain(BPy_Operators * /*self*/,
PyObject *args,
@@ -287,44 +250,34 @@ static PyObject *Operators_bidirectional_chain(BPy_Operators * /*self*/,
PyDoc_STRVAR(Operators_sequential_split_doc,
".. staticmethod:: sequential_split(starting_pred, stopping_pred, sampling=0.0)\n"
+ " sequential_split(pred, sampling=0.0)\n"
"\n"
" Splits each chain of the current set of chains in a sequential way.\n"
" The points of each chain are processed (with a specified sampling)\n"
- " sequentially. Each time a user specified starting condition is\n"
- " verified, a new chain begins and ends as soon as a user-defined\n"
- " stopping predicate is verified. This allows chains overlapping rather\n"
- " than chains partitioning. The first point of the initial chain is the\n"
+ " sequentially. The first point of the initial chain is the\n"
" first point of one of the resulting chains. The splitting ends when\n"
" no more chain can start.\n"
"\n"
+ " .. tip::\n"
+ "\n"
+ " By specifiying a starting and stopping predicate allows\n"
+ " the chains to overlapp rather than chains partitioning.\n"
+ "\n"
" :arg starting_pred: The predicate on a point that expresses the\n"
- " starting condition.\n"
+ " starting condition. Each time this condition is verified, a new chain begins\n"
" :type starting_pred: :class:`UnaryPredicate0D`\n"
" :arg stopping_pred: The predicate on a point that expresses the\n"
- " stopping condition.\n"
+ " stopping condition. The chain ends as soon as this predicate is verified.\n"
" :type stopping_pred: :class:`UnaryPredicate0D`\n"
+ " :arg pred: The predicate on a point that expresses the splitting condition.\n"
+ " Each time the condition is verified, the chain is split into two chains.\n"
+ " The resulting set of chains is a partition of the initial chain\n"
+ " :type pred: :class:`UnaryPredicate0D`\n"
" :arg sampling: The resolution used to sample the chain for the\n"
" predicates evaluation. (The chain is not actually resampled;\n"
" a virtual point only progresses along the curve using this\n"
" resolution.)\n"
- " :type sampling: float\n"
- "\n"
- ".. staticmethod:: sequential_split(pred, sampling=0.0)\n"
- "\n"
- " Splits each chain of the current set of chains in a sequential way.\n"
- " The points of each chain are processed (with a specified sampling)\n"
- " sequentially and each time a user specified condition is verified,\n"
- " the chain is split into two chains. The resulting set of chains is a\n"
- " partition of the initial chain\n"
- "\n"
- " :arg pred: The predicate on a point that expresses the splitting\n"
- " condition.\n"
- " :type pred: :class:`UnaryPredicate0D`\n"
- " :arg sampling: The resolution used to sample the chain for the\n"
- " predicate evaluation. (The chain is not actually resampled; a\n"
- " virtual point only progresses along the curve using this\n"
- " resolution.)\n"
- " :type sampling: float");
+ " :type sampling: float\n");
static PyObject *Operators_sequential_split(BPy_Operators * /*self*/,
PyObject *args,
@@ -389,61 +342,41 @@ static PyObject *Operators_sequential_split(BPy_Operators * /*self*/,
Py_RETURN_NONE;
}
-PyDoc_STRVAR(Operators_recursive_split_doc,
- ".. staticmethod:: recursive_split(func, pred_1d, sampling=0.0)\n"
- "\n"
- " Splits the current set of chains in a recursive way. We process the\n"
- " points of each chain (with a specified sampling) to find the point\n"
- " minimizing a specified function. The chain is split in two at this\n"
- " point and the two new chains are processed in the same way. The\n"
- " recursivity level is controlled through a predicate 1D that expresses\n"
- " a stopping condition on the chain that is about to be processed.\n"
- "\n"
- " :arg func: The Unary Function evaluated at each point of the chain.\n"
- " The splitting point is the point minimizing this function.\n"
- " :type func: :class:`UnaryFunction0DDouble`\n"
- " :arg pred_1d: The Unary Predicate expressing the recursivity stopping\n"
- " condition. This predicate is evaluated for each curve before it\n"
- " actually gets split. If pred_1d(chain) is true, the curve won't be\n"
- " split anymore.\n"
- " :type pred_1d: :class:`UnaryPredicate1D`\n"
- " :arg sampling: The resolution used to sample the chain for the\n"
- " predicates evaluation. (The chain is not actually resampled, a\n"
- " virtual point only progresses along the curve using this\n"
- " resolution.)\n"
- " :type sampling: float\n"
- "\n"
- ".. staticmethod:: recursive_split(func, pred_0d, pred_1d, sampling=0.0)\n"
- "\n"
- " Splits the current set of chains in a recursive way. We process the\n"
- " points of each chain (with a specified sampling) to find the point\n"
- " minimizing a specified function. The chain is split in two at this\n"
- " point and the two new chains are processed in the same way. The user\n"
- " can specify a 0D predicate to make a first selection on the points\n"
- " that can potentially be split. A point that doesn't verify the 0D\n"
- " predicate won't be candidate in realizing the min. The recursivity\n"
- " level is controlled through a predicate 1D that expresses a stopping\n"
- " condition on the chain that is about to be processed.\n"
- "\n"
- " :arg func: The Unary Function evaluated at each point of the chain.\n"
- " The splitting point is the point minimizing this function.\n"
- " :type func: :class:`UnaryFunction0DDouble`\n"
- " :arg pred_0d: The Unary Predicate 0D used to select the candidate\n"
- " points where the split can occur. For example, it is very likely\n"
- " that would rather have your chain splitting around its middle\n"
- " point than around one of its extremities. A 0D predicate working\n"
- " on the curvilinear abscissa allows to add this kind of constraints.\n"
- " :type pred_0d: :class:`UnaryPredicate0D`\n"
- " :arg pred_1d: The Unary Predicate expressing the recursivity stopping\n"
- " condition. This predicate is evaluated for each curve before it\n"
- " actually gets split. If pred_1d(chain) is true, the curve won't be\n"
- " split anymore.\n"
- " :type pred_1d: :class:`UnaryPredicate1D`\n"
- " :arg sampling: The resolution used to sample the chain for the\n"
- " predicates evaluation. (The chain is not actually resampled; a\n"
- " virtual point only progresses along the curve using this\n"
- " resolution.)\n"
- " :type sampling: float");
+PyDoc_STRVAR(
+ Operators_recursive_split_doc,
+ ".. staticmethod:: recursive_split(func, pred_1d, sampling=0.0)\n"
+ " recursive_split(func, pred_0d, pred_1d, sampling=0.0)\n"
+ "\n"
+ " Splits the current set of chains in a recursive way. We process the\n"
+ " points of each chain (with a specified sampling) to find the point\n"
+ " minimizing a specified function. The chain is split in two at this\n"
+ " point and the two new chains are processed in the same way. The\n"
+ " recursivity level is controlled through a predicate 1D that expresses\n"
+ " a stopping condition on the chain that is about to be processed.\n"
+ "\n"
+ " The user can also specify a 0D predicate to make a first selection on the points\n"
+ " that can potentially be split. A point that doesn't verify the 0D\n"
+ " predicate won't be candidate in realizing the min.\n"
+ "\n"
+ " :arg func: The Unary Function evaluated at each point of the chain.\n"
+ " The splitting point is the point minimizing this function.\n"
+ " :type func: :class:`UnaryFunction0DDouble`\n"
+ " :arg pred_0d: The Unary Predicate 0D used to select the candidate\n"
+ " points where the split can occur. For example, it is very likely\n"
+ " that would rather have your chain splitting around its middle\n"
+ " point than around one of its extremities. A 0D predicate working\n"
+ " on the curvilinear abscissa allows to add this kind of constraints.\n"
+ " :type pred_0d: :class:`UnaryPredicate0D`\n"
+ " :arg pred_1d: The Unary Predicate expressing the recursivity stopping\n"
+ " condition. This predicate is evaluated for each curve before it\n"
+ " actually gets split. If pred_1d(chain) is true, the curve won't be\n"
+ " split anymore.\n"
+ " :type pred_1d: :class:`UnaryPredicate1D`\n"
+ " :arg sampling: The resolution used to sample the chain for the\n"
+ " predicates evaluation. (The chain is not actually resampled; a\n"
+ " virtual point only progresses along the curve using this\n"
+ " resolution.)\n"
+ " :type sampling: float\n");
static PyObject *Operators_recursive_split(BPy_Operators * /*self*/,
PyObject *args,
diff --git a/source/blender/freestyle/intern/python/BPy_SShape.cpp b/source/blender/freestyle/intern/python/BPy_SShape.cpp
index 9712dccfa5e..b1d5f8f4aac 100644
--- a/source/blender/freestyle/intern/python/BPy_SShape.cpp
+++ b/source/blender/freestyle/intern/python/BPy_SShape.cpp
@@ -50,20 +50,18 @@ int SShape_Init(PyObject *module)
/*----------------------SShape methods ----------------------------*/
-PyDoc_STRVAR(SShape_doc,
- "Class to define a feature shape. It is the gathering of feature\n"
- "elements from an identified input shape.\n"
- "\n"
- ".. method:: __init__()\n"
- "\n"
- " Default constructor.\n"
- "\n"
- ".. method:: __init__(brother)\n"
- "\n"
- " Copy constructor.\n"
- "\n"
- " :arg brother: An SShape object.\n"
- " :type brother: :class:`SShape`");
+PyDoc_STRVAR(
+ SShape_doc,
+ "Class to define a feature shape. It is the gathering of feature\n"
+ "elements from an identified input shape.\n"
+ "\n"
+ ".. method:: __init__()\n"
+ " __init__(brother)\n"
+ "\n"
+ " Creates a :class:`SShape` class using either a default constructor or copy constructor.\n"
+ "\n"
+ " :arg brother: An SShape object.\n"
+ " :type brother: :class:`SShape`");
static int SShape_init(BPy_SShape *self, PyObject *args, PyObject *kwds)
{
diff --git a/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp
index 214385f74ad..3718fddcf20 100644
--- a/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp
+++ b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp
@@ -53,20 +53,16 @@ PyDoc_STRVAR(StrokeAttribute_doc,
"Vertex.\n"
"\n"
".. method:: __init__()\n"
+ " __init__(brother)\n"
+ " __init__(red, green, blue, alpha, thickness_right, thickness_left)\n"
+ " __init__(attribute1, attribute2, t)\n"
"\n"
- " Default constructor.\n"
+ " Creates a :class:`StrokeAttribute` object using either a default constructor,\n"
+ " copy constructor, overloaded constructor, or and interpolation constructor\n"
+ " to interpolate between two :class:`StrokeAttribute` objects.\n"
"\n"
- ".. method:: __init__(brother)\n"
- "\n"
- " Copy constructor.\n"
- "\n"
- " :arg brother: A StrokeAttribute object.\n"
+ " :arg brother: A StrokeAttribute object to be used as a copy constructor.\n"
" :type brother: :class:`StrokeAttribute`\n"
- "\n"
- ".. method:: __init__(red, green, blue, alpha, thickness_right, thickness_left)\n"
- "\n"
- " Build a stroke vertex attribute from a set of parameters.\n"
- "\n"
" :arg red: Red component of a stroke color.\n"
" :type red: float\n"
" :arg green: Green component of a stroke color.\n"
@@ -79,12 +75,6 @@ PyDoc_STRVAR(StrokeAttribute_doc,
" :type thickness_right: float\n"
" :arg thickness_left: Stroke thickness on the left.\n"
" :type thickness_left: float\n"
- "\n"
- ".. method:: __init__(attribute1, attribute2, t)\n"
- "\n"
- " Interpolation constructor. Build a StrokeAttribute from two\n"
- " StrokeAttribute objects and an interpolation parameter.\n"
- "\n"
" :arg attribute1: The first StrokeAttribute object.\n"
" :type attribute1: :class:`StrokeAttribute`\n"
" :arg attribute2: The second StrokeAttribute object.\n"
diff --git a/source/blender/freestyle/intern/python/BPy_ViewShape.cpp b/source/blender/freestyle/intern/python/BPy_ViewShape.cpp
index 2adcae13e6d..7d8b5ef6fa9 100644
--- a/source/blender/freestyle/intern/python/BPy_ViewShape.cpp
+++ b/source/blender/freestyle/intern/python/BPy_ViewShape.cpp
@@ -55,20 +55,14 @@ PyDoc_STRVAR(ViewShape_doc,
"and :class:`ViewEdge`) that are issued from the same input shape.\n"
"\n"
".. method:: __init__()\n"
+ " __init__(brother)\n"
+ " __init__(sshape)\n"
"\n"
- " Default constructor.\n"
- "\n"
- ".. method:: __init__(brother)\n"
- "\n"
- " Copy constructor.\n"
+ " Builds a :class:`ViewShape` using the default constructor,\n"
+ " copy constructor, or from a :class:`SShape`.\n"
"\n"
" :arg brother: A ViewShape object.\n"
" :type brother: :class:`ViewShape`\n"
- "\n"
- ".. method:: __init__(sshape)\n"
- "\n"
- " Builds a ViewShape from an SShape.\n"
- "\n"
" :arg sshape: An SShape object.\n"
" :type sshape: :class:`SShape`");
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
index 81dd79ff270..7b3571c479f 100644
--- a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
@@ -44,40 +44,28 @@ PyDoc_STRVAR(CurvePoint_doc,
"given resolution.\n"
"\n"
".. method:: __init__()\n"
+ " __init__(brother)\n"
+ " __init__(first_vertex, second_vertex, t2d)\n"
+ " __init__(first_point, second_point, t2d)\n"
"\n"
- " Default constructor.\n"
- "\n"
- ".. method:: __init__(brother)\n"
- "\n"
- " Copy constructor.\n"
+ " Builds a CurvePoint using the default constructor, copy constructor,\n"
+ " or one of the overloaded constructors. The over loaded constructors\n"
+ " can either take two :class:`SVertex` or two :class:`CurvePoint`\n"
+ " objects and an interpolation parameter\n"
"\n"
" :arg brother: A CurvePoint object.\n"
" :type brother: :class:`CurvePoint`\n"
- "\n"
- ".. method:: __init__(first_vertex, second_vertex, t2d)\n"
- "\n"
- " Builds a CurvePoint from two SVertex objects and an interpolation parameter.\n"
- "\n"
" :arg first_vertex: The first SVertex.\n"
" :type first_vertex: :class:`SVertex`\n"
" :arg second_vertex: The second SVertex.\n"
" :type second_vertex: :class:`SVertex`\n"
- " :arg t2d: A 2D interpolation parameter used to linearly interpolate\n"
- " first_vertex and second_vertex.\n"
- " :type t2d: float\n"
- "\n"
- ".. method:: __init__(first_point, second_point, t2d)\n"
- "\n"
- " Builds a CurvePoint from two CurvePoint objects and an interpolation\n"
- " parameter.\n"
- "\n"
" :arg first_point: The first CurvePoint.\n"
" :type first_point: :class:`CurvePoint`\n"
" :arg second_point: The second CurvePoint.\n"
" :type second_point: :class:`CurvePoint`\n"
- " :arg t2d: The 2D interpolation parameter used to linearly interpolate\n"
- " first_point and second_point.\n"
- " :type t2d: float");
+ " :arg t2d: A 2D interpolation parameter used to linearly interpolate\n"
+ " first_vertex and second_vertex or first_point and second_point.\n"
+ " :type t2d: float\n");
static int CurvePoint_init(BPy_CurvePoint *self, PyObject *args, PyObject *kwds)
{
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp
index c01f1f17000..63725c6b0e8 100644
--- a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp
@@ -38,20 +38,15 @@ PyDoc_STRVAR(SVertex_doc,
"Class to define a vertex of the embedding.\n"
"\n"
".. method:: __init__()\n"
+ " __init__(brother)\n"
+ " __init__(point_3d, id)\n"
"\n"
- " Default constructor.\n"
- "\n"
- ".. method:: __init__(brother)\n"
- "\n"
- " Copy constructor.\n"
+ " Builds a :class:`SVertex` using the default constructor,\n"
+ " copy constructor or the overloaded constructor which builds"
+ " a :class:`SVertex` from 3D coordinates and an Id.\n"
"\n"
" :arg brother: A SVertex object.\n"
" :type brother: :class:`SVertex`\n"
- "\n"
- ".. method:: __init__(point_3d, id)\n"
- "\n"
- " Builds a SVertex from 3D coordinates and an Id.\n"
- "\n"
" :arg point_3d: A three-dimensional vector.\n"
" :type point_3d: :class:`mathutils.Vector`\n"
" :arg id: An Id object.\n"
diff --git a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp
index 519bd72db3b..5c1a8f8482f 100644
--- a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp
+++ b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp
@@ -40,46 +40,29 @@ PyDoc_STRVAR(
"Class to define a stroke vertex.\n"
"\n"
".. method:: __init__()\n"
+ " __init__(brother)\n"
+ " __init__(first_vertex, second_vertex, t3d)\n"
+ " __init__(point)\n"
+ " __init__(svertex)\n"
+ " __init__(svertex, attribute)\n"
"\n"
- " Default constructor.\n"
- "\n"
- ".. method:: __init__(brother)\n"
- "\n"
- " Copy constructor.\n"
+ " Builds a :class:`StrokeVertex` using the default constructor,\n"
+ " copy constructor, from 2 :class:`StrokeVertex` and an interpolation parameter,\n"
+ " from a CurvePoint, from a SVertex, or a :class:`SVertex`"
+ " and a :class:`StrokeAttribute` object.\n"
"\n"
" :arg brother: A StrokeVertex object.\n"
" :type brother: :class:`StrokeVertex`\n"
- "\n"
- ".. method:: __init__(first_vertex, second_vertex, t3d)\n"
- "\n"
- " Build a stroke vertex from 2 stroke vertices and an interpolation\n"
- " parameter.\n"
- "\n"
" :arg first_vertex: The first StrokeVertex.\n"
" :type first_vertex: :class:`StrokeVertex`\n"
" :arg second_vertex: The second StrokeVertex.\n"
" :type second_vertex: :class:`StrokeVertex`\n"
" :arg t3d: An interpolation parameter.\n"
" :type t3d: float\n"
- "\n"
- ".. method:: __init__(point)\n"
- "\n"
- " Build a stroke vertex from a CurvePoint\n"
- "\n"
" :arg point: A CurvePoint object.\n"
" :type point: :class:`CurvePoint`\n"
- "\n"
- ".. method:: __init__(svertex)\n"
- "\n"
- " Build a stroke vertex from a SVertex\n"
- "\n"
" :arg svertex: An SVertex object.\n"
" :type svertex: :class:`SVertex`\n"
- "\n"
- ".. method:: __init__(svertex, attribute)\n"
- "\n"
- " Build a stroke vertex from an SVertex and a StrokeAttribute object.\n"
- "\n"
" :arg svertex: An SVertex object.\n"
" :type svertex: :class:`SVertex`\n"
" :arg attribute: A StrokeAttribute object.\n"
diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp
index 9295e4f424b..ff53f5bfcbe 100644
--- a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp
+++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp
@@ -31,22 +31,20 @@ extern "C" {
/*----------------------NonTVertex methods ----------------------------*/
-PyDoc_STRVAR(NonTVertex_doc,
- "Class hierarchy: :class:`Interface0D` > :class:`ViewVertex` > :class:`NonTVertex`\n"
- "\n"
- "View vertex for corners, cusps, etc. associated to a single SVertex.\n"
- "Can be associated to 2 or more view edges.\n"
- "\n"
- ".. method:: __init__()\n"
- "\n"
- " Default constructor.\n"
- "\n"
- ".. method:: __init__(svertex)\n"
- "\n"
- " Build a NonTVertex from a SVertex.\n"
- "\n"
- " :arg svertex: An SVertex object.\n"
- " :type svertex: :class:`SVertex`");
+PyDoc_STRVAR(
+ NonTVertex_doc,
+ "Class hierarchy: :class:`Interface0D` > :class:`ViewVertex` > :class:`NonTVertex`\n"
+ "\n"
+ "View vertex for corners, cusps, etc. associated to a single SVertex.\n"
+ "Can be associated to 2 or more view edges.\n"
+ "\n"
+ ".. method:: __init__()\n"
+ " __init__(svertex)\n"
+ "\n"
+ " Builds a :class:`NonTVertex` using the default constructor or a :class:`SVertex`.\n"
+ "\n"
+ " :arg svertex: An SVertex object.\n"
+ " :type svertex: :class:`SVertex`");
/* Note: No copy constructor in Python because the C++ copy constructor is 'protected'. */
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp
index 187ab94360a..e04a89bad3b 100644
--- a/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp
@@ -48,20 +48,13 @@ PyDoc_STRVAR(FEdge_doc,
"from one to the other.\n"
"\n"
".. method:: FEdge()\n"
+ " FEdge(brother)\n"
"\n"
- " Default constructor.\n"
- "\n"
- ".. method:: FEdge(brother)\n"
- "\n"
- " Copy constructor.\n"
+ " Builds an :class:`FEdge` using the default constructor,\n"
+ " copy constructor, or between two :class:`SVertex` objects.\n"
"\n"
" :arg brother: An FEdge object.\n"
" :type brother: :class:`FEdge`\n"
- "\n"
- ".. method:: FEdge(first_vertex, second_vertex)\n"
- "\n"
- " Builds an FEdge going from the first vertex to the second.\n"
- "\n"
" :arg first_vertex: The first SVertex.\n"
" :type first_vertex: :class:`SVertex`\n"
" :arg second_vertex: The second SVertex.\n"
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp
index 788dfa78992..78c0ee051d6 100644
--- a/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp
@@ -41,20 +41,14 @@ PyDoc_STRVAR(FrsCurve_doc,
"specialization of a Curve.\n"
"\n"
".. method:: __init__()\n"
+ " __init__(brother)\n"
+ " __init__(id)\n"
"\n"
- " Default Constructor.\n"
- "\n"
- ".. method:: __init__(brother)\n"
- "\n"
- " Copy Constructor.\n"
+ " Builds a :class:`FrsCurve` using a default constructor,\n"
+ " copy constructor or from an :class:`Id`.\n"
"\n"
" :arg brother: A Curve object.\n"
" :type brother: :class:`Curve`\n"
- "\n"
- ".. method:: __init__(id)\n"
- "\n"
- " Builds a Curve from its Id.\n"
- "\n"
" :arg id: An Id object.\n"
" :type id: :class:`Id`");
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
index b31efe1f923..910f9cdfa07 100644
--- a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
@@ -50,12 +50,9 @@ PyDoc_STRVAR(Stroke_doc,
"defines the stroke's shape and appearance at this vertex position.\n"
"\n"
".. method:: Stroke()\n"
+ " Stroke(brother)\n"
"\n"
- " Default constructor\n"
- "\n"
- ".. method:: Stroke(brother)\n"
- "\n"
- " Copy constructor");
+ " Creates a :class:`Stroke` using the default constructor or copy constructor\n");
static int Stroke_init(BPy_Stroke *self, PyObject *args, PyObject *kwds)
{
@@ -127,21 +124,18 @@ static PyObject *Stroke_compute_sampling(BPy_Stroke *self, PyObject *args, PyObj
PyDoc_STRVAR(Stroke_resample_doc,
".. method:: resample(n)\n"
+ " resample(sampling)\n"
"\n"
- " Resamples the stroke so that it eventually has N points. That means\n"
- " it is going to add N-vertices_size, where vertices_size is the\n"
- " number of points we already have. If vertices_size >= N, no\n"
- " resampling is done.\n"
+ " Resamples the stroke so using one of two methods with the goal\n"
+ " of creating a stroke with fewer points and the same shape.\n"
"\n"
- " :arg n: The number of vertices we eventually want in our stroke.\n"
+ " :arg n: Resamples the stroke so that it eventually has N points. That means\n"
+ " it is going to add N-vertices_size, where vertices_size is the\n"
+ " number of points we already have. If vertices_size >= N, no\n"
+ " resampling is done.\n"
" :type n: int\n"
- "\n"
- ".. method:: resample(sampling)\n"
- "\n"
- " Resamples the stroke with a given sampling. If the sampling is\n"
- " smaller than the actual sampling value, no resampling is done.\n"
- "\n"
- " :arg sampling: The new sampling value.\n"
+ " :arg sampling: Resamples the stroke with a given sampling value. If the\n"
+ " sampling is smaller than the actual sampling value, no resampling is done.\n"
" :type sampling: float");
static PyObject *Stroke_resample(BPy_Stroke *self, PyObject *args, PyObject *kwds)
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp
index 58c2ba69c79..e9160d7a5c7 100644
--- a/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp
@@ -36,23 +36,21 @@ extern "C" {
/*----------------------ViewEdge methods ----------------------------*/
-PyDoc_STRVAR(ViewEdge_doc,
- "Class hierarchy: :class:`Interface1D` > :class:`ViewEdge`\n"
- "\n"
- "Class defining a ViewEdge. A ViewEdge in an edge of the image graph.\n"
- "it connects two :class:`ViewVertex` objects. It is made by connecting\n"
- "a set of FEdges.\n"
- "\n"
- ".. method:: __init__()\n"
- "\n"
- " Default constructor.\n"
- "\n"
- ".. method:: __init__(brother)\n"
- "\n"
- " Copy constructor.\n"
- "\n"
- " :arg brother: A ViewEdge object.\n"
- " :type brother: :class:`ViewEdge`");
+PyDoc_STRVAR(
+ ViewEdge_doc,
+ "Class hierarchy: :class:`Interface1D` > :class:`ViewEdge`\n"
+ "\n"
+ "Class defining a ViewEdge. A ViewEdge in an edge of the image graph.\n"
+ "it connects two :class:`ViewVertex` objects. It is made by connecting\n"
+ "a set of FEdges.\n"
+ "\n"
+ ".. method:: __init__()\n"
+ " __init__(brother)\n"
+ "\n"
+ " Builds a :class:`ViewEdge` using the default constructor or the copy constructor.\n"
+ "\n"
+ " :arg brother: A ViewEdge object.\n"
+ " :type brother: :class:`ViewEdge`");
static int ViewEdge_init(BPy_ViewEdge *self, PyObject *args, PyObject *kwds)
{
diff --git a/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp b/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp
index 9cdc344081e..028e36145b9 100644
--- a/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp
+++ b/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp
@@ -40,20 +40,14 @@ PyDoc_STRVAR(Chain_doc,
"Splitting and Creation processes.\n"
"\n"
".. method:: __init__()\n"
+ " __init__(brother)\n"
+ " __init__(id)\n"
"\n"
- " Default constructor.\n"
- "\n"
- ".. method:: __init__(brother)\n"
- "\n"
- " Copy constructor.\n"
+ " Builds a :class:`Chain` using the default constructor,\n"
+ " copy constructor or from an :class:`Id`.\n"
"\n"
" :arg brother: A Chain object.\n"
" :type brother: :class:`Chain`\n"
- "\n"
- ".. method:: __init__(id)\n"
- "\n"
- " Builds a chain from its Id.\n"
- "\n"
" :arg id: An Id object.\n"
" :type id: :class:`Id`");
diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp
index c329a3badd5..018e0449552 100644
--- a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp
+++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp
@@ -42,20 +42,14 @@ PyDoc_STRVAR(FEdgeSharp_doc,
"a is None.\n"
"\n"
".. method:: __init__()\n"
+ " __init__(brother)\n"
+ " __init__(first_vertex, second_vertex)\n"
"\n"
- " Default constructor.\n"
- "\n"
- ".. method:: __init__(brother)\n"
- "\n"
- " Copy constructor.\n"
+ " Builds an :class:`FEdgeSharp` using the default constructor,\n"
+ " copy constructor, or between two :class:`SVertex` objects.\n"
"\n"
" :arg brother: An FEdgeSharp object.\n"
" :type brother: :class:`FEdgeSharp`\n"
- "\n"
- ".. method:: __init__(first_vertex, second_vertex)\n"
- "\n"
- " Builds an FEdgeSharp going from the first vertex to the second.\n"
- "\n"
" :arg first_vertex: The first SVertex object.\n"
" :type first_vertex: :class:`SVertex`\n"
" :arg second_vertex: The second SVertex object.\n"
diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp
index 3fb739b18db..014f0411356 100644
--- a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp
+++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp
@@ -39,20 +39,14 @@ PyDoc_STRVAR(FEdgeSmooth_doc,
"a suggestive contour.\n"
"\n"
".. method:: __init__()\n"
+ " __init__(brother)\n"
+ " __init__(first_vertex, second_vertex)\n"
"\n"
- " Default constructor.\n"
- "\n"
- ".. method:: __init__(brother)\n"
- "\n"
- " Copy constructor.\n"
+ " Builds an :class:`FEdgeSmooth` using the default constructor,\n"
+ " copy constructor, or between two :class:`SVertex`.\n"
"\n"
" :arg brother: An FEdgeSmooth object.\n"
" :type brother: :class:`FEdgeSmooth`\n"
- "\n"
- ".. method:: __init__(first_vertex, second_vertex)\n"
- "\n"
- " Builds an FEdgeSmooth going from the first to the second.\n"
- "\n"
" :arg first_vertex: The first SVertex object.\n"
" :type first_vertex: :class:`SVertex`\n"
" :arg second_vertex: The second SVertex object.\n"
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp
index 90e751333b9..dc32b73fda1 100644
--- a/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp
@@ -41,20 +41,14 @@ PyDoc_STRVAR(
"traverse() method of the ChainingIterator.\n"
"\n"
".. method:: __init__()\n"
+ " __init__(brother)\n"
+ " __init__(vertex, restrict_to_selection=True, restrict_to_unvisited=True)\n"
"\n"
- " Default constructor.\n"
- "\n"
- ".. method:: __init__(brother)\n"
- "\n"
- " Copy constructor.\n"
+ " Builds an :class:`AdjacencyIterator` using the default constructor,\n"
+ " copy constructor or the overloaded constructor.\n"
"\n"
" :arg brother: An AdjacencyIterator object.\n"
" :type brother: :class:`AdjacencyIterator`\n"
- "\n"
- ".. method:: __init__(vertex, restrict_to_selection=True, restrict_to_unvisited=True)\n"
- "\n"
- " Builds a AdjacencyIterator object.\n"
- "\n"
" :arg vertex: The vertex which is the next crossing.\n"
" :type vertex: :class:`ViewVertex`\n"
" :arg restrict_to_selection: Indicates whether to force the chaining\n"
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp
index 1703fc2bddb..9c534a3463c 100644
--- a/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp
@@ -33,55 +33,52 @@ extern "C" {
//------------------------INSTANCE METHODS ----------------------------------
-PyDoc_STRVAR(ChainPredicateIterator_doc,
-
- "Class hierarchy: :class:`freestyle.types.Iterator` >\n"
- ":class:`freestyle.types.ViewEdgeIterator` >\n"
- ":class:`freestyle.types.ChainingIterator` >\n"
- ":class:`ChainPredicateIterator`\n"
- "\n"
- "A \"generic\" user-controlled ViewEdge iterator. This iterator is in\n"
- "particular built from a unary predicate and a binary predicate.\n"
- "First, the unary predicate is evaluated for all potential next\n"
- "ViewEdges in order to only keep the ones respecting a certain\n"
- "constraint. Then, the binary predicate is evaluated on the current\n"
- "ViewEdge together with each ViewEdge of the previous selection. The\n"
- "first ViewEdge respecting both the unary predicate and the binary\n"
- "predicate is kept as the next one. If none of the potential next\n"
- "ViewEdge respects these two predicates, None is returned.\n"
- "\n"
- ".. method:: __init__(upred, bpred, restrict_to_selection=True, "
- "restrict_to_unvisited=True, begin=None, "
- "orientation=True)\n"
- "\n"
- " Builds a ChainPredicateIterator from a unary predicate, a binary\n"
- " predicate, a starting ViewEdge and its orientation.\n"
- "\n"
- " :arg upred: The unary predicate that the next ViewEdge must satisfy.\n"
- " :type upred: :class:`freestyle.types.UnaryPredicate1D`\n"
- " :arg bpred: The binary predicate that the next ViewEdge must\n"
- " satisfy together with the actual pointed ViewEdge.\n"
- " :type bpred: :class:`freestyle.types.BinaryPredicate1D`\n"
- " :arg restrict_to_selection: Indicates whether to force the chaining\n"
- " to stay within the set of selected ViewEdges or not.\n"
- " :type restrict_to_selection: bool\n"
- " :arg restrict_to_unvisited: Indicates whether a ViewEdge that has\n"
- " already been chained must be ignored ot not.\n"
- " :type restrict_to_unvisited: bool\n"
- " :arg begin: The ViewEdge from where to start the iteration.\n"
- " :type begin: :class:`freestyle.types.ViewEdge` or None\n"
- " :arg orientation: If true, we'll look for the next ViewEdge among\n"
- " the ViewEdges that surround the ending ViewVertex of begin. If\n"
- " false, we'll search over the ViewEdges surrounding the ending\n"
- " ViewVertex of begin.\n"
- " :type orientation: bool\n"
- "\n"
- ".. method:: __init__(brother)\n"
- "\n"
- " Copy constructor.\n"
- "\n"
- " :arg brother: A ChainPredicateIterator object.\n"
- " :type brother: :class:`ChainPredicateIterator`");
+PyDoc_STRVAR(
+ ChainPredicateIterator_doc,
+
+ "Class hierarchy: :class:`freestyle.types.Iterator` >\n"
+ ":class:`freestyle.types.ViewEdgeIterator` >\n"
+ ":class:`freestyle.types.ChainingIterator` >\n"
+ ":class:`ChainPredicateIterator`\n"
+ "\n"
+ "A \"generic\" user-controlled ViewEdge iterator. This iterator is in\n"
+ "particular built from a unary predicate and a binary predicate.\n"
+ "First, the unary predicate is evaluated for all potential next\n"
+ "ViewEdges in order to only keep the ones respecting a certain\n"
+ "constraint. Then, the binary predicate is evaluated on the current\n"
+ "ViewEdge together with each ViewEdge of the previous selection. The\n"
+ "first ViewEdge respecting both the unary predicate and the binary\n"
+ "predicate is kept as the next one. If none of the potential next\n"
+ "ViewEdge respects these two predicates, None is returned.\n"
+ "\n"
+ ".. method:: __init__(upred, bpred, restrict_to_selection=True, "
+ " restrict_to_unvisited=True, begin=None, "
+ " orientation=True)\n"
+ " __init__(brother)\n"
+ "\n"
+ " Builds a ChainPredicateIterator from a unary predicate, a binary\n"
+ " predicate, a starting ViewEdge and its orientation or using the copy constructor.\n"
+ "\n"
+ " :arg upred: The unary predicate that the next ViewEdge must satisfy.\n"
+ " :type upred: :class:`freestyle.types.UnaryPredicate1D`\n"
+ " :arg bpred: The binary predicate that the next ViewEdge must\n"
+ " satisfy together with the actual pointed ViewEdge.\n"
+ " :type bpred: :class:`freestyle.types.BinaryPredicate1D`\n"
+ " :arg restrict_to_selection: Indicates whether to force the chaining\n"
+ " to stay within the set of selected ViewEdges or not.\n"
+ " :type restrict_to_selection: bool\n"
+ " :arg restrict_to_unvisited: Indicates whether a ViewEdge that has\n"
+ " already been chained must be ignored ot not.\n"
+ " :type restrict_to_unvisited: bool\n"
+ " :arg begin: The ViewEdge from where to start the iteration.\n"
+ " :type begin: :class:`freestyle.types.ViewEdge` or None\n"
+ " :arg orientation: If true, we'll look for the next ViewEdge among\n"
+ " the ViewEdges that surround the ending ViewVertex of begin. If\n"
+ " false, we'll search over the ViewEdges surrounding the ending\n"
+ " ViewVertex of begin.\n"
+ " :type orientation: bool\n"
+ " :arg brother: A ChainPredicateIterator object.\n"
+ " :type brother: :class:`ChainPredicateIterator`");
static int check_begin(PyObject *obj, void *v)
{
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp
index d8ad82d667c..9fa84d5f6b8 100644
--- a/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp
@@ -48,9 +48,10 @@ PyDoc_STRVAR(ChainSilhouetteIterator_doc,
"precedence of the silhouette over the crease criterion.\n"
"\n"
".. method:: __init__(restrict_to_selection=True, begin=None, orientation=True)\n"
+ " __init__(brother)\n"
"\n"
" Builds a ChainSilhouetteIterator from the first ViewEdge used for\n"
- " iteration and its orientation.\n"
+ " iteration and its orientation or the copy constructor.\n"
"\n"
" :arg restrict_to_selection: Indicates whether to force the chaining\n"
" to stay within the set of selected ViewEdges or not.\n"
@@ -62,11 +63,6 @@ PyDoc_STRVAR(ChainSilhouetteIterator_doc,
" false, we'll search over the ViewEdges surrounding the ending\n"
" ViewVertex of begin.\n"
" :type orientation: bool\n"
- "\n"
- ".. method:: __init__(brother)\n"
- "\n"
- " Copy constructor.\n"
- "\n"
" :arg brother: A ChainSilhouetteIterator object.\n"
" :type brother: :class:`ChainSilhouetteIterator`");
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp
index dbd6e8dd09d..d24e1dc527d 100644
--- a/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp
@@ -46,11 +46,12 @@ PyDoc_STRVAR(
"they will be included in the adjacency iterator (i.e, the adjacent\n"
"iterator will only stop on \"valid\" edges).\n"
"\n"
- ".. method:: __init__(restrict_to_selection=True, restrict_to_unvisited=True, begin=None, "
- "orientation=True)\n"
+ ".. method:: __init__(restrict_to_selection=True, restrict_to_unvisited=True,"
+ " begin=None, orientation=True)\n"
+ " __init__(brother)\n"
"\n"
" Builds a Chaining Iterator from the first ViewEdge used for\n"
- " iteration and its orientation.\n"
+ " iteration and its orientation or by using the copy constructor.\n"
"\n"
" :arg restrict_to_selection: Indicates whether to force the chaining\n"
" to stay within the set of selected ViewEdges or not.\n"
@@ -63,11 +64,6 @@ PyDoc_STRVAR(
" :arg orientation: The direction to follow to explore the graph. If\n"
" true, the direction indicated by the first ViewEdge is used.\n"
" :type orientation: bool\n"
- "\n"
- ".. method:: __init__(brother)\n"
- "\n"
- " Copy constructor.\n"
- "\n"
" :arg brother: \n"
" :type brother: ChainingIterator");
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp
index 6c496b0308b..8eac657316e 100644
--- a/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp
@@ -39,20 +39,14 @@ PyDoc_STRVAR(CurvePointIterator_doc,
"through the .object attribute.\n"
"\n"
".. method:: __init__()\n"
+ " __init__(brother)\n"
+ " __init__(step=0.0)\n"
"\n"
- " Default constructor.\n"
- "\n"
- ".. method:: __init__(brother)\n"
- "\n"
- " Copy constructor.\n"
+ " Builds a CurvePointIterator object using either the default constructor,\n"
+ " copy constructor, or the overloaded constructor.\n"
"\n"
" :arg brother: A CurvePointIterator object.\n"
" :type brother: :class:`CurvePointIterator`\n"
- "\n"
- ".. method:: __init__(step=0.0)\n"
- "\n"
- " Builds a CurvePointIterator object.\n"
- "\n"
" :arg step: A resampling resolution with which the curve is resampled.\n"
" If zero, no resampling is done (i.e., the iterator iterates over\n"
" initial vertices).\n"
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp
index 734ed0117f4..f7afc7695ae 100644
--- a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp
@@ -38,17 +38,13 @@ PyDoc_STRVAR(Interface0DIterator_doc,
"this iterator is always obtained from a 1D element.\n"
"\n"
".. method:: __init__(brother)\n"
+ " __init__(it)\n"
"\n"
- " Copy constructor.\n"
+ " Construct a nested Interface0DIterator using either the copy constructor\n"
+ " or the constructor that takes an he argument of a Function0D.\n"
"\n"
" :arg brother: An Interface0DIterator object.\n"
" :type brother: :class:`Interface0DIterator`\n"
- "\n"
- ".. method:: __init__(it)\n"
- "\n"
- " Construct a nested Interface0DIterator that can be the argument of\n"
- " a Function0D.\n"
- "\n"
" :arg it: An iterator object to be nested.\n"
" :type it: :class:`SVertexIterator`, :class:`CurvePointIterator`, or\n"
" :class:`StrokeVertexIterator`");
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp
index 4a5927ff6eb..83c504081c1 100644
--- a/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp
@@ -32,39 +32,33 @@ extern "C" {
//------------------------INSTANCE METHODS ----------------------------------
-PyDoc_STRVAR(SVertexIterator_doc,
- "Class hierarchy: :class:`Iterator` > :class:`SVertexIterator`\n"
- "\n"
- "Class representing an iterator over :class:`SVertex` of a\n"
- ":class:`ViewEdge`. An instance of an SVertexIterator can be obtained\n"
- "from a ViewEdge by calling verticesBegin() or verticesEnd().\n"
- "\n"
- ".. method:: __init__()\n"
- "\n"
- " Default constructor.\n"
- "\n"
- ".. method:: __init__(brother)\n"
- "\n"
- " Copy constructor.\n"
- "\n"
- " :arg brother: An SVertexIterator object.\n"
- " :type brother: :class:`SVertexIterator`\n"
- "\n"
- ".. method:: __init__(vertex, begin, previous_edge, next_edge, t)\n"
- "\n"
- " Build an SVertexIterator that starts iteration from an SVertex\n"
- " object v.\n"
- "\n"
- " :arg vertex: The SVertex from which the iterator starts iteration.\n"
- " :type vertex: :class:`SVertex`\n"
- " :arg begin: The first SVertex of a ViewEdge.\n"
- " :type begin: :class:`SVertex`\n"
- " :arg previous_edge: The previous FEdge coming to vertex.\n"
- " :type previous_edge: :class:`FEdge`\n"
- " :arg next_edge: The next FEdge going out from vertex.\n"
- " :type next_edge: :class:`FEdge`\n"
- " :arg t: The curvilinear abscissa at vertex.\n"
- " :type t: float");
+PyDoc_STRVAR(
+ SVertexIterator_doc,
+ "Class hierarchy: :class:`Iterator` > :class:`SVertexIterator`\n"
+ "\n"
+ "Class representing an iterator over :class:`SVertex` of a\n"
+ ":class:`ViewEdge`. An instance of an SVertexIterator can be obtained\n"
+ "from a ViewEdge by calling verticesBegin() or verticesEnd().\n"
+ "\n"
+ ".. method:: __init__()\n"
+ " __init__(brother)\n"
+ " __init__(vertex, begin, previous_edge, next_edge, t)"
+ "\n"
+ " Build an SVertexIterator using either the default constructor, copy constructor,\n"
+ " or the overloaded constructor that starts iteration from an SVertex object vertex.\n"
+ "\n"
+ " :arg brother: An SVertexIterator object.\n"
+ " :type brother: :class:`SVertexIterator`\n"
+ " :arg vertex: The SVertex from which the iterator starts iteration.\n"
+ " :type vertex: :class:`SVertex`\n"
+ " :arg begin: The first SVertex of a ViewEdge.\n"
+ " :type begin: :class:`SVertex`\n"
+ " :arg previous_edge: The previous FEdge coming to vertex.\n"
+ " :type previous_edge: :class:`FEdge`\n"
+ " :arg next_edge: The next FEdge going out from vertex.\n"
+ " :type next_edge: :class:`FEdge`\n"
+ " :arg t: The curvilinear abscissa at vertex.\n"
+ " :type t: float");
static int SVertexIterator_init(BPy_SVertexIterator *self, PyObject *args, PyObject *kwds)
{
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp
index cda4031240b..e1b24e768e3 100644
--- a/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp
@@ -48,12 +48,10 @@ PyDoc_STRVAR(StrokeVertexIterator_doc,
"by calling Interface0DIterator(it).\n"
"\n"
".. method:: __init__()\n"
+ " __init__(brother)\n"
"\n"
- " Default constructor.\n"
- "\n"
- ".. method:: __init__(brother)\n"
- "\n"
- " Copy constructor.\n"
+ " Creates a :class:`StrokeVertexIterator` using either the\n"
+ " default constructor or the copy constructor.\n"
"\n"
" :arg brother: A StrokeVertexIterator object.\n"
" :type brother: :class:`StrokeVertexIterator`");
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp
index 3d0ed5d5a4d..20134057864 100644
--- a/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp
@@ -40,9 +40,10 @@ PyDoc_STRVAR(ViewEdgeIterator_doc,
"on a given ViewEdge.\n"
"\n"
".. method:: __init__(begin=None, orientation=True)\n"
+ " __init__(brother)\n"
"\n"
" Builds a ViewEdgeIterator from a starting ViewEdge and its\n"
- " orientation.\n"
+ " orientation or the copy constructor.\n"
"\n"
" :arg begin: The ViewEdge from where to start the iteration.\n"
" :type begin: :class:`ViewEdge` or None\n"
@@ -51,11 +52,6 @@ PyDoc_STRVAR(ViewEdgeIterator_doc,
" false, we'll search over the ViewEdges surrounding the ending\n"
" ViewVertex of begin.\n"
" :type orientation: bool\n"
- "\n"
- ".. method:: __init__(brother)\n"
- "\n"
- " Copy constructor.\n"
- "\n"
" :arg brother: A ViewEdgeIterator object.\n"
" :type brother: :class:`ViewEdgeIterator`");
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp
index fe6210468d1..30b7b3ccde5 100644
--- a/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp
@@ -39,12 +39,10 @@ PyDoc_STRVAR(orientedViewEdgeIterator_doc,
"obtained from a ViewVertex by calling edges_begin() or edges_end().\n"
"\n"
".. method:: __init__()\n"
+ " __init__(iBrother)\n"
"\n"
- " Default constructor.\n"
- "\n"
- ".. method:: __init__(iBrother)\n"
- "\n"
- " Copy constructor.\n"
+ " Creates an :class:`orientedViewEdgeIterator` using either the\n"
+ " default constructor or the copy constructor.\n"
"\n"
" :arg iBrother: An orientedViewEdgeIterator object.\n"
" :type iBrother: :class:`orientedViewEdgeIterator`");
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp
index 88705c41204..b59e27dcea9 100644
--- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp
@@ -160,13 +160,10 @@ static char UnaryFunction1DDouble___doc__[] =
":class:`Interface1D` and return a float value.\n"
"\n"
".. method:: __init__()\n"
+ " __init__(integration_type)\n"
"\n"
- " Default constructor.\n"
- "\n"
- ".. method:: __init__(integration_type)\n"
- "\n"
- " Builds a unary 1D function using the integration method given as\n"
- " argument.\n"
+ " Builds a unary 1D function using the default constructor\n"
+ " or the integration method given as an argument.\n"
"\n"
" :arg integration_type: An integration method.\n"
" :type integration_type: :class:`IntegrationType`\n";
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp
index 3cfc5464296..2f5a59f9c7a 100644
--- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp
@@ -65,13 +65,10 @@ static char UnaryFunction1DEdgeNature___doc__[] =
":class:`Interface1D` and return a :class:`Nature` object.\n"
"\n"
".. method:: __init__()\n"
+ " __init__(integration_type)\n"
"\n"
- " Default constructor.\n"
- "\n"
- ".. method:: __init__(integration_type)\n"
- "\n"
- " Builds a unary 1D function using the integration method given as\n"
- " argument.\n"
+ " Builds a unary 1D function using the default constructor\n"
+ " or the integration method given as an argument.\n"
"\n"
" :arg integration_type: An integration method.\n"
" :type integration_type: :class:`IntegrationType`\n";
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp
index 4fdc68a2e89..e11d21b6c8e 100644
--- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp
@@ -56,13 +56,10 @@ static char UnaryFunction1DFloat___doc__[] =
":class:`Interface1D` and return a float value.\n"
"\n"
".. method:: __init__()\n"
+ " __init__(integration_type)\n"
"\n"
- " Default constructor.\n"
- "\n"
- ".. method:: __init__(integration_type)\n"
- "\n"
- " Builds a unary 1D function using the integration method given as\n"
- " argument.\n"
+ " Builds a unary 1D function using the default constructor\n"
+ " or the integration method given as an argument.\n"
"\n"
" :arg integration_type: An integration method.\n"
" :type integration_type: :class:`IntegrationType`\n";
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp
index 218afa3ff10..e04a5b9d7f4 100644
--- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp
@@ -65,13 +65,10 @@ static char UnaryFunction1DUnsigned___doc__[] =
":class:`Interface1D` and return an int value.\n"
"\n"
".. method:: __init__()\n"
+ " __init__(integration_type)\n"
"\n"
- " Default constructor.\n"
- "\n"
- ".. method:: __init__(integration_type)\n"
- "\n"
- " Builds a unary 1D function using the integration method given as\n"
- " argument.\n"
+ " Builds a unary 1D function using the default constructor\n"
+ " or the integration method given as an argument.\n"
"\n"
" :arg integration_type: An integration method.\n"
" :type integration_type: :class:`IntegrationType`\n";
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp
index 939ccfb8905..f8d75640811 100644
--- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp
@@ -71,13 +71,10 @@ static char UnaryFunction1DVec2f___doc__[] =
":class:`Interface1D` and return a 2D vector.\n"
"\n"
".. method:: __init__()\n"
+ " __init__(integration_type)\n"
"\n"
- " Default constructor.\n"
- "\n"
- ".. method:: __init__(integration_type)\n"
- "\n"
- " Builds a unary 1D function using the integration method given as\n"
- " argument.\n"
+ " Builds a unary 1D function using the default constructor\n"
+ " or the integration method given as an argument.\n"
"\n"
" :arg integration_type: An integration method.\n"
" :type integration_type: :class:`IntegrationType`\n";
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp
index 02b6373cce4..9f71fb3840b 100644
--- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp
@@ -64,13 +64,10 @@ static char UnaryFunction1DVec3f___doc__[] =
":class:`Interface1D` and return a 3D vector.\n"
"\n"
".. method:: __init__()\n"
+ " __init__(integration_type)\n"
"\n"
- " Default constructor.\n"
- "\n"
- ".. method:: __init__(integration_type)\n"
- "\n"
- " Builds a unary 1D function using the integration method given as\n"
- " argument.\n"
+ " Builds a unary 1D function using the default constructor\n"
+ " or the integration method given as an argument.\n"
"\n"
" :arg integration_type: An integration method.\n"
" :type integration_type: :class:`IntegrationType`\n";
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp
index b2020e9f554..cb4982f4532 100644
--- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp
@@ -80,13 +80,10 @@ static char UnaryFunction1DVectorViewShape___doc__[] =
"objects.\n"
"\n"
".. method:: __init__()\n"
+ " __init__(integration_type)\n"
"\n"
- " Default constructor.\n"
- "\n"
- ".. method:: __init__(integration_type)\n"
- "\n"
- " Builds a unary 1D function using the integration method given as\n"
- " argument.\n"
+ " Builds a unary 1D function using the default constructor\n"
+ " or the integration method given as an argument.\n"
"\n"
" :arg integration_type: An integration method.\n"
" :type integration_type: :class:`IntegrationType`\n";
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp
index 7b25daa24f9..46564cdaeca 100644
--- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp
@@ -79,13 +79,10 @@ static char UnaryFunction1DVoid___doc__[] =
":class:`Interface1D`.\n"
"\n"
".. method:: __init__()\n"
+ " __init__(integration_type)\n"
"\n"
- " Default constructor.\n"
- "\n"
- ".. method:: __init__(integration_type)\n"
- "\n"
- " Builds a unary 1D function using the integration method given as\n"
- " argument.\n"
+ " Builds a unary 1D function using either a default constructor\n"
+ " or the integration method given as an argument.\n"
"\n"
" :arg integration_type: An integration method.\n"
" :type integration_type: :class:`IntegrationType`\n";
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c
index 6eb12974408..8f17be97710 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c
@@ -101,6 +101,11 @@ static void deformStroke(GpencilModifierData *md,
}
BKE_gpencil_stroke_subdivide(gps, mmd->level, mmd->type);
+
+ /* If the stroke is cyclic, must generate the closing geometry. */
+ if (gps->flag & GP_STROKE_CYCLIC) {
+ BKE_gpencil_stroke_close(gps);
+ }
}
static void bakeModifier(struct Main *UNUSED(bmain),
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
index 3708b8b0531..3bd578e1ffc 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
@@ -450,7 +450,7 @@ void node_bsdf_principled_glass(vec4 base_color,
eevee_closure_glass(N,
vec3(1.0),
- vec3(1.0),
+ vec3((use_multiscatter != 0.0) ? 1.0 : -1.0),
int(ssr_id),
roughness,
1.0,
diff --git a/source/blender/imbuf/intern/util_gpu.c b/source/blender/imbuf/intern/util_gpu.c
index 2826bd63cc1..607ab95f0b4 100644
--- a/source/blender/imbuf/intern/util_gpu.c
+++ b/source/blender/imbuf/intern/util_gpu.c
@@ -97,6 +97,7 @@ static void *imb_gpu_get_data(const ImBuf *ibuf,
{
const bool is_float_rect = (ibuf->rect_float != NULL);
void *data_rect = (is_float_rect) ? (void *)ibuf->rect_float : (void *)ibuf->rect;
+ bool freedata = false;
if (is_float_rect) {
/* Float image is already in scene linear colorspace or non-color data by
@@ -104,7 +105,7 @@ static void *imb_gpu_get_data(const ImBuf *ibuf,
* currently. */
if (ibuf->channels != 4 || !store_premultiplied) {
data_rect = MEM_mallocN(sizeof(float[4]) * ibuf->x * ibuf->y, __func__);
- *r_freedata = true;
+ *r_freedata = freedata = true;
if (data_rect == NULL) {
return NULL;
@@ -124,7 +125,7 @@ static void *imb_gpu_get_data(const ImBuf *ibuf,
* and consistency with float images. */
if (!IMB_colormanagement_space_is_data(ibuf->rect_colorspace)) {
data_rect = MEM_mallocN(sizeof(uchar[4]) * ibuf->x * ibuf->y, __func__);
- *r_freedata = true;
+ *r_freedata = freedata = true;
if (data_rect == NULL) {
return NULL;
@@ -147,6 +148,10 @@ static void *imb_gpu_get_data(const ImBuf *ibuf,
ImBuf *scale_ibuf = IMB_allocFromBuffer(rect, rect_float, ibuf->x, ibuf->y, 4);
IMB_scaleImBuf(scale_ibuf, UNPACK2(rescale_size));
+ if (freedata) {
+ MEM_freeN(data_rect);
+ }
+
data_rect = (is_float_rect) ? (void *)scale_ibuf->rect_float : (void *)scale_ibuf->rect;
*r_freedata = true;
/* Steal the rescaled buffer to avoid double free. */
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index 37b7947dbea..713f5ee2afa 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -775,6 +775,7 @@ typedef enum eBrushFlags2 {
BRUSH_POSE_USE_LOCK_ROTATION = (1 << 5),
BRUSH_CLOTH_USE_COLLISION = (1 << 6),
BRUSH_AREA_RADIUS_PRESSURE = (1 << 7),
+ BRUSH_GRAB_SILHOUETTE = (1 << 8),
} eBrushFlags2;
typedef enum {
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index 92ee3f062a6..c95e5376670 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -690,8 +690,10 @@ typedef enum eBConstraint_Types {
/* flag 0x20 (1 << 5) was used to indicate that a constraint was evaluated
* using a 'local' hack for posebones only. */
typedef enum eBConstraint_Flags {
+#ifdef DNA_DEPRECATED_ALLOW
/* Expansion for old box constraint layouts. Just for versioning. */
CONSTRAINT_EXPAND_DEPRECATED = (1 << 0),
+#endif
/* pre-check for illegal object name or bone name */
CONSTRAINT_DISABLE = (1 << 2),
/* to indicate which Ipo should be shown, maybe for 3d access later too */
diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h
index 7e2ec8b6c65..3a9f9bd7b66 100644
--- a/source/blender/makesdna/DNA_gpencil_modifier_types.h
+++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h
@@ -57,7 +57,9 @@ typedef enum GpencilModifierMode {
eGpencilModifierMode_Realtime = (1 << 0),
eGpencilModifierMode_Render = (1 << 1),
eGpencilModifierMode_Editmode = (1 << 2),
+#ifdef DNA_DEPRECATED_ALLOW
eGpencilModifierMode_Expanded_DEPRECATED = (1 << 3),
+#endif
eGpencilModifierMode_Virtual = (1 << 4),
} GpencilModifierMode;
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index e2837ba85f8..a822a6723fa 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -48,7 +48,6 @@ struct MPropCol;
struct MVert;
struct Material;
struct Mesh;
-struct Multires;
struct SubdivCCG;
#
@@ -230,9 +229,6 @@ typedef struct Mesh {
* default and Face Sets can be used without affecting the color of the mesh. */
int face_sets_color_default;
- /** Deprecated multiresolution modeling data, only keep for loading old files. */
- struct Multires *mr DNA_DEPRECATED;
-
Mesh_Runtime runtime;
} Mesh;
diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h
index 45bf6e8c282..7cc94a2ad0b 100644
--- a/source/blender/makesdna/DNA_meshdata_types.h
+++ b/source/blender/makesdna/DNA_meshdata_types.h
@@ -518,54 +518,4 @@ typedef struct MRecast {
int i;
} MRecast;
-/** Multires structs kept for compatibility with old files. */
-typedef struct MultiresCol {
- float a, r, g, b;
-} MultiresCol;
-
-typedef struct MultiresColFace {
- /* vertex colors */
- MultiresCol col[4];
-} MultiresColFace;
-
-typedef struct MultiresFace {
- unsigned int v[4];
- unsigned int mid;
- char flag, mat_nr, _pad[2];
-} MultiresFace;
-
-typedef struct MultiresEdge {
- unsigned int v[2];
- unsigned int mid;
-} MultiresEdge;
-
-typedef struct MultiresLevel {
- struct MultiresLevel *next, *prev;
-
- MultiresFace *faces;
- MultiresColFace *colfaces;
- MultiresEdge *edges;
-
- unsigned int totvert, totface, totedge;
- char _pad[4];
-
- /* Kept for compatibility with even older files */
- MVert *verts;
-} MultiresLevel;
-
-typedef struct Multires {
- ListBase levels;
- MVert *verts;
-
- unsigned char level_count, current, newlvl, edgelvl, pinlvl, renderlvl;
- unsigned char use_col, flag;
-
- /* Special level 1 data that cannot be modified from other levels */
- CustomData vdata;
- CustomData fdata;
- short *edge_flags;
- char *edge_creases;
-} Multires;
-/* End multi-res structs. */
-
/** \} */
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 3df80e1157d..414c21fd428 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -106,8 +106,10 @@ typedef enum ModifierMode {
eModifierMode_Render = (1 << 1),
eModifierMode_Editmode = (1 << 2),
eModifierMode_OnCage = (1 << 3),
- /* Old modifier box expansion, just for versioning. */
+#ifdef DNA_DEPRECATED_ALLOW
+ /** Old modifier box expansion, just for versioning. */
eModifierMode_Expanded_DEPRECATED = (1 << 4),
+#endif
eModifierMode_Virtual = (1 << 5),
eModifierMode_ApplyOnSpline = (1 << 6),
eModifierMode_DisableTemporary = (1u << 31),
diff --git a/source/blender/makesdna/DNA_shader_fx_types.h b/source/blender/makesdna/DNA_shader_fx_types.h
index 5bb78edb280..5567d65b6db 100644
--- a/source/blender/makesdna/DNA_shader_fx_types.h
+++ b/source/blender/makesdna/DNA_shader_fx_types.h
@@ -49,7 +49,9 @@ typedef enum ShaderFxMode {
eShaderFxMode_Realtime = (1 << 0),
eShaderFxMode_Render = (1 << 1),
eShaderFxMode_Editmode = (1 << 2),
+#ifdef DNA_DEPRECATED_ALLOW
eShaderFxMode_Expanded_DEPRECATED = (1 << 3),
+#endif
} ShaderFxMode;
typedef enum {
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index ad032a6d7b6..4a02ac8f429 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -633,10 +633,9 @@ typedef struct UserDef_Experimental {
char use_new_hair_type;
char use_new_point_cloud_type;
char use_sculpt_vertex_colors;
- char use_tools_missing_icons;
char use_switch_object_operator;
char use_sculpt_tools_tilt;
- char _pad[6];
+ char _pad[7];
/** `makesdna` does not allow empty structs. */
} UserDef_Experimental;
diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h
index 3f7e3e61d56..4b4e17b38bd 100644
--- a/source/blender/makesdna/DNA_windowmanager_types.h
+++ b/source/blender/makesdna/DNA_windowmanager_types.h
@@ -383,6 +383,19 @@ enum {
KMI_EXPANDED = (1 << 1),
KMI_USER_MODIFIED = (1 << 2),
KMI_UPDATE = (1 << 3),
+ /**
+ * When set, ignore events with #wmEvent.is_repeat enabled.
+ *
+ * \note this flag isn't cleared when editing/loading the key-map items,
+ * so it may be set in cases which don't make sense (modifier-keys or mouse-motion for example).
+ *
+ * Knowing if an event may repeat is something set at the operating-systems event handling level
+ * so rely on #wmEvent.is_repeat being false non keyboard events instead of checking if this
+ * flag makes sense.
+ *
+ * Only used when: `ISKEYBOARD(kmi->type) || (kmi->type == KM_TEXTINPUT)`
+ * as mouse, 3d-mouse, timer... etc never repeat.
+ */
KMI_REPEAT_IGNORE = (1 << 4),
};
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index d119be66916..6f227ec210c 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -2968,6 +2968,12 @@ static void rna_def_brush(BlenderRNA *brna)
"Apply the maximum grab strength to the active vertex instead of the cursor location");
RNA_def_property_update(prop, 0, "rna_Brush_update");
+ prop = RNA_def_property(srna, "use_grab_silhouette", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag2", BRUSH_GRAB_SILHOUETTE);
+ RNA_def_property_ui_text(
+ prop, "Grab Silhouette", "Grabs trying to automask the silhouette of the object");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
prop = RNA_def_property(srna, "use_paint_antialiasing", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "sampling_flag", BRUSH_PAINT_ANTIALIASING);
RNA_def_property_ui_text(prop, "Anti-Aliasing", "Smooths the edges of the strokes");
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index 653056e4dc1..76b419926a1 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -512,6 +512,17 @@ static void rna_Constraint_influence_update(Main *bmain, Scene *scene, PointerRN
rna_Constraint_update(bmain, scene, ptr);
}
+/* Update only needed so this isn't overwritten on first evaluation. */
+static void rna_Constraint_childof_inverse_matrix_update(Main *bmain,
+ Scene *scene,
+ PointerRNA *ptr)
+{
+ bConstraint *con = ptr->data;
+ bChildOfConstraint *data = con->data;
+ data->flag &= ~CHILDOF_SET_INVERSE;
+ rna_Constraint_update(bmain, scene, ptr);
+}
+
static void rna_Constraint_ik_type_set(struct PointerRNA *ptr, int value)
{
bConstraint *con = ptr->data;
@@ -999,7 +1010,8 @@ static void rna_def_constraint_childof(BlenderRNA *brna)
RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Inverse Matrix", "Transformation matrix to apply before");
- RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+ RNA_def_property_update(
+ prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_childof_inverse_matrix_update");
RNA_define_lib_overridable(false);
}
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 061026288e6..c31766efe58 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -6175,10 +6175,6 @@ static void rna_def_userdef_experimental(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Switch Object Operator", "Enable the operator to switch objects by pressing D");
- prop = RNA_def_property(srna, "use_tools_missing_icons", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "use_tools_missing_icons", 1);
- RNA_def_property_ui_text(prop, "Tools with Missing Icons", "Show tools with missing icons");
-
prop = RNA_def_property(srna, "use_sculpt_tools_tilt", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_sculpt_tools_tilt", 1);
RNA_def_property_ui_text(
diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c
index 47d5e9b6313..2c373eb8d46 100644
--- a/source/blender/makesrna/intern/rna_wm_api.c
+++ b/source/blender/makesrna/intern/rna_wm_api.c
@@ -632,6 +632,7 @@ static wmEvent *rna_Window_event_add_simulate(wmWindow *win,
wmEvent e = *win->eventstate;
e.type = type;
e.val = value;
+ e.is_repeat = false;
e.x = x;
e.y = y;
/* Note: KM_MOD_FIRST, KM_MOD_SECOND aren't used anywhere, set as bools */
@@ -1134,7 +1135,7 @@ void RNA_api_keymapitems(StructRNA *srna)
RNA_def_boolean(func, "alt", 0, "Alt", "");
RNA_def_boolean(func, "oskey", 0, "OS Key", "");
RNA_def_enum(func, "key_modifier", rna_enum_event_type_items, 0, "Key Modifier", "");
- RNA_def_boolean(func, "repeat", true, "Repeat", "When set, accept key-repeat events");
+ RNA_def_boolean(func, "repeat", false, "Repeat", "When set, accept key-repeat events");
RNA_def_boolean(func,
"head",
0,
@@ -1158,7 +1159,7 @@ void RNA_api_keymapitems(StructRNA *srna)
RNA_def_boolean(func, "alt", 0, "Alt", "");
RNA_def_boolean(func, "oskey", 0, "OS Key", "");
RNA_def_enum(func, "key_modifier", rna_enum_event_type_items, 0, "Key Modifier", "");
- RNA_def_boolean(func, "repeat", true, "Repeat", "When set, accept key-repeat events");
+ RNA_def_boolean(func, "repeat", false, "Repeat", "When set, accept key-repeat events");
parm = RNA_def_pointer(func, "item", "KeyMapItem", "Item", "Added key map item");
RNA_def_function_return(func, parm);
diff --git a/source/blender/makesrna/intern/rna_wm_gizmo.c b/source/blender/makesrna/intern/rna_wm_gizmo.c
index 971991869e2..27d46e4d25b 100644
--- a/source/blender/makesrna/intern/rna_wm_gizmo.c
+++ b/source/blender/makesrna/intern/rna_wm_gizmo.c
@@ -61,6 +61,8 @@
# include "MEM_guardedalloc.h"
+# include "GPU_state.h"
+
# ifdef WITH_PYTHON
# include "BPY_extern.h"
# endif
@@ -84,6 +86,8 @@ static void rna_gizmo_draw_cb(const struct bContext *C, struct wmGizmo *gz)
RNA_parameter_set_lookup(&list, "context", &C);
gzgroup->type->rna_ext.call((bContext *)C, &gz_ptr, func, &list);
RNA_parameter_list_free(&list);
+ /* This callback may have called bgl functions. */
+ GPU_bgl_end();
}
static void rna_gizmo_draw_select_cb(const struct bContext *C, struct wmGizmo *gz, int select_id)
@@ -101,6 +105,8 @@ static void rna_gizmo_draw_select_cb(const struct bContext *C, struct wmGizmo *g
RNA_parameter_set_lookup(&list, "select_id", &select_id);
gzgroup->type->rna_ext.call((bContext *)C, &gz_ptr, func, &list);
RNA_parameter_list_free(&list);
+ /* This callback may have called bgl functions. */
+ GPU_bgl_end();
}
static int rna_gizmo_test_select_cb(struct bContext *C, struct wmGizmo *gz, const int location[2])
diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c
index 94dc8a8c43b..17d716b731c 100644
--- a/source/blender/modifiers/intern/MOD_datatransfer.c
+++ b/source/blender/modifiers/intern/MOD_datatransfer.c
@@ -268,7 +268,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
- uiItemO(layout, "Generate Data Layers", ICON_NONE, "OBJECT_OT_datalayout_transfer");
+ uiItemO(layout, IFACE_("Generate Data Layers"), ICON_NONE, "OBJECT_OT_datalayout_transfer");
modifier_panel_end(layout, ptr);
}
diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c
index def72af45e8..e0c362171f2 100644
--- a/source/blender/modifiers/intern/MOD_hook.c
+++ b/source/blender/modifiers/intern/MOD_hook.c
@@ -492,11 +492,11 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
if (RNA_enum_get(&ob_ptr, "mode") == OB_MODE_EDIT) {
row = uiLayoutRow(layout, true);
- uiItemO(row, "Reset", ICON_NONE, "OBJECT_OT_hook_reset");
- uiItemO(row, "Recenter", ICON_NONE, "OBJECT_OT_hook_recenter");
+ uiItemO(row, IFACE_("Reset"), ICON_NONE, "OBJECT_OT_hook_reset");
+ uiItemO(row, IFACE_("Recenter"), ICON_NONE, "OBJECT_OT_hook_recenter");
row = uiLayoutRow(layout, true);
- uiItemO(row, "Select", ICON_NONE, "OBJECT_OT_hook_select");
- uiItemO(row, "Assign", ICON_NONE, "OBJECT_OT_hook_assign");
+ uiItemO(row, IFACE_("Select"), ICON_NONE, "OBJECT_OT_hook_select");
+ uiItemO(row, IFACE_("Assign"), ICON_NONE, "OBJECT_OT_hook_assign");
}
modifier_panel_end(layout, ptr);
diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c
index c4f0fff72dd..8886d3718c9 100644
--- a/source/blender/modifiers/intern/MOD_solidify.c
+++ b/source/blender/modifiers/intern/MOD_solidify.c
@@ -230,8 +230,9 @@ static void vertex_group_panel_draw(const bContext *UNUSED(C), Panel *panel)
uiLayoutSetPropSep(layout, true);
col = uiLayoutColumn(layout, false);
- uiItemPointerR(col, ptr, "shell_vertex_group", &ob_ptr, "vertex_groups", "Shell", ICON_NONE);
- uiItemPointerR(col, ptr, "rim_vertex_group", &ob_ptr, "vertex_groups", "Rim", ICON_NONE);
+ uiItemPointerR(
+ col, ptr, "shell_vertex_group", &ob_ptr, "vertex_groups", IFACE_("Shell"), ICON_NONE);
+ uiItemPointerR(col, ptr, "rim_vertex_group", &ob_ptr, "vertex_groups", IFACE_("Rim"), ICON_NONE);
}
static void panelRegister(ARegionType *region_type)
diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c
index 554ab2645a7..a580b4f10f0 100644
--- a/source/blender/python/intern/bpy_app.c
+++ b/source/blender/python/intern/bpy_app.c
@@ -82,6 +82,7 @@ static PyTypeObject BlenderAppType;
static PyStructSequence_Field app_info_fields[] = {
{"version", "The Blender version as a tuple of 3 numbers. eg. (2, 83, 1)"},
+ {"version_file", "The blend file version, compatible with ``bpy.data.version``"},
{"version_string", "The Blender version formatted as a string"},
{"version_cycle", "The release status of this build alpha/beta/rc/release"},
{"version_char", "Deprecated, always an empty string"},
@@ -151,6 +152,8 @@ static PyObject *make_app_info(void)
SetObjItem(
PyC_Tuple_Pack_I32(BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_VERSION_PATCH));
+ SetObjItem(PyC_Tuple_Pack_I32(
+ BLENDER_FILE_VERSION / 100, BLENDER_FILE_VERSION % 100, BLENDER_FILE_SUBVERSION));
SetStrItem(BKE_blender_version_string());
SetStrItem(STRINGIFY(BLENDER_VERSION_CYCLE));
diff --git a/source/blender/python/mathutils/mathutils_noise.c b/source/blender/python/mathutils/mathutils_noise.c
index eece782f6d0..49a3f114ebb 100644
--- a/source/blender/python/mathutils/mathutils_noise.c
+++ b/source/blender/python/mathutils/mathutils_noise.c
@@ -140,11 +140,11 @@ static void next_state(void)
left = N;
next = state;
- for (j = N - M + 1; j--; p++) {
+ for (j = N - M + 1; --j; p++) {
*p = p[M] ^ TWIST(p[0], p[1]);
}
- for (j = M; j--; p++) {
+ for (j = M; --j; p++) {
*p = p[M - N] ^ TWIST(p[0], p[1]);
}
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index b23446e0dce..a8d24205268 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -503,6 +503,9 @@ typedef struct wmGesture {
/** For gestures that support snapping, stores if snapping is enabled using the modal keymap
* toggle. */
uint use_snap : 1;
+ /** For gestures that support flip, stores if flip is enabled using the modal keymap
+ * toggle. */
+ uint use_flip : 1;
/**
* customdata
@@ -556,7 +559,12 @@ typedef struct wmEvent {
/** From ghost, fallback if utf8 isn't set. */
char ascii;
- /** Generated by auto-repeat. */
+ /**
+ * Generated by auto-repeat, note that this must only ever be set for keyboard events
+ * where `ISKEYBOARD(event->type) == true`.
+ *
+ * See #KMI_REPEAT_IGNORE for details on how key-map handling uses this.
+ */
char is_repeat;
/** Previous state, used for double click and the 'click'. */
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index e6ec68f706c..8eb9a3b0650 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -155,6 +155,15 @@ wmEvent *WM_event_add_simulate(wmWindow *win, const wmEvent *event_to_add)
void wm_event_free(wmEvent *event)
{
+#ifndef NDEBUG
+ /* Don't use assert here because it's fairly harmless in most cases,
+ * more an issue of correctness, something we should avoid in general. */
+ if (event->is_repeat && !ISKEYBOARD(event->type)) {
+ printf("%s: 'is_repeat=true' for non-keyboard event, this should not happen.\n", __func__);
+ WM_event_print(event);
+ }
+#endif
+
if (event->customdata) {
if (event->customdatafree) {
/* Note: pointer to listbase struct elsewhere. */
@@ -3402,6 +3411,7 @@ void wm_event_do_handlers(bContext *C)
tevent.type = MOUSEMOVE;
tevent.prevx = tevent.x;
tevent.prevy = tevent.y;
+ tevent.is_repeat = false;
wm_event_add(win, &tevent);
win->addmousemove = 0;
}
diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c
index ae8b78876c2..4c1b403ac96 100644
--- a/source/blender/windowmanager/intern/wm_gesture.c
+++ b/source/blender/windowmanager/intern/wm_gesture.c
@@ -200,7 +200,7 @@ int wm_gesture_evaluate(wmGesture *gesture, const wmEvent *event)
/* ******************* gesture draw ******************* */
-static void wm_gesture_draw_line_active_side(rcti *rect)
+static void wm_gesture_draw_line_active_side(rcti *rect, const bool flip)
{
GPUVertFormat *format = immVertexFormat();
uint shdr_pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
@@ -222,7 +222,9 @@ static void wm_gesture_draw_line_active_side(rcti *rect)
sub_v2_v2v2(line_dir, line_end, line_start);
normalize_v2(line_dir);
ortho_v2_v2(gradient_dir, line_dir);
- mul_v2_fl(gradient_dir, -1.0f);
+ if (!flip) {
+ mul_v2_fl(gradient_dir, -1.0f);
+ }
mul_v2_fl(gradient_dir, gradient_length);
add_v2_v2v2(gradient_point[0], line_start, gradient_dir);
add_v2_v2v2(gradient_point[1], line_end, gradient_dir);
@@ -252,7 +254,7 @@ static void wm_gesture_draw_line(wmGesture *gt)
rcti *rect = (rcti *)gt->customdata;
if (gt->draw_active_side) {
- wm_gesture_draw_line_active_side(rect);
+ wm_gesture_draw_line_active_side(rect, gt->use_flip);
}
uint shdr_pos = GPU_vertformat_attr_add(
diff --git a/source/blender/windowmanager/intern/wm_gesture_ops.c b/source/blender/windowmanager/intern/wm_gesture_ops.c
index 00112e82771..edf9a3bc693 100644
--- a/source/blender/windowmanager/intern/wm_gesture_ops.c
+++ b/source/blender/windowmanager/intern/wm_gesture_ops.c
@@ -851,6 +851,7 @@ static bool gesture_straightline_apply(bContext *C, wmOperator *op)
RNA_int_set(op->ptr, "ystart", rect->ymin);
RNA_int_set(op->ptr, "xend", rect->xmax);
RNA_int_set(op->ptr, "yend", rect->ymax);
+ RNA_boolean_set(op->ptr, "flip", gesture->use_flip);
if (op->type->exec) {
int retval = op->type->exec(C, op);
@@ -892,6 +893,7 @@ int WM_gesture_straightline_active_side_invoke(bContext *C, wmOperator *op, cons
WM_gesture_straightline_invoke(C, op, event);
wmGesture *gesture = op->customdata;
gesture->draw_active_side = true;
+ gesture->use_flip = false;
return OPERATOR_RUNNING_MODAL;
}
@@ -950,6 +952,11 @@ int WM_gesture_straightline_modal(bContext *C, wmOperator *op, const wmEvent *ev
gesture->use_snap = !gesture->use_snap;
break;
}
+ case GESTURE_MODAL_FLIP: {
+ /* Toggle snapping on/off. */
+ gesture->use_flip = !gesture->use_flip;
+ break;
+ }
case GESTURE_MODAL_SELECT: {
if (gesture_straightline_apply(C, op)) {
gesture_modal_end(C, op);
@@ -1029,6 +1036,11 @@ int WM_gesture_straightline_oneshot_modal(bContext *C, wmOperator *op, const wmE
gesture->use_snap = !gesture->use_snap;
break;
}
+ case GESTURE_MODAL_FLIP: {
+ /* Toggle flip on/off. */
+ gesture->use_flip = !gesture->use_flip;
+ break;
+ }
case GESTURE_MODAL_SELECT:
case GESTURE_MODAL_DESELECT:
case GESTURE_MODAL_IN:
diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c
index 78d8fc9a20d..62294d70306 100644
--- a/source/blender/windowmanager/intern/wm_operator_props.c
+++ b/source/blender/windowmanager/intern/wm_operator_props.c
@@ -498,6 +498,8 @@ void WM_operator_properties_gesture_straightline(wmOperatorType *ot, int cursor)
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_int(ot->srna, "yend", 0, INT_MIN, INT_MAX, "Y End", "", INT_MIN, INT_MAX);
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "flip", false, "Flip", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
if (cursor) {
prop = RNA_def_int(ot->srna,
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 5e4a45ea3be..613de5a9b17 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -3807,6 +3807,7 @@ static void gesture_straightline_modal_keymap(wmKeyConfig *keyconf)
{GESTURE_MODAL_BEGIN, "BEGIN", 0, "Begin", ""},
{GESTURE_MODAL_MOVE, "MOVE", 0, "Move", ""},
{GESTURE_MODAL_SNAP, "SNAP", 0, "Snap", ""},
+ {GESTURE_MODAL_FLIP, "FLIP", 0, "Flip", ""},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h
index 21662a4e83a..223f6cf543d 100644
--- a/source/blender/windowmanager/wm_event_types.h
+++ b/source/blender/windowmanager/wm_event_types.h
@@ -496,6 +496,9 @@ enum {
/** Toggle to activate snapping (angle snapping for straight line). */
GESTURE_MODAL_SNAP = 13,
+
+ /** Toggle to activate flip (flip the active side of a straight line). */
+ GESTURE_MODAL_FLIP = 14,
};
#ifdef __cplusplus
diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c
index 47ab96bbc7e..3b54811657d 100644
--- a/source/creator/creator_args.c
+++ b/source/creator/creator_args.c
@@ -48,6 +48,7 @@
# include "BKE_blender_version.h"
# include "BKE_context.h"
+# include "BKE_appdir.h"
# include "BKE_global.h"
# include "BKE_image.h"
# include "BKE_lib_id.h"
@@ -56,9 +57,7 @@
# include "BKE_scene.h"
# include "BKE_sound.h"
-# ifdef WITH_FFMPEG
-# include "IMB_imbuf.h"
-# endif
+# include "IMB_imbuf.h"
# ifdef WITH_PYTHON
# include "BPY_extern_python.h"
@@ -1205,6 +1204,8 @@ static int arg_handle_playback_mode(int argc, const char **argv, void *UNUSED(da
{
/* not if -b was given first */
if (G.background == 0) {
+ BKE_appdir_init();
+ IMB_init();
# ifdef WITH_FFMPEG
/* Setup FFmpeg with current debug flags. */
IMB_ffmpeg_init();