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:
authorCampbell Barton <ideasman42@gmail.com>2016-07-18 12:25:44 +0300
committerCampbell Barton <ideasman42@gmail.com>2016-07-18 12:25:44 +0300
commit9186b9ae4806f4bbc1a14417c408e844f8e8cc1a (patch)
tree117bbd4ace75825e3a65f0ba2a447509bde0df85 /source
parentcfbd605567f48229a923df382baf6db98fbafc61 (diff)
parent9946cca14676bf07b3c7c103e99033fe1e4e423e (diff)
Merge branch 'master' into blender2.8
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_action.h2
-rw-r--r--source/blender/blenkernel/BKE_armature.h2
-rw-r--r--source/blender/blenkernel/BKE_brush.h2
-rw-r--r--source/blender/blenkernel/BKE_camera.h2
-rw-r--r--source/blender/blenkernel/BKE_curve.h2
-rw-r--r--source/blender/blenkernel/BKE_icons.h2
-rw-r--r--source/blender/blenkernel/BKE_image.h2
-rw-r--r--source/blender/blenkernel/BKE_key.h1
-rw-r--r--source/blender/blenkernel/BKE_lamp.h2
-rw-r--r--source/blender/blenkernel/BKE_lattice.h2
-rw-r--r--source/blender/blenkernel/BKE_library.h2
-rw-r--r--source/blender/blenkernel/BKE_material.h2
-rw-r--r--source/blender/blenkernel/BKE_mball.h2
-rw-r--r--source/blender/blenkernel/BKE_mesh.h2
-rw-r--r--source/blender/blenkernel/BKE_node.h2
-rw-r--r--source/blender/blenkernel/BKE_object.h4
-rw-r--r--source/blender/blenkernel/BKE_speaker.h2
-rw-r--r--source/blender/blenkernel/BKE_texture.h2
-rw-r--r--source/blender/blenkernel/BKE_world.h2
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf_util.c2
-rw-r--r--source/blender/blenkernel/intern/action.c6
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c10
-rw-r--r--source/blender/blenkernel/intern/armature.c6
-rw-r--r--source/blender/blenkernel/intern/armature_update.c2
-rw-r--r--source/blender/blenkernel/intern/brush.c8
-rw-r--r--source/blender/blenkernel/intern/camera.c6
-rw-r--r--source/blender/blenkernel/intern/curve.c9
-rw-r--r--source/blender/blenkernel/intern/icons.c57
-rw-r--r--source/blender/blenkernel/intern/image.c11
-rw-r--r--source/blender/blenkernel/intern/key.c12
-rw-r--r--source/blender/blenkernel/intern/lamp.c6
-rw-r--r--source/blender/blenkernel/intern/lattice.c9
-rw-r--r--source/blender/blenkernel/intern/library.c61
-rw-r--r--source/blender/blenkernel/intern/material.c6
-rw-r--r--source/blender/blenkernel/intern/mball.c6
-rw-r--r--source/blender/blenkernel/intern/mesh.c14
-rw-r--r--source/blender/blenkernel/intern/node.c7
-rw-r--r--source/blender/blenkernel/intern/object.c6
-rw-r--r--source/blender/blenkernel/intern/object_update.c7
-rw-r--r--source/blender/blenkernel/intern/scene.c2
-rw-r--r--source/blender/blenkernel/intern/seqeffects.c44
-rw-r--r--source/blender/blenkernel/intern/sequencer.c34
-rw-r--r--source/blender/blenkernel/intern/speaker.c6
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c2
-rw-r--r--source/blender/blenkernel/intern/texture.c6
-rw-r--r--source/blender/blenkernel/intern/world.c6
-rw-r--r--source/blender/blenlib/BLI_threads.h2
-rw-r--r--source/blender/blenlib/intern/BLI_heap.c129
-rw-r--r--source/blender/blenloader/intern/readfile.c76
-rw-r--r--source/blender/blenloader/intern/readfile.h2
-rw-r--r--source/blender/blenloader/intern/versioning_270.c13
-rw-r--r--source/blender/blenloader/intern/writefile.c8
-rw-r--r--source/blender/bmesh/operators/bmo_connect_pair.c2
-rw-r--r--source/blender/bmesh/operators/bmo_normals.c2
-rw-r--r--source/blender/collada/DocumentImporter.cpp36
-rw-r--r--source/blender/collada/EffectExporter.cpp7
-rw-r--r--source/blender/collada/ErrorHandler.cpp2
-rw-r--r--source/blender/collada/collada_utils.cpp4
-rw-r--r--source/blender/compositor/operations/COM_MaskOperation.cpp1
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc19
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc16
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_flush.cc3
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node.cc5
-rw-r--r--source/blender/editors/armature/armature_utils.c12
-rw-r--r--source/blender/editors/include/ED_keyframing.h8
-rw-r--r--source/blender/editors/include/ED_view3d.h2
-rw-r--r--source/blender/editors/interface/interface.c2
-rw-r--r--source/blender/editors/interface/interface_handlers.c170
-rw-r--r--source/blender/editors/interface/interface_icons.c30
-rw-r--r--source/blender/editors/interface/interface_ops.c2
-rw-r--r--source/blender/editors/interface/interface_regions.c2
-rw-r--r--source/blender/editors/interface/interface_templates.c4
-rw-r--r--source/blender/editors/mesh/editmesh_intersect.c2
-rw-r--r--source/blender/editors/mesh/editmesh_rip.c2
-rw-r--r--source/blender/editors/object/object_group.c2
-rw-r--r--source/blender/editors/object/object_relations.c10
-rw-r--r--source/blender/editors/object/object_select.c1
-rw-r--r--source/blender/editors/object/object_vgroup.c6
-rw-r--r--source/blender/editors/render/render_internal.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c8
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c29
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c10
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c25
-rw-r--r--source/blender/editors/space_clip/clip_editor.c2
-rw-r--r--source/blender/editors/space_graph/graph_draw.c2
-rw-r--r--source/blender/editors/space_image/image_ops.c172
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c194
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c19
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h1
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_project.c55
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c68
-rw-r--r--source/blender/editors/transform/transform_snap_object.c1316
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c2
-rw-r--r--source/blender/gpu/intern/gpu_draw.c2
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c7
-rw-r--r--source/blender/gpu/intern/gpu_material.c3
-rw-r--r--source/blender/makesdna/DNA_cloth_types.h2
-rw-r--r--source/blender/makesdna/DNA_genfile.h20
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h16
-rw-r--r--source/blender/makesdna/DNA_sdna_types.h11
-rw-r--r--source/blender/makesdna/intern/CMakeLists.txt2
-rw-r--r--source/blender/makesdna/intern/dna_genfile.c307
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt3
-rw-r--r--source/blender/makesrna/intern/rna_ID.c2
-rw-r--r--source/blender/makesrna/intern/rna_access.c14
-rw-r--r--source/blender/makesrna/intern/rna_define.c8
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c38
-rw-r--r--source/blender/makesrna/intern/rna_object.c2
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.c36
-rw-r--r--source/blender/python/bmesh/bmesh_py_api.c9
-rw-r--r--source/blender/python/generic/idprop_py_api.c2
-rw-r--r--source/blender/python/generic/py_capi_utils.c10
-rw-r--r--source/blender/python/intern/bpy_app.c12
-rw-r--r--source/blender/python/intern/bpy_driver.c9
-rw-r--r--source/blender/python/intern/bpy_library_load.c60
-rw-r--r--source/blender/python/intern/gpu.c4
-rw-r--r--source/blender/python/mathutils/mathutils.c10
-rw-r--r--source/blender/quicktime/apple/qtkit_import.m2
-rw-r--r--source/blender/render/intern/include/render_types.h1
-rw-r--r--source/blender/render/intern/include/rendercore.h2
-rw-r--r--source/blender/render/intern/raytrace/rayobject.cpp8
-rw-r--r--source/blender/render/intern/source/convertblender.c4
-rw-r--r--source/blender/render/intern/source/occlusion.c11
-rw-r--r--source/blender/render/intern/source/pipeline.c2
-rw-r--r--source/blender/render/intern/source/rayshade.c14
-rw-r--r--source/blender/render/intern/source/render_texture.c3
-rw-r--r--source/blender/render/intern/source/sss.c14
-rw-r--r--source/blender/windowmanager/intern/wm_files.c10
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c3
-rw-r--r--source/blenderplayer/CMakeLists.txt2
-rw-r--r--source/creator/CMakeLists.txt2
-rw-r--r--source/creator/creator.c4
-rw-r--r--source/creator/creator_args.c19
-rw-r--r--source/gameengine/GameLogic/SCA_PythonController.cpp4
-rw-r--r--source/gameengine/GameLogic/SCA_PythonKeyboard.cpp26
-rw-r--r--source/gameengine/GameLogic/SCA_PythonMouse.cpp31
m---------source/tools0
140 files changed, 2181 insertions, 1457 deletions
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index 5874f95502b..ac9b0b6fb10 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -63,7 +63,7 @@ struct bAction *BKE_action_copy(struct Main *bmain, struct bAction *src);
/* Deallocate all of the Action's data, but not the Action itself */
void BKE_action_free(struct bAction *act);
-void BKE_action_make_local(struct Main *bmain, struct bAction *act);
+void BKE_action_make_local(struct Main *bmain, struct bAction *act, const bool force_local);
/* Action API ----------------- */
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index 326c335338f..bfd4a7e3dd8 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -76,7 +76,7 @@ struct bArmature *BKE_armature_from_object(struct Object *ob);
int BKE_armature_bonelist_count(struct ListBase *lb);
void BKE_armature_bonelist_free(struct ListBase *lb);
void BKE_armature_free(struct bArmature *arm);
-void BKE_armature_make_local(struct Main *bmain, struct bArmature *arm);
+void BKE_armature_make_local(struct Main *bmain, struct bArmature *arm, const bool force_local);
struct bArmature *BKE_armature_copy(struct Main *bmain, struct bArmature *arm);
/* Bounding box. */
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h
index c7116bf2ef6..4be4d95490b 100644
--- a/source/blender/blenkernel/BKE_brush.h
+++ b/source/blender/blenkernel/BKE_brush.h
@@ -45,7 +45,7 @@ void BKE_brush_init(struct Brush *brush);
struct Brush *BKE_brush_add(struct Main *bmain, const char *name, short ob_mode);
struct Brush *BKE_brush_first_search(struct Main *bmain, short ob_mode);
struct Brush *BKE_brush_copy(struct Main *bmain, struct Brush *brush);
-void BKE_brush_make_local(struct Main *bmain, struct Brush *brush);
+void BKE_brush_make_local(struct Main *bmain, struct Brush *brush, const bool force_local);
void BKE_brush_unlink(struct Main *bmain, struct Brush *brush);
void BKE_brush_free(struct Brush *brush);
diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h
index 97f4b30894b..3ae0e0e1111 100644
--- a/source/blender/blenkernel/BKE_camera.h
+++ b/source/blender/blenkernel/BKE_camera.h
@@ -53,7 +53,7 @@ struct GPUFXSettings;
void BKE_camera_init(struct Camera *cam);
void *BKE_camera_add(struct Main *bmain, const char *name);
struct Camera *BKE_camera_copy(struct Main *bmain, struct Camera *cam);
-void BKE_camera_make_local(struct Main *bmain, struct Camera *cam);
+void BKE_camera_make_local(struct Main *bmain, struct Camera *cam, const bool force_local);
void BKE_camera_free(struct Camera *ca);
/* Camera Usage */
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 89dbe246910..c2a0404e96e 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -71,7 +71,7 @@ void BKE_curve_editfont_free(struct Curve *cu);
void BKE_curve_init(struct Curve *cu);
struct Curve *BKE_curve_add(struct Main *bmain, const char *name, int type);
struct Curve *BKE_curve_copy(struct Main *bmain, struct Curve *cu);
-void BKE_curve_make_local(struct Main *bmain, struct Curve *cu);
+void BKE_curve_make_local(struct Main *bmain, struct Curve *cu, const bool force_local);
short BKE_curve_type_get(struct Curve *cu);
void BKE_curve_type_test(struct Object *ob);
void BKE_curve_curve_dimension_update(struct Curve *cu);
diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h
index 763a3874d4e..7839b9e2154 100644
--- a/source/blender/blenkernel/BKE_icons.h
+++ b/source/blender/blenkernel/BKE_icons.h
@@ -55,7 +55,7 @@ void BKE_icons_init(int first_dyn_id);
/* return icon id for library object or create new icon if not found */
int BKE_icon_id_ensure(struct ID *id);
-int BKE_icon_preview_ensure(struct PreviewImage *preview);
+int BKE_icon_preview_ensure(struct ID *id, struct PreviewImage *preview);
/* retrieve icon for id */
struct Icon *BKE_icon_get(int icon_id);
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index 0895feef983..db73b42d894 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -108,7 +108,7 @@ struct anim *openanim_noload(const char *name, int flags, int streamindex, char
void BKE_image_de_interlace(struct Image *ima, int odd);
-void BKE_image_make_local(struct Main *bmain, struct Image *ima);
+void BKE_image_make_local(struct Main *bmain, struct Image *ima, const bool force_local);
void BKE_image_tag_time(struct Image *ima);
diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h
index f30f9eac4e8..e590ff148d7 100644
--- a/source/blender/blenkernel/BKE_key.h
+++ b/source/blender/blenkernel/BKE_key.h
@@ -53,7 +53,6 @@ void BKE_key_free_nolib(struct Key *key);
struct Key *BKE_key_add(struct ID *id);
struct Key *BKE_key_copy(struct Main *bmain, struct Key *key);
struct Key *BKE_key_copy_nolib(struct Key *key);
-void BKE_key_make_local(struct Main *bmain, struct Key *key);
void BKE_key_sort(struct Key *key);
void key_curve_position_weights(float t, float data[4], int type);
diff --git a/source/blender/blenkernel/BKE_lamp.h b/source/blender/blenkernel/BKE_lamp.h
index 49b43550e67..dc977eabbb1 100644
--- a/source/blender/blenkernel/BKE_lamp.h
+++ b/source/blender/blenkernel/BKE_lamp.h
@@ -46,7 +46,7 @@ void BKE_lamp_init(struct Lamp *la);
struct Lamp *BKE_lamp_add(struct Main *bmain, const char *name) ATTR_WARN_UNUSED_RESULT;
struct Lamp *BKE_lamp_copy(struct Main *bmain, struct Lamp *la) ATTR_WARN_UNUSED_RESULT;
struct Lamp *localize_lamp(struct Lamp *la) ATTR_WARN_UNUSED_RESULT;
-void BKE_lamp_make_local(struct Main *bmain, struct Lamp *la);
+void BKE_lamp_make_local(struct Main *bmain, struct Lamp *la, const bool force_local);
void BKE_lamp_free(struct Lamp *la);
void lamp_drivers_update(struct Scene *scene, struct Lamp *la, float ctime);
diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h
index 606df9dcec8..4f72bbecff4 100644
--- a/source/blender/blenkernel/BKE_lattice.h
+++ b/source/blender/blenkernel/BKE_lattice.h
@@ -49,7 +49,7 @@ void BKE_lattice_init(struct Lattice *lt);
struct Lattice *BKE_lattice_add(struct Main *bmain, const char *name);
struct Lattice *BKE_lattice_copy(struct Main *bmain, struct Lattice *lt);
void BKE_lattice_free(struct Lattice *lt);
-void BKE_lattice_make_local(struct Main *bmain, struct Lattice *lt);
+void BKE_lattice_make_local(struct Main *bmain, struct Lattice *lt, const bool force_local);
void calc_lat_fudu(int flag, int res, float *r_fu, float *r_du);
struct LatticeDeformData;
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index cb39b2e53ee..b6a91caee4e 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -80,7 +80,7 @@ void id_us_min(struct ID *id);
void id_fake_user_set(struct ID *id);
void id_fake_user_clear(struct ID *id);
-bool id_make_local(struct Main *bmain, struct ID *id, bool test);
+bool id_make_local(struct Main *bmain, struct ID *id, const bool test, const bool force_local);
bool id_single_user(struct bContext *C, struct ID *id, struct PointerRNA *ptr, struct PropertyRNA *prop);
bool id_copy(struct Main *bmain, struct ID *id, struct ID **newid, bool test);
void id_sort_by_name(struct ListBase *lb, struct ID *id);
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
index 0bc54ee4a16..bbe104cd6ee 100644
--- a/source/blender/blenkernel/BKE_material.h
+++ b/source/blender/blenkernel/BKE_material.h
@@ -57,7 +57,7 @@ struct Material *BKE_material_add(struct Main *bmain, const char *name);
struct Material *BKE_material_copy(struct Main *bmain, struct Material *ma);
struct Material *localize_material(struct Material *ma);
struct Material *give_node_material(struct Material *ma); /* returns node material or self */
-void BKE_material_make_local(struct Main *bmain, struct Material *ma);
+void BKE_material_make_local(struct Main *bmain, struct Material *ma, const bool force_local);
/* UNUSED */
// void automatname(struct Material *);
diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h
index 42704c1b2db..191e8721099 100644
--- a/source/blender/blenkernel/BKE_mball.h
+++ b/source/blender/blenkernel/BKE_mball.h
@@ -43,7 +43,7 @@ void BKE_mball_init(struct MetaBall *mb);
struct MetaBall *BKE_mball_add(struct Main *bmain, const char *name);
struct MetaBall *BKE_mball_copy(struct Main *bmain, struct MetaBall *mb);
-void BKE_mball_make_local(struct Main *bmain, struct MetaBall *mb);
+void BKE_mball_make_local(struct Main *bmain, struct MetaBall *mb, const bool force_local);
bool BKE_mball_is_basis_for(struct Object *ob1, struct Object *ob2);
bool BKE_mball_is_basis(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index d3bb34d7a41..ef8d1c98318 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -91,7 +91,7 @@ struct Mesh *BKE_mesh_copy(struct Main *bmain, struct Mesh *me);
void BKE_mesh_update_customdata_pointers(struct Mesh *me, const bool do_ensure_tess_cd);
void BKE_mesh_ensure_skin_customdata(struct Mesh *me);
-void BKE_mesh_make_local(struct Main *bmain, struct Mesh *me);
+void BKE_mesh_make_local(struct Main *bmain, struct Mesh *me, const bool force_local);
void BKE_mesh_boundbox_calc(struct Mesh *me, float r_loc[3], float r_size[3]);
void BKE_mesh_texspace_calc(struct Mesh *me);
float (*BKE_mesh_orco_verts_get(struct Object *ob))[3];
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index b44cb226f0d..647b96fb9ae 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -346,7 +346,7 @@ void ntreeUserDecrefID(struct bNodeTree *ntree);
struct bNodeTree *ntreeFromID(struct ID *id);
-void ntreeMakeLocal(struct Main *bmain, struct bNodeTree *ntree, bool id_in_mainlist);
+void ntreeMakeLocal(struct Main *bmain, struct bNodeTree *ntree, bool id_in_mainlist, const bool force_local);
struct bNode *ntreeFindType(const struct bNodeTree *ntree, int type);
bool ntreeHasType(const struct bNodeTree *ntree, int type);
bool ntreeHasTree(const struct bNodeTree *ntree, const struct bNodeTree *lookup);
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 2c4df9620c2..8811f358cd3 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -104,7 +104,7 @@ struct Object *BKE_object_lod_matob_get(struct Object *ob, struct Scene *scene);
struct Object *BKE_object_copy_ex(struct Main *bmain, struct Object *ob, bool copy_caches);
struct Object *BKE_object_copy(struct Main *bmain, struct Object *ob);
-void BKE_object_make_local(struct Main *bmain, struct Object *ob);
+void BKE_object_make_local(struct Main *bmain, struct Object *ob, const bool force_local);
bool BKE_object_is_libdata(struct Object *ob);
bool BKE_object_obdata_is_libdata(struct Object *ob);
@@ -203,8 +203,6 @@ void BKE_object_eval_uber_data(struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob);
-void BKE_object_eval_proxy_backlink(struct EvaluationContext *eval_ctx, struct Object *ob);
-
void BKE_object_handle_data_update(struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_speaker.h b/source/blender/blenkernel/BKE_speaker.h
index 89b948a2126..fb730d95b92 100644
--- a/source/blender/blenkernel/BKE_speaker.h
+++ b/source/blender/blenkernel/BKE_speaker.h
@@ -34,7 +34,7 @@ struct Speaker;
void BKE_speaker_init(struct Speaker *spk);
void *BKE_speaker_add(struct Main *bmain, const char *name);
struct Speaker *BKE_speaker_copy(struct Main *bmain, struct Speaker *spk);
-void BKE_speaker_make_local(struct Main *bmain, struct Speaker *spk);
+void BKE_speaker_make_local(struct Main *bmain, struct Speaker *spk, const bool force_local);
void BKE_speaker_free(struct Speaker *spk);
#endif
diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h
index 52b1906a78b..b853ebd4793 100644
--- a/source/blender/blenkernel/BKE_texture.h
+++ b/source/blender/blenkernel/BKE_texture.h
@@ -71,7 +71,7 @@ void BKE_texture_default(struct Tex *tex);
struct Tex *BKE_texture_copy(struct Main *bmain, struct Tex *tex);
struct Tex *BKE_texture_add(struct Main *bmain, const char *name);
struct Tex *BKE_texture_localize(struct Tex *tex);
-void BKE_texture_make_local(struct Main *bmain, struct Tex *tex);
+void BKE_texture_make_local(struct Main *bmain, struct Tex *tex, const bool force_local);
void BKE_texture_type_set(struct Tex *tex, int type);
void BKE_texture_mtex_default(struct MTex *mtex);
diff --git a/source/blender/blenkernel/BKE_world.h b/source/blender/blenkernel/BKE_world.h
index da5cca09b27..8b8dac4ab22 100644
--- a/source/blender/blenkernel/BKE_world.h
+++ b/source/blender/blenkernel/BKE_world.h
@@ -41,7 +41,7 @@ void BKE_world_init(struct World *wrld);
struct World *add_world(struct Main *bmian, const char *name);
struct World *BKE_world_copy(struct Main *bmain, struct World *wrld);
struct World *localize_world(struct World *wrld);
-void BKE_world_make_local(struct Main *bmain, struct World *wrld);
+void BKE_world_make_local(struct Main *bmain, struct World *wrld, const bool force_local);
#endif
diff --git a/source/blender/blenkernel/intern/CCGSubSurf_util.c b/source/blender/blenkernel/intern/CCGSubSurf_util.c
index 9af69115559..c7ef528c02f 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf_util.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf_util.c
@@ -184,7 +184,7 @@ int ccg_ehashIterator_isStopped(EHashIterator *ehi)
}
/**
- * Standard allocator implementarion.
+ * Standard allocator implementation.
*/
static void *_stdAllocator_alloc(CCGAllocatorHDL UNUSED(a), int numBytes)
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index f7ff1261c8a..fa49797126d 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -95,11 +95,11 @@ bAction *add_empty_action(Main *bmain, const char name[])
/* .................................. */
// does copy_fcurve...
-void BKE_action_make_local(Main *bmain, bAction *act)
+void BKE_action_make_local(Main *bmain, bAction *act, const bool force_local)
{
bool is_local = false, is_lib = false;
- /* - only lib users: do nothing
+ /* - only lib users: do nothing (unless force_local is set)
* - only local users: set flag
* - mixed: make copy
*/
@@ -110,7 +110,7 @@ void BKE_action_make_local(Main *bmain, bAction *act)
BKE_library_ID_test_usages(bmain, act, &is_local, &is_lib);
- if (is_local) {
+ if (force_local || is_local) {
if (!is_lib) {
id_clear_lib_data(bmain, &act->id);
BKE_id_expand_local(&act->id);
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 7f10f6833db..fa156e95d46 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -399,8 +399,8 @@ static void make_local_strips(ListBase *strips)
NlaStrip *strip;
for (strip = strips->first; strip; strip = strip->next) {
- if (strip->act) BKE_action_make_local(G.main, strip->act);
- if (strip->remap && strip->remap->target) BKE_action_make_local(G.main, strip->remap->target);
+ if (strip->act) BKE_action_make_local(G.main, strip->act, false);
+ if (strip->remap && strip->remap->target) BKE_action_make_local(G.main, strip->remap->target, false);
make_local_strips(&strip->strips);
}
@@ -412,10 +412,10 @@ void BKE_animdata_make_local(AnimData *adt)
NlaTrack *nlt;
/* Actions - Active and Temp */
- if (adt->action) BKE_action_make_local(G.main, adt->action);
- if (adt->tmpact) BKE_action_make_local(G.main, adt->tmpact);
+ if (adt->action) BKE_action_make_local(G.main, adt->action, false);
+ if (adt->tmpact) BKE_action_make_local(G.main, adt->tmpact, false);
/* Remaps */
- if (adt->remap && adt->remap->target) BKE_action_make_local(G.main, adt->remap->target);
+ if (adt->remap && adt->remap->target) BKE_action_make_local(G.main, adt->remap->target, false);
/* Drivers */
/* TODO: need to remap the ID-targets too? */
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 5f564e1c4d2..53e28177bdf 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -144,11 +144,11 @@ void BKE_armature_free(bArmature *arm)
}
}
-void BKE_armature_make_local(Main *bmain, bArmature *arm)
+void BKE_armature_make_local(Main *bmain, bArmature *arm, const bool force_local)
{
bool is_local = false, is_lib = false;
- /* - only lib users: do nothing
+ /* - only lib users: do nothing (unless force_local is set)
* - only local users: set flag
* - mixed: make copy
*/
@@ -159,7 +159,7 @@ void BKE_armature_make_local(Main *bmain, bArmature *arm)
BKE_library_ID_test_usages(bmain, arm, &is_local, &is_lib);
- if (is_local) {
+ if (force_local || is_local) {
if (!is_lib) {
id_clear_lib_data(bmain, &arm->id);
BKE_id_expand_local(&arm->id);
diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c
index ece17335fa0..aebd564ca58 100644
--- a/source/blender/blenkernel/intern/armature_update.c
+++ b/source/blender/blenkernel/intern/armature_update.c
@@ -224,7 +224,7 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos
}
/* make a new Spline-IK chain, and store it in the IK chains */
- /* TODO: we should check if there is already an IK chain on this, since that would take presidence... */
+ /* TODO: we should check if there is already an IK chain on this, since that would take precedence... */
{
/* make new tree */
tSplineIK_Tree *tree = MEM_callocN(sizeof(tSplineIK_Tree), "SplineIK Tree");
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 20621feac6c..3d9cabdc15d 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -219,11 +219,11 @@ void BKE_brush_free(Brush *brush)
BKE_previewimg_free(&(brush->preview));
}
-void BKE_brush_make_local(Main *bmain, Brush *brush)
+void BKE_brush_make_local(Main *bmain, Brush *brush, const bool force_local)
{
bool is_local = false, is_lib = false;
- /* - only lib users: do nothing
+ /* - only lib users: do nothing (unless force_local is set)
* - only local users: set flag
* - mixed: make copy
*/
@@ -234,12 +234,12 @@ void BKE_brush_make_local(Main *bmain, Brush *brush)
if (brush->clone.image) {
/* Special case: ima always local immediately. Clone image should only have one user anyway. */
- id_make_local(bmain, &brush->clone.image->id, false);
+ id_make_local(bmain, &brush->clone.image->id, false, false);
}
BKE_library_ID_test_usages(bmain, brush, &is_local, &is_lib);
- if (is_local) {
+ if (force_local || is_local) {
if (!is_lib) {
id_clear_lib_data(bmain, &brush->id);
BKE_id_expand_local(&brush->id);
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index ae7aac8b54f..cd085816b4d 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -107,11 +107,11 @@ Camera *BKE_camera_copy(Main *bmain, Camera *cam)
return camn;
}
-void BKE_camera_make_local(Main *bmain, Camera *cam)
+void BKE_camera_make_local(Main *bmain, Camera *cam, const bool force_local)
{
bool is_local = false, is_lib = false;
- /* - only lib users: do nothing
+ /* - only lib users: do nothing (unless force_local is set)
* - only local users: set flag
* - mixed: make copy
*/
@@ -122,7 +122,7 @@ void BKE_camera_make_local(Main *bmain, Camera *cam)
BKE_library_ID_test_usages(bmain, cam, &is_local, &is_lib);
- if (is_local) {
+ if (force_local || is_local) {
if (!is_lib) {
id_clear_lib_data(bmain, &cam->id);
BKE_id_expand_local(&cam->id);
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 0e634e21ea3..693e7eb0c80 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -215,11 +215,11 @@ Curve *BKE_curve_copy(Main *bmain, Curve *cu)
return cun;
}
-void BKE_curve_make_local(Main *bmain, Curve *cu)
+void BKE_curve_make_local(Main *bmain, Curve *cu, const bool force_local)
{
bool is_local = false, is_lib = false;
- /* - when there are only lib users: don't do
+ /* - only lib users: do nothing (unless force_local is set)
* - when there are only local users: set flag
* - mixed: do a copy
*/
@@ -230,12 +230,9 @@ void BKE_curve_make_local(Main *bmain, Curve *cu)
BKE_library_ID_test_usages(bmain, cu, &is_local, &is_lib);
- if (is_local) {
+ if (force_local || is_local) {
if (!is_lib) {
id_clear_lib_data(bmain, &cu->id);
- if (cu->key) {
- BKE_key_make_local(bmain, cu->key);
- }
BKE_id_expand_local(&cu->id);
}
else {
diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c
index f3e86b44459..63055dc0646 100644
--- a/source/blender/blenkernel/intern/icons.c
+++ b/source/blender/blenkernel/intern/icons.c
@@ -423,10 +423,26 @@ void BKE_icon_changed(int id)
}
}
-int BKE_icon_id_ensure(struct ID *id)
+static int icon_id_ensure_create_icon(struct ID *id)
{
Icon *new_icon = NULL;
+ new_icon = MEM_mallocN(sizeof(Icon), __func__);
+
+ new_icon->obj = id;
+ new_icon->type = GS(id->name);
+
+ /* next two lines make sure image gets created */
+ new_icon->drawinfo = NULL;
+ new_icon->drawinfo_free = NULL;
+
+ BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(id->icon_id), new_icon);
+
+ return id->icon_id;
+}
+
+int BKE_icon_id_ensure(struct ID *id)
+{
if (!id || G.background)
return 0;
@@ -440,32 +456,39 @@ int BKE_icon_id_ensure(struct ID *id)
return 0;
}
- new_icon = MEM_mallocN(sizeof(Icon), __func__);
-
- new_icon->obj = id;
- new_icon->type = GS(id->name);
-
- /* next two lines make sure image gets created */
- new_icon->drawinfo = NULL;
- new_icon->drawinfo_free = NULL;
+ /* Ensure we synchronize ID icon_id with its previewimage if it has one. */
+ PreviewImage **p_prv = BKE_previewimg_id_get_p(id);
+ if (p_prv && *p_prv) {
+ BLI_assert(ELEM((*p_prv)->icon_id, 0, id->icon_id));
+ (*p_prv)->icon_id = id->icon_id;
+ }
- BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(id->icon_id), new_icon);
-
- return id->icon_id;
+ return icon_id_ensure_create_icon(id);
}
/**
* Return icon id of given preview, or create new icon if not found.
*/
-int BKE_icon_preview_ensure(PreviewImage *preview)
+int BKE_icon_preview_ensure(ID *id, PreviewImage *preview)
{
Icon *new_icon = NULL;
if (!preview || G.background)
return 0;
- if (preview->icon_id)
+ if (id) {
+ BLI_assert(BKE_previewimg_id_ensure(id) == preview);
+ }
+
+ if (preview->icon_id) {
+ BLI_assert(!id || !id->icon_id || id->icon_id == preview->icon_id);
return preview->icon_id;
+ }
+
+ if (id && id->icon_id) {
+ preview->icon_id = id->icon_id;
+ return preview->icon_id;
+ }
preview->icon_id = get_next_free_id();
@@ -474,6 +497,12 @@ int BKE_icon_preview_ensure(PreviewImage *preview)
return 0;
}
+ /* Ensure we synchronize ID icon_id with its previewimage if available, and generate suitable 'ID' icon. */
+ if (id) {
+ id->icon_id = preview->icon_id;
+ return icon_id_ensure_create_icon(id);
+ }
+
new_icon = MEM_mallocN(sizeof(Icon), __func__);
new_icon->obj = preview;
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index f6f38977402..ae3163d388e 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -469,11 +469,11 @@ Image *BKE_image_copy(Main *bmain, Image *ima)
return nima;
}
-void BKE_image_make_local(Main *bmain, Image *ima)
+void BKE_image_make_local(Main *bmain, Image *ima, const bool force_local)
{
bool is_local = false, is_lib = false;
- /* - only lib users: do nothing
+ /* - only lib users: do nothing (unless force_local is set)
* - only local users: set flag
* - mixed: make copy
*/
@@ -484,7 +484,7 @@ void BKE_image_make_local(Main *bmain, Image *ima)
BKE_library_ID_test_usages(bmain, ima, &is_local, &is_lib);
- if (is_local) {
+ if (force_local || is_local) {
if (!is_lib) {
id_clear_lib_data(bmain, &ima->id);
BKE_id_expand_local(&ima->id);
@@ -1118,8 +1118,11 @@ int BKE_image_imtype_to_ftype(const char imtype, ImbFormatOptions *r_options)
return IMB_FTYPE_DPX;
#endif
#ifdef WITH_OPENJPEG
- else if (imtype == R_IMF_IMTYPE_JP2)
+ else if (imtype == R_IMF_IMTYPE_JP2) {
+ r_options->flag |= JP2_JP2;
+ r_options->quality = 90;
return IMB_FTYPE_JP2;
+ }
#endif
else {
r_options->quality = 90;
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index e59facd3c39..a524f927cad 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -203,18 +203,6 @@ Key *BKE_key_copy_nolib(Key *key)
return keyn;
}
-void BKE_key_make_local(Main *bmain, Key *key)
-{
- /* Note that here for now we simply just make it local...
- * Sounds fishy behavior, but since skeys are not *real* IDs... */
-
- if (!ID_IS_LINKED_DATABLOCK(key)) {
- return;
- }
-
- id_clear_lib_data(bmain, &key->id);
-}
-
/* Sort shape keys and Ipo curves after a change. This assumes that at most
* one key was moved, which is a valid assumption for the places it's
* currently being called.
diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c
index 003b154a70b..c224b5ca0a7 100644
--- a/source/blender/blenkernel/intern/lamp.c
+++ b/source/blender/blenkernel/intern/lamp.c
@@ -172,11 +172,11 @@ Lamp *localize_lamp(Lamp *la)
return lan;
}
-void BKE_lamp_make_local(Main *bmain, Lamp *la)
+void BKE_lamp_make_local(Main *bmain, Lamp *la, const bool force_local)
{
bool is_local = false, is_lib = false;
- /* - only lib users: do nothing
+ /* - only lib users: do nothing (unless force_local is set)
* - only local users: set flag
* - mixed: make copy
*/
@@ -187,7 +187,7 @@ void BKE_lamp_make_local(Main *bmain, Lamp *la)
BKE_library_ID_test_usages(bmain, la, &is_local, &is_lib);
- if (is_local) {
+ if (force_local || is_local) {
if (!is_lib) {
id_clear_lib_data(bmain, &la->id);
BKE_id_expand_local(&la->id);
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index 67f49266efc..c2675fabe3b 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -330,11 +330,11 @@ void BKE_lattice_free(Lattice *lt)
}
-void BKE_lattice_make_local(Main *bmain, Lattice *lt)
+void BKE_lattice_make_local(Main *bmain, Lattice *lt, const bool force_local)
{
bool is_local = false, is_lib = false;
- /* - only lib users: do nothing
+ /* - only lib users: do nothing (unless force_local is set)
* - only local users: set flag
* - mixed: make copy
*/
@@ -345,12 +345,9 @@ void BKE_lattice_make_local(Main *bmain, Lattice *lt)
BKE_library_ID_test_usages(bmain, lt, &is_local, &is_lib);
- if (is_local) {
+ if (force_local || is_local) {
if (!is_lib) {
id_clear_lib_data(bmain, &lt->id);
- if (lt->key) {
- BKE_key_make_local(bmain, lt->key);
- }
BKE_id_expand_local(&lt->id);
}
else {
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 978f1acefba..9b9b80a2ecc 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -270,7 +270,7 @@ void BKE_id_expand_local(ID *id)
/* calls the appropriate make_local method for the block, unless test. Returns true
* if the block can be made local. */
-bool id_make_local(Main *bmain, ID *id, bool test)
+bool id_make_local(Main *bmain, ID *id, const bool test, const bool force_local)
{
if (id->tag & LIB_TAG_INDIRECT)
return false;
@@ -281,45 +281,44 @@ bool id_make_local(Main *bmain, ID *id, bool test)
case ID_LI:
return false; /* can't be linked */
case ID_OB:
- if (!test) BKE_object_make_local(bmain, (Object *)id);
+ if (!test) BKE_object_make_local(bmain, (Object *)id, force_local);
return true;
case ID_ME:
- if (!test) BKE_mesh_make_local(bmain, (Mesh *)id);
+ if (!test) BKE_mesh_make_local(bmain, (Mesh *)id, force_local);
return true;
case ID_CU:
- if (!test) BKE_curve_make_local(bmain, (Curve *)id);
+ if (!test) BKE_curve_make_local(bmain, (Curve *)id, force_local);
return true;
case ID_MB:
- if (!test) BKE_mball_make_local(bmain, (MetaBall *)id);
+ if (!test) BKE_mball_make_local(bmain, (MetaBall *)id, force_local);
return true;
case ID_MA:
- if (!test) BKE_material_make_local(bmain, (Material *)id);
+ if (!test) BKE_material_make_local(bmain, (Material *)id, force_local);
return true;
case ID_TE:
- if (!test) BKE_texture_make_local(bmain, (Tex *)id);
+ if (!test) BKE_texture_make_local(bmain, (Tex *)id, force_local);
return true;
case ID_IM:
- if (!test) BKE_image_make_local(bmain, (Image *)id);
+ if (!test) BKE_image_make_local(bmain, (Image *)id, force_local);
return true;
case ID_LT:
- if (!test) BKE_lattice_make_local(bmain, (Lattice *)id);
+ if (!test) BKE_lattice_make_local(bmain, (Lattice *)id, force_local);
return true;
case ID_LA:
- if (!test) BKE_lamp_make_local(bmain, (Lamp *)id);
+ if (!test) BKE_lamp_make_local(bmain, (Lamp *)id, force_local);
return true;
case ID_CA:
- if (!test) BKE_camera_make_local(bmain, (Camera *)id);
+ if (!test) BKE_camera_make_local(bmain, (Camera *)id, force_local);
return true;
case ID_SPK:
- if (!test) BKE_speaker_make_local(bmain, (Speaker *)id);
+ if (!test) BKE_speaker_make_local(bmain, (Speaker *)id, force_local);
return true;
case ID_IP:
return false; /* deprecated */
case ID_KE:
- if (!test) BKE_key_make_local(bmain, (Key *)id);
- return true;
+ return false; /* can't be linked */
case ID_WO:
- if (!test) BKE_world_make_local(bmain, (World *)id);
+ if (!test) BKE_world_make_local(bmain, (World *)id, force_local);
return true;
case ID_SCR:
return false; /* can't be linked */
@@ -332,16 +331,16 @@ bool id_make_local(Main *bmain, ID *id, bool test)
case ID_GR:
return false; /* not implemented */
case ID_AR:
- if (!test) BKE_armature_make_local(bmain, (bArmature *)id);
+ if (!test) BKE_armature_make_local(bmain, (bArmature *)id, force_local);
return true;
case ID_AC:
- if (!test) BKE_action_make_local(bmain, (bAction *)id);
+ if (!test) BKE_action_make_local(bmain, (bAction *)id, force_local);
return true;
case ID_NT:
- if (!test) ntreeMakeLocal(bmain, (bNodeTree *)id, true);
+ if (!test) ntreeMakeLocal(bmain, (bNodeTree *)id, true, force_local);
return true;
case ID_BR:
- if (!test) BKE_brush_make_local(bmain, (Brush *)id);
+ if (!test) BKE_brush_make_local(bmain, (Brush *)id, force_local);
return true;
case ID_WM:
return false; /* can't be linked */
@@ -1455,6 +1454,7 @@ bool new_id(ListBase *lb, ID *id, const char *tname)
void id_clear_lib_data_ex(Main *bmain, ID *id, bool id_in_mainlist)
{
bNodeTree *ntree = NULL;
+ Key *key = NULL;
BKE_id_lib_local_paths(bmain, id->lib, id);
@@ -1465,13 +1465,14 @@ void id_clear_lib_data_ex(Main *bmain, ID *id, bool id_in_mainlist)
if (id_in_mainlist)
new_id(which_libbase(bmain, GS(id->name)), id, NULL);
- /* internal bNodeTree blocks inside ID types below
- * also stores id->lib, make sure this stays in sync.
- */
- ntree = ntreeFromID(id);
+ /* Internal bNodeTree blocks inside datablocks also stores id->lib, make sure this stays in sync. */
+ if ((ntree = ntreeFromID(id))) {
+ id_clear_lib_data_ex(bmain, &ntree->id, false); /* Datablocks' nodetree is never in Main. */
+ }
- if (ntree) {
- ntreeMakeLocal(bmain, ntree, false);
+ /* Same goes for shapekeys. */
+ if ((key = BKE_key_from_id(id))) {
+ id_clear_lib_data_ex(bmain, &key->id, id_in_mainlist); /* sigh, why are keys in Main? */
}
if (GS(id->name) == ID_OB) {
@@ -1585,14 +1586,8 @@ void BKE_library_make_local(Main *bmain, const Library *lib, const bool untagged
{
if (lib == NULL || id->lib == lib) {
if (id->lib) {
- /* for Make Local > All we should be calling id_make_local,
- * but doing that breaks append (see #36003 and #36006), we
- * we should make it work with all datablocks and id.us==0 */
- id_clear_lib_data(bmain, id); /* sets 'id->tag' */
-
- /* why sort alphabetically here but not in
- * id_clear_lib_data() ? - campbell */
- id_sort_by_name(lbarray[a], id);
+ /* In this specific case, we do want to make ID local even if it has no local usage yet... */
+ id_make_local(bmain, id, false, true);
}
else {
id->tag &= ~(LIB_TAG_EXTERN | LIB_TAG_INDIRECT | LIB_TAG_NEW);
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 17811893c03..2ae369fdd1b 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -285,11 +285,11 @@ Material *localize_material(Material *ma)
return man;
}
-void BKE_material_make_local(Main *bmain, Material *ma)
+void BKE_material_make_local(Main *bmain, Material *ma, const bool force_local)
{
bool is_local = false, is_lib = false;
- /* - only lib users: do nothing
+ /* - only lib users: do nothing (unless force_local is set)
* - only local users: set flag
* - mixed: make copy
*/
@@ -300,7 +300,7 @@ void BKE_material_make_local(Main *bmain, Material *ma)
BKE_library_ID_test_usages(bmain, ma, &is_local, &is_lib);
- if (is_local) {
+ if (force_local || is_local) {
if (!is_lib) {
id_clear_lib_data(bmain, &ma->id);
BKE_id_expand_local(&ma->id);
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 9a0a6e3540c..aeb38b3bd1d 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -127,11 +127,11 @@ MetaBall *BKE_mball_copy(Main *bmain, MetaBall *mb)
return mbn;
}
-void BKE_mball_make_local(Main *bmain, MetaBall *mb)
+void BKE_mball_make_local(Main *bmain, MetaBall *mb, const bool force_local)
{
bool is_local = false, is_lib = false;
- /* - only lib users: do nothing
+ /* - only lib users: do nothing (unless force_local is set)
* - only local users: set flag
* - mixed: make copy
*/
@@ -142,7 +142,7 @@ void BKE_mball_make_local(Main *bmain, MetaBall *mb)
BKE_library_ID_test_usages(bmain, mb, &is_local, &is_lib);
- if (is_local) {
+ if (force_local || is_local) {
if (!is_lib) {
id_clear_lib_data(bmain, &mb->id);
BKE_id_expand_local(&mb->id);
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 787b9905734..b2f57328df3 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -555,11 +555,11 @@ BMesh *BKE_mesh_to_bmesh(
return bm;
}
-void BKE_mesh_make_local(Main *bmain, Mesh *me)
+void BKE_mesh_make_local(Main *bmain, Mesh *me, const bool force_local)
{
bool is_local = false, is_lib = false;
- /* - only lib users: do nothing
+ /* - only lib users: do nothing (unless force_local is set)
* - only local users: set flag
* - mixed: make copy
*/
@@ -570,12 +570,9 @@ void BKE_mesh_make_local(Main *bmain, Mesh *me)
BKE_library_ID_test_usages(bmain, me, &is_local, &is_lib);
- if (is_local) {
+ if (force_local || is_local) {
if (!is_lib) {
id_clear_lib_data(bmain, &me->id);
- if (me->key) {
- BKE_key_make_local(bmain, me->key);
- }
BKE_id_expand_local(&me->id);
}
else {
@@ -2227,7 +2224,6 @@ Mesh *BKE_mesh_new_from_object(
{
Mesh *tmpmesh;
Curve *tmpcu = NULL, *copycu;
- Object *tmpobj = NULL;
int render = settings == eModifierMode_Render, i;
int cage = !apply_modifiers;
@@ -2242,7 +2238,7 @@ Mesh *BKE_mesh_new_from_object(
int uv_from_orco;
/* copies object and modifiers (but not the data) */
- tmpobj = BKE_object_copy_ex(bmain, ob, true);
+ Object *tmpobj = BKE_object_copy_ex(bmain, ob, true);
tmpcu = (Curve *)tmpobj->data;
id_us_min(&tmpcu->id);
@@ -2443,7 +2439,7 @@ Mesh *BKE_mesh_new_from_object(
}
/* make sure materials get updated in object */
- test_object_materials(tmpobj ? tmpobj : ob, &tmpmesh->id);
+ test_object_materials(ob, &tmpmesh->id);
return tmpmesh;
}
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 296a00388c4..eec09973a82 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -1211,7 +1211,6 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, Main *bmain, bool ski
}
else {
newtree = BKE_libblock_copy_nolib(&ntree->id, true);
- newtree->id.lib = NULL; /* same as owning datablock id.lib */
}
id_us_plus((ID *)newtree->gpd);
@@ -1951,11 +1950,11 @@ bNodeTree *ntreeFromID(ID *id)
}
}
-void ntreeMakeLocal(Main *bmain, bNodeTree *ntree, bool id_in_mainlist)
+void ntreeMakeLocal(Main *bmain, bNodeTree *ntree, bool id_in_mainlist, const bool force_local)
{
bool is_lib = false, is_local = false;
- /* - only lib users: do nothing
+ /* - only lib users: do nothing (unless force_local is set)
* - only local users: set flag
* - mixed: make copy
*/
@@ -1966,7 +1965,7 @@ void ntreeMakeLocal(Main *bmain, bNodeTree *ntree, bool id_in_mainlist)
BKE_library_ID_test_usages(bmain, ntree, &is_local, &is_lib);
- if (is_local) {
+ if (force_local || is_local) {
if (!is_lib) {
id_clear_lib_data_ex(bmain, (ID *)ntree, id_in_mainlist);
BKE_id_expand_local(&ntree->id);
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 00c25bed1f7..5d654515fc8 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -1023,11 +1023,11 @@ Object *BKE_object_copy(Main *bmain, Object *ob)
return BKE_object_copy_ex(bmain, ob, false);
}
-void BKE_object_make_local(Main *bmain, Object *ob)
+void BKE_object_make_local(Main *bmain, Object *ob, const bool force_local)
{
bool is_local = false, is_lib = false;
- /* - only lib users: do nothing
+ /* - only lib users: do nothing (unless force_local is set)
* - only local users: set flag
* - mixed: make copy
*/
@@ -1038,7 +1038,7 @@ void BKE_object_make_local(Main *bmain, Object *ob)
BKE_library_ID_test_usages(bmain, ob, &is_local, &is_lib);
- if (is_local) {
+ if (force_local || is_local) {
if (!is_lib) {
id_clear_lib_data(bmain, &ob->id);
BKE_id_expand_local(&ob->id);
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index b5cb59da7d2..b8cb8955672 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -300,10 +300,3 @@ void BKE_object_eval_uber_data(EvaluationContext *eval_ctx,
ob->recalc &= ~(OB_RECALC_DATA | OB_RECALC_TIME);
}
-
-void BKE_object_eval_proxy_backlink(EvaluationContext *UNUSED(eval_ctx), Object *ob)
-{
- if (ob->proxy) {
- ob->proxy->proxy_from = ob;
- }
-}
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 572d23b39c7..d284548d6bc 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -1103,7 +1103,7 @@ char *BKE_scene_find_last_marker_name(Scene *scene, int frame)
Base *BKE_scene_base_add(Scene *sce, Object *ob)
{
- Base *b = MEM_callocN(sizeof(*b), "BKE_scene_base_add");
+ Base *b = MEM_callocN(sizeof(*b), __func__);
BLI_addhead(&sce->base, b);
b->object = ob;
diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c
index 3de4a426973..ce7c520438a 100644
--- a/source/blender/blenkernel/intern/seqeffects.c
+++ b/source/blender/blenkernel/intern/seqeffects.c
@@ -123,28 +123,34 @@ static ImBuf *prepare_effect_imbufs(const SeqRenderData *context, ImBuf *ibuf1,
out = IMB_allocImBuf(x, y, 32, IB_rect);
}
- if (ibuf1 && !ibuf1->rect_float && out->rect_float) {
- BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf1, true);
- }
- if (ibuf2 && !ibuf2->rect_float && out->rect_float) {
- BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf2, true);
- }
- if (ibuf3 && !ibuf3->rect_float && out->rect_float) {
- BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf3, true);
- }
+ if (out->rect_float) {
+ if (ibuf1 && !ibuf1->rect_float) {
+ BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf1, true);
+ }
+
+ if (ibuf2 && !ibuf2->rect_float) {
+ BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf2, true);
+ }
+
+ if (ibuf3 && !ibuf3->rect_float) {
+ BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf3, true);
+ }
- if (ibuf1 && !ibuf1->rect && !out->rect_float) {
- IMB_rect_from_float(ibuf1);
- }
- if (ibuf2 && !ibuf2->rect && !out->rect_float) {
- IMB_rect_from_float(ibuf2);
- }
- if (ibuf3 && !ibuf3->rect && !out->rect_float) {
- IMB_rect_from_float(ibuf3);
+ IMB_colormanagement_assign_float_colorspace(out, scene->sequencer_colorspace_settings.name);
}
+ else {
+ if (ibuf1 && !ibuf1->rect) {
+ IMB_rect_from_float(ibuf1);
+ }
- if (out->rect_float)
- IMB_colormanagement_assign_float_colorspace(out, scene->sequencer_colorspace_settings.name);
+ if (ibuf2 && !ibuf2->rect) {
+ IMB_rect_from_float(ibuf2);
+ }
+
+ if (ibuf3 && !ibuf3->rect) {
+ IMB_rect_from_float(ibuf3);
+ }
+ }
/* If effect only affecting a single channel, forward input's metadata to the output. */
if (ibuf1 != NULL && ibuf1 == ibuf2 && ibuf2 == ibuf3) {
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 5ef502e0182..2f497d807e4 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -1308,41 +1308,40 @@ StripElem *BKE_sequencer_give_stripelem(Sequence *seq, int cfra)
static int evaluate_seq_frame_gen(Sequence **seq_arr, ListBase *seqbase, int cfra, int chanshown)
{
- Sequence *seq;
- Sequence *effect_inputs[MAXSEQ + 1];
- int i, totseq = 0, num_effect_inputs = 0;
+ /* Use arbitrary sized linked list, the size could be over MAXSEQ. */
+ LinkNodePair effect_inputs = {NULL, NULL};
+ int totseq = 0;
memset(seq_arr, 0, sizeof(Sequence *) * (MAXSEQ + 1));
- seq = seqbase->first;
- while (seq) {
- if (seq->startdisp <= cfra && seq->enddisp > cfra) {
+ for (Sequence *seq = seqbase->first; seq; seq = seq->next) {
+ if ((seq->startdisp <= cfra) && (seq->enddisp > cfra)) {
if ((seq->type & SEQ_TYPE_EFFECT) && !(seq->flag & SEQ_MUTE)) {
+
if (seq->seq1) {
- effect_inputs[num_effect_inputs++] = seq->seq1;
+ BLI_linklist_append_alloca(&effect_inputs, seq->seq1);
}
if (seq->seq2) {
- effect_inputs[num_effect_inputs++] = seq->seq2;
+ BLI_linklist_append_alloca(&effect_inputs, seq->seq2);
}
if (seq->seq3) {
- effect_inputs[num_effect_inputs++] = seq->seq3;
+ BLI_linklist_append_alloca(&effect_inputs, seq->seq3);
}
}
seq_arr[seq->machine] = seq;
totseq++;
}
- seq = seq->next;
}
/* Drop strips which are used for effect inputs, we don't want
* them to blend into render stack in any other way than effect
* string rendering.
*/
- for (i = 0; i < num_effect_inputs; i++) {
- seq = effect_inputs[i];
+ for (LinkNode *seq_item = effect_inputs.list; seq_item; seq_item = seq_item->next) {
+ Sequence *seq = seq_item->link;
/* It's possible that effetc strip would be placed to the same
* 'machine' as it's inputs. We don't want to clear such strips
* from the stack.
@@ -1826,8 +1825,10 @@ static void seq_proxy_build_frame(
IMB_freeImBuf(ibuf);
}
-/* returns whether the file this context would read from even exist, if not, don't create the context
-*/
+/**
+ * Returns whether the file this context would read from even exist,
+ * if not, don't create the context
+ */
static bool seq_proxy_multiview_context_invalid(Sequence *seq, Scene *scene, const int view_id)
{
if ((scene->r.scemode & R_MULTIVIEW) == 0)
@@ -1862,8 +1863,9 @@ static bool seq_proxy_multiview_context_invalid(Sequence *seq, Scene *scene, con
return false;
}
-/** This returns the maximum possible number of required contexts
-*/
+/**
+ * This returns the maximum possible number of required contexts
+ */
static int seq_proxy_context_count(Sequence *seq, Scene *scene)
{
int num_views = 1;
diff --git a/source/blender/blenkernel/intern/speaker.c b/source/blender/blenkernel/intern/speaker.c
index a91d8657179..c027f3b38ca 100644
--- a/source/blender/blenkernel/intern/speaker.c
+++ b/source/blender/blenkernel/intern/speaker.c
@@ -85,11 +85,11 @@ Speaker *BKE_speaker_copy(Main *bmain, Speaker *spk)
return spkn;
}
-void BKE_speaker_make_local(Main *bmain, Speaker *spk)
+void BKE_speaker_make_local(Main *bmain, Speaker *spk, const bool force_local)
{
bool is_local = false, is_lib = false;
- /* - only lib users: do nothing
+ /* - only lib users: do nothing (unless force_local is set)
* - only local users: set flag
* - mixed: make copy
*/
@@ -100,7 +100,7 @@ void BKE_speaker_make_local(Main *bmain, Speaker *spk)
BKE_library_ID_test_usages(bmain, spk, &is_local, &is_lib);
- if (is_local) {
+ if (force_local || is_local) {
if (!is_lib) {
id_clear_lib_data(bmain, &spk->id);
BKE_id_expand_local(&spk->id);
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index b0d19320230..f73dbd8078f 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -3472,7 +3472,7 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
if (!flush && compareDrawOptions) {
/* also compare draw options and flush buffer if they're different
- * need for face selection highlight in edit mode */
+ * need for face selection highlight in edit mode */
flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
}
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index dcd60aaa702..155c7f04e53 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -917,11 +917,11 @@ Tex *BKE_texture_localize(Tex *tex)
/* ------------------------------------------------------------------------- */
-void BKE_texture_make_local(Main *bmain, Tex *tex)
+void BKE_texture_make_local(Main *bmain, Tex *tex, const bool force_local)
{
bool is_local = false, is_lib = false;
- /* - only lib users: do nothing
+ /* - only lib users: do nothing (unless force_local is set)
* - only local users: set flag
* - mixed: make copy
*/
@@ -932,7 +932,7 @@ void BKE_texture_make_local(Main *bmain, Tex *tex)
BKE_library_ID_test_usages(bmain, tex, &is_local, &is_lib);
- if (is_local) {
+ if (force_local || is_local) {
if (!is_lib) {
id_clear_lib_data(bmain, &tex->id);
BKE_id_expand_local(&tex->id);
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index 9795a8174f8..277aeaa7e42 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -176,11 +176,11 @@ World *localize_world(World *wrld)
return wrldn;
}
-void BKE_world_make_local(Main *bmain, World *wrld)
+void BKE_world_make_local(Main *bmain, World *wrld, const bool force_local)
{
bool is_local = false, is_lib = false;
- /* - only lib users: do nothing
+ /* - only lib users: do nothing (unless force_local is set)
* - only local users: set flag
* - mixed: make copy
*/
@@ -191,7 +191,7 @@ void BKE_world_make_local(Main *bmain, World *wrld)
BKE_library_ID_test_usages(bmain, wrld, &is_local, &is_lib);
- if (is_local) {
+ if (force_local || is_local) {
if (!is_lib) {
id_clear_lib_data(bmain, &wrld->id);
BKE_id_expand_local(&wrld->id);
diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h
index b4a465bbc74..0b1b4d8ee8c 100644
--- a/source/blender/blenlib/BLI_threads.h
+++ b/source/blender/blenlib/BLI_threads.h
@@ -42,7 +42,7 @@ extern "C" {
#endif
/* for tables, button in UI, etc */
-#define BLENDER_MAX_THREADS 64
+#define BLENDER_MAX_THREADS 1024
struct ListBase;
struct TaskScheduler;
diff --git a/source/blender/blenlib/intern/BLI_heap.c b/source/blender/blenlib/intern/BLI_heap.c
index 4bd404e5d73..d48e9fbddde 100644
--- a/source/blender/blenlib/intern/BLI_heap.c
+++ b/source/blender/blenlib/intern/BLI_heap.c
@@ -32,7 +32,6 @@
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
-#include "BLI_memarena.h"
#include "BLI_heap.h"
#include "BLI_strict_flags.h"
@@ -44,15 +43,37 @@ struct HeapNode {
unsigned int index;
};
+struct HeapNode_Chunk {
+ struct HeapNode_Chunk *prev;
+ unsigned int size;
+ unsigned int bufsize;
+ struct HeapNode buf[0];
+};
+
+/**
+ * Number of nodes to include per #HeapNode_Chunk when no reserved size is passed,
+ * or we allocate past the reserved number.
+ *
+ * \note Optimize number for 64kb allocs.
+ */
+#define HEAP_CHUNK_DEFAULT_NUM \
+ ((MEM_SIZE_OPTIMAL((1 << 16) - sizeof(struct HeapNode_Chunk))) / sizeof(HeapNode))
+
struct Heap {
unsigned int size;
unsigned int bufsize;
- MemArena *arena;
- HeapNode *freenodes;
HeapNode **tree;
+
+ struct {
+ /* Always keep at least one chunk (never NULL) */
+ struct HeapNode_Chunk *chunk;
+ /* when NULL, allocate a new chunk */
+ HeapNode *free;
+ } nodes;
};
-/* internal functions */
+/** \name Internal Functions
+ * \{ */
#define HEAP_PARENT(i) (((i) - 1) >> 1)
#define HEAP_LEFT(i) (((i) << 1) + 1)
@@ -92,11 +113,13 @@ static void heap_down(Heap *heap, unsigned int i)
smallest = ((l < size) && HEAP_COMPARE(heap->tree[l], heap->tree[i])) ? l : i;
- if ((r < size) && HEAP_COMPARE(heap->tree[r], heap->tree[smallest]))
+ if ((r < size) && HEAP_COMPARE(heap->tree[r], heap->tree[smallest])) {
smallest = r;
+ }
- if (smallest == i)
+ if (smallest == i) {
break;
+ }
heap_swap(heap, i, smallest);
i = smallest;
@@ -108,25 +131,74 @@ static void heap_up(Heap *heap, unsigned int i)
while (i > 0) {
const unsigned int p = HEAP_PARENT(i);
- if (HEAP_COMPARE(heap->tree[p], heap->tree[i]))
+ if (HEAP_COMPARE(heap->tree[p], heap->tree[i])) {
break;
-
+ }
heap_swap(heap, p, i);
i = p;
}
}
+/** \} */
-/***/
+
+/** \name Internal Memory Management
+ * \{ */
+
+static struct HeapNode_Chunk *heap_node_alloc_chunk(
+ unsigned int tot_nodes, struct HeapNode_Chunk *chunk_prev)
+{
+ struct HeapNode_Chunk *chunk = MEM_mallocN(
+ sizeof(struct HeapNode_Chunk) + (sizeof(HeapNode) * tot_nodes), __func__);
+ chunk->prev = chunk_prev;
+ chunk->bufsize = tot_nodes;
+ chunk->size = 0;
+ return chunk;
+}
+
+static struct HeapNode *heap_node_alloc(Heap *heap)
+{
+ HeapNode *node;
+
+ if (heap->nodes.free) {
+ node = heap->nodes.free;
+ heap->nodes.free = heap->nodes.free->ptr;
+ }
+ else {
+ struct HeapNode_Chunk *chunk = heap->nodes.chunk;
+ if (UNLIKELY(chunk->size == chunk->bufsize)) {
+ struct HeapNode_Chunk *chunk_next = heap_node_alloc_chunk(HEAP_CHUNK_DEFAULT_NUM, chunk);
+ chunk = chunk_next;
+ }
+ node = &chunk->buf[chunk->size++];
+ }
+
+ return node;
+}
+
+static void heap_node_free(Heap *heap, HeapNode *node)
+{
+ node->ptr = heap->nodes.free;
+ heap->nodes.free = node;
+}
+
+/** \} */
+
+
+/** \name Public Heap API
+ * \{ */
/* use when the size of the heap is known in advance */
Heap *BLI_heap_new_ex(unsigned int tot_reserve)
{
- Heap *heap = (Heap *)MEM_callocN(sizeof(Heap), __func__);
+ Heap *heap = MEM_mallocN(sizeof(Heap), __func__);
/* ensure we have at least one so we can keep doubling it */
+ heap->size = 0;
heap->bufsize = MAX2(1u, tot_reserve);
- heap->tree = (HeapNode **)MEM_mallocN(heap->bufsize * sizeof(HeapNode *), "BLIHeapTree");
- heap->arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "heap arena");
+ heap->tree = MEM_mallocN(heap->bufsize * sizeof(HeapNode *), "BLIHeapTree");
+
+ heap->nodes.chunk = heap_node_alloc_chunk((tot_reserve > 1) ? tot_reserve : HEAP_CHUNK_DEFAULT_NUM, NULL);
+ heap->nodes.free = NULL;
return heap;
}
@@ -146,8 +218,15 @@ void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp)
}
}
+ struct HeapNode_Chunk *chunk = heap->nodes.chunk;
+ do {
+ struct HeapNode_Chunk *chunk_prev;
+ chunk_prev = chunk->prev;
+ MEM_freeN(chunk);
+ chunk = chunk_prev;
+ } while (chunk);
+
MEM_freeN(heap->tree);
- BLI_memarena_free(heap->arena);
MEM_freeN(heap);
}
@@ -160,10 +239,16 @@ void BLI_heap_clear(Heap *heap, HeapFreeFP ptrfreefp)
ptrfreefp(heap->tree[i]->ptr);
}
}
-
heap->size = 0;
- BLI_memarena_clear(heap->arena);
- heap->freenodes = NULL;
+
+ /* Remove all except the last chunk */
+ while (heap->nodes.chunk->prev) {
+ struct HeapNode_Chunk *chunk_prev = heap->nodes.chunk->prev;
+ MEM_freeN(heap->nodes.chunk);
+ heap->nodes.chunk = chunk_prev;
+ }
+ heap->nodes.chunk->size = 0;
+ heap->nodes.free = NULL;
}
HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr)
@@ -175,13 +260,7 @@ HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr)
heap->tree = MEM_reallocN(heap->tree, heap->bufsize * sizeof(*heap->tree));
}
- if (heap->freenodes) {
- node = heap->freenodes;
- heap->freenodes = heap->freenodes->ptr;
- }
- else {
- node = (HeapNode *)BLI_memarena_alloc(heap->arena, sizeof(*node));
- }
+ node = heap_node_alloc(heap);
node->ptr = ptr;
node->value = value;
@@ -217,8 +296,7 @@ void *BLI_heap_popmin(Heap *heap)
BLI_assert(heap->size != 0);
- heap->tree[0]->ptr = heap->freenodes;
- heap->freenodes = heap->tree[0];
+ heap_node_free(heap, heap->tree[0]);
if (--heap->size) {
heap_swap(heap, 0, heap->size);
@@ -254,3 +332,4 @@ void *BLI_heap_node_ptr(HeapNode *node)
return node->ptr;
}
+/** \} */
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 5d0de6526b6..a7c625b0842 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -907,7 +907,10 @@ static void decode_blender_header(FileData *fd)
}
}
-static int read_file_dna(FileData *fd)
+/**
+ * \return Success if the file is read correctly, else set \a r_error_message.
+ */
+static bool read_file_dna(FileData *fd, const char **r_error_message)
{
BHead *bhead;
@@ -915,20 +918,25 @@ static int read_file_dna(FileData *fd)
if (bhead->code == DNA1) {
const bool do_endian_swap = (fd->flags & FD_FLAGS_SWITCH_ENDIAN) != 0;
- fd->filesdna = DNA_sdna_from_data(&bhead[1], bhead->len, do_endian_swap, true);
+ fd->filesdna = DNA_sdna_from_data(&bhead[1], bhead->len, do_endian_swap, true, r_error_message);
if (fd->filesdna) {
fd->compflags = DNA_struct_get_compareflags(fd->filesdna, fd->memsdna);
/* used to retrieve ID names from (bhead+1) */
fd->id_name_offs = DNA_elem_offset(fd->filesdna, "ID", "char", "name[]");
+
+ return true;
+ }
+ else {
+ return false;
}
- return 1;
}
else if (bhead->code == ENDB)
break;
}
- return 0;
+ *r_error_message = "Missing DNA block";
+ return false;
}
static int *read_file_thumbnail(FileData *fd)
@@ -1070,13 +1078,9 @@ static FileData *filedata_new(void)
fd->filedes = -1;
fd->gzfiledes = NULL;
-
- /* XXX, this doesn't need to be done all the time,
- * but it keeps us re-entrant, remove once we have
- * a lib that provides a nice lock. - zr
- */
- fd->memsdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false);
-
+
+ fd->memsdna = DNA_sdna_current_get();
+
fd->datamap = oldnewmap_new();
fd->globmap = oldnewmap_new();
fd->libmap = oldnewmap_new();
@@ -1089,8 +1093,11 @@ static FileData *blo_decode_and_check(FileData *fd, ReportList *reports)
decode_blender_header(fd);
if (fd->flags & FD_FLAGS_FILE_OK) {
- if (!read_file_dna(fd)) {
- BKE_reportf(reports, RPT_ERROR, "Failed to read blend file '%s', incomplete", fd->relabase);
+ const char *error_message = NULL;
+ if (read_file_dna(fd, &error_message) == false) {
+ BKE_reportf(reports, RPT_ERROR,
+ "Failed to read blend file '%s': %s",
+ fd->relabase, error_message);
blo_freefiledata(fd);
fd = NULL;
}
@@ -1267,9 +1274,7 @@ void blo_freefiledata(FileData *fd)
// Free all BHeadN data blocks
BLI_freelistN(&fd->listbase);
-
- if (fd->memsdna)
- DNA_sdna_free(fd->memsdna);
+
if (fd->filesdna)
DNA_sdna_free(fd->filesdna);
if (fd->compflags)
@@ -1842,7 +1847,7 @@ void blo_add_library_pointer_map(ListBase *old_mainlist, FileData *fd)
/* ********** END OLD POINTERS ****************** */
/* ********** READ FILE ****************** */
-static void switch_endian_structs(struct SDNA *filesdna, BHead *bhead)
+static void switch_endian_structs(const struct SDNA *filesdna, BHead *bhead)
{
int blocksize, nblocks;
char *data;
@@ -2137,6 +2142,7 @@ static PreviewImage *direct_link_preview_image(FileData *fd, PreviewImage *old_p
}
prv->gputexture[i] = NULL;
}
+ prv->icon_id = 0;
}
return prv;
@@ -2705,7 +2711,7 @@ static void lib_link_node_socket(FileData *fd, ID *UNUSED(id), bNodeSocket *sock
IDP_LibLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
-/* singe node tree (also used for material/scene trees), ntree is not NULL */
+/* Single node tree (also used for material/scene trees), ntree is not NULL */
static void lib_link_ntree(FileData *fd, ID *id, bNodeTree *ntree)
{
bNode *node;
@@ -2748,22 +2754,6 @@ static void lib_link_nodetree(FileData *fd, Main *main)
}
}
-/* get node tree stored locally in other IDs */
-static bNodeTree *nodetree_from_id(ID *id)
-{
- if (!id)
- return NULL;
- switch (GS(id->name)) {
- case ID_SCE: return ((Scene *)id)->nodetree;
- case ID_MA: return ((Material *)id)->nodetree;
- case ID_WO: return ((World *)id)->nodetree;
- case ID_LA: return ((Lamp *)id)->nodetree;
- case ID_TE: return ((Tex *)id)->nodetree;
- case ID_LS: return ((FreestyleLineStyle *)id)->nodetree;
- }
- return NULL;
-}
-
/* updates group node socket identifier so that
* external links to/from the group node are preserved.
*/
@@ -5957,11 +5947,9 @@ static void lib_link_screen(FileData *fd, Main *main)
snode->id = newlibadr(fd, sc->id.lib, snode->id);
snode->from = newlibadr(fd, sc->id.lib, snode->from);
- ntree = nodetree_from_id(snode->id);
- if (ntree)
- snode->nodetree = ntree;
- else {
- snode->nodetree = newlibadr_us(fd, sc->id.lib, snode->nodetree);
+ if (snode->id) {
+ ntree = ntreeFromID(snode->id);
+ snode->nodetree = ntree ? ntree : newlibadr_us(fd, sc->id.lib, snode->nodetree);
}
for (path = snode->treepath.first; path; path = path->next) {
@@ -6341,11 +6329,11 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
snode->id = restore_pointer_by_name(id_map, snode->id, USER_REAL);
snode->from = restore_pointer_by_name(id_map, snode->from, USER_IGNORE);
- ntree = nodetree_from_id(snode->id);
- if (ntree)
- snode->nodetree = ntree;
- else
- snode->nodetree = restore_pointer_by_name(id_map, (ID*)snode->nodetree, USER_REAL);
+ if (snode->id) {
+ ntree = ntreeFromID(snode->id);
+ snode->nodetree = ntree ? ntree :
+ restore_pointer_by_name(id_map, (ID *)snode->nodetree, USER_REAL);
+ }
for (path = snode->treepath.first; path; path = path->next) {
if (path == snode->treepath.first) {
diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h
index 42728fd406f..b054cd0031d 100644
--- a/source/blender/blenloader/intern/readfile.h
+++ b/source/blender/blenloader/intern/readfile.h
@@ -74,7 +74,7 @@ typedef struct FileData {
// general reading variables
struct SDNA *filesdna;
- struct SDNA *memsdna;
+ const struct SDNA *memsdna;
char *compflags; /* array of eSDNA_StructCompare */
int fileversion;
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index d631e1507e3..81b61f399c9 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -1130,5 +1130,18 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
}
+
+ if (!DNA_struct_elem_find(fd->filesdna, "BooleanModifierData", "float", "double_threshold")) {
+ Object *ob;
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ ModifierData *md;
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Boolean) {
+ BooleanModifierData *bmd = (BooleanModifierData *)md;
+ bmd->double_threshold = 1e-6f;
+ }
+ }
+ }
+ }
}
}
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 9c7aa87f3cc..c9f4858e545 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -301,7 +301,7 @@ static void ww_handle_init(eWriteWrapType ww_type, WriteWrap *r_ww)
typedef struct {
- struct SDNA *sdna;
+ const struct SDNA *sdna;
unsigned char *buf;
MemFile *compare, *current;
@@ -323,7 +323,7 @@ static WriteData *writedata_new(WriteWrap *ww)
{
WriteData *wd = MEM_callocN(sizeof(*wd), "writedata");
- wd->sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false);
+ wd->sdna = DNA_sdna_current_get();
wd->ww = ww;
@@ -355,8 +355,6 @@ static void writedata_do_write(WriteData *wd, const void *mem, int memlen)
static void writedata_free(WriteData *wd)
{
- DNA_sdna_free(wd->sdna);
-
MEM_freeN(wd->buf);
MEM_freeN(wd);
}
@@ -2042,7 +2040,7 @@ static void write_meshes(WriteData *wd, ListBase *idbase)
mesh->edit_btmesh = NULL;
/* now fill in polys to mfaces */
- /* XXX This breaks writing desing, by using temp allocated memory, which will likely generate
+ /* XXX This breaks writing design, by using temp allocated memory, which will likely generate
* duplicates in stored 'old' addresses.
* This is very bad, but do not see easy way to avoid this, aside from generating those data
* outside of save process itself.
diff --git a/source/blender/bmesh/operators/bmo_connect_pair.c b/source/blender/bmesh/operators/bmo_connect_pair.c
index 3eb6fe0cb97..241086fbf02 100644
--- a/source/blender/bmesh/operators/bmo_connect_pair.c
+++ b/source/blender/bmesh/operators/bmo_connect_pair.c
@@ -125,7 +125,7 @@ typedef struct PathLinkState {
/**
\name Min Dist Dir Util
-
+ *
* Simply getting the closest intersecting vert/edge is _not_ good enough. see T43792
* we need to get the closest in both directions since the absolute closest may be a dead-end.
*
diff --git a/source/blender/bmesh/operators/bmo_normals.c b/source/blender/bmesh/operators/bmo_normals.c
index f0738303d5c..73dbee25be3 100644
--- a/source/blender/bmesh/operators/bmo_normals.c
+++ b/source/blender/bmesh/operators/bmo_normals.c
@@ -86,7 +86,7 @@ static int recalc_face_normals_find_index(BMesh *bm, BMFace **faces, const int f
int f_start_index;
int i;
- /* Search for the best loop. Members are comapred in-order defined here. */
+ /* Search for the best loop. Members are compared in-order defined here. */
struct {
/* Squared distance from the center to the loops vertex 'l->v'.
* The normalized direction between the center and this vertex is also used for the dot-products below. */
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index f06f299d381..226f319cefd 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -904,6 +904,7 @@ void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Materia
i++;
}
}
+
// EMISSION
// color
if (ef->getEmission().isColor()) {
@@ -919,8 +920,22 @@ void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Materia
i++;
}
}
-
- if (ef->getOpacity().isTexture()) {
+
+ // TRANSPARENT
+ // color
+ if (ef->getOpacity().isColor()) {
+ col = ef->getTransparent().getColor();
+ float alpha = ef->getTransparency().getFloatValue();
+ if (col.isValid()) {
+ alpha *= col.getAlpha(); // Assuming A_ONE opaque mode
+ }
+ if (col.isValid() || alpha < 1.0) {
+ ma->alpha = alpha;
+ ma->mode |= MA_ZTRANSP | MA_TRANSP;
+ }
+ }
+ // texture
+ else if (ef->getOpacity().isTexture()) {
COLLADAFW::Texture ctex = ef->getOpacity().getTexture();
mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
if (mtex != NULL) {
@@ -930,22 +945,7 @@ void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Materia
ma->mode |= MA_ZTRANSP | MA_TRANSP;
}
}
- // TRANSPARENT
- // color
-#if 0
- if (ef->getOpacity().isColor()) {
- // XXX don't know what to do here
- }
- // texture
- else if (ef->getOpacity().isTexture()) {
- ctex = ef->getOpacity().getTexture();
- if (mtex != NULL) mtex->mapto &= MAP_ALPHA;
- else {
- mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
- if (mtex != NULL) mtex->mapto = MAP_ALPHA;
- }
- }
-#endif
+
material_texture_mapping_map[ma] = texindex_texarray_map;
}
diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp
index 13dc1eda580..76b51148509 100644
--- a/source/blender/collada/EffectExporter.cpp
+++ b/source/blender/collada/EffectExporter.cpp
@@ -30,6 +30,7 @@
#include <set>
#include "COLLADASWEffectProfile.h"
+#include "COLLADAFWColorOrTexture.h"
#include "EffectExporter.h"
#include "DocumentExporter.h"
@@ -217,9 +218,9 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
// transparency
if (ma->mode & MA_TRANSP) {
// Tod: because we are in A_ONE mode transparency is calculated like this:
- ep.setTransparency(ma->alpha, false, "transparency");
- // cot = getcol(1.0f, 1.0f, 1.0f, 1.0f);
- // ep.setTransparent(cot);
+ cot = getcol(1.0f, 1.0f, 1.0f, ma->alpha);
+ ep.setTransparent(cot);
+ ep.setOpaque(COLLADASW::EffectProfile::A_ONE);
}
// emission
diff --git a/source/blender/collada/ErrorHandler.cpp b/source/blender/collada/ErrorHandler.cpp
index b271604f839..98aa85f8a9b 100644
--- a/source/blender/collada/ErrorHandler.cpp
+++ b/source/blender/collada/ErrorHandler.cpp
@@ -79,7 +79,7 @@ bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error)
COLLADASaxFWL::SaxFWLError *saxFWLError = (COLLADASaxFWL::SaxFWLError *) error;
/*
* Accept non critical errors as warnings (i.e. texture not found)
- * This makes the importer more gracefull, so it now imports what makes sense.
+ * This makes the importer more graceful, so it now imports what makes sense.
*/
if (saxFWLError->getSeverity() == COLLADASaxFWL::IError::SEVERITY_ERROR_NONCRITICAL) {
isError = false;
diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp
index 649c86edd25..abe5130b9c1 100644
--- a/source/blender/collada/collada_utils.cpp
+++ b/source/blender/collada/collada_utils.cpp
@@ -539,8 +539,8 @@ void BoneExtended::set_bone_layers(std::string layerString, std::vector<std::str
}
/* If numeric layers and labeled layers are used in parallel (unlikely),
- we get a potential mixup. Just leave as is for now.
- */
+ * we get a potential mixup. Just leave as is for now.
+ */
this->bone_layers = bc_set_layer(this->bone_layers, pos);
}
diff --git a/source/blender/compositor/operations/COM_MaskOperation.cpp b/source/blender/compositor/operations/COM_MaskOperation.cpp
index d6e5fdf86bb..caafdfe8f0c 100644
--- a/source/blender/compositor/operations/COM_MaskOperation.cpp
+++ b/source/blender/compositor/operations/COM_MaskOperation.cpp
@@ -1,5 +1,4 @@
/*
-
* Copyright 2012, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 6bf9dbe3e54..9364c86196e 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -294,15 +294,16 @@ void DepsgraphNodeBuilder::build_scene(Main *bmain, Scene *scene)
for (Base *base = (Base *)scene->base.first; base; base = base->next) {
Object *ob = base->object;
+ /* object itself */
+ build_object(scene, base, ob);
+
/* object that this is a proxy for */
// XXX: the way that proxies work needs to be completely reviewed!
if (ob->proxy) {
ob->proxy->proxy_from = ob;
+ build_object(scene, base, ob->proxy);
}
- /* object itself */
- build_object(scene, base, ob);
-
/* Object dupligroup. */
if (ob->dup_group) {
build_group(scene, base, ob->dup_group);
@@ -395,12 +396,12 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob)
{
if (ob->id.tag & LIB_TAG_DOIT) {
IDDepsNode *id_node = m_graph->find_id_node(&ob->id);
- id_node->layers = base->lay;
+ id_node->layers |= base->lay;
return;
}
IDDepsNode *id_node = add_id_node(&ob->id);
- id_node->layers = base->lay;
+ id_node->layers |= base->lay;
ob->customdata_mask = 0;
/* standard components */
@@ -439,7 +440,7 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob)
}
case OB_ARMATURE: /* Pose */
- if (ob->id.lib != NULL && ob->proxy_from != NULL) {
+ if (ID_IS_LINKED_DATABLOCK(ob) && ob->proxy_from != NULL) {
build_proxy_rig(ob);
}
else {
@@ -478,12 +479,6 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob)
if (ob->gpd) {
build_gpencil(ob->gpd);
}
-
- if (ob->proxy != NULL) {
- add_operation_node(&ob->id, DEPSNODE_TYPE_PROXY, DEPSOP_TYPE_POST,
- function_bind(BKE_object_eval_proxy_backlink, _1, ob),
- DEG_OPCODE_PLACEHOLDER, "Parameters Eval");
- }
}
void DepsgraphNodeBuilder::build_object_transform(Scene *scene, Object *ob)
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index 9ca42e1e7d5..72005880161 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -264,18 +264,12 @@ void DepsgraphRelationBuilder::build_scene(Main *bmain, Scene *scene)
for (Base *base = (Base *)scene->base.first; base; base = base->next) {
Object *ob = base->object;
- /* Object that this is a proxy for.
- * Just makes sure backlink is correct.
- */
- if (ob->proxy) {
- ob->proxy->proxy_from = ob;
- }
-
/* object itself */
build_object(bmain, scene, ob);
/* object that this is a proxy for */
if (ob->proxy) {
+ ob->proxy->proxy_from = ob;
build_object(bmain, scene, ob->proxy);
/* TODO(sergey): This is an inverted relation, matches old depsgraph
* behavior and need to be investigated if it still need to be inverted.
@@ -439,7 +433,7 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o
}
case OB_ARMATURE: /* Pose */
- if (ob->id.lib != NULL && ob->proxy_from != NULL) {
+ if (ID_IS_LINKED_DATABLOCK(ob) && ob->proxy_from != NULL) {
build_proxy_rig(ob);
}
else {
@@ -919,6 +913,12 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
}
}
else {
+ if (dtar->id == id) {
+ /* Ignore input dependency if we're driving properties of the same ID,
+ * otherwise we'll be ending up in a cyclic dependency here.
+ */
+ continue;
+ }
/* resolve path to get node */
RNAPathKey target_key(dtar->id, dtar->rna_path ? dtar->rna_path : "");
add_relation(target_key, driver_key, DEPSREL_TYPE_DRIVER_TARGET, "[RNA Target -> Driver]");
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
index 9ba0b61a4f1..f9e1504b3ce 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
@@ -85,9 +85,6 @@ static void flush_init_func(void *data_v, int i)
id_node->done = 0;
comp_node->done = 0;
node->scheduled = false;
- if (comp_node->type == DEPSNODE_TYPE_PROXY) {
- node->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
- }
}
/* Flush updates from tagged nodes outwards until all affected nodes
diff --git a/source/blender/depsgraph/intern/nodes/deg_node.cc b/source/blender/depsgraph/intern/nodes/deg_node.cc
index 12d5ee00a63..db807d22b89 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node.cc
+++ b/source/blender/depsgraph/intern/nodes/deg_node.cc
@@ -181,6 +181,11 @@ void IDDepsNode::init(const ID *id, const string &UNUSED(subdata))
this->layers = (1 << 20) - 1;
this->eval_flags = 0;
+ /* For object we initialize layers to layer from base. */
+ if (GS(id) == ID_OB) {
+ this->layers = 0;
+ }
+
components = BLI_ghash_new(id_deps_node_hash_key,
id_deps_node_hash_key_cmp,
"Depsgraph id components hash");
diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c
index 6306926e0b2..6979a324b69 100644
--- a/source/blender/editors/armature/armature_utils.c
+++ b/source/blender/editors/armature/armature_utils.c
@@ -424,7 +424,9 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone
for (curBone = bones->first; curBone; curBone = curBone->next) {
eBone = MEM_callocN(sizeof(EditBone), "make_editbone");
- /* Copy relevant data from bone to eBone */
+ /* Copy relevant data from bone to eBone
+ * Keep selection logic in sync with ED_armature_sync_selection.
+ */
eBone->parent = parent;
BLI_strncpy(eBone->name, curBone->name, sizeof(eBone->name));
eBone->flag = curBone->flag;
@@ -435,11 +437,11 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone
eBone->flag |= BONE_TIPSEL;
if (eBone->parent && (eBone->flag & BONE_CONNECTED)) {
eBone->parent->flag |= BONE_TIPSEL;
- eBone->flag &= ~BONE_ROOTSEL; /* this is ignored when there is a connected parent, so unset it */
- }
- else {
- eBone->flag |= BONE_ROOTSEL;
}
+
+ /* For connected bones, take care when changing the selection when we have a connected parent,
+ * this flag is a copy of '(eBone->parent->flag & BONE_TIPSEL)'. */
+ eBone->flag |= BONE_ROOTSEL;
}
else {
/* if the bone is not selected, but connected to its parent
diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h
index 81e2558e765..602e203a381 100644
--- a/source/blender/editors/include/ED_keyframing.h
+++ b/source/blender/editors/include/ED_keyframing.h
@@ -325,18 +325,18 @@ bool ANIM_driver_vars_paste(struct ReportList *reports, struct FCurve *fcu, bool
/* Notes:
* - All the defines for this (User-Pref settings and Per-Scene settings)
* are defined in DNA_userdef_types.h
- * - Scene settings take presidence over those for userprefs, with old files
+ * - Scene settings take precedence over those for userprefs, with old files
* inheriting userpref settings for the scene settings
* - "On/Off + Mode" are stored per Scene, but "settings" are currently stored
* as userprefs
*/
/* Auto-Keying macros for use by various tools */
-/* check if auto-keyframing is enabled (per scene takes presidence) */
+/* check if auto-keyframing is enabled (per scene takes precedence) */
#define IS_AUTOKEY_ON(scene) ((scene) ? (scene->toolsettings->autokey_mode & AUTOKEY_ON) : (U.autokey_mode & AUTOKEY_ON))
-/* check the mode for auto-keyframing (per scene takes presidence) */
+/* check the mode for auto-keyframing (per scene takes precedence) */
#define IS_AUTOKEY_MODE(scene, mode) ((scene) ? (scene->toolsettings->autokey_mode == AUTOKEY_MODE_##mode) : (U.autokey_mode == AUTOKEY_MODE_##mode))
-/* check if a flag is set for auto-keyframing (per scene takes presidence) */
+/* check if a flag is set for auto-keyframing (per scene takes precedence) */
#define IS_AUTOKEY_FLAG(scene, flag) \
((scene) ? \
((scene->toolsettings->autokey_flag & AUTOKEY_FLAG_##flag) || (U.autokey_flag & AUTOKEY_FLAG_##flag)) \
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index b09284aa759..48c1e2d1996 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -208,6 +208,7 @@ eV3DProjStatus ED_view3d_project_float_global(const struct ARegion *ar, const fl
eV3DProjStatus ED_view3d_project_float_object(const struct ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag);
float ED_view3d_calc_zfac(const struct RegionView3D *rv3d, const float co[3], bool *r_flip);
+bool ED_view3d_clip_segment(const struct RegionView3D *rv3d, float ray_start[3], float ray_end[3]);
bool ED_view3d_win_to_ray(
const struct ARegion *ar, const struct View3D *v3d, const float mval[2],
float ray_start[3], float ray_normal[3], const bool do_clip);
@@ -218,6 +219,7 @@ void ED_view3d_global_to_vector(const struct RegionView3D *rv3d, const float coo
void ED_view3d_win_to_3d(const struct ARegion *ar, const float depth_pt[3], const float mval[2], float out[3]);
void ED_view3d_win_to_3d_int(const struct ARegion *ar, const float depth_pt[3], const int mval[2], float out[3]);
void ED_view3d_win_to_delta(const struct ARegion *ar, const float mval[2], float out[3], const float zfac);
+void ED_view3d_win_to_origin(const struct ARegion *ar, const float mval[2], float out[3]);
void ED_view3d_win_to_vector(const struct ARegion *ar, const float mval[2], float out[3]);
bool ED_view3d_win_to_segment(const struct ARegion *ar, struct View3D *v3d, const float mval[2],
float r_ray_start[3], float r_ray_end[3], const bool do_clip);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index ba7240be5d8..cbe8654ceb6 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -1138,7 +1138,7 @@ static bool ui_but_event_property_operator_string(const bContext *C, uiBut *but,
* as new items are added to the menu later on. It also optimises efficiency -
* a radial menu is best kept symmetrical, with as large an angle between
* items as possible, so that the gestural mouse movements can be fast and inexact.
-
+ *
* It starts off with two opposite sides for the first two items
* then joined by the one below for the third (this way, even with three items,
* the menu seems to still be 'in order' reading left to right). Then the fourth is
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 0a0ecf93d17..11703208b2a 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -1057,7 +1057,9 @@ static void ui_multibut_free(uiHandleButtonData *data, uiBlock *block)
}
}
-static bool ui_multibut_states_tag(uiBut *but_active, uiHandleButtonData *data, const wmEvent *event)
+static bool ui_multibut_states_tag(
+ uiBut *but_active,
+ uiHandleButtonData *data, const wmEvent *event)
{
uiBut *but;
float seg[2][2];
@@ -1668,7 +1670,9 @@ static bool ui_but_contains_point_px_icon(uiBut *but, ARegion *ar, const wmEvent
return BLI_rcti_isect_pt(&rect, x, y);
}
-static bool ui_but_drag_init(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static bool ui_but_drag_init(
+ bContext *C, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
/* prevent other WM gestures to start while we try to drag */
WM_gestures_remove(C);
@@ -1740,11 +1744,16 @@ static bool ui_but_drag_init(bContext *C, uiBut *but, uiHandleButtonData *data,
}
}
else {
- wmDrag *drag;
+ wmDrag *drag = WM_event_start_drag(
+ C, but->icon, but->dragtype, but->dragpoin,
+ ui_but_value_get(but), WM_DRAG_NOP);
- drag = WM_event_start_drag(C, but->icon, but->dragtype, but->dragpoin, ui_but_value_get(but), WM_DRAG_NOP);
- if (but->imb)
- WM_event_drag_image(drag, but->imb, but->imb_scale, BLI_rctf_size_x(&but->rect), BLI_rctf_size_y(&but->rect));
+ if (but->imb) {
+ WM_event_drag_image(
+ drag, but->imb, but->imb_scale,
+ BLI_rctf_size_x(&but->rect),
+ BLI_rctf_size_y(&but->rect));
+ }
}
return true;
}
@@ -1872,11 +1881,15 @@ static void ui_but_smart_controller_add(bContext *C, uiBut *from, uiBut *to)
/* (3) add a new controller */
if (WM_operator_name_call(C, "LOGIC_OT_controller_add", WM_OP_EXEC_DEFAULT, &props_ptr) & OPERATOR_FINISHED) {
cont = (bController *)ob->controllers.last;
- cont->type = CONT_LOGIC_AND; /* Quick fix to make sure we always have an AND controller. It might be nicer to make sure the operator gives us the right one though... */
+ /* Quick fix to make sure we always have an AND controller.
+ * It might be nicer to make sure the operator gives us the right one though... */
+ cont->type = CONT_LOGIC_AND;
/* (4) link the sensor->controller->actuator */
tmp_but = MEM_callocN(sizeof(uiBut), "uiBut");
- UI_but_link_set(tmp_but, (void **)&cont, (void ***)&(cont->links), &(cont->totlinks), from->link->tocode, (int)to->hardmin);
+ UI_but_link_set(
+ tmp_but, (void **)&cont, (void ***)&(cont->links),
+ &cont->totlinks, from->link->tocode, (int)to->hardmin);
tmp_but->hardmin = from->link->tocode;
tmp_but->poin = (char *)cont;
@@ -3180,7 +3193,9 @@ static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa
}
-static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static void ui_do_but_textedit(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
int retval = WM_UI_HANDLER_CONTINUE;
bool changed = false, inbox = false, update = false;
@@ -3233,7 +3248,8 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
if (data->searchbox)
inbox = ui_searchbox_inside(data->searchbox, event->x, event->y);
- /* for double click: we do a press again for when you first click on button (selects all text, no cursor pos) */
+ /* for double click: we do a press again for when you first click on button
+ * (selects all text, no cursor pos) */
if (event->val == KM_PRESS || event->val == KM_DBL_CLICK) {
float mx, my;
@@ -3477,7 +3493,9 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
ED_region_tag_redraw(data->region);
}
-static void ui_do_but_textedit_select(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static void ui_do_but_textedit_select(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
int mx, my, retval = WM_UI_HANDLER_CONTINUE;
@@ -3682,7 +3700,9 @@ static uiBut *ui_but_list_row_text_activate(
/* ***************** events for different button types *************** */
-static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_BUT(
+ bContext *C, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
@@ -3713,7 +3733,9 @@ static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, cons
return WM_UI_HANDLER_CONTINUE;
}
-static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_HOTKEYEVT(
+ bContext *C, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
@@ -3776,7 +3798,9 @@ static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data
return WM_UI_HANDLER_CONTINUE;
}
-static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_KEYEVT(
+ bContext *C, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
@@ -3802,7 +3826,9 @@ static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, c
return WM_UI_HANDLER_CONTINUE;
}
-static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_TEX(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY) && event->val == KM_PRESS) {
@@ -3830,7 +3856,9 @@ static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
return WM_UI_HANDLER_CONTINUE;
}
-static int ui_do_but_SEARCH_UNLINK(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_SEARCH_UNLINK(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
uiButExtraIconType extra_icon_type;
@@ -3877,7 +3905,9 @@ static int ui_do_but_SEARCH_UNLINK(bContext *C, uiBlock *block, uiBut *but, uiHa
return ui_do_but_TEX(C, block, but, data, event);
}
-static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_TOG(
+ bContext *C, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
#ifdef USE_DRAG_TOGGLE
if (data->state == BUTTON_STATE_HIGHLIGHT) {
@@ -3944,7 +3974,9 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons
return WM_UI_HANDLER_CONTINUE;
}
-static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_EXIT(
+ bContext *C, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
@@ -4092,7 +4124,7 @@ static float ui_numedit_apply_snap(
static bool ui_numedit_but_NUM(
uiBut *but, uiHandleButtonData *data,
- int mx,
+ int mx, const bool is_motion,
const enum eSnapType snap, float fac)
{
float deler, tempf, softmin, softmax, softrange;
@@ -4100,8 +4132,10 @@ static bool ui_numedit_but_NUM(
bool changed = false;
const bool is_float = ui_but_is_float(but);
- /* prevent unwanted drag adjustments */
- if (ui_but_dragedit_update_mval(data, mx) == false) {
+ /* prevent unwanted drag adjustments, test motion so modifier keys refresh. */
+ if ((is_motion || data->draglock) &&
+ (ui_but_dragedit_update_mval(data, mx) == false))
+ {
return changed;
}
@@ -4242,7 +4276,9 @@ static bool ui_numedit_but_NUM(
return changed;
}
-static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_NUM(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
int mx, my; /* mouse location scaled to fit the UI */
int screen_mx, screen_my; /* mouse location kept at screen pixel coords */
@@ -4324,6 +4360,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
}
}
else if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) {
+ const bool is_motion = (event->type == MOUSEMOVE);
const enum eSnapType snap = ui_event_to_snap(event);
float fac;
@@ -4335,8 +4372,9 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
fac = 1.0f;
if (event->shift) fac /= 10.0f;
- if (ui_numedit_but_NUM(but, data, (ui_but_is_cursor_warp(but) ? screen_mx : mx), snap, fac))
+ if (ui_numedit_but_NUM(but, data, (ui_but_is_cursor_warp(but) ? screen_mx : mx), is_motion, snap, fac)) {
ui_numedit_apply(C, block, but, data);
+ }
#ifdef USE_DRAG_MULTINUM
else if (data->multi_data.has_mbuts) {
if (data->multi_data.init == BUTTON_MULTI_INIT_ENABLE) {
@@ -4430,7 +4468,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
static bool ui_numedit_but_SLI(
uiBut *but, uiHandleButtonData *data,
- int mx, const bool is_horizontal,
+ int mx, const bool is_horizontal, const bool is_motion,
const bool snap, const bool shift)
{
float deler, f, tempf, softmin, softmax, softrange;
@@ -4440,8 +4478,9 @@ static bool ui_numedit_but_SLI(
/* note, 'offs' is really from the widget drawing rounded corners see 'widget_numslider' */
float offs;
- /* prevent unwanted drag adjustments */
+ /* prevent unwanted drag adjustments, test motion so modifier keys refresh. */
if ((but->type != UI_BTYPE_SCROLL) &&
+ (is_motion || data->draglock) &&
(ui_but_dragedit_update_mval(data, mx) == false))
{
return changed;
@@ -4541,7 +4580,9 @@ static bool ui_numedit_but_SLI(
return changed;
}
-static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_SLI(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
int mx, my, click = 0;
int retval = WM_UI_HANDLER_CONTINUE;
@@ -4634,12 +4675,14 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
}
}
else if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) {
+ const bool is_motion = (event->type == MOUSEMOVE);
#ifdef USE_DRAG_MULTINUM
data->multi_data.drag_dir[0] += abs(data->draglastx - mx);
data->multi_data.drag_dir[1] += abs(data->draglasty - my);
#endif
- if (ui_numedit_but_SLI(but, data, mx, true, event->ctrl != 0, event->shift != 0))
+ if (ui_numedit_but_SLI(but, data, mx, true, is_motion, event->ctrl != 0, event->shift != 0)) {
ui_numedit_apply(C, block, but, data);
+ }
#ifdef USE_DRAG_MULTINUM
else if (data->multi_data.has_mbuts) {
@@ -4722,7 +4765,9 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
return retval;
}
-static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_SCROLL(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
int mx, my /*, click = 0 */;
int retval = WM_UI_HANDLER_CONTINUE;
@@ -4765,8 +4810,10 @@ static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
else if (event->type == MOUSEMOVE) {
- if (ui_numedit_but_SLI(but, data, (horizontal) ? mx : my, horizontal, false, false))
+ const bool is_motion = (event->type == MOUSEMOVE);
+ if (ui_numedit_but_SLI(but, data, (horizontal) ? mx : my, horizontal, is_motion, false, false)) {
ui_numedit_apply(C, block, but, data);
+ }
}
retval = WM_UI_HANDLER_BREAK;
@@ -4775,7 +4822,9 @@ static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut
return retval;
}
-static int ui_do_but_GRIP(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_GRIP(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
int mx, my;
int retval = WM_UI_HANDLER_CONTINUE;
@@ -4826,7 +4875,9 @@ static int ui_do_but_GRIP(bContext *C, uiBlock *block, uiBut *but, uiHandleButto
return retval;
}
-static int ui_do_but_LISTROW(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_LISTROW(
+ bContext *C, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
/* hack to pass on ctrl+click and double click to overlapping text
@@ -4846,7 +4897,9 @@ static int ui_do_but_LISTROW(bContext *C, uiBut *but, uiHandleButtonData *data,
return ui_do_but_EXIT(C, but, data, event);
}
-static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_BLOCK(
+ bContext *C, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
@@ -5021,7 +5074,9 @@ static void ui_palette_set_active(uiBut *but)
}
}
-static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_COLOR(
+ bContext *C, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
if (data->state == BUTTON_STATE_HIGHLIGHT) {
/* first handle click on icondrag type button */
@@ -5154,7 +5209,9 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
return WM_UI_HANDLER_CONTINUE;
}
-static int ui_do_but_UNITVEC(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_UNITVEC(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
int mx, my;
@@ -5431,7 +5488,9 @@ static void ui_ndofedit_but_HSVCUBE(
ui_but_v3_set(but, data->vec);
}
-static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_HSVCUBE(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
int mx, my;
@@ -5693,7 +5752,9 @@ static void ui_ndofedit_but_HSVCIRCLE(
}
-static int ui_do_but_HSVCIRCLE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_HSVCIRCLE(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
ColorPicker *cpicker = but->custom_data;
float *hsv = cpicker->color_data;
@@ -5821,7 +5882,9 @@ static bool ui_numedit_but_COLORBAND(uiBut *but, uiHandleButtonData *data, int m
return changed;
}
-static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_COLORBAND(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
ColorBand *coba;
CBData *cbd;
@@ -5997,7 +6060,9 @@ static bool ui_numedit_but_CURVE(
return changed;
}
-static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_CURVE(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
int mx, my, a;
bool changed = false;
@@ -6165,7 +6230,9 @@ static bool ui_numedit_but_HISTOGRAM(uiBut *but, uiHandleButtonData *data, int m
return changed;
}
-static int ui_do_but_HISTOGRAM(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_HISTOGRAM(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
int mx, my;
@@ -6238,7 +6305,9 @@ static bool ui_numedit_but_WAVEFORM(uiBut *but, uiHandleButtonData *data, int mx
return changed;
}
-static int ui_do_but_WAVEFORM(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_WAVEFORM(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
int mx, my;
@@ -6292,7 +6361,9 @@ static int ui_do_but_WAVEFORM(bContext *C, uiBlock *block, uiBut *but, uiHandleB
return WM_UI_HANDLER_CONTINUE;
}
-static int ui_do_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_LINK(
+ bContext *C, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
VECCOPY2D(but->linkto, event->mval);
@@ -6355,7 +6426,9 @@ static bool ui_numedit_but_TRACKPREVIEW(
return changed;
}
-static int ui_do_but_TRACKPREVIEW(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+static int ui_do_but_TRACKPREVIEW(
+ bContext *C, uiBlock *block, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event)
{
int mx, my;
@@ -6851,7 +6924,8 @@ static bool ui_but_menu(bContext *C, uiBut *but)
WM_operator_properties_create(&ptr_props, "WM_OT_doc_view");
RNA_string_set(&ptr_props, "doc_id", buf);
- uiItemFullO(layout, "WM_OT_doc_view", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"),
+ uiItemFullO(layout, "WM_OT_doc_view",
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"),
ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0);
/* XXX inactive option, not for public! */
@@ -6860,7 +6934,8 @@ static bool ui_but_menu(bContext *C, uiBut *but)
RNA_string_set(&ptr_props, "doc_id", buf);
RNA_string_set(&ptr_props, "doc_new", RNA_property_description(but->rnaprop));
- uiItemFullO(layout, "WM_OT_doc_edit", "Submit Description", ICON_NONE, ptr_props.data, WM_OP_INVOKE_DEFAULT, 0);
+ uiItemFullO(layout, "WM_OT_doc_edit",
+ "Submit Description", ICON_NONE, ptr_props.data, WM_OP_INVOKE_DEFAULT, 0);
#endif
}
}
@@ -7440,7 +7515,8 @@ static bool ui_but_contains_point_px(ARegion *ar, uiBut *but, int x, int y)
/**
* Can we mouse over the button or is it hidden/disabled/layout.
- * Note: ctrl is kind of a hack currently, so that non-embossed UI_BTYPE_TEXT button behaves as a label when ctrl is not pressed.
+ * \note ctrl is kind of a hack currently,
+ * so that non-embossed UI_BTYPE_TEXT button behaves as a label when ctrl is not pressed.
*/
static bool ui_but_is_interactive(const uiBut *but, const bool labeledit)
{
@@ -7634,7 +7710,9 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
if (but->block->auto_open == true) { /* test for toolbox */
time = 1;
}
- else if ((but->block->flag & UI_BLOCK_LOOP && but->type != UI_BTYPE_BLOCK) || but->block->auto_open == true) {
+ else if ((but->block->flag & UI_BLOCK_LOOP && but->type != UI_BTYPE_BLOCK) ||
+ (but->block->auto_open == true))
+ {
time = 5 * U.menuthreshold2;
}
else if (U.uiflag & USER_MENUOPENAUTO) {
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index c1d7a9ada96..3660160a98c 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -1061,6 +1061,9 @@ static void icon_create_rect(struct PreviewImage *prv_img, enum eIconSizes size)
}
}
+static void ui_id_preview_image_render_size(
+ const bContext *C, Scene *scene, ID *id, PreviewImage *pi, int size, const bool use_job);
+
void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool big)
{
Icon *icon = BKE_icon_get(icon_id);
@@ -1076,22 +1079,19 @@ void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool bi
}
if (di) {
- if (di->type == ICON_TYPE_PREVIEW) {
- PreviewImage *prv = (icon->type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj;
-
- if (prv) {
- const int size = big ? ICON_SIZE_PREVIEW : ICON_SIZE_ICON;
-
- if (!prv->use_deferred || prv->rect[size] || (prv->flag[size] & PRV_USER_EDITED)) {
- return;
+ switch (di->type) {
+ case ICON_TYPE_PREVIEW:
+ {
+ ID *id = (icon->type != 0) ? icon->obj : NULL;
+ PreviewImage *prv = id ? BKE_previewimg_id_ensure(id) : icon->obj;
+
+ if (prv) {
+ const int size = big ? ICON_SIZE_PREVIEW : ICON_SIZE_ICON;
+
+ if (id || prv->use_deferred) {
+ ui_id_preview_image_render_size(C, NULL, id, prv, size, true);
+ }
}
-
- icon_create_rect(prv, size);
-
- /* Always using job (background) version. */
- ED_preview_icon_job(C, prv, NULL, prv->rect[size], prv->w[size], prv->h[size]);
-
- prv->flag[size] &= ~PRV_CHANGED;
}
}
}
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 01b10b7b032..1af6d902b18 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -416,7 +416,7 @@ bool UI_context_copy_to_selected_list(
if ((id_data == NULL) ||
(id_data->tag & LIB_TAG_DOIT) == 0 ||
- ID_IS_LINKED_DATABLOCK(id_data->lib) ||
+ ID_IS_LINKED_DATABLOCK(id_data) ||
(GS(id_data->name) != id_code))
{
BLI_remlink(&lb, link);
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 575b32e81e8..d4205c50ddc 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -110,7 +110,7 @@ bool ui_but_menu_step_poll(const uiBut *but)
{
BLI_assert(but->type == UI_BTYPE_MENU);
- /* currenly only RNA buttons */
+ /* currently only RNA buttons */
return ((but->menu_step_func != NULL) ||
(but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM));
}
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 7cc7b540cc0..3af25ba8894 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -301,7 +301,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
break;
case UI_ID_LOCAL:
if (id) {
- if (id_make_local(CTX_data_main(C), id, false)) {
+ if (id_make_local(CTX_data_main(C), id, false, false)) {
/* reassign to get get proper updates/notifiers */
idptr = RNA_property_pointer_get(&template->ptr, template->prop);
RNA_property_pointer_set(&template->ptr, template->prop, idptr);
@@ -453,7 +453,7 @@ static void template_ID(
else {
but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y,
NULL, 0, 0, 0, 0, TIP_("Direct linked library datablock, click to make local"));
- if (!id_make_local(CTX_data_main(C), id, true /* test */) || (idfrom && idfrom->lib))
+ if (!id_make_local(CTX_data_main(C), id, true /* test */, false) || (idfrom && idfrom->lib))
UI_but_flag_enable(but, UI_BUT_DISABLED);
}
diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c
index 69588928253..281a8b2a02d 100644
--- a/source/blender/editors/mesh/editmesh_intersect.c
+++ b/source/blender/editors/mesh/editmesh_intersect.c
@@ -563,7 +563,7 @@ static BMEdge *bm_face_split_edge_find(
if (UNLIKELY(BM_edge_exists(v_pivot, l_iter->e->v1) ||
BM_edge_exists(v_pivot, l_iter->e->v2)))
{
- /* very unlikley but will cause complications splicing the verts together,
+ /* very unlikely but will cause complications splicing the verts together,
* so just skip this case */
ok = false;
}
diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c
index e3e5863dc0e..2cdb00286aa 100644
--- a/source/blender/editors/mesh/editmesh_rip.c
+++ b/source/blender/editors/mesh/editmesh_rip.c
@@ -395,7 +395,7 @@ static void edbm_ripsel_deselect_helper(BMesh *bm, EdgeLoopPair *eloop_pairs,
* return an un-ordered array of loop pairs
* use for rebuilding face-fill
*
- * \note the method currenly used fails for edges with 3+ face users and gives
+ * \note the method currently used fails for edges with 3+ face users and gives
* nasty holes in the mesh, there isnt a good way of knowing ahead of time
* which loops will be split apart (its possible to figure out but quite involved).
* So for now this is a known limitation of current rip-fill option.
diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c
index bcdd170c53c..0fe43c44d7d 100644
--- a/source/blender/editors/object/object_group.c
+++ b/source/blender/editors/object/object_group.c
@@ -440,7 +440,7 @@ static int group_link_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
/* Early return check, if the object is already in group
- * we could sckip all the dependency check and just consider
+ * we could skip all the dependency check and just consider
* operator is finished.
*/
if (BKE_group_object_exists(group, ob)) {
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 55eb30ac2de..d8b0767562c 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -2103,11 +2103,11 @@ static void make_local_makelocalmaterial(Material *ma)
AnimData *adt;
int b;
- id_make_local(G.main, &ma->id, false);
+ id_make_local(G.main, &ma->id, false, false);
for (b = 0; b < MAX_MTEX; b++)
if (ma->mtex[b] && ma->mtex[b]->tex)
- id_make_local(G.main, &ma->mtex[b]->tex->id, false);
+ id_make_local(G.main, &ma->mtex[b]->tex->id, false, false);
adt = BKE_animdata_from_id(&ma->id);
if (adt) BKE_animdata_make_local(adt);
@@ -2235,7 +2235,7 @@ static int make_local_exec(bContext *C, wmOperator *op)
}
if (ob->id.lib)
- id_make_local(bmain, &ob->id, false);
+ id_make_local(bmain, &ob->id, false, false);
}
CTX_DATA_END;
@@ -2257,7 +2257,7 @@ static int make_local_exec(bContext *C, wmOperator *op)
id = ob->data;
if (id && (ELEM(mode, MAKE_LOCAL_SELECT_OBDATA, MAKE_LOCAL_SELECT_OBDATA_MATERIAL))) {
- id_make_local(bmain, id, false);
+ id_make_local(bmain, id, false, false);
adt = BKE_animdata_from_id(id);
if (adt) BKE_animdata_make_local(adt);
@@ -2289,7 +2289,7 @@ static int make_local_exec(bContext *C, wmOperator *op)
for (b = 0; b < MAX_MTEX; b++)
if (la->mtex[b] && la->mtex[b]->tex)
- id_make_local(bmain, &la->mtex[b]->tex->id, false);
+ id_make_local(bmain, &la->mtex[b]->tex->id, false, false);
}
else {
for (a = 0; a < ob->totcol; a++) {
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index 8501cea4e00..7db32957b42 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -538,7 +538,6 @@ static bool select_grouped_parent(bContext *C) /* Makes parent active and de-sel
/* can be NULL if parent in other scene */
if (baspar && BASE_SELECTABLE(v3d, baspar)) {
- ED_base_object_select(basact, BA_DESELECT);
ED_base_object_select(baspar, BA_SELECT);
ED_base_object_activate(C, baspar);
changed = true;
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 6e8aaebcccc..ad41fb23a69 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -3538,8 +3538,10 @@ static int vgroup_sort_name(const void *def_a_ptr, const void *def_b_ptr)
return BLI_natstrcmp(def_a->name, def_b->name);
}
-/* Sorts the weight groups according to the bone hierarchy of the
- associated armature (similar to how bones are ordered in the Outliner) */
+/**
+ * Sorts the weight groups according to the bone hierarchy of the
+ * associated armature (similar to how bones are ordered in the Outliner)
+ */
static void vgroup_sort_bone_hierarchy(Object *ob, ListBase *bonebase)
{
if (bonebase == NULL) {
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 1203889cf0e..8c5d25ad44d 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -1482,7 +1482,7 @@ static void render_view3d_do(RenderEngine *engine, const bContext *C)
void render_view3d_update(RenderEngine *engine, const bContext *C)
{
/* this shouldn't be needed and causes too many database rebuilds, but we
- * aren't actually tracking updates for all relevent datablocks so this is
+ * aren't actually tracking updates for all relevant datablocks so this is
* a catch-all for updates */
engine->update_flag |= RE_ENGINE_UPDATE_DATABASE;
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 6ed969cb270..d60c8e8dbd9 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -183,8 +183,8 @@ BLI_INLINE unsigned char f_to_char(const float val)
/* to avoid locking in tile initialization */
#define TILE_PENDING SET_INT_IN_POINTER(-1)
-/* This is mainly a convenience struct used so we can keep an array of images we use
- * Thir imbufs, etc, in 1 array, When using threads this array is copied for each thread
+/* This is mainly a convenience struct used so we can keep an array of images we use -
+ * their imbufs, etc, in 1 array, When using threads this array is copied for each thread
* because 'partRedrawRect' and 'touch' values would not be thread safe */
typedef struct ProjPaintImage {
Image *ima;
@@ -202,7 +202,7 @@ typedef struct ProjPaintImage {
*/
typedef struct ProjStrokeHandle {
/* Support for painting from multiple views at once,
- * currently used to impliment symmetry painting,
+ * currently used to implement symmetry painting,
* we can assume at least the first is set while painting. */
struct ProjPaintState *ps_views[8];
int ps_views_tot;
@@ -2174,7 +2174,7 @@ static void project_bucket_clip_face(
if ((*tot) < 3) {
/* no intersections to speak of, but more probable is that all face is just outside the
- * rectangle and culled due to float precision issues. Since above teste have failed,
+ * rectangle and culled due to float precision issues. Since above tests have failed,
* just dump triangle as is for painting */
*tot = 0;
copy_v2_v2(bucket_bounds_uv[*tot], uv1co); (*tot)++;
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index aa17cb02fe5..1431958501d 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -491,31 +491,30 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const float
}
/* Returns zero if no sculpt changes should be made, non-zero otherwise */
-static int paint_smooth_stroke(PaintStroke *stroke, float output[2], float *outpressure,
- const PaintSample *sample, PaintMode mode)
+static bool paint_smooth_stroke(
+ PaintStroke *stroke, const PaintSample *sample, PaintMode mode,
+ float r_mouse[2], float *r_pressure)
{
if (paint_supports_smooth_stroke(stroke->brush, mode)) {
float radius = stroke->brush->smooth_stroke_radius * stroke->zoom_2d;
- float u = stroke->brush->smooth_stroke_factor, v = 1.0f - u;
- float dx = stroke->last_mouse_position[0] - sample->mouse[0];
- float dy = stroke->last_mouse_position[1] - sample->mouse[1];
+ float u = stroke->brush->smooth_stroke_factor;
/* If the mouse is moving within the radius of the last move,
* don't update the mouse position. This allows sharp turns. */
- if (dx * dx + dy * dy < radius * radius)
- return 0;
+ if (len_squared_v2v2(stroke->last_mouse_position, sample->mouse) < SQUARE(radius)) {
+ return false;
+ }
- output[0] = sample->mouse[0] * v + stroke->last_mouse_position[0] * u;
- output[1] = sample->mouse[1] * v + stroke->last_mouse_position[1] * u;
- *outpressure = sample->pressure * v + stroke->last_pressure * u;
+ interp_v2_v2v2(r_mouse, sample->mouse, stroke->last_mouse_position, u);
+ *r_pressure = interpf(sample->pressure, stroke->last_pressure, u);
}
else {
- output[0] = sample->mouse[0];
- output[1] = sample->mouse[1];
- *outpressure = sample->pressure;
+ r_mouse[0] = sample->mouse[0];
+ r_mouse[1] = sample->mouse[1];
+ *r_pressure = sample->pressure;
}
- return 1;
+ return true;
}
static float paint_space_stroke_spacing(const Scene *scene, PaintStroke *stroke, float size_pressure, float spacing_pressure)
@@ -1190,7 +1189,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* airbrush */
((br->flag & BRUSH_AIRBRUSH) && event->type == TIMER && event->customdata == stroke->timer))
{
- if (paint_smooth_stroke(stroke, mouse, &pressure, &sample_average, mode)) {
+ if (paint_smooth_stroke(stroke, &sample_average, mode, mouse, &pressure)) {
if (stroke->stroke_started) {
if (paint_space_stroke_enabled(br, mode)) {
if (paint_space_stroke(C, op, mouse, pressure))
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index e874a969963..f21f62cc141 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -2379,9 +2379,8 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
swap_m4m4(vc->rv3d->persmat, mat);
/* calculate pivot for rotation around seletion if needed */
- if (U.uiflag & USER_ORBIT_SELECTION) {
- paint_last_stroke_update(scene, vc->ar, mval);
- }
+ /* also needed for "View Selected" on last stroke */
+ paint_last_stroke_update(scene, vc->ar, mval);
DAG_id_tag_update(ob->data, 0);
ED_region_tag_redraw(vc->ar);
@@ -2842,9 +2841,8 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
}
/* calculate pivot for rotation around seletion if needed */
- if (U.uiflag & USER_ORBIT_SELECTION) {
- paint_last_stroke_update(scene, vc->ar, mval);
- }
+ /* also needed for "View Selected" on last stroke */
+ paint_last_stroke_update(scene, vc->ar, mval);
ED_region_tag_redraw(vc->ar);
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index cc7531b9783..1305b76b5ad 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -1145,7 +1145,9 @@ static void calc_area_normal_and_center(
/* Return modified brush strength. Includes the direction of the brush, positive
* values pull vertices, negative values push. Uses tablet pressure and a
* special multiplier found experimentally to scale the strength factor. */
-static float brush_strength(const Sculpt *sd, const StrokeCache *cache, const float feather, const UnifiedPaintSettings *ups)
+static float brush_strength(
+ const Sculpt *sd, const StrokeCache *cache,
+ const float feather, const UnifiedPaintSettings *ups)
{
const Scene *scene = cache->vc->scene;
const Brush *brush = BKE_paint_brush((Paint *)&sd->paint);
@@ -3985,7 +3987,9 @@ static void sculpt_init_mirror_clipping(Object *ob, SculptSession *ss)
}
/* Initialize the stroke cache invariants from operator properties */
-static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSession *ss, wmOperator *op, const float mouse[2])
+static void sculpt_update_cache_invariants(
+ bContext *C, Sculpt *sd, SculptSession *ss,
+ wmOperator *op, const float mouse[2])
{
StrokeCache *cache = MEM_callocN(sizeof(StrokeCache), "stroke cache");
Scene *scene = CTX_data_scene(C);
@@ -4448,7 +4452,9 @@ static void sculpt_raycast_detail_cb(PBVHNode *node, void *data_v, float *tmin)
}
}
-static float sculpt_raycast_init(ViewContext *vc, const float mouse[2], float ray_start[3], float ray_end[3], float ray_normal[3], bool original)
+static float sculpt_raycast_init(
+ ViewContext *vc, const float mouse[2],
+ float ray_start[3], float ray_end[3], float ray_normal[3], bool original)
{
float obimat[4][4];
float dist;
@@ -4956,8 +4962,9 @@ void sculpt_dyntopo_node_layers_add(SculptSession *ss)
cd_node_layer_index = CustomData_get_named_layer_index(&ss->bm->vdata, CD_PROP_INT, layer_id);
}
- ss->cd_vert_node_offset = CustomData_get_n_offset(&ss->bm->vdata, CD_PROP_INT,
- cd_node_layer_index - CustomData_get_layer_index(&ss->bm->vdata, CD_PROP_INT));
+ ss->cd_vert_node_offset = CustomData_get_n_offset(
+ &ss->bm->vdata, CD_PROP_INT,
+ cd_node_layer_index - CustomData_get_layer_index(&ss->bm->vdata, CD_PROP_INT));
ss->bm->vdata.layers[cd_node_layer_index].flag |= CD_FLAG_TEMPORARY;
@@ -4967,8 +4974,9 @@ void sculpt_dyntopo_node_layers_add(SculptSession *ss)
cd_node_layer_index = CustomData_get_named_layer_index(&ss->bm->pdata, CD_PROP_INT, layer_id);
}
- ss->cd_face_node_offset = CustomData_get_n_offset(&ss->bm->pdata, CD_PROP_INT,
- cd_node_layer_index - CustomData_get_layer_index(&ss->bm->pdata, CD_PROP_INT));
+ ss->cd_face_node_offset = CustomData_get_n_offset(
+ &ss->bm->pdata, CD_PROP_INT,
+ cd_node_layer_index - CustomData_get_layer_index(&ss->bm->pdata, CD_PROP_INT));
ss->bm->pdata.layers[cd_node_layer_index].flag |= CD_FLAG_TEMPORARY;
}
@@ -5667,7 +5675,8 @@ static void SCULPT_OT_sample_detail_size(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- RNA_def_int_array(ot->srna, "location", 2, NULL, 0, SHRT_MAX, "Location", "Screen Coordinates of sampling", 0, SHRT_MAX);
+ RNA_def_int_array(ot->srna, "location", 2, NULL, 0, SHRT_MAX,
+ "Location", "Screen Coordinates of sampling", 0, SHRT_MAX);
}
diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c
index 1ff656243d6..14d0f909d23 100644
--- a/source/blender/editors/space_clip/clip_editor.c
+++ b/source/blender/editors/space_clip/clip_editor.c
@@ -634,7 +634,7 @@ typedef struct PrefetchQueue {
short render_size, render_flag;
/* If true prefecthing goes forward in time,
- * othwewise it goes backwards in time (starting from current frame).
+ * otherwise it goes backwards in time (starting from current frame).
*/
bool forward;
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index b837e516422..ae91a466495 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -826,7 +826,7 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
//if ((driver->flag & DRIVER_FLAG_SHOWDEBUG) == 0)
// return;
- /* No curve to modify/visualise the result?
+ /* No curve to modify/visualize the result?
* => We still want to show the 1-1 default...
*/
if ((fcu->totvert == 0) && BLI_listbase_is_empty(&fcu->modifiers)) {
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 06caf930988..1538842b139 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -1061,6 +1061,12 @@ typedef struct ImageOpenData {
ImageFormatData im_format;
} ImageOpenData;
+typedef struct ImageFrameRange {
+ struct ImageFrameRange *next, *prev;
+ ListBase frames;
+ char filepath[FILE_MAX];
+} ImageFrameRange;
+
typedef struct ImageFrame {
struct ImageFrame *next, *prev;
int framenr;
@@ -1086,10 +1092,10 @@ static void image_open_cancel(bContext *UNUSED(C), wmOperator *op)
* \param frames [out] the list of frame numbers found in the files matching the first one by name
* \param path [out] the full path of the first file in the list of image files
*/
-static void image_sequence_get_frames(PointerRNA *ptr, ListBase *frames, char *path, const size_t maxlen)
+static void image_sequence_get_frame_ranges(PointerRNA *ptr, ListBase *frames_all)
{
char dir[FILE_MAXDIR];
- bool is_first_entry = true;
+ ImageFrameRange *frame_range = NULL;
RNA_string_get(ptr, "directory", dir);
RNA_BEGIN (ptr, itemptr, "files")
@@ -1101,29 +1107,26 @@ static void image_sequence_get_frames(PointerRNA *ptr, ListBase *frames, char *p
ImageFrame *frame = MEM_callocN(sizeof(ImageFrame), "image_frame");
/* use the first file in the list as base filename */
- if (is_first_entry) {
- BLI_join_dirfile(path, maxlen, dir, filename);
- frame->framenr = BLI_stringdec(filename, base_head, base_tail, &digits);
- BLI_addtail(frames, frame);
- is_first_entry = false;
+ frame->framenr = BLI_stringdec(filename, head, tail, &digits);
+
+ /* still in the same sequence */
+ if ((frame_range != NULL) &&
+ (STREQLEN(base_head, head, FILE_MAX)) &&
+ (STREQLEN(base_tail, tail, FILE_MAX)))
+ {
+ /* pass */
}
else {
- frame->framenr = BLI_stringdec(filename, head, tail, &digits);
+ /* start a new frame range */
+ frame_range = MEM_callocN(sizeof(*frame_range), __func__);
+ BLI_join_dirfile(frame_range->filepath, sizeof(frame_range->filepath), dir, filename);
+ BLI_addtail(frames_all, frame_range);
- /* still in the same sequence */
- if ((STREQLEN(base_head, head, FILE_MAX)) &&
- (STREQLEN(base_tail, tail, FILE_MAX)))
- {
- BLI_addtail(frames, frame);
- }
- else {
- /* different file base name found, is ignored */
- MEM_freeN(filename);
- MEM_freeN(frame);
- break;
- }
+ BLI_strncpy(base_head, head, sizeof(base_head));
+ BLI_strncpy(base_tail, tail, sizeof(base_tail));
}
+ BLI_addtail(&frame_range->frames, frame);
MEM_freeN(filename);
}
RNA_END
@@ -1164,6 +1167,52 @@ static int image_sequence_get_len(ListBase *frames, int *ofs)
return 0;
}
+static Image *image_open_single(
+ wmOperator *op, const char *filepath, const char *relbase,
+ bool is_relative_path, bool use_multiview, int frame_seq_len)
+{
+ bool exists = false;
+ Image *ima = NULL;
+
+ errno = 0;
+ ima = BKE_image_load_exists_ex(filepath, &exists);
+
+ if (!ima) {
+ if (op->customdata) MEM_freeN(op->customdata);
+ BKE_reportf(op->reports, RPT_ERROR, "Cannot read '%s': %s",
+ filepath, errno ? strerror(errno) : TIP_("unsupported image format"));
+ return NULL;
+ }
+
+ if (!exists) {
+ /* only image path after save, never ibuf */
+ if (is_relative_path) {
+ BLI_path_rel(ima->name, relbase);
+ }
+
+ /* handle multiview images */
+ if (use_multiview) {
+ ImageOpenData *iod = op->customdata;
+ ImageFormatData *imf = &iod->im_format;
+
+ ima->flag |= IMA_USE_VIEWS;
+ ima->views_format = imf->views_format;
+ *ima->stereo3d_format = imf->stereo3d_format;
+ }
+ else {
+ ima->flag &= ~IMA_USE_VIEWS;
+ BKE_image_free_views(ima);
+ }
+
+ if ((frame_seq_len > 1) && (ima->source == IMA_SRC_FILE)) {
+ ima->source = IMA_SRC_SEQUENCE;
+ }
+ }
+
+ return ima;
+}
+
+
static int image_open_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
@@ -1174,70 +1223,60 @@ static int image_open_exec(bContext *C, wmOperator *op)
ImageOpenData *iod = op->customdata;
PointerRNA idptr;
Image *ima = NULL;
- char path[FILE_MAX];
+ char filepath[FILE_MAX];
int frame_seq_len = 0;
int frame_ofs = 1;
- bool exists = false;
const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
+ const bool use_multiview = RNA_boolean_get(op->ptr, "use_multiview");
- RNA_string_get(op->ptr, "filepath", path);
+ if (!op->customdata)
+ image_open_init(C, op);
+
+ RNA_string_get(op->ptr, "filepath", filepath);
if (RNA_struct_property_is_set(op->ptr, "directory") &&
RNA_struct_property_is_set(op->ptr, "files"))
{
- /* only to pass to imbuf */
- char path_full[FILE_MAX];
- BLI_strncpy(path_full, path, sizeof(path_full));
- BLI_path_abs(path_full, G.main->name);
+ bool was_relative = BLI_path_is_rel(filepath);
+ ListBase frame_ranges_all;
- if (!IMB_isanim(path_full)) {
- bool was_relative = BLI_path_is_rel(path);
- ListBase frames;
+ BLI_listbase_clear(&frame_ranges_all);
+ image_sequence_get_frame_ranges(op->ptr, &frame_ranges_all);
+ for (ImageFrameRange *frame_range = frame_ranges_all.first; frame_range; frame_range = frame_range->next) {
+ int frame_range_ofs;
+ int frame_range_seq_len = image_sequence_get_len(&frame_range->frames, &frame_range_ofs);
+ BLI_freelistN(&frame_range->frames);
- BLI_listbase_clear(&frames);
- image_sequence_get_frames(op->ptr, &frames, path, sizeof(path));
- frame_seq_len = image_sequence_get_len(&frames, &frame_ofs);
- BLI_freelistN(&frames);
+ char filepath_range[FILE_MAX];
+ BLI_strncpy(filepath_range, frame_range->filepath, sizeof(filepath_range));
if (was_relative) {
- BLI_path_rel(path, G.main->name);
+ BLI_path_rel(filepath_range, bmain->name);
}
- }
- }
-
- errno = 0;
- ima = BKE_image_load_exists_ex(path, &exists);
+ Image *ima_range = image_open_single(
+ op, filepath_range, bmain->name,
+ is_relative_path, use_multiview, frame_range_seq_len);
- if (!ima) {
- if (op->customdata) MEM_freeN(op->customdata);
- BKE_reportf(op->reports, RPT_ERROR, "Cannot read '%s': %s",
- path, errno ? strerror(errno) : TIP_("unsupported image format"));
- return OPERATOR_CANCELLED;
- }
-
- if (!op->customdata)
- image_open_init(C, op);
-
- /* handle multiview images */
- if (RNA_boolean_get(op->ptr, "use_multiview")) {
- ImageFormatData *imf = &iod->im_format;
-
- ima->flag |= IMA_USE_VIEWS;
- ima->views_format = imf->views_format;
- *ima->stereo3d_format = imf->stereo3d_format;
+ /* take the first image */
+ if ((ima == NULL) && ima_range) {
+ ima = ima_range;
+ frame_seq_len = frame_range_seq_len;
+ frame_ofs = frame_range_ofs;
+ }
+ }
+ BLI_freelistN(&frame_ranges_all);
}
else {
- ima->flag &= ~IMA_USE_VIEWS;
- BKE_image_free_views(ima);
+ /* for drag & drop etc. */
+ ima = image_open_single(
+ op, filepath, bmain->name,
+ is_relative_path, use_multiview, 1);
}
- /* only image path after save, never ibuf */
- if (is_relative_path) {
- if (!exists) {
- BLI_path_rel(ima->name, bmain->name);
- }
+ if (ima == NULL) {
+ return OPERATOR_CANCELLED;
}
/* hook into UI */
@@ -1245,11 +1284,8 @@ static int image_open_exec(bContext *C, wmOperator *op)
if (iod->pprop.prop) {
/* when creating new ID blocks, use is already 1, but RNA
- * pointer se also increases user, so this compensates it */
+ * pointer also increases user, so this compensates it */
id_us_min(&ima->id);
- if ((frame_seq_len > 1) && ima->source == IMA_SRC_FILE) {
- ima->source = IMA_SRC_SEQUENCE;
- }
RNA_id_pointer_create(&ima->id, &idptr);
RNA_property_pointer_set(&iod->pprop.ptr, iod->pprop.prop, idptr);
RNA_property_update(C, &iod->pprop.ptr, iod->pprop.prop);
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 7b7ea180604..14efd4338b4 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -1234,106 +1234,106 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
UI_icon_draw(x, y, ICON_DOT); break;
}
}
- else if (GS(tselem->id->name) == ID_OB) {
- Object *ob = (Object *)tselem->id;
- switch (ob->type) {
- case OB_LAMP:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LAMP); break;
- case OB_MESH:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_MESH); break;
- case OB_CAMERA:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CAMERA); break;
- case OB_CURVE:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CURVE); break;
- case OB_MBALL:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_META); break;
- case OB_LATTICE:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LATTICE); break;
- case OB_ARMATURE:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_ARMATURE); break;
- case OB_FONT:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_FONT); break;
- case OB_SURF:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SURFACE); break;
- case OB_SPEAKER:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SPEAKER); break;
- case OB_EMPTY:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_EMPTY); break;
-
+ else if (tselem->id) {
+ if (GS(tselem->id->name) == ID_OB) {
+ Object *ob = (Object *)tselem->id;
+ switch (ob->type) {
+ case OB_LAMP:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LAMP); break;
+ case OB_MESH:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_MESH); break;
+ case OB_CAMERA:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CAMERA); break;
+ case OB_CURVE:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_CURVE); break;
+ case OB_MBALL:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_META); break;
+ case OB_LATTICE:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_LATTICE); break;
+ case OB_ARMATURE:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_ARMATURE); break;
+ case OB_FONT:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_FONT); break;
+ case OB_SURF:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SURFACE); break;
+ case OB_SPEAKER:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_SPEAKER); break;
+ case OB_EMPTY:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_OB_EMPTY); break;
+ }
}
- }
- else {
- switch (GS(tselem->id->name)) {
- case ID_SCE:
- tselem_draw_icon_uibut(&arg, ICON_SCENE_DATA); break;
- case ID_ME:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_MESH); break;
- case ID_CU:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_CURVE); break;
- case ID_MB:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_META); break;
- case ID_LT:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_LATTICE); break;
- case ID_LA:
- {
- Lamp *la = (Lamp *)tselem->id;
-
- switch (la->type) {
- case LA_LOCAL:
- tselem_draw_icon_uibut(&arg, ICON_LAMP_POINT); break;
- case LA_SUN:
- tselem_draw_icon_uibut(&arg, ICON_LAMP_SUN); break;
- case LA_SPOT:
- tselem_draw_icon_uibut(&arg, ICON_LAMP_SPOT); break;
- case LA_HEMI:
- tselem_draw_icon_uibut(&arg, ICON_LAMP_HEMI); break;
- case LA_AREA:
- tselem_draw_icon_uibut(&arg, ICON_LAMP_AREA); break;
- default:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_LAMP); break;
+ else {
+ switch (GS(tselem->id->name)) {
+ case ID_SCE:
+ tselem_draw_icon_uibut(&arg, ICON_SCENE_DATA); break;
+ case ID_ME:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_MESH); break;
+ case ID_CU:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_CURVE); break;
+ case ID_MB:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_META); break;
+ case ID_LT:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_LATTICE); break;
+ case ID_LA:
+ {
+ Lamp *la = (Lamp *)tselem->id;
+ switch (la->type) {
+ case LA_LOCAL:
+ tselem_draw_icon_uibut(&arg, ICON_LAMP_POINT); break;
+ case LA_SUN:
+ tselem_draw_icon_uibut(&arg, ICON_LAMP_SUN); break;
+ case LA_SPOT:
+ tselem_draw_icon_uibut(&arg, ICON_LAMP_SPOT); break;
+ case LA_HEMI:
+ tselem_draw_icon_uibut(&arg, ICON_LAMP_HEMI); break;
+ case LA_AREA:
+ tselem_draw_icon_uibut(&arg, ICON_LAMP_AREA); break;
+ default:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_LAMP); break;
+ }
+ break;
}
- break;
+ case ID_MA:
+ tselem_draw_icon_uibut(&arg, ICON_MATERIAL_DATA); break;
+ case ID_TE:
+ tselem_draw_icon_uibut(&arg, ICON_TEXTURE_DATA); break;
+ case ID_IM:
+ tselem_draw_icon_uibut(&arg, ICON_IMAGE_DATA); break;
+ case ID_SPK:
+ case ID_SO:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_SPEAKER); break;
+ case ID_AR:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_ARMATURE); break;
+ case ID_CA:
+ tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_CAMERA); break;
+ case ID_KE:
+ tselem_draw_icon_uibut(&arg, ICON_SHAPEKEY_DATA); break;
+ case ID_WO:
+ tselem_draw_icon_uibut(&arg, ICON_WORLD_DATA); break;
+ case ID_AC:
+ tselem_draw_icon_uibut(&arg, ICON_ACTION); break;
+ case ID_NLA:
+ tselem_draw_icon_uibut(&arg, ICON_NLA); break;
+ case ID_TXT:
+ tselem_draw_icon_uibut(&arg, ICON_SCRIPT); break;
+ case ID_GR:
+ tselem_draw_icon_uibut(&arg, ICON_GROUP); break;
+ case ID_LI:
+ if (tselem->id->tag & LIB_TAG_MISSING) {
+ tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_BROKEN);
+ }
+ else if (((Library *)tselem->id)->parent) {
+ tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_INDIRECT);
+ }
+ else {
+ tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_DIRECT);
+ }
+ break;
+ case ID_LS:
+ tselem_draw_icon_uibut(&arg, ICON_LINE_DATA); break;
+ case ID_GD:
+ tselem_draw_icon_uibut(&arg, ICON_GREASEPENCIL); break;
}
- case ID_MA:
- tselem_draw_icon_uibut(&arg, ICON_MATERIAL_DATA); break;
- case ID_TE:
- tselem_draw_icon_uibut(&arg, ICON_TEXTURE_DATA); break;
- case ID_IM:
- tselem_draw_icon_uibut(&arg, ICON_IMAGE_DATA); break;
- case ID_SPK:
- case ID_SO:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_SPEAKER); break;
- case ID_AR:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_ARMATURE); break;
- case ID_CA:
- tselem_draw_icon_uibut(&arg, ICON_OUTLINER_DATA_CAMERA); break;
- case ID_KE:
- tselem_draw_icon_uibut(&arg, ICON_SHAPEKEY_DATA); break;
- case ID_WO:
- tselem_draw_icon_uibut(&arg, ICON_WORLD_DATA); break;
- case ID_AC:
- tselem_draw_icon_uibut(&arg, ICON_ACTION); break;
- case ID_NLA:
- tselem_draw_icon_uibut(&arg, ICON_NLA); break;
- case ID_TXT:
- tselem_draw_icon_uibut(&arg, ICON_SCRIPT); break;
- case ID_GR:
- tselem_draw_icon_uibut(&arg, ICON_GROUP); break;
- case ID_LI:
- if (tselem->id->tag & LIB_TAG_MISSING) {
- tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_BROKEN);
- }
- else if (((Library *)tselem->id)->parent) {
- tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_INDIRECT);
- }
- else {
- tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_DIRECT);
- }
- break;
- case ID_LS:
- tselem_draw_icon_uibut(&arg, ICON_LINE_DATA); break;
- case ID_GD:
- tselem_draw_icon_uibut(&arg, ICON_GREASEPENCIL); break;
}
}
}
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index f3235d07757..111e60e5159 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -439,7 +439,7 @@ static void id_local_cb(
Main *bmain = CTX_data_main(C);
/* if the ID type has no special local function,
* just clear the lib */
- if (id_make_local(bmain, tselem->id, false) == false) {
+ if (id_make_local(bmain, tselem->id, false, false) == false) {
id_clear_lib_data(bmain, tselem->id);
}
}
@@ -516,23 +516,16 @@ static void group_linkobs2scene_cb(
Group *group = (Group *)tselem->id;
GroupObject *gob;
Base *base;
-
+
for (gob = group->gobject.first; gob; gob = gob->next) {
base = BKE_scene_base_find(scene, gob->ob);
- if (base) {
- base->object->flag |= SELECT;
- base->flag |= SELECT;
- }
- else {
+ if (!base) {
/* link to scene */
- base = MEM_callocN(sizeof(Base), "add_base");
- BLI_addhead(&scene->base, base);
- base->lay = gob->ob->lay;
- gob->ob->flag |= SELECT;
- base->flag = gob->ob->flag;
- base->object = gob->ob;
+ base = BKE_scene_base_add(scene, gob->ob);
id_lib_extern((ID *)gob->ob); /* in case these are from a linked group */
}
+ base->object->flag |= SELECT;
+ base->flag |= SELECT;
}
}
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index c11a4d2e5a3..ede6b7ce469 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -1071,7 +1071,7 @@ static int sequencer_add_effect_strip_invoke(bContext *C, wmOperator *op, const
{
bool is_type_set = RNA_struct_property_is_set(op->ptr, "type");
int type = -1;
- int prop_flag = SEQPROP_ENDFRAME;
+ int prop_flag = SEQPROP_ENDFRAME | SEQPROP_NOPATHS;
if (is_type_set) {
type = RNA_enum_get(op->ptr, "type");
@@ -1106,9 +1106,6 @@ void SEQUENCER_OT_effect_strip_add(struct wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- WM_operator_properties_filesel(
- ot, 0, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_ENDFRAME);
RNA_def_enum(ot->srna, "type", sequencer_prop_effect_types, SEQ_TYPE_CROSS, "Type", "Sequencer effect type");
RNA_def_float_vector(ot->srna, "color", 3, NULL, 0.0f, 1.0f, "Color",
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 2b0bd7690e2..83fde34fcde 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -3075,7 +3075,9 @@ static int viewselected_exec(bContext *C, wmOperator *op)
else if (BKE_paint_select_face_test(ob)) {
ok = paintface_minmax(ob, min, max);
}
- else if (ob && (ob->mode & (OB_MODE_SCULPT | OB_MODE_TEXTURE_PAINT))) {
+ else if (ob &&
+ (ob->mode & (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)))
+ {
BKE_paint_stroke_get_average(scene, ob, min);
copy_v3_v3(max, min);
ok = true;
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index 2d050c4fa95..c5026fbb32b 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -274,6 +274,7 @@ bool ED_view3d_minmax_verts(struct Object *obedit, float min[3], float max[3]);
void VIEW3D_OT_snap_selected_to_grid(struct wmOperatorType *ot);
void VIEW3D_OT_snap_selected_to_cursor(struct wmOperatorType *ot);
+void VIEW3D_OT_snap_selected_to_active(struct wmOperatorType *ot);
void VIEW3D_OT_snap_cursor_to_grid(struct wmOperatorType *ot);
void VIEW3D_OT_snap_cursor_to_center(struct wmOperatorType *ot);
void VIEW3D_OT_snap_cursor_to_selected(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index 1c84ce3c985..b273f46fca3 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -214,6 +214,7 @@ void view3d_operatortypes(void)
WM_operatortype_append(VIEW3D_OT_snap_selected_to_grid);
WM_operatortype_append(VIEW3D_OT_snap_selected_to_cursor);
+ WM_operatortype_append(VIEW3D_OT_snap_selected_to_active);
WM_operatortype_append(VIEW3D_OT_snap_cursor_to_grid);
WM_operatortype_append(VIEW3D_OT_snap_cursor_to_center);
WM_operatortype_append(VIEW3D_OT_snap_cursor_to_selected);
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c
index ac05853e6d0..7448d4c658e 100644
--- a/source/blender/editors/space_view3d/view3d_project.c
+++ b/source/blender/editors/space_view3d/view3d_project.c
@@ -312,25 +312,9 @@ static void view3d_win_to_ray_segment(
if (!r_ray_co) r_ray_co = _ray_co;
if (!r_ray_dir) r_ray_dir = _ray_dir;
+ ED_view3d_win_to_origin(ar, mval, r_ray_co);
ED_view3d_win_to_vector(ar, mval, r_ray_dir);
- if (rv3d->is_persp) {
- copy_v3_v3(r_ray_co, rv3d->viewinv[3]);
- }
- else {
- r_ray_co[0] = 2.0f * mval[0] / ar->winx - 1.0f;
- r_ray_co[1] = 2.0f * mval[1] / ar->winy - 1.0f;
-
- if (rv3d->persp == RV3D_CAMOB) {
- r_ray_co[2] = -1.0f;
- }
- else {
- r_ray_co[2] = 0.0f;
- }
-
- mul_project_m4_v3(rv3d->persinv, r_ray_co);
- }
-
if ((rv3d->is_persp == false) && (rv3d->persp != RV3D_CAMOB)) {
end_offset = v3d->far / 2.0f;
start_offset = -end_offset;
@@ -347,7 +331,7 @@ static void view3d_win_to_ray_segment(
}
}
-BLI_INLINE bool view3d_clip_segment(const RegionView3D *rv3d, float ray_start[3], float ray_end[3])
+bool ED_view3d_clip_segment(const RegionView3D *rv3d, float ray_start[3], float ray_end[3])
{
if ((rv3d->rflag & RV3D_CLIPPING) &&
(clip_segment_v3_plane_n(ray_start, ray_end, rv3d->clip, 6,
@@ -384,7 +368,7 @@ bool ED_view3d_win_to_ray_ex(
/* bounds clipping */
if (do_clip) {
- return view3d_clip_segment(ar->regiondata, r_ray_start, ray_end);
+ return ED_view3d_clip_segment(ar->regiondata, r_ray_start, ray_end);
}
return true;
@@ -549,6 +533,37 @@ void ED_view3d_win_to_delta(const ARegion *ar, const float mval[2], float out[3]
}
/**
+ * Calculate a 3d origin from 2d window coordinates.
+ * \note Orthographic views have a less obvious origin,
+ * Since far clip can be a very large value resulting in numeric precision issues,
+ * the origin in this case is close to zero coordinate.
+ *
+ * \param ar The region (used for the window width and height).
+ * \param mval The area relative 2d location (such as event->mval converted to floats).
+ * \param out The resulting normalized world-space direction vector.
+ */
+void ED_view3d_win_to_origin(const ARegion *ar, const float mval[2], float out[3])
+{
+ RegionView3D *rv3d = ar->regiondata;
+ if (rv3d->is_persp) {
+ copy_v3_v3(out, rv3d->viewinv[3]);
+ }
+ else {
+ out[0] = 2.0f * mval[0] / ar->winx - 1.0f;
+ out[1] = 2.0f * mval[1] / ar->winy - 1.0f;
+
+ if (rv3d->persp == RV3D_CAMOB) {
+ out[2] = -1.0f;
+ }
+ else {
+ out[2] = 0.0f;
+ }
+
+ mul_project_m4_v3(rv3d->persinv, out);
+ }
+}
+
+/**
* Calculate a 3d direction vector from 2d window coordinates.
* This direction vector starts and the view in the direction of the 2d window coordinates.
* In orthographic view all window coordinates yield the same vector.
@@ -599,7 +614,7 @@ bool ED_view3d_win_to_segment(const ARegion *ar, View3D *v3d, const float mval[2
/* bounds clipping */
if (do_clip) {
- return view3d_clip_segment((RegionView3D *)ar->regiondata, r_ray_start, r_ray_end);
+ return ED_view3d_clip_segment((RegionView3D *)ar->regiondata, r_ray_start, r_ray_end);
}
return true;
diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c
index e8e7d3c62fb..5dd69cc66eb 100644
--- a/source/blender/editors/space_view3d/view3d_snap.c
+++ b/source/blender/editors/space_view3d/view3d_snap.c
@@ -44,6 +44,7 @@
#include "BKE_main.h"
#include "BKE_mball.h"
#include "BKE_object.h"
+#include "BKE_report.h"
#include "BKE_tracking.h"
#include "WM_api.h"
@@ -204,7 +205,7 @@ void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot)
/* *************************************************** */
-static int snap_sel_to_curs_exec(bContext *C, wmOperator *op)
+static int snap_selected_to_location(bContext *C, const float snap_target_global[3], const bool use_offset)
{
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
@@ -213,15 +214,10 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op)
TransVertStore tvs = {NULL};
TransVert *tv;
float imat[3][3], bmat[3][3];
- const float *cursor_global;
float center_global[3];
float offset_global[3];
int a;
- const bool use_offset = RNA_boolean_get(op->ptr, "use_offset");
-
- cursor_global = ED_view3d_cursor3d_get(scene, v3d);
-
if (use_offset) {
if ((v3d && v3d->around == V3D_AROUND_ACTIVE) &&
snap_calc_active_center(C, true, center_global))
@@ -231,11 +227,11 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op)
else {
snap_curs_to_sel_ex(C, center_global);
}
- sub_v3_v3v3(offset_global, cursor_global, center_global);
+ sub_v3_v3v3(offset_global, snap_target_global, center_global);
}
if (obedit) {
- float cursor_local[3];
+ float snap_target_local[3];
if (ED_transverts_check_obedit(obedit))
ED_transverts_create_from_obedit(&tvs, obedit, 0);
@@ -246,8 +242,8 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op)
invert_m3_m3(imat, bmat);
/* get the cursor in object space */
- sub_v3_v3v3(cursor_local, cursor_global, obedit->obmat[3]);
- mul_m3_v3(imat, cursor_local);
+ sub_v3_v3v3(snap_target_local, snap_target_global, obedit->obmat[3]);
+ mul_m3_v3(imat, snap_target_local);
if (use_offset) {
float offset_local[3];
@@ -262,7 +258,7 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op)
else {
tv = tvs.transverts;
for (a = 0; a < tvs.transverts_tot; a++, tv++) {
- copy_v3_v3(tv->loc, cursor_local);
+ copy_v3_v3(tv->loc, snap_target_local);
}
}
@@ -274,10 +270,10 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op)
bPoseChannel *pchan;
bArmature *arm = obact->data;
- float cursor_local[3];
+ float snap_target_local[3];
invert_m4_m4(obact->imat, obact->obmat);
- mul_v3_m4v3(cursor_local, obact->imat, cursor_global);
+ mul_v3_m4v3(snap_target_local, obact->imat, snap_target_global);
for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
if ((pchan->bone->flag & BONE_SELECTED) &&
@@ -311,7 +307,7 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op)
BKE_armature_loc_pose_to_bone(pchan, cursor_pose, cursor_pose);
}
else {
- BKE_armature_loc_pose_to_bone(pchan, cursor_local, cursor_pose);
+ BKE_armature_loc_pose_to_bone(pchan, snap_target_local, cursor_pose);
}
/* copy new position */
@@ -367,7 +363,7 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op)
add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global);
}
else {
- copy_v3_v3(cursor_parent, cursor_global);
+ copy_v3_v3(cursor_parent, snap_target_global);
}
sub_v3_v3(cursor_parent, ob->obmat[3]);
@@ -401,6 +397,18 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+static int snap_selected_to_cursor_exec(bContext *C, wmOperator *op)
+{
+ const bool use_offset = RNA_boolean_get(op->ptr, "use_offset");
+
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+
+ const float *snap_target_global = ED_view3d_cursor3d_get(scene, v3d);
+
+ return snap_selected_to_location(C, snap_target_global, use_offset);
+}
+
void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot)
{
/* identifiers */
@@ -409,7 +417,7 @@ void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot)
ot->idname = "VIEW3D_OT_snap_selected_to_cursor";
/* api callbacks */
- ot->exec = snap_sel_to_curs_exec;
+ ot->exec = snap_selected_to_cursor_exec;
ot->poll = ED_operator_view3d_active;
/* flags */
@@ -419,6 +427,34 @@ void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "use_offset", 1, "Offset", "");
}
+static int snap_selected_to_active_exec(bContext *C, wmOperator *op)
+{
+ float snap_target_global[3];
+
+ if (snap_calc_active_center(C, false, snap_target_global) == false) {
+ BKE_report(op->reports, RPT_ERROR, "No active element found!");
+ return OPERATOR_CANCELLED;
+ }
+
+ return snap_selected_to_location(C, snap_target_global, false);
+}
+
+void VIEW3D_OT_snap_selected_to_active(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Snap Selection to Active";
+ ot->description = "Snap selected item(s) to the active item";
+ ot->idname = "VIEW3D_OT_snap_selected_to_active";
+
+ /* api callbacks */
+ ot->exec = snap_selected_to_active_exec;
+ ot->poll = ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
/* *************************************************** */
static int snap_curs_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index ed6d49da681..724eba160a0 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -110,6 +110,12 @@ struct SnapObjectContext {
};
+enum eViewProj {
+ VIEW_PROJ_NONE = -1,
+ VIEW_PROJ_ORTHO = 0,
+ VIEW_PROJ_PERSP = -1,
+};
+
static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt);
@@ -137,10 +143,6 @@ struct RayCastAll_Data {
Object *ob;
unsigned int ob_uuid;
- /* DerivedMesh only */
- DerivedMesh *dm;
- const struct MLoopTri *dm_looptri;
-
/* output data */
ListBase *hit_list;
bool retval;
@@ -218,76 +220,177 @@ static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVH
/* -------------------------------------------------------------------- */
-/** \name Internal Object Snapping API
+/** \Common utilities
* \{ */
+
+/**
+ * Struct that kepts basic information about a BVHTree build from a editmesh.
+ */
+typedef struct BVHTreeFromMeshType {
+ void *userdata;
+ char type;
+} BVHTreeFromMeshType;
+
+typedef struct PreDefProject {
+ float pmat[4][4]; /* perspective matrix multiplied by object matrix */
+ float win_half[2];
+ float dist_px_sq;
+} PreDefProject;
+
+static void precalc_project(
+ PreDefProject *projectdefs, const ARegion *ar,
+ const float dist_px, float obmat[4][4])
+{
+ float (*pmat)[4] = ((RegionView3D *)ar->regiondata)->persmat;
+ if (obmat) {
+ mul_m4_m4m4(projectdefs->pmat, pmat, obmat);
+ }
+ else {
+ copy_m4_m4(projectdefs->pmat, pmat);
+ }
+ projectdefs->win_half[0] = ar->winx / 2;
+ projectdefs->win_half[1] = ar->winy / 2;
+ projectdefs->dist_px_sq = SQUARE(dist_px);
+}
+
+/**
+ * From a threshold (maximum distance to snap in pixels) returns:
+ *
+ * - The *real* distance (3D) if you are in orthographic-view.
+ * - The *tangent* (view cone radius at distance 1.0) if you are in perspective-view.
+ */
+static float dist_px_to_dist3d_or_tangent(const ARegion *ar, const float dist_px)
+{
+ const RegionView3D *rv3d = ar->regiondata;
+ if (ar->winx >= ar->winy)
+ return 2 * (dist_px / ar->winx) / rv3d->winmat[0][0];
+ else
+ return 2 * (dist_px / ar->winy) / rv3d->winmat[1][1];
+}
+
+static const float *get_vert_co(const BVHTreeFromMeshType *meshdata, const int index)
+{
+ switch (meshdata->type) {
+ case SNAP_MESH:
+ {
+ BVHTreeFromMesh *data = meshdata->userdata;
+ const MVert *vert = data->vert;
+ return vert[index].co;
+ }
+ case SNAP_EDIT_MESH:
+ {
+ BVHTreeFromEditMesh *data = meshdata->userdata;
+ BMVert *eve = BM_vert_at_index(data->em->bm, index);
+ return eve->co;
+ }
+ }
+ return NULL;
+}
+
+static void copy_vert_no(const BVHTreeFromMeshType *meshdata, const int index, float r_no[3])
+{
+ switch (meshdata->type) {
+ case SNAP_MESH:
+ {
+ BVHTreeFromMesh *data = meshdata->userdata;
+ const MVert *vert = data->vert;
+ normal_short_to_float_v3(r_no, vert->no);
+ break;
+ }
+ case SNAP_EDIT_MESH:
+ {
+ BVHTreeFromEditMesh *data = meshdata->userdata;
+ BMVert *eve = BM_vert_at_index(data->em->bm, index);
+ copy_v3_v3(r_no, eve->no);
+ break;
+ }
+ }
+}
+
+static void get_edge_verts(
+ const BVHTreeFromMeshType *meshdata, const int index,
+ const float *v_pair[2])
+{
+ switch (meshdata->type) {
+ case SNAP_MESH:
+ {
+ BVHTreeFromMesh *data = meshdata->userdata;
+
+ const MVert *vert = data->vert;
+ const MEdge *edge = data->edge + index;
+
+ v_pair[0] = vert[edge->v1].co;
+ v_pair[1] = vert[edge->v2].co;
+ break;
+ }
+ case SNAP_EDIT_MESH:
+ {
+ BVHTreeFromEditMesh *data = meshdata->userdata;
+ BMEdge *eed = BM_edge_at_index(data->em->bm, index);
+
+ v_pair[0] = eed->v1->co;
+ v_pair[1] = eed->v2->co;
+ break;
+ }
+ }
+}
+
#define V3_MUL_ELEM(a, b) \
(a)[0] * (b)[0], \
(a)[1] * (b)[1], \
(a)[2] * (b)[2]
-static bool test_vert(
- const float vco[3], const float vno[3], const float ray_co[3], const float ray_dir[3],
- const float ray_depth_range[2], const float scale[3], const bool is_persp,
+static bool test_vert_dist(
+ const float vco[3], const float ray_co[3], const float ray_dir[3],
+ const float ray_depth_range[2], const float scale[3],
/* read/write args */
float *ray_depth, float *dist_to_ray_sq,
/* return args */
- float r_co[3], float r_no[3])
+ float r_co[3])
{
const float vco_sc[3] = {V3_MUL_ELEM(vco, scale)};
- const float co_sc[3] = {V3_MUL_ELEM(ray_co, scale)};
+ const float origin_sc[3] = {V3_MUL_ELEM(ray_co, scale)};
const float dir_sc[3] = {V3_MUL_ELEM(ray_dir, scale)};
- float depth;
- float dist_sq = dist_squared_to_ray_v3(co_sc, dir_sc, vco_sc, &depth);
+ float depth, dist_sq;
+ dist_sq = dist_squared_to_ray_v3(origin_sc, dir_sc, vco_sc, &depth);
if (depth < ray_depth_range[0]) {
return false;
}
- if (is_persp) {
- dist_sq /= SQUARE(depth);
- }
-
if ((dist_sq < *dist_to_ray_sq) && (depth < *ray_depth)) {
*dist_to_ray_sq = dist_sq;
copy_v3_v3(r_co, vco);
- if (vno) {
- copy_v3_v3(r_no, vno);
- }
-
*ray_depth = depth;
return true;
}
return false;
}
-static bool test_edge(
+static bool test_edge_dist(
const float v1[3], const float v2[3], const float ray_co[3], const float ray_dir[3],
- const float ray_depth_range[2], const float scale[3], const bool is_persp,
+ const float ray_depth_range[2], const float scale[3],
/* read/write args */
float *ray_depth, float *dist_to_ray_sq,
/* return args */
- float r_co[3], float r_no[3])
+ float r_co[3])
{
const float v1_sc[3] = {V3_MUL_ELEM(v1, scale)};
const float v2_sc[3] = {V3_MUL_ELEM(v2, scale)};
const float co_sc[3] = {V3_MUL_ELEM(ray_co, scale)};
const float dir_sc[3] = {V3_MUL_ELEM(ray_dir, scale)};
- float tmp_co[3], depth;
- float dist_sq = dist_squared_ray_to_seg_v3(co_sc, dir_sc, v1_sc, v2_sc, tmp_co, &depth);
+ float tmp_co[3], depth, dist_sq;
+ dist_sq = dist_squared_ray_to_seg_v3(co_sc, dir_sc, v1_sc, v2_sc, tmp_co, &depth);
if (depth < ray_depth_range[0]) {
return false;
}
- if (is_persp) {
- dist_sq /= SQUARE(depth);
- }
-
if ((dist_sq < *dist_to_ray_sq) && (depth < *ray_depth)) {
*dist_to_ray_sq = dist_sq;
@@ -297,10 +400,6 @@ static bool test_edge(
copy_v3_v3(r_co, tmp_co);
- if (r_no) {
- sub_v3_v3v3(r_no, v1, v2);
- }
-
*ray_depth = depth;
return true;
}
@@ -309,50 +408,369 @@ static bool test_edge(
#undef V3_MUL_ELEM
+static bool test_projected_vert_dist(
+ PreDefProject *projectdefs,
+ const float co[3], const enum eViewProj view_proj,
+ const float mval[2], const float depth_range[2],
+ float r_co[3])
+{
+ float depth;
+ float(*pmat)[4] = projectdefs->pmat;
+ if (view_proj == VIEW_PROJ_PERSP) {
+ depth = mul_project_m4_v3_zfac(pmat, co);
+ if (depth < depth_range[0] || depth > depth_range[1]) {
+ return false;
+ }
+ }
+
+ float co2d[2] = {
+ (dot_m4_v3_row_x(pmat, co) + pmat[3][0]),
+ (dot_m4_v3_row_y(pmat, co) + pmat[3][1]),
+ };
+
+ if (view_proj == VIEW_PROJ_PERSP) {
+ mul_v2_fl(co2d, 1 / depth);
+ }
+
+ co2d[0] += 1.0f;
+ co2d[1] += 1.0f;
+ co2d[0] *= projectdefs->win_half[0];
+ co2d[1] *= projectdefs->win_half[1];
+
+ const float dist_sq = len_squared_v2v2(mval, co2d);
+ if (dist_sq < projectdefs->dist_px_sq) {
+ copy_v3_v3(r_co, co);
+ projectdefs->dist_px_sq = dist_sq;
+ return true;
+ }
+ return false;
+}
+
+static bool test_projected_edge_dist(
+ PreDefProject *projectdefs,
+ const float va[3], const float vb[3], const float ray_start[3], const float ray_normal[3],
+ const enum eViewProj view_proj, const float mval[2], const float depth_range[2],
+ float r_co[3])
+{
+
+ float tmp_co[3], depth;
+ dist_squared_ray_to_seg_v3(ray_start, ray_normal, va, vb, tmp_co, &depth);
+ return test_projected_vert_dist(projectdefs, tmp_co, view_proj, mval, depth_range, r_co);
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \Walk DFS
+ * \{ */
+typedef struct Object_Nearest2dPrecalc {
+ float ray_origin_local[3];
+ float ray_direction_local[3];
+ float ray_inv_dir[3];
+
+ PreDefProject projectdefs;
+ float mval[2];
+ bool sign[3];
+ bool r_axis_closest[3];
+ float depth_range[2];
+
+ void *userdata;
+ int index;
+ float co[3];
+ float no[3];
+} Object_Nearest2dPrecalc;
+
+
+static void nearest2d_precalc(
+ Object_Nearest2dPrecalc *neasrest_precalc, const ARegion *ar,
+ const float dist_px, float obmat[4][4],
+ const float ray_origin_local[3], const float ray_direction_local[3],
+ const float mval[2], const float depth_range[2])
+{
+ precalc_project(&neasrest_precalc->projectdefs, ar, dist_px, obmat);
+ copy_v3_v3(neasrest_precalc->ray_origin_local, ray_origin_local);
+ copy_v3_v3(neasrest_precalc->ray_direction_local, ray_direction_local);
+ copy_v2_v2(neasrest_precalc->mval, mval);
+ copy_v2_v2(neasrest_precalc->depth_range, depth_range);
+
+ for (int i = 0; i < 3; i++) {
+ neasrest_precalc->ray_inv_dir[i] =
+ (neasrest_precalc->ray_direction_local[i] != 0.0f) ?
+ (1.0f / neasrest_precalc->ray_direction_local[i]) : FLT_MAX;
+ neasrest_precalc->sign[i] = (neasrest_precalc->ray_inv_dir[i] < 0.0f);
+ neasrest_precalc->r_axis_closest[i] = true;
+ }
+}
+
+static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *user_data)
+{
+ Object_Nearest2dPrecalc *data = user_data;
+ float local_bvmin[3], local_bvmax[3];
+ if (data->sign[0]) {
+ local_bvmin[0] = bounds[0].max;
+ local_bvmax[0] = bounds[0].min;
+ }
+ else {
+ local_bvmin[0] = bounds[0].min;
+ local_bvmax[0] = bounds[0].max;
+ }
+ if (data->sign[1]) {
+ local_bvmin[1] = bounds[1].max;
+ local_bvmax[1] = bounds[1].min;
+ }
+ else {
+ local_bvmin[1] = bounds[1].min;
+ local_bvmax[1] = bounds[1].max;
+ }
+ if (data->sign[2]) {
+ local_bvmin[2] = bounds[2].max;
+ local_bvmax[2] = bounds[2].min;
+ }
+ else {
+ local_bvmin[2] = bounds[2].min;
+ local_bvmax[2] = bounds[2].max;
+ }
+
+ const float tmin[3] = {
+ (local_bvmin[0] - data->ray_origin_local[0]) * data->ray_inv_dir[0],
+ (local_bvmin[1] - data->ray_origin_local[1]) * data->ray_inv_dir[1],
+ (local_bvmin[2] - data->ray_origin_local[2]) * data->ray_inv_dir[2],
+ };
+ const float tmax[3] = {
+ (local_bvmax[0] - data->ray_origin_local[0]) * data->ray_inv_dir[0],
+ (local_bvmax[1] - data->ray_origin_local[1]) * data->ray_inv_dir[1],
+ (local_bvmax[2] - data->ray_origin_local[2]) * data->ray_inv_dir[2],
+ };
+ float va[3], vb[3];
+ float rtmin, rtmax;
+ int main_axis;
+
+ if ((tmax[0] <= tmax[1]) && (tmax[0] <= tmax[2])) {
+ rtmax = tmax[0];
+ va[0] = vb[0] = local_bvmax[0];
+ main_axis = 3;
+ data->r_axis_closest[0] = data->sign[0];
+ }
+ else if ((tmax[1] <= tmax[0]) && (tmax[1] <= tmax[2])) {
+ rtmax = tmax[1];
+ va[1] = vb[1] = local_bvmax[1];
+ main_axis = 2;
+ data->r_axis_closest[1] = data->sign[1];
+ }
+ else {
+ rtmax = tmax[2];
+ va[2] = vb[2] = local_bvmax[2];
+ main_axis = 1;
+ data->r_axis_closest[2] = data->sign[2];
+ }
+
+ if ((tmin[0] >= tmin[1]) && (tmin[0] >= tmin[2])) {
+ rtmin = tmin[0];
+ va[0] = vb[0] = local_bvmin[0];
+ main_axis -= 3;
+ data->r_axis_closest[0] = !data->sign[0];
+ }
+ else if ((tmin[1] >= tmin[0]) && (tmin[1] >= tmin[2])) {
+ rtmin = tmin[1];
+ va[1] = vb[1] = local_bvmin[1];
+ main_axis -= 1;
+ data->r_axis_closest[1] = !data->sign[1];
+ }
+ else {
+ rtmin = tmin[2];
+ va[2] = vb[2] = local_bvmin[2];
+ main_axis -= 2;
+ data->r_axis_closest[2] = !data->sign[2];
+ }
+ if (main_axis < 0) {
+ main_axis += 3;
+ }
+
+ /* if rtmin < rtmax, ray intersect `AABB` */
+ if (rtmin <= rtmax) {
+#ifdef IGNORE_BEHIND_RAY
+ /* `if rtmax < depth_min`, the whole `AABB` is behind us */
+ if (rtmax < min_depth) {
+ return fallback;
+ }
+#endif
+ const float proj = rtmin * data->ray_direction_local[main_axis];
+ data->r_axis_closest[main_axis] = (proj - va[main_axis]) < (vb[main_axis] - proj);
+ return true;
+ }
+#ifdef IGNORE_BEHIND_RAY
+ /* `if rtmin < depth_min`, the whole `AABB` is behing us */
+ else if (rtmin < min_depth) {
+ return fallback;
+ }
+#endif
+ if (data->sign[main_axis]) {
+ va[main_axis] = local_bvmax[main_axis];
+ vb[main_axis] = local_bvmin[main_axis];
+ }
+ else {
+ va[main_axis] = local_bvmin[main_axis];
+ vb[main_axis] = local_bvmax[main_axis];
+ }
+ float scale = fabsf(local_bvmax[main_axis] - local_bvmin[main_axis]);
+
+ float (*pmat)[4] = data->projectdefs.pmat;
+ float depth_a = mul_project_m4_v3_zfac(pmat, va);
+ float depth_b = depth_a + pmat[main_axis][3] * scale;
+
+ float va2d[2] = {
+ (dot_m4_v3_row_x(pmat, va) + pmat[3][0]),
+ (dot_m4_v3_row_y(pmat, va) + pmat[3][1]),
+ };
+ float vb2d[2] = {
+ (va2d[0] + pmat[main_axis][0] * scale) / depth_b,
+ (va2d[1] + pmat[main_axis][1] * scale) / depth_b,
+ };
+
+ va2d[0] /= depth_a;
+ va2d[1] /= depth_a;
+
+ va2d[0] += 1.0f;
+ va2d[1] += 1.0f;
+ vb2d[0] += 1.0f;
+ vb2d[1] += 1.0f;
+
+ va2d[0] *= data->projectdefs.win_half[0];
+ va2d[1] *= data->projectdefs.win_half[1];
+ vb2d[0] *= data->projectdefs.win_half[0];
+ vb2d[1] *= data->projectdefs.win_half[1];
+
+ //float dvec[2], edge[2], rdist;
+ //sub_v2_v2v2(dvec, data->mval, va2d);
+ //sub_v2_v2v2(edge, vb2d, va2d);
+ float rdist;
+ short dvec[2] = {data->mval[0] - va2d[0], data->mval[1] - va2d[1]};
+ short edge[2] = {vb2d[0] - va2d[0], vb2d[1] - va2d[1]};
+ float lambda = dvec[0] * edge[0] + dvec[1] * edge[1];
+ if (lambda != 0.0f) {
+ lambda /= edge[0] * edge[0] + edge[1] * edge[1];
+ if (lambda <= 0.0f) {
+ rdist = len_squared_v2v2(data->mval, va2d);
+ data->r_axis_closest[main_axis] = true;
+ }
+ else if (lambda >= 1.0f) {
+ rdist = len_squared_v2v2(data->mval, vb2d);
+ data->r_axis_closest[main_axis] = false;
+ }
+ else {
+ va2d[0] += edge[0] * lambda;
+ va2d[1] += edge[1] * lambda;
+ rdist = len_squared_v2v2(data->mval, va2d);
+ data->r_axis_closest[main_axis] = lambda < 0.5f;
+ }
+ }
+ else {
+ rdist = len_squared_v2v2(data->mval, va2d);
+ }
+ return rdist < data->projectdefs.dist_px_sq;
+}
+
+static bool cb_walk_leaf_snap_vert(const BVHTreeAxisRange *bounds, int index, void *userdata)
+{
+ struct Object_Nearest2dPrecalc *neasrest_precalc = userdata;
+ const float co[3] = {
+ (bounds[0].min + bounds[0].max) / 2,
+ (bounds[1].min + bounds[1].max) / 2,
+ (bounds[2].min + bounds[2].max) / 2,
+ };
+
+ /* Currently the `BLI_bvhtree_walk_dfs` is being used only in the perspective view mode (VIEW_PROJ_PERSP)
+ * It could be used in orthographic view mode too (VIEW_PROJ_ORTHO),
+ * but in this case the `BLI_bvhtree_find_nearest_to_ray` is more efficient.*/
+ if (test_projected_vert_dist(
+ &neasrest_precalc->projectdefs, co, VIEW_PROJ_PERSP,
+ neasrest_precalc->mval, neasrest_precalc->depth_range,
+ neasrest_precalc->co))
+ {
+ copy_vert_no(neasrest_precalc->userdata, index, neasrest_precalc->no);
+ neasrest_precalc->index = index;
+ }
+ return true;
+}
+
+static bool cb_walk_leaf_snap_edge(const BVHTreeAxisRange *UNUSED(bounds), int index, void *userdata)
+{
+ struct Object_Nearest2dPrecalc *neasrest_precalc = userdata;
+
+ const float *v_pair[2];
+ get_edge_verts(neasrest_precalc->userdata, index, v_pair);
+
+ /* Currently the `BLI_bvhtree_walk_dfs` is being used only in the perspective view mode (VIEW_PROJ_PERSP)
+ * It could be used in orthographic view mode too (VIEW_PROJ_ORTHO),
+ * but in this case the `BLI_bvhtree_find_nearest_to_ray` is more efficient.*/
+ if (test_projected_edge_dist(
+ &neasrest_precalc->projectdefs, v_pair[0], v_pair[1],
+ neasrest_precalc->ray_origin_local, neasrest_precalc->ray_direction_local,
+ VIEW_PROJ_PERSP, neasrest_precalc->mval, neasrest_precalc->depth_range,
+ neasrest_precalc->co))
+ {
+ sub_v3_v3v3(neasrest_precalc->no, v_pair[0], v_pair[1]);
+ neasrest_precalc->index = index;
+ }
+ return true;
+}
+
+static bool cb_nearest_walk_order(const BVHTreeAxisRange *UNUSED(bounds), char axis, void *userdata)
+{
+ const bool *r_axis_closest = ((struct Object_Nearest2dPrecalc *)userdata)->r_axis_closest;
+ return r_axis_closest[axis];
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Internal Object Snapping API
+ * \{ */
+
static bool snapArmature(
- Object *ob, bArmature *arm, float obmat[4][4],
- const short snap_to, const bool is_persp,
- const float ray_origin[3], const float ray_normal[3], const float ray_depth_range[2],
+ const ARegion *ar, Object *ob, bArmature *arm, float obmat[4][4],
+ const short snap_to, const float origin[3], const float dir[3],
+ const float mval[2], const enum eViewProj view_proj, const float depth_range[2],
/* read/write args */
- float *ray_depth, float *dist_to_ray_sq,
+ float *dist_px,
/* return args */
float r_loc[3], float *UNUSED(r_no))
{
- float imat[4][4];
- float ray_origin_local[3], ray_normal_local[3];
bool retval = false;
- invert_m4_m4(imat, obmat);
+ float ray_start_local[3], ray_normal_local[3];
+ if (snap_to != SCE_SNAP_MODE_VERTEX) {
+ float imat[4][4];
+ invert_m4_m4(imat, obmat);
- mul_v3_m4v3(ray_origin_local, imat, ray_origin);
- mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal);
+ copy_v3_v3(ray_start_local, origin);
+ copy_v3_v3(ray_normal_local, dir);
+ mul_m4_v3(imat, ray_start_local);
+ mul_mat3_m4_v3(imat, ray_normal_local);
+ }
- float ob_scale[3];
- mat4_to_size(ob_scale, obmat);
+ PreDefProject projectdefs;
+ precalc_project(&projectdefs, ar, *dist_px, obmat);
if (arm->edbo) {
- EditBone *eBone;
-
- for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
+ for (EditBone *eBone = arm->edbo->first; eBone; eBone = eBone->next) {
if (eBone->layer & arm->layer) {
/* skip hidden or moving (selected) bones */
if ((eBone->flag & (BONE_HIDDEN_A | BONE_ROOTSEL | BONE_TIPSEL)) == 0) {
switch (snap_to) {
case SCE_SNAP_MODE_VERTEX:
- retval |= test_vert(
- eBone->head, NULL, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
- retval |= test_vert(
- eBone->tail, NULL, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
+ retval |= test_projected_vert_dist(
+ &projectdefs, eBone->head, view_proj, mval, depth_range, r_loc);
+ retval |= test_projected_vert_dist(
+ &projectdefs, eBone->tail, view_proj, mval, depth_range, r_loc);
break;
case SCE_SNAP_MODE_EDGE:
- retval |= test_edge(
- eBone->head, eBone->tail, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
+ retval |= test_projected_edge_dist(
+ &projectdefs, eBone->head, eBone->tail, ray_start_local, ray_normal_local,
+ view_proj, mval, depth_range, r_loc);
break;
}
}
@@ -360,11 +778,8 @@ static bool snapArmature(
}
}
else if (ob->pose && ob->pose->chanbase.first) {
- bPoseChannel *pchan;
- Bone *bone;
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- bone = pchan->bone;
+ for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ Bone *bone = pchan->bone;
/* skip hidden bones */
if (bone && !(bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) {
const float *head_vec = pchan->pose_head;
@@ -372,26 +787,22 @@ static bool snapArmature(
switch (snap_to) {
case SCE_SNAP_MODE_VERTEX:
- retval |= test_vert(
- head_vec, NULL, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
- retval |= test_vert(
- tail_vec, NULL, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
+ retval |= test_projected_vert_dist(
+ &projectdefs, head_vec, view_proj, mval, depth_range, r_loc);
+ retval |= test_projected_vert_dist(
+ &projectdefs, tail_vec, view_proj, mval, depth_range, r_loc);
break;
case SCE_SNAP_MODE_EDGE:
- retval |= test_edge(
- head_vec, tail_vec, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
+ retval |= test_projected_edge_dist(
+ &projectdefs, head_vec, tail_vec, ray_start_local, ray_normal_local,
+ view_proj, mval, depth_range, r_loc);
break;
}
}
}
}
if (retval) {
+ *dist_px = sqrtf(projectdefs.dist_px_sq);
mul_m4_v3(obmat, r_loc);
return true;
}
@@ -399,39 +810,26 @@ static bool snapArmature(
}
static bool snapCurve(
- Object *ob, Curve *cu, float obmat[4][4],
- const short snap_to, const bool is_persp,
- const float ray_origin[3], const float ray_normal[3], const float ray_depth_range[2],
+ const ARegion *ar, Object *ob, Curve *cu, float obmat[4][4],
+ const short snap_to, const float mval[2], const enum eViewProj view_proj,
+ const float depth_range[2],
/* read/write args */
- float *ray_depth, float *dist_to_ray_sq,
+ float *dist_px,
/* return args */
float r_loc[3], float *UNUSED(r_no))
{
- float imat[4][4];
- float ray_origin_local[3], ray_normal_local[3];
bool retval = false;
- int u;
-
- Nurb *nu;
/* only vertex snapping mode (eg control points and handles) supported for now) */
if (snap_to != SCE_SNAP_MODE_VERTEX) {
return retval;
}
- invert_m4_m4(imat, obmat);
-
- copy_v3_v3(ray_origin_local, ray_origin);
- copy_v3_v3(ray_normal_local, ray_normal);
-
- mul_m4_v3(imat, ray_origin_local);
- mul_mat3_m4_v3(imat, ray_normal_local);
-
- float ob_scale[3];
- mat4_to_size(ob_scale, obmat);
+ PreDefProject projectdefs;
+ precalc_project(&projectdefs, ar, *dist_px, obmat);
- for (nu = (ob->mode == OB_MODE_EDIT ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) {
- for (u = 0; u < nu->pntsu; u++) {
+ for (Nurb *nu = (ob->mode == OB_MODE_EDIT ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) {
+ for (int u = 0; u < nu->pntsu; u++) {
switch (snap_to) {
case SCE_SNAP_MODE_VERTEX:
{
@@ -441,26 +839,20 @@ static bool snapCurve(
if (nu->bezt[u].f2 & SELECT || nu->bezt[u].hide != 0) {
break;
}
- retval |= test_vert(
- nu->bezt[u].vec[1], NULL, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
+ retval |= test_projected_vert_dist(
+ &projectdefs, nu->bezt[u].vec[1], view_proj, mval, depth_range, r_loc);
/* don't snap if handle is selected (moving), or if it is aligning to a moving handle */
if (!(nu->bezt[u].f1 & SELECT) &&
!(nu->bezt[u].h1 & HD_ALIGN && nu->bezt[u].f3 & SELECT))
{
- retval |= test_vert(
- nu->bezt[u].vec[0], NULL, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
+ retval |= test_projected_vert_dist(
+ &projectdefs, nu->bezt[u].vec[0], view_proj, mval, depth_range, r_loc);
}
if (!(nu->bezt[u].f3 & SELECT) &&
!(nu->bezt[u].h2 & HD_ALIGN && nu->bezt[u].f1 & SELECT))
{
- retval |= test_vert(
- nu->bezt[u].vec[2], NULL, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
+ retval |= test_projected_vert_dist(
+ &projectdefs, nu->bezt[u].vec[2], view_proj, mval, depth_range, r_loc);
}
}
else {
@@ -468,26 +860,20 @@ static bool snapCurve(
if (nu->bp[u].f1 & SELECT || nu->bp[u].hide != 0) {
break;
}
- retval |= test_vert(
- nu->bp[u].vec, NULL, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
+ retval |= test_projected_vert_dist(
+ &projectdefs, nu->bp[u].vec, view_proj, mval, depth_range, r_loc);
}
}
else {
/* curve is not visible outside editmode if nurb length less than two */
if (nu->pntsu > 1) {
if (nu->bezt) {
- retval |= test_vert(
- nu->bezt[u].vec[1], NULL, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
+ retval |= test_projected_vert_dist(
+ &projectdefs, nu->bezt[u].vec[1], view_proj, mval, depth_range, r_loc);
}
else {
- retval |= test_vert(
- nu->bp[u].vec, NULL, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
+ retval |= test_projected_vert_dist(
+ &projectdefs, nu->bp[u].vec, view_proj, mval, depth_range, r_loc);
}
}
}
@@ -499,6 +885,7 @@ static bool snapCurve(
}
}
if (retval) {
+ *dist_px = sqrtf(projectdefs.dist_px_sq);
mul_m4_v3(obmat, r_loc);
return true;
}
@@ -507,11 +894,11 @@ static bool snapCurve(
/* may extend later (for now just snaps to empty center) */
static bool snapEmpty(
- Object *ob, float obmat[4][4],
- const short snap_to, const bool is_persp,
- const float ray_origin[3], const float ray_normal[3], const float ray_depth_range[2],
+ const ARegion *ar, Object *ob, float obmat[4][4],
+ const short snap_to, const float mval[2], const enum eViewProj view_proj,
+ const float depth_range[2],
/* read/write args */
- float *ray_depth, float *dist_to_ray_sq,
+ float *dist_px,
/* return args */
float r_loc[3], float *UNUSED(r_no))
{
@@ -520,17 +907,19 @@ static bool snapEmpty(
if (ob->transflag & OB_DUPLI) {
return retval;
}
+
/* for now only vertex supported */
switch (snap_to) {
case SCE_SNAP_MODE_VERTEX:
{
- float ob_loc[3], ob_scale[3] = {1.0, 1.0, 1.0};
- copy_v3_v3(ob_loc, obmat[3]);
-
- retval |= test_vert(
- ob_loc, NULL, ray_origin, ray_normal,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
+ PreDefProject projectdefs;
+ precalc_project(&projectdefs, ar, *dist_px, NULL);
+ float tmp_co[3];
+ copy_v3_v3(tmp_co, obmat[3]);
+ if (test_projected_vert_dist(&projectdefs, tmp_co, view_proj, mval, depth_range, r_loc)) {
+ *dist_px = sqrtf(projectdefs.dist_px_sq);
+ retval = true;
+ }
break;
}
default:
@@ -541,19 +930,23 @@ static bool snapEmpty(
}
static bool snapCamera(
- Scene *scene, Object *object, float obmat[4][4],
- const short snap_to, const bool is_persp,
- const float ray_origin[3], const float ray_normal[3], const float ray_depth_range[2],
+ const SnapObjectContext *sctx, Object *object, float obmat[4][4],
+ const short snap_to, const float mval[2], const enum eViewProj view_proj,
+ const float depth_range[2],
/* read/write args */
- float *ray_depth, float *dist_to_ray_sq,
+ float *dist_px,
/* return args */
float r_loc[3], float *UNUSED(r_no))
{
+ Scene *scene = sctx->scene;
+
+ PreDefProject projectdefs;
+ precalc_project(&projectdefs, sctx->v3d_data.ar, *dist_px, NULL);
+
float orig_camera_mat[4][4], orig_camera_imat[4][4], imat[4][4];
bool retval = false;
MovieClip *clip = BKE_object_movieclip_get(scene, object, false);
MovieTracking *tracking;
- float ray_origin_local[3], ray_normal_local[3];
if (clip == NULL) {
return retval;
@@ -584,9 +977,6 @@ static bool snapCamera(
reconstructed_camera_imat[4][4];
float (*vertex_obmat)[4];
- copy_v3_v3(ray_origin_local, ray_origin);
- copy_v3_v3(ray_normal_local, ray_normal);
-
if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) {
BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object,
CFRA, reconstructed_camera_mat);
@@ -603,26 +993,16 @@ static bool snapCamera(
copy_v3_v3(bundle_pos, track->bundle_pos);
if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
- mul_m4_v3(orig_camera_imat, ray_origin_local);
- mul_mat3_m4_v3(orig_camera_imat, ray_normal_local);
vertex_obmat = orig_camera_mat;
}
else {
mul_m4_v3(reconstructed_camera_imat, bundle_pos);
- mul_m4_v3(imat, ray_origin_local);
- mul_mat3_m4_v3(imat, ray_normal_local);
vertex_obmat = obmat;
}
- float ob_scale[3];
- mat4_to_size(ob_scale, vertex_obmat);
-
- retval |= test_vert(
- bundle_pos, NULL, ray_origin_local, ray_normal_local,
- ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq,
- r_loc, NULL);
-
- mul_m4_v3(vertex_obmat, r_loc);
+ mul_m4_v3(vertex_obmat, bundle_pos);
+ retval |= test_projected_vert_dist(
+ &projectdefs, bundle_pos, view_proj, mval, depth_range, r_loc);
}
}
@@ -632,7 +1012,11 @@ static bool snapCamera(
break;
}
- return retval;
+ if (retval) {
+ *dist_px = sqrtf(projectdefs.dist_px_sq);
+ return true;
+ }
+ return false;
}
static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt)
@@ -643,44 +1027,45 @@ static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt)
struct NearestDM_Data {
void *bvhdata;
- bool is_persp;
- const float *ray_depth_range;
-
+ const float *depth_range;
float *ray_depth;
};
-static void test_vert_depth_cb(
+static void test_vert_ray_dist_cb(
void *userdata, const float origin[3], const float dir[3],
const float scale[3], int index, BVHTreeNearest *nearest)
{
struct NearestDM_Data *ndata = userdata;
- const BVHTreeFromMesh *data = ndata->bvhdata;
- const MVert *vert = data->vert + index;
+ const struct BVHTreeFromMeshType *data = ndata->bvhdata;
+
+ const float *co = get_vert_co(data, index);
- if (test_vert(
- vert->co, NULL, origin, dir, ndata->ray_depth_range, scale, ndata->is_persp,
- ndata->ray_depth, &nearest->dist_sq,
- nearest->co, NULL))
+ if (test_vert_dist(
+ co, origin, dir, ndata->depth_range,
+ scale, ndata->ray_depth, &nearest->dist_sq,
+ nearest->co))
{
- normal_short_to_float_v3(nearest->no, vert->no);
+ copy_vert_no(data, index, nearest->no);
nearest->index = index;
}
}
-static void test_edge_depth_cb(
+static void test_edge_ray_dist_cb(
void *userdata, const float origin[3], const float dir[3],
const float scale[3], int index, BVHTreeNearest *nearest)
{
struct NearestDM_Data *ndata = userdata;
- const BVHTreeFromMesh *data = ndata->bvhdata;
- const MVert *vert = data->vert;
- const MEdge *edge = data->edge + index;
-
- if (test_edge(
- vert[edge->v1].co, vert[edge->v2].co, origin, dir, ndata->ray_depth_range, scale, ndata->is_persp,
- ndata->ray_depth, &nearest->dist_sq,
- nearest->co, nearest->no))
+ BVHTreeFromMeshType *data = ndata->bvhdata;
+
+ const float *v_pair[2];
+ get_edge_verts(data, index, v_pair);
+
+ if (test_edge_dist(
+ v_pair[0], v_pair[1], origin, dir, ndata->depth_range,
+ scale, ndata->ray_depth, &nearest->dist_sq,
+ nearest->co))
{
+ sub_v3_v3v3(nearest->no, v_pair[0], v_pair[1]);
nearest->index = index;
}
}
@@ -688,10 +1073,11 @@ static void test_edge_depth_cb(
static bool snapDerivedMesh(
SnapObjectContext *sctx,
Object *ob, DerivedMesh *dm, float obmat[4][4], const unsigned int ob_index,
- const short snap_to, const bool is_persp, bool do_bb,
- const float ray_origin[3], const float ray_start[3], const float ray_normal[3], const float ray_depth_range[2],
+ const short snap_to, const float mval[2], const enum eViewProj view_proj, bool do_bb,
+ const float ray_origin[3], const float ray_start[3], const float ray_normal[3],
+ const float depth_range[2],
/* read/write args */
- float *ray_depth, float *dist_to_ray_sq,
+ float *ray_depth, float *dist_px,
/* return args */
float r_loc[3], float r_no[3], int *r_index,
ListBase *r_hit_list)
@@ -703,7 +1089,7 @@ static bool snapDerivedMesh(
return retval;
}
}
- if (snap_to == SCE_SNAP_MODE_EDGE) {
+ else if (snap_to == SCE_SNAP_MODE_EDGE) {
if (dm->getNumEdges(dm) == 0) {
return retval;
}
@@ -715,7 +1101,7 @@ static bool snapDerivedMesh(
}
{
- bool need_ray_start_correction_init = (snap_to == SCE_SNAP_MODE_FACE) && sctx->use_v3d && !is_persp;
+ bool need_ray_start_correction_init = (snap_to == SCE_SNAP_MODE_FACE) && (view_proj == VIEW_PROJ_ORTHO);
float imat[4][4];
float timat[3][3]; /* transpose inverse matrix for normals */
@@ -823,28 +1209,30 @@ static bool snapDerivedMesh(
}
}
+ if (!treedata || !treedata->tree) {
+ return retval;
+ }
+
if (snap_to == SCE_SNAP_MODE_FACE) {
/* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already
* been *inside* boundbox, leading to snap failures (see T38409).
* Note also ar might be null (see T38435), in this case we assume ray_start is ok!
*/
- if (sctx->use_v3d && !is_persp) { /* do_ray_start_correction */
+ if (view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */
if (need_ray_start_correction_init) {
/* We *need* a reasonably valid len_diff in this case.
* Use BHVTree to find the closest face from ray_start_local.
*/
- if (treedata && treedata->tree != NULL) {
- BVHTreeNearest nearest;
- nearest.index = -1;
- nearest.dist_sq = FLT_MAX;
- /* Compute and store result. */
- BLI_bvhtree_find_nearest(
- treedata->tree, ray_start_local, &nearest, treedata->nearest_callback, treedata);
- if (nearest.index != -1) {
- float dvec[3];
- sub_v3_v3v3(dvec, nearest.co, ray_start_local);
- len_diff = dot_v3v3(dvec, ray_normal_local);
- }
+ BVHTreeNearest nearest;
+ nearest.index = -1;
+ nearest.dist_sq = FLT_MAX;
+ /* Compute and store result. */
+ BLI_bvhtree_find_nearest(
+ treedata->tree, ray_start_local, &nearest, treedata->nearest_callback, treedata);
+ if (nearest.index != -1) {
+ float dvec[3];
+ sub_v3_v3v3(dvec, nearest.co, ray_start_local);
+ len_diff = dot_v3v3(dvec, ray_normal_local);
}
}
float ray_org_local[3];
@@ -856,8 +1244,7 @@ static bool snapDerivedMesh(
* away ray_start values (as returned in case of ortho view3d), see T38358.
*/
len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
- madd_v3_v3v3fl(ray_start_local, ray_org_local, ray_normal_local,
- len_diff + ray_depth_range[0]);
+ madd_v3_v3v3fl(ray_start_local, ray_org_local, ray_normal_local, len_diff + depth_range[0]);
local_depth -= len_diff;
}
else {
@@ -874,24 +1261,19 @@ static bool snapDerivedMesh(
data.local_scale = local_scale;
data.ob = ob;
data.ob_uuid = ob_index;
- data.dm = dm;
data.hit_list = r_hit_list;
data.retval = retval;
BLI_bvhtree_ray_cast_all(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- *ray_depth, raycast_all_cb, &data);
+ treedata->tree, ray_start_local, ray_normal_local, 0.0f,
+ *ray_depth, raycast_all_cb, &data);
retval = data.retval;
}
else {
- BVHTreeRayHit hit;
+ BVHTreeRayHit hit = {.index = -1, .dist = local_depth};
- hit.index = -1;
- hit.dist = local_depth;
-
- if (treedata->tree &&
- BLI_bvhtree_ray_cast(
+ if (BLI_bvhtree_ray_cast(
treedata->tree, ray_start_local, ray_normal_local, 0.0f,
&hit, treedata->raycast_callback, treedata) != -1)
{
@@ -900,12 +1282,15 @@ static bool snapDerivedMesh(
if (hit.dist <= *ray_depth) {
*ray_depth = hit.dist;
copy_v3_v3(r_loc, hit.co);
- copy_v3_v3(r_no, hit.no);
/* back to worldspace */
mul_m4_v3(obmat, r_loc);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
+
+ if (r_no) {
+ copy_v3_v3(r_no, hit.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+ }
retval = true;
@@ -917,51 +1302,78 @@ static bool snapDerivedMesh(
}
}
else {
- /* Vert & edge use nearly identical logic. */
- BLI_assert(ELEM(snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE));
+ const ARegion *ar = sctx->v3d_data.ar;
float ray_org_local[3];
-
copy_v3_v3(ray_org_local, ray_origin);
mul_m4_v3(imat, ray_org_local);
- BVHTreeNearest nearest;
+ BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_MESH};
- nearest.index = -1;
- nearest.dist_sq = *dist_to_ray_sq;
+ if (view_proj == VIEW_PROJ_PERSP) {
+ Object_Nearest2dPrecalc neasrest_precalc;
+ neasrest_precalc.userdata = &treedata_type;
+ neasrest_precalc.index = -1;
- struct NearestDM_Data userdata;
- userdata.bvhdata = treedata;
- userdata.is_persp = is_persp;
- userdata.ray_depth_range = ray_depth_range;
- userdata.ray_depth = ray_depth;
+ nearest2d_precalc(&neasrest_precalc, ar, *dist_px, obmat,
+ ray_org_local, ray_normal_local, mval, depth_range);
- float ob_scale[3];
- mat4_to_size(ob_scale, obmat);
+ BVHTree_WalkLeafCallback cb_walk_leaf =
+ (snap_to == SCE_SNAP_MODE_VERTEX) ?
+ cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
- BVHTree_NearestToRayCallback callback =
- (snap_to == SCE_SNAP_MODE_VERTEX) ?
- test_vert_depth_cb : test_edge_depth_cb;
+ BLI_bvhtree_walk_dfs(
+ treedata->tree,
+ cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest_precalc);
- if (treedata->tree &&
- (is_persp ?
- BLI_bvhtree_find_nearest_to_ray_angle(
- treedata->tree, ray_org_local, ray_normal_local,
- true, ob_scale, &nearest, callback, &userdata) :
- BLI_bvhtree_find_nearest_to_ray(
- treedata->tree, ray_org_local, ray_normal_local,
- true, ob_scale, &nearest, callback, &userdata)) != -1)
- {
- copy_v3_v3(r_loc, nearest.co);
- mul_m4_v3(obmat, r_loc);
- if (r_no) {
- copy_v3_v3(r_no, nearest.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
+ if (neasrest_precalc.index != -1) {
+ copy_v3_v3(r_loc, neasrest_precalc.co);
+ mul_m4_v3(obmat, r_loc);
+ if (r_no) {
+ copy_v3_v3(r_no, neasrest_precalc.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+ }
+ *dist_px = sqrtf(neasrest_precalc.projectdefs.dist_px_sq);
+
+ retval = true;
}
- *dist_to_ray_sq = nearest.dist_sq;
+ }
+ else {
+ BVHTreeNearest nearest;
- retval = true;
+ nearest.index = -1;
+ float dist_3d = dist_px_to_dist3d_or_tangent(ar, *dist_px);
+ nearest.dist_sq = SQUARE(dist_3d);
+
+
+ float ob_scale[3];
+ mat4_to_size(ob_scale, obmat);
+
+ struct NearestDM_Data userdata;
+ userdata.bvhdata = &treedata_type;
+ userdata.depth_range = depth_range;
+ userdata.ray_depth = ray_depth;
+
+ BVHTree_NearestToRayCallback cb_test_ray_dist =
+ (snap_to == SCE_SNAP_MODE_VERTEX) ?
+ test_vert_ray_dist_cb : test_edge_ray_dist_cb;
+
+ if (BLI_bvhtree_find_nearest_to_ray(
+ treedata->tree, ray_org_local, ray_normal_local,
+ false, ob_scale, &nearest, cb_test_ray_dist, &userdata) != -1)
+ {
+ copy_v3_v3(r_loc, nearest.co);
+ mul_m4_v3(obmat, r_loc);
+ if (r_no) {
+ copy_v3_v3(r_no, nearest.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+ }
+ *dist_px *= sqrtf(nearest.dist_sq) / dist_3d;
+
+ retval = true;
+ }
}
}
@@ -975,47 +1387,14 @@ static bool snapDerivedMesh(
return retval;
}
-static void test_bmvert_depth_cb(
- void *userdata, const float origin[3], const float dir[3],
- const float scale[3], int index, BVHTreeNearest *nearest)
-{
- struct NearestDM_Data *ndata = userdata;
- const BMEditMesh *em = ndata->bvhdata;
- BMVert *eve = BM_vert_at_index(em->bm, index);
-
- if (test_vert(
- eve->co, eve->no, origin, dir, ndata->ray_depth_range, scale, ndata->is_persp,
- ndata->ray_depth, &nearest->dist_sq,
- nearest->co, nearest->no))
- {
- nearest->index = index;
- }
-}
-
-static void test_bmedge_depth_cb(
- void *userdata, const float origin[3], const float dir[3],
- const float scale[3], int index, BVHTreeNearest *nearest)
-{
- struct NearestDM_Data *ndata = userdata;
- const BMEditMesh *em = ndata->bvhdata;
- BMEdge *eed = BM_edge_at_index(em->bm, index);
-
- if (test_edge(
- eed->v1->co, eed->v2->co, origin, dir, ndata->ray_depth_range, scale, ndata->is_persp,
- ndata->ray_depth, &nearest->dist_sq,
- nearest->co, nearest->no))
- {
- nearest->index = index;
- }
-}
-
static bool snapEditMesh(
SnapObjectContext *sctx,
Object *ob, BMEditMesh *em, float obmat[4][4], const unsigned int ob_index,
- const short snap_to, const bool is_persp,
- const float ray_origin[3], const float ray_start[3], const float ray_normal[3], const float ray_depth_range[2],
+ const short snap_to, const float mval[2], const enum eViewProj view_proj,
+ const float ray_origin[3], const float ray_start[3], const float ray_normal[3],
+ const float depth_range[2],
/* read/write args */
- float *ray_depth, float *dist_to_ray_sq,
+ float *ray_depth, float *dist_px,
/* return args */
float r_loc[3], float r_no[3], int *r_index,
ListBase *r_hit_list)
@@ -1143,6 +1522,10 @@ static bool snapEditMesh(
}
}
+ if (!treedata || !treedata->tree) {
+ return retval;
+ }
+
if (snap_to == SCE_SNAP_MODE_FACE) {
float ray_start_local[3];
copy_v3_v3(ray_start_local, ray_start);
@@ -1160,35 +1543,32 @@ static bool snapEditMesh(
* Note also ar might be null (see T38435), in this case we assume ray_start is ok!
*/
float len_diff = 0.0f;
- if (sctx->use_v3d && !is_persp) { /* do_ray_start_correction */
+ if (view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */
/* We *need* a reasonably valid len_diff in this case.
* Use BHVTree to find the closest face from ray_start_local.
*/
- if (treedata && treedata->tree != NULL) {
- BVHTreeNearest nearest;
- nearest.index = -1;
- nearest.dist_sq = FLT_MAX;
- /* Compute and store result. */
- if (BLI_bvhtree_find_nearest(
- treedata->tree, ray_start_local, &nearest, NULL, NULL) != -1)
- {
- float dvec[3];
- sub_v3_v3v3(dvec, nearest.co, ray_start_local);
- len_diff = dot_v3v3(dvec, ray_normal_local);
- float ray_org_local[3];
-
- copy_v3_v3(ray_org_local, ray_origin);
- mul_m4_v3(imat, ray_org_local);
-
- /* We pass a temp ray_start, set from object's boundbox,
- * to avoid precision issues with very far away ray_start values
- * (as returned in case of ortho view3d), see T38358.
- */
- len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
- madd_v3_v3v3fl(ray_start_local, ray_org_local, ray_normal_local,
- len_diff + ray_depth_range[0]);
- local_depth -= len_diff;
- }
+ BVHTreeNearest nearest;
+ nearest.index = -1;
+ nearest.dist_sq = FLT_MAX;
+ /* Compute and store result. */
+ if (BLI_bvhtree_find_nearest(
+ treedata->tree, ray_start_local, &nearest, NULL, NULL) != -1)
+ {
+ float dvec[3];
+ sub_v3_v3v3(dvec, nearest.co, ray_start_local);
+ len_diff = dot_v3v3(dvec, ray_normal_local);
+ float ray_org_local[3];
+
+ copy_v3_v3(ray_org_local, ray_origin);
+ mul_m4_v3(imat, ray_org_local);
+
+ /* We pass a temp ray_start, set from object's boundbox,
+ * to avoid precision issues with very far away ray_start values
+ * (as returned in case of ortho view3d), see T38358.
+ */
+ len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
+ madd_v3_v3v3fl(ray_start_local, ray_org_local, ray_normal_local, len_diff + depth_range[0]);
+ local_depth -= len_diff;
}
}
if (r_hit_list) {
@@ -1202,7 +1582,6 @@ static bool snapEditMesh(
data.local_scale = local_scale;
data.ob = ob;
data.ob_uuid = ob_index;
- data.dm = NULL;
data.hit_list = r_hit_list;
data.retval = retval;
@@ -1213,13 +1592,9 @@ static bool snapEditMesh(
retval = data.retval;
}
else {
- BVHTreeRayHit hit;
+ BVHTreeRayHit hit = {.index = -1, .dist = local_depth};
- hit.index = -1;
- hit.dist = local_depth;
-
- if (treedata->tree &&
- BLI_bvhtree_ray_cast(
+ if (BLI_bvhtree_ray_cast(
treedata->tree, ray_start_local, ray_normal_local, 0.0f,
&hit, treedata->raycast_callback, treedata) != -1)
{
@@ -1228,12 +1603,15 @@ static bool snapEditMesh(
if (hit.dist <= *ray_depth) {
*ray_depth = hit.dist;
copy_v3_v3(r_loc, hit.co);
- copy_v3_v3(r_no, hit.no);
/* back to worldspace */
mul_m4_v3(obmat, r_loc);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
+
+ if (r_no) {
+ copy_v3_v3(r_no, hit.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+ }
retval = true;
@@ -1245,51 +1623,78 @@ static bool snapEditMesh(
}
}
else {
- /* Vert & edge use nearly identical logic. */
- BLI_assert(ELEM(snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE));
+ const ARegion *ar = sctx->v3d_data.ar;
float ray_org_local[3];
-
copy_v3_v3(ray_org_local, ray_origin);
mul_m4_v3(imat, ray_org_local);
- BVHTreeNearest nearest;
+ BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_EDIT_MESH};
- nearest.index = -1;
- nearest.dist_sq = *dist_to_ray_sq;
+ if (view_proj == VIEW_PROJ_PERSP) {
+ Object_Nearest2dPrecalc neasrest_precalc;
+ neasrest_precalc.userdata = &treedata_type;
+ neasrest_precalc.index = -1;
- struct NearestDM_Data userdata;
- userdata.bvhdata = em;
- userdata.is_persp = is_persp;
- userdata.ray_depth_range = ray_depth_range;
- userdata.ray_depth = ray_depth;
+ nearest2d_precalc(&neasrest_precalc, ar, *dist_px, obmat,
+ ray_org_local, ray_normal_local, mval, depth_range);
- float ob_scale[3];
- mat4_to_size(ob_scale, obmat);
+ BVHTree_WalkLeafCallback cb_walk_leaf =
+ (snap_to == SCE_SNAP_MODE_VERTEX) ?
+ cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
- BVHTree_NearestToRayCallback callback =
- (snap_to == SCE_SNAP_MODE_VERTEX) ?
- test_bmvert_depth_cb : test_bmedge_depth_cb;
+ BLI_bvhtree_walk_dfs(
+ treedata->tree,
+ cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest_precalc);
- if (treedata->tree &&
- (is_persp ?
- BLI_bvhtree_find_nearest_to_ray_angle(
- treedata->tree, ray_org_local, ray_normal_local,
- false, ob_scale, &nearest, callback, &userdata) :
- BLI_bvhtree_find_nearest_to_ray(
- treedata->tree, ray_org_local, ray_normal_local,
- false, ob_scale, &nearest, callback, &userdata)) != -1)
- {
- copy_v3_v3(r_loc, nearest.co);
- mul_m4_v3(obmat, r_loc);
- if (r_no) {
- copy_v3_v3(r_no, nearest.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
+ if (neasrest_precalc.index != -1) {
+ copy_v3_v3(r_loc, neasrest_precalc.co);
+ mul_m4_v3(obmat, r_loc);
+ if (r_no) {
+ copy_v3_v3(r_no, neasrest_precalc.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+ }
+ *dist_px = sqrtf(neasrest_precalc.projectdefs.dist_px_sq);
+
+ retval = true;
}
- *dist_to_ray_sq = nearest.dist_sq;
+ }
+ else {
+ BVHTreeNearest nearest;
- retval = true;
+ nearest.index = -1;
+ float dist_3d = dist_px_to_dist3d_or_tangent(ar, *dist_px);
+ nearest.dist_sq = SQUARE(dist_3d);
+
+
+ float ob_scale[3];
+ mat4_to_size(ob_scale, obmat);
+
+ struct NearestDM_Data userdata;
+ userdata.bvhdata = &treedata_type;
+ userdata.depth_range = depth_range;
+ userdata.ray_depth = ray_depth;
+
+ BVHTree_NearestToRayCallback cb_test_ray_dist =
+ (snap_to == SCE_SNAP_MODE_VERTEX) ?
+ test_vert_ray_dist_cb : test_edge_ray_dist_cb;
+
+ if (BLI_bvhtree_find_nearest_to_ray(
+ treedata->tree, ray_org_local, ray_normal_local,
+ false, ob_scale, &nearest, cb_test_ray_dist, &userdata) != -1)
+ {
+ copy_v3_v3(r_loc, nearest.co);
+ mul_m4_v3(obmat, r_loc);
+ if (r_no) {
+ copy_v3_v3(r_no, nearest.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+ }
+ *dist_px *= sqrtf(nearest.dist_sq) / dist_3d;
+
+ retval = true;
+ }
}
}
@@ -1305,26 +1710,28 @@ static bool snapEditMesh(
/**
* \param use_obedit: Uses the coordinates of BMesh (if any) to do the snapping;
- * \param ray_depth_range:
- * - 0: distance from the ray_origin to the clipping plane min (can be negative).
- * - 1: maximum distance, elements outside this are ignored.
- * \param ray_depth: maximum depth allowed for r_co.
*
* \note Duplicate args here are documented at #snapObjectsRay
*/
static bool snapObject(
SnapObjectContext *sctx,
Object *ob, float obmat[4][4], const unsigned int ob_index,
- bool use_obedit, const short snap_to,
- const float ray_origin[3], const float ray_start[3], const float ray_normal[3], const float ray_depth_range[2],
+ bool use_obedit, const short snap_to, const float mval[2],
+ const float ray_origin[3], const float ray_start[3], const float ray_normal[3],
+ const float depth_range[2],
/* read/write args */
- float *ray_depth, float *dist_to_ray_sq,
+ float *ray_depth, float *dist_px,
/* return args */
float r_loc[3], float r_no[3], int *r_index,
Object **r_ob, float r_obmat[4][4],
ListBase *r_hit_list)
{
- const bool is_persp = sctx->use_v3d && ((RegionView3D *)sctx->v3d_data.ar->regiondata)->is_persp;
+ const enum eViewProj view_proj =
+ ((sctx->use_v3d == false) || (mval == NULL)) ? VIEW_PROJ_NONE :
+ (((RegionView3D *)sctx->v3d_data.ar->regiondata)->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO);
+
+ const ARegion *ar = sctx->v3d_data.ar;
+
bool retval = false;
if (ob->type == OB_MESH) {
@@ -1334,9 +1741,9 @@ static bool snapObject(
em = BKE_editmesh_from_object(ob);
retval = snapEditMesh(
sctx, ob, em, obmat, ob_index,
- snap_to, is_persp,
- ray_origin, ray_start, ray_normal, ray_depth_range,
- ray_depth, dist_to_ray_sq,
+ snap_to, mval, view_proj,
+ ray_origin, ray_start, ray_normal, depth_range,
+ ray_depth, dist_px,
r_loc, r_no, r_index,
r_hit_list);
}
@@ -1353,42 +1760,43 @@ static bool snapObject(
}
retval = snapDerivedMesh(
sctx, ob, dm, obmat, ob_index,
- snap_to, is_persp, true,
- ray_origin, ray_start, ray_normal, ray_depth_range,
- ray_depth, dist_to_ray_sq,
+ snap_to, mval, view_proj, true,
+ ray_origin, ray_start, ray_normal, depth_range,
+ ray_depth, dist_px,
r_loc, r_no,
r_index, r_hit_list);
dm->release(dm);
}
}
- else if (ob->type == OB_ARMATURE) {
- retval = snapArmature(
- ob, ob->data, obmat, snap_to, is_persp,
- ray_origin, ray_normal, ray_depth_range,
- ray_depth, dist_to_ray_sq,
- r_loc, r_no);
- }
- else if (ob->type == OB_CURVE) {
- retval = snapCurve(
- ob, ob->data, obmat, snap_to, is_persp,
- ray_origin, ray_normal, ray_depth_range,
- ray_depth, dist_to_ray_sq,
- r_loc, r_no);
- }
- else if (ob->type == OB_EMPTY) {
- retval = snapEmpty(
- ob, obmat, snap_to, is_persp,
- ray_origin, ray_normal, ray_depth_range,
- ray_depth, dist_to_ray_sq,
- r_loc, r_no);
- }
- else if (ob->type == OB_CAMERA) {
- retval = snapCamera(
- sctx->scene, ob, obmat, snap_to, is_persp,
- ray_origin, ray_normal, ray_depth_range,
- ray_depth, dist_to_ray_sq,
- r_loc, r_no);
+ else if (snap_to != SCE_SNAP_MODE_FACE) {
+ if (ob->type == OB_ARMATURE) {
+ retval = snapArmature(
+ ar, ob, ob->data, obmat, snap_to, ray_origin, ray_normal,
+ mval, view_proj, depth_range, dist_px,
+ r_loc, r_no);
+ }
+ else if (ob->type == OB_CURVE) {
+ retval = snapCurve(
+ ar, ob, ob->data, obmat, snap_to, mval, view_proj,
+ depth_range,
+ dist_px,
+ r_loc, r_no);
+ }
+ else if (ob->type == OB_EMPTY) {
+ retval = snapEmpty(
+ ar, ob, obmat, snap_to, mval, view_proj,
+ depth_range,
+ dist_px,
+ r_loc, r_no);
+ }
+ else if (ob->type == OB_CAMERA) {
+ retval = snapCamera(
+ sctx, ob, obmat, snap_to, mval, view_proj,
+ depth_range,
+ dist_px,
+ r_loc, r_no);
+ }
}
if (retval) {
@@ -1414,16 +1822,18 @@ static bool snapObject(
* \param snap_select: from enum SnapSelect.
*
* \param use_object_edit_cage: Uses the coordinates of BMesh (if any) to do the snapping.
+ * \param mval: Mouse coords.
+ * When NULL, ray-casting is handled without any projection matrix correction.
* \param ray_origin: ray_start before being moved toward the ray_normal at the distance from vew3d clip_min.
* \param ray_start: ray_origin moved for the start clipping plane (clip_min).
* \param ray_normal: Unit length direction of the ray.
+ * \param depth_range: distances of clipe plane min and clip plane max;
*
* Read/Write Args
* ---------------
*
* \param ray_depth: maximum depth allowed for r_co, elements deeper than this value will be ignored.
- * \param dist_to_ray_sq: Real distance (3D) or Tangent (view cone radius at distance 1.0) squared.
- * resulting of the function #dist_px_to_dist3d_or_tangent.
+ * \param dist_px: Maximum threshold distance (in pixels).
*
* Output Args
* -----------
@@ -1440,10 +1850,11 @@ static bool snapObject(
static bool snapObjectsRay(
SnapObjectContext *sctx,
const unsigned short snap_to, const SnapSelect snap_select,
- const bool use_object_edit_cage,
+ const bool use_object_edit_cage, const float mval[2],
const float ray_origin[3], const float ray_start[3], const float ray_normal[3],
+ const float depth_range[2],
/* read/write args */
- float *ray_depth, float *dist_to_ray_sq,
+ float *ray_depth, float *dist_px,
/* return args */
float r_loc[3], float r_no[3], int *r_index,
Object **r_ob, float r_obmat[4][4],
@@ -1451,14 +1862,6 @@ static bool snapObjectsRay(
{
bool retval = false;
- float dvec[3];
- sub_v3_v3v3(dvec, ray_start, ray_origin);
-
- const float ray_depth_range[2] = {
- dot_v3v3(dvec, ray_normal),
- *ray_depth,
- };
-
unsigned int ob_index = 0;
Object *obedit = use_object_edit_cage ? sctx->scene->obedit : NULL;
Base *base_act = sctx->scene->basact;
@@ -1493,9 +1896,9 @@ static bool snapObjectsRay(
retval |= snapObject(
sctx, dupli_snap, dupli_ob->mat, ob_index++,
- use_obedit_dupli, snap_to,
- ray_origin, ray_start, ray_normal, ray_depth_range,
- ray_depth, dist_to_ray_sq,
+ use_obedit_dupli, snap_to, mval,
+ ray_origin, ray_start, ray_normal, depth_range,
+ ray_depth, dist_px,
r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
}
@@ -1507,9 +1910,9 @@ static bool snapObjectsRay(
retval |= snapObject(
sctx, ob_snap, ob->obmat, ob_index++,
- use_obedit, snap_to,
- ray_origin, ray_start, ray_normal, ray_depth_range,
- ray_depth, dist_to_ray_sq,
+ use_obedit, snap_to, mval,
+ ray_origin, ray_start, ray_normal, depth_range,
+ ray_depth, dist_px,
r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
}
}
@@ -1616,13 +2019,12 @@ bool ED_transform_snap_object_project_ray_ex(
float r_loc[3], float r_no[3], int *r_index,
Object **r_ob, float r_obmat[4][4])
{
- float dist_to_ray_sq = 0.0f;
-
+ const float depth_range[2] = {0.0f, FLT_MAX};
return snapObjectsRay(
sctx,
- snap_to, params->snap_select, params->use_object_edit_cage,
- ray_start, ray_start, ray_normal,
- ray_depth, &dist_to_ray_sq,
+ snap_to, params->snap_select, params->use_object_edit_cage, NULL,
+ ray_start, ray_start, ray_normal, depth_range,
+ ray_depth, NULL,
r_loc, r_no, r_index, r_ob, r_obmat, NULL);
}
@@ -1641,8 +2043,7 @@ bool ED_transform_snap_object_project_ray_all(
float ray_depth, bool sort,
ListBase *r_hit_list)
{
- float dist_to_ray_sq = 0.0f;
-
+ const float depth_range[2] = {0.0f, FLT_MAX};
if (ray_depth == -1.0f) {
ray_depth = BVH_RAYCAST_DIST_MAX;
}
@@ -1653,9 +2054,9 @@ bool ED_transform_snap_object_project_ray_all(
bool retval = snapObjectsRay(
sctx,
- snap_to, params->snap_select, params->use_object_edit_cage,
- ray_start, ray_start, ray_normal,
- &ray_depth, &dist_to_ray_sq,
+ snap_to, params->snap_select, params->use_object_edit_cage, NULL,
+ ray_start, ray_start, ray_normal, depth_range,
+ &ray_depth, NULL,
NULL, NULL, NULL, NULL, NULL,
r_hit_list);
@@ -1710,11 +2111,6 @@ bool ED_transform_snap_object_project_ray(
ray_depth = &ray_depth_fallback;
}
- float no_fallback[3];
- if (r_no == NULL) {
- r_no = no_fallback;
- }
-
return transform_snap_context_project_ray_impl(
sctx,
params,
@@ -1733,11 +2129,6 @@ static bool transform_snap_context_project_view3d_mixed_impl(
float ray_depth = BVH_RAYCAST_DIST_MAX;
bool is_hit = false;
- float r_no_dummy[3];
- if (r_no == NULL) {
- r_no = r_no_dummy;
- }
-
const int elem_type[3] = {SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE, SCE_SNAP_MODE_FACE};
BLI_assert(snap_to_flag != 0);
@@ -1764,21 +2155,6 @@ static bool transform_snap_context_project_view3d_mixed_impl(
}
/**
- * From a threshold (maximum distance to snap in pixels) returns:
- *
- * - The *real* distance (3D) if you are in orthographic-view.
- * - The *tangent* (view cone radius at distance 1.0) if you are in perspective-view.
- */
-static float dist_px_to_dist3d_or_tangent(const ARegion *ar, const float dist_px)
-{
- const RegionView3D *rv3d = ar->regiondata;
- if (ar->winx >= ar->winy)
- return 2 * (dist_px / ar->winx) / rv3d->winmat[0][0];
- else
- return 2 * (dist_px / ar->winy) / rv3d->winmat[1][1];
-}
-
-/**
* Convenience function for performing snapping.
*
* Given a 2D region value, snap to vert/edge/face.
@@ -1814,55 +2190,37 @@ bool ED_transform_snap_object_project_view3d_ex(
float *ray_depth,
float r_loc[3], float r_no[3], int *r_index)
{
- float ray_start[3], ray_normal[3], ray_origin[3];
+ float ray_origin[3], ray_start[3], ray_normal[3], depth_range[2], ray_end[3];
- float ray_depth_fallback;
- if (ray_depth == NULL) {
- ray_depth_fallback = BVH_RAYCAST_DIST_MAX;
- ray_depth = &ray_depth_fallback;
- }
+ const ARegion *ar = sctx->v3d_data.ar;
+ const RegionView3D *rv3d = ar->regiondata;
- if (!ED_view3d_win_to_ray_ex(
- sctx->v3d_data.ar, sctx->v3d_data.v3d,
- mval, ray_origin, ray_normal, ray_start, true))
- {
+ ED_view3d_win_to_origin(ar, mval, ray_origin);
+ ED_view3d_win_to_vector(ar, mval, ray_normal);
+
+ ED_view3d_clip_range_get(
+ sctx->v3d_data.v3d, sctx->v3d_data.ar->regiondata,
+ &depth_range[0], &depth_range[1], false);
+
+ madd_v3_v3v3fl(ray_start, ray_origin, ray_normal, depth_range[0]);
+ madd_v3_v3v3fl(ray_end, ray_origin, ray_normal, depth_range[1]);
+
+ if (!ED_view3d_clip_segment(rv3d, ray_start, ray_end)) {
return false;
}
- float radius, dist_to_ray_sq = 0.0f;
- if (dist_px) {
- radius = dist_px_to_dist3d_or_tangent(sctx->v3d_data.ar, *dist_px);
- /**
- * Workaround to use of cone (Instead of project the radius on view plane):
- * In perspective view, the radius of the cone may decrease depending on the ray direction.
- * This is more evident with small values of the `Viewport lens angle`.
- * The threshold becomes distorted that way.
- */
- RegionView3D *rv3d = sctx->v3d_data.ar->regiondata;
- if (rv3d->is_persp) {
- float view_dir[3];
- negate_v3_v3(view_dir, rv3d->viewinv[2]);
- normalize_v3(view_dir);
- radius *= dot_v3v3(ray_normal, view_dir);
- }
-
- dist_to_ray_sq = SQUARE(radius);
+ float ray_depth_fallback;
+ if (ray_depth == NULL) {
+ ray_depth_fallback = BVH_RAYCAST_DIST_MAX;
+ ray_depth = &ray_depth_fallback;
}
- if (snapObjectsRay(
+ return snapObjectsRay(
sctx,
snap_to, params->snap_select, params->use_object_edit_cage,
- ray_origin, ray_start, ray_normal,
- ray_depth, &dist_to_ray_sq,
- r_loc, r_no, r_index, NULL, NULL, NULL))
- {
- if (dist_px) {
- *dist_px *= sqrtf(dist_to_ray_sq) / radius;
- }
- return true;
- }
-
- return false;
+ mval, ray_origin, ray_start, ray_normal, depth_range,
+ ray_depth, dist_px,
+ r_loc, r_no, r_index, NULL, NULL, NULL);
}
bool ED_transform_snap_object_project_view3d(
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index c663af0ccbb..370841327aa 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -916,7 +916,7 @@ void GPU_buffer_unlock(GPUBuffer *UNUSED(buffer), GPUBindingType binding)
{
int bindtypegl = gpu_binding_type_gl[binding];
/* note: this operation can fail, could return
- * an error code from this function? */
+ * an error code from this function? */
glUnmapBuffer(bindtypegl);
glBindBuffer(bindtypegl, 0);
}
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 3ea64e1f6d5..1c2dbfb8085 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -802,7 +802,7 @@ static void **gpu_gen_cube_map(unsigned int *rect, float *frect, int rectw, int
* | | | |
* | NegZ | PosZ | PosY |
* |______|______|______|
- */
+ */
if (use_high_bit_depth) {
float (*frectb)[4] = (float(*)[4])frect;
float (**fsides)[4] = (float(**)[4])sides;
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index b8a39c81122..d41573b681b 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -77,9 +77,10 @@ static struct GPUGlobal {
GPUDeviceType device;
GPUOSType os;
GPUDriverType driver;
- float dfdyfactors[2]; /* workaround for different calculation of dfdy factors on GPUs. Some GPUs/drivers
- calculate dfdy in shader differently when drawing to an offscreen buffer. First
- number is factor on screen and second is off-screen */
+ /* workaround for different calculation of dfdy factors on GPUs. Some GPUs/drivers
+ * calculate dfdy in shader differently when drawing to an offscreen buffer. First
+ * number is factor on screen and second is off-screen */
+ float dfdyfactors[2];
float max_anisotropy;
} GG = {1, 0};
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index ba78c347e99..24228c8d087 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -1720,8 +1720,7 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr)
(GPU_link_changed(shi->refl) || ma->ref != 0.0f))
{
if (world->aocolor != WO_AOPLAIN) {
- if (!(is_zero_v3(&world->horr) & is_zero_v3(&world->zenr)))
- {
+ if (!(is_zero_v3(&world->horr) & is_zero_v3(&world->zenr))) {
GPUNodeLink *fcol, *f;
GPU_link(mat, "math_multiply", shi->amb, shi->refl, &f);
GPU_link(mat, "math_multiply", f, GPU_uniform(&world->ao_env_energy), &f);
diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h
index 07bc2478837..d385e303a7c 100644
--- a/source/blender/makesdna/DNA_cloth_types.h
+++ b/source/blender/makesdna/DNA_cloth_types.h
@@ -42,7 +42,7 @@
*
* I've tried to keep similar, if not exact names for the variables as
* are presented in the paper. Where I've changed the concept slightly,
- * as in stepsPerFrame comapred to the time step in the paper, I've used
+ * as in stepsPerFrame compared to the time step in the paper, I've used
* variables with different names to minimize confusion.
*/
diff --git a/source/blender/makesdna/DNA_genfile.h b/source/blender/makesdna/DNA_genfile.h
index 77877f7bada..0e34792e624 100644
--- a/source/blender/makesdna/DNA_genfile.h
+++ b/source/blender/makesdna/DNA_genfile.h
@@ -76,13 +76,23 @@ enum eSDNA_StructCompare {
struct SDNA *DNA_sdna_from_data(
const void *data, const int datalen,
- bool do_endian_swap, bool data_alloc);
+ bool do_endian_swap, bool data_alloc,
+ const char **r_error_message);
void DNA_sdna_free(struct SDNA *sdna);
-int DNA_struct_find_nr(struct SDNA *sdna, const char *str);
-void DNA_struct_switch_endian(struct SDNA *oldsdna, int oldSDNAnr, char *data);
-char *DNA_struct_get_compareflags(struct SDNA *sdna, struct SDNA *newsdna);
-void *DNA_struct_reconstruct(struct SDNA *newsdna, struct SDNA *oldsdna, char *compflags, int oldSDNAnr, int blocks, void *data);
+/* Access for current Blender versions SDNA*/
+void DNA_sdna_current_init(void);
+/* borrowed reference */
+const struct SDNA *DNA_sdna_current_get(void);
+void DNA_sdna_current_free(void);
+
+int DNA_struct_find_nr_ex(const struct SDNA *sdna, const char *str, unsigned int *index_last);
+int DNA_struct_find_nr(const struct SDNA *sdna, const char *str);
+void DNA_struct_switch_endian(const struct SDNA *oldsdna, int oldSDNAnr, char *data);
+char *DNA_struct_get_compareflags(const struct SDNA *sdna, const struct SDNA *newsdna);
+void *DNA_struct_reconstruct(
+ const struct SDNA *newsdna, const struct SDNA *oldsdna,
+ char *compflags, int oldSDNAnr, int blocks, void *data);
int DNA_elem_array_size(const char *str);
int DNA_elem_offset(struct SDNA *sdna, const char *stype, const char *vartype, const char *name);
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 5d04fba776f..a6bbb40d826 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -639,8 +639,9 @@ typedef struct BooleanModifierData {
struct Object *object;
char operation;
- char bm_flag, pad[2];
- float threshold;
+ char solver;
+ char pad[2];
+ float double_threshold;
} BooleanModifierData;
typedef enum {
@@ -649,13 +650,10 @@ typedef enum {
eBooleanModifierOp_Difference = 2,
} BooleanModifierOp;
-/* temp bm_flag (debugging only) */
-enum {
- eBooleanModifierBMeshFlag_Enabled = (1 << 0),
- eBooleanModifierBMeshFlag_BMesh_Separate = (1 << 1),
- eBooleanModifierBMeshFlag_BMesh_NoDissolve = (1 << 2),
- eBooleanModifierBMeshFlag_BMesh_NoConnectRegions = (1 << 3),
-};
+typedef enum {
+ eBooleanModifierSolver_Carve = 0,
+ eBooleanModifierSolver_BMesh = 1,
+} BooleanSolver;
typedef struct MDefInfluence {
int vertex;
diff --git a/source/blender/makesdna/DNA_sdna_types.h b/source/blender/makesdna/DNA_sdna_types.h
index 791aca77558..bd8f23f30c1 100644
--- a/source/blender/makesdna/DNA_sdna_types.h
+++ b/source/blender/makesdna/DNA_sdna_types.h
@@ -35,17 +35,17 @@
#
#
typedef struct SDNA {
- const char *data; /* full copy of 'encoded' data */
+ const char *data; /* full copy of 'encoded' data (when data_alloc is set, otherwise borrowed). */
int datalen; /* length of data */
bool data_alloc;
int nr_names; /* total number of struct members */
- const char **names; /* struct member names */
+ const char **names; /* struct member names */
int pointerlen; /* size of a pointer in bytes */
int nr_types; /* number of basic types + struct types */
- char **types; /* type names */
+ const char **types; /* type names */
short *typelens; /* type lengths */
int nr_structs; /* number of struct types */
@@ -57,11 +57,6 @@ typedef struct SDNA {
struct GHash *structs_map; /* ghash for faster lookups,
* requires WITH_DNA_GHASH to be used for now */
-
- /* wrong place for this really, its a simple
- * cache for findstruct_nr.
- */
- int lastfind;
} SDNA;
#
diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt
index 0bb6e866bf4..8c758c33dc5 100644
--- a/source/blender/makesdna/intern/CMakeLists.txt
+++ b/source/blender/makesdna/intern/CMakeLists.txt
@@ -52,6 +52,8 @@ endif()
# SRC_DNA_INC is defined in the parent dir
+add_cc_flags_custom_test(makesdna)
+
add_executable(makesdna ${SRC} ${SRC_DNA_INC})
# Output dna.c
diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c
index 9135d7bab7d..4db98bda7dd 100644
--- a/source/blender/makesdna/intern/dna_genfile.c
+++ b/source/blender/makesdna/intern/dna_genfile.c
@@ -39,6 +39,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#include "MEM_guardedalloc.h" // for MEM_freeN MEM_mallocN MEM_callocN
@@ -133,39 +134,6 @@
*
*/
-/* ************************* ENDIAN STUFF ********************** */
-
-/**
- * converts a short between big/little endian.
- */
-static short le_short(short temp)
-{
- short new;
- char *rt = (char *)&temp, *rtn = (char *)&new;
-
- rtn[0] = rt[1];
- rtn[1] = rt[0];
-
- return new;
-}
-
-/**
- * converts an int between big/little endian.
- */
-static int le_int(int temp)
-{
- int new;
- char *rt = (char *)&temp, *rtn = (char *)&new;
-
- rtn[0] = rt[3];
- rtn[1] = rt[2];
- rtn[2] = rt[1];
- rtn[3] = rt[0];
-
- return new;
-}
-
-
/* ************************* MAKE DNA ********************** */
/* allowed duplicate code from makesdna.c */
@@ -280,37 +248,16 @@ static void printstruct(SDNA *sdna, short strnr)
#endif
/**
- * Returns a pointer to the start of the struct info for the struct with the specified name.
- */
-static short *findstruct_name(SDNA *sdna, const char *str)
-{
- int a;
- short *sp = NULL;
-
-
- for (a = 0; a < sdna->nr_structs; a++) {
-
- sp = sdna->structs[a];
-
- if (strcmp(sdna->types[sp[0]], str) == 0) {
- return sp;
- }
- }
-
- return NULL;
-}
-
-/**
* Returns the index of the struct info for the struct with the specified name.
*/
-int DNA_struct_find_nr(SDNA *sdna, const char *str)
+int DNA_struct_find_nr_ex(const SDNA *sdna, const char *str, unsigned int *index_last)
{
const short *sp = NULL;
- if (sdna->lastfind < sdna->nr_structs) {
- sp = sdna->structs[sdna->lastfind];
+ if (*index_last < sdna->nr_structs) {
+ sp = sdna->structs[*index_last];
if (strcmp(sdna->types[sp[0]], str) == 0) {
- return sdna->lastfind;
+ return *index_last;
}
}
@@ -323,7 +270,7 @@ int DNA_struct_find_nr(SDNA *sdna, const char *str)
if (index_p) {
a = GET_INT_FROM_POINTER(*index_p);
- sdna->lastfind = a;
+ *index_last = a;
}
else {
a = -1;
@@ -339,7 +286,7 @@ int DNA_struct_find_nr(SDNA *sdna, const char *str)
sp = sdna->structs[a];
if (strcmp(sdna->types[sp[0]], str) == 0) {
- sdna->lastfind = a;
+ *index_last = a;
return a;
}
}
@@ -348,26 +295,51 @@ int DNA_struct_find_nr(SDNA *sdna, const char *str)
#endif
}
+int DNA_struct_find_nr(const SDNA *sdna, const char *str)
+{
+ unsigned int index_last_dummy = UINT_MAX;
+ return DNA_struct_find_nr_ex(sdna, str, &index_last_dummy);
+}
+
/* ************************* END DIV ********************** */
/* ************************* READ DNA ********************** */
+BLI_INLINE const char *pad_up_4(const char *ptr)
+{
+ return (const char *)((((uintptr_t)ptr) + 3) & ~3);
+}
+
/**
* In sdna->data the data, now we convert that to something understandable
*/
-static void init_structDNA(SDNA *sdna, bool do_endian_swap)
+static bool init_structDNA(
+ SDNA *sdna, bool do_endian_swap,
+ const char **r_error_message)
{
int *data, *verg, gravity_fix = -1;
- intptr_t nr;
short *sp;
- char str[8], *cp;
+ char str[8];
verg = (int *)str;
data = (int *)sdna->data;
+ /* clear pointers incase of error */
+ sdna->names = NULL;
+ sdna->types = NULL;
+ sdna->structs = NULL;
+#ifdef WITH_DNA_GHASH
+ sdna->structs_map = NULL;
+#endif
+
strcpy(str, "SDNA");
- if (*data == *verg) {
-
+ if (*data != *verg) {
+ *r_error_message = "SDNA error in SDNA file";
+ return false;
+ }
+ else {
+ const char *cp;
+
data++;
/* load names array */
@@ -375,20 +347,21 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap)
if (*data == *verg) {
data++;
- if (do_endian_swap) sdna->nr_names = le_int(*data);
- else sdna->nr_names = *data;
+ sdna->nr_names = *data;
+ if (do_endian_swap) {
+ BLI_endian_switch_int32(&sdna->nr_names);
+ }
data++;
sdna->names = MEM_callocN(sizeof(void *) * sdna->nr_names, "sdnanames");
}
else {
- printf("NAME error in SDNA file\n");
- return;
+ *r_error_message = "NAME error in SDNA file";
+ return false;
}
- nr = 0;
cp = (char *)data;
- while (nr < sdna->nr_names) {
+ for (int nr = 0; nr < sdna->nr_names; nr++) {
sdna->names[nr] = cp;
/* "float gravity [3]" was parsed wrong giving both "gravity" and
@@ -403,32 +376,31 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap)
while (*cp) cp++;
cp++;
- nr++;
}
- nr = (intptr_t)cp; /* prevent BUS error */
- nr = (nr + 3) & ~3;
- cp = (char *)nr;
+
+ cp = pad_up_4(cp);
/* load type names array */
data = (int *)cp;
strcpy(str, "TYPE");
if (*data == *verg) {
data++;
-
- if (do_endian_swap) sdna->nr_types = le_int(*data);
- else sdna->nr_types = *data;
+
+ sdna->nr_types = *data;
+ if (do_endian_swap) {
+ BLI_endian_switch_int32(&sdna->nr_types);
+ }
data++;
sdna->types = MEM_callocN(sizeof(void *) * sdna->nr_types, "sdnatypes");
}
else {
- printf("TYPE error in SDNA file\n");
- return;
+ *r_error_message = "TYPE error in SDNA file";
+ return false;
}
- nr = 0;
cp = (char *)data;
- while (nr < sdna->nr_types) {
+ for (int nr = 0; nr < sdna->nr_types; nr++) {
sdna->types[nr] = cp;
/* this is a patch, to change struct names without a conflict with SDNA */
@@ -441,11 +413,9 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap)
while (*cp) cp++;
cp++;
- nr++;
}
- nr = (intptr_t)cp; /* prevent BUS error */
- nr = (nr + 3) & ~3;
- cp = (char *)nr;
+
+ cp = pad_up_4(cp);
/* load typelen array */
data = (int *)cp;
@@ -456,20 +426,14 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap)
sdna->typelens = sp;
if (do_endian_swap) {
- short a, *spo = sp;
-
- a = sdna->nr_types;
- while (a--) {
- spo[0] = le_short(spo[0]);
- spo++;
- }
+ BLI_endian_switch_int16_array(sp, sdna->nr_types);
}
sp += sdna->nr_types;
}
else {
- printf("TLEN error in SDNA file\n");
- return;
+ *r_error_message = "TLEN error in SDNA file";
+ return false;
}
if (sdna->nr_types & 1) sp++; /* prevent BUS error */
@@ -479,74 +443,90 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap)
if (*data == *verg) {
data++;
- if (do_endian_swap) sdna->nr_structs = le_int(*data);
- else sdna->nr_structs = *data;
+ sdna->nr_structs = *data;
+ if (do_endian_swap) {
+ BLI_endian_switch_int32(&sdna->nr_structs);
+ }
data++;
sdna->structs = MEM_callocN(sizeof(void *) * sdna->nr_structs, "sdnastrcs");
}
else {
- printf("STRC error in SDNA file\n");
- return;
+ *r_error_message = "STRC error in SDNA file";
+ return false;
}
- nr = 0;
sp = (short *)data;
- while (nr < sdna->nr_structs) {
+ for (int nr = 0; nr < sdna->nr_structs; nr++) {
sdna->structs[nr] = sp;
if (do_endian_swap) {
short a;
- sp[0] = le_short(sp[0]);
- sp[1] = le_short(sp[1]);
+ BLI_endian_switch_int16(&sp[0]);
+ BLI_endian_switch_int16(&sp[1]);
a = sp[1];
sp += 2;
while (a--) {
- sp[0] = le_short(sp[0]);
- sp[1] = le_short(sp[1]);
+ BLI_endian_switch_int16(&sp[0]);
+ BLI_endian_switch_int16(&sp[1]);
sp += 2;
}
}
else {
sp += 2 * sp[1] + 2;
}
-
- nr++;
}
+ }
- /* finally pointerlen: use struct ListBase to test it, never change the size of it! */
- sp = findstruct_name(sdna, "ListBase");
- /* weird; i have no memory of that... I think I used sizeof(void *) before... (ton) */
-
- sdna->pointerlen = sdna->typelens[sp[0]] / 2;
-
- if (sp[1] != 2 || (sdna->pointerlen != 4 && sdna->pointerlen != 8)) {
- printf("ListBase struct error! Needs it to calculate pointerize.\n");
- exit(1);
- /* well, at least sizeof(ListBase) is error proof! (ton) */
- }
-
+ {
/* second part of gravity problem, setting "gravity" type to void */
if (gravity_fix > -1) {
- for (nr = 0; nr < sdna->nr_structs; nr++) {
+ for (int nr = 0; nr < sdna->nr_structs; nr++) {
sp = sdna->structs[nr];
if (strcmp(sdna->types[sp[0]], "ClothSimSettings") == 0)
sp[10] = SDNA_TYPE_VOID;
}
}
+ }
#ifdef WITH_DNA_GHASH
+ {
/* create a ghash lookup to speed up */
sdna->structs_map = BLI_ghash_str_new_ex("init_structDNA gh", sdna->nr_structs);
- for (nr = 0; nr < sdna->nr_structs; nr++) {
+ for (intptr_t nr = 0; nr < sdna->nr_structs; nr++) {
sp = sdna->structs[nr];
- BLI_ghash_insert(sdna->structs_map, sdna->types[sp[0]], SET_INT_IN_POINTER(nr));
+ BLI_ghash_insert(sdna->structs_map, (void *)sdna->types[sp[0]], SET_INT_IN_POINTER(nr));
}
+ }
#endif
+
+ /* Calculate 'sdna->pointerlen' */
+ {
+ intptr_t nr = DNA_struct_find_nr(sdna, "ListBase");
+
+ /* should never happen, only with corrupt file for example */
+ if (UNLIKELY(nr == -1)) {
+ *r_error_message = "ListBase struct error! Not found.";
+ return false;
+ }
+
+ /* finally pointerlen: use struct ListBase to test it, never change the size of it! */
+ sp = sdna->structs[nr];
+ /* weird; i have no memory of that... I think I used sizeof(void *) before... (ton) */
+
+ sdna->pointerlen = sdna->typelens[sp[0]] / 2;
+
+ if (sp[1] != 2 || (sdna->pointerlen != 4 && sdna->pointerlen != 8)) {
+ *r_error_message = "ListBase struct error! Needs it to calculate pointerize.";
+ /* well, at least sizeof(ListBase) is error proof! (ton) */
+ return false;
+ }
}
+
+ return true;
}
/**
@@ -554,11 +534,11 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap)
*/
SDNA *DNA_sdna_from_data(
const void *data, const int datalen,
- bool do_endian_swap, bool data_alloc)
+ bool do_endian_swap, bool data_alloc,
+ const char **r_error_message)
{
SDNA *sdna = MEM_mallocN(sizeof(*sdna), "sdna");
-
- sdna->lastfind = 0;
+ const char *error_message = NULL;
sdna->datalen = datalen;
if (data_alloc) {
@@ -571,9 +551,44 @@ SDNA *DNA_sdna_from_data(
}
sdna->data_alloc = data_alloc;
- init_structDNA(sdna, do_endian_swap);
-
- return sdna;
+
+ if (init_structDNA(sdna, do_endian_swap, &error_message)) {
+ return sdna;
+ }
+ else {
+ if (r_error_message == NULL) {
+ fprintf(stderr, "Error decoding blend file SDNA: %s\n", error_message);
+ }
+ else {
+ *r_error_message = error_message;
+ }
+ DNA_sdna_free(sdna);
+ return NULL;
+ }
+}
+
+/**
+ * Using globals is acceptable here, the data is read-only and only changes between Blender versions.
+ *
+ * So it is safe to create once and reuse.
+ */
+static SDNA *g_sdna = NULL;
+
+void DNA_sdna_current_init(void)
+{
+ g_sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false, NULL);
+}
+
+const struct SDNA *DNA_sdna_current_get(void)
+{
+ BLI_assert(g_sdna != NULL);
+ return g_sdna;
+}
+
+void DNA_sdna_current_free(void)
+{
+ DNA_sdna_free(g_sdna);
+ g_sdna = NULL;
}
/* ******************** END READ DNA ********************** */
@@ -623,7 +638,7 @@ static void recurs_test_compflags(const SDNA *sdna, char *compflags, int structn
* - 1 Struct is the same (can be loaded with straight memory copy after any necessary endian conversion)
* - 2 Struct is different in some way (needs to be copied/converted field by field)
*/
-char *DNA_struct_get_compareflags(SDNA *oldsdna, SDNA *newsdna)
+char *DNA_struct_get_compareflags(const SDNA *oldsdna, const SDNA *newsdna)
{
int a, b;
const short *sp_old, *sp_new;
@@ -640,14 +655,19 @@ char *DNA_struct_get_compareflags(SDNA *oldsdna, SDNA *newsdna)
/* we check all structs in 'oldsdna' and compare them with
* the structs in 'newsdna'
*/
+ unsigned int newsdna_index_last = 0;
for (a = 0; a < oldsdna->nr_structs; a++) {
sp_old = oldsdna->structs[a];
/* search for type in cur */
- sp_new = findstruct_name(newsdna, oldsdna->types[sp_old[0]]);
-
- if (sp_new) {
+ int sp_new_index = DNA_struct_find_nr_ex(newsdna, oldsdna->types[sp_old[0]], &newsdna_index_last);
+
+ /* The next indices will almost always match */
+ newsdna_index_last++;
+
+ if (sp_new_index != -1) {
+ sp_new = newsdna->structs[sp_new_index];
/* initial assumption */
compflags[a] = SDNA_CMP_NOT_EQUAL;
@@ -1037,8 +1057,8 @@ static void reconstruct_elem(
* \param cur Where to put converted struct contents
*/
static void reconstruct_struct(
- SDNA *newsdna,
- SDNA *oldsdna,
+ const SDNA *newsdna,
+ const SDNA *oldsdna,
const char *compflags,
int oldSDNAnr,
@@ -1056,6 +1076,10 @@ static void reconstruct_struct(
char *cpo, *cpc;
const char *name, *nameo;
+ unsigned int oldsdna_index_last = UINT_MAX;
+ unsigned int cursdna_index_last = UINT_MAX;
+
+
if (oldSDNAnr == -1) return;
if (curSDNAnr == -1) return;
@@ -1090,8 +1114,8 @@ static void reconstruct_struct(
cpo = find_elem(oldsdna, type, name, spo, data, &sppo);
if (cpo) {
- oldSDNAnr = DNA_struct_find_nr(oldsdna, type);
- curSDNAnr = DNA_struct_find_nr(newsdna, type);
+ oldSDNAnr = DNA_struct_find_nr_ex(oldsdna, type, &oldsdna_index_last);
+ curSDNAnr = DNA_struct_find_nr_ex(newsdna, type, &cursdna_index_last);
/* array! */
mul = DNA_elem_array_size(name);
@@ -1132,7 +1156,7 @@ static void reconstruct_struct(
* \param oldSDNAnr Index of struct info within oldsdna
* \param data Struct data
*/
-void DNA_struct_switch_endian(SDNA *oldsdna, int oldSDNAnr, char *data)
+void DNA_struct_switch_endian(const SDNA *oldsdna, int oldSDNAnr, char *data)
{
/* Recursive!
* If element is a struct, call recursive.
@@ -1141,6 +1165,7 @@ void DNA_struct_switch_endian(SDNA *oldsdna, int oldSDNAnr, char *data)
const short *spo, *spc;
char *cur;
const char *type, *name;
+ unsigned int oldsdna_index_last = UINT_MAX;
if (oldSDNAnr == -1) return;
firststructtypenr = *(oldsdna->structs[0]);
@@ -1165,7 +1190,7 @@ void DNA_struct_switch_endian(SDNA *oldsdna, int oldSDNAnr, char *data)
/* where does the old data start (is there one?) */
char *cpo = find_elem(oldsdna, type, name, spo, data, NULL);
if (cpo) {
- oldSDNAnr = DNA_struct_find_nr(oldsdna, type);
+ oldSDNAnr = DNA_struct_find_nr_ex(oldsdna, type, &oldsdna_index_last);
mul = DNA_elem_array_size(name);
elena = elen / mul;
@@ -1223,7 +1248,9 @@ void DNA_struct_switch_endian(SDNA *oldsdna, int oldSDNAnr, char *data)
* \param data Array of struct data
* \return An allocated reconstructed struct
*/
-void *DNA_struct_reconstruct(SDNA *newsdna, SDNA *oldsdna, char *compflags, int oldSDNAnr, int blocks, void *data)
+void *DNA_struct_reconstruct(
+ const SDNA *newsdna, const SDNA *oldsdna,
+ char *compflags, int oldSDNAnr, int blocks, void *data)
{
int a, curSDNAnr, curlen = 0, oldlen;
const short *spo, *spc;
@@ -1263,7 +1290,6 @@ void *DNA_struct_reconstruct(SDNA *newsdna, SDNA *oldsdna, char *compflags, int
*/
int DNA_elem_offset(SDNA *sdna, const char *stype, const char *vartype, const char *name)
{
-
const int SDNAnr = DNA_struct_find_nr(sdna, stype);
const short * const spo = sdna->structs[SDNAnr];
const char * const cp = find_elem(sdna, vartype, name, spo, NULL, NULL);
@@ -1273,7 +1299,6 @@ int DNA_elem_offset(SDNA *sdna, const char *stype, const char *vartype, const ch
bool DNA_struct_elem_find(SDNA *sdna, const char *stype, const char *vartype, const char *name)
{
-
const int SDNAnr = DNA_struct_find_nr(sdna, stype);
if (SDNAnr != -1) {
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index b1f3d1757bc..ef159cf5930 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -348,7 +348,10 @@ blender_include_dirs_sys(
"${GLEW_INCLUDE_PATH}"
)
+add_cc_flags_custom_test(makesrna)
+
add_executable(makesrna ${SRC} ${SRC_RNA_INC} ${SRC_DNA_INC})
+
target_link_libraries(makesrna bf_dna)
target_link_libraries(makesrna bf_dna_blenlib)
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 983d3f659ef..af8fe78c0af 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -686,7 +686,7 @@ static void rna_ImagePreview_icon_pixels_float_set(PointerRNA *ptr, const float
static int rna_ImagePreview_icon_id_get(PointerRNA *ptr)
{
/* Using a callback here allows us to only generate icon matching that preview when icon_id is requested. */
- return BKE_icon_preview_ensure((PreviewImage *)(ptr->data));
+ return BKE_icon_preview_ensure(ptr->id.data, (PreviewImage *)(ptr->data));
}
static void rna_ImagePreview_icon_reload(PreviewImage *prv)
{
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 00b7df122ee..5a93e18a7dd 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -3127,8 +3127,11 @@ void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA
RNA_parameter_list_free(&params);
}
}
- /*else
- printf("%s %s.%s: not implemented for this property.\n", __func__, ptr->type->identifier, prop->identifier);*/
+#if 0
+ else {
+ printf("%s %s.%s: not implemented for this property.\n", __func__, ptr->type->identifier, prop->identifier);
+ }
+#endif
#endif
if (r_ptr) {
@@ -3187,8 +3190,11 @@ bool RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key)
return false;
}
- /*else
- printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier);*/
+#if 0
+ else {
+ printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier);
+ }
+#endif
#endif
return false;
}
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index bf2b091576e..7ff4eaea169 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -531,12 +531,18 @@ BlenderRNA *RNA_create(void)
BlenderRNA *brna;
brna = MEM_callocN(sizeof(BlenderRNA), "BlenderRNA");
+ const char *error_message = NULL;
- DefRNA.sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false);
BLI_listbase_clear(&DefRNA.structs);
DefRNA.error = 0;
DefRNA.preprocess = 1;
+ DefRNA.sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false, &error_message);
+ if (DefRNA.sdna == NULL) {
+ fprintf(stderr, "Error decoding SDNA: %s\n", error_message);
+ DefRNA.error = 1;
+ }
+
return brna;
}
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index ffc78a1db97..be783e5373a 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -1875,6 +1875,12 @@ static void rna_def_modifier_boolean(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem prop_solver_items[] = {
+ {eBooleanModifierSolver_BMesh, "BMESH", 0, "BMesh", "Use the BMesh boolean solver"},
+ {eBooleanModifierSolver_Carve, "CARVE", 0, "Carve", "Use the Carve boolean solver"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
srna = RNA_def_struct(brna, "BooleanModifier", "Modifier");
RNA_def_struct_ui_text(srna, "Boolean Modifier", "Boolean operations modifier");
RNA_def_struct_sdna(srna, "BooleanModifierData");
@@ -1891,35 +1897,17 @@ static void rna_def_modifier_boolean(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Operation", "");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
-#if 0 /* WITH_MOD_BOOLEAN */
- /* BMesh intersection options */
- prop = RNA_def_property(srna, "use_bmesh", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "bm_flag", eBooleanModifierBMeshFlag_Enabled);
- RNA_def_property_ui_text(prop, "Use BMesh", "Use BMesh boolean calculation");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
-
- prop = RNA_def_property(srna, "use_bmesh_separate", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "bm_flag", eBooleanModifierBMeshFlag_BMesh_Separate);
- RNA_def_property_ui_text(prop, "Separate", "Keep edges separate");
+ prop = RNA_def_property(srna, "solver", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, prop_solver_items);
+ RNA_def_property_ui_text(prop, "Solver", "");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
- prop = RNA_def_property(srna, "use_bmesh_dissolve", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "bm_flag", eBooleanModifierBMeshFlag_BMesh_NoDissolve);
- RNA_def_property_ui_text(prop, "Dissolve", "Dissolve verts created from tessellated intersection");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
-
- prop = RNA_def_property(srna, "use_bmesh_connect_regions", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "bm_flag", eBooleanModifierBMeshFlag_BMesh_NoConnectRegions);
- RNA_def_property_ui_text(prop, "Calculate Holes", "Connect regions (needed for hole filling)");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
-
- prop = RNA_def_property(srna, "threshold", PROP_FLOAT, PROP_DISTANCE);
- RNA_def_property_float_sdna(prop, NULL, "threshold");
+ prop = RNA_def_property(srna, "double_threshold", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_float_sdna(prop, NULL, "double_threshold");
RNA_def_property_range(prop, 0, 1.0f);
- RNA_def_property_ui_range(prop, 0, 1, 1, 7);
- RNA_def_property_ui_text(prop, "Threshold", "");
+ RNA_def_property_ui_range(prop, 0, 1, 0.0001, 7);
+ RNA_def_property_ui_text(prop, "Overlap Threshold", "Threshold for checking overlapping geometry");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
-#endif
}
static void rna_def_modifier_array(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index e8efb202531..127c6d4d95e 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -1002,7 +1002,7 @@ static void rna_GameObjectSettings_physics_type_set(PointerRNA *ptr, int value)
ob->gameflag &= ~(OB_SENSOR | OB_OCCLUDER | OB_DYNAMIC | OB_RIGID_BODY | OB_SOFT_BODY | OB_ACTOR |
OB_ANISOTROPIC_FRICTION | OB_DO_FH | OB_ROT_FH | OB_COLLISION_RESPONSE | OB_NAVMESH);
/* When we switch to character physics and the collision bounds is set to triangle mesh
- we have to change collision bounds because triangle mesh is not supported by Characters*/
+ * we have to change collision bounds because triangle mesh is not supported by Characters */
if ((ob->gameflag & OB_BOUNDS) && ob->collision_boundtype == OB_BOUND_TRIANGLE_MESH) {
ob->boundtype = ob->collision_boundtype = OB_BOUND_BOX;
}
diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c
index 3f418fa16f3..da0f5aa3923 100644
--- a/source/blender/modifiers/intern/MOD_boolean.c
+++ b/source/blender/modifiers/intern/MOD_boolean.c
@@ -33,7 +33,7 @@
*/
// #ifdef DEBUG_TIME
-// #define USE_BMESH
+#define USE_BMESH
#ifdef WITH_MOD_BOOLEAN
# define USE_CARVE WITH_MOD_BOOLEAN
#endif
@@ -71,6 +71,14 @@
#include "PIL_time_utildefines.h"
#endif
+static void initData(ModifierData *md)
+{
+ BooleanModifierData *bmd = (BooleanModifierData *)md;
+
+ bmd->solver = eBooleanModifierSolver_BMesh;
+ bmd->double_threshold = 1e-6f;
+}
+
static void copyData(ModifierData *md, ModifierData *target)
{
#if 0
@@ -222,7 +230,9 @@ static DerivedMesh *applyModifier_bmesh(
#ifdef DEBUG_TIME
TIMEIT_START(boolean_bmesh);
#endif
- bm = BM_mesh_create_ex(&allocsize, );
+ bm = BM_mesh_create(
+ &allocsize,
+ &((struct BMeshCreateParams){.use_toolflags = false,}));
DM_to_bmesh_ex(dm_other, bm, true);
DM_to_bmesh_ex(dm, bm, true);
@@ -296,16 +306,21 @@ static DerivedMesh *applyModifier_bmesh(
* currently this is ok for 'BM_mesh_intersect' */
// BM_mesh_normals_update(bm);
+ /* change for testing */
+ bool use_separate = false;
+ bool use_dissolve = true;
+ bool use_island_connect = true;
+
BM_mesh_intersect(
bm,
looptris, tottri,
bm_face_isect_pair, NULL,
false,
- (bmd->bm_flag & eBooleanModifierBMeshFlag_BMesh_Separate) != 0,
- (bmd->bm_flag & eBooleanModifierBMeshFlag_BMesh_NoDissolve) == 0,
- (bmd->bm_flag & eBooleanModifierBMeshFlag_BMesh_NoConnectRegions) == 0,
+ use_separate,
+ use_dissolve,
+ use_island_connect,
bmd->operation,
- bmd->threshold);
+ bmd->double_threshold);
MEM_freeN(looptris);
}
@@ -409,15 +424,14 @@ static DerivedMesh *applyModifier(
ModifierApplyFlag flag)
{
BooleanModifierData *bmd = (BooleanModifierData *)md;
- const int method = (bmd->bm_flag & eBooleanModifierBMeshFlag_Enabled) ? 1 : 0;
- switch (method) {
+ switch (bmd->solver) {
#ifdef USE_CARVE
- case 0:
+ case eBooleanModifierSolver_Carve:
return applyModifier_carve(md, ob, derivedData, flag);
#endif
#ifdef USE_BMESH
- case 1:
+ case eBooleanModifierSolver_BMesh:
return applyModifier_bmesh(md, ob, derivedData, flag);
#endif
default:
@@ -441,7 +455,7 @@ ModifierTypeInfo modifierType_Boolean = {
/* deformMatricesEM */ NULL,
/* applyModifier */ applyModifier,
/* applyModifierEM */ NULL,
- /* initData */ NULL,
+ /* initData */ initData,
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
diff --git a/source/blender/python/bmesh/bmesh_py_api.c b/source/blender/python/bmesh/bmesh_py_api.c
index eb1594688c7..d5973baeadb 100644
--- a/source/blender/python/bmesh/bmesh_py_api.c
+++ b/source/blender/python/bmesh/bmesh_py_api.c
@@ -207,20 +207,21 @@ PyObject *BPyInit_bmesh(void)
/* bmesh.types */
PyModule_AddObject(mod, "types", (submodule = BPyInit_bmesh_types()));
- PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
+ PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
Py_INCREF(submodule);
+ /* bmesh.ops (not a real module, exposes module like access). */
PyModule_AddObject(mod, "ops", (submodule = BPyInit_bmesh_ops()));
- /* PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule); */
+ /* PyDict_SetItemString(sys_modules, PyModule_GetNameObject(submodule), submodule); */
PyDict_SetItemString(sys_modules, "bmesh.ops", submodule); /* fake module */
Py_INCREF(submodule);
PyModule_AddObject(mod, "utils", (submodule = BPyInit_bmesh_utils()));
- PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
+ PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
Py_INCREF(submodule);
PyModule_AddObject(mod, "geometry", (submodule = BPyInit_bmesh_geometry()));
- PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
+ PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
Py_INCREF(submodule);
return mod;
diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c
index db8ed072722..11646f3f3df 100644
--- a/source/blender/python/generic/idprop_py_api.c
+++ b/source/blender/python/generic/idprop_py_api.c
@@ -1560,7 +1560,7 @@ PyObject *BPyInit_idprop(void)
/* idprop.types */
PyModule_AddObject(mod, "types", (submodule = BPyInit_idprop_types()));
- PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
+ PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
Py_INCREF(submodule);
return mod;
diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c
index 7f13a7a4d94..72dec55e50b 100644
--- a/source/blender/python/generic/py_capi_utils.c
+++ b/source/blender/python/generic/py_capi_utils.c
@@ -177,7 +177,7 @@ PyObject *PyC_FromArray(const void *array, int length, const PyTypeObject *type,
/**
* Caller needs to ensure tuple is uninitialized.
- * Handy for filling a typle with None for eg.
+ * Handy for filling a tuple with None for eg.
*/
void PyC_Tuple_Fill(PyObject *tuple, PyObject *value)
{
@@ -367,11 +367,12 @@ PyObject *PyC_FrozenSetFromStrings(const char **strings)
}
-/* similar to PyErr_Format(),
+/**
+ * Similar to #PyErr_Format(),
*
- * implementation - we cant actually preprend the existing exception,
+ * Implementation - we cant actually prepend the existing exception,
* because it could have _any_ arguments given to it, so instead we get its
- * __str__ output and raise our own exception including it.
+ * ``__str__`` output and raise our own exception including it.
*/
PyObject *PyC_Err_Format_Prefix(PyObject *exception_type_prefix, const char *format, ...)
{
@@ -748,6 +749,7 @@ void PyC_RunQuicky(const char *filepath, int n, ...)
/* set the value so we can access it */
PyDict_SetItemString(py_dict, "values", values);
+ Py_DECREF(values);
py_result = PyRun_File(fp, filepath, Py_file_input, py_dict, py_dict);
diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c
index 17617a231b2..727d980b182 100644
--- a/source/blender/python/intern/bpy_app.c
+++ b/source/blender/python/intern/bpy_app.c
@@ -236,7 +236,7 @@ static int bpy_app_debug_set(PyObject *UNUSED(self), PyObject *value, void *clos
PyDoc_STRVAR(bpy_app_binary_path_python_doc,
"String, the path to the python executable (read-only)"
);
-static PyObject *bpy_app_binary_path_python_get(PyObject *UNUSED(self), void *UNUSED(closure))
+static PyObject *bpy_app_binary_path_python_get(PyObject *self, void *UNUSED(closure))
{
/* refcount is held in BlenderAppType.tp_dict */
static PyObject *ret = NULL;
@@ -248,7 +248,7 @@ static PyObject *bpy_app_binary_path_python_get(PyObject *UNUSED(self), void *UN
fullpath, sizeof(fullpath),
PY_MAJOR_VERSION, PY_MINOR_VERSION);
ret = PyC_UnicodeFromByte(fullpath);
- PyDict_SetItemString(BlenderAppType.tp_dict, "binary_path_python", ret);
+ PyDict_SetItem(BlenderAppType.tp_dict, PyDescr_NAME(self), ret);
}
else {
Py_INCREF(ret);
@@ -356,10 +356,10 @@ static PyGetSetDef bpy_app_getsets[] = {
static void py_struct_seq_getset_init(void)
{
/* tricky dynamic members, not to py-spec! */
- PyGetSetDef *getset;
-
- for (getset = bpy_app_getsets; getset->name; getset++) {
- PyDict_SetItemString(BlenderAppType.tp_dict, getset->name, PyDescr_NewGetSet(&BlenderAppType, getset));
+ for (PyGetSetDef *getset = bpy_app_getsets; getset->name; getset++) {
+ PyObject *item = PyDescr_NewGetSet(&BlenderAppType, getset);
+ PyDict_SetItem(BlenderAppType.tp_dict, PyDescr_NAME(item), item);
+ Py_DECREF(item);
}
}
/* end dynamic bpy.app */
diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c
index 9b477e384db..65b6bd501ce 100644
--- a/source/blender/python/intern/bpy_driver.c
+++ b/source/blender/python/intern/bpy_driver.c
@@ -110,9 +110,11 @@ static void bpy_pydriver_update_dict(const float evaltime)
bpy_pydriver_InternStr__frame = PyUnicode_FromString("frame");
}
+ PyObject *item = PyFloat_FromDouble(evaltime);
PyDict_SetItem(bpy_pydriver_Dict,
bpy_pydriver_InternStr__frame,
- PyFloat_FromDouble(evaltime));
+ item);
+ Py_DECREF(item);
bpy_pydriver_evaltime_prev = evaltime;
}
@@ -301,7 +303,10 @@ float BPY_driver_exec(ChannelDriver *driver, const float evaltime)
/* try to add to dictionary */
/* if (PyDict_SetItemString(driver_vars, dvar->name, driver_arg)) { */
- if (PyDict_SetItem(driver_vars, PyTuple_GET_ITEM(expr_vars, i++), driver_arg) < 0) {
+ if (PyDict_SetItem(driver_vars, PyTuple_GET_ITEM(expr_vars, i++), driver_arg) != -1) {
+ Py_DECREF(driver_arg);
+ }
+ else {
/* this target failed - bad name */
if (targets_ok) {
/* first one - print some extra info for easier identification */
diff --git a/source/blender/python/intern/bpy_library_load.c b/source/blender/python/intern/bpy_library_load.c
index a120e4886e0..37a7e0e23dd 100644
--- a/source/blender/python/intern/bpy_library_load.c
+++ b/source/blender/python/intern/bpy_library_load.c
@@ -39,7 +39,6 @@
#include "BLO_readfile.h"
-#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_library.h"
#include "BKE_idcode.h"
@@ -186,6 +185,7 @@ PyDoc_STRVAR(bpy_lib_load_doc,
static PyObject *bpy_lib_load(PyObject *UNUSED(self), PyObject *args, PyObject *kwds)
{
static const char *kwlist[] = {"filepath", "link", "relative", NULL};
+ Main *bmain = CTX_data_main(BPy_GetContext());
BPy_Library *ret;
const char *filename = NULL;
bool is_rel = false, is_link = false;
@@ -204,7 +204,7 @@ static PyObject *bpy_lib_load(PyObject *UNUSED(self), PyObject *args, PyObject *
BLI_strncpy(ret->relpath, filename, sizeof(ret->relpath));
BLI_strncpy(ret->abspath, filename, sizeof(ret->abspath));
- BLI_path_abs(ret->abspath, G.main->name);
+ BLI_path_abs(ret->abspath, bmain->name);
ret->blo_handle = NULL;
ret->flag = ((is_link ? FILE_LINK : 0) |
@@ -222,19 +222,16 @@ static PyObject *_bpy_names(BPy_Library *self, int blocktype)
int totnames;
names = BLO_blendhandle_get_datablock_names(self->blo_handle, blocktype, &totnames);
+ list = PyList_New(totnames);
if (names) {
int counter = 0;
- list = PyList_New(totnames);
for (l = names; l; l = l->next) {
PyList_SET_ITEM(list, counter, PyUnicode_FromString((char *)l->link));
counter++;
}
BLI_linklist_free(names, free); /* free linklist *and* each node's data */
}
- else {
- list = PyList_New(0);
- }
return list;
}
@@ -264,8 +261,13 @@ static PyObject *bpy_lib_enter(BPy_Library *self, PyObject *UNUSED(args))
if (BKE_idcode_is_linkable(code)) {
const char *name_plural = BKE_idcode_to_name_plural(code);
PyObject *str = PyUnicode_FromString(name_plural);
- PyDict_SetItem(self->dict, str, PyList_New(0));
- PyDict_SetItem(from_dict, str, _bpy_names(self, code));
+ PyObject *item;
+
+ PyDict_SetItem(self->dict, str, item = PyList_New(0));
+ Py_DECREF(item);
+ PyDict_SetItem(from_dict, str, item = _bpy_names(self, code));
+ Py_DECREF(item);
+
Py_DECREF(str);
}
}
@@ -346,48 +348,44 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
/* loop */
Py_ssize_t size = PyList_GET_SIZE(ls);
Py_ssize_t i;
- PyObject *item;
- const char *item_str;
for (i = 0; i < size; i++) {
- item = PyList_GET_ITEM(ls, i);
- item_str = _PyUnicode_AsString(item);
+ PyObject *item_src = PyList_GET_ITEM(ls, i);
+ PyObject *item_dst; /* must be set below */
+ const char *item_idname = _PyUnicode_AsString(item_src);
- // printf(" %s\n", item_str);
+ // printf(" %s\n", item_idname);
- if (item_str) {
- ID *id = BLO_library_link_named_part(mainl, &(self->blo_handle), idcode, item_str);
+ if (item_idname) {
+ ID *id = BLO_library_link_named_part(mainl, &(self->blo_handle), idcode, item_idname);
if (id) {
#ifdef USE_RNA_DATABLOCKS
/* swap name for pointer to the id */
- Py_DECREF(item);
- item = PyCapsule_New((void *)id, NULL, NULL);
+ item_dst = PyCapsule_New((void *)id, NULL, NULL);
+#else
+ /* leave as is */
+ continue;
#endif
}
else {
- bpy_lib_exit_warn_idname(self, name_plural, item_str);
+ bpy_lib_exit_warn_idname(self, name_plural, item_idname);
/* just warn for now */
/* err = -1; */
-#ifdef USE_RNA_DATABLOCKS
- item = Py_INCREF_RET(Py_None);
-#endif
+ item_dst = Py_INCREF_RET(Py_None);
}
/* ID or None */
}
else {
/* XXX, could complain about this */
- bpy_lib_exit_warn_type(self, item);
+ bpy_lib_exit_warn_type(self, item_src);
PyErr_Clear();
-
-#ifdef USE_RNA_DATABLOCKS
- item = Py_INCREF_RET(Py_None);
-#endif
+ item_dst = Py_INCREF_RET(Py_None);
}
-#ifdef USE_RNA_DATABLOCKS
- PyList_SET_ITEM(ls, i, item);
-#endif
+ /* item_dst must be new or already incref'd */
+ Py_DECREF(item_src);
+ PyList_SET_ITEM(ls, i, item_dst);
}
}
}
@@ -410,7 +408,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
/* copied from wm_operator.c */
{
/* mark all library linked objects to be updated */
- BKE_main_lib_objects_recalc_all(G.main);
+ BKE_main_lib_objects_recalc_all(bmain);
/* append, rather than linking */
if ((self->flag & FILE_LINK) == 0) {
@@ -422,6 +420,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
/* finally swap the capsules for real bpy objects
* important since BLO_library_append_end initializes NodeTree types used by srna->refine */
+#ifdef USE_RNA_DATABLOCKS
{
int idcode_step = 0, idcode;
while ((idcode = BKE_idcode_iter_step(&idcode_step))) {
@@ -451,6 +450,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args))
}
}
}
+#endif /* USE_RNA_DATABLOCKS */
Py_RETURN_NONE;
}
diff --git a/source/blender/python/intern/gpu.c b/source/blender/python/intern/gpu.c
index c3bb588f7eb..50dd4618166 100644
--- a/source/blender/python/intern/gpu.c
+++ b/source/blender/python/intern/gpu.c
@@ -330,10 +330,10 @@ PyObject *GPU_initPython(void)
/* gpu.offscreen */
PyModule_AddObject(module, "offscreen", (submodule = BPyInit_gpu_offscreen()));
- PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
+ PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
Py_INCREF(submodule);
- PyDict_SetItemString(PyImport_GetModuleDict(), "gpu", module);
+ PyDict_SetItem(PyImport_GetModuleDict(), PyModule_GetNameObject(module), module);
return module;
}
diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c
index 635090869ea..5c505247a97 100644
--- a/source/blender/python/mathutils/mathutils.c
+++ b/source/blender/python/mathutils/mathutils.c
@@ -638,30 +638,30 @@ PyMODINIT_FUNC PyInit_mathutils(void)
/* XXX, python doesnt do imports with this usefully yet
* 'from mathutils.geometry import PolyFill'
* ...fails without this. */
- PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
+ PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
Py_INCREF(submodule);
PyModule_AddObject(mod, "interpolate", (submodule = PyInit_mathutils_interpolate()));
/* XXX, python doesnt do imports with this usefully yet
* 'from mathutils.geometry import PolyFill'
* ...fails without this. */
- PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
+ PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
Py_INCREF(submodule);
#ifndef MATH_STANDALONE
/* Noise submodule */
PyModule_AddObject(mod, "noise", (submodule = PyInit_mathutils_noise()));
- PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
+ PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
Py_INCREF(submodule);
/* BVHTree submodule */
PyModule_AddObject(mod, "bvhtree", (submodule = PyInit_mathutils_bvhtree()));
- PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
+ PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
Py_INCREF(submodule);
/* KDTree submodule */
PyModule_AddObject(mod, "kdtree", (submodule = PyInit_mathutils_kdtree()));
- PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
+ PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule);
Py_INCREF(submodule);
#endif
diff --git a/source/blender/quicktime/apple/qtkit_import.m b/source/blender/quicktime/apple/qtkit_import.m
index d42d0ee8ebb..ba7ee0a8936 100644
--- a/source/blender/quicktime/apple/qtkit_import.m
+++ b/source/blender/quicktime/apple/qtkit_import.m
@@ -200,7 +200,7 @@ static ImBuf *nsImageToiBuf(NSImage *sourceImage, int width, int height)
/* Convert the image in a RGBA 32bit format */
/* As Core Graphics does not support contextes with non premutliplied alpha,
- we need to get alpha key values in a separate batch */
+ * we need to get alpha key values in a separate batch */
/* First get RGB values w/o Alpha to avoid pre-multiplication, 32bit but last byte is unused */
blBitmapFormatImageRGB = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index 6de5da3795a..b3a5ccdae17 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -180,6 +180,7 @@ struct Render {
float jit[32][2];
float mblur_jit[32][2];
ListBase *qmcsamplers;
+ int num_qmc_samplers;
/* shadow counter, detect shadow-reuse for shaders */
int shadowsamplenr[BLENDER_MAX_THREADS];
diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h
index 308903c6c6d..7254fd25ee6 100644
--- a/source/blender/render/intern/include/rendercore.h
+++ b/source/blender/render/intern/include/rendercore.h
@@ -90,7 +90,7 @@ extern void ray_shadow(ShadeInput *shi, LampRen *lar, float shadfac[4]);
extern void ray_trace(ShadeInput *shi, ShadeResult *);
extern void ray_ao(ShadeInput *shi, float ao[3], float env[3]);
extern void init_jitter_plane(LampRen *lar);
-extern void init_ao_sphere(struct World *wrld);
+extern void init_ao_sphere(Render *re, struct World *wrld);
extern void init_render_qmcsampler(Render *re);
extern void free_render_qmcsampler(Render *re);
diff --git a/source/blender/render/intern/raytrace/rayobject.cpp b/source/blender/render/intern/raytrace/rayobject.cpp
index f511042749e..2104315dc00 100644
--- a/source/blender/render/intern/raytrace/rayobject.cpp
+++ b/source/blender/render/intern/raytrace/rayobject.cpp
@@ -145,8 +145,8 @@ MALWAYS_INLINE int isec_tri_quad(float start[3], const struct IsectRayPrecalc *i
if (isect_ray_tri_watertight_v3(start, isect_precalc, face->v1, face->v2, face->v3, &l, uv)) {
/* check if intersection is within ray length */
if (l > -RE_RAYTRACE_EPSILON && l < *lambda) {
- r_uv[0] = uv[0];
- r_uv[1] = uv[1];
+ r_uv[0] = -uv[0];
+ r_uv[1] = -uv[1];
*lambda = l;
return 1;
}
@@ -157,8 +157,8 @@ MALWAYS_INLINE int isec_tri_quad(float start[3], const struct IsectRayPrecalc *i
if (isect_ray_tri_watertight_v3(start, isect_precalc, face->v1, face->v3, face->v4, &l, uv)) {
/* check if intersection is within ray length */
if (l > -RE_RAYTRACE_EPSILON && l < *lambda) {
- r_uv[0] = uv[0];
- r_uv[1] = uv[1];
+ r_uv[0] = -uv[0];
+ r_uv[1] = -uv[1];
*lambda = l;
return 2;
}
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 3dcde1f4bb1..468d66f6065 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -3961,7 +3961,7 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
if (re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT))
if (re->wrld.ao_samp_method == WO_AOSAMP_CONSTANT)
- init_ao_sphere(&re->wrld);
+ init_ao_sphere(re, &re->wrld);
}
/* still bad... doing all */
@@ -4687,7 +4687,7 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay,
if (re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT))
if (re->wrld.ao_samp_method == WO_AOSAMP_CONSTANT)
- init_ao_sphere(&re->wrld);
+ init_ao_sphere(re, &re->wrld);
}
/* still bad... doing all */
diff --git a/source/blender/render/intern/source/occlusion.c b/source/blender/render/intern/source/occlusion.c
index c5c3b6bbf94..b3d31e3b93a 100644
--- a/source/blender/render/intern/source/occlusion.c
+++ b/source/blender/render/intern/source/occlusion.c
@@ -115,6 +115,8 @@ typedef struct OcclusionTree {
int doindirect;
OcclusionCache *cache;
+
+ int num_threads;
} OcclusionTree;
typedef struct OcclusionThread {
@@ -641,6 +643,7 @@ static void occ_build_sh_normalize(OccNode *node)
static OcclusionTree *occ_tree_build(Render *re)
{
+ const int num_threads = re->r.threads;
OcclusionTree *tree;
ObjectInstanceRen *obi;
ObjectRen *obr;
@@ -679,7 +682,7 @@ static OcclusionTree *occ_tree_build(Render *re)
BLI_memarena_use_calloc(tree->arena);
if (re->wrld.aomode & WO_AOCACHE)
- tree->cache = MEM_callocN(sizeof(OcclusionCache) * BLENDER_MAX_THREADS, "OcclusionCache");
+ tree->cache = MEM_callocN(sizeof(OcclusionCache) * num_threads, "OcclusionCache");
tree->face = MEM_callocN(sizeof(OccFace) * totface, "OcclusionFace");
tree->co = MEM_callocN(sizeof(float) * 3 * totface, "OcclusionCo");
@@ -730,9 +733,11 @@ static OcclusionTree *occ_tree_build(Render *re)
if (!(re->test_break(re->tbh)))
occ_build_sh_normalize(tree->root);
- for (a = 0; a < BLENDER_MAX_THREADS; a++)
+ for (a = 0; a < num_threads; a++)
tree->stack[a] = MEM_callocN(sizeof(OccNode) * TOTCHILD * (tree->maxdepth + 1), "OccStack");
+ tree->num_threads = num_threads;
+
return tree;
}
@@ -742,7 +747,7 @@ static void occ_free_tree(OcclusionTree *tree)
if (tree) {
if (tree->arena) BLI_memarena_free(tree->arena);
- for (a = 0; a < BLENDER_MAX_THREADS; a++)
+ for (a = 0; a < tree->num_threads; a++)
if (tree->stack[a])
MEM_freeN(tree->stack[a]);
if (tree->occlusion) MEM_freeN(tree->occlusion);
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 100d87a037a..49d6e5a0d7f 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -354,7 +354,7 @@ Scene *RE_GetScene(Render *re)
* Same as #RE_AcquireResultImage but creating the necessary views to store the result
* fill provided result struct with a copy of thew views of what is done so far the
* #RenderResult.views #ListBase needs to be freed after with #RE_ReleaseResultImageViews
-*/
+ */
void RE_AcquireResultImageViews(Render *re, RenderResult *rr)
{
memset(rr, 0, sizeof(RenderResult));
diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c
index 9aac5ed1f1d..26a0b0c71b4 100644
--- a/source/blender/render/intern/source/rayshade.c
+++ b/source/blender/render/intern/source/rayshade.c
@@ -174,10 +174,11 @@ void freeraytree(Render *re)
#ifdef RE_RAYCOUNTER
{
+ const int num_threads = re->r.threads;
RayCounter sum;
memset(&sum, 0, sizeof(sum));
int i;
- for (i=0; i<BLENDER_MAX_THREADS; i++)
+ for (i=0; i<num_threads; i++)
RE_RC_MERGE(&sum, re_rc_counter+i);
RE_RC_INFO(&sum);
}
@@ -1186,7 +1187,9 @@ static void QMC_sampleHemiCosine(float vec[3], QMCSampler *qsa, int thread, int
/* called from convertBlenderScene.c */
void init_render_qmcsampler(Render *re)
{
- re->qmcsamplers= MEM_callocN(sizeof(ListBase)*BLENDER_MAX_THREADS, "QMCListBase");
+ const int num_threads = re->r.threads;
+ re->qmcsamplers= MEM_callocN(sizeof(ListBase)*num_threads, "QMCListBase");
+ re->num_qmc_samplers = num_threads;
}
static QMCSampler *get_thread_qmcsampler(Render *re, int thread, int type, int tot)
@@ -1220,7 +1223,7 @@ void free_render_qmcsampler(Render *re)
if (re->qmcsamplers) {
QMCSampler *qsa, *next;
int a;
- for (a=0; a<BLENDER_MAX_THREADS; a++) {
+ for (a = 0; a < re->num_qmc_samplers; a++) {
for (qsa=re->qmcsamplers[a].first; qsa; qsa=next) {
next= qsa->next;
QMC_freeSampler(qsa);
@@ -1695,9 +1698,10 @@ static void DS_energy(float *sphere, int tot, float vec[3])
/* called from convertBlenderScene.c */
/* creates an equally distributed spherical sample pattern */
/* and allocates threadsafe memory */
-void init_ao_sphere(World *wrld)
+void init_ao_sphere(Render *re, World *wrld)
{
/* fixed random */
+ const int num_threads = re->r.threads;
RNG *rng;
float *fp;
int a, tot, iter= 16;
@@ -1721,7 +1725,7 @@ void init_ao_sphere(World *wrld)
}
/* tables */
- wrld->aotables= MEM_mallocN(BLENDER_MAX_THREADS*3*tot*sizeof(float), "AO tables");
+ wrld->aotables= MEM_mallocN(num_threads*3*tot*sizeof(float), "AO tables");
BLI_rng_free(rng);
}
diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c
index 513cfa6df7d..b4a14f5337d 100644
--- a/source/blender/render/intern/source/render_texture.c
+++ b/source/blender/render/intern/source/render_texture.c
@@ -3653,7 +3653,8 @@ void render_realtime_texture(ShadeInput *shi, Image *ima)
if (firsttime) {
BLI_lock_thread(LOCK_IMAGE);
if (firsttime) {
- for (a=0; a<BLENDER_MAX_THREADS; a++) {
+ const int num_threads = BLI_system_thread_count();
+ for (a = 0; a < num_threads; a++) {
memset(&imatex[a], 0, sizeof(Tex));
BKE_texture_default(&imatex[a]);
imatex[a].type= TEX_IMAGE;
diff --git a/source/blender/render/intern/source/sss.c b/source/blender/render/intern/source/sss.c
index 553710b4367..26ca3ad50e0 100644
--- a/source/blender/render/intern/source/sss.c
+++ b/source/blender/render/intern/source/sss.c
@@ -279,13 +279,19 @@ static void build_Rd_table(ScatterSettings *ss)
for (i= 0; i < size; i++) {
r= i*(RD_TABLE_RANGE/RD_TABLE_SIZE);
- /*if (r < ss->invsigma_t_*ss->invsigma_t_)
- r= ss->invsigma_t_*ss->invsigma_t_;*/
+#if 0
+ if (r < ss->invsigma_t_*ss->invsigma_t_) {
+ r= ss->invsigma_t_*ss->invsigma_t_;
+ }
+#endif
ss->tableRd[i]= Rd(ss, sqrtf(r));
r= i*(RD_TABLE_RANGE_2/RD_TABLE_SIZE);
- /*if (r < ss->invsigma_t_)
- r= ss->invsigma_t_;*/
+#if 0
+ if (r < ss->invsigma_t_) {
+ r= ss->invsigma_t_;
+ }
+#endif
ss->tableRd2[i]= Rd(ss, r);
}
}
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 729af731dfe..fe257cc4c41 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -482,8 +482,6 @@ static void wm_file_read_post(bContext *C, bool is_startup_file)
BPY_python_reset(C);
addons_loaded = true;
}
-#else
- UNUSED_VARS(is_startup_file);
#endif /* WITH_PYTHON */
WM_operatortype_last_properties_clear_all();
@@ -492,8 +490,12 @@ static void wm_file_read_post(bContext *C, bool is_startup_file)
BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_VERSION_UPDATE);
BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST);
- /* would otherwise be handled by event loop */
- if (G.background) {
+ /* Would otherwise be handled by event loop.
+ *
+ * Disabled for startup file, since it causes problems when PyDrivers are used in the startup file.
+ * While its possible state of startup file may be wrong,
+ * in this case users nearly always load a file to replace the startup file. */
+ if (G.background && (is_startup_file == false)) {
Main *bmain = CTX_data_main(C);
BKE_scene_update_tagged(bmain->eval_ctx, bmain, CTX_data_scene(C));
}
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 9d1083bbf63..3022d865460 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -40,6 +40,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_genfile.h"
#include "DNA_scene_types.h"
#include "DNA_userdef_types.h"
#include "DNA_windowmanager_types.h"
@@ -584,6 +585,8 @@ void WM_exit_ext(bContext *C, const bool do_python)
GHOST_DisposeSystemPaths();
+ DNA_sdna_current_free();
+
BLI_threadapi_exit();
BKE_blender_atexit();
diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt
index 206007b8d8b..ca841954b16 100644
--- a/source/blenderplayer/CMakeLists.txt
+++ b/source/blenderplayer/CMakeLists.txt
@@ -63,6 +63,8 @@ if(WIN32 AND NOT UNIX)
COMPONENT Blenderplayer
DESTINATION ".")
+add_cc_flags_custom_test(blenderplayer)
+
elseif(APPLE)
add_executable(blenderplayer ${EXETYPE} bad_level_call_stubs/stubs.c)
# setup Info.plist
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index 4e8dd6f9fd3..d8435284096 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -222,6 +222,8 @@ if(WITH_BUILDINFO)
add_dependencies(buildinfoobj buildinfo)
endif()
+add_cc_flags_custom_test(blender)
+
# message(STATUS "Configuring blender")
if(WITH_PYTHON_MODULE)
add_definitions(-DWITH_PYTHON_MODULE)
diff --git a/source/creator/creator.c b/source/creator/creator.c
index bd4db12888f..85c4e5b0681 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -42,6 +42,8 @@
#include "MEM_guardedalloc.h"
+#include "DNA_genfile.h"
+
#include "BLI_args.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
@@ -349,6 +351,8 @@ int main(
BLI_threadapi_init();
+ DNA_sdna_current_init();
+
BKE_blender_globals_init(); /* blender.c */
IMB_init();
diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c
index c89cdea4e29..c3c76a0d1d3 100644
--- a/source/creator/creator_args.c
+++ b/source/creator/creator_args.c
@@ -739,8 +739,6 @@ static const char arg_handle_debug_mode_generic_set_doc_handlers[] =
"\n\tEnable debug messages for event handling";
static const char arg_handle_debug_mode_generic_set_doc_wm[] =
"\n\tEnable debug messages for the window manager, also prints every operator call";
-static const char arg_handle_debug_mode_generic_set_doc_all[] =
-"\n\tEnable all debug messages (excludes libmv)";
static const char arg_handle_debug_mode_generic_set_doc_jobs[] =
"\n\tEnable time profiling for background jobs.";
static const char arg_handle_debug_mode_generic_set_doc_gpu[] =
@@ -758,6 +756,20 @@ static int arg_handle_debug_mode_generic_set(int UNUSED(argc), const char **UNUS
return 0;
}
+static const char arg_handle_debug_mode_all_doc[] =
+"\n\tEnable all debug messages";
+static int arg_handle_debug_mode_all(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
+{
+ G.debug |= G_DEBUG_ALL;
+#ifdef WITH_LIBMV
+ libmv_startDebugLogging();
+#endif
+#ifdef WITH_CYCLES_LOGGING
+ CCL_start_debug_logging();
+#endif
+ return 0;
+}
+
#ifdef WITH_LIBMV
static const char arg_handle_debug_mode_libmv_doc[] =
"\n\tEnable debug messages from libmv library"
@@ -1791,8 +1803,7 @@ void main_args_setup(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
CB_EX(arg_handle_debug_mode_generic_set, handlers), (void *)G_DEBUG_HANDLERS);
BLI_argsAdd(ba, 1, NULL, "--debug-wm",
CB_EX(arg_handle_debug_mode_generic_set, wm), (void *)G_DEBUG_WM);
- BLI_argsAdd(ba, 1, NULL, "--debug-all",
- CB_EX(arg_handle_debug_mode_generic_set, all), (void *)G_DEBUG_ALL);
+ BLI_argsAdd(ba, 1, NULL, "--debug-all", CB(arg_handle_debug_mode_all), NULL);
BLI_argsAdd(ba, 1, NULL, "--debug-fpe",
CB(arg_handle_debug_fpe_set), NULL);
diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp
index 25936b34fde..fd2e723741c 100644
--- a/source/gameengine/GameLogic/SCA_PythonController.cpp
+++ b/source/gameengine/GameLogic/SCA_PythonController.cpp
@@ -163,7 +163,9 @@ void SCA_PythonController::SetNamespace(PyObject* pythondictionary)
/* Without __file__ set the sys.argv[0] is used for the filename
* which ends up with lines from the blender binary being printed in the console */
- PyDict_SetItemString(m_pythondictionary, "__file__", PyUnicode_From_STR_String(m_scriptName));
+ PyObject *value = PyUnicode_From_STR_String(m_scriptName);
+ PyDict_SetItemString(m_pythondictionary, "__file__", value);
+ Py_DECREF(value);
}
#endif
diff --git a/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp b/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp
index 19aae46f2a3..9a96a7b0334 100644
--- a/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp
+++ b/source/gameengine/GameLogic/SCA_PythonKeyboard.cpp
@@ -113,11 +113,15 @@ PyObject *SCA_PythonKeyboard::pyattr_get_events(void *self_v, const KX_PYATTRIBU
{
SCA_PythonKeyboard* self = static_cast<SCA_PythonKeyboard*>(self_v);
- for (int i=SCA_IInputDevice::KX_BEGINKEY; i<=SCA_IInputDevice::KX_ENDKEY; i++)
- {
+ for (int i = SCA_IInputDevice::KX_BEGINKEY; i <= SCA_IInputDevice::KX_ENDKEY; i++) {
const SCA_InputEvent & inevent = self->m_keyboard->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i);
-
- PyDict_SetItem(self->m_event_dict, PyLong_FromLong(i), PyLong_FromLong(inevent.m_status));
+ PyObject *key = PyLong_FromLong(i);
+ PyObject *value = PyLong_FromLong(inevent.m_status);
+
+ PyDict_SetItem(self->m_event_dict, key, value);
+
+ Py_DECREF(key);
+ Py_DECREF(value);
}
Py_INCREF(self->m_event_dict);
return self->m_event_dict;
@@ -129,12 +133,18 @@ PyObject *SCA_PythonKeyboard::pyattr_get_active_events(void *self_v, const KX_PY
PyDict_Clear(self->m_event_dict);
- for (int i=SCA_IInputDevice::KX_BEGINKEY; i<=SCA_IInputDevice::KX_ENDKEY; i++)
- {
+ for (int i = SCA_IInputDevice::KX_BEGINKEY; i <= SCA_IInputDevice::KX_ENDKEY; i++) {
const SCA_InputEvent & inevent = self->m_keyboard->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i);
- if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS)
- PyDict_SetItem(self->m_event_dict, PyLong_FromLong(i), PyLong_FromLong(inevent.m_status));
+ if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS) {
+ PyObject *key = PyLong_FromLong(i);
+ PyObject *value = PyLong_FromLong(inevent.m_status);
+
+ PyDict_SetItem(self->m_event_dict, key, value);
+
+ Py_DECREF(key);
+ Py_DECREF(value);
+ }
}
Py_INCREF(self->m_event_dict);
return self->m_event_dict;
diff --git a/source/gameengine/GameLogic/SCA_PythonMouse.cpp b/source/gameengine/GameLogic/SCA_PythonMouse.cpp
index 1617f714113..184b306a665 100644
--- a/source/gameengine/GameLogic/SCA_PythonMouse.cpp
+++ b/source/gameengine/GameLogic/SCA_PythonMouse.cpp
@@ -96,11 +96,15 @@ PyObject *SCA_PythonMouse::pyattr_get_events(void *self_v, const KX_PYATTRIBUTE_
{
SCA_PythonMouse* self = static_cast<SCA_PythonMouse*>(self_v);
- for (int i=SCA_IInputDevice::KX_BEGINMOUSE; i<=SCA_IInputDevice::KX_ENDMOUSE; i++)
- {
- const SCA_InputEvent & inevent = self->m_mouse->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i);
-
- PyDict_SetItem(self->m_event_dict, PyLong_FromLong(i), PyLong_FromLong(inevent.m_status));
+ for (int i = SCA_IInputDevice::KX_BEGINMOUSE; i <= SCA_IInputDevice::KX_ENDMOUSE; i++) {
+ const SCA_InputEvent &inevent = self->m_mouse->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i);
+ PyObject *key = PyLong_FromLong(i);
+ PyObject *value = PyLong_FromLong(inevent.m_status);
+
+ PyDict_SetItem(self->m_event_dict, key, value);
+
+ Py_DECREF(key);
+ Py_DECREF(value);
}
Py_INCREF(self->m_event_dict);
return self->m_event_dict;
@@ -112,12 +116,19 @@ PyObject *SCA_PythonMouse::pyattr_get_active_events(void *self_v, const KX_PYATT
PyDict_Clear(self->m_event_dict);
- for (int i=SCA_IInputDevice::KX_BEGINMOUSE; i<=SCA_IInputDevice::KX_ENDMOUSE; i++)
- {
- const SCA_InputEvent & inevent = self->m_mouse->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i);
+ for (int i = SCA_IInputDevice::KX_BEGINMOUSE; i <= SCA_IInputDevice::KX_ENDMOUSE; i++) {
+ const SCA_InputEvent &inevent = self->m_mouse->GetEventValue((SCA_IInputDevice::KX_EnumInputs)i);
- if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS)
- PyDict_SetItem(self->m_event_dict, PyLong_FromLong(i), PyLong_FromLong(inevent.m_status));
+ if (inevent.m_status != SCA_InputEvent::KX_NO_INPUTSTATUS) {
+
+ PyObject *key = PyLong_FromLong(i);
+ PyObject *value = PyLong_FromLong(inevent.m_status);
+
+ PyDict_SetItem(self->m_event_dict, key, value);
+
+ Py_DECREF(key);
+ Py_DECREF(value);
+ }
}
Py_INCREF(self->m_event_dict);
return self->m_event_dict;
diff --git a/source/tools b/source/tools
new file mode 160000
+Subproject 373945d0978b6601c55c9d5879e0f488b18515c