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:
authorClément Foucault <foucault.clem@gmail.com>2017-01-25 14:28:52 +0300
committerClément Foucault <foucault.clem@gmail.com>2017-01-25 14:28:52 +0300
commit72ff78a9515255c1b687ad3fd63d169ef5c27355 (patch)
tree56ae2d118761dcc7080a8282e35715d8b83852d3 /source
parentc5ed9434791ec01a65756cd182e15f8744b7e6f3 (diff)
parent95e9790704c61cb26171f4c7c84673eacd5ac3bd (diff)
Merge branch 'render-layers' of git.blender.org:blender into clay-engine
# Conflicts: # source/blender/editors/space_view3d/drawobject.c
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h7
-rw-r--r--source/blender/blenkernel/BKE_armature.h1
-rw-r--r--source/blender/blenkernel/BKE_collection.h6
-rw-r--r--source/blender/blenkernel/BKE_deform.h9
-rw-r--r--source/blender/blenkernel/BKE_group.h5
-rw-r--r--source/blender/blenkernel/BKE_layer.h33
-rw-r--r--source/blender/blenkernel/BKE_mesh_render.h42
-rw-r--r--source/blender/blenkernel/BKE_modifier.h11
-rw-r--r--source/blender/blenkernel/BKE_object.h2
-rw-r--r--source/blender/blenkernel/BKE_scene.h5
-rw-r--r--source/blender/blenkernel/CMakeLists.txt6
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c13
-rw-r--r--source/blender/blenkernel/intern/action.c3
-rw-r--r--source/blender/blenkernel/intern/anim.c10
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c1
-rw-r--r--source/blender/blenkernel/intern/armature.c16
-rw-r--r--source/blender/blenkernel/intern/armature_update.c6
-rw-r--r--source/blender/blenkernel/intern/collection.c46
-rw-r--r--source/blender/blenkernel/intern/collision.c6
-rw-r--r--source/blender/blenkernel/intern/constraint.c2
-rw-r--r--source/blender/blenkernel/intern/context.c17
-rw-r--r--source/blender/blenkernel/intern/customdata.c3
-rw-r--r--source/blender/blenkernel/intern/deform.c187
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c3352
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c561
-rw-r--r--source/blender/blenkernel/intern/fcurve.c1
-rw-r--r--source/blender/blenkernel/intern/freestyle.c1
-rw-r--r--source/blender/blenkernel/intern/gpencil.c1
-rw-r--r--source/blender/blenkernel/intern/group.c17
-rw-r--r--source/blender/blenkernel/intern/ipo.c1
-rw-r--r--source/blender/blenkernel/intern/key.c1
-rw-r--r--source/blender/blenkernel/intern/layer.c197
-rw-r--r--source/blender/blenkernel/intern/library.c8
-rw-r--r--source/blender/blenkernel/intern/library_remap.c28
-rw-r--r--source/blender/blenkernel/intern/linestyle.c1
-rw-r--r--source/blender/blenkernel/intern/mask.c2
-rw-r--r--source/blender/blenkernel/intern/mball.c31
-rw-r--r--source/blender/blenkernel/intern/mball_tessellate.c2
-rw-r--r--source/blender/blenkernel/intern/mesh.c9
-rw-r--r--source/blender/blenkernel/intern/mesh_render.c619
-rw-r--r--source/blender/blenkernel/intern/modifier.c3
-rw-r--r--source/blender/blenkernel/intern/nla.c2
-rw-r--r--source/blender/blenkernel/intern/node.c5
-rw-r--r--source/blender/blenkernel/intern/object.c13
-rw-r--r--source/blender/blenkernel/intern/object_deform.c3
-rw-r--r--source/blender/blenkernel/intern/object_update.c6
-rw-r--r--source/blender/blenkernel/intern/scene.c647
-rw-r--r--source/blender/blenkernel/intern/seqmodifier.c2
-rw-r--r--source/blender/blenkernel/intern/smoke.c9
-rw-r--r--source/blender/blenkernel/intern/text.c7
-rw-r--r--source/blender/blenkernel/intern/tracking.c2
-rw-r--r--source/blender/blenkernel/intern/tracking_util.c24
-rw-r--r--source/blender/blenlib/BLI_math_geom.h8
-rw-r--r--source/blender/blenlib/BLI_math_vector.h2
-rw-r--r--source/blender/blenlib/BLI_path_util.h5
-rw-r--r--source/blender/blenlib/BLI_string_utf8.h4
-rw-r--r--source/blender/blenlib/BLI_string_utils.h63
-rw-r--r--source/blender/blenlib/CMakeLists.txt2
-rw-r--r--source/blender/blenlib/intern/math_geom.c71
-rw-r--r--source/blender/blenlib/intern/math_vector_inline.c2
-rw-r--r--source/blender/blenlib/intern/path_util.c159
-rw-r--r--source/blender/blenlib/intern/string_utf8.c18
-rw-r--r--source/blender/blenlib/intern/string_utils.c385
-rw-r--r--source/blender/blenloader/intern/readfile.c15
-rw-r--r--source/blender/blenloader/intern/versioning_260.c1
-rw-r--r--source/blender/blenloader/intern/versioning_270.c30
-rw-r--r--source/blender/blenloader/intern/versioning_280.c9
-rw-r--r--source/blender/blenloader/intern/writefile.c4
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.c34
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.h7
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.c142
-rw-r--r--source/blender/bmesh/operators/bmo_create.c6
-rw-r--r--source/blender/bmesh/operators/bmo_inset.c10
-rw-r--r--source/blender/collada/AnimationImporter.cpp2
-rw-r--r--source/blender/collada/DocumentImporter.cpp3
-rw-r--r--source/blender/depsgraph/CMakeLists.txt4
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc2
-rw-r--r--source/blender/depsgraph/intern/depsgraph_eval.cc34
-rw-r--r--source/blender/depsgraph/util/deg_util_foreach.h10
-rw-r--r--source/blender/depsgraph/util/deg_util_function.h61
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c135
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c5
-rw-r--r--source/blender/editors/animation/keyframes_general.c3
-rw-r--r--source/blender/editors/armature/armature_add.c9
-rw-r--r--source/blender/editors/armature/armature_naming.c69
-rw-r--r--source/blender/editors/armature/armature_relations.c26
-rw-r--r--source/blender/editors/armature/armature_select.c23
-rw-r--r--source/blender/editors/armature/armature_skinning.c3
-rw-r--r--source/blender/editors/armature/armature_utils.c3
-rw-r--r--source/blender/editors/armature/editarmature_retarget.c2
-rw-r--r--source/blender/editors/armature/pose_edit.c16
-rw-r--r--source/blender/editors/armature/pose_lib.c1
-rw-r--r--source/blender/editors/armature/pose_transform.c3
-rw-r--r--source/blender/editors/curve/editcurve.c17
-rw-r--r--source/blender/editors/gpencil/CMakeLists.txt1
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c5
-rw-r--r--source/blender/editors/gpencil/gpencil_convert.c3
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c1
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c810
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h3
-rw-r--r--source/blender/editors/gpencil/gpencil_interpolate.c1145
-rw-r--r--source/blender/editors/gpencil/gpencil_ops.c7
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c28
-rw-r--r--source/blender/editors/include/BIF_glutil.h1
-rw-r--r--source/blender/editors/include/ED_armature.h1
-rw-r--r--source/blender/editors/include/ED_object.h8
-rw-r--r--source/blender/editors/include/UI_resources.h4
-rw-r--r--source/blender/editors/interface/interface.c2
-rw-r--r--source/blender/editors/interface/interface_handlers.c2
-rw-r--r--source/blender/editors/interface/interface_utils.c8
-rw-r--r--source/blender/editors/interface/resources.c21
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c81
-rw-r--r--source/blender/editors/mesh/mesh_navmesh.c5
-rw-r--r--source/blender/editors/mesh/meshtools.c12
-rw-r--r--source/blender/editors/object/object_add.c190
-rw-r--r--source/blender/editors/object/object_bake.c8
-rw-r--r--source/blender/editors/object/object_edit.c184
-rw-r--r--source/blender/editors/object/object_group.c45
-rw-r--r--source/blender/editors/object/object_intern.h5
-rw-r--r--source/blender/editors/object/object_ops.c25
-rw-r--r--source/blender/editors/object/object_relations.c141
-rw-r--r--source/blender/editors/object/object_select.c306
-rw-r--r--source/blender/editors/physics/rigidbody_constraint.c4
-rw-r--r--source/blender/editors/physics/rigidbody_object.c4
-rw-r--r--source/blender/editors/screen/area.c29
-rw-r--r--source/blender/editors/screen/glutil.c12
-rw-r--r--source/blender/editors/screen/screen_context.c85
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c3
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c6
-rw-r--r--source/blender/editors/space_action/action_draw.c34
-rw-r--r--source/blender/editors/space_logic/logic_ops.c1
-rw-r--r--source/blender/editors/space_logic/logic_window.c2
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c18
-rw-r--r--source/blender/editors/space_nla/nla_channels.c5
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c308
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c205
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h7
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c9
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c86
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c70
-rw-r--r--source/blender/editors/space_text/text_ops.c1
-rw-r--r--source/blender/editors/space_view3d/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_view3d/drawanimviz.c190
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c10
-rw-r--r--source/blender/editors/space_view3d/drawobject.c386
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c140
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c34
-rw-r--r--source/blender/editors/transform/CMakeLists.txt4
-rw-r--r--source/blender/editors/transform/transform.c272
-rw-r--r--source/blender/editors/transform/transform.h2
-rw-r--r--source/blender/editors/transform/transform_conversions.c30
-rw-r--r--source/blender/editors/transform/transform_input.c4
-rw-r--r--source/blender/editors/transform/transform_orientations.c2
-rw-r--r--source/blender/gpu/GPU_immediate.h2
-rw-r--r--source/blender/gpu/gawain/batch.h2
-rw-r--r--source/blender/gpu/intern/gpu_immediate.c8
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl3
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl2
-rw-r--r--source/blender/makesdna/DNA_action_types.h8
-rw-r--r--source/blender/makesdna/DNA_layer_types.h3
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h1
-rw-r--r--source/blender/makesdna/DNA_scene_types.h52
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/RNA_types.h6
-rw-r--r--source/blender/makesrna/intern/rna_actuator.c3
-rw-r--r--source/blender/makesrna/intern/rna_animviz.c29
-rw-r--r--source/blender/makesrna/intern/rna_controller.c1
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c25
-rw-r--r--source/blender/makesrna/intern/rna_group.c12
-rw-r--r--source/blender/makesrna/intern/rna_key.c1
-rw-r--r--source/blender/makesrna/intern/rna_linestyle.c3
-rw-r--r--source/blender/makesrna/intern/rna_mesh_api.c4
-rw-r--r--source/blender/makesrna/intern/rna_particle.c2
-rw-r--r--source/blender/makesrna/intern/rna_pose.c1
-rw-r--r--source/blender/makesrna/intern/rna_property.c1
-rw-r--r--source/blender/makesrna/intern/rna_render.c11
-rw-r--r--source/blender/makesrna/intern/rna_scene.c160
-rw-r--r--source/blender/makesrna/intern/rna_sculpt_paint.c9
-rw-r--r--source/blender/makesrna/intern/rna_sensor.c1
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c2
-rw-r--r--source/blender/modifiers/intern/MOD_armature.c17
-rw-r--r--source/blender/modifiers/intern/MOD_array.c35
-rw-r--r--source/blender/modifiers/intern/MOD_bevel.c1
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.c17
-rw-r--r--source/blender/modifiers/intern/MOD_build.c1
-rw-r--r--source/blender/modifiers/intern/MOD_cast.c17
-rw-r--r--source/blender/modifiers/intern/MOD_cloth.c15
-rw-r--r--source/blender/modifiers/intern/MOD_collision.c1
-rw-r--r--source/blender/modifiers/intern/MOD_correctivesmooth.c1
-rw-r--r--source/blender/modifiers/intern/MOD_curve.c18
-rw-r--r--source/blender/modifiers/intern/MOD_datatransfer.c17
-rw-r--r--source/blender/modifiers/intern/MOD_decimate.c1
-rw-r--r--source/blender/modifiers/intern/MOD_displace.c26
-rw-r--r--source/blender/modifiers/intern/MOD_dynamicpaint.c22
-rw-r--r--source/blender/modifiers/intern/MOD_edgesplit.c1
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c1
-rw-r--r--source/blender/modifiers/intern/MOD_fluidsim.c28
-rw-r--r--source/blender/modifiers/intern/MOD_hook.c19
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciandeform.c1
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciansmooth.c1
-rw-r--r--source/blender/modifiers/intern/MOD_lattice.c17
-rw-r--r--source/blender/modifiers/intern/MOD_mask.c19
-rw-r--r--source/blender/modifiers/intern/MOD_meshcache.c1
-rw-r--r--source/blender/modifiers/intern/MOD_meshdeform.c18
-rw-r--r--source/blender/modifiers/intern/MOD_meshsequencecache.c18
-rw-r--r--source/blender/modifiers/intern/MOD_mirror.c16
-rw-r--r--source/blender/modifiers/intern/MOD_multires.c1
-rw-r--r--source/blender/modifiers/intern/MOD_none.c1
-rw-r--r--source/blender/modifiers/intern/MOD_normal_edit.c15
-rw-r--r--source/blender/modifiers/intern/MOD_ocean.c1
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c19
-rw-r--r--source/blender/modifiers/intern/MOD_particlesystem.c1
-rw-r--r--source/blender/modifiers/intern/MOD_remesh.c1
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c19
-rw-r--r--source/blender/modifiers/intern/MOD_shapekey.c1
-rw-r--r--source/blender/modifiers/intern/MOD_shrinkwrap.c18
-rw-r--r--source/blender/modifiers/intern/MOD_simpledeform.c13
-rw-r--r--source/blender/modifiers/intern/MOD_skin.c1
-rw-r--r--source/blender/modifiers/intern/MOD_smoke.c17
-rw-r--r--source/blender/modifiers/intern/MOD_smooth.c1
-rw-r--r--source/blender/modifiers/intern/MOD_softbody.c13
-rw-r--r--source/blender/modifiers/intern/MOD_solidify.c1
-rw-r--r--source/blender/modifiers/intern/MOD_subsurf.c1
-rw-r--r--source/blender/modifiers/intern/MOD_surface.c1
-rw-r--r--source/blender/modifiers/intern/MOD_triangulate.c1
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c20
-rw-r--r--source/blender/modifiers/intern/MOD_uvwarp.c13
-rw-r--r--source/blender/modifiers/intern/MOD_warp.c22
-rw-r--r--source/blender/modifiers/intern/MOD_wave.c24
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgedit.c21
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgmix.c21
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c27
-rw-r--r--source/blender/modifiers/intern/MOD_wireframe.c1
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_outputFile.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_light_path.c2
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h3
-rw-r--r--source/blender/render/intern/source/convertblender.c15
-rw-r--r--source/blender/render/intern/source/occlusion.c9
-rw-r--r--source/blender/render/intern/source/render_result.c6
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c3
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulator.c2
-rw-r--r--source/creator/creator_args.c16
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp2
m---------source/tools0
244 files changed, 5016 insertions, 8420 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 059f7309cf5..784c76bffd3 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -145,10 +145,6 @@ typedef DMDrawOption (*DMSetDrawOptions)(void *userData, int index);
typedef DMDrawOption (*DMSetDrawOptionsMappedTex)(void *userData, int origindex, int mat_nr);
typedef DMDrawOption (*DMSetDrawOptionsTex)(struct MTexPoly *mtexpoly, const bool has_vcol, int matnr);
-/* Cleanup callback type */
-typedef void (*DMCleanupBatchCache)(void *batchCache);
-void DM_set_batch_cleanup_callback(DMCleanupBatchCache);
-
typedef enum DMDrawFlag {
DM_DRAW_USE_COLORS = (1 << 0),
DM_DRAW_ALWAYS_SMOOTH = (1 << 1),
@@ -176,6 +172,8 @@ typedef enum DMDirtyFlag {
/* check this with modifier dependsOnNormals callback to see if normals need recalculation */
DM_DIRTY_NORMALS = 1 << 2,
+
+ DM_MESH_BATCH_CACHE = 1 << 3,
} DMDirtyFlag;
typedef struct DerivedMesh DerivedMesh;
@@ -187,7 +185,6 @@ struct DerivedMesh {
int deformedOnly; /* set by modifier stack if only deformed from original */
BVHCache *bvhCache;
struct GPUDrawObject *drawObject;
- void *batchCache;
DerivedMeshType type;
float auto_bump_scale;
DMDirtyFlag dirty;
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index 78d6f6c7cb9..c2323100205 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -97,7 +97,6 @@ void BKE_armature_where_is(struct bArmature *arm);
void BKE_armature_where_is_bone(struct Bone *bone, struct Bone *prevbone, const bool use_recursion);
void BKE_pose_clear_pointers(struct bPose *pose);
void BKE_pose_rebuild(struct Object *ob, struct bArmature *arm);
-void BKE_pose_rebuild_ex(struct Object *ob, struct bArmature *arm, const bool sort_bones);
void BKE_pose_where_is(struct Scene *scene, struct Object *ob);
void BKE_pose_where_is_bone(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime, bool do_extra);
void BKE_pose_where_is_bone_tail(struct bPoseChannel *pchan);
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
index 5f09ad9cde4..47f70012bdb 100644
--- a/source/blender/blenkernel/BKE_collection.h
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -39,6 +39,7 @@ struct Iterator;
struct SceneCollection;
struct Object;
struct ObjectBase;
+struct Main;
struct Scene;
struct SceneCollection *BKE_collection_add(struct Scene *scene, struct SceneCollection *sc_parent, const char *name);
@@ -46,8 +47,9 @@ bool BKE_collection_remove(struct Scene *scene, struct SceneCollection *sc);
struct SceneCollection *BKE_collection_master(struct Scene *scene);
void BKE_collection_master_free(struct Scene *scene);
void BKE_collection_object_add(struct Scene *scene, struct SceneCollection *sc, struct Object *object);
-void BKE_collection_object_remove(struct Scene *scene, struct SceneCollection *sc, struct Object *object);
-void BKE_collections_object_remove(struct Scene *scene, struct Object *object);
+void BKE_collection_object_add_from(struct Scene *scene, struct Object *ob_src, struct Object *ob_dst);
+void BKE_collection_object_remove(struct Main *bmain, struct Scene *scene, struct SceneCollection *sc, struct Object *object, const bool free_us);
+void BKE_collections_object_remove(struct Main *bmain, struct Scene *scene, struct Object *object, const bool free_us);
typedef void (*BKE_scene_objects_Cb)(struct Object *ob, void *data);
typedef void (*BKE_scene_collections_Cb)(struct SceneCollection *ob, void *data);
diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h
index 8756f73df72..3ce08a14177 100644
--- a/source/blender/blenkernel/BKE_deform.h
+++ b/source/blender/blenkernel/BKE_deform.h
@@ -116,13 +116,4 @@ void BKE_defvert_extract_vgroup_to_polyweights(
struct MDeformVert *dvert, const int defgroup, const int num_verts, struct MLoop *loops, const int num_loops,
struct MPoly *polys, const int num_polys, float *r_weights, const bool invert_vgroup);
-/* utility function, note that MAX_VGROUP_NAME chars is the maximum string length since its only
- * used with defgroups currently */
-
-void BKE_deform_split_suffix(const char string[MAX_VGROUP_NAME], char base[MAX_VGROUP_NAME], char ext[MAX_VGROUP_NAME]);
-void BKE_deform_split_prefix(const char string[MAX_VGROUP_NAME], char base[MAX_VGROUP_NAME], char ext[MAX_VGROUP_NAME]);
-
-void BKE_deform_flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[MAX_VGROUP_NAME],
- const bool strip_number);
-
#endif /* __BKE_DEFORM_H__ */
diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h
index 09a069ee36f..59dae4cf79f 100644
--- a/source/blender/blenkernel/BKE_group.h
+++ b/source/blender/blenkernel/BKE_group.h
@@ -34,6 +34,7 @@
*/
struct Base;
+struct ObjectBase;
struct EvaluationContext;
struct Group;
struct Main;
@@ -44,8 +45,8 @@ void BKE_group_free(struct Group *group);
struct Group *BKE_group_add(struct Main *bmain, const char *name);
struct Group *BKE_group_copy(struct Main *bmain, struct Group *group);
void BKE_group_make_local(struct Main *bmain, struct Group *group, const bool lib_local);
-bool BKE_group_object_add(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
-bool BKE_group_object_unlink(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
+bool BKE_group_object_add(struct Group *group, struct Object *ob);
+bool BKE_group_object_unlink(struct Group *group, struct Object *ob);
struct Group *BKE_group_object_find(struct Group *group, struct Object *ob);
bool BKE_group_object_exists(struct Group *group, struct Object *ob);
bool BKE_group_object_cyclic_check(struct Main *bmain, struct Object *object, struct Group *group);
diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h
index 1d62c31188e..0f328700bfb 100644
--- a/source/blender/blenkernel/BKE_layer.h
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -59,9 +59,11 @@ void BKE_scene_layer_engine_set(struct SceneLayer *sl, const char *engine);
void BKE_scene_layer_selected_objects_tag(struct SceneLayer *sl, const int tag);
+struct SceneLayer *BKE_scene_layer_find_from_collection(struct Scene *scene, struct LayerCollection *lc);
struct ObjectBase *BKE_scene_layer_base_find(struct SceneLayer *sl, struct Object *ob);
void BKE_scene_layer_base_deselect_all(struct SceneLayer *sl);
void BKE_scene_layer_base_select(struct SceneLayer *sl, struct ObjectBase *selbase);
+void BKE_scene_layer_base_flag_recalculate(struct SceneLayer *sl);
void BKE_layer_collection_free(struct SceneLayer *sl, struct LayerCollection *lc);
@@ -75,6 +77,9 @@ struct LayerCollection *BKE_collection_link(struct SceneLayer *sl, struct SceneC
void BKE_collection_unlink(struct SceneLayer *sl, struct LayerCollection *lc);
+bool BKE_scene_layer_has_collection(struct SceneLayer *sl, struct SceneCollection *sc);
+bool BKE_scene_has_object(struct Scene *scene, struct Object *ob);
+
/* syncing */
void BKE_layer_sync_new_scene_collection(struct Scene *scene, const struct SceneCollection *sc_parent, struct SceneCollection *sc);
@@ -91,6 +96,14 @@ void BKE_selected_objects_Iterator_begin(Iterator *iter, void *data_in);
void BKE_selected_objects_Iterator_next(Iterator *iter);
void BKE_selected_objects_Iterator_end(Iterator *iter);
+void BKE_visible_objects_Iterator_begin(Iterator *iter, void *data_in);
+void BKE_visible_objects_Iterator_next(Iterator *iter);
+void BKE_visible_objects_Iterator_end(Iterator *iter);
+
+void BKE_visible_bases_Iterator_begin(Iterator *iter, void *data_in);
+void BKE_visible_bases_Iterator_next(Iterator *iter);
+void BKE_visible_bases_Iterator_end(Iterator *iter);
+
#define FOREACH_SELECTED_OBJECT(sl, _ob) \
ITER_BEGIN(BKE_selected_objects_Iterator_begin, \
BKE_selected_objects_Iterator_next, \
@@ -100,6 +113,26 @@ void BKE_selected_objects_Iterator_end(Iterator *iter);
#define FOREACH_SELECTED_OBJECT_END \
ITER_END
+#define FOREACH_VISIBLE_OBJECT(sl, _ob) \
+ ITER_BEGIN(BKE_visible_objects_Iterator_begin, \
+ BKE_visible_objects_Iterator_next, \
+ BKE_visible_objects_Iterator_end, \
+ sl, _ob)
+
+#define FOREACH_VISIBLE_OBJECT_END \
+ ITER_END
+
+
+#define FOREACH_VISIBLE_BASE(sl, _object_base) \
+ ITER_BEGIN(BKE_visible_bases_Iterator_begin, \
+ BKE_visible_bases_Iterator_next, \
+ BKE_visible_bases_Iterator_end, \
+ sl, _object_base)
+
+#define FOREACH_VISIBLE_BASE_END \
+ ITER_END
+
+
#define FOREACH_OBJECT(sl, _ob) \
{ \
ObjectBase *base; \
diff --git a/source/blender/blenkernel/BKE_mesh_render.h b/source/blender/blenkernel/BKE_mesh_render.h
new file mode 100644
index 00000000000..8a2b3f9d9ec
--- /dev/null
+++ b/source/blender/blenkernel/BKE_mesh_render.h
@@ -0,0 +1,42 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2017 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, Mike Erwin, Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __BKE_MESH_RENDER_H__
+#define __BKE_MESH_RENDER_H__
+
+/** \file BKE_mesh_render.h
+ * \ingroup bke
+ */
+
+struct Batch;
+struct Mesh;
+
+void BKE_mesh_batch_cache_free(struct Mesh *me);
+struct Batch *BKE_mesh_batch_cache_get_all_edges(struct Mesh *me);
+struct Batch *BKE_mesh_batch_cache_get_all_triangles(struct Mesh *me);
+struct Batch *BKE_mesh_batch_cache_get_all_verts(struct Mesh *me);
+struct Batch *BKE_mesh_batch_cache_get_fancy_edges(struct Mesh *me);
+struct Batch *BKE_mesh_batch_cache_get_overlay_edges(struct Mesh *me);
+
+#endif /* __BKE_MESH_RENDER_H__ */
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index f6c08909d23..92b186d7329 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -260,20 +260,11 @@ typedef struct ModifierTypeInfo {
*/
bool (*isDisabled)(struct ModifierData *md, int userRenderParams);
- /* Add the appropriate relations to the DEP graph depending on the
- * modifier data.
- *
- * This function is optional.
- */
- void (*updateDepgraph)(struct ModifierData *md, struct DagForest *forest,
- struct Main *bmain, struct Scene *scene,
- struct Object *ob, struct DagNode *obNode);
-
/* Add the appropriate relations to the dependency graph.
*
* This function is optional.
*/
- /* TODO(sergey): Remove once we finalyl switched to the new depsgraph. */
+ /* TODO(sergey): Remove once we finally switched to the new depsgraph. */
void (*updateDepsgraph)(struct ModifierData *md,
struct Main *bmain,
struct Scene *scene,
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 61413e0536d..d1e7e2e5e45 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -260,7 +260,7 @@ typedef enum eObjectSet {
struct LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter);
struct LinkNode *BKE_object_groups(struct Object *ob);
-void BKE_object_groups_clear(struct Scene *scene, struct Base *base, struct Object *object);
+void BKE_object_groups_clear(struct Object *object);
struct KDTree *BKE_object_as_kdtree(struct Object *ob, int *r_tot);
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index fc3dde2ffb1..21e6e795142 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -42,6 +42,7 @@ struct Base;
struct EvaluationContext;
struct Main;
struct Object;
+struct ObjectBase;
struct QuicktimeCodecData;
struct RenderData;
struct SceneRenderLayer;
@@ -96,6 +97,10 @@ int BKE_scene_base_iter_next(struct EvaluationContext *eval_ctx, struct SceneBas
void BKE_scene_base_flag_to_objects(struct Scene *scene);
void BKE_scene_base_flag_from_objects(struct Scene *scene);
+void BKE_scene_base_flag_sync_from_base(struct Base *base);
+void BKE_scene_base_flag_sync_from_object(struct Base *base);
+void BKE_scene_object_base_flag_sync_from_base(struct ObjectBase *base);
+void BKE_scene_object_base_flag_sync_from_object(struct ObjectBase *base);
void BKE_scene_set_background(struct Main *bmain, struct Scene *sce);
struct Scene *BKE_scene_set_name(struct Main *bmain, const char *name);
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index fcdaa33acfc..6202c84f320 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -134,6 +134,7 @@ set(SRC
intern/mesh_evaluate.c
intern/mesh_mapping.c
intern/mesh_remap.c
+ intern/mesh_render.c
intern/mesh_validate.c
intern/modifier.c
intern/modifiers_bmesh.c
@@ -260,6 +261,7 @@ set(SRC
BKE_mesh.h
BKE_mesh_mapping.h
BKE_mesh_remap.h
+ BKE_mesh_render.h
BKE_modifier.h
BKE_movieclip.h
BKE_multires.h
@@ -539,8 +541,4 @@ endif()
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX")
#endif()
-if(WITH_LEGACY_DEPSGRAPH)
- add_definitions(-DWITH_LEGACY_DEPSGRAPH)
-endif()
-
blender_add_lib(bf_blenkernel "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index fb0087aefac..e0bbe345fc4 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -260,12 +260,6 @@ static CustomData *dm_getPolyCData(DerivedMesh *dm)
return &dm->polyData;
}
-static DMCleanupBatchCache cleanupBatchCache = NULL;
-void DM_set_batch_cleanup_callback(DMCleanupBatchCache func)
-{
- cleanupBatchCache = func;
-}
-
/**
* Utility function to initialize a DerivedMesh's function pointers to
* the default implementation (for those functions which have a default)
@@ -324,8 +318,6 @@ void DM_init(
DM_init_funcs(dm);
- dm->batchCache = NULL; /* necessary? dm->drawObject is not set to NULL yet it works fine */
-
dm->needsFree = 1;
dm->auto_bump_scale = -1.0f;
dm->dirty = 0;
@@ -385,10 +377,7 @@ int DM_release(DerivedMesh *dm)
if (dm->needsFree) {
bvhcache_free(&dm->bvhCache);
GPU_drawobject_free(dm);
- if (dm->batchCache && cleanupBatchCache) {
- cleanupBatchCache(dm->batchCache);
- dm->batchCache = NULL;
- }
+
CustomData_free(&dm->vertData, dm->numVertData);
CustomData_free(&dm->edgeData, dm->numEdgeData);
CustomData_free(&dm->faceData, dm->numTessFaceData);
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index dcbb667adca..1e33fe4ab46 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -44,6 +44,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
@@ -494,7 +495,7 @@ bPoseChannel *BKE_pose_channel_get_mirrored(const bPose *pose, const char *name)
{
char name_flip[MAXBONENAME];
- BKE_deform_flip_side_name(name_flip, name, false);
+ BLI_string_flip_side_name(name_flip, name, false, sizeof(name_flip));
if (!STREQ(name_flip, name)) {
return BKE_pose_channel_find_name(pose, name_flip);
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index 7d3d12ac112..2f65e71c6d2 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -201,7 +201,15 @@ bMotionPath *animviz_verify_motionpaths(ReportList *reports, Scene *scene, Objec
mpath->flag |= MOTIONPATH_FLAG_BHEAD;
else
mpath->flag &= ~MOTIONPATH_FLAG_BHEAD;
-
+
+ /* set default custom values */
+ mpath->color[0] = 1.0; /* Red */
+ mpath->color[1] = 0.0;
+ mpath->color[2] = 0.0;
+
+ mpath->line_thickness = 1;
+ mpath->flag |= MOTIONPATH_FLAG_LINES; /* draw lines by default */
+
/* allocate a cache */
mpath->points = MEM_callocN(sizeof(bMotionPathVert) * mpath->length, "bMotionPathVerts");
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 21279392392..0b637355ecf 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -43,6 +43,7 @@
#include "BLI_alloca.h"
#include "BLI_dynstr.h"
#include "BLI_listbase.h"
+#include "BLI_string_utils.h"
#include "BLT_translation.h"
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 2b333941c6e..89e93a6384d 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -87,6 +87,7 @@ bArmature *BKE_armature_add(Main *bmain, const char *name)
arm->deformflag = ARM_DEF_VGROUP | ARM_DEF_ENVELOPE;
arm->flag = ARM_COL_CUSTOM; /* custom bone-group colors */
arm->layer = 1;
+ arm->ghostsize = 1;
return arm;
}
@@ -1917,7 +1918,7 @@ void BKE_pose_clear_pointers(bPose *pose)
/* only after leave editmode, duplicating, validating older files, library syncing */
/* NOTE: pose->flag is set for it */
-void BKE_pose_rebuild_ex(Object *ob, bArmature *arm, const bool sort_bones)
+void BKE_pose_rebuild(Object *ob, bArmature *arm)
{
Bone *bone;
bPose *pose;
@@ -1961,25 +1962,12 @@ void BKE_pose_rebuild_ex(Object *ob, bArmature *arm, const bool sort_bones)
BKE_pose_update_constraint_flags(ob->pose); /* for IK detection for example */
-#ifdef WITH_LEGACY_DEPSGRAPH
- /* the sorting */
- /* Sorting for new dependnecy graph is done on the scene graph level. */
- if (counter > 1 && sort_bones) {
- DAG_pose_sort(ob);
- }
-#endif
-
ob->pose->flag &= ~POSE_RECALC;
ob->pose->flag |= POSE_WAS_REBUILT;
BKE_pose_channels_hash_make(ob->pose);
}
-void BKE_pose_rebuild(Object *ob, bArmature *arm)
-{
- BKE_pose_rebuild_ex(ob, arm, true);
-}
-
/* ********************** THE POSE SOLVER ******************* */
/* loc/rot/size to given mat4 */
diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c
index 3bc81a69c86..a8ab1e9357b 100644
--- a/source/blender/blenkernel/intern/armature_update.c
+++ b/source/blender/blenkernel/intern/armature_update.c
@@ -53,11 +53,7 @@
#include "DEG_depsgraph.h"
-#ifdef WITH_LEGACY_DEPSGRAPH
-# define DEBUG_PRINT if (!DEG_depsgraph_use_legacy() && G.debug & G_DEBUG_DEPSGRAPH) printf
-#else
-# define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
-#endif
+#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
/* ********************** SPLINE IK SOLVER ******************* */
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index d88d3fe5b03..c7ff70e4047 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -29,10 +29,12 @@
#include "BLI_iterator.h"
#include "BLI_listbase.h"
#include "BLT_translation.h"
+#include "BLI_string_utils.h"
#include "BKE_collection.h"
#include "BKE_layer.h"
#include "BKE_library.h"
+#include "BKE_main.h"
#include "BKE_scene.h"
#include "DNA_ID.h"
@@ -154,6 +156,7 @@ bool BKE_collection_remove(Scene *scene, SceneCollection *sc)
/* check all layers that use this collection and clear them */
for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
layer_collection_remove(sl, &sl->layer_collections, sc);
+ BKE_scene_layer_base_flag_recalculate(sl);
sl->active_collection = 0;
}
@@ -177,25 +180,45 @@ void BKE_collection_master_free(Scene *scene){
collection_free(BKE_collection_master(scene));
}
+static void collection_object_add(Scene *scene, SceneCollection *sc, Object *ob)
+{
+ BLI_addtail(&sc->objects, BLI_genericNodeN(ob));
+ id_us_plus((ID *)ob);
+ BKE_layer_sync_object_link(scene, sc, ob);
+}
+
/**
* Add object to collection
*/
-void BKE_collection_object_add(struct Scene *scene, struct SceneCollection *sc, struct Object *ob)
+void BKE_collection_object_add(Scene *scene, SceneCollection *sc, Object *ob)
{
if (BLI_findptr(&sc->objects, ob, offsetof(LinkData, data))) {
/* don't add the same object twice */
return;
}
+ collection_object_add(scene, sc, ob);
+}
- BLI_addtail(&sc->objects, BLI_genericNodeN(ob));
- id_us_plus((ID *)ob);
- BKE_layer_sync_object_link(scene, sc, ob);
+/**
+ * Add object to all collections that reference objects is in
+ * (used to copy objects)
+ */
+void BKE_collection_object_add_from(Scene *scene, Object *ob_src, Object *ob_dst)
+{
+ SceneCollection *sc;
+ FOREACH_SCENE_COLLECTION(scene, sc)
+ {
+ if (BLI_findptr(&sc->objects, ob_src, offsetof(LinkData, data))) {
+ collection_object_add(scene, sc, ob_dst);
+ }
+ }
+ FOREACH_SCENE_COLLECTION_END
}
/**
* Remove object from collection
*/
-void BKE_collection_object_remove(struct Scene *scene, struct SceneCollection *sc, struct Object *ob)
+void BKE_collection_object_remove(Main *bmain, Scene *scene, SceneCollection *sc, Object *ob, const bool free_us)
{
LinkData *link = BLI_findptr(&sc->objects, ob, offsetof(LinkData, data));
@@ -207,23 +230,28 @@ void BKE_collection_object_remove(struct Scene *scene, struct SceneCollection *s
BLI_remlink(&sc->objects, link);
MEM_freeN(link);
- id_us_min((ID *)ob);
-
TODO_LAYER_SYNC_FILTER; /* need to remove all instances of ob in scene collections -> filter_objects */
BKE_layer_sync_object_unlink(scene, sc, ob);
+
+ if (free_us) {
+ BKE_libblock_free_us(bmain, ob);
+ }
+ else {
+ id_us_min(&ob->id);
+ }
}
/**
* Remove object from all collections of scene
*/
-void BKE_collections_object_remove(Scene *scene, Object *ob)
+void BKE_collections_object_remove(Main *bmain, Scene *scene, Object *ob, const bool free_us)
{
BKE_scene_remove_rigidbody_object(scene, ob);
SceneCollection *sc;
FOREACH_SCENE_COLLECTION(scene, sc)
{
- BKE_collection_object_remove(scene, sc, ob);
+ BKE_collection_object_remove(bmain, scene, sc, ob, free_us);
}
FOREACH_SCENE_COLLECTION_END
}
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index 18ca1407ba0..ee25be36855 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -1014,7 +1014,7 @@ static bool cloth_points_collision_response_static(ClothModifierData *clmd, Coll
}
BLI_INLINE bool cloth_point_face_collision_params(const float p1[3], const float p2[3], const float v0[3], const float v1[3], const float v2[3],
- float r_nor[3], float *r_lambda, float r_w[4])
+ float r_nor[3], float *r_lambda, float r_w[3])
{
float edge1[3], edge2[3], p2face[3], p1p2[3], v0p2[3];
float nor_v0p2, nor_p1p2;
@@ -1026,7 +1026,7 @@ BLI_INLINE bool cloth_point_face_collision_params(const float p1[3], const float
nor_v0p2 = dot_v3v3(v0p2, r_nor);
madd_v3_v3v3fl(p2face, p2, r_nor, -nor_v0p2);
- interp_weights_face_v3(r_w, v0, v1, v2, NULL, p2face);
+ interp_weights_tri_v3(r_w, v0, v1, v2, p2face);
sub_v3_v3v3(p1p2, p2, p1);
sub_v3_v3v3(v0p2, p2, v0);
@@ -1085,7 +1085,7 @@ static CollPair *cloth_point_collpair(
const float *co1 = mverts[bp1].co, *co2 = mverts[bp2].co, *co3 = mverts[bp3].co;
float lambda /*, distance1 */, distance2;
float facenor[3], v1p1[3], v1p2[3];
- float w[4];
+ float w[3];
if (!cloth_point_face_collision_params(p1, p2, co1, co2, co3, facenor, &lambda, w))
return collpair;
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index cb74dbcd8d1..58ad171ee20 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -42,7 +42,7 @@
#include "BLI_math.h"
#include "BLI_kdopbvh.h"
#include "BLI_utildefines.h"
-
+#include "BLI_string_utils.h"
#include "BLT_translation.h"
#include "DNA_armature_types.h"
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 9beeeac6287..592adfc578a 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -912,12 +912,27 @@ SceneLayer *CTX_data_scene_layer(const bContext *C)
}
}
+/**
+ * This is tricky. Sometimes the user overrides the render_layer
+ * but not the scene_collection. In this case what to do?
+ *
+ * If the scene_collection is linked to the SceneLayer we use it.
+ * Otherwise we fallback to the active one of the SceneLayer.
+ */
SceneCollection *CTX_data_scene_collection(const bContext *C)
{
+ SceneLayer *sl = CTX_data_scene_layer(C);
SceneCollection *sc;
if (ctx_data_pointer_verify(C, "scene_collection", (void *)&sc)) {
- return sc;
+ if (BKE_scene_layer_has_collection(sl, sc)) {
+ return sc;
+ }
+ else {
+ /* fallback */
+ LayerCollection *lc = BKE_layer_collection_active(sl);
+ return lc->scene_collection;
+ }
}
else {
return C->data.scene_collection;
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 612f1f477e1..98d37fb07bf 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -45,8 +45,9 @@
#include "DNA_ID.h"
#include "BLI_utildefines.h"
-#include "BLI_string.h"
#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "BLI_string_utils.h"
#include "BLI_math.h"
#include "BLI_math_color_blend.h"
#include "BLI_mempool.h"
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index 7052e0a7d25..13b1aab5e1c 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -45,8 +45,8 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BLI_path_util.h"
#include "BLI_string.h"
+#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -509,7 +509,7 @@ int *defgroup_flip_map(Object *ob, int *flip_map_len, const bool use_default)
if (use_default)
map[i] = i;
- BKE_deform_flip_side_name(name_flip, dg->name, false);
+ BLI_string_flip_side_name(name_flip, dg->name, false, sizeof(name_flip));
if (!STREQ(name_flip, dg->name)) {
flip_num = defgroup_name_index(ob, name_flip);
@@ -545,7 +545,7 @@ int *defgroup_flip_map_single(Object *ob, int *flip_map_len, const bool use_defa
dg = BLI_findlink(&ob->defbase, defgroup);
- BKE_deform_flip_side_name(name_flip, dg->name, false);
+ BLI_string_flip_side_name(name_flip, dg->name, false, sizeof(name_flip));
if (!STREQ(name_flip, dg->name)) {
flip_num = defgroup_name_index(ob, name_flip);
@@ -566,7 +566,7 @@ int defgroup_flip_index(Object *ob, int index, const bool use_default)
if (dg) {
char name_flip[sizeof(dg->name)];
- BKE_deform_flip_side_name(name_flip, dg->name, false);
+ BLI_string_flip_side_name(name_flip, dg->name, false, sizeof(name_flip));
if (!STREQ(name_flip, dg->name)) {
flip_index = defgroup_name_index(ob, name_flip);
@@ -606,185 +606,6 @@ void defgroup_unique_name(bDeformGroup *dg, Object *ob)
BLI_uniquename_cb(defgroup_unique_check, &data, DATA_("Group"), '.', dg->name, sizeof(dg->name));
}
-static bool is_char_sep(const char c)
-{
- return ELEM(c, '.', ' ', '-', '_');
-}
-
-/**
- * based on `BLI_split_dirfile()` / `os.path.splitext()`,
- * `"a.b.c"` -> (`"a.b"`, `".c"`).
- */
-void BKE_deform_split_suffix(const char string[MAX_VGROUP_NAME], char body[MAX_VGROUP_NAME], char suf[MAX_VGROUP_NAME])
-{
- size_t len = BLI_strnlen(string, MAX_VGROUP_NAME);
- size_t i;
-
- body[0] = suf[0] = '\0';
-
- for (i = len; i > 0; i--) {
- if (is_char_sep(string[i])) {
- BLI_strncpy(body, string, i + 1);
- BLI_strncpy(suf, string + i, (len + 1) - i);
- return;
- }
- }
-
- memcpy(body, string, len + 1);
-}
-
-/**
- * `"a.b.c"` -> (`"a."`, `"b.c"`)
- */
-void BKE_deform_split_prefix(const char string[MAX_VGROUP_NAME], char pre[MAX_VGROUP_NAME], char body[MAX_VGROUP_NAME])
-{
- size_t len = BLI_strnlen(string, MAX_VGROUP_NAME);
- size_t i;
-
- body[0] = pre[0] = '\0';
-
- for (i = 1; i < len; i++) {
- if (is_char_sep(string[i])) {
- i++;
- BLI_strncpy(pre, string, i + 1);
- BLI_strncpy(body, string + i, (len + 1) - i);
- return;
- }
- }
-
- BLI_strncpy(body, string, len);
-}
-
-/**
- * Finds the best possible flipped name. For renaming; check for unique names afterwards.
- *
- * if strip_number: removes number extensions
- *
- * \note don't use sizeof() for 'name' or 'from_name'.
- */
-void BKE_deform_flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[MAX_VGROUP_NAME],
- const bool strip_number)
-{
- int len;
- char prefix[MAX_VGROUP_NAME] = ""; /* The part before the facing */
- char suffix[MAX_VGROUP_NAME] = ""; /* The part after the facing */
- char replace[MAX_VGROUP_NAME] = ""; /* The replacement string */
- char number[MAX_VGROUP_NAME] = ""; /* The number extension string */
- char *index = NULL;
- bool is_set = false;
-
- /* always copy the name, since this can be called with an uninitialized string */
- BLI_strncpy(name, from_name, MAX_VGROUP_NAME);
-
- len = BLI_strnlen(from_name, MAX_VGROUP_NAME);
- if (len < 3) {
- /* we don't do names like .R or .L */
- return;
- }
-
- /* We first check the case with a .### extension, let's find the last period */
- if (isdigit(name[len - 1])) {
- index = strrchr(name, '.'); // last occurrence
- if (index && isdigit(index[1])) { // doesnt handle case bone.1abc2 correct..., whatever!
- if (strip_number == false) {
- BLI_strncpy(number, index, sizeof(number));
- }
- *index = 0;
- len = BLI_strnlen(name, MAX_VGROUP_NAME);
- }
- }
-
- BLI_strncpy(prefix, name, sizeof(prefix));
-
- /* first case; separator . - _ with extensions r R l L */
- if ((len > 1) && is_char_sep(name[len - 2])) {
- is_set = true;
- switch (name[len - 1]) {
- case 'l':
- prefix[len - 1] = 0;
- strcpy(replace, "r");
- break;
- case 'r':
- prefix[len - 1] = 0;
- strcpy(replace, "l");
- break;
- case 'L':
- prefix[len - 1] = 0;
- strcpy(replace, "R");
- break;
- case 'R':
- prefix[len - 1] = 0;
- strcpy(replace, "L");
- break;
- default:
- is_set = false;
- }
- }
-
- /* case; beginning with r R l L, with separator after it */
- if (!is_set && is_char_sep(name[1])) {
- is_set = true;
- switch (name[0]) {
- case 'l':
- strcpy(replace, "r");
- BLI_strncpy(suffix, name + 1, sizeof(suffix));
- prefix[0] = 0;
- break;
- case 'r':
- strcpy(replace, "l");
- BLI_strncpy(suffix, name + 1, sizeof(suffix));
- prefix[0] = 0;
- break;
- case 'L':
- strcpy(replace, "R");
- BLI_strncpy(suffix, name + 1, sizeof(suffix));
- prefix[0] = 0;
- break;
- case 'R':
- strcpy(replace, "L");
- BLI_strncpy(suffix, name + 1, sizeof(suffix));
- prefix[0] = 0;
- break;
- default:
- is_set = false;
- }
- }
-
- if (!is_set && len > 5) {
- /* hrms, why test for a separator? lets do the rule 'ultimate left or right' */
- if (((index = BLI_strcasestr(prefix, "right")) == prefix) ||
- (index == prefix + len - 5))
- {
- is_set = true;
- if (index[0] == 'r') {
- strcpy(replace, "left");
- }
- else {
- strcpy(replace, (index[1] == 'I') ? "LEFT" : "Left");
- }
- *index = 0;
- BLI_strncpy(suffix, index + 5, sizeof(suffix));
- }
- else if (((index = BLI_strcasestr(prefix, "left")) == prefix) ||
- (index == prefix + len - 4))
- {
- is_set = true;
- if (index[0] == 'l') {
- strcpy(replace, "right");
- }
- else {
- strcpy(replace, (index[1] == 'E') ? "RIGHT" : "Right");
- }
- *index = 0;
- BLI_strncpy(suffix, index + 4, sizeof(suffix));
- }
- }
-
- (void)is_set; /* quiet warning */
-
- BLI_snprintf(name, MAX_VGROUP_NAME, "%s%s%s%s", prefix, replace, suffix, number);
-}
-
float defvert_find_weight(const struct MDeformVert *dvert, const int defgroup)
{
MDeformWeight *dw = defvert_find_index(dvert, defgroup);
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index a8341939692..c5b8a18fd65 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -40,56 +40,12 @@
#endif
#include "BLI_utildefines.h"
-#include "BLI_listbase.h"
-#include "BLI_ghash.h"
-#include "BLI_threads.h"
-#include "DNA_anim_types.h"
-#include "DNA_camera_types.h"
-#include "DNA_cachefile_types.h"
-#include "DNA_group_types.h"
-#include "DNA_lamp_types.h"
-#include "DNA_lattice_types.h"
-#include "DNA_key_types.h"
-#include "DNA_material_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_node_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_windowmanager_types.h"
-#include "DNA_movieclip_types.h"
-#include "DNA_mask_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_rigidbody_types.h"
-#include "BKE_anim.h"
-#include "BKE_animsys.h"
-#include "BKE_action.h"
-#include "BKE_DerivedMesh.h"
-#include "BKE_collision.h"
-#include "BKE_effect.h"
-#include "BKE_fcurve.h"
#include "BKE_global.h"
-#include "BKE_idcode.h"
-#include "BKE_image.h"
-#include "BKE_key.h"
-#include "BKE_library.h"
#include "BKE_main.h"
-#include "BKE_node.h"
-#include "BKE_material.h"
-#include "BKE_mball.h"
-#include "BKE_modifier.h"
-#include "BKE_object.h"
-#include "BKE_paint.h"
-#include "BKE_particle.h"
-#include "BKE_pointcache.h"
-#include "BKE_scene.h"
-#include "BKE_screen.h"
-#include "BKE_tracking.h"
-
-#include "GPU_buffers.h"
-
-#include "atomic_ops.h"
#include "depsgraph_private.h"
@@ -98,3310 +54,6 @@
#include "DEG_depsgraph_debug.h"
#include "DEG_depsgraph_query.h"
-#ifdef WITH_LEGACY_DEPSGRAPH
-
-static SpinLock threaded_update_lock;
-
-void DAG_init(void)
-{
- BLI_spin_init(&threaded_update_lock);
- DEG_register_node_types();
-}
-
-void DAG_exit(void)
-{
- BLI_spin_end(&threaded_update_lock);
- DEG_free_node_types();
-}
-
-/* Queue and stack operations for dag traversal
- *
- * the queue store a list of freenodes to avoid successive alloc/dealloc
- */
-
-DagNodeQueue *queue_create(int slots)
-{
- DagNodeQueue *queue;
- DagNodeQueueElem *elem;
- int i;
-
- queue = MEM_mallocN(sizeof(DagNodeQueue), "DAG queue");
- queue->freenodes = MEM_mallocN(sizeof(DagNodeQueue), "DAG queue");
- queue->count = 0;
- queue->maxlevel = 0;
- queue->first = queue->last = NULL;
- elem = MEM_mallocN(sizeof(DagNodeQueueElem), "DAG queue elem3");
- elem->node = NULL;
- elem->next = NULL;
- queue->freenodes->first = queue->freenodes->last = elem;
-
- for (i = 1; i < slots; i++) {
- elem = MEM_mallocN(sizeof(DagNodeQueueElem), "DAG queue elem4");
- elem->node = NULL;
- elem->next = NULL;
- queue->freenodes->last->next = elem;
- queue->freenodes->last = elem;
- }
- queue->freenodes->count = slots;
- return queue;
-}
-
-void queue_raz(DagNodeQueue *queue)
-{
- DagNodeQueueElem *elem;
-
- elem = queue->first;
- if (queue->freenodes->last)
- queue->freenodes->last->next = elem;
- else
- queue->freenodes->first = queue->freenodes->last = elem;
-
- elem->node = NULL;
- queue->freenodes->count++;
- while (elem->next) {
- elem = elem->next;
- elem->node = NULL;
- queue->freenodes->count++;
- }
- queue->freenodes->last = elem;
- queue->count = 0;
-}
-
-void queue_delete(DagNodeQueue *queue)
-{
- DagNodeQueueElem *elem;
- DagNodeQueueElem *temp;
-
- elem = queue->first;
- while (elem) {
- temp = elem;
- elem = elem->next;
- MEM_freeN(temp);
- }
-
- elem = queue->freenodes->first;
- while (elem) {
- temp = elem;
- elem = elem->next;
- MEM_freeN(temp);
- }
-
- MEM_freeN(queue->freenodes);
- MEM_freeN(queue);
-}
-
-/* insert in queue, remove in front */
-void push_queue(DagNodeQueue *queue, DagNode *node)
-{
- DagNodeQueueElem *elem;
- int i;
-
- if (node == NULL) {
- fprintf(stderr, "pushing null node\n");
- return;
- }
- /*fprintf(stderr, "BFS push : %s %d\n", ((ID *) node->ob)->name, queue->count);*/
-
- elem = queue->freenodes->first;
- if (elem != NULL) {
- queue->freenodes->first = elem->next;
- if (queue->freenodes->last == elem) {
- queue->freenodes->last = NULL;
- queue->freenodes->first = NULL;
- }
- queue->freenodes->count--;
- }
- else { /* alllocating more */
- elem = MEM_mallocN(sizeof(DagNodeQueueElem), "DAG queue elem1");
- elem->node = NULL;
- elem->next = NULL;
- queue->freenodes->first = queue->freenodes->last = elem;
-
- for (i = 1; i < DAGQUEUEALLOC; i++) {
- elem = MEM_mallocN(sizeof(DagNodeQueueElem), "DAG queue elem2");
- elem->node = NULL;
- elem->next = NULL;
- queue->freenodes->last->next = elem;
- queue->freenodes->last = elem;
- }
- queue->freenodes->count = DAGQUEUEALLOC;
-
- elem = queue->freenodes->first;
- queue->freenodes->first = elem->next;
- }
- elem->next = NULL;
- elem->node = node;
- if (queue->last != NULL)
- queue->last->next = elem;
- queue->last = elem;
- if (queue->first == NULL) {
- queue->first = elem;
- }
- queue->count++;
-}
-
-
-/* insert in front, remove in front */
-void push_stack(DagNodeQueue *queue, DagNode *node)
-{
- DagNodeQueueElem *elem;
- int i;
-
- elem = queue->freenodes->first;
- if (elem != NULL) {
- queue->freenodes->first = elem->next;
- if (queue->freenodes->last == elem) {
- queue->freenodes->last = NULL;
- queue->freenodes->first = NULL;
- }
- queue->freenodes->count--;
- }
- else { /* alllocating more */
- elem = MEM_mallocN(sizeof(DagNodeQueueElem), "DAG queue elem1");
- elem->node = NULL;
- elem->next = NULL;
- queue->freenodes->first = queue->freenodes->last = elem;
-
- for (i = 1; i < DAGQUEUEALLOC; i++) {
- elem = MEM_mallocN(sizeof(DagNodeQueueElem), "DAG queue elem2");
- elem->node = NULL;
- elem->next = NULL;
- queue->freenodes->last->next = elem;
- queue->freenodes->last = elem;
- }
- queue->freenodes->count = DAGQUEUEALLOC;
-
- elem = queue->freenodes->first;
- queue->freenodes->first = elem->next;
- }
- elem->next = queue->first;
- elem->node = node;
- queue->first = elem;
- if (queue->last == NULL)
- queue->last = elem;
- queue->count++;
-}
-
-
-DagNode *pop_queue(DagNodeQueue *queue)
-{
- DagNodeQueueElem *elem;
- DagNode *node;
-
- elem = queue->first;
- if (elem) {
- queue->first = elem->next;
- if (queue->last == elem) {
- queue->last = NULL;
- queue->first = NULL;
- }
- queue->count--;
- if (queue->freenodes->last)
- queue->freenodes->last->next = elem;
- queue->freenodes->last = elem;
- if (queue->freenodes->first == NULL)
- queue->freenodes->first = elem;
- node = elem->node;
- elem->node = NULL;
- elem->next = NULL;
- queue->freenodes->count++;
- return node;
- }
- else {
- fprintf(stderr, "return null\n");
- return NULL;
- }
-}
-
-DagNode *get_top_node_queue(DagNodeQueue *queue)
-{
- return queue->first->node;
-}
-
-DagForest *dag_init(void)
-{
- DagForest *forest;
- /* use callocN to init all zero */
- forest = MEM_callocN(sizeof(DagForest), "DAG root");
- forest->ugly_hack_sorry = true;
- return forest;
-}
-
-/* isdata = object data... */
-/* XXX this needs to be extended to be more flexible (so that not only objects are evaluated via depsgraph)... */
-static void dag_add_driver_relation(AnimData *adt, DagForest *dag, DagNode *node, int isdata)
-{
- FCurve *fcu;
- DagNode *node1;
-
- for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
- ChannelDriver *driver = fcu->driver;
- DriverVar *dvar;
- int isdata_fcu = (isdata) || (fcu->rna_path && strstr(fcu->rna_path, "modifiers["));
-
- /* loop over variables to get the target relationships */
- for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
- /* only used targets */
- DRIVER_TARGETS_USED_LOOPER(dvar)
- {
- if (dtar->id) {
- /* FIXME: other data types need to be added here so that they can work! */
- if (GS(dtar->id->name) == ID_OB) {
- Object *ob = (Object *)dtar->id;
-
- /* normal channel-drives-channel */
- node1 = dag_get_node(dag, dtar->id);
-
- /* check if bone... */
- if ((ob->type == OB_ARMATURE) &&
- ( ((dtar->rna_path) && strstr(dtar->rna_path, "pose.bones[")) ||
- ((dtar->flag & DTAR_FLAG_STRUCT_REF) && (dtar->pchan_name[0])) ))
- {
- dag_add_relation(dag, node1, node, isdata_fcu ? DAG_RL_DATA_DATA : DAG_RL_DATA_OB, "Driver");
- }
- /* check if ob data */
- else if (dtar->rna_path && strstr(dtar->rna_path, "data."))
- dag_add_relation(dag, node1, node, isdata_fcu ? DAG_RL_DATA_DATA : DAG_RL_DATA_OB, "Driver");
- /* normal */
- else
- dag_add_relation(dag, node1, node, isdata_fcu ? DAG_RL_OB_DATA : DAG_RL_OB_OB, "Driver");
- }
- }
- }
- DRIVER_TARGETS_LOOPER_END
- }
- }
-}
-
-/* XXX: forward def for material driver handling... */
-static void dag_add_material_driver_relations(DagForest *dag, DagNode *node, Material *ma);
-
-/* recursive handling for shader nodetree drivers */
-static void dag_add_shader_nodetree_driver_relations(DagForest *dag, DagNode *node, bNodeTree *ntree)
-{
- bNode *n;
-
- /* nodetree itself */
- if (ntree->adt) {
- dag_add_driver_relation(ntree->adt, dag, node, 1);
- }
-
- /* nodetree's nodes... */
- for (n = ntree->nodes.first; n; n = n->next) {
- if (n->id) {
- if (GS(n->id->name) == ID_MA) {
- dag_add_material_driver_relations(dag, node, (Material *)n->id);
- }
- else if (n->type == NODE_GROUP) {
- dag_add_shader_nodetree_driver_relations(dag, node, (bNodeTree *)n->id);
- }
- }
- }
-}
-
-/* recursive handling for material drivers */
-static void dag_add_material_driver_relations(DagForest *dag, DagNode *node, Material *ma)
-{
- /* Prevent infinite recursion by checking (and tagging the material) as having been visited
- * already (see build_dag()). This assumes ma->id.tag & LIB_TAG_DOIT isn't set by anything else
- * in the meantime... [#32017]
- */
- if (ma->id.tag & LIB_TAG_DOIT)
- return;
-
- ma->id.tag |= LIB_TAG_DOIT;
-
- /* material itself */
- if (ma->adt)
- dag_add_driver_relation(ma->adt, dag, node, 1);
-
- /* textures */
- // TODO...
- //dag_add_texture_driver_relations(DagForest *dag, DagNode *node, ID *id);
-
- /* material's nodetree */
- if (ma->nodetree)
- dag_add_shader_nodetree_driver_relations(dag, node, ma->nodetree);
-
- ma->id.tag &= ~LIB_TAG_DOIT;
-}
-
-/* recursive handling for lamp drivers */
-static void dag_add_lamp_driver_relations(DagForest *dag, DagNode *node, Lamp *la)
-{
- /* Prevent infinite recursion by checking (and tagging the lamp) as having been visited
- * already (see build_dag()). This assumes la->id.tag & LIB_TAG_DOIT isn't set by anything else
- * in the meantime... [#32017]
- */
- if (la->id.tag & LIB_TAG_DOIT)
- return;
-
- la->id.tag |= LIB_TAG_DOIT;
-
- /* lamp itself */
- if (la->adt)
- dag_add_driver_relation(la->adt, dag, node, 1);
-
- /* textures */
- // TODO...
- //dag_add_texture_driver_relations(DagForest *dag, DagNode *node, ID *id);
-
- /* lamp's nodetree */
- if (la->nodetree)
- dag_add_shader_nodetree_driver_relations(dag, node, la->nodetree);
-
- la->id.tag &= ~LIB_TAG_DOIT;
-}
-
-static void create_collision_relation(DagForest *dag, DagNode *node, Object *ob1, const char *name)
-{
- DagNode *node2 = dag_get_node(dag, ob1);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, name);
-}
-
-void dag_add_collision_relations(DagForest *dag, Scene *scene, Object *ob, DagNode *node, Group *group, int layer, unsigned int modifier_type, DagCollobjFilterFunction fn, bool dupli, const char *name)
-{
- unsigned int numcollobj;
- Object **collobjs = get_collisionobjects_ext(scene, ob, group, layer, &numcollobj, modifier_type, dupli);
-
- for (unsigned int i = 0; i < numcollobj; i++) {
- Object *ob1 = collobjs[i];
-
- if (!fn || fn(ob1, modifiers_findByType(ob1, modifier_type))) {
- create_collision_relation(dag, node, ob1, name);
- }
- }
-
- if (collobjs)
- MEM_freeN(collobjs);
-}
-
-void dag_add_forcefield_relations(DagForest *dag, Scene *scene, Object *ob, DagNode *node, EffectorWeights *effector_weights, bool add_absorption, int skip_forcefield, const char *name)
-{
- ListBase *effectors = pdInitEffectors(scene, ob, NULL, effector_weights, false);
-
- if (effectors) {
- for (EffectorCache *eff = effectors->first; eff; eff = eff->next) {
- if (eff->ob != ob && eff->pd->forcefield != skip_forcefield) {
- create_collision_relation(dag, node, eff->ob, name);
-
- if (eff->pd->forcefield == PFIELD_SMOKEFLOW && eff->pd->f_source) {
- create_collision_relation(dag, node, eff->pd->f_source, "Smoke Force Domain");
- }
-
- if (add_absorption && (eff->pd->flag & PFIELD_VISIBILITY)) {
- /* Actual code uses get_collider_cache */
- dag_add_collision_relations(dag, scene, ob, node, NULL, eff->ob->lay, eModifierType_Collision, NULL, true, "Force Absorption");
- }
- }
- }
- }
-
- pdEndEffectors(&effectors);
-}
-
-static void build_dag_object(DagForest *dag, DagNode *scenenode, Main *bmain, Scene *scene, Object *ob, int mask)
-{
- bConstraint *con;
- DagNode *node;
- DagNode *node2;
- DagNode *node3;
- Key *key;
- ParticleSystem *psys;
- int addtoroot = 1;
-
- node = dag_get_node(dag, ob);
-
- if ((ob->data) && (mask & DAG_RL_DATA)) {
- node2 = dag_get_node(dag, ob->data);
- dag_add_relation(dag, node, node2, DAG_RL_DATA, "Object-Data Relation");
- node2->first_ancestor = ob;
- node2->ancestor_count += 1;
- }
-
- /* also build a custom data mask for dependencies that need certain layers */
-
- if (ob->type == OB_ARMATURE) {
- if (ob->pose) {
- bPoseChannel *pchan;
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- for (con = pchan->constraints.first; con; con = con->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- if (cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- if (ct->tar && ct->tar != ob) {
- // fprintf(stderr, "armature %s target :%s\n", ob->id.name, target->id.name);
- node3 = dag_get_node(dag, ct->tar);
-
- if (ct->subtarget[0]) {
- dag_add_relation(dag, node3, node, DAG_RL_OB_DATA | DAG_RL_DATA_DATA, cti->name);
- if (ct->tar->type == OB_MESH)
- node3->customdata_mask |= CD_MASK_MDEFORMVERT;
- }
- else if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK))
- dag_add_relation(dag, node3, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, cti->name);
- else
- dag_add_relation(dag, node3, node, DAG_RL_OB_DATA, cti->name);
- }
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 1);
- }
-
- }
- }
- }
- }
-
- /* driver dependencies, nla modifiers */
-#if 0 // XXX old animation system
- if (ob->nlastrips.first) {
- bActionStrip *strip;
- bActionChannel *chan;
- for (strip = ob->nlastrips.first; strip; strip = strip->next) {
- if (strip->modifiers.first) {
- bActionModifier *amod;
- for (amod = strip->modifiers.first; amod; amod = amod->next) {
- if (amod->ob) {
- node2 = dag_get_node(dag, amod->ob);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "NLA Strip Modifier");
- }
- }
- }
- }
- }
-#endif // XXX old animation system
- if (ob->adt)
- dag_add_driver_relation(ob->adt, dag, node, (ob->type == OB_ARMATURE)); // XXX isdata arg here doesn't give an accurate picture of situation
-
- key = BKE_key_from_object(ob);
- if (key && key->adt)
- dag_add_driver_relation(key->adt, dag, node, 1);
-
- if (ob->modifiers.first) {
- ModifierData *md;
-
- for (md = ob->modifiers.first; md; md = md->next) {
- const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
-
- if (mti->updateDepgraph) mti->updateDepgraph(md, dag, bmain, scene, ob, node);
- }
- }
- if (ob->parent) {
- node2 = dag_get_node(dag, ob->parent);
-
- switch (ob->partype) {
- case PARSKEL:
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_OB, "Parent");
- break;
- case PARVERT1: case PARVERT3:
- dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, "Vertex Parent");
- node2->customdata_mask |= CD_MASK_ORIGINDEX;
- break;
- case PARBONE:
- dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, "Bone Parent");
- break;
- default:
- if (ob->parent->type == OB_LATTICE)
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_OB, "Lattice Parent");
- else if (ob->parent->type == OB_CURVE) {
- Curve *cu = ob->parent->data;
- if (cu->flag & CU_PATH)
- dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, "Curve Parent");
- else
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Curve Parent");
- }
- else
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Parent");
- break;
- }
- /* exception case: parent is duplivert */
- if (ob->type == OB_MBALL && (ob->parent->transflag & OB_DUPLIVERTS)) {
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_OB, "Duplivert");
- }
-
- addtoroot = 0;
- }
- if (ob->proxy) {
- node2 = dag_get_node(dag, ob->proxy);
- dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA | DAG_RL_OB_OB, "Proxy");
- /* inverted relation, so addtoroot shouldn't be set to zero */
- }
-
- if (ob->transflag & OB_DUPLI) {
- if ((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) {
- GroupObject *go;
- for (go = ob->dup_group->gobject.first; go; go = go->next) {
- if (go->ob) {
- node2 = dag_get_node(dag, go->ob);
- /* node2 changes node1, this keeps animations updated in groups?? not logical? */
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Dupligroup");
- }
- }
- }
- }
-
- /* rigidbody force fields */
- if ((ob->type == OB_MESH) || (ob->type == OB_CURVE) || (ob->type == OB_LATTICE)) {
- if (ob->rigidbody_object && scene->rigidbody_world) {
- dag_add_forcefield_relations(dag, scene, ob, node, scene->rigidbody_world->effector_weights, true, 0, "Force Field");
- }
- }
-
- /* object data drivers */
- if (ob->data) {
- AnimData *adt = BKE_animdata_from_id((ID *)ob->data);
- if (adt)
- dag_add_driver_relation(adt, dag, node, 1);
- }
-
- /* object type/data relationships */
- switch (ob->type) {
- case OB_CAMERA:
- {
- Camera *cam = (Camera *)ob->data;
-
- if (cam->dof_ob) {
- node2 = dag_get_node(dag, cam->dof_ob);
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Camera DoF");
- }
- break;
- }
- case OB_MBALL:
- {
- Object *mom = BKE_mball_basis_find(scene, ob);
-
- if (mom != ob) {
- node2 = dag_get_node(dag, mom);
- dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Metaball"); /* mom depends on children! */
- }
- break;
- }
- case OB_CURVE:
- case OB_FONT:
- {
- Curve *cu = ob->data;
-
- if (cu->bevobj) {
- node2 = dag_get_node(dag, cu->bevobj);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Curve Bevel");
- }
- if (cu->taperobj) {
- node2 = dag_get_node(dag, cu->taperobj);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Curve Taper");
- }
- if (ob->type == OB_FONT) {
- /* Really rather dirty hack. needs to support font family to work
- * reliably on render export.
- *
- * This totally mimics behavior of regular verts duplication with
- * parenting. The only tricky thing here is to get list of objects
- * used for the custom "font".
- *
- * This shouldn't harm so much because this code only runs on DAG
- * rebuild and this feature is not that commonly used.
- *
- * - sergey -
- */
- if (cu->family[0] != '\n') {
- ListBase *duplilist;
- DupliObject *dob;
- duplilist = object_duplilist(G.main->eval_ctx, scene, ob);
- for (dob = duplilist->first; dob; dob = dob->next) {
- node2 = dag_get_node(dag, dob->ob);
- dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Object Font");
- }
- free_object_duplilist(duplilist);
- }
-
- if (cu->textoncurve) {
- node2 = dag_get_node(dag, cu->textoncurve);
- /* Text on curve requires path to be evaluated for the target curve. */
- node2->eval_flags |= DAG_EVAL_NEED_CURVE_PATH;
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Texture On Curve");
- }
- }
- break;
- }
- }
-
- /* material drivers */
- if (ob->totcol) {
- int a;
-
- for (a = 1; a <= ob->totcol; a++) {
- Material *ma = give_current_material(ob, a);
-
- if (ma) {
- /* recursively figure out if there are drivers, and hook these up to this object */
- dag_add_material_driver_relations(dag, node, ma);
- }
- }
- }
- else if (ob->type == OB_LAMP) {
- dag_add_lamp_driver_relations(dag, node, ob->data);
- }
-
- /* particles */
- psys = ob->particlesystem.first;
- if (psys) {
- GroupObject *go;
-
- for (; psys; psys = psys->next) {
- BoidRule *rule = NULL;
- BoidState *state = NULL;
- ParticleSettings *part = psys->part;
-
- if (part->adt) {
- dag_add_driver_relation(part->adt, dag, node, 1);
- }
-
- dag_add_relation(dag, node, node, DAG_RL_OB_DATA, "Particle-Object Relation");
-
- if (!psys_check_enabled(ob, psys, G.is_rendering))
- continue;
-
- if (ELEM(part->phystype, PART_PHYS_KEYED, PART_PHYS_BOIDS)) {
- ParticleTarget *pt = psys->targets.first;
-
- for (; pt; pt = pt->next) {
- if (pt->ob && BLI_findlink(&pt->ob->particlesystem, pt->psys - 1)) {
- node2 = dag_get_node(dag, pt->ob);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Particle Targets");
- }
- }
- }
-
- if (part->ren_as == PART_DRAW_OB && part->dup_ob) {
- node2 = dag_get_node(dag, part->dup_ob);
- /* note that this relation actually runs in the wrong direction, the problem
- * is that dupli system all have this (due to parenting), and the render
- * engine instancing assumes particular ordering of objects in list */
- dag_add_relation(dag, node, node2, DAG_RL_OB_OB, "Particle Object Visualization");
- if (part->dup_ob->type == OB_MBALL)
- dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA, "Particle Object Visualization");
- }
-
- if (part->ren_as == PART_DRAW_GR && part->dup_group) {
- for (go = part->dup_group->gobject.first; go; go = go->next) {
- node2 = dag_get_node(dag, go->ob);
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Particle Group Visualization");
- }
- }
-
- if (part->type != PART_HAIR) {
- /* Actual code uses get_collider_cache */
- dag_add_collision_relations(dag, scene, ob, node, part->collision_group, ob->lay, eModifierType_Collision, NULL, true, "Particle Collision");
- }
- else if ((psys->flag & PSYS_HAIR_DYNAMICS) && psys->clmd && psys->clmd->coll_parms) {
- /* Hair uses cloth simulation, i.e. get_collision_objects */
- dag_add_collision_relations(dag, scene, ob, node, psys->clmd->coll_parms->group, ob->lay | scene->lay, eModifierType_Collision, NULL, true, "Hair Collision");
- }
-
- dag_add_forcefield_relations(dag, scene, ob, node, part->effector_weights, part->type == PART_HAIR, 0, "Particle Force Field");
-
- if (part->boids) {
- for (state = part->boids->states.first; state; state = state->next) {
- for (rule = state->rules.first; rule; rule = rule->next) {
- Object *ruleob = NULL;
- if (rule->type == eBoidRuleType_Avoid)
- ruleob = ((BoidRuleGoalAvoid *)rule)->ob;
- else if (rule->type == eBoidRuleType_FollowLeader)
- ruleob = ((BoidRuleFollowLeader *)rule)->ob;
-
- if (ruleob) {
- node2 = dag_get_node(dag, ruleob);
- dag_add_relation(dag, node2, node, DAG_RL_OB_DATA, "Boid Rule");
- }
- }
- }
- }
- }
- }
-
- /* object constraints */
- for (con = ob->constraints.first; con; con = con->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- if (!cti)
- continue;
-
- /* special case for camera tracking -- it doesn't use targets to define relations */
- if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, CONSTRAINT_TYPE_OBJECTSOLVER)) {
- int depends_on_camera = 0;
-
- if (cti->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
- bFollowTrackConstraint *data = (bFollowTrackConstraint *)con->data;
-
- if ((data->clip || data->flag & FOLLOWTRACK_ACTIVECLIP) && data->track[0])
- depends_on_camera = 1;
-
- if (data->depth_ob) {
- node2 = dag_get_node(dag, data->depth_ob);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, cti->name);
- }
- }
- else if (cti->type == CONSTRAINT_TYPE_OBJECTSOLVER)
- depends_on_camera = 1;
-
- if (depends_on_camera && scene->camera) {
- node2 = dag_get_node(dag, scene->camera);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, cti->name);
- }
-
- dag_add_relation(dag, scenenode, node, DAG_RL_SCENE, "Scene Relation");
- addtoroot = 0;
- }
- else if (cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- Object *obt;
-
- if (ct->tar)
- obt = ct->tar;
- else
- continue;
-
- node2 = dag_get_node(dag, obt);
- if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO))
- dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, cti->name);
- else {
- if (ELEM(obt->type, OB_ARMATURE, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) {
- dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, cti->name);
- if (obt->type == OB_MESH)
- node2->customdata_mask |= CD_MASK_MDEFORMVERT;
- }
- else
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB, cti->name);
- }
- addtoroot = 0;
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 1);
- }
- }
-
- if (addtoroot == 1)
- dag_add_relation(dag, scenenode, node, DAG_RL_SCENE, "Scene Relation");
-}
-
-static void build_dag_group(DagForest *dag, DagNode *scenenode, Main *bmain, Scene *scene, Group *group, short mask)
-{
- GroupObject *go;
-
- if (group->id.tag & LIB_TAG_DOIT)
- return;
-
- group->id.tag |= LIB_TAG_DOIT;
-
- for (go = group->gobject.first; go; go = go->next) {
- build_dag_object(dag, scenenode, bmain, scene, go->ob, mask);
- if (go->ob->dup_group)
- build_dag_group(dag, scenenode, bmain, scene, go->ob->dup_group, mask);
- }
-}
-
-DagForest *build_dag(Main *bmain, Scene *sce, short mask)
-{
- Base *base;
- Object *ob;
- DagNode *node;
- DagNode *scenenode;
- DagForest *dag;
- DagAdjList *itA;
-
- dag = sce->theDag;
- if (dag)
- free_forest(dag);
- else {
- dag = dag_init();
- sce->theDag = dag;
- }
- dag->need_update = false;
-
- BKE_main_id_tag_idcode(bmain, ID_OB, LIB_TAG_DOIT, false);
-
- /* clear "LIB_TAG_DOIT" flag from all materials, to prevent infinite recursion problems later [#32017] */
- BKE_main_id_tag_idcode(bmain, ID_MA, LIB_TAG_DOIT, false);
- BKE_main_id_tag_idcode(bmain, ID_LA, LIB_TAG_DOIT, false);
- BKE_main_id_tag_idcode(bmain, ID_GR, LIB_TAG_DOIT, false);
-
- /* add base node for scene. scene is always the first node in DAG */
- scenenode = dag_add_node(dag, sce);
-
- /* add current scene objects */
- for (base = sce->base.first; base; base = base->next) {
- ob = base->object;
- ob->id.tag |= LIB_TAG_DOIT;
- build_dag_object(dag, scenenode, bmain, sce, ob, mask);
- if (ob->proxy)
- build_dag_object(dag, scenenode, bmain, sce, ob->proxy, mask);
- if (ob->dup_group)
- build_dag_group(dag, scenenode, bmain, sce, ob->dup_group, mask);
- }
-
- /* There might be situations when object from current scene depends on
- * objects form other scene AND objects from other scene has own
- * dependencies on objects from other scene.
- *
- * This is really important to include such indirect dependencies in order
- * to keep threaded update safe but since we don't really know if object is
- * coming from current scene or another scene we do rather stupid tag-based
- * check here: all the objects for which build_dag_object() was called are
- * getting tagged with LIB_TAG_DOIT. This way if some node has untagged
- * object we know it's an object from other scene.
- *
- * It should be enough to to it once, because if there's longer chain of
- * indirect dependencies, all the new nodes will be added to the end of the
- * list, meaning we'll keep covering them in this for loop.
- */
- for (node = sce->theDag->DagNode.first; node != NULL; node = node->next) {
- if (node->type == ID_OB) {
- ob = node->ob;
- if ((ob->id.tag & LIB_TAG_DOIT) == 0) {
- ob->id.tag |= LIB_TAG_DOIT;
- build_dag_object(dag, scenenode, bmain, sce, ob, mask);
- if (ob->proxy)
- build_dag_object(dag, scenenode, bmain, sce, ob->proxy, mask);
- if (ob->dup_group)
- build_dag_group(dag, scenenode, bmain, sce, ob->dup_group, mask);
- }
- }
- }
-
- BKE_main_id_tag_idcode(bmain, ID_GR, LIB_TAG_DOIT, false);
-
- /* Now all relations were built, but we need to solve 1 exceptional case;
- * When objects have multiple "parents" (for example parent + constraint working on same object)
- * the relation type has to be synced. One of the parents can change, and should give same event to child */
-
- /* nodes were callocced, so we can use node->color for temporal storage */
- for (node = sce->theDag->DagNode.first; node; node = node->next) {
- if (node->type == ID_OB) {
- for (itA = node->child; itA; itA = itA->next) {
- if (itA->node->type == ID_OB) {
- itA->node->color |= itA->type;
- }
- }
-
- /* also flush custom data mask */
- ((Object *)node->ob)->customdata_mask = node->customdata_mask;
-
- if (node->parent == NULL) {
- dag_add_relation(dag, scenenode, node, DAG_RL_SCENE, "Scene Relation");
- }
- }
- }
- /* now set relations equal, so that when only one parent changes, the correct recalcs are found */
- for (node = sce->theDag->DagNode.first; node; node = node->next) {
- if (node->type == ID_OB) {
- for (itA = node->child; itA; itA = itA->next) {
- if (itA->node->type == ID_OB) {
- itA->type |= itA->node->color;
- }
- }
- }
- }
-
- /* cycle detection and solving */
- // solve_cycles(dag);
-
- return dag;
-}
-
-
-void free_forest(DagForest *Dag)
-{ /* remove all nodes and deps */
- DagNode *tempN;
- DagAdjList *tempA;
- DagAdjList *itA;
- DagNode *itN = Dag->DagNode.first;
-
- while (itN) {
- itA = itN->child;
- while (itA) {
- tempA = itA;
- itA = itA->next;
- MEM_freeN(tempA);
- }
-
- itA = itN->parent;
- while (itA) {
- tempA = itA;
- itA = itA->next;
- MEM_freeN(tempA);
- }
-
- tempN = itN;
- itN = itN->next;
- MEM_freeN(tempN);
- }
-
- BLI_ghash_free(Dag->nodeHash, NULL, NULL);
- Dag->nodeHash = NULL;
- Dag->DagNode.first = NULL;
- Dag->DagNode.last = NULL;
- Dag->numNodes = 0;
-
-}
-
-DagNode *dag_find_node(DagForest *forest, void *fob)
-{
- if (forest->nodeHash)
- return BLI_ghash_lookup(forest->nodeHash, fob);
-
- return NULL;
-}
-
-static int dag_print_dependencies = 0; /* debugging */
-
-/* no checking of existence, use dag_find_node first or dag_get_node */
-DagNode *dag_add_node(DagForest *forest, void *fob)
-{
- DagNode *node;
-
- node = MEM_callocN(sizeof(DagNode), "DAG node");
- if (node) {
- node->ob = fob;
- node->color = DAG_WHITE;
-
- if (forest->ugly_hack_sorry) node->type = GS(((ID *) fob)->name); /* sorry, done for pose sorting */
- if (forest->numNodes) {
- ((DagNode *) forest->DagNode.last)->next = node;
- forest->DagNode.last = node;
- forest->numNodes++;
- }
- else {
- forest->DagNode.last = node;
- forest->DagNode.first = node;
- forest->numNodes = 1;
- }
-
- if (!forest->nodeHash)
- forest->nodeHash = BLI_ghash_ptr_new("dag_add_node gh");
- BLI_ghash_insert(forest->nodeHash, fob, node);
- }
-
- return node;
-}
-
-DagNode *dag_get_node(DagForest *forest, void *fob)
-{
- DagNode *node;
-
- node = dag_find_node(forest, fob);
- if (!node)
- node = dag_add_node(forest, fob);
- return node;
-}
-
-
-
-DagNode *dag_get_sub_node(DagForest *forest, void *fob)
-{
- DagNode *node;
- DagAdjList *mainchild, *prev = NULL;
-
- mainchild = ((DagNode *) forest->DagNode.first)->child;
- /* remove from first node (scene) adj list if present */
- while (mainchild) {
- if (mainchild->node == fob) {
- if (prev) {
- prev->next = mainchild->next;
- MEM_freeN(mainchild);
- break;
- }
- else {
- ((DagNode *) forest->DagNode.first)->child = mainchild->next;
- MEM_freeN(mainchild);
- break;
- }
- }
- prev = mainchild;
- mainchild = mainchild->next;
- }
- node = dag_find_node(forest, fob);
- if (!node)
- node = dag_add_node(forest, fob);
- return node;
-}
-
-static void dag_add_parent_relation(DagForest *UNUSED(forest), DagNode *fob1, DagNode *fob2, short rel, const char *name)
-{
- DagAdjList *itA = fob2->parent;
-
- while (itA) { /* search if relation exist already */
- if (itA->node == fob1) {
- itA->type |= rel;
- itA->count += 1;
- return;
- }
- itA = itA->next;
- }
- /* create new relation and insert at head. MALLOC alert! */
- itA = MEM_mallocN(sizeof(DagAdjList), "DAG adj list");
- itA->node = fob1;
- itA->type = rel;
- itA->count = 1;
- itA->next = fob2->parent;
- itA->name = name;
- fob2->parent = itA;
-}
-
-void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, const char *name)
-{
- DagAdjList *itA = fob1->child;
-
- /* parent relation is for cycle checking */
- dag_add_parent_relation(forest, fob1, fob2, rel, name);
-
- /* TODO(sergey): Find a better place for this. */
-#ifdef WITH_OPENSUBDIV
- if ((rel & (DAG_RL_DATA_DATA | DAG_RL_DATA_OB)) != 0) {
- if (fob1->type == ID_OB) {
- if ((fob1->eval_flags & DAG_EVAL_NEED_CPU) == 0) {
- Object *ob2 = fob2->ob;
- if (ob2->recalc & OB_RECALC_ALL) {
- /* Make sure object has all the data on CPU. */
- Object *ob1 = fob1->ob;
- ob1->recalc |= OB_RECALC_DATA;
- }
- fob1->eval_flags |= DAG_EVAL_NEED_CPU;
- }
- }
- }
-#endif
-
- while (itA) { /* search if relation exist already */
- if (itA->node == fob2) {
- itA->type |= rel;
- itA->count += 1;
- return;
- }
- itA = itA->next;
- }
- /* create new relation and insert at head. MALLOC alert! */
- itA = MEM_mallocN(sizeof(DagAdjList), "DAG adj list");
- itA->node = fob2;
- itA->type = rel;
- itA->count = 1;
- itA->next = fob1->child;
- itA->name = name;
- fob1->child = itA;
-}
-
-static const char *dag_node_name(DagForest *dag, DagNode *node)
-{
- if (node->ob == NULL)
- return "null";
- else if (dag->ugly_hack_sorry)
- return ((ID *)(node->ob))->name + 2;
- else
- return ((bPoseChannel *)(node->ob))->name;
-}
-
-static void dag_node_print_dependencies(DagForest *dag, DagNode *node)
-{
- DagAdjList *itA;
-
- printf("%s depends on:\n", dag_node_name(dag, node));
-
- for (itA = node->parent; itA; itA = itA->next)
- printf(" %s through %s\n", dag_node_name(dag, itA->node), itA->name);
- printf("\n");
-}
-
-static int dag_node_print_dependency_recurs(DagForest *dag, DagNode *node, DagNode *endnode)
-{
- DagAdjList *itA;
-
- if (node->color == DAG_BLACK)
- return 0;
-
- node->color = DAG_BLACK;
-
- if (node == endnode)
- return 1;
-
- for (itA = node->parent; itA; itA = itA->next) {
- if (dag_node_print_dependency_recurs(dag, itA->node, endnode)) {
- printf(" %s depends on %s through %s.\n", dag_node_name(dag, node), dag_node_name(dag, itA->node), itA->name);
- return 1;
- }
- }
-
- return 0;
-}
-
-static void dag_node_print_dependency_cycle(DagForest *dag, DagNode *startnode, DagNode *endnode, const char *name)
-{
- DagNode *node;
-
- for (node = dag->DagNode.first; node; node = node->next)
- node->color = DAG_WHITE;
-
- printf(" %s depends on %s through %s.\n", dag_node_name(dag, endnode), dag_node_name(dag, startnode), name);
- dag_node_print_dependency_recurs(dag, startnode, endnode);
- printf("\n");
-}
-
-static int dag_node_recurs_level(DagNode *node, int level)
-{
- DagAdjList *itA;
- int newlevel;
-
- node->color = DAG_BLACK; /* done */
- newlevel = ++level;
-
- for (itA = node->parent; itA; itA = itA->next) {
- if (itA->node->color == DAG_WHITE) {
- itA->node->ancestor_count = dag_node_recurs_level(itA->node, level);
- newlevel = MAX2(newlevel, level + itA->node->ancestor_count);
- }
- else
- newlevel = MAX2(newlevel, level + itA->node->ancestor_count);
- }
-
- return newlevel;
-}
-
-static void dag_check_cycle(DagForest *dag)
-{
- DagNode *node;
- DagAdjList *itA;
-
- dag->is_acyclic = true;
-
- /* debugging print */
- if (dag_print_dependencies)
- for (node = dag->DagNode.first; node; node = node->next)
- dag_node_print_dependencies(dag, node);
-
- /* tag nodes unchecked */
- for (node = dag->DagNode.first; node; node = node->next)
- node->color = DAG_WHITE;
-
- for (node = dag->DagNode.first; node; node = node->next) {
- if (node->color == DAG_WHITE) {
- node->ancestor_count = dag_node_recurs_level(node, 0);
- }
- }
-
- /* check relations, and print errors */
- for (node = dag->DagNode.first; node; node = node->next) {
- for (itA = node->parent; itA; itA = itA->next) {
- if (itA->node->ancestor_count > node->ancestor_count) {
- if (node->ob && itA->node->ob) {
- dag->is_acyclic = false;
- printf("Dependency cycle detected:\n");
- dag_node_print_dependency_cycle(dag, itA->node, node, itA->name);
- }
- }
- }
- }
-
- /* parent relations are only needed for cycle checking, so free now */
- for (node = dag->DagNode.first; node; node = node->next) {
- while (node->parent) {
- itA = node->parent->next;
- MEM_freeN(node->parent);
- node->parent = itA;
- }
- }
-}
-
-/* debug test functions */
-
-void graph_print_queue(DagNodeQueue *nqueue)
-{
- DagNodeQueueElem *queueElem;
-
- queueElem = nqueue->first;
- while (queueElem) {
- fprintf(stderr, "** %s %i %i-%i ", ((ID *) queueElem->node->ob)->name, queueElem->node->color, queueElem->node->DFS_dvtm, queueElem->node->DFS_fntm);
- queueElem = queueElem->next;
- }
- fprintf(stderr, "\n");
-}
-
-void graph_print_queue_dist(DagNodeQueue *nqueue)
-{
- DagNodeQueueElem *queueElem;
- int count;
-
- queueElem = nqueue->first;
- count = 0;
- while (queueElem) {
- fprintf(stderr, "** %25s %2.2i-%2.2i ", ((ID *) queueElem->node->ob)->name, queueElem->node->DFS_dvtm, queueElem->node->DFS_fntm);
- while (count < queueElem->node->DFS_dvtm - 1) { fputc(' ', stderr); count++; }
- fputc('|', stderr);
- while (count < queueElem->node->DFS_fntm - 2) { fputc('-', stderr); count++; }
- fputc('|', stderr);
- fputc('\n', stderr);
- count = 0;
- queueElem = queueElem->next;
- }
- fprintf(stderr, "\n");
-}
-
-void graph_print_adj_list(DagForest *dag)
-{
- DagNode *node;
- DagAdjList *itA;
-
- node = dag->DagNode.first;
- while (node) {
- fprintf(stderr, "node : %s col: %i", ((ID *) node->ob)->name, node->color);
- itA = node->child;
- while (itA) {
- fprintf(stderr, "-- %s ", ((ID *) itA->node->ob)->name);
-
- itA = itA->next;
- }
- fprintf(stderr, "\n");
- node = node->next;
- }
-}
-
-/* ************************ API *********************** */
-
-/* mechanism to allow editors to be informed of depsgraph updates,
- * to do their own updates based on changes... */
-static void (*EditorsUpdateIDCb)(Main *bmain, ID *id) = NULL;
-static void (*EditorsUpdateSceneCb)(Main *bmain, Scene *scene, int updated) = NULL;
-static void (*EditorsUpdateScenePreCb)(Main *bmain, Scene *scene, bool time) = NULL;
-
-void DAG_editors_update_cb(void (*id_func)(Main *bmain, ID *id),
- void (*scene_func)(Main *bmain, Scene *scene, int updated),
- void (*scene_pre_func)(Main *bmain, Scene *scene, bool time))
-{
- if (DEG_depsgraph_use_legacy()) {
- EditorsUpdateIDCb = id_func;
- EditorsUpdateSceneCb = scene_func;
- EditorsUpdateScenePreCb = scene_pre_func;
- }
- else {
- /* New dependency graph. */
- DEG_editors_set_update_cb(id_func, scene_func, scene_pre_func);
- }
-}
-
-void DAG_editors_update_pre(Main *bmain, Scene *scene, bool time)
-{
- if (DEG_depsgraph_use_legacy()) {
- if (EditorsUpdateScenePreCb != NULL) {
- EditorsUpdateScenePreCb(bmain, scene, time);
- }
- }
- else {
- DEG_editors_update_pre(bmain, scene, time);
- }
-}
-
-static void dag_editors_id_update(Main *bmain, ID *id)
-{
- if (EditorsUpdateIDCb)
- EditorsUpdateIDCb(bmain, id);
-}
-
-static void dag_editors_scene_update(Main *bmain, Scene *scene, int updated)
-{
- if (EditorsUpdateSceneCb)
- EditorsUpdateSceneCb(bmain, scene, updated);
-}
-
-/* groups with objects in this scene need to be put in the right order as well */
-static void scene_sort_groups(Main *bmain, Scene *sce)
-{
- Base *base;
- Group *group;
- GroupObject *go;
- Object *ob;
-
- /* test; are group objects all in this scene? */
- for (ob = bmain->object.first; ob; ob = ob->id.next) {
- ob->id.tag &= ~LIB_TAG_DOIT;
- }
- for (base = sce->base.first; base; base = base->next)
- base->object->id.tag |= LIB_TAG_DOIT;
-
- for (group = bmain->group.first; group; group = group->id.next) {
- for (go = group->gobject.first; go; go = go->next) {
- if ((go->ob->id.tag & LIB_TAG_DOIT) == 0)
- break;
- }
- /* this group is entirely in this scene */
- if (go == NULL) {
- ListBase listb = {NULL, NULL};
-
- for (go = group->gobject.first; go; go = go->next)
- go->ob->id.newid = (ID *)go;
-
- /* in order of sorted bases we reinsert group objects */
- for (base = sce->base.first; base; base = base->next) {
-
- if (base->object->id.newid) {
- go = (GroupObject *)base->object->id.newid;
- base->object->id.newid = NULL;
- BLI_remlink(&group->gobject, go);
- BLI_addtail(&listb, go);
- }
- }
- /* copy the newly sorted listbase */
- group->gobject = listb;
- }
- }
-
- /* newid abused for GroupObject, cleanup. */
- for (ob = bmain->object.first; ob; ob = ob->id.next) {
- ob->id.newid = NULL;
- }
-}
-
-static void dag_scene_tag_rebuild(Scene *sce)
-{
- if (sce->theDag) {
- sce->theDag->need_update = true;
- }
-}
-
-/* free the depency graph */
-static void dag_scene_free(Scene *sce)
-{
- if (sce->theDag) {
- free_forest(sce->theDag);
- MEM_freeN(sce->theDag);
- sce->theDag = NULL;
- }
-}
-
-/* Check whether object data needs to be evaluated before it
- * might be used by others.
- *
- * Means that mesh object needs to have proper derivedFinal,
- * curves-typed objects are to have proper curve cache.
- *
- * Other objects or objects which are tagged for data update are
- * not considered to be in need of evaluation.
- */
-static bool check_object_needs_evaluation(Object *object)
-{
- if (object->recalc & OB_RECALC_ALL) {
- /* Object is tagged for update anyway, no need to re-tag it. */
- return false;
- }
-
- if (object->type == OB_MESH) {
- return object->derivedFinal == NULL;
- }
- else if (ELEM(object->type, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
- return object->curve_cache == NULL;
- }
-
- return false;
-}
-
-/* Check whether object data is tagged for update. */
-static bool check_object_tagged_for_update(Object *object)
-{
- if (object->recalc & OB_RECALC_ALL) {
- return true;
- }
-
- if (ELEM(object->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
- ID *data_id = object->data;
- return (data_id->tag & (LIB_TAG_ID_RECALC_DATA | LIB_TAG_ID_RECALC)) != 0;
- }
-
- return false;
-}
-
-/* Flush changes from tagged objects in the scene to their
- * dependencies which are not evaluated yet.
- *
- * This is needed to ensure all the dependencies are met
- * before objects gets handled by object_handle_update(),
- *
- * This is needed when visible layers are changed or changing
- * scene graph layout which involved usage of objects which
- * aren't in the scene or weren't visible yet.
- */
-static void dag_invisible_dependencies_flush(Scene *scene)
-{
- DagNode *root_node = scene->theDag->DagNode.first, *node;
- DagNodeQueue *queue;
-
- for (node = root_node; node != NULL; node = node->next) {
- node->color = DAG_WHITE;
- }
-
- queue = queue_create(DAGQUEUEALLOC);
-
- for (node = root_node; node != NULL; node = node->next) {
- if (node->color == DAG_WHITE) {
- push_stack(queue, node);
- node->color = DAG_GRAY;
-
- while (queue->count) {
- DagNode *current_node = get_top_node_queue(queue);
- DagAdjList *itA;
- bool skip = false;
-
- for (itA = current_node->child; itA; itA = itA->next) {
- if (itA->node->color == DAG_WHITE) {
- itA->node->color = DAG_GRAY;
- push_stack(queue, itA->node);
- skip = true;
- break;
- }
- }
-
- if (!skip) {
- current_node = pop_queue(queue);
-
- if (current_node->type == ID_OB) {
- Object *current_object = current_node->ob;
- if (check_object_needs_evaluation(current_object)) {
- for (itA = current_node->child; itA; itA = itA->next) {
- if (itA->node->type == ID_OB) {
- Object *object = itA->node->ob;
- if (check_object_tagged_for_update(object)) {
- current_object->recalc |= OB_RECALC_OB | OB_RECALC_DATA;
- }
- }
- }
- }
- }
- node->color = DAG_BLACK;
- }
- }
- }
- }
-
- queue_delete(queue);
-}
-
-static void dag_invisible_dependencies_check_flush(Main *bmain, Scene *scene)
-{
- if (DAG_id_type_tagged(bmain, ID_OB) ||
- DAG_id_type_tagged(bmain, ID_ME) || /* Mesh */
- DAG_id_type_tagged(bmain, ID_CU) || /* Curve */
- DAG_id_type_tagged(bmain, ID_MB) || /* MetaBall */
- DAG_id_type_tagged(bmain, ID_LT)) /* Lattice */
- {
- dag_invisible_dependencies_flush(scene);
- }
-}
-
-/* sort the base list on dependency order */
-static void dag_scene_build(Main *bmain, Scene *sce)
-{
- DagNode *node, *rootnode;
- DagNodeQueue *nqueue;
- DagAdjList *itA;
- int time;
- int skip = 0;
- ListBase tempbase;
- Base *base;
-
- BLI_listbase_clear(&tempbase);
-
- build_dag(bmain, sce, DAG_RL_ALL_BUT_DATA);
-
- dag_check_cycle(sce->theDag);
-
- nqueue = queue_create(DAGQUEUEALLOC);
-
- for (node = sce->theDag->DagNode.first; node; node = node->next) {
- node->color = DAG_WHITE;
- }
-
- time = 1;
-
- rootnode = sce->theDag->DagNode.first;
- rootnode->color = DAG_GRAY;
- time++;
- push_stack(nqueue, rootnode);
-
- while (nqueue->count) {
-
- skip = 0;
- node = get_top_node_queue(nqueue);
-
- itA = node->child;
- while (itA != NULL) {
- if (itA->node->color == DAG_WHITE) {
- itA->node->DFS_dvtm = time;
- itA->node->color = DAG_GRAY;
-
- time++;
- push_stack(nqueue, itA->node);
- skip = 1;
- break;
- }
- itA = itA->next;
- }
-
- if (!skip) {
- if (node) {
- node = pop_queue(nqueue);
- if (node->ob == sce) /* we are done */
- break;
- node->color = DAG_BLACK;
-
- time++;
- base = sce->base.first;
- while (base && base->object != node->ob)
- base = base->next;
- if (base) {
- BLI_remlink(&sce->base, base);
- BLI_addhead(&tempbase, base);
- }
- }
- }
- }
-
- /* temporal correction for circular dependencies */
- base = sce->base.first;
- while (base) {
- BLI_remlink(&sce->base, base);
- BLI_addhead(&tempbase, base);
- //if (G.debug & G_DEBUG)
- printf("cyclic %s\n", base->object->id.name);
- base = sce->base.first;
- }
-
- sce->base = tempbase;
- queue_delete(nqueue);
-
- /* all groups with objects in this scene gets resorted too */
- scene_sort_groups(bmain, sce);
-
- if (G.debug & G_DEBUG) {
- printf("\nordered\n");
- for (base = sce->base.first; base; base = base->next) {
- printf(" %s\n", base->object->id.name);
- }
- }
-
- /* Make sure that new dependencies which came from invisible layers
- * are tagged for update (if they're needed for objects which were
- * tagged for update).
- */
- dag_invisible_dependencies_check_flush(bmain, sce);
-}
-
-/* clear all dependency graphs */
-void DAG_relations_tag_update(Main *bmain)
-{
- if (DEG_depsgraph_use_legacy()) {
- Scene *sce;
- for (sce = bmain->scene.first; sce; sce = sce->id.next) {
- dag_scene_tag_rebuild(sce);
- }
- }
- else {
- /* New dependency graph. */
- DEG_relations_tag_update(bmain);
- }
-}
-
-/* rebuild dependency graph only for a given scene */
-void DAG_scene_relations_rebuild(Main *bmain, Scene *sce)
-{
- if (DEG_depsgraph_use_legacy()) {
- dag_scene_free(sce);
- DAG_scene_relations_update(bmain, sce);
- }
- else {
- /* New dependency graph. */
- DEG_scene_relations_rebuild(bmain, sce);
- }
-}
-
-/* create dependency graph if it was cleared or didn't exist yet */
-void DAG_scene_relations_update(Main *bmain, Scene *sce)
-{
- if (DEG_depsgraph_use_legacy()) {
- if (!sce->theDag || sce->theDag->need_update)
- dag_scene_build(bmain, sce);
- }
- else {
- /* New dependency graph. */
- DEG_scene_relations_update(bmain, sce);
- }
-}
-
-void DAG_scene_relations_validate(Main *bmain, Scene *sce)
-{
- if (!DEG_depsgraph_use_legacy()) {
- DEG_debug_scene_relations_validate(bmain, sce);
- }
-}
-
-void DAG_scene_free(Scene *sce)
-{
- if (DEG_depsgraph_use_legacy()) {
- if (sce->theDag) {
- free_forest(sce->theDag);
- MEM_freeN(sce->theDag);
- sce->theDag = NULL;
- }
- }
- else {
- if (sce->depsgraph) {
- DEG_graph_free(sce->depsgraph);
- sce->depsgraph = NULL;
- }
- }
-}
-
-static void lib_id_recalc_tag(Main *bmain, ID *id)
-{
- id->tag |= LIB_TAG_ID_RECALC;
- DAG_id_type_tag(bmain, GS(id->name));
-}
-
-static void lib_id_recalc_data_tag(Main *bmain, ID *id)
-{
- id->tag |= LIB_TAG_ID_RECALC_DATA;
- DAG_id_type_tag(bmain, GS(id->name));
-}
-
-/* node was checked to have lasttime != curtime and is if type ID_OB */
-static void flush_update_node(Main *bmain, DagNode *node, unsigned int layer, int curtime)
-{
- DagAdjList *itA;
- Object *ob, *obc;
- int oldflag;
- bool changed = false;
- unsigned int all_layer;
-
- node->lasttime = curtime;
-
- ob = node->ob;
- if (ob && (ob->recalc & OB_RECALC_ALL)) {
- all_layer = node->scelay;
-
- /* got an object node that changes, now check relations */
- for (itA = node->child; itA; itA = itA->next) {
- all_layer |= itA->lay;
- /* the relationship is visible */
- if ((itA->lay & layer)) { // XXX || (itA->node->ob == obedit)
- if (itA->node->type == ID_OB) {
- obc = itA->node->ob;
- oldflag = obc->recalc;
-
- /* got a ob->obc relation, now check if flag needs flush */
- if (ob->recalc & OB_RECALC_OB) {
- if (itA->type & DAG_RL_OB_OB) {
- //printf("ob %s changes ob %s\n", ob->id.name, obc->id.name);
- obc->recalc |= OB_RECALC_OB;
- lib_id_recalc_tag(bmain, &obc->id);
- }
- if (itA->type & DAG_RL_OB_DATA) {
- //printf("ob %s changes obdata %s\n", ob->id.name, obc->id.name);
- obc->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &obc->id);
- }
- }
- if (ob->recalc & OB_RECALC_DATA) {
- if (itA->type & DAG_RL_DATA_OB) {
- //printf("obdata %s changes ob %s\n", ob->id.name, obc->id.name);
- obc->recalc |= OB_RECALC_OB;
- lib_id_recalc_tag(bmain, &obc->id);
- }
- if (itA->type & DAG_RL_DATA_DATA) {
- //printf("obdata %s changes obdata %s\n", ob->id.name, obc->id.name);
- obc->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &obc->id);
- }
- }
- if (oldflag != obc->recalc) changed = 1;
- }
- }
- }
- /* even nicer, we can clear recalc flags... */
- if ((all_layer & layer) == 0) { // XXX && (ob != obedit)) {
- /* but existing displaylists or derivedmesh should be freed */
- if (ob->recalc & OB_RECALC_DATA)
- BKE_object_free_derived_caches(ob);
-
- ob->recalc &= ~OB_RECALC_ALL;
- }
- }
-
- /* check case where child changes and parent forcing obdata to change */
- /* should be done regardless if this ob has recalc set */
- /* could merge this in with loop above...? (ton) */
- for (itA = node->child; itA; itA = itA->next) {
- /* the relationship is visible */
- if ((itA->lay & layer)) { // XXX || (itA->node->ob == obedit)
- if (itA->node->type == ID_OB) {
- obc = itA->node->ob;
- /* child moves */
- if ((obc->recalc & OB_RECALC_ALL) == OB_RECALC_OB) {
- /* parent has deforming info */
- if (itA->type & (DAG_RL_OB_DATA | DAG_RL_DATA_DATA)) {
- // printf("parent %s changes ob %s\n", ob->id.name, obc->id.name);
- obc->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &obc->id);
- }
- }
- }
- }
- }
-
- /* we only go deeper if node not checked or something changed */
- for (itA = node->child; itA; itA = itA->next) {
- if (changed || itA->node->lasttime != curtime)
- flush_update_node(bmain, itA->node, layer, curtime);
- }
-
-}
-
-/* node was checked to have lasttime != curtime, and is of type ID_OB */
-static unsigned int flush_layer_node(Scene *sce, DagNode *node, int curtime)
-{
- DagAdjList *itA;
-
- node->lasttime = curtime;
- node->lay = node->scelay;
-
- for (itA = node->child; itA; itA = itA->next) {
- if (itA->node->type == ID_OB) {
- if (itA->node->lasttime != curtime) {
- itA->lay = flush_layer_node(sce, itA->node, curtime); /* lay is only set once for each relation */
- }
- else {
- itA->lay = itA->node->lay;
- }
-
- node->lay |= itA->lay;
- }
- }
-
- return node->lay;
-}
-
-/* node was checked to have lasttime != curtime, and is of type ID_OB */
-static void flush_pointcache_reset(Main *bmain, Scene *scene, DagNode *node,
- int curtime, unsigned int lay, bool reset)
-{
- DagAdjList *itA;
- Object *ob;
-
- node->lasttime = curtime;
-
- for (itA = node->child; itA; itA = itA->next) {
- if (itA->node->type == ID_OB) {
- if (itA->node->lasttime != curtime) {
- ob = (Object *)(itA->node->ob);
-
- if (reset || (ob->recalc & OB_RECALC_ALL)) {
- if (BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH)) {
- /* Don't tag nodes which are on invisible layer. */
- if (itA->node->lay & lay) {
- ob->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &ob->id);
- }
- }
-
- flush_pointcache_reset(bmain, scene, itA->node, curtime, lay, true);
- }
- else
- flush_pointcache_reset(bmain, scene, itA->node, curtime, lay, false);
- }
- }
- }
-}
-
-/* flush layer flags to dependencies */
-static void dag_scene_flush_layers(Scene *sce, int lay)
-{
- DagNode *node, *firstnode;
- DagAdjList *itA;
- Base *base;
- int lasttime;
-
- firstnode = sce->theDag->DagNode.first; /* always scene node */
-
- for (itA = firstnode->child; itA; itA = itA->next)
- itA->lay = 0;
-
- sce->theDag->time++; /* so we know which nodes were accessed */
- lasttime = sce->theDag->time;
-
- /* update layer flags in nodes */
- for (base = sce->base.first; base; base = base->next) {
- node = dag_get_node(sce->theDag, base->object);
- node->scelay = base->object->lay;
- }
-
- /* ensure cameras are set as if they are on a visible layer, because
- * they ared still used for rendering or setting the camera view
- *
- * XXX, this wont work for local view / unlocked camera's */
- if (sce->camera) {
- node = dag_get_node(sce->theDag, sce->camera);
- node->scelay |= lay;
- }
-
-#ifdef DURIAN_CAMERA_SWITCH
- {
- TimeMarker *m;
-
- for (m = sce->markers.first; m; m = m->next) {
- if (m->camera) {
- node = dag_get_node(sce->theDag, m->camera);
- node->scelay |= lay;
- }
- }
- }
-#endif
-
- /* flush layer nodes to dependencies */
- for (itA = firstnode->child; itA; itA = itA->next)
- if (itA->node->lasttime != lasttime && itA->node->type == ID_OB)
- flush_layer_node(sce, itA->node, lasttime);
-}
-
-static void dag_tag_renderlayers(Scene *sce, unsigned int lay)
-{
- if (sce->nodetree) {
- bNode *node;
- Base *base;
- unsigned int lay_changed = 0;
-
- for (base = sce->base.first; base; base = base->next)
- if (base->lay & lay)
- if (base->object->recalc)
- lay_changed |= base->lay;
-
- for (node = sce->nodetree->nodes.first; node; node = node->next) {
- if (node->id == (ID *)sce) {
- SceneRenderLayer *srl = BLI_findlink(&sce->r.layers, node->custom1);
- if (srl && (srl->lay & lay_changed))
- nodeUpdate(sce->nodetree, node);
- }
- }
- }
-}
-
-/* flushes all recalc flags in objects down the dependency tree */
-void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, const short time)
-{
- DagNode *firstnode;
- DagAdjList *itA;
- Object *ob;
- int lasttime;
-
- if (!DEG_depsgraph_use_legacy()) {
- return;
- }
-
- if (sce->theDag == NULL || sce->theDag->need_update) {
- printf("DAG zero... not allowed to happen!\n");
- DAG_scene_relations_update(bmain, sce);
- }
-
- firstnode = sce->theDag->DagNode.first; /* always scene node */
-
- /* first we flush the layer flags */
- dag_scene_flush_layers(sce, lay);
-
- /* then we use the relationships + layer info to flush update events */
- sce->theDag->time++; /* so we know which nodes were accessed */
- lasttime = sce->theDag->time;
- for (itA = firstnode->child; itA; itA = itA->next)
- if (itA->node->lasttime != lasttime && itA->node->type == ID_OB)
- flush_update_node(bmain, itA->node, lay, lasttime);
-
- /* if update is not due to time change, do pointcache clears */
- if (!time) {
- sce->theDag->time++; /* so we know which nodes were accessed */
- lasttime = sce->theDag->time;
- for (itA = firstnode->child; itA; itA = itA->next) {
- if (itA->node->lasttime != lasttime && itA->node->type == ID_OB) {
- ob = (Object *)(itA->node->ob);
-
- if (ob->recalc & OB_RECALC_ALL) {
- if (BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH)) {
- ob->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &ob->id);
- }
-
- flush_pointcache_reset(bmain, sce, itA->node, lasttime,
- lay, true);
- }
- else
- flush_pointcache_reset(bmain, sce, itA->node, lasttime,
- lay, false);
- }
- }
- }
-
- dag_tag_renderlayers(sce, lay);
-}
-
-static bool modifier_nlastrips_use_time(ListBase *strips)
-{
- NlaStrip *strip;
-
- if (strips) {
- for (strip = strips->first; strip; strip = strip->next) {
- if (modifier_nlastrips_use_time(&strip->strips)) {
- return true;
- }
- else if (strip->act) {
- FCurve *fcu;
-
- for (fcu = strip->act->curves.first; fcu; fcu = fcu->next) {
- if (fcu->rna_path && strstr(fcu->rna_path, "modifiers["))
- return true;
- }
- }
- }
- }
-
- return false;
-}
-
-static bool object_modifiers_use_time(Object *ob)
-{
- ModifierData *md;
-
- /* check if a modifier in modifier stack needs time input */
- for (md = ob->modifiers.first; md; md = md->next) {
- if (modifier_dependsOnTime(md))
- return true;
- }
-
- /* check whether any modifiers are animated */
- if (ob->adt) {
- AnimData *adt = ob->adt;
- NlaTrack *nlt;
- FCurve *fcu;
-
- /* action - check for F-Curves with paths containing 'modifiers[' */
- if (adt->action) {
- for (fcu = adt->action->curves.first; fcu; fcu = fcu->next) {
- if (fcu->rna_path && strstr(fcu->rna_path, "modifiers["))
- return true;
- }
- }
-
- /* This here allows modifier properties to get driven and still update properly
- *
- * Workaround to get [#26764] (e.g. subsurf levels not updating when animated/driven)
- * working, without the updating problems ([#28525] [#28690] [#28774] [#28777]) caused
- * by the RNA updates cache introduced in r.38649
- */
- for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
- if (fcu->rna_path && strstr(fcu->rna_path, "modifiers["))
- return true;
- }
-
- /* Also check NLA Strips... [#T45938] */
- for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
- if (modifier_nlastrips_use_time(&nlt->strips))
- return true;
- }
- }
-
- return false;
-}
-
-static short animdata_use_time(AnimData *adt)
-{
- NlaTrack *nlt;
-
- if (adt == NULL) return 0;
-
- /* check action - only if assigned, and it has anim curves */
- if (adt->action && adt->action->curves.first)
- return 1;
-
- /* check NLA tracks + strips */
- for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
- if (nlt->strips.first)
- return 1;
- }
-
- /* If we have drivers, more likely than not, on a frame change
- * they'll need updating because their owner changed
- *
- * This is kindof a hack to get around a whole host of problems
- * involving drivers using non-object datablock data (which the
- * depsgraph currently has no way of representing let alone correctly
- * dependency sort+tagging). By doing this, at least we ensure that
- * some commonly attempted drivers (such as scene -> current frame;
- * see "Driver updates fail" thread on Bf-committers dated July 2)
- * will work correctly, and that other non-object datablocks will have
- * their drivers update at least on frame change.
- *
- * -- Aligorith, July 4 2011
- */
- if (adt->drivers.first)
- return 1;
-
- return 0;
-}
-
-static void dag_object_time_update_flags(Main *bmain, Scene *scene, Object *ob)
-{
- if (ob->constraints.first) {
- bConstraint *con;
- for (con = ob->constraints.first; con; con = con->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- if (cti) {
- /* special case for camera tracking -- it doesn't use targets to define relations */
- if (ELEM(cti->type,
- CONSTRAINT_TYPE_FOLLOWTRACK,
- CONSTRAINT_TYPE_CAMERASOLVER,
- CONSTRAINT_TYPE_OBJECTSOLVER,
- CONSTRAINT_TYPE_TRANSFORM_CACHE))
- {
- ob->recalc |= OB_RECALC_OB;
- }
- else if (cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- if (ct->tar) {
- ob->recalc |= OB_RECALC_OB;
- break;
- }
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 1);
- }
-
- }
- }
- }
-
- if (ob->parent) {
- /* motion path or bone child */
- if (ob->parent->type == OB_CURVE || ob->parent->type == OB_ARMATURE) ob->recalc |= OB_RECALC_OB;
- }
-
-#if 0 // XXX old animation system
- if (ob->nlastrips.first) {
- if (ob->dup_group) {
- bActionStrip *strip;
- /* this case is for groups with nla, whilst nla target has no action or nla */
- for (strip = ob->nlastrips.first; strip; strip = strip->next) {
- if (strip->object)
- strip->object->recalc |= OB_RECALC_ALL;
- }
- }
- }
-#endif // XXX old animation system
-
- if (animdata_use_time(ob->adt)) {
- ob->recalc |= OB_RECALC_OB;
- ob->adt->recalc |= ADT_RECALC_ANIM;
- }
-
- if ((ob->adt) && (ob->type == OB_ARMATURE)) ob->recalc |= OB_RECALC_DATA;
-
- if (object_modifiers_use_time(ob)) ob->recalc |= OB_RECALC_DATA;
- if ((ob->pose) && (ob->pose->flag & POSE_CONSTRAINTS_TIMEDEPEND)) ob->recalc |= OB_RECALC_DATA;
-
- // XXX: scene here may not be the scene that contains the rigidbody world affecting this!
- if (ob->rigidbody_object && BKE_scene_check_rigidbody_active(scene))
- ob->recalc |= OB_RECALC_OB;
-
- {
- AnimData *adt = BKE_animdata_from_id((ID *)ob->data);
- Mesh *me;
- Curve *cu;
- Lattice *lt;
-
- switch (ob->type) {
- case OB_MESH:
- me = ob->data;
- if (me->key) {
- if (!(ob->shapeflag & OB_SHAPE_LOCK)) {
- ob->recalc |= OB_RECALC_DATA;
- }
- }
- if (ob->particlesystem.first)
- ob->recalc |= OB_RECALC_DATA;
- break;
- case OB_CURVE:
- case OB_SURF:
- cu = ob->data;
- if (cu->key) {
- if (!(ob->shapeflag & OB_SHAPE_LOCK)) {
- ob->recalc |= OB_RECALC_DATA;
- }
- }
- break;
- case OB_FONT:
- cu = ob->data;
- if (BLI_listbase_is_empty(&cu->nurb) && cu->str && cu->vfont)
- ob->recalc |= OB_RECALC_DATA;
- break;
- case OB_LATTICE:
- lt = ob->data;
- if (lt->key) {
- if (!(ob->shapeflag & OB_SHAPE_LOCK)) {
- ob->recalc |= OB_RECALC_DATA;
- }
- }
- break;
- case OB_MBALL:
- if (ob->transflag & OB_DUPLI) ob->recalc |= OB_RECALC_DATA;
- break;
- case OB_EMPTY:
- /* update animated images */
- if (ob->empty_drawtype == OB_EMPTY_IMAGE && ob->data)
- if (BKE_image_is_animated(ob->data))
- ob->recalc |= OB_RECALC_DATA;
- break;
- }
-
- if (animdata_use_time(adt)) {
- ob->recalc |= OB_RECALC_DATA;
- adt->recalc |= ADT_RECALC_ANIM;
- }
-
- if (ob->particlesystem.first) {
- ParticleSystem *psys = ob->particlesystem.first;
-
- for (; psys; psys = psys->next) {
- if (psys_check_enabled(ob, psys, G.is_rendering)) {
- ob->recalc |= OB_RECALC_DATA;
- break;
- }
- }
- }
- }
-
- if (ob->recalc & OB_RECALC_OB)
- lib_id_recalc_tag(bmain, &ob->id);
- if (ob->recalc & OB_RECALC_DATA)
- lib_id_recalc_data_tag(bmain, &ob->id);
-
-}
-
-/* recursively update objects in groups, each group is done at most once */
-static void dag_group_update_flags(Main *bmain, Scene *scene, Group *group, const bool do_time)
-{
- GroupObject *go;
-
- if (group->id.tag & LIB_TAG_DOIT)
- return;
-
- group->id.tag |= LIB_TAG_DOIT;
-
- for (go = group->gobject.first; go; go = go->next) {
- if (do_time)
- dag_object_time_update_flags(bmain, scene, go->ob);
- if (go->ob->dup_group)
- dag_group_update_flags(bmain, scene, go->ob->dup_group, do_time);
- }
-}
-
-/* flag all objects that need recalc, for changes in time for example */
-/* do_time: make this optional because undo resets objects to their animated locations without this */
-void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const bool do_time, const bool do_invisible_flush)
-{
- Base *base;
- Object *ob;
- Group *group;
- GroupObject *go;
- Scene *sce_iter;
-
- BKE_main_id_tag_idcode(bmain, ID_GR, LIB_TAG_DOIT, false);
-
- /* set ob flags where animated systems are */
- for (SETLOOPER(scene, sce_iter, base)) {
- ob = base->object;
-
- if (do_time) {
- /* now if DagNode were part of base, the node->lay could be checked... */
- /* we do all now, since the scene_flush checks layers and clears recalc flags even */
-
- /* NOTE: "sce_iter" not "scene" so that rigidbodies in background scenes work
- * (i.e. muting + rbw availability can be checked and tagged properly) [#33970]
- */
- dag_object_time_update_flags(bmain, sce_iter, ob);
- }
-
- /* recursively tag groups with LIB_TAG_DOIT, and update flags for objects */
- if (ob->dup_group)
- dag_group_update_flags(bmain, scene, ob->dup_group, do_time);
- }
-
- for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set)
- DAG_scene_flush_update(bmain, sce_iter, lay, 1);
-
- if (do_time) {
- /* test: set time flag, to disable baked systems to update */
- for (SETLOOPER(scene, sce_iter, base)) {
- ob = base->object;
- if (ob->recalc & OB_RECALC_ALL)
- ob->recalc |= OB_RECALC_TIME;
- }
-
- /* hrmf... an exception to look at once, for invisible camera object we do it over */
- if (scene->camera)
- dag_object_time_update_flags(bmain, scene, scene->camera);
- }
-
- /* and store the info in groupobject */
- for (group = bmain->group.first; group; group = group->id.next) {
- if (group->id.tag & LIB_TAG_DOIT) {
- for (go = group->gobject.first; go; go = go->next) {
- go->recalc = go->ob->recalc;
- // printf("ob %s recalc %d\n", go->ob->id.name, go->recalc);
- }
- group->id.tag &= ~LIB_TAG_DOIT;
- }
- }
-
- if (do_invisible_flush) {
- dag_invisible_dependencies_check_flush(bmain, scene);
- }
-}
-
-/* struct returned by DagSceneLayer */
-typedef struct DagSceneLayer {
- struct DagSceneLayer *next, *prev;
- Scene *scene;
- unsigned int layer;
-} DagSceneLayer;
-
-/* returns visible scenes with valid DAG */
-static void dag_current_scene_layers(Main *bmain, ListBase *lb)
-{
- wmWindowManager *wm;
- wmWindow *win;
-
- BLI_listbase_clear(lb);
-
- /* if we have a windowmanager, look into windows */
- if ((wm = bmain->wm.first)) {
-
- BKE_main_id_flag_listbase(&bmain->scene, LIB_TAG_DOIT, 1);
-
- for (win = wm->windows.first; win; win = win->next) {
- if (win->screen && win->screen->scene->theDag) {
- Scene *scene = win->screen->scene;
- DagSceneLayer *dsl;
-
- if (scene->id.tag & LIB_TAG_DOIT) {
- dsl = MEM_mallocN(sizeof(DagSceneLayer), "dag scene layer");
-
- BLI_addtail(lb, dsl);
-
- dsl->scene = scene;
- dsl->layer = BKE_screen_visible_layers(win->screen, scene);
-
- scene->id.tag &= ~LIB_TAG_DOIT;
- }
- else {
- /* It is possible that multiple windows shares the same scene
- * and have different layers visible.
- *
- * Here we deal with such cases by squashing layers bits from
- * multiple windoew to the DagSceneLayer.
- *
- * TODO(sergey): Such a lookup could be optimized perhaps,
- * however should be fine for now since we usually have only
- * few open windows.
- */
- for (dsl = lb->first; dsl; dsl = dsl->next) {
- if (dsl->scene == scene) {
- dsl->layer |= BKE_screen_visible_layers(win->screen, scene);
- break;
- }
- }
- }
- }
- }
- }
- else {
- /* if not, use the first sce */
- DagSceneLayer *dsl = MEM_mallocN(sizeof(DagSceneLayer), "dag scene layer");
-
- BLI_addtail(lb, dsl);
-
- dsl->scene = bmain->scene.first;
- dsl->layer = dsl->scene->lay;
-
- /* XXX for background mode, we should get the scene
- * from somewhere, for the -S option, but it's in
- * the context, how to get it here? */
- }
-}
-
-static void dag_group_on_visible_update(Scene *scene, Group *group)
-{
- GroupObject *go;
-
- if (group->id.tag & LIB_TAG_DOIT)
- return;
-
- group->id.tag |= LIB_TAG_DOIT;
-
- for (go = group->gobject.first; go; go = go->next) {
- if (ELEM(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
- go->ob->recalc |= OB_RECALC_DATA;
- go->ob->id.tag |= LIB_TAG_DOIT;
- lib_id_recalc_tag(G.main, &go->ob->id);
- }
- if (go->ob->proxy_from) {
- go->ob->recalc |= OB_RECALC_OB;
- go->ob->id.tag |= LIB_TAG_DOIT;
- lib_id_recalc_tag(G.main, &go->ob->id);
- }
-
- if (go->ob->dup_group)
- dag_group_on_visible_update(scene, go->ob->dup_group);
- }
-}
-
-void DAG_on_visible_update(Main *bmain, const bool do_time)
-{
- ListBase listbase;
- DagSceneLayer *dsl;
-
- if (!DEG_depsgraph_use_legacy()) {
- /* Inform new dependnecy graphs about visibility changes. */
- DEG_on_visible_update(bmain, do_time);
- return;
- }
-
- /* get list of visible scenes and layers */
- dag_current_scene_layers(bmain, &listbase);
-
- for (dsl = listbase.first; dsl; dsl = dsl->next) {
- Scene *scene = dsl->scene;
- Scene *sce_iter;
- Base *base;
- Object *ob;
- DagNode *node;
- unsigned int lay = dsl->layer, oblay;
-
- /* derivedmeshes and displists are not saved to file so need to be
- * remade, tag them so they get remade in the scene update loop,
- * note armature poses or object matrices are preserved and do not
- * require updates, so we skip those */
- for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set)
- dag_scene_flush_layers(sce_iter, lay);
-
- BKE_main_id_tag_idcode(bmain, ID_GR, LIB_TAG_DOIT, false);
-
- for (SETLOOPER(scene, sce_iter, base)) {
- ob = base->object;
- node = (sce_iter->theDag) ? dag_get_node(sce_iter->theDag, ob) : NULL;
- oblay = (node) ? node->lay : ob->lay;
-
- if ((oblay & lay) & ~scene->lay_updated) {
- /* TODO(sergey): Why do we need armature here now but didn't need before? */
- if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE, OB_ARMATURE)) {
- ob->recalc |= OB_RECALC_DATA;
- lib_id_recalc_tag(bmain, &ob->id);
- }
- /* This should not be needed here, but in some cases, like after a redo, we can end up with
- * a wrong final matrix (see T42472).
- * Quoting Sergey, this comes from BKE_object_handle_update_ex, which is calling
- * BKE_object_where_is_calc_ex when it shouldn't, but that issue is not easily fixable.
- */
- else {
- ob->recalc |= OB_RECALC_OB;
- lib_id_recalc_tag(bmain, &ob->id);
- }
- if (ob->proxy && (ob->proxy_group == NULL)) {
- ob->proxy->recalc |= OB_RECALC_DATA;
- lib_id_recalc_tag(bmain, &ob->id);
- }
- if (ob->dup_group)
- dag_group_on_visible_update(scene, ob->dup_group);
- }
- }
-
- BKE_main_id_tag_idcode(bmain, ID_GR, LIB_TAG_DOIT, false);
-
- /* now tag update flags, to ensure deformers get calculated on redraw */
- DAG_scene_update_flags(bmain, scene, lay, do_time, true);
- scene->lay_updated |= lay;
- }
-
- BLI_freelistN(&listbase);
-
- /* hack to get objects updating on layer changes */
- DAG_id_type_tag(bmain, ID_OB);
-
- /* so masks update on load */
- if (bmain->mask.first) {
- Mask *mask;
-
- for (mask = bmain->mask.first; mask; mask = mask->id.next) {
- DAG_id_tag_update(&mask->id, 0);
- }
- }
-}
-
-static void dag_id_flush_update__isDependentTexture(
- void *userData, Object *UNUSED(ob), ID **idpoin, int UNUSED(cd_flag))
-{
- struct { ID *id; bool is_dependent; } *data = userData;
-
- if (*idpoin && GS((*idpoin)->name) == ID_TE) {
- if (data->id == (*idpoin))
- data->is_dependent = 1;
- }
-}
-
-static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id)
-{
- Object *obt, *ob = NULL;
- short idtype;
-
- /* here we flush a few things before actual scene wide flush, mostly
- * due to only objects and not other datablocks being in the depsgraph */
-
- /* set flags & pointcache for object */
- if (GS(id->name) == ID_OB) {
- ob = (Object *)id;
- BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH);
-
- /* So if someone tagged object recalc directly,
- * id_tag_update bit-field stays relevant
- */
- if (ob->recalc & OB_RECALC_ALL) {
- DAG_id_type_tag(bmain, GS(id->name));
- }
-
- if (ob->recalc & OB_RECALC_DATA) {
- /* all users of this ob->data should be checked */
- id = ob->data;
-
- /* no point in trying in this cases */
- if (id && id->us <= 1) {
- dag_editors_id_update(bmain, id);
- id = NULL;
- }
- }
- }
-
- /* set flags & pointcache for object data */
- if (id) {
- idtype = GS(id->name);
-
-
- if (OB_DATA_SUPPORT_ID(idtype)) {
- for (obt = bmain->object.first; obt; obt = obt->id.next) {
- if (!(ob && obt == ob) && obt->data == id) {
- obt->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &obt->id);
- BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
- }
- }
- }
- else if (idtype == ID_VF) {
- for (obt = bmain->object.first; obt; obt = obt->id.next) {
- if (obt->type == OB_FONT) {
- Curve *cu = obt->data;
- if (ELEM((struct VFont *)id, CURVE_VFONT_ANY(cu))) {
- obt->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &obt->id);
- }
- }
- }
- }
-
- /* set flags based on textures - can influence depgraph via modifiers */
- if (idtype == ID_TE) {
- for (obt = bmain->object.first; obt; obt = obt->id.next) {
- struct { ID *id; bool is_dependent; } data;
- data.id = id;
- data.is_dependent = 0;
-
- modifiers_foreachIDLink(obt, dag_id_flush_update__isDependentTexture, &data);
- if (data.is_dependent) {
- obt->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &obt->id);
- }
-
- /* particle settings can use the texture as well */
- if (obt->particlesystem.first) {
- ParticleSystem *psys = obt->particlesystem.first;
- MTex **mtexp, *mtex;
- int a;
- for (; psys; psys = psys->next) {
- mtexp = psys->part->mtex;
- for (a = 0; a < MAX_MTEX; a++, mtexp++) {
- mtex = *mtexp;
- if (mtex && mtex->tex == (Tex *)id) {
- obt->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &obt->id);
-
- if (mtex->mapto & PAMAP_INIT)
- psys->recalc |= PSYS_RECALC_RESET;
- if (mtex->mapto & PAMAP_CHILD)
- psys->recalc |= PSYS_RECALC_CHILD;
-
- BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
- }
- }
- }
- }
- }
- }
-
- /* set flags based on ShapeKey */
- if (idtype == ID_KE) {
- for (obt = bmain->object.first; obt; obt = obt->id.next) {
- Key *key = BKE_key_from_object(obt);
- if (!(ob && obt == ob) && ((ID *)key == id)) {
- obt->flag |= (OB_RECALC_OB | OB_RECALC_DATA);
- lib_id_recalc_tag(bmain, &obt->id);
- lib_id_recalc_data_tag(bmain, &obt->id);
- BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
- }
- }
- }
-
- /* set flags based on particle settings */
- if (idtype == ID_PA) {
- ParticleSystem *psys;
- for (obt = bmain->object.first; obt; obt = obt->id.next)
- for (psys = obt->particlesystem.first; psys; psys = psys->next)
- if (&psys->part->id == id)
- BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
- }
-
- if (ELEM(idtype, ID_MA, ID_TE)) {
- obt = sce->basact ? sce->basact->object : NULL;
- if (obt && obt->mode & OB_MODE_TEXTURE_PAINT) {
- BKE_texpaint_slots_refresh_object(sce, obt);
- BKE_paint_proj_mesh_data_check(sce, obt, NULL, NULL, NULL, NULL);
- GPU_drawobject_free(obt->derivedFinal);
- }
- }
-
- if (idtype == ID_MC) {
- MovieClip *clip = (MovieClip *) id;
-
- BKE_tracking_dopesheet_tag_update(&clip->tracking);
-
- for (obt = bmain->object.first; obt; obt = obt->id.next) {
- bConstraint *con;
- for (con = obt->constraints.first; con; con = con->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER,
- CONSTRAINT_TYPE_OBJECTSOLVER))
- {
- obt->recalc |= OB_RECALC_OB;
- lib_id_recalc_tag(bmain, &obt->id);
- break;
- }
- }
- }
-
- if (sce->nodetree) {
- bNode *node;
-
- for (node = sce->nodetree->nodes.first; node; node = node->next) {
- if (node->id == id) {
- nodeUpdate(sce->nodetree, node);
- }
- }
- }
- }
-
- /* Not pretty to iterate all the nodes here, but it's as good as it
- * could be with the current depsgraph design/
- */
- if (idtype == ID_IM) {
- FOREACH_NODETREE(bmain, ntree, parent_id) {
- if (ntree->type == NTREE_SHADER) {
- bNode *node;
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->id == id) {
- lib_id_recalc_tag(bmain, &ntree->id);
- break;
- }
- }
- }
- } FOREACH_NODETREE_END
- }
-
- if (idtype == ID_MSK) {
- if (sce->nodetree) {
- bNode *node;
-
- for (node = sce->nodetree->nodes.first; node; node = node->next) {
- if (node->id == id) {
- nodeUpdate(sce->nodetree, node);
- }
- }
- }
- }
-
- /* camera's matrix is used to orient reconstructed stuff,
- * so it should happen tracking-related constraints recalculation
- * when camera is changing (sergey) */
- if (sce->camera && &sce->camera->id == id) {
- MovieClip *clip = BKE_object_movieclip_get(sce, sce->camera, true);
-
- if (clip)
- dag_id_flush_update(bmain, sce, &clip->id);
- }
-
- /* update editors */
- dag_editors_id_update(bmain, id);
- }
-}
-
-void DAG_ids_flush_tagged(Main *bmain)
-{
- ListBase listbase;
- DagSceneLayer *dsl;
- ListBase *lbarray[MAX_LIBARRAY];
- int a;
- bool do_flush = false;
-
- if (!DEG_depsgraph_use_legacy()) {
- DEG_ids_flush_tagged(bmain);
- return;
- }
-
- /* get list of visible scenes and layers */
- dag_current_scene_layers(bmain, &listbase);
-
- if (BLI_listbase_is_empty(&listbase))
- return;
-
- /* loop over all ID types */
- a = set_listbasepointers(bmain, lbarray);
-
- while (a--) {
- ListBase *lb = lbarray[a];
- ID *id = lb->first;
-
- if (id && bmain->id_tag_update[BKE_idcode_to_index(GS(id->name))]) {
- for (; id; id = id->next) {
- if (id->tag & (LIB_TAG_ID_RECALC | LIB_TAG_ID_RECALC_DATA)) {
-
- for (dsl = listbase.first; dsl; dsl = dsl->next)
- dag_id_flush_update(bmain, dsl->scene, id);
-
- do_flush = true;
- }
- }
- }
- }
-
- /* flush changes to other objects */
- if (do_flush) {
- for (dsl = listbase.first; dsl; dsl = dsl->next)
- DAG_scene_flush_update(bmain, dsl->scene, dsl->layer, 0);
- }
-
- BLI_freelistN(&listbase);
-}
-
-void DAG_ids_check_recalc(Main *bmain, Scene *scene, bool time)
-{
- ListBase *lbarray[MAX_LIBARRAY];
- int a;
- bool updated = false;
-
- if (!DEG_depsgraph_use_legacy()) {
- DEG_ids_check_recalc(bmain, scene, time);
- return;
- }
-
- /* loop over all ID types */
- a = set_listbasepointers(bmain, lbarray);
-
- while (a--) {
- ListBase *lb = lbarray[a];
- ID *id = lb->first;
-
- if (id && bmain->id_tag_update[BKE_idcode_to_index(GS(id->name))]) {
- updated = true;
- break;
- }
- }
-
- dag_editors_scene_update(bmain, scene, (updated || time));
-}
-
-/* It is possible that scene_update_post and frame_update_post handlers
- * will modify objects. The issue is that DAG_ids_clear_recalc is called
- * just after callbacks, which leaves objects with recalc flags but no
- * corresponding bit in ID recalc bitfield. This leads to some kind of
- * regression when using ID type tag fields to check whether there objects
- * to be updated internally comparing threaded DAG with legacy one.
- *
- * For now let's have a workaround which will preserve tag for ID_OB
- * if there're objects with OB_RECALC_ALL bits. This keeps behavior
- * unchanged comparing with 2.69 release.
- *
- * TODO(sergey): Need to get rid of such a workaround.
- *
- * - sergey -
- */
-
-#define POST_UPDATE_HANDLER_WORKAROUND
-
-void DAG_ids_clear_recalc(Main *bmain)
-{
- ListBase *lbarray[MAX_LIBARRAY];
- bNodeTree *ntree;
- int a;
-
-#ifdef POST_UPDATE_HANDLER_WORKAROUND
- bool have_updated_objects = false;
-
- if (DAG_id_type_tagged(bmain, ID_OB)) {
- ListBase listbase;
- DagSceneLayer *dsl;
-
- /* We need to check all visible scenes, otherwise resetting
- * OB_ID changed flag will only work fine for first scene of
- * multiple visible and all the rest will skip update.
- *
- * This could also lead to wrong behavior scene update handlers
- * because of missing ID datablock changed flags.
- *
- * This is a bit of a bummer to allocate list here, but likely
- * it wouldn't become too much bad because it only happens when
- * objects were actually changed.
- */
- dag_current_scene_layers(bmain, &listbase);
-
- for (dsl = listbase.first; dsl; dsl = dsl->next) {
- Scene *scene = dsl->scene;
- DagNode *node;
- for (node = scene->theDag->DagNode.first;
- node != NULL && have_updated_objects == false;
- node = node->next)
- {
- if (node->type == ID_OB) {
- Object *object = (Object *) node->ob;
- if (object->recalc & OB_RECALC_ALL) {
- have_updated_objects = true;
- break;
- }
- }
- }
- }
-
- BLI_freelistN(&listbase);
- }
-#endif
-
- /* loop over all ID types */
- a = set_listbasepointers(bmain, lbarray);
-
- while (a--) {
- ListBase *lb = lbarray[a];
- ID *id = lb->first;
-
- if (id && bmain->id_tag_update[BKE_idcode_to_index(GS(id->name))]) {
- for (; id; id = id->next) {
- if (id->tag & (LIB_TAG_ID_RECALC | LIB_TAG_ID_RECALC_DATA))
- id->tag &= ~(LIB_TAG_ID_RECALC | LIB_TAG_ID_RECALC_DATA);
-
- /* some ID's contain semi-datablock nodetree */
- ntree = ntreeFromID(id);
- if (ntree && (ntree->id.tag & (LIB_TAG_ID_RECALC | LIB_TAG_ID_RECALC_DATA)))
- ntree->id.tag &= ~(LIB_TAG_ID_RECALC | LIB_TAG_ID_RECALC_DATA);
- }
- }
- }
-
- memset(bmain->id_tag_update, 0, sizeof(bmain->id_tag_update));
-
-#ifdef POST_UPDATE_HANDLER_WORKAROUND
- if (have_updated_objects) {
- DAG_id_type_tag(bmain, ID_OB);
- }
-#endif
-}
-
-void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag)
-{
- if (!DEG_depsgraph_use_legacy()) {
- DEG_id_tag_update_ex(bmain, id, flag);
- return;
- }
-
- if (id == NULL) return;
-
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- printf("%s: id=%s flag=%d\n", __func__, id->name, flag);
- }
-
- /* tag ID for update */
- if (flag) {
- if (flag & OB_RECALC_OB)
- lib_id_recalc_tag(bmain, id);
- if (flag & (OB_RECALC_DATA | PSYS_RECALC))
- lib_id_recalc_data_tag(bmain, id);
- }
- else
- lib_id_recalc_tag(bmain, id);
-
- /* flag is for objects and particle systems */
- if (flag) {
- Object *ob;
- short idtype = GS(id->name);
-
- if (idtype == ID_OB) {
- /* only quick tag */
- ob = (Object *)id;
- ob->recalc |= (flag & OB_RECALC_ALL);
- }
- else if (idtype == ID_PA) {
- ParticleSystem *psys;
- /* this is weak still, should be done delayed as well */
- for (ob = bmain->object.first; ob; ob = ob->id.next) {
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- if (&psys->part->id == id) {
- ob->recalc |= (flag & OB_RECALC_ALL);
- psys->recalc |= (flag & PSYS_RECALC);
- lib_id_recalc_tag(bmain, &ob->id);
- lib_id_recalc_data_tag(bmain, &ob->id);
- }
- }
- }
- }
- else {
- /* disable because this is called on various ID types automatically.
- * where printing warning is not useful. for now just ignore */
- /* BLI_assert(!"invalid flag for this 'idtype'"); */
- }
- }
- else if (GS(id->name) == ID_CF) {
- for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
- ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache);
-
- if (md) {
- MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md;
-
- if (mcmd->cache_file && (&mcmd->cache_file->id == id)) {
- ob->recalc |= OB_RECALC_ALL;
- continue;
- }
- }
-
- for (bConstraint *con = ob->constraints.first; con; con = con->next) {
- if (con->type != CONSTRAINT_TYPE_TRANSFORM_CACHE) {
- continue;
- }
-
- bTransformCacheConstraint *data = con->data;
-
- if (data->cache_file && (&data->cache_file->id == id)) {
- ob->recalc |= OB_RECALC_ALL;
- break;
- }
- }
- }
- }
-}
-
-void DAG_id_tag_update(ID *id, short flag)
-{
- DAG_id_tag_update_ex(G.main, id, flag);
-}
-
-void DAG_id_type_tag(Main *bmain, short idtype)
-{
- if (idtype == ID_NT) {
- /* stupid workaround so parent datablocks of nested nodetree get looped
- * over when we loop over tagged datablock types */
- DAG_id_type_tag(bmain, ID_MA);
- DAG_id_type_tag(bmain, ID_TE);
- DAG_id_type_tag(bmain, ID_LA);
- DAG_id_type_tag(bmain, ID_WO);
- DAG_id_type_tag(bmain, ID_SCE);
- }
-
- bmain->id_tag_update[BKE_idcode_to_index(idtype)] = 1;
-}
-
-int DAG_id_type_tagged(Main *bmain, short idtype)
-{
- return bmain->id_tag_update[BKE_idcode_to_index(idtype)];
-}
-
-#if 0 // UNUSED
-/* recursively descends tree, each node only checked once */
-/* node is checked to be of type object */
-static int parent_check_node(DagNode *node, int curtime)
-{
- DagAdjList *itA;
-
- node->lasttime = curtime;
-
- if (node->color == DAG_GRAY)
- return DAG_GRAY;
-
- for (itA = node->child; itA; itA = itA->next) {
- if (itA->node->type == ID_OB) {
-
- if (itA->node->color == DAG_GRAY)
- return DAG_GRAY;
-
- /* descend if not done */
- if (itA->node->lasttime != curtime) {
- itA->node->color = parent_check_node(itA->node, curtime);
-
- if (itA->node->color == DAG_GRAY)
- return DAG_GRAY;
- }
- }
- }
-
- return DAG_WHITE;
-}
-#endif
-
-/* ******************* DAG FOR ARMATURE POSE ***************** */
-
-/* we assume its an armature with pose */
-void DAG_pose_sort(Object *ob)
-{
- bPose *pose = ob->pose;
- bPoseChannel *pchan;
- bConstraint *con;
- DagNode *node;
- DagNode *node2, *node3;
- DagNode *rootnode;
- DagForest *dag;
- DagNodeQueue *nqueue;
- DagAdjList *itA;
- ListBase tempbase;
- int skip = 0;
-
- dag = dag_init();
- dag->ugly_hack_sorry = false; /* no ID structs */
-
- rootnode = dag_add_node(dag, NULL); /* node->ob becomes NULL */
-
- /* we add the hierarchy and the constraints */
- for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- int addtoroot = 1;
-
- node = dag_get_node(dag, pchan);
-
- if (pchan->parent) {
- node2 = dag_get_node(dag, pchan->parent);
- dag_add_relation(dag, node2, node, 0, "Parent Relation");
- addtoroot = 0;
- }
- for (con = pchan->constraints.first; con; con = con->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- if (cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- if (ct->tar == ob && ct->subtarget[0]) {
- bPoseChannel *target = BKE_pose_channel_find_name(ob->pose, ct->subtarget);
- if (target) {
- node2 = dag_get_node(dag, target);
- dag_add_relation(dag, node2, node, 0, "Pose Constraint");
-
- if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
- bKinematicConstraint *data = (bKinematicConstraint *)con->data;
- bPoseChannel *parchan;
- int segcount = 0;
-
- /* exclude tip from chain? */
- if (!(data->flag & CONSTRAINT_IK_TIP))
- parchan = pchan->parent;
- else
- parchan = pchan;
-
- /* Walk to the chain's root */
- while (parchan) {
- node3 = dag_get_node(dag, parchan);
- dag_add_relation(dag, node2, node3, 0, "IK Constraint");
-
- segcount++;
- if (segcount == data->rootbone || segcount > 255) break; /* 255 is weak */
- parchan = parchan->parent;
- }
- }
- }
- }
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 1);
- }
- }
- if (addtoroot == 1) {
- dag_add_relation(dag, rootnode, node, 0, "Root Bone Relation");
- }
- }
-
- dag_check_cycle(dag);
-
- /* now we try to sort... */
- BLI_listbase_clear(&tempbase);
-
- nqueue = queue_create(DAGQUEUEALLOC);
-
- /* tag nodes unchecked */
- for (node = dag->DagNode.first; node; node = node->next)
- node->color = DAG_WHITE;
-
- rootnode->color = DAG_GRAY;
- push_stack(nqueue, rootnode);
-
- while (nqueue->count) {
-
- skip = 0;
- node = get_top_node_queue(nqueue);
-
- itA = node->child;
- while (itA != NULL) {
- if (itA->node->color == DAG_WHITE) {
- itA->node->color = DAG_GRAY;
- push_stack(nqueue, itA->node);
- skip = 1;
- break;
- }
- itA = itA->next;
- }
-
- if (!skip) {
- if (node) {
- node = pop_queue(nqueue);
- if (node->ob == NULL) /* we are done */
- break;
- node->color = DAG_BLACK;
-
- /* put node in new list */
- BLI_remlink(&pose->chanbase, node->ob);
- BLI_addhead(&tempbase, node->ob);
- }
- }
- }
-
- /* temporal correction for circular dependencies */
- while (pose->chanbase.first) {
- pchan = pose->chanbase.first;
- BLI_remlink(&pose->chanbase, pchan);
- BLI_addhead(&tempbase, pchan);
-
- printf("cyclic %s\n", pchan->name);
- }
-
- pose->chanbase = tempbase;
- queue_delete(nqueue);
-
-// printf("\nordered\n");
-// for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
-// printf(" %s\n", pchan->name);
-// }
-
- free_forest(dag);
- MEM_freeN(dag);
-}
-
-/* ************************ DAG FOR THREADED UPDATE ********************* */
-
-/* Initialize run-time data in the graph needed for traversing it
- * from multiple threads and start threaded tree traversal by adding
- * the root node to the queue.
- *
- * This will mark DAG nodes as object/non-object and will calculate
- * num_pending_parents of nodes (which is how many non-updated parents node
- * have, which helps a lot checking whether node could be scheduled
- * already or not).
- */
-void DAG_threaded_update_begin(Scene *scene,
- void (*func)(void *node, void *user_data),
- void *user_data)
-{
- DagNode *node;
-
- /* We reset num_pending_parents to zero first and tag node as not scheduled yet... */
- for (node = scene->theDag->DagNode.first; node; node = node->next) {
- node->num_pending_parents = 0;
- node->scheduled = false;
- }
-
- /* ... and then iterate over all the nodes and
- * increase num_pending_parents for node childs.
- */
- for (node = scene->theDag->DagNode.first; node; node = node->next) {
- DagAdjList *itA;
-
- for (itA = node->child; itA; itA = itA->next) {
- if (itA->node != node) {
- itA->node->num_pending_parents++;
- }
- }
- }
-
- /* Add root nodes to the queue. */
- BLI_spin_lock(&threaded_update_lock);
- for (node = scene->theDag->DagNode.first; node; node = node->next) {
- if (node->num_pending_parents == 0) {
- node->scheduled = true;
- func(node, user_data);
- }
- }
- BLI_spin_unlock(&threaded_update_lock);
-}
-
-/* This function is called when handling node is done.
- *
- * This function updates num_pending_parents for all childs and
- * schedules them if they're ready.
- */
-void DAG_threaded_update_handle_node_updated(void *node_v,
- void (*func)(void *node, void *user_data),
- void *user_data)
-{
- DagNode *node = node_v;
- DagAdjList *itA;
-
- for (itA = node->child; itA; itA = itA->next) {
- DagNode *child_node = itA->node;
- if (child_node != node) {
- atomic_sub_and_fetch_uint32(&child_node->num_pending_parents, 1);
-
- if (child_node->num_pending_parents == 0) {
- bool need_schedule;
-
- BLI_spin_lock(&threaded_update_lock);
- need_schedule = child_node->scheduled == false;
- child_node->scheduled = true;
- BLI_spin_unlock(&threaded_update_lock);
-
- if (need_schedule) {
- func(child_node, user_data);
- }
- }
- }
- }
-}
-
-/* ************************ DAG DEBUGGING ********************* */
-
-void DAG_print_dependencies(Main *bmain, Scene *scene, Object *ob)
-{
- /* utility for debugging dependencies */
- dag_print_dependencies = 1;
-
- if (ob && (ob->mode & OB_MODE_POSE)) {
- printf("\nDEPENDENCY RELATIONS for %s\n\n", ob->id.name + 2);
- DAG_pose_sort(ob);
- }
- else {
- printf("\nDEPENDENCY RELATIONS for %s\n\n", scene->id.name + 2);
- DAG_scene_relations_rebuild(bmain, scene);
- }
-
- dag_print_dependencies = 0;
-}
-
-/* ************************ DAG querying ********************* */
-
-/* Will return Object ID if node represents Object,
- * and will return NULL otherwise.
- */
-Object *DAG_get_node_object(void *node_v)
-{
- DagNode *node = node_v;
-
- if (node->type == ID_OB) {
- return node->ob;
- }
-
- return NULL;
-}
-
-/* Returns node name, used for debug output only, atm. */
-const char *DAG_get_node_name(Scene *scene, void *node_v)
-{
- DagNode *node = node_v;
-
- return dag_node_name(scene->theDag, node);
-}
-
-short DAG_get_eval_flags_for_object(Scene *scene, void *object)
-{
- DagNode *node;
-
- if (!DEG_depsgraph_use_legacy()) {
- return DEG_get_eval_flags_for_id(scene->depsgraph, (ID *)object);
- }
-
- if (scene->theDag == NULL) {
- /* Happens when converting objects to mesh from a python script
- * after modifying scene graph.
- *
- * Currently harmless because it's only called for temporary
- * objects which are out of the DAG anyway.
- */
- return 0;
- }
-
- node = dag_find_node(scene->theDag, object);
-
- if (node) {
- return node->eval_flags;
- }
- else {
- /* Happens when external render engine exports temporary objects
- * which are not in the DAG.
- */
-
- /* TODO(sergey): Doublecheck objects with Curve Deform exports all fine. */
-
- /* TODO(sergey): Weak but currently we can't really access proper DAG from
- * the modifiers stack. This is because in most cases modifier is to use
- * the foreground scene, but to access evaluation flags we need to know
- * active background scene, which we don't know.
- */
- if (scene->set) {
- return DAG_get_eval_flags_for_object(scene->set, object);
- }
- return 0;
- }
-}
-
-bool DAG_is_acyclic(Scene *scene)
-{
- return scene->theDag->is_acyclic;
-}
-
-#else
-
/* *********************************************************************
* Stubs to avoid linking issues and make sure legacy crap is not used *
* *********************************************************************
@@ -3686,5 +338,3 @@ void DAG_print_dependencies(Main *UNUSED(bmain),
{
DEG_debug_graphviz(scene->depsgraph, stdout, "Depsgraph", false);
}
-
-#endif
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index fce4620294d..bc9871aee54 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -32,6 +32,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_kdtree.h"
+#include "BLI_string_utils.h"
#include "BLI_task.h"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
@@ -215,6 +216,7 @@ typedef struct ImgSeqFormatData {
/* adjacency data flags */
#define ADJ_ON_MESH_EDGE (1 << 0)
+#define ADJ_BORDER_PIXEL (1 << 1)
typedef struct PaintAdjData {
int *n_target; /* array of neighboring point indexes, for single sample use (n_index + neigh_num) */
@@ -222,6 +224,8 @@ typedef struct PaintAdjData {
int *n_num; /* num of neighs for each point */
int *flags; /* vertex adjacency flags */
int total_targets; /* size of n_target */
+ int *border; /* indices of border pixels (only for texture paint) */
+ int total_border; /* size of border */
} PaintAdjData;
/***************************** General Utils ******************************/
@@ -822,6 +826,8 @@ static void dynamicPaint_freeAdjData(PaintSurfaceData *data)
MEM_freeN(data->adj_data->n_target);
if (data->adj_data->flags)
MEM_freeN(data->adj_data->flags);
+ if (data->adj_data->border)
+ MEM_freeN(data->adj_data->border);
MEM_freeN(data->adj_data);
data->adj_data = NULL;
}
@@ -1298,6 +1304,8 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, const b
ad->n_target = MEM_callocN(sizeof(int) * neigh_points, "Surface Adj Targets");
ad->flags = MEM_callocN(sizeof(int) * sData->total_points, "Surface Adj Flags");
ad->total_targets = neigh_points;
+ ad->border = NULL;
+ ad->total_border = 0;
/* in case of allocation error, free memory */
if (!ad->n_index || !ad->n_num || !ad->n_target || !temp_data) {
@@ -2295,6 +2303,36 @@ static void dynamic_paint_create_uv_surface_neighbor_cb(void *userdata, const in
#undef JITTER_SAMPLES
+static float dist_squared_to_looptri_uv_edges(const MLoopTri *mlooptri, const MLoopUV *mloopuv, int tri_index, const float point[2])
+{
+ float min_distance = FLT_MAX;
+
+ for (int i = 0; i < 3; i++) {
+ const float dist_squared = dist_squared_to_line_segment_v2(
+ point,
+ mloopuv[mlooptri[tri_index].tri[(i + 0)]].uv,
+ mloopuv[mlooptri[tri_index].tri[(i + 1) % 3]].uv
+ );
+
+ if (dist_squared < min_distance)
+ min_distance = dist_squared;
+ }
+
+ return min_distance;
+}
+
+typedef struct DynamicPaintFindIslandBorderData {
+ const MeshElemMap *vert_to_looptri_map;
+ int w, h, px, py;
+
+ int best_index;
+ float best_weight;
+} DynamicPaintFindIslandBorderData;
+
+static void dynamic_paint_find_island_border(
+ const DynamicPaintCreateUVSurfaceData *data, DynamicPaintFindIslandBorderData *bdata,
+ int tri_index, const float pixel[2], int in_edge, int depth);
+
/* Tries to find the neighboring pixel in given (uv space) direction.
* Result is used by effect system to move paint on the surface.
*
@@ -2345,167 +2383,162 @@ static int dynamic_paint_find_neighbour_pixel(
* TODO: Implement something more accurate / optimized?
*/
{
- const MLoop *mloop = data->mloop;
- const MLoopTri *mlooptri = data->mlooptri;
- const MLoopUV *mloopuv = data->mloopuv;
-
- /* Get closest edge to that subpixel on UV map */
+ DynamicPaintFindIslandBorderData bdata = {
+ .vert_to_looptri_map = vert_to_looptri_map,
+ .w = w, .h = h, .px = px, .py = py,
+ .best_index = NOT_FOUND, .best_weight = 1.0f
+ };
float pixel[2];
- /* distances only used for comparison */
- float dist_squared, t_dist_squared;
-
- int edge1_index, edge2_index;
- int e1_index, e2_index, target_tri;
- float closest_point[2], lambda, dir_vec[2];
- int target_uv1 = 0, target_uv2 = 0, final_pixel[2], final_index;
-
- const float *s_uv1, *s_uv2, *t_uv1, *t_uv2;
pixel[0] = ((float)(px + neighX[n_index]) + 0.5f) / (float)w;
pixel[1] = ((float)(py + neighY[n_index]) + 0.5f) / (float)h;
- /*
- * Find closest edge to that pixel
- */
+ /* Do a small recursive search for the best island edge. */
+ dynamic_paint_find_island_border(data, &bdata, cPoint->tri_index, pixel, -1, 5);
- /* Dist to first edge */
- e1_index = cPoint->v1;
- e2_index = cPoint->v2;
- edge1_index = 0;
- edge2_index = 1;
- dist_squared = dist_squared_to_line_segment_v2(
- pixel,
- mloopuv[mlooptri[cPoint->tri_index].tri[0]].uv,
- mloopuv[mlooptri[cPoint->tri_index].tri[1]].uv);
-
- /* Dist to second edge */
- t_dist_squared = dist_squared_to_line_segment_v2(
- pixel,
- mloopuv[mlooptri[cPoint->tri_index].tri[1]].uv,
- mloopuv[mlooptri[cPoint->tri_index].tri[2]].uv);
- if (t_dist_squared < dist_squared) {
- e1_index = cPoint->v2;
- e2_index = cPoint->v3;
- edge1_index = 1;
- edge2_index = 2;
- dist_squared = t_dist_squared;
- }
-
- /* Dist to third edge */
- t_dist_squared = dist_squared_to_line_segment_v2(
- pixel,
- mloopuv[mlooptri[cPoint->tri_index].tri[2]].uv,
- mloopuv[mlooptri[cPoint->tri_index].tri[0]].uv);
- if (t_dist_squared < dist_squared) {
- e1_index = cPoint->v3;
- e2_index = cPoint->v1;
- edge1_index = 2;
- edge2_index = 0;
- dist_squared = t_dist_squared;
- }
+ return bdata.best_index;
+ }
+}
- /*
- * Now find another face that is linked to that edge
- */
- target_tri = -1;
+static void dynamic_paint_find_island_border(
+ const DynamicPaintCreateUVSurfaceData *data, DynamicPaintFindIslandBorderData *bdata,
+ int tri_index, const float pixel[2], int in_edge, int depth)
+{
+ const MLoop *mloop = data->mloop;
+ const MLoopTri *mlooptri = data->mlooptri;
+ const MLoopUV *mloopuv = data->mloopuv;
- /* Use a pre-computed vert-to-looptri mapping, speeds up things a lot compared to looping over all loopti. */
- for (int i = 0; i < vert_to_looptri_map[e1_index].count; i++) {
- const int lt_index = vert_to_looptri_map[e1_index].indices[i];
- const int v0 = mloop[mlooptri[lt_index].tri[0]].v;
- const int v1 = mloop[mlooptri[lt_index].tri[1]].v;
- const int v2 = mloop[mlooptri[lt_index].tri[2]].v;
+ const unsigned int *loop_idx = mlooptri[tri_index].tri;
- BLI_assert(ELEM(e1_index, v0, v1, v2));
+ /* Enumerate all edges of the triangle, rotating the vertex list accordingly. */
+ for (int edge_idx = 0; edge_idx < 3; edge_idx++) {
+ /* but not the edge we have just recursed through */
+ if (edge_idx == in_edge)
+ continue;
- if (ELEM(e2_index, v0, v1, v2)) {
- if (lt_index == cPoint->tri_index)
- continue;
+ float uv0[2], uv1[2], uv2[2];
- target_tri = lt_index;
+ copy_v2_v2(uv0, mloopuv[loop_idx[(edge_idx + 0)]].uv);
+ copy_v2_v2(uv1, mloopuv[loop_idx[(edge_idx + 1) % 3]].uv);
+ copy_v2_v2(uv2, mloopuv[loop_idx[(edge_idx + 2) % 3]].uv);
- /* Get edge UV index */
- target_uv1 = (e1_index == v0) ? 0 : ((e1_index == v1) ? 1 : 2);
- target_uv2 = (e2_index == v0) ? 0 : ((e2_index == v1) ? 1 : 2);
- break;
- }
- }
+ /* Verify the target point is on the opposite side of the edge from the third triangle
+ * vertex, to ensure that we always move closer to the goal point. */
+ const float sidep = line_point_side_v2(uv0, uv1, pixel);
+ const float side2 = line_point_side_v2(uv0, uv1, uv2);
- /* If none found pixel is on mesh edge */
- if (target_tri == -1)
- return ON_MESH_EDGE;
+ if (side2 == 0.0f)
+ continue;
- /*
- * If target face is connected in UV space as well, just use original index
- */
- s_uv1 = mloopuv[mlooptri[cPoint->tri_index].tri[edge1_index]].uv;
- s_uv2 = mloopuv[mlooptri[cPoint->tri_index].tri[edge2_index]].uv;
- t_uv1 = mloopuv[mlooptri[target_tri].tri[target_uv1]].uv;
- t_uv2 = mloopuv[mlooptri[target_tri].tri[target_uv2]].uv;
+ /* Hack: allow all edges of the original triangle */
+ const bool correct_side = (in_edge == -1) || (sidep < 0 && side2 > 0) || (sidep > 0 && side2 < 0);
- //printf("connected UV : %f,%f & %f,%f - %f,%f & %f,%f\n", s_uv1[0], s_uv1[1], s_uv2[0], s_uv2[1], t_uv1[0], t_uv1[1], t_uv2[0], t_uv2[1]);
+ /* Allow exactly on edge for the non-recursive case */
+ if (!correct_side && sidep != 0.0f)
+ continue;
- if (((s_uv1[0] == t_uv1[0] && s_uv1[1] == t_uv1[1]) &&
- (s_uv2[0] == t_uv2[0] && s_uv2[1] == t_uv2[1])) ||
- ((s_uv2[0] == t_uv1[0] && s_uv2[1] == t_uv1[1]) &&
- (s_uv1[0] == t_uv2[0] && s_uv1[1] == t_uv2[1])))
- {
- final_index = x + w * y;
+ /* Now find another face that is linked to that edge. */
+ const int vert0 = mloop[loop_idx[(edge_idx + 0)]].v;
+ const int vert1 = mloop[loop_idx[(edge_idx + 1) % 3]].v;
+
+ /* Use a pre-computed vert-to-looptri mapping, speeds up things a lot compared to looping over all loopti. */
+ const MeshElemMap *map = &bdata->vert_to_looptri_map[vert0];
+
+ bool found_other = false;
+ int target_tri = -1;
+ int target_edge = -1;
+
+ float ouv0[2], ouv1[2];
+
+ for (int i = 0; i < map->count && !found_other; i++) {
+ const int lt_index = map->indices[i];
+
+ if (lt_index == tri_index)
+ continue;
+
+ const unsigned int *other_loop_idx = mlooptri[lt_index].tri;
+
+ /* Check edges for match, looping in the same order as the outer loop. */
+ for (int j = 0; j < 3; j++)
+ {
+ const int overt0 = mloop[other_loop_idx[(j + 0)]].v;
+ const int overt1 = mloop[other_loop_idx[(j + 1) % 3]].v;
+
+ /* Allow for swapped vertex order */
+ if (overt0 == vert0 && overt1 == vert1) {
+ found_other = true;
+ copy_v2_v2(ouv0, mloopuv[other_loop_idx[(j + 0)]].uv);
+ copy_v2_v2(ouv1, mloopuv[other_loop_idx[(j + 1) % 3]].uv);
+ }
+ else if (overt0 == vert1 && overt1 == vert0) {
+ found_other = true;
+ copy_v2_v2(ouv1, mloopuv[other_loop_idx[(j + 0)]].uv);
+ copy_v2_v2(ouv0, mloopuv[other_loop_idx[(j + 1) % 3]].uv);
+ }
+
+ if (found_other) {
+ target_tri = lt_index;
+ target_edge = j;
+ break;
+ }
+ }
+ }
- /* If not an active pixel, bail out */
- if (tempPoints[final_index].tri_index == -1)
- return NOT_FOUND;
+ if (!found_other) {
+ if (bdata->best_index < 0)
+ bdata->best_index = ON_MESH_EDGE;
- /* If final point is an "edge pixel", use it's "real" neighbor instead */
- if (tempPoints[final_index].neighbour_pixel != -1) {
- final_index = tempPoints[final_index].neighbour_pixel;
+ continue;
+ }
- /* If we ended up to our origin point */
- if (final_index == (px + w * py))
- return NOT_FOUND;
+ /* If this edge is connected in UV space too, recurse */
+ if (equals_v2v2(uv0, ouv0) && equals_v2v2(uv1, ouv1)) {
+ if (depth > 0 && correct_side) {
+ dynamic_paint_find_island_border(data, bdata, target_tri, pixel, target_edge, depth - 1);
}
- return final_index;
+ continue;
}
+ /* Otherwise try to map to the other side of the edge.
+ * First check if there already is a better solution. */
+ const float dist_squared = dist_squared_to_line_segment_v2(pixel, uv0, uv1);
+
+ if (bdata->best_index >= 0 && dist_squared >= bdata->best_weight)
+ continue;
+
/*
* Find a point that is relatively at same edge position
* on this other face UV
*/
- lambda = closest_to_line_v2(
- closest_point, pixel,
- mloopuv[mlooptri[cPoint->tri_index].tri[edge1_index]].uv,
- mloopuv[mlooptri[cPoint->tri_index].tri[edge2_index]].uv);
- CLAMP(lambda, 0.0f, 1.0f);
+ float closest_point[2], dir_vec[2], tgt_pixel[2];
- sub_v2_v2v2(
- dir_vec,
- mloopuv[mlooptri[target_tri].tri[target_uv2]].uv,
- mloopuv[mlooptri[target_tri].tri[target_uv1]].uv);
+ float lambda = closest_to_line_v2(closest_point, pixel, uv0, uv1);
+ CLAMP(lambda, 0.0f, 1.0f);
- mul_v2_fl(dir_vec, lambda);
+ sub_v2_v2v2(dir_vec, ouv1, ouv0);
+ madd_v2_v2v2fl(tgt_pixel, ouv0, dir_vec, lambda);
- copy_v2_v2(pixel, mloopuv[mlooptri[target_tri].tri[target_uv1]].uv);
- add_v2_v2(pixel, dir_vec);
- pixel[0] = (pixel[0] * (float)w);
- pixel[1] = (pixel[1] * (float)h);
+ int w = bdata->w, h = bdata->h, px = bdata->px, py = bdata->py;
- final_pixel[0] = (int)floorf(pixel[0]);
- final_pixel[1] = (int)floorf(pixel[1]);
+ int final_pixel[2] = { (int)floorf(tgt_pixel[0] * w), (int)floorf(tgt_pixel[1] * h) };
/* If current pixel uv is outside of texture */
if (final_pixel[0] < 0 || final_pixel[0] >= w || final_pixel[1] < 0 || final_pixel[1] >= h)
- return OUT_OF_TEXTURE;
+ {
+ if (bdata->best_index == NOT_FOUND)
+ bdata->best_index = OUT_OF_TEXTURE;
+
+ continue;
+ }
- final_index = final_pixel[0] + w * final_pixel[1];
+ const PaintUVPoint *tempPoints = data->tempPoints;
+ int final_index = final_pixel[0] + w * final_pixel[1];
/* If we ended up to our origin point ( mesh has smaller than pixel sized faces) */
if (final_index == (px + w * py))
- return NOT_FOUND;
- /* If found pixel still lies on wrong face ( mesh has smaller than pixel sized faces) */
- if (tempPoints[final_index].tri_index != target_tri)
- return NOT_FOUND;
+ continue;
/* If final point is an "edge pixel", use it's "real" neighbor instead */
if (tempPoints[final_index].neighbour_pixel != -1) {
@@ -2513,11 +2546,125 @@ static int dynamic_paint_find_neighbour_pixel(
/* If we ended up to our origin point */
if (final_index == (px + w * py))
- return NOT_FOUND;
+ continue;
+ }
+
+ /* If found pixel still lies on wrong face ( mesh has smaller than pixel sized faces) */
+ if (tempPoints[final_index].tri_index != target_tri) {
+ /* Check if it's close enough to likely touch the intended triangle. Any triangle
+ * becomes thinner than a pixel at its vertices, so robustness requires some margin. */
+ const float final_pt[2] = { ((final_index % w) + 0.5f) / w, ((final_index / w) + 0.5f) / h };
+ const float threshold = SQUARE(0.7f) / (w * h);
+
+ if (dist_squared_to_looptri_uv_edges(mlooptri, mloopuv, tempPoints[final_index].tri_index, final_pt) > threshold)
+ continue;
+ }
+
+ bdata->best_index = final_index;
+ bdata->best_weight = dist_squared;
+ }
+}
+
+static bool dynamicPaint_pointHasNeighbor(PaintAdjData *ed, int index, int neighbor)
+{
+ const int idx = ed->n_index[index];
+
+ for (int i = 0; i < ed->n_num[index]; i++) {
+ if (ed->n_target[idx + i] == neighbor) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* Makes the adjacency data symmetric, except for border pixels. I.e. if A is neighbor of B, B is neighbor of A. */
+static bool dynamicPaint_symmetrizeAdjData(PaintAdjData *ed, int active_points)
+{
+ int *new_n_index = MEM_callocN(sizeof(int) * active_points, "Surface Adj Index");
+ int *new_n_num = MEM_callocN(sizeof(int) * active_points, "Surface Adj Counts");
+
+ if (new_n_num && new_n_index) {
+ /* Count symmetrized neigbors */
+ int total_targets = 0;
+
+ for (int index = 0; index < active_points; index++) {
+ total_targets += ed->n_num[index];
+ new_n_num[index] = ed->n_num[index];
+ }
+
+ for (int index = 0; index < active_points; index++) {
+ if (ed->flags[index] & ADJ_BORDER_PIXEL) {
+ continue;
+ }
+
+ for (int i = 0, idx = ed->n_index[index]; i < ed->n_num[index]; i++) {
+ const int target = ed->n_target[idx + i];
+
+ assert(!(ed->flags[target] & ADJ_BORDER_PIXEL));
+
+ if (!dynamicPaint_pointHasNeighbor(ed, target, index)) {
+ new_n_num[target]++;
+ total_targets++;
+ }
+ }
}
- return final_index;
+ /* Allocate a new target map */
+ int *new_n_target = MEM_callocN(sizeof(int) * total_targets, "Surface Adj Targets");
+
+ if (new_n_target) {
+ /* Copy existing neighbors to the new map */
+ int n_pos = 0;
+
+ for (int index = 0; index < active_points; index++) {
+ new_n_index[index] = n_pos;
+ memcpy(&new_n_target[n_pos], &ed->n_target[ed->n_index[index]], sizeof(int) * ed->n_num[index]);
+
+ /* Reset count to old, but advance position by new, leaving a gap to fill below. */
+ n_pos += new_n_num[index];
+ new_n_num[index] = ed->n_num[index];
+ }
+
+ assert(n_pos == total_targets);
+
+ /* Add symmetrized - this loop behavior must exactly match the count pass above */
+ for (int index = 0; index < active_points; index++) {
+ if (ed->flags[index] & ADJ_BORDER_PIXEL) {
+ continue;
+ }
+
+ for (int i = 0, idx = ed->n_index[index]; i < ed->n_num[index]; i++) {
+ const int target = ed->n_target[idx + i];
+
+ if (!dynamicPaint_pointHasNeighbor(ed, target, index)) {
+ const int num = new_n_num[target]++;
+ new_n_target[new_n_index[target] + num] = index;
+ }
+ }
+ }
+
+ /* Swap maps */
+ MEM_freeN(ed->n_target);
+ ed->n_target = new_n_target;
+
+ MEM_freeN(ed->n_index);
+ ed->n_index = new_n_index;
+
+ MEM_freeN(ed->n_num);
+ ed->n_num = new_n_num;
+
+ ed->total_targets = total_targets;
+ return true;
+ }
}
+
+ if (new_n_index)
+ MEM_freeN(new_n_index);
+ if (new_n_num)
+ MEM_freeN(new_n_num);
+
+ return false;
}
int dynamicPaint_createUVSurface(Scene *scene, DynamicPaintSurface *surface, float *progress, short *do_update)
@@ -2668,30 +2815,28 @@ int dynamicPaint_createUVSurface(Scene *scene, DynamicPaintSurface *surface, flo
&vert_to_looptri_map, &vert_to_looptri_map_mem,
dm->getVertArray(dm), dm->getNumVerts(dm), mlooptri, tottri, mloop, dm->getNumLoops(dm));
+ int total_border = 0;
+
for (int ty = 0; ty < h; ty++) {
for (int tx = 0; tx < w; tx++) {
const int index = tx + w * ty;
if (tempPoints[index].tri_index != -1) {
- int start_pos = n_pos;
ed->n_index[final_index[index]] = n_pos;
ed->n_num[final_index[index]] = 0;
+ if (tempPoints[index].neighbour_pixel != -1) {
+ ed->flags[final_index[index]] |= ADJ_BORDER_PIXEL;
+ total_border++;
+ }
+
for (int i = 0; i < 8; i++) {
/* Try to find a neighboring pixel in defined direction. If not found, -1 is returned */
const int n_target = dynamic_paint_find_neighbour_pixel(
&data, vert_to_looptri_map, w, h, tx, ty, i);
if (n_target >= 0 && n_target != index) {
- bool duplicate = false;
- for (int j = start_pos; j < n_pos; j++) {
- if (ed->n_target[j] == final_index[n_target]) {
- duplicate = true;
- break;
- }
- }
-
- if (!duplicate) {
+ if (!dynamicPaint_pointHasNeighbor(ed, final_index[index], final_index[n_target])) {
ed->n_target[n_pos] = final_index[n_target];
ed->n_num[final_index[index]]++;
n_pos++;
@@ -2707,6 +2852,57 @@ int dynamicPaint_createUVSurface(Scene *scene, DynamicPaintSurface *surface, flo
MEM_freeN(vert_to_looptri_map);
MEM_freeN(vert_to_looptri_map_mem);
+
+ /* Make neighbors symmetric */
+ if (!dynamicPaint_symmetrizeAdjData(ed, active_points)) {
+ error = true;
+ }
+
+ /* Create a list of border pixels */
+ ed->border = MEM_callocN(sizeof(int) * total_border, "Border Pixel Index");
+
+ if (ed->border) {
+ ed->total_border = total_border;
+
+ for (int i = 0, next = 0; i < active_points; i++) {
+ if (ed->flags[i] & ADJ_BORDER_PIXEL) {
+ ed->border[next++] = i;
+ }
+ }
+ }
+
+#if 0
+ /* -----------------------------------------------------------------
+ * For debug, write a dump of adjacency data to a file.
+ * -----------------------------------------------------------------*/
+ FILE *dump_file = fopen("dynpaint-adj-data.txt", "w");
+ int *tmp = MEM_callocN(sizeof(int) * active_points, "tmp");
+ for (int ty = 0; ty < h; ty++) {
+ for (int tx = 0; tx < w; tx++) {
+ const int index = tx + w * ty;
+ if (tempPoints[index].tri_index != -1)
+ tmp[final_index[index]] = index;
+ }
+ }
+ for (int ty = 0; ty < h; ty++) {
+ for (int tx = 0; tx < w; tx++) {
+ const int index = tx + w * ty;
+ const int fidx = final_index[index];
+
+ if (tempPoints[index].tri_index != -1) {
+ int nidx = tempPoints[index].neighbour_pixel;
+ fprintf(dump_file, "%d\t%d,%d\t%u\t%d,%d\t%d\t", fidx, tx, h-1-ty, tempPoints[index].tri_index, nidx<0?-1:(nidx%w), nidx<0?-1:h-1-(nidx/w), ed->flags[fidx]);
+ for (int i = 0; i < ed->n_num[fidx]; i++) {
+ int tgt = tmp[ed->n_target[ed->n_index[fidx]+i]];
+ fprintf(dump_file, "%s%d,%d", i?" ":"", tgt%w, h-1-tgt/w);
+ }
+ fprintf(dump_file, "\n");
+ }
+ }
+ }
+ MEM_freeN(tmp);
+ fclose(dump_file);
+#endif
}
}
@@ -3739,7 +3935,7 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex(
/* velocity brush, only do on main sample */
if (brush->flags & MOD_DPAINT_USES_VELOCITY && ss == 0 && brushVelocity) {
- float weights[4];
+ float weights[3];
float brushPointVelocity[3];
float velocity[3];
@@ -3748,7 +3944,7 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex(
const int v3 = mloop[mlooptri[hitTri].tri[2]].v;
/* calculate barycentric weights for hit point */
- interp_weights_face_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, NULL, hitCoord);
+ interp_weights_tri_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, hitCoord);
/* simple check based on brush surface velocity,
* todo: perhaps implement something that handles volume movement as well */
@@ -4529,6 +4725,10 @@ static void dynamicPaint_doSmudge(DynamicPaintSurface *surface, DynamicPaintBrus
for (step = 0; step < steps; step++) {
for (index = 0; index < sData->total_points; index++) {
int i;
+
+ if (sData->adj_data->flags[index] & ADJ_BORDER_PIXEL)
+ continue;
+
PaintPoint *pPoint = &((PaintPoint *)sData->type_data)[index];
float smudge_str = bData->brush_velocity[index * 4 + 3];
@@ -4708,6 +4908,9 @@ static void dynamic_paint_effect_spread_cb(void *userdata, const int index)
const DynamicPaintSurface *surface = data->surface;
const PaintSurfaceData *sData = surface->data;
+ if (sData->adj_data->flags[index] & ADJ_BORDER_PIXEL)
+ return;
+
const int numOfNeighs = sData->adj_data->n_num[index];
BakeAdjPoint *bNeighs = sData->bData->bNeighs;
PaintPoint *pPoint = &((PaintPoint *)sData->type_data)[index];
@@ -4750,6 +4953,9 @@ static void dynamic_paint_effect_shrink_cb(void *userdata, const int index)
const DynamicPaintSurface *surface = data->surface;
const PaintSurfaceData *sData = surface->data;
+ if (sData->adj_data->flags[index] & ADJ_BORDER_PIXEL)
+ return;
+
const int numOfNeighs = sData->adj_data->n_num[index];
BakeAdjPoint *bNeighs = sData->bData->bNeighs;
PaintPoint *pPoint = &((PaintPoint *)sData->type_data)[index];
@@ -4796,6 +5002,10 @@ static void dynamic_paint_effect_drip_cb(void *userdata, const int index)
const DynamicPaintSurface *surface = data->surface;
const PaintSurfaceData *sData = surface->data;
+
+ if (sData->adj_data->flags[index] & ADJ_BORDER_PIXEL)
+ return;
+
BakeAdjPoint *bNeighs = sData->bData->bNeighs;
PaintPoint *pPoint = &((PaintPoint *)sData->type_data)[index];
const PaintPoint *prevPoint = data->prevPoint;
@@ -4964,6 +5174,80 @@ static void dynamicPaint_doEffectStep(
}
}
+static void dynamic_paint_border_cb(void *userdata, const int b_index)
+{
+ const DynamicPaintEffectData *data = userdata;
+
+ const DynamicPaintSurface *surface = data->surface;
+ const PaintSurfaceData *sData = surface->data;
+
+ const int index = sData->adj_data->border[b_index];
+
+ const int numOfNeighs = sData->adj_data->n_num[index];
+ PaintPoint *pPoint = &((PaintPoint *)sData->type_data)[index];
+
+ const int *n_index = sData->adj_data->n_index;
+ const int *n_target = sData->adj_data->n_target;
+
+ /* Average neighboring points. Intermediaries use premultiplied alpha. */
+ float mix_color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ float mix_e_color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ float mix_wetness = 0.0f;
+
+ for (int i = 0; i < numOfNeighs; i++) {
+ const int n_idx = n_index[index] + i;
+ const int target = n_target[n_idx];
+
+ PaintPoint *pPoint2 = &((PaintPoint *)sData->type_data)[target];
+
+ assert(!(sData->adj_data->flags[target] & ADJ_BORDER_PIXEL));
+
+ madd_v3_v3fl(mix_color, pPoint2->color, pPoint2->color[3]);
+ mix_color[3] += pPoint2->color[3];
+
+ madd_v3_v3fl(mix_e_color, pPoint2->e_color, pPoint2->e_color[3]);
+ mix_e_color[3] += pPoint2->e_color[3];
+
+ mix_wetness += pPoint2->wetness;
+ }
+
+ const float divisor = 1.0f / numOfNeighs;
+
+ if (mix_color[3]) {
+ pPoint->color[3] = mix_color[3] * divisor;
+ mul_v3_v3fl(pPoint->color, mix_color, divisor / pPoint->color[3]);
+ }
+ else {
+ pPoint->color[3] = 0.0f;
+ }
+
+ if (mix_e_color[3]) {
+ pPoint->e_color[3] = mix_e_color[3] * divisor;
+ mul_v3_v3fl(pPoint->e_color, mix_e_color, divisor / pPoint->e_color[3]);
+ }
+ else {
+ pPoint->e_color[3] = 0.0f;
+ }
+
+ pPoint->wetness = mix_wetness / numOfNeighs;
+}
+
+static void dynamicPaint_doBorderStep(DynamicPaintSurface *surface)
+{
+ PaintSurfaceData *sData = surface->data;
+
+ if (!sData->adj_data || !sData->adj_data->border)
+ return;
+
+ /* Don't use prevPoint, relying on the condition that neighbors are never border pixels. */
+ DynamicPaintEffectData data = {
+ .surface = surface
+ };
+
+ BLI_task_parallel_range(
+ 0, sData->adj_data->total_border, &data, dynamic_paint_border_cb, sData->adj_data->total_border > 1000);
+}
+
static void dynamic_paint_wave_step_cb(void *userdata, const int index)
{
const DynamicPaintEffectData *data = userdata;
@@ -5633,6 +5917,11 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
if (force)
MEM_freeN(force);
}
+
+ /* paint island border pixels */
+ if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
+ dynamicPaint_doBorderStep(surface);
+ }
}
return ret;
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index a89d423e7a6..c67a61a5aad 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -47,6 +47,7 @@
#include "BLI_math.h"
#include "BLI_easing.h"
#include "BLI_threads.h"
+#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
diff --git a/source/blender/blenkernel/intern/freestyle.c b/source/blender/blenkernel/intern/freestyle.c
index 21fc1674dc5..0a0b023df82 100644
--- a/source/blender/blenkernel/intern/freestyle.c
+++ b/source/blender/blenkernel/intern/freestyle.c
@@ -40,6 +40,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_string_utils.h"
// function declarations
static FreestyleLineSet *alloc_lineset(void);
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index cd2eac078cf..30fc8915d46 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -39,6 +39,7 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_math_vector.h"
+#include "BLI_string_utils.h"
#include "BLT_translation.h"
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
index 9b011dbb003..9c81a8b49be 100644
--- a/source/blender/blenkernel/intern/group.c
+++ b/source/blender/blenkernel/intern/group.c
@@ -130,18 +130,11 @@ static bool group_object_add_internal(Group *group, Object *ob)
return true;
}
-bool BKE_group_object_add(Group *group, Object *object, Scene *scene, Base *base)
+bool BKE_group_object_add(Group *group, Object *object)
{
if (group_object_add_internal(group, object)) {
if ((object->flag & OB_FROMGROUP) == 0) {
-
- if (scene && base == NULL)
- base = BKE_scene_base_find(scene, object);
-
object->flag |= OB_FROMGROUP;
-
- if (base)
- base->flag |= OB_FROMGROUP;
}
return true;
}
@@ -208,18 +201,12 @@ bool BKE_group_object_cyclic_check(Main *bmain, Object *object, Group *group)
return group_object_cyclic_check_internal(object, group);
}
-bool BKE_group_object_unlink(Group *group, Object *object, Scene *scene, Base *base)
+bool BKE_group_object_unlink(Group *group, Object *object)
{
if (group_object_unlink_internal(group, object)) {
/* object can be NULL */
if (object && BKE_group_object_find(NULL, object) == NULL) {
- if (scene && base == NULL)
- base = BKE_scene_base_find(scene, object);
-
object->flag &= ~OB_FROMGROUP;
-
- if (base)
- base->flag &= ~OB_FROMGROUP;
}
return true;
}
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index 730d5a93758..f3a85dcee2b 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -62,6 +62,7 @@
#include "BLI_blenlib.h"
#include "BLI_dynstr.h"
+#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index 6cdeaf5e59b..8a7c1dd2833 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -38,6 +38,7 @@
#include "BLI_blenlib.h"
#include "BLI_math_vector.h"
+#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index 9d8f9997de9..40cba304377 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -25,9 +25,9 @@
*/
#include "BLI_listbase.h"
-#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
+#include "BLI_string_utils.h"
#include "BLT_translation.h"
#include "BKE_collection.h"
@@ -44,8 +44,10 @@
#include "MEM_guardedalloc.h"
/* prototype */
-LayerCollection *layer_collection_add(SceneLayer *sl, ListBase *lb, SceneCollection *sc);
-void layer_collection_free(SceneLayer *sl, LayerCollection *lc);
+static void layer_collection_free(SceneLayer *sl, LayerCollection *lc);
+static LayerCollection *layer_collection_add(SceneLayer *sl, ListBase *lb, SceneCollection *sc);
+static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const SceneCollection *sc);
+static void object_bases_Iterator_next(Iterator *iter, const int flag);
/* RenderLayer */
@@ -134,6 +136,32 @@ void BKE_scene_layer_selected_objects_tag(SceneLayer *sl, const int tag)
}
}
+static bool find_scene_collection_in_scene_collections(ListBase *lb, const LayerCollection *lc)
+{
+ for (LayerCollection *lcn = lb->first; lcn; lcn = lcn->next) {
+ if (lcn == lc) {
+ return true;
+ }
+ if (find_scene_collection_in_scene_collections(&lcn->layer_collections, lc)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Find the SceneLayer a LayerCollection belongs to
+ */
+SceneLayer *BKE_scene_layer_find_from_collection(Scene *scene, LayerCollection *lc)
+{
+ for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+ if (find_scene_collection_in_scene_collections(&sl->layer_collections, lc)) {
+ return sl;
+ }
+ }
+ return false;
+}
+
/* ObjectBase */
ObjectBase *BKE_scene_layer_base_find(SceneLayer *sl, Object *ob)
@@ -152,8 +180,10 @@ void BKE_scene_layer_base_deselect_all(SceneLayer *sl)
void BKE_scene_layer_base_select(struct SceneLayer *sl, ObjectBase *selbase)
{
- selbase->flag |= BASE_SELECTED;
sl->basact = selbase;
+ if ((selbase->flag & BASE_SELECTABLED) != 0) {
+ selbase->flag |= BASE_SELECTED;
+ }
}
static void scene_layer_object_base_unref(SceneLayer* sl, ObjectBase *base)
@@ -171,6 +201,52 @@ static void scene_layer_object_base_unref(SceneLayer* sl, ObjectBase *base)
}
}
+static void layer_collection_base_flag_recalculate(LayerCollection *lc, const bool tree_is_visible, const bool tree_is_selectable)
+{
+ bool is_visible = tree_is_visible && ((lc->flag & COLLECTION_VISIBLE) != 0);
+ /* an object can only be selected if it's visible */
+ bool is_selectable = tree_is_selectable && is_visible && ((lc->flag & COLLECTION_SELECTABLE) != 0);
+
+ for (LinkData *link = lc->object_bases.first; link; link = link->next) {
+ ObjectBase *base = link->data;
+
+ if (is_visible) {
+ base->flag |= BASE_VISIBLED;
+ }
+ else {
+ base->flag &= ~BASE_VISIBLED;
+ }
+
+ if (is_selectable) {
+ base->flag |= BASE_SELECTABLED;
+ }
+ else {
+ base->flag &= ~BASE_SELECTABLED;
+ }
+ }
+
+ for (LayerCollection *lcn = lc->layer_collections.first; lcn; lcn = lcn->next) {
+ layer_collection_base_flag_recalculate(lcn, is_visible, is_selectable);
+ }
+}
+
+/**
+ * Re-evaluate the ObjectBase flags for SceneLayer
+ */
+void BKE_scene_layer_base_flag_recalculate(SceneLayer *sl)
+{
+ for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+ layer_collection_base_flag_recalculate(lc, true, true);
+ }
+
+ /* if base is not selectabled, clear select */
+ for (ObjectBase *base = sl->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_SELECTABLED) == 0) {
+ base->flag &= ~BASE_SELECTED;
+ }
+ }
+}
+
/**
* Return the base if existent, or create it if necessary
* Always bump the refcount
@@ -197,7 +273,7 @@ static ObjectBase *object_base_add(SceneLayer *sl, Object *ob)
* When freeing the entire SceneLayer at once we don't bother with unref
* otherwise SceneLayer is passed to keep the syncing of the LayerCollection tree
*/
-void layer_collection_free(SceneLayer *sl, LayerCollection *lc)
+static void layer_collection_free(SceneLayer *sl, LayerCollection *lc)
{
if (sl) {
for (LinkData *link = lc->object_bases.first; link; link = link->next) {
@@ -321,6 +397,7 @@ LayerCollection *BKE_collection_link(SceneLayer *sl, SceneCollection *sc)
void BKE_collection_unlink(SceneLayer *sl, LayerCollection *lc)
{
BKE_layer_collection_free(sl, lc);
+ BKE_scene_layer_base_flag_recalculate(sl);
BLI_remlink(&sl->layer_collections, lc);
MEM_freeN(lc);
@@ -338,6 +415,8 @@ static void layer_collection_object_add(SceneLayer *sl, LayerCollection *lc, Obj
return;
}
+ BKE_scene_layer_base_flag_recalculate(sl);
+
BLI_addtail(&lc->object_bases, BLI_genericNodeN(base));
}
@@ -370,7 +449,7 @@ static void layer_collection_populate(SceneLayer *sl, LayerCollection *lc, Scene
}
}
-LayerCollection *layer_collection_add(SceneLayer *sl, ListBase *lb, SceneCollection *sc)
+static LayerCollection *layer_collection_add(SceneLayer *sl, ListBase *lb, SceneCollection *sc)
{
LayerCollection *lc = MEM_callocN(sizeof(LayerCollection), "Collection Base");
BLI_addtail(lb, lc);
@@ -384,6 +463,36 @@ LayerCollection *layer_collection_add(SceneLayer *sl, ListBase *lb, SceneCollect
/* ---------------------------------------------------------------------- */
+
+/**
+ * See if render layer has the scene collection linked directly, or indirectly (nested)
+ */
+bool BKE_scene_layer_has_collection(struct SceneLayer *sl, struct SceneCollection *sc)
+{
+ for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+ if (find_layer_collection_by_scene_collection(lc, sc) != NULL) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * See if the object is in any of the scene layers of the scene
+ */
+bool BKE_scene_has_object(Scene *scene, Object *ob)
+{
+ for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+ ObjectBase *base = BKE_scene_layer_base_find(sl, ob);
+ if (base) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+/* ---------------------------------------------------------------------- */
/* Syncing */
static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const SceneCollection *sc)
@@ -444,6 +553,7 @@ void BKE_layer_sync_object_unlink(Scene *scene, SceneCollection *sc, Object *ob)
layer_collection_object_remove(sl, found, ob);
}
}
+ BKE_scene_layer_base_flag_recalculate(sl);
}
}
@@ -458,9 +568,10 @@ void BKE_collection_override_datablock_add(LayerCollection *UNUSED(lc), const ch
TODO_LAYER_OVERRIDE;
}
+/* ---------------------------------------------------------------------- */
/* Iterators */
-void BKE_selected_objects_Iterator_begin(Iterator *iter, void *data_in)
+static void object_bases_Iterator_begin(Iterator *iter, void *data_in, const int flag)
{
SceneLayer *sl = data_in;
ObjectBase *base = sl->object_bases.first;
@@ -474,32 +585,90 @@ void BKE_selected_objects_Iterator_begin(Iterator *iter, void *data_in)
iter->valid = true;
iter->data = base;
- if ((base->flag & BASE_SELECTED) == 0) {
- BKE_selected_objects_Iterator_next(iter);
+ if ((base->flag & flag) == 0) {
+ object_bases_Iterator_next(iter, flag);
}
else {
- iter->current = base->object;
+ iter->current = base;
}
}
-void BKE_selected_objects_Iterator_next(Iterator *iter)
+static void object_bases_Iterator_next(Iterator *iter, const int flag)
{
ObjectBase *base = ((ObjectBase *)iter->data)->next;
while (base) {
- if ((base->flag & BASE_SELECTED) != 0) {
- iter->current = base->object;
+ if ((base->flag & flag) != 0) {
+ iter->current = base;
iter->data = base;
return;
}
base = base->next;
- };
+ }
iter->current = NULL;
iter->valid = false;
}
+static void objects_Iterator_begin(Iterator *iter, void *data_in, const int flag)
+{
+ object_bases_Iterator_begin(iter, data_in, flag);
+
+ if (iter->valid) {
+ iter->current = ((ObjectBase *)iter->current)->object;
+ }
+}
+
+static void objects_Iterator_next(Iterator *iter, const int flag)
+{
+ object_bases_Iterator_next(iter, flag);
+
+ if (iter->valid) {
+ iter->current = ((ObjectBase *)iter->current)->object;
+ }
+}
+
+void BKE_selected_objects_Iterator_begin(Iterator *iter, void *data_in)
+{
+ objects_Iterator_begin(iter, data_in, BASE_SELECTED);
+}
+
+void BKE_selected_objects_Iterator_next(Iterator *iter)
+{
+ object_bases_Iterator_next(iter, BASE_SELECTED);
+}
+
void BKE_selected_objects_Iterator_end(Iterator *UNUSED(iter))
{
/* do nothing */
}
+
+void BKE_visible_objects_Iterator_begin(Iterator *iter, void *data_in)
+{
+ objects_Iterator_begin(iter, data_in, BASE_VISIBLED);
+}
+
+void BKE_visible_objects_Iterator_next(Iterator *iter)
+{
+ objects_Iterator_next(iter, BASE_VISIBLED);
+}
+
+void BKE_visible_objects_Iterator_end(Iterator *UNUSED(iter))
+{
+ /* do nothing */
+}
+
+void BKE_visible_bases_Iterator_begin(Iterator *iter, void *data_in)
+{
+ object_bases_Iterator_begin(iter, data_in, BASE_VISIBLED);
+}
+
+void BKE_visible_bases_Iterator_next(Iterator *iter)
+{
+ object_bases_Iterator_next(iter, BASE_VISIBLED);
+}
+
+void BKE_visible_bases_Iterator_end(Iterator *UNUSED(iter))
+{
+ /* do nothing */
+}
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 056e302eee2..de35d1e0eac 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -76,6 +76,7 @@
#include "BLI_ghash.h"
#include "BLI_linklist.h"
#include "BLI_memarena.h"
+#include "BLI_string_utils.h"
#include "BLI_threads.h"
#include "BLT_translation.h"
@@ -1407,7 +1408,8 @@ static ID *is_dupid(ListBase *lb, ID *id, const char *name)
static bool check_for_dupid(ListBase *lb, ID *id, char *name)
{
ID *idtest;
- int nr = 0, a, left_len;
+ int nr = 0, a;
+ size_t left_len;
#define MAX_IN_USE 64
bool in_use[MAX_IN_USE];
/* to speed up finding unused numbers within [1 .. MAX_IN_USE - 1] */
@@ -1441,7 +1443,7 @@ static bool check_for_dupid(ListBase *lb, ID *id, char *name)
/* Code above may have generated invalid utf-8 string, due to raw truncation.
* Ensure we get a valid one now! */
- left_len -= BLI_utf8_invalid_strip(left, left_len);
+ left_len -= (size_t)BLI_utf8_invalid_strip(left, left_len);
for (idtest = lb->first; idtest; idtest = idtest->next) {
int nrtest;
@@ -1483,7 +1485,7 @@ static bool check_for_dupid(ListBase *lb, ID *id, char *name)
* shave off the end chars until we have a unique name.
* Check the null terminators match as well so we don't get Cube.000 -> Cube.00 */
if (nr == 0 && name[left_len] == '\0') {
- int len;
+ size_t len;
/* FIXME: this code will never be executed, because either nr will be
* at least 1, or name will not end at left_len! */
BLI_assert(0);
diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c
index 44cf3d04203..df6440d89f8 100644
--- a/source/blender/blenkernel/intern/library_remap.c
+++ b/source/blender/blenkernel/intern/library_remap.c
@@ -255,7 +255,7 @@ static void libblock_remap_data_preprocess_scene_base_unlink(
}
}
-/* Some reamapping unfortunately require extra and/or specific handling, tackle those here. */
+/* Some remapping unfortunately require extra and/or specific handling, tackle those here. */
static void libblock_remap_data_preprocess_scene_object_unlink(
IDRemap *r_id_remap_data, Scene *sce, Object *ob, const bool skip_indirect, const bool is_indirect)
{
@@ -264,7 +264,7 @@ static void libblock_remap_data_preprocess_scene_object_unlink(
r_id_remap_data->skipped_refcounted++;
}
else {
- BKE_collections_object_remove(sce, ob);
+ BKE_collections_object_remove(r_id_remap_data->bmain, sce, ob, false);
if (!is_indirect) {
r_id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT;
}
@@ -354,7 +354,7 @@ static void libblock_remap_data_postprocess_object_fromgroup_update(Main *bmain,
}
if (new_ob == NULL) { /* We need to remove NULL-ified groupobjects... */
for (Group *group = bmain->group.first; group; group = group->id.next) {
- BKE_group_object_unlink(group, NULL, NULL, NULL);
+ BKE_group_object_unlink(group, NULL);
}
}
else {
@@ -368,22 +368,16 @@ static void libblock_remap_data_postprocess_group_scene_unlink(Main *UNUSED(bmai
/* Note that here we assume no object has no base (i.e. all objects are assumed instanced
* in one scene...). */
for (Base *base = sce->base.first; base; base = base->next) {
- if (base->flag & OB_FROMGROUP) {
- Object *ob = base->object;
-
- if (ob->flag & OB_FROMGROUP) {
- Group *grp = BKE_group_object_find(NULL, ob);
+ Object *ob = base->object;
+ if (ob->flag & OB_FROMGROUP) {
+ Group *grp = BKE_group_object_find(NULL, ob);
- /* Unlinked group (old_id) is still in bmain... */
- if (grp && (&grp->id == old_id || grp->id.us == 0)) {
- grp = BKE_group_object_find(grp, ob);
- }
- if (!grp) {
- ob->flag &= ~OB_FROMGROUP;
- }
+ /* Unlinked group (old_id) is still in bmain... */
+ if (grp && (&grp->id == old_id || grp->id.us == 0)) {
+ grp = BKE_group_object_find(grp, ob);
}
- if (!(ob->flag & OB_FROMGROUP)) {
- base->flag &= ~OB_FROMGROUP;
+ if (!grp) {
+ ob->flag &= ~OB_FROMGROUP;
}
}
}
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
index bd21215f91e..1eb909bd9f9 100644
--- a/source/blender/blenkernel/intern/linestyle.c
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -41,6 +41,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index 21023d9f53c..6f23b82c6df 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -36,8 +36,8 @@
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
-#include "BLI_path_util.h"
#include "BLI_string.h"
+#include "BLI_string_utils.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 8d024ea9aa5..33b1a9cdb9e 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -49,6 +49,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
#include "BKE_global.h"
@@ -358,27 +359,25 @@ void BKE_mball_properties_copy(Scene *scene, Object *active_object)
*/
Object *BKE_mball_basis_find(Scene *scene, Object *basis)
{
- Scene *sce_iter = scene;
- Base *base;
- Object *ob, *bob = basis;
+ Object *bob = basis;
int basisnr, obnr;
char basisname[MAX_ID_NAME], obname[MAX_ID_NAME];
- SceneBaseIter iter;
- EvaluationContext *eval_ctx = G.main->eval_ctx;
BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.');
- BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL);
- while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) {
- if ((ob->type == OB_MBALL) && !(base->flag & OB_FROMDUPLI)) {
- if (ob != bob) {
- BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
-
- /* object ob has to be in same "group" ... it means, that it has to have same base of its name */
- if (STREQ(obname, basisname)) {
- if (obnr < basisnr) {
- basis = ob;
- basisnr = obnr;
+ for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+ for (ObjectBase *base = sl->object_bases.first; base; base = base->next) {
+ Object *ob = base->object;
+ if ((ob->type == OB_MBALL) && !(base->flag & OB_FROMDUPLI)) {
+ if (ob != bob) {
+ BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
+
+ /* object ob has to be in same "group" ... it means, that it has to have same base of its name */
+ if (STREQ(obname, basisname)) {
+ if (obnr < basisnr) {
+ basis = ob;
+ basisnr = obnr;
+ }
}
}
}
diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c
index 2068854421f..5c0b09f0ff0 100644
--- a/source/blender/blenkernel/intern/mball_tessellate.c
+++ b/source/blender/blenkernel/intern/mball_tessellate.c
@@ -41,8 +41,8 @@
#include "DNA_scene_types.h"
#include "BLI_listbase.h"
-#include "BLI_path_util.h"
#include "BLI_math.h"
+#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
#include "BLI_memarena.h"
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index d21f43ac484..134173580ae 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -48,6 +48,7 @@
#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
+#include "BKE_mesh_render.h"
#include "BKE_displist.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
@@ -435,6 +436,8 @@ void BKE_mesh_free(Mesh *me)
{
BKE_animdata_free(&me->id, false);
+ BKE_mesh_batch_cache_free(me);
+
CustomData_free(&me->vdata, me->totvert);
CustomData_free(&me->edata, me->totedge);
CustomData_free(&me->fdata, me->totface);
@@ -522,6 +525,7 @@ Mesh *BKE_mesh_copy(Main *bmain, Mesh *me)
BKE_mesh_update_customdata_pointers(men, do_tessface);
men->edit_btmesh = NULL;
+ men->batch_cache = NULL;
men->mselect = MEM_dupallocN(men->mselect);
men->bb = MEM_dupallocN(men->bb);
@@ -2346,6 +2350,11 @@ Mesh *BKE_mesh_new_from_object(
tmpmesh = BKE_mesh_add(bmain, "Mesh");
DM_to_mesh(dm, tmpmesh, ob, mask, true);
+
+ /* Copy autosmooth settings from original mesh. */
+ Mesh *me = (Mesh *)ob->data;
+ tmpmesh->flag |= (me->flag & ME_AUTOSMOOTH);
+ tmpmesh->smoothresh = me->smoothresh;
}
/* BKE_mesh_add/copy gives us a user count we don't need */
diff --git a/source/blender/blenkernel/intern/mesh_render.c b/source/blender/blenkernel/intern/mesh_render.c
new file mode 100644
index 00000000000..f90783a3dbb
--- /dev/null
+++ b/source/blender/blenkernel/intern/mesh_render.c
@@ -0,0 +1,619 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2017 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, Mike Erwin, Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/mesh_render.c
+ * \ingroup bke
+ *
+ * \brief Mesh API for render engines
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BKE_customdata.h"
+#include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_editmesh.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_render.h"
+
+#include "GPU_batch.h"
+
+/* ---------------------------------------------------------------------- */
+/* Mesh Interface */
+
+#define MESH_RENDER_FUNCTION(func_name) \
+ if (me->edit_btmesh) { \
+ return mesh_bmesh_##func_name(me); \
+ } \
+ else { \
+ return mesh_struct_##func_name(me); \
+ }
+
+
+/* Mesh Implementation */
+
+static int mesh_struct_get_num_edges(Mesh *me)
+{
+ return me->totedge;
+}
+
+static int mesh_struct_get_num_verts(Mesh *me)
+{
+ return me->totvert;
+}
+
+static int mesh_struct_get_num_faces(Mesh *me)
+{
+ BKE_mesh_tessface_ensure(me);
+ return me->totface;
+}
+
+static int mesh_struct_get_num_polys(Mesh *me)
+{
+ return me->totpoly;
+}
+
+static MEdge *mesh_struct_get_array_edge(Mesh *me)
+{
+ return CustomData_get_layer(&me->edata, CD_MEDGE);
+}
+
+static MFace *mesh_struct_get_array_face(Mesh *me)
+{
+ BKE_mesh_tessface_ensure(me);
+ return CustomData_get_layer(&me->fdata, CD_MFACE);
+}
+
+static MLoop *mesh_struct_get_array_loop(Mesh *me)
+{
+ return me->mloop;
+}
+
+static MPoly *mesh_struct_get_array_poly(Mesh *me)
+{
+ return me->mpoly;
+}
+
+static MVert *mesh_struct_get_array_vert(Mesh *me)
+{
+ return CustomData_get_layer(&me->vdata, CD_MVERT);
+}
+
+/* BMesh Implementation */
+
+/* NOTE: we may want to get rid of Derived Mesh and
+ * access BMesh directly */
+
+static int mesh_bmesh_get_num_verts(Mesh *me)
+{
+ BMEditMesh *bm = me->edit_btmesh;
+ DerivedMesh *dm = bm->derivedFinal;
+ return dm->getNumVerts(dm);
+}
+
+static int mesh_bmesh_get_num_edges(Mesh *me)
+{
+ BMEditMesh *bm = me->edit_btmesh;
+ DerivedMesh *dm = bm->derivedFinal;
+ return dm->getNumEdges(dm);
+}
+
+static int mesh_bmesh_get_num_faces(Mesh *me)
+{
+ BMEditMesh *bm = me->edit_btmesh;
+ DerivedMesh *dm = bm->derivedFinal;
+ return dm->getNumTessFaces(dm);
+}
+
+static int mesh_bmesh_get_num_polys(Mesh *me)
+{
+ BMEditMesh *bm = me->edit_btmesh;
+ DerivedMesh *dm = bm->derivedFinal;
+ return dm->getNumPolys(dm);
+}
+
+static MEdge *mesh_bmesh_get_array_edge(Mesh *me)
+{
+ BMEditMesh *bm = me->edit_btmesh;
+ DerivedMesh *dm = bm->derivedFinal;
+ return dm->getEdgeArray(dm);
+}
+
+static MFace *mesh_bmesh_get_array_face(Mesh *me)
+{
+ BMEditMesh *bm = me->edit_btmesh;
+ DerivedMesh *dm = bm->derivedFinal;
+ return dm->getTessFaceArray(dm);
+}
+
+static MLoop *mesh_bmesh_get_array_loop(Mesh *me)
+{
+ BMEditMesh *bm = me->edit_btmesh;
+ DerivedMesh *dm = bm->derivedFinal;
+ return dm->getLoopArray(dm);
+}
+
+static MPoly *mesh_bmesh_get_array_poly(Mesh *me)
+{
+ BMEditMesh *bm = me->edit_btmesh;
+ DerivedMesh *dm = bm->derivedFinal;
+ return dm->getPolyArray(dm);
+}
+
+static MVert *mesh_bmesh_get_array_vert(Mesh *me)
+{
+ BMEditMesh *bm = me->edit_btmesh;
+ DerivedMesh *dm = bm->derivedFinal;
+ return dm->getVertArray(dm);
+}
+
+/* Mesh API */
+
+static int mesh_render_get_num_edges(Mesh *me)
+{
+ MESH_RENDER_FUNCTION(get_num_edges);
+}
+
+static int mesh_render_get_num_faces(Mesh *me)
+{
+ MESH_RENDER_FUNCTION(get_num_faces);
+}
+
+static int mesh_render_get_num_polys(Mesh *me)
+{
+ MESH_RENDER_FUNCTION(get_num_polys);
+}
+
+static int mesh_render_get_num_verts(Mesh *me)
+{
+ MESH_RENDER_FUNCTION(get_num_verts);
+}
+
+static MEdge *mesh_render_get_array_edge(Mesh *me)
+{
+ MESH_RENDER_FUNCTION(get_array_edge);
+}
+
+static MFace *mesh_render_get_array_face(Mesh *me)
+{
+ MESH_RENDER_FUNCTION(get_array_face);
+}
+
+static MLoop *mesh_render_get_array_loop(Mesh *me)
+{
+ MESH_RENDER_FUNCTION(get_array_loop);
+}
+
+static MPoly *mesh_render_get_array_poly(Mesh *me)
+{
+ MESH_RENDER_FUNCTION(get_array_poly);
+}
+
+static MVert *mesh_render_get_array_vert(Mesh *me)
+{
+ MESH_RENDER_FUNCTION(get_array_vert);
+}
+
+/* ---------------------------------------------------------------------- */
+/* Mesh Batch Cache */
+
+typedef struct MeshBatchCache {
+ VertexBuffer *pos_in_order;
+ ElementList *edges_in_order;
+ ElementList *triangles_in_order;
+
+ Batch *all_verts;
+ Batch *all_edges;
+ Batch *all_triangles;
+
+ Batch *fancy_edges; /* owns its vertex buffer (not shared) */
+ Batch *overlay_edges; /* owns its vertex buffer */
+
+ /* TODO: settings, before DEPSGRAPH update */
+ int tot_edges;
+ int tot_faces;
+ int tot_polys;
+ int tot_verts;
+ bool is_editmode;
+} MeshBatchCache;
+
+static bool mesh_batch_cache_valid(Mesh *me)
+{
+ MeshBatchCache *cache = me->batch_cache;
+
+ if (cache == NULL) {
+ return false;
+ }
+
+ if (cache->is_editmode != (me->edit_btmesh != NULL)) {
+ return false;
+ }
+
+ if (cache->is_editmode) {
+ DerivedMesh *dm = me->edit_btmesh->derivedFinal;
+ if ((dm->dirty & DM_MESH_BATCH_CACHE) == 0) {
+ return false;
+ }
+ }
+
+ /* TODO: temporary check, waiting for depsgraph update */
+ if ((cache->tot_edges != mesh_render_get_num_edges(me)) ||
+ (cache->tot_faces != mesh_render_get_num_faces(me)) ||
+ (cache->tot_polys != mesh_render_get_num_polys(me)) ||
+ (cache->tot_verts != mesh_render_get_num_verts(me)))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+static void mesh_batch_cache_init(Mesh *me)
+{
+ MeshBatchCache *cache = me->batch_cache;
+ cache->is_editmode = me->edit_btmesh != NULL;
+
+ cache->tot_edges = mesh_render_get_num_edges(me);
+ cache->tot_faces = mesh_render_get_num_faces(me);
+ cache->tot_polys = mesh_render_get_num_polys(me);
+ cache->tot_verts = mesh_render_get_num_verts(me);
+
+ if (cache->is_editmode) {
+ DerivedMesh *dm = me->edit_btmesh->derivedFinal;
+ dm->dirty |= DM_MESH_BATCH_CACHE;
+ }
+}
+
+static MeshBatchCache *mesh_batch_cache_get(Mesh *me)
+{
+ if (!mesh_batch_cache_valid(me)) {
+ BKE_mesh_batch_cache_free(me);
+ me->batch_cache = MEM_callocN(sizeof(MeshBatchCache), "MeshBatchCache");
+ mesh_batch_cache_init(me);
+ }
+ return me->batch_cache;
+}
+
+static VertexBuffer *mesh_batch_cache_get_pos_in_order(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->pos_in_order == NULL) {
+ static VertexFormat format = { 0 };
+ static unsigned pos_id;
+ if (format.attrib_ct == 0) {
+ /* initialize vertex format */
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ }
+
+ const int vertex_ct = mesh_render_get_num_verts(me);
+ const MVert *verts = mesh_render_get_array_vert(me);
+
+ cache->pos_in_order = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(cache->pos_in_order, vertex_ct);
+#if 0
+ const unsigned stride = (verts + 1) - verts; /* or sizeof(MVert) */
+ fillAttribStride(cache->pos_in_order, pos_id, stride, &verts[0].co);
+#else
+ for (int i = 0; i < vertex_ct; ++i) {
+ setAttrib(cache->pos_in_order, pos_id, i, &verts[i].co);
+ }
+#endif
+ }
+
+ return cache->pos_in_order;
+}
+
+static ElementList *mesh_batch_cache_get_edges_in_order(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->edges_in_order == NULL) {
+ const int vertex_ct = mesh_render_get_num_verts(me);
+ const int edge_ct = mesh_render_get_num_edges(me);
+ const MEdge *edges = mesh_render_get_array_edge(me);
+
+ ElementListBuilder elb;
+ ElementListBuilder_init(&elb, GL_LINES, edge_ct, vertex_ct);
+ for (int i = 0; i < edge_ct; ++i) {
+ const MEdge *edge = edges + i;
+ add_line_vertices(&elb, edge->v1, edge->v2);
+ }
+ cache->edges_in_order = ElementList_build(&elb);
+ }
+
+ return cache->edges_in_order;
+}
+
+static ElementList *mesh_batch_cache_get_triangles_in_order(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->triangles_in_order == NULL) {
+ const int vertex_ct = mesh_render_get_num_verts(me);
+ const int tessface_ct = mesh_render_get_num_faces(me);
+ MFace *tessfaces = mesh_render_get_array_face(me);
+
+ ElementListBuilder elb;
+ ElementListBuilder_init(&elb, GL_TRIANGLES, tessface_ct * 2, vertex_ct); /* up to 2 triangles per tessface */
+ for (int i = 0; i < tessface_ct; ++i) {
+ const MFace *tess = tessfaces + i;
+ add_triangle_vertices(&elb, tess->v1, tess->v2, tess->v3);
+
+ if (tess->v4) {
+ add_triangle_vertices(&elb, tess->v1, tess->v3, tess->v4);
+ }
+ }
+ cache->triangles_in_order = ElementList_build(&elb);
+ }
+
+ /* NOTE: we are reallocating, it would be interesting to reallocating the memory once we
+ * know the exactly triangle count (like in BKE_mesh_batch_cache_get_overlay_edges) */
+
+ return cache->triangles_in_order;
+}
+
+void BKE_mesh_batch_cache_free(Mesh *me)
+{
+ MeshBatchCache *cache = me->batch_cache;
+ if (!cache) {
+ return;
+ }
+
+ if (cache->all_verts) Batch_discard(cache->all_verts);
+ if (cache->all_edges) Batch_discard(cache->all_edges);
+ if (cache->all_triangles) Batch_discard(cache->all_triangles);
+
+ if (cache->pos_in_order) VertexBuffer_discard(cache->pos_in_order);
+ if (cache->edges_in_order) ElementList_discard(cache->edges_in_order);
+ if (cache->triangles_in_order) ElementList_discard(cache->triangles_in_order);
+
+ if (cache->fancy_edges) {
+ Batch_discard_all(cache->fancy_edges);
+ }
+
+ if (cache->overlay_edges) {
+ Batch_discard_all(cache->overlay_edges);
+ }
+
+ MEM_freeN(cache);
+ me->batch_cache = NULL;
+}
+
+Batch *BKE_mesh_batch_cache_get_all_edges(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->all_edges == NULL) {
+ /* create batch from Mesh */
+ cache->all_edges = Batch_create(GL_LINES, mesh_batch_cache_get_pos_in_order(me), mesh_batch_cache_get_edges_in_order(me));
+ }
+
+ return cache->all_edges;
+}
+
+Batch *BKE_mesh_batch_cache_get_all_triangles(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->all_triangles == NULL) {
+ /* create batch from DM */
+ cache->all_triangles = Batch_create(GL_TRIANGLES, mesh_batch_cache_get_pos_in_order(me), mesh_batch_cache_get_triangles_in_order(me));
+ }
+
+ return cache->all_triangles;
+}
+
+Batch *BKE_mesh_batch_cache_get_all_verts(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->all_verts == NULL) {
+ /* create batch from DM */
+ cache->all_verts = Batch_create(GL_POINTS, mesh_batch_cache_get_pos_in_order(me), NULL);
+ Batch_set_builtin_program(cache->all_verts, GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR);
+ }
+
+ return cache->all_verts;
+}
+
+Batch *BKE_mesh_batch_cache_get_fancy_edges(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->fancy_edges == NULL) {
+ /* create batch from DM */
+ static VertexFormat format = { 0 };
+ static unsigned pos_id, n1_id, n2_id;
+ if (format.attrib_ct == 0) {
+ /* initialize vertex format */
+ pos_id = add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
+
+#if USE_10_10_10 /* takes 1/3 the space */
+ n1_id = add_attrib(&format, "N1", COMP_I10, 3, NORMALIZE_INT_TO_FLOAT);
+ n2_id = add_attrib(&format, "N2", COMP_I10, 3, NORMALIZE_INT_TO_FLOAT);
+#else
+ n1_id = add_attrib(&format, "N1", COMP_F32, 3, KEEP_FLOAT);
+ n2_id = add_attrib(&format, "N2", COMP_F32, 3, KEEP_FLOAT);
+#endif
+ }
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+
+ const MVert *verts = mesh_render_get_array_vert(me);
+ const MEdge *edges = mesh_render_get_array_edge(me);
+ const MPoly *polys = mesh_render_get_array_poly(me);
+ const MLoop *loops = mesh_render_get_array_loop(me);
+ const int edge_ct = mesh_render_get_num_edges(me);
+ const int poly_ct = mesh_render_get_num_polys(me);
+
+ /* need normal of each face, and which faces are adjacent to each edge */
+ typedef struct {
+ int count;
+ int face_index[2];
+ } AdjacentFaces;
+
+ float (*face_normal)[3] = MEM_mallocN(poly_ct * 3 * sizeof(float), "face_normal");
+ AdjacentFaces *adj_faces = MEM_callocN(edge_ct * sizeof(AdjacentFaces), "adj_faces");
+
+ for (int i = 0; i < poly_ct; ++i) {
+ const MPoly *poly = polys + i;
+
+ BKE_mesh_calc_poly_normal(poly, loops + poly->loopstart, verts, face_normal[i]);
+
+ for (int j = poly->loopstart; j < (poly->loopstart + poly->totloop); ++j) {
+ AdjacentFaces *adj = adj_faces + loops[j].e;
+ if (adj->count < 2)
+ adj->face_index[adj->count] = i;
+ adj->count++;
+ }
+ }
+
+ const int vertex_ct = edge_ct * 2; /* these are GL_LINE verts, not mesh verts */
+ VertexBuffer_allocate_data(vbo, vertex_ct);
+ for (int i = 0; i < edge_ct; ++i) {
+ const MEdge *edge = edges + i;
+ const AdjacentFaces *adj = adj_faces + i;
+
+#if USE_10_10_10
+ PackedNormal n1value = { .x = 0, .y = 0, .z = +511 };
+ PackedNormal n2value = { .x = 0, .y = 0, .z = -511 };
+
+ if (adj->count == 2) {
+ n1value = convert_i10_v3(face_normal[adj->face_index[0]]);
+ n2value = convert_i10_v3(face_normal[adj->face_index[1]]);
+ }
+
+ const PackedNormal *n1 = &n1value;
+ const PackedNormal *n2 = &n2value;
+#else
+ const float dummy1[3] = { 0.0f, 0.0f, +1.0f };
+ const float dummy2[3] = { 0.0f, 0.0f, -1.0f };
+
+ const float *n1 = (adj->count == 2) ? face_normal[adj->face_index[0]] : dummy1;
+ const float *n2 = (adj->count == 2) ? face_normal[adj->face_index[1]] : dummy2;
+#endif
+
+ setAttrib(vbo, pos_id, 2 * i, &verts[edge->v1].co);
+ setAttrib(vbo, n1_id, 2 * i, n1);
+ setAttrib(vbo, n2_id, 2 * i, n2);
+
+ setAttrib(vbo, pos_id, 2 * i + 1, &verts[edge->v2].co);
+ setAttrib(vbo, n1_id, 2 * i + 1, n1);
+ setAttrib(vbo, n2_id, 2 * i + 1, n2);
+ }
+
+ MEM_freeN(adj_faces);
+ MEM_freeN(face_normal);
+
+ cache->fancy_edges = Batch_create(GL_LINES, vbo, NULL);
+ }
+
+ return cache->fancy_edges;
+}
+
+static bool edge_is_real(const MEdge *edges, int edge_ct, int v1, int v2)
+{
+ /* TODO: same thing, except not ridiculously slow */
+
+ for (int e = 0; e < edge_ct; ++e) {
+ const MEdge *edge = edges + e;
+ if ((edge->v1 == v1 && edge->v2 == v2) || (edge->v1 == v2 && edge->v2 == v1)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static void add_overlay_tri(
+ VertexBuffer *vbo, unsigned pos_id, unsigned edgeMod_id, const MVert *verts,
+ const MEdge *edges, int edge_ct, int v1, int v2, int v3, int base_vert_idx)
+{
+ const float edgeMods[2] = { 0.0f, 1.0f };
+
+ const float *pos = verts[v1].co;
+ setAttrib(vbo, pos_id, base_vert_idx + 0, pos);
+ setAttrib(vbo, edgeMod_id, base_vert_idx + 0, edgeMods + (edge_is_real(edges, edge_ct, v2, v3) ? 1 : 0));
+
+ pos = verts[v2].co;
+ setAttrib(vbo, pos_id, base_vert_idx + 1, pos);
+ setAttrib(vbo, edgeMod_id, base_vert_idx + 1, edgeMods + (edge_is_real(edges, edge_ct, v3, v1) ? 1 : 0));
+
+ pos = verts[v3].co;
+ setAttrib(vbo, pos_id, base_vert_idx + 2, pos);
+ setAttrib(vbo, edgeMod_id, base_vert_idx + 2, edgeMods + (edge_is_real(edges, edge_ct, v1, v2) ? 1 : 0));
+}
+
+Batch *BKE_mesh_batch_cache_get_overlay_edges(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->overlay_edges == NULL) {
+ /* create batch from DM */
+ static VertexFormat format = { 0 };
+ static unsigned pos_id, edgeMod_id;
+
+ if (format.attrib_ct == 0) {
+ /* initialize vertex format */
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ edgeMod_id = add_attrib(&format, "edgeWidthModulator", GL_FLOAT, 1, KEEP_FLOAT);
+ }
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+
+ const int edge_ct = mesh_render_get_num_edges(me);
+ const int tessface_ct = mesh_render_get_num_faces(me);
+ const MVert *verts = mesh_render_get_array_vert(me);
+ const MEdge *edges = mesh_render_get_array_edge(me);
+ const MFace *tessfaces = mesh_render_get_array_face(me);
+
+ VertexBuffer_allocate_data(vbo, tessface_ct * 6); /* up to 2 triangles per tessface */
+
+ int gpu_vert_idx = 0;
+ for (int i = 0; i < tessface_ct; ++i) {
+ const MFace *tess = tessfaces + i;
+ add_overlay_tri(vbo, pos_id, edgeMod_id, verts, edges, edge_ct, tess->v1, tess->v2, tess->v3, gpu_vert_idx);
+ gpu_vert_idx += 3;
+ /* tessface can be triangle or quad */
+ if (tess->v4) {
+ add_overlay_tri(vbo, pos_id, edgeMod_id, verts, edges, edge_ct, tess->v3, tess->v2, tess->v4, gpu_vert_idx);
+ gpu_vert_idx += 3;
+ }
+ }
+
+ /* in some cases all the faces are quad, so no need to reallocate */
+ if (vbo->vertex_ct != gpu_vert_idx) {
+ VertexBuffer_resize_data(vbo, gpu_vert_idx);
+ }
+
+ cache->overlay_edges = Batch_create(GL_TRIANGLES, vbo, NULL);
+ }
+
+ return cache->overlay_edges;
+}
+
+#undef MESH_RENDER_FUNCTION
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 41e4c21d814..2276d56b9c6 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -49,10 +49,11 @@
#include "DNA_object_types.h"
#include "BLI_utildefines.h"
-#include "BLI_path_util.h"
#include "BLI_listbase.h"
#include "BLI_linklist.h"
+#include "BLI_path_util.h"
#include "BLI_string.h"
+#include "BLI_string_utils.h"
#include "BLT_translation.h"
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index c321bc92a71..148fc3827e0 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -40,9 +40,9 @@
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
-#include "BLI_path_util.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
+#include "BLI_string_utils.h"
#include "BLI_ghash.h"
#include "BLT_translation.h"
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index cb3bc399ed0..05422a01dbf 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -46,10 +46,11 @@
#include "DNA_world_types.h"
#include "DNA_linestyle_types.h"
-#include "BLI_string.h"
-#include "BLI_math.h"
#include "BLI_listbase.h"
+#include "BLI_math.h"
#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 81110df9352..ffa82f33d25 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -3495,18 +3495,11 @@ struct LinkNode *BKE_object_groups(Object *ob)
return group_linknode;
}
-void BKE_object_groups_clear(Scene *scene, Base *base, Object *object)
+void BKE_object_groups_clear(Object *ob)
{
Group *group = NULL;
-
- BLI_assert((base == NULL) || (base->object == object));
-
- if (scene && base == NULL) {
- base = BKE_scene_base_find(scene, object);
- }
-
- while ((group = BKE_group_object_find(group, base->object))) {
- BKE_group_object_unlink(group, object, scene, base);
+ while ((group = BKE_group_object_find(group, ob))) {
+ BKE_group_object_unlink(group, ob);
}
}
diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c
index b5e1ded35bb..ccf2aec5c7a 100644
--- a/source/blender/blenkernel/intern/object_deform.c
+++ b/source/blender/blenkernel/intern/object_deform.c
@@ -32,6 +32,7 @@
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "BLI_listbase.h"
+#include "BLI_string_utils.h"
#include "DNA_armature_types.h"
#include "DNA_cloth_types.h"
@@ -623,7 +624,7 @@ void BKE_object_defgroup_mirror_selection(
if (dg_selection[i]) {
char name_flip[MAXBONENAME];
- BKE_deform_flip_side_name(name_flip, defgroup->name, false);
+ BLI_string_flip_side_name(name_flip, defgroup->name, false, sizeof(name_flip));
i_mirr = STREQ(name_flip, defgroup->name) ? i : defgroup_name_index(ob, name_flip);
if ((i_mirr >= 0 && i_mirr < defbase_tot) && (dg_flags_sel[i_mirr] == false)) {
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index 5cb704e4737..047de18d5b5 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -60,11 +60,7 @@
#include "DEG_depsgraph.h"
-#ifdef WITH_LEGACY_DEPSGRAPH
-# define DEBUG_PRINT if (!DEG_depsgraph_use_legacy() && G.debug & G_DEBUG_DEPSGRAPH) printf
-#else
-# define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
-#endif
+#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
static ThreadMutex material_lock = BLI_MUTEX_INITIALIZER;
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 36a8219579e..4b2c9204d7b 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -56,6 +56,7 @@
#include "BLI_utildefines.h"
#include "BLI_callbacks.h"
#include "BLI_string.h"
+#include "BLI_string_utils.h"
#include "BLI_threads.h"
#include "BLI_task.h"
@@ -372,13 +373,16 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
ts->imapaint.paintcursor = NULL;
id_us_plus((ID *)ts->imapaint.stencil);
ts->particle.paintcursor = NULL;
+
/* duplicate Grease Pencil Drawing Brushes */
BLI_listbase_clear(&ts->gp_brushes);
for (bGPDbrush *brush = sce->toolsettings->gp_brushes.first; brush; brush = brush->next) {
bGPDbrush *newbrush = BKE_gpencil_brush_duplicate(brush);
BLI_addtail(&ts->gp_brushes, newbrush);
}
-
+
+ /* duplicate Grease Pencil interpolation curve */
+ ts->gp_interpolate.custom_ipo = curvemapping_copy(ts->gp_interpolate.custom_ipo);
}
/* make a private copy of the avicodecdata */
@@ -525,12 +529,17 @@ void BKE_scene_free(Scene *sce)
BKE_paint_free(&sce->toolsettings->uvsculpt->paint);
MEM_freeN(sce->toolsettings->uvsculpt);
}
+ BKE_paint_free(&sce->toolsettings->imapaint.paint);
+
/* free Grease Pencil Drawing Brushes */
BKE_gpencil_free_brushes(&sce->toolsettings->gp_brushes);
BLI_freelistN(&sce->toolsettings->gp_brushes);
-
- BKE_paint_free(&sce->toolsettings->imapaint.paint);
-
+
+ /* free Grease Pencil interpolation curve */
+ if (sce->toolsettings->gp_interpolate.custom_ipo) {
+ curvemapping_free(sce->toolsettings->gp_interpolate.custom_ipo);
+ }
+
MEM_freeN(sce->toolsettings);
sce->toolsettings = NULL;
}
@@ -964,7 +973,6 @@ void BKE_scene_set_background(Main *bmain, Scene *scene)
Object *ob;
Group *group;
GroupObject *go;
- int flag;
/* check for cyclic sets, for reading old files but also for definite security (py?) */
BKE_scene_validate_setscene(bmain, scene);
@@ -996,13 +1004,7 @@ void BKE_scene_set_background(Main *bmain, Scene *scene)
ob->lay = base->lay;
/* group patch... */
- base->flag &= ~(OB_FROMGROUP);
- flag = ob->flag & (OB_FROMGROUP);
- base->flag |= flag;
-
- /* not too nice... for recovering objects with lost data */
- //if (ob->pose == NULL) base->flag &= ~OB_POSEMODE;
- ob->flag = base->flag;
+ BKE_scene_base_flag_sync_from_base(base);
}
/* no full animation update, this to enable render code to work (render code calls own animation updates) */
}
@@ -1290,7 +1292,9 @@ void BKE_scene_base_deselect_all(Scene *sce)
for (b = sce->base.first; b; b = b->next) {
b->flag &= ~SELECT;
+ int flag = b->object->flag & (OB_FROMGROUP);
b->object->flag = b->flag;
+ b->object->flag |= flag;
}
}
@@ -1351,109 +1355,6 @@ void BKE_scene_frame_set(struct Scene *scene, double cfra)
scene->r.cfra = (int)intpart;
}
-#ifdef WITH_LEGACY_DEPSGRAPH
-/* drivers support/hacks
- * - this method is called from scene_update_tagged_recursive(), so gets included in viewport + render
- * - these are always run since the depsgraph can't handle non-object data
- * - these happen after objects are all done so that we can read in their final transform values,
- * though this means that objects can't refer to scene info for guidance...
- */
-static void scene_update_drivers(Main *UNUSED(bmain), Scene *scene)
-{
- SceneRenderLayer *srl;
- float ctime = BKE_scene_frame_get(scene);
-
- /* scene itself */
- if (scene->adt && scene->adt->drivers.first) {
- BKE_animsys_evaluate_animdata(scene, &scene->id, scene->adt, ctime, ADT_RECALC_DRIVERS);
- }
-
- /* world */
- /* TODO: what about world textures? but then those have nodes too... */
- if (scene->world) {
- ID *wid = (ID *)scene->world;
- AnimData *adt = BKE_animdata_from_id(wid);
-
- if (adt && adt->drivers.first)
- BKE_animsys_evaluate_animdata(scene, wid, adt, ctime, ADT_RECALC_DRIVERS);
- }
-
- /* nodes */
- if (scene->nodetree) {
- ID *nid = (ID *)scene->nodetree;
- AnimData *adt = BKE_animdata_from_id(nid);
-
- if (adt && adt->drivers.first)
- BKE_animsys_evaluate_animdata(scene, nid, adt, ctime, ADT_RECALC_DRIVERS);
- }
-
- /* world nodes */
- if (scene->world && scene->world->nodetree) {
- ID *nid = (ID *)scene->world->nodetree;
- AnimData *adt = BKE_animdata_from_id(nid);
-
- if (adt && adt->drivers.first)
- BKE_animsys_evaluate_animdata(scene, nid, adt, ctime, ADT_RECALC_DRIVERS);
- }
-
- /* freestyle */
- for (srl = scene->r.layers.first; srl; srl = srl->next) {
- FreestyleConfig *config = &srl->freestyleConfig;
- FreestyleLineSet *lineset;
-
- for (lineset = config->linesets.first; lineset; lineset = lineset->next) {
- if (lineset->linestyle) {
- ID *lid = &lineset->linestyle->id;
- AnimData *adt = BKE_animdata_from_id(lid);
-
- if (adt && adt->drivers.first)
- BKE_animsys_evaluate_animdata(scene, lid, adt, ctime, ADT_RECALC_DRIVERS);
- }
- }
- }
-}
-
-/* deps hack - do extra recalcs at end */
-static void scene_depsgraph_hack(EvaluationContext *eval_ctx, Scene *scene, Scene *scene_parent)
-{
- Base *base;
-
- scene->customdata_mask = scene_parent->customdata_mask;
-
- /* sets first, we allow per definition current scene to have
- * dependencies on sets, but not the other way around. */
- if (scene->set)
- scene_depsgraph_hack(eval_ctx, scene->set, scene_parent);
-
- for (base = scene->base.first; base; base = base->next) {
- Object *ob = base->object;
-
- if (ob->depsflag) {
- int recalc = 0;
- // printf("depshack %s\n", ob->id.name + 2);
-
- if (ob->depsflag & OB_DEPS_EXTRA_OB_RECALC)
- recalc |= OB_RECALC_OB;
- if (ob->depsflag & OB_DEPS_EXTRA_DATA_RECALC)
- recalc |= OB_RECALC_DATA;
-
- ob->recalc |= recalc;
- BKE_object_handle_update(eval_ctx, scene_parent, ob);
-
- if (ob->dup_group && (ob->transflag & OB_DUPLIGROUP)) {
- GroupObject *go;
-
- for (go = ob->dup_group->gobject.first; go; go = go->next) {
- if (go->ob)
- go->ob->recalc |= recalc;
- }
- BKE_group_handle_recalc_and_update(eval_ctx, scene_parent, ob, ob->dup_group);
- }
- }
- }
-}
-#endif /* WITH_LEGACY_DEPSGRAPH */
-
/* That's like really a bummer, because currently animation data for armatures
* might want to use pose, and pose might be missing on the object.
* This happens when changing visible layers, which leads to situations when
@@ -1482,350 +1383,6 @@ static void scene_armature_depsgraph_workaround(Main *bmain)
}
#endif
-#ifdef WITH_LEGACY_DEPSGRAPH
-static void scene_rebuild_rbw_recursive(Scene *scene, float ctime)
-{
- if (scene->set)
- scene_rebuild_rbw_recursive(scene->set, ctime);
-
- if (BKE_scene_check_rigidbody_active(scene))
- BKE_rigidbody_rebuild_world(scene, ctime);
-}
-
-static void scene_do_rb_simulation_recursive(Scene *scene, float ctime)
-{
- if (scene->set)
- scene_do_rb_simulation_recursive(scene->set, ctime);
-
- if (BKE_scene_check_rigidbody_active(scene))
- BKE_rigidbody_do_simulation(scene, ctime);
-}
-#endif
-
-/* Used to visualize CPU threads activity during threaded object update,
- * would pollute STDERR with whole bunch of timing information which then
- * could be parsed and nicely visualized.
- */
-#ifdef WITH_LEGACY_DEPSGRAPH
-# undef DETAILED_ANALYSIS_OUTPUT
-#else
-/* ALWAYS KEEY DISABLED! */
-# undef DETAILED_ANALYSIS_OUTPUT
-#endif
-
-/* Mballs evaluation uses BKE_scene_base_iter_next which calls
- * duplilist for all objects in the scene. This leads to conflict
- * accessing and writing same data from multiple threads.
- *
- * Ideally Mballs shouldn't do such an iteration and use DAG
- * queries instead. For the time being we've got new DAG
- * let's keep it simple and update mballs in a single thread.
- */
-#define MBALL_SINGLETHREAD_HACK
-
-#ifdef WITH_LEGACY_DEPSGRAPH
-typedef struct StatisicsEntry {
- struct StatisicsEntry *next, *prev;
- Object *object;
- double start_time;
- double duration;
-} StatisicsEntry;
-
-typedef struct ThreadedObjectUpdateState {
- /* TODO(sergey): We might want this to be per-thread object. */
- EvaluationContext *eval_ctx;
- Scene *scene;
- Scene *scene_parent;
- double base_time;
-
-#ifdef MBALL_SINGLETHREAD_HACK
- bool has_mballs;
-#endif
-
- /* Execution statistics */
- bool has_updated_objects;
- ListBase *statistics;
-} ThreadedObjectUpdateState;
-
-static void scene_update_object_add_task(void *node, void *user_data);
-
-static void scene_update_all_bases(EvaluationContext *eval_ctx, Scene *scene, Scene *scene_parent)
-{
- Base *base;
-
- for (base = scene->base.first; base; base = base->next) {
- Object *object = base->object;
-
- BKE_object_handle_update_ex(eval_ctx, scene_parent, object, scene->rigidbody_world, true);
-
- if (object->dup_group && (object->transflag & OB_DUPLIGROUP))
- BKE_group_handle_recalc_and_update(eval_ctx, scene_parent, object, object->dup_group);
-
- /* always update layer, so that animating layers works (joshua july 2010) */
- /* XXX commented out, this has depsgraph issues anyway - and this breaks setting scenes
- * (on scene-set, the base-lay is copied to ob-lay (ton nov 2012) */
- // base->lay = ob->lay;
- }
-}
-
-static void scene_update_object_func(TaskPool * __restrict pool, void *taskdata, int threadid)
-{
-/* Disable print for now in favor of summary statistics at the end of update. */
-#define PRINT if (false) printf
-
- ThreadedObjectUpdateState *state = (ThreadedObjectUpdateState *) BLI_task_pool_userdata(pool);
- void *node = taskdata;
- Object *object = DAG_get_node_object(node);
- EvaluationContext *eval_ctx = state->eval_ctx;
- Scene *scene = state->scene;
- Scene *scene_parent = state->scene_parent;
-
-#ifdef MBALL_SINGLETHREAD_HACK
- if (object && object->type == OB_MBALL) {
- state->has_mballs = true;
- }
- else
-#endif
- if (object) {
- double start_time = 0.0;
- bool add_to_stats = false;
-
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- if (object->recalc & OB_RECALC_ALL) {
- printf("Thread %d: update object %s\n", threadid, object->id.name);
- }
-
- start_time = PIL_check_seconds_timer();
-
- if (object->recalc & OB_RECALC_ALL) {
- state->has_updated_objects = true;
- add_to_stats = true;
- }
- }
-
- /* We only update object itself here, dupli-group will be updated
- * separately from main thread because of we've got no idea about
- * dependencies inside the group.
- */
- BKE_object_handle_update_ex(eval_ctx, scene_parent, object, scene->rigidbody_world, false);
-
- /* Calculate statistics. */
- if (add_to_stats) {
- StatisicsEntry *entry;
-
- BLI_assert(threadid < BLI_pool_get_num_threads(pool));
-
- entry = MEM_mallocN(sizeof(StatisicsEntry), "update thread statistics");
- entry->object = object;
- entry->start_time = start_time;
- entry->duration = PIL_check_seconds_timer() - start_time;
-
- BLI_addtail(&state->statistics[threadid], entry);
- }
- }
- else {
- PRINT("Threda %d: update node %s\n", threadid,
- DAG_get_node_name(scene, node));
- }
-
- /* Update will decrease child's valency and schedule child with zero valency. */
- DAG_threaded_update_handle_node_updated(node, scene_update_object_add_task, pool);
-
-#undef PRINT
-}
-
-static void scene_update_object_add_task(void *node, void *user_data)
-{
- TaskPool *task_pool = user_data;
-
- BLI_task_pool_push(task_pool, scene_update_object_func, node, false, TASK_PRIORITY_LOW);
-}
-
-static void print_threads_statistics(ThreadedObjectUpdateState *state)
-{
- int i, tot_thread;
- double finish_time;
-
- if ((G.debug & G_DEBUG_DEPSGRAPH) == 0) {
- return;
- }
-
-#ifdef DETAILED_ANALYSIS_OUTPUT
- if (state->has_updated_objects) {
- tot_thread = BLI_system_thread_count();
-
- fprintf(stderr, "objects update base time %f\n", state->base_time);
-
- for (i = 0; i < tot_thread; i++) {
- StatisicsEntry *entry;
- for (entry = state->statistics[i].first;
- entry;
- entry = entry->next)
- {
- fprintf(stderr, "thread %d object %s start_time %f duration %f\n",
- i, entry->object->id.name + 2,
- entry->start_time, entry->duration);
- }
- BLI_freelistN(&state->statistics[i]);
- }
- }
-#else
- finish_time = PIL_check_seconds_timer();
- tot_thread = BLI_system_thread_count();
- int total_objects = 0;
-
- for (i = 0; i < tot_thread; i++) {
- int thread_total_objects = 0;
- double thread_total_time = 0.0;
- StatisicsEntry *entry;
-
- if (state->has_updated_objects) {
- /* Don't pollute output if no objects were updated. */
- for (entry = state->statistics[i].first;
- entry;
- entry = entry->next)
- {
- thread_total_objects++;
- thread_total_time += entry->duration;
- }
-
- printf("Thread %d: total %d objects in %f sec.\n",
- i,
- thread_total_objects,
- thread_total_time);
-
- for (entry = state->statistics[i].first;
- entry;
- entry = entry->next)
- {
- printf(" %s in %f sec\n", entry->object->id.name + 2, entry->duration);
- }
-
- total_objects += thread_total_objects;
- }
-
- BLI_freelistN(&state->statistics[i]);
- }
- if (state->has_updated_objects) {
- printf("Scene updated %d objects in %f sec\n",
- total_objects,
- finish_time - state->base_time);
- }
-#endif
-}
-
-static bool scene_need_update_objects(Main *bmain)
-{
- return
- /* Object datablocks themselves (for OB_RECALC_OB) */
- DAG_id_type_tagged(bmain, ID_OB) ||
-
- /* Objects data datablocks (for OB_RECALC_DATA) */
- DAG_id_type_tagged(bmain, ID_ME) || /* Mesh */
- DAG_id_type_tagged(bmain, ID_CU) || /* Curve */
- DAG_id_type_tagged(bmain, ID_MB) || /* MetaBall */
- DAG_id_type_tagged(bmain, ID_LA) || /* Lamp */
- DAG_id_type_tagged(bmain, ID_LT) || /* Lattice */
- DAG_id_type_tagged(bmain, ID_CA) || /* Camera */
- DAG_id_type_tagged(bmain, ID_KE) || /* KE */
- DAG_id_type_tagged(bmain, ID_SPK) || /* Speaker */
- DAG_id_type_tagged(bmain, ID_AR); /* Armature */
-}
-
-static void scene_update_objects(EvaluationContext *eval_ctx, Main *bmain, Scene *scene, Scene *scene_parent)
-{
- TaskScheduler *task_scheduler = BLI_task_scheduler_get();
- TaskPool *task_pool;
- ThreadedObjectUpdateState state;
- bool need_singlethread_pass;
-
- /* Early check for whether we need to invoke all the task-based
- * things (spawn new ppol, traverse dependency graph and so on).
- *
- * Basically if there's no ID datablocks tagged for update which
- * corresponds to object->recalc flags (which are checked in
- * BKE_object_handle_update() then we do nothing here.
- */
- if (!scene_need_update_objects(bmain)) {
- return;
- }
-
- state.eval_ctx = eval_ctx;
- state.scene = scene;
- state.scene_parent = scene_parent;
-
- /* Those are only needed when blender is run with --debug argument. */
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- const int tot_thread = BLI_task_scheduler_num_threads(task_scheduler);
- state.statistics = MEM_callocN(tot_thread * sizeof(*state.statistics),
- "scene update objects stats");
- state.has_updated_objects = false;
- state.base_time = PIL_check_seconds_timer();
- }
-
-#ifdef MBALL_SINGLETHREAD_HACK
- state.has_mballs = false;
-#endif
-
- task_pool = BLI_task_pool_create(task_scheduler, &state);
- if (G.debug & G_DEBUG_DEPSGRAPH_NO_THREADS) {
- BLI_pool_set_num_threads(task_pool, 1);
- }
-
- DAG_threaded_update_begin(scene, scene_update_object_add_task, task_pool);
- BLI_task_pool_work_and_wait(task_pool);
- BLI_task_pool_free(task_pool);
-
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- print_threads_statistics(&state);
- MEM_freeN(state.statistics);
- }
-
- /* We do single thread pass to update all the objects which are in cyclic dependency.
- * Such objects can not be handled by a generic DAG traverse and it's really tricky
- * to detect whether cycle could be solved or not.
- *
- * In this situation we simply update all remaining objects in a single thread and
- * it'll happen in the same exact order as it was in single-threaded DAG.
- *
- * We couldn't use threaded update for objects which are in cycle because they might
- * access data of each other which is being re-evaluated.
- *
- * Also, as was explained above, for now we also update all the mballs in single thread.
- *
- * - sergey -
- */
- need_singlethread_pass = DAG_is_acyclic(scene) == false;
-#ifdef MBALL_SINGLETHREAD_HACK
- need_singlethread_pass |= state.has_mballs;
-#endif
-
- if (need_singlethread_pass) {
- scene_update_all_bases(eval_ctx, scene, scene_parent);
- }
-}
-
-static void scene_update_tagged_recursive(EvaluationContext *eval_ctx, Main *bmain, Scene *scene, Scene *scene_parent)
-{
- scene->customdata_mask = scene_parent->customdata_mask;
-
- /* sets first, we allow per definition current scene to have
- * dependencies on sets, but not the other way around. */
- if (scene->set)
- scene_update_tagged_recursive(eval_ctx, bmain, scene->set, scene_parent);
-
- /* scene objects */
- scene_update_objects(eval_ctx, bmain, scene, scene_parent);
-
- /* scene drivers... */
- scene_update_drivers(bmain, scene);
-
- /* update masking curves */
- BKE_mask_update_scene(bmain, scene);
-
-}
-#endif /* WITH_LEGACY_DEPSGRAPH */
-
static bool check_rendered_viewport_visible(Main *bmain)
{
wmWindowManager *wm = bmain->wm.first;
@@ -1876,9 +1433,6 @@ static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene)
void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *scene)
{
Scene *sce_iter;
-#ifdef WITH_LEGACY_DEPSGRAPH
- bool use_new_eval = !DEG_depsgraph_use_legacy();
-#endif
/* keep this first */
BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_SCENE_UPDATE_PRE);
@@ -1888,12 +1442,7 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc
DAG_scene_relations_update(bmain, sce_iter);
/* Uncomment this to check if graph was properly tagged for update. */
#if 0
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (use_new_eval)
-#endif
- {
- DAG_scene_relations_validate(bmain, sce_iter);
- }
+ DAG_scene_relations_validate(bmain, sce_iter);
#endif
}
@@ -1916,17 +1465,9 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc
*
* in the future this should handle updates for all datablocks, not
* only objects and scenes. - brecht */
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (!use_new_eval) {
- scene_update_tagged_recursive(eval_ctx, bmain, scene, scene);
- }
- else
-#endif
- {
- DEG_evaluate_on_refresh(eval_ctx, scene->depsgraph, scene);
- /* TODO(sergey): This is to beocme a node in new depsgraph. */
- BKE_mask_update_scene(bmain, scene);
- }
+ DEG_evaluate_on_refresh(eval_ctx, scene->depsgraph, scene);
+ /* TODO(sergey): This is to beocme a node in new depsgraph. */
+ BKE_mask_update_scene(bmain, scene);
/* update sound system animation (TODO, move to depsgraph) */
BKE_sound_update_scene(bmain, scene);
@@ -1940,40 +1481,6 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc
BKE_animsys_evaluate_animdata(scene, &scene->id, adt, ctime, 0);
}
- /* Extra call here to recalc material animation.
- *
- * Need to do this so changing material settings from the graph/dopesheet
- * will update stuff in the viewport.
- */
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (!use_new_eval && DAG_id_type_tagged(bmain, ID_MA)) {
- Material *material;
- float ctime = BKE_scene_frame_get(scene);
-
- for (material = bmain->mat.first;
- material;
- material = material->id.next)
- {
- AnimData *adt = BKE_animdata_from_id(&material->id);
- if (adt && (adt->recalc & ADT_RECALC_ANIM))
- BKE_animsys_evaluate_animdata(scene, &material->id, adt, ctime, 0);
- }
- }
-
- /* Also do the same for node trees. */
- if (!use_new_eval && DAG_id_type_tagged(bmain, ID_NT)) {
- float ctime = BKE_scene_frame_get(scene);
-
- FOREACH_NODETREE(bmain, ntree, id)
- {
- AnimData *adt = BKE_animdata_from_id(&ntree->id);
- if (adt && (adt->recalc & ADT_RECALC_ANIM))
- BKE_animsys_evaluate_animdata(scene, &ntree->id, adt, ctime, 0);
- }
- FOREACH_NODETREE_END
- }
-#endif
-
/* notify editors and python about recalc */
BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_SCENE_UPDATE_POST);
@@ -1990,19 +1497,10 @@ void BKE_scene_update_for_newframe(EvaluationContext *eval_ctx, Main *bmain, Sce
BKE_scene_update_for_newframe_ex(eval_ctx, bmain, sce, lay, false);
}
-void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain, Scene *sce, unsigned int lay, bool do_invisible_flush)
+void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain, Scene *sce, unsigned int lay, bool UNUSED(do_invisible_flush))
{
float ctime = BKE_scene_frame_get(sce);
Scene *sce_iter;
-#ifdef DETAILED_ANALYSIS_OUTPUT
- double start_time = PIL_check_seconds_timer();
-#endif
-#ifdef WITH_LEGACY_DEPSGRAPH
- bool use_new_eval = !DEG_depsgraph_use_legacy();
-#else
- /* TODO(sergey): Pass to evaluation routines instead of storing layer in the graph? */
- (void) do_invisible_flush;
-#endif
DAG_editors_update_pre(bmain, sce, true);
@@ -2013,38 +1511,15 @@ void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain,
/* update animated image textures for particles, modifiers, gpu, etc,
* call this at the start so modifiers with textures don't lag 1 frame */
BKE_image_update_frame(bmain, sce->r.cfra);
-
-#ifdef WITH_LEGACY_DEPSGRAPH
- /* rebuild rigid body worlds before doing the actual frame update
- * this needs to be done on start frame but animation playback usually starts one frame later
- * we need to do it here to avoid rebuilding the world on every simulation change, which can be very expensive
- */
- if (!use_new_eval) {
- scene_rebuild_rbw_recursive(sce, ctime);
- }
-#endif
-
+
BKE_sound_set_cfra(sce->r.cfra);
-
+
/* clear animation overrides */
/* XXX TODO... */
for (sce_iter = sce; sce_iter; sce_iter = sce_iter->set)
DAG_scene_relations_update(bmain, sce_iter);
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (!use_new_eval) {
- /* flush recalc flags to dependencies, if we were only changing a frame
- * this would not be necessary, but if a user or a script has modified
- * some datablock before BKE_scene_update_tagged was called, we need the flush */
- DAG_ids_flush_tagged(bmain);
-
- /* Following 2 functions are recursive
- * so don't call within 'scene_update_tagged_recursive' */
- DAG_scene_update_flags(bmain, sce, lay, true, do_invisible_flush); // only stuff that moves or needs display still
- }
-#endif
-
BKE_mask_evaluate_all_masks(bmain, ctime, true);
/* Update animated cache files for modifiers. */
@@ -2054,54 +1529,18 @@ void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain,
scene_armature_depsgraph_workaround(bmain);
#endif
- /* All 'standard' (i.e. without any dependencies) animation is handled here,
- * with an 'local' to 'macro' order of evaluation. This should ensure that
- * settings stored nestled within a hierarchy (i.e. settings in a Texture block
- * can be overridden by settings from Scene, which owns the Texture through a hierarchy
- * such as Scene->World->MTex/Texture) can still get correctly overridden.
- */
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (!use_new_eval) {
- BKE_animsys_evaluate_all_animation(bmain, sce, ctime);
- /*...done with recursive funcs */
- }
-#endif
-
/* clear "LIB_TAG_DOIT" flag from all materials, to prevent infinite recursion problems later
* when trying to find materials with drivers that need evaluating [#32017]
*/
BKE_main_id_tag_idcode(bmain, ID_MA, LIB_TAG_DOIT, false);
BKE_main_id_tag_idcode(bmain, ID_LA, LIB_TAG_DOIT, false);
- /* run rigidbody sim */
- /* NOTE: current position is so that rigidbody sim affects other objects, might change in the future */
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (!use_new_eval) {
- scene_do_rb_simulation_recursive(sce, ctime);
- }
-#endif
-
/* BKE_object_handle_update() on all objects, groups and sets */
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (use_new_eval) {
- DEG_evaluate_on_framechange(eval_ctx, bmain, sce->depsgraph, ctime, lay);
- }
- else {
- scene_update_tagged_recursive(eval_ctx, bmain, sce, sce);
- }
-#else
DEG_evaluate_on_framechange(eval_ctx, bmain, sce->depsgraph, ctime, lay);
-#endif
/* update sound system animation (TODO, move to depsgraph) */
BKE_sound_update_scene(bmain, sce);
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (!use_new_eval) {
- scene_depsgraph_hack(eval_ctx, sce, sce);
- }
-#endif
-
/* notify editors and python about recalc */
BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_SCENE_UPDATE_POST);
BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_FRAME_CHANGE_POST);
@@ -2111,10 +1550,6 @@ void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain,
/* clear recalc flags */
DAG_ids_clear_recalc(bmain);
-
-#ifdef DETAILED_ANALYSIS_OUTPUT
- fprintf(stderr, "frame update start_time %f duration %f\n", start_time, PIL_check_seconds_timer() - start_time);
-#endif
}
/* return default layer, also used to patch old files */
@@ -2313,7 +1748,7 @@ void BKE_scene_base_flag_to_objects(struct Scene *scene)
Base *base = scene->base.first;
while (base) {
- base->object->flag = base->flag;
+ BKE_scene_base_flag_sync_from_base(base);
base = base->next;
}
}
@@ -2323,11 +1758,43 @@ void BKE_scene_base_flag_from_objects(struct Scene *scene)
Base *base = scene->base.first;
while (base) {
- base->flag = base->object->flag;
+ BKE_scene_base_flag_sync_from_object(base);
base = base->next;
}
}
+void BKE_scene_base_flag_sync_from_base(Base *base)
+{
+ Object *ob = base->object;
+
+ /* keep the object only flags untouched */
+ int flag = ob->flag & OB_FROMGROUP;
+
+ ob->flag = base->flag;
+ ob->flag |= flag;
+}
+
+void BKE_scene_base_flag_sync_from_object(Base *base)
+{
+ base->flag = base->object->flag;
+}
+
+void BKE_scene_object_base_flag_sync_from_base(ObjectBase *base)
+{
+ Object *ob = base->object;
+
+ /* keep the object only flags untouched */
+ int flag = ob->flag & OB_FROMGROUP;
+
+ ob->flag = base->flag;
+ ob->flag |= flag;
+}
+
+void BKE_scene_object_base_flag_sync_from_object(ObjectBase *base)
+{
+ base->flag = base->object->flag;
+}
+
void BKE_scene_disable_color_management(Scene *scene)
{
ColorManagedDisplaySettings *display_settings = &scene->display_settings;
diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c
index 95c6b7736e1..89c2f76c661 100644
--- a/source/blender/blenkernel/intern/seqmodifier.c
+++ b/source/blender/blenkernel/intern/seqmodifier.c
@@ -34,8 +34,8 @@
#include "MEM_guardedalloc.h"
#include "BLI_listbase.h"
-#include "BLI_path_util.h"
#include "BLI_string.h"
+#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index e8970d416e9..d0ef5cfc092 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -758,15 +758,14 @@ static void obstacles_from_derivedmesh_task_cb(void *userdata, const int z)
/* find the nearest point on the mesh */
if (BLI_bvhtree_find_nearest(data->tree->tree, ray_start, &nearest, data->tree->nearest_callback, data->tree) != -1) {
const MLoopTri *lt = &data->looptri[nearest.index];
- float weights[4];
+ float weights[3];
int v1, v2, v3;
/* calculate barycentric weights for nearest point */
v1 = data->mloop[lt->tri[0]].v;
v2 = data->mloop[lt->tri[1]].v;
v3 = data->mloop[lt->tri[2]].v;
- interp_weights_face_v3(
- weights, data->mvert[v1].co, data->mvert[v2].co, data->mvert[v3].co, NULL, nearest.co);
+ interp_weights_tri_v3(weights, data->mvert[v1].co, data->mvert[v2].co, data->mvert[v3].co, nearest.co);
// DG TODO
if (data->has_velocity)
@@ -1454,7 +1453,7 @@ static void sample_derivedmesh(
/* find the nearest point on the mesh */
if (BLI_bvhtree_find_nearest(treeData->tree, ray_start, &nearest, treeData->nearest_callback, treeData) != -1) {
- float weights[4];
+ float weights[3];
int v1, v2, v3, f_index = nearest.index;
float n1[3], n2[3], n3[3], hit_normal[3];
@@ -1471,7 +1470,7 @@ static void sample_derivedmesh(
v1 = mloop[mlooptri[f_index].tri[0]].v;
v2 = mloop[mlooptri[f_index].tri[1]].v;
v3 = mloop[mlooptri[f_index].tri[2]].v;
- interp_weights_face_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, NULL, nearest.co);
+ interp_weights_tri_v3(weights, mvert[v1].co, mvert[v2].co, mvert[v3].co, nearest.co);
if (sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && velocity_map) {
/* apply normal directional velocity */
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 672857e88fe..88575c7d3be 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -235,8 +235,9 @@ Text *BKE_text_add(Main *bmain, const char *name)
/* to a valid utf-8 sequences */
int txt_extended_ascii_as_utf8(char **str)
{
- int bad_char, added = 0, i = 0;
- int length = strlen(*str);
+ ptrdiff_t bad_char, i = 0;
+ const ptrdiff_t length = (ptrdiff_t)strlen(*str);
+ int added = 0;
while ((*str)[i]) {
if ((bad_char = BLI_utf8_invalid_byte(*str + i, length - i)) == -1)
@@ -248,7 +249,7 @@ int txt_extended_ascii_as_utf8(char **str)
if (added != 0) {
char *newstr = MEM_mallocN(length + added + 1, "text_line");
- int mi = 0;
+ ptrdiff_t mi = 0;
i = 0;
while ((*str)[i]) {
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index 96ab8693122..990d250b854 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -49,8 +49,8 @@
#include "BLI_math.h"
#include "BLI_math_base.h"
#include "BLI_listbase.h"
-#include "BLI_path_util.h"
#include "BLI_string.h"
+#include "BLI_string_utils.h"
#include "BLI_threads.h"
#include "BLT_translation.h"
diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c
index a90b1dee927..1c056cda68d 100644
--- a/source/blender/blenkernel/intern/tracking_util.c
+++ b/source/blender/blenkernel/intern/tracking_util.c
@@ -42,8 +42,8 @@
#include "BLI_math.h"
#include "BLI_listbase.h"
#include "BLI_ghash.h"
-#include "BLI_path_util.h"
#include "BLI_string.h"
+#include "BLI_string_utils.h"
#include "BLT_translation.h"
@@ -625,17 +625,17 @@ static ImBuf *make_grayscale_ibuf_copy(ImBuf *ibuf)
*/
size = (size_t)grayscale->x * (size_t)grayscale->y * sizeof(float);
grayscale->channels = 1;
- if ((grayscale->rect_float = MEM_mapallocN(size, "tracking grayscale image"))) {
+ if ((grayscale->rect_float = MEM_mapallocN(size, "tracking grayscale image")) != NULL) {
grayscale->mall |= IB_rectfloat;
grayscale->flags |= IB_rectfloat;
- }
- for (i = 0; i < grayscale->x * grayscale->y; ++i) {
- const float *pixel = ibuf->rect_float + ibuf->channels * i;
+ for (i = 0; i < grayscale->x * grayscale->y; ++i) {
+ const float *pixel = ibuf->rect_float + ibuf->channels * i;
- grayscale->rect_float[i] = 0.2126f * pixel[0] +
- 0.7152f * pixel[1] +
- 0.0722f * pixel[2];
+ grayscale->rect_float[i] = 0.2126f * pixel[0] +
+ 0.7152f * pixel[1] +
+ 0.0722f * pixel[2];
+ }
}
return grayscale;
@@ -653,14 +653,14 @@ static void ibuf_to_float_image(const ImBuf *ibuf, libmv_FloatImage *float_image
static ImBuf *float_image_to_ibuf(libmv_FloatImage *float_image)
{
ImBuf *ibuf = IMB_allocImBuf(float_image->width, float_image->height, 32, 0);
- size_t size = (size_t)ibuf->x * (size_t)ibuf->y *
- float_image->channels * sizeof(float);
+ size_t size = (size_t)ibuf->x * (size_t)ibuf->y * float_image->channels * sizeof(float);
ibuf->channels = float_image->channels;
- if ((ibuf->rect_float = MEM_mapallocN(size, "tracking grayscale image"))) {
+ if ((ibuf->rect_float = MEM_mapallocN(size, "tracking grayscale image")) != NULL) {
ibuf->mall |= IB_rectfloat;
ibuf->flags |= IB_rectfloat;
+
+ memcpy(ibuf->rect_float, float_image->buffer, size);
}
- memcpy(ibuf->rect_float, float_image->buffer, size);
return ibuf;
}
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index b5007b29f4c..e3635be671f 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -323,10 +323,8 @@ bool clip_segment_v3_plane_n(
float r_p1[3], float r_p2[3]);
/****************************** Interpolation ********************************/
-
-/* tri or quad, d can be NULL */
-void interp_weights_face_v3(float w[4],
- const float a[3], const float b[3], const float c[3], const float d[3], const float p[3]);
+void interp_weights_tri_v3(float w[3], const float a[3], const float b[3], const float c[3], const float p[3]);
+void interp_weights_quad_v3(float w[4], const float a[3], const float b[3], const float c[3], const float d[3], const float p[3]);
void interp_weights_poly_v3(float w[], float v[][3], const int n, const float co[3]);
void interp_weights_poly_v2(float w[], float v[][2], const int n, const float co[2]);
@@ -391,6 +389,8 @@ void box_minmax_bounds_m4(float min[3], float max[3],
void map_to_tube(float *r_u, float *r_v, const float x, const float y, const float z);
void map_to_sphere(float *r_u, float *r_v, const float x, const float y, const float z);
+void map_to_plane_v2_v3v3(float r_co[2], const float co[3], const float no[3]);
+void map_to_plane_axis_angle_v2_v3v3fl(float r_co[2], const float co[3], const float axis[3], const float angle);
/********************************** Normals **********************************/
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index 2bf3747c41d..dc9432fef64 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -123,7 +123,7 @@ MINLINE void mul_v4_fl(float r[4], float f);
MINLINE void mul_v4_v4fl(float r[3], const float a[3], float f);
MINLINE void mul_v2_v2_cw(float r[2], const float mat[2], const float vec[2]);
MINLINE void mul_v2_v2_ccw(float r[2], const float mat[2], const float vec[2]);
-MINLINE float mul_project_m4_v3_zfac(float mat[4][4], const float co[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE float mul_project_m4_v3_zfac(const float mat[4][4], const float co[3]) ATTR_WARN_UNUSED_RESULT;
MINLINE float dot_m3_v3_row_x(float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT;
MINLINE float dot_m3_v3_row_y(float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT;
MINLINE float dot_m3_v3_row_z(float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT;
diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h
index 1a626ff44bd..baa1f792018 100644
--- a/source/blender/blenlib/BLI_path_util.h
+++ b/source/blender/blenlib/BLI_path_util.h
@@ -91,13 +91,8 @@ bool BLI_testextensie_glob(const char *str, const char *ext_fnmatch) ATTR_NONNUL
bool BLI_replace_extension(char *path, size_t maxlen, const char *ext) ATTR_NONNULL();
bool BLI_ensure_extension(char *path, size_t maxlen, const char *ext) ATTR_NONNULL();
bool BLI_ensure_filename(char *filepath, size_t maxlen, const char *filename) ATTR_NONNULL();
-bool BLI_uniquename(struct ListBase *list, void *vlink, const char *defname, char delim, int name_offs, int len);
-bool BLI_uniquename_cb(bool (*unique_check)(void *arg, const char *name),
- void *arg, const char *defname, char delim, char *name, int name_len);
-void BLI_newname(char *name, int add);
int BLI_stringdec(const char *string, char *head, char *start, unsigned short *numlen);
void BLI_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic);
-int BLI_split_name_num(char *left, int *nr, const char *name, const char delim);
/* removes trailing slash */
void BLI_cleanup_file(const char *relabase, char *path) ATTR_NONNULL(2);
diff --git a/source/blender/blenlib/BLI_string_utf8.h b/source/blender/blenlib/BLI_string_utf8.h
index 0740b574c1a..32504a88b48 100644
--- a/source/blender/blenlib/BLI_string_utf8.h
+++ b/source/blender/blenlib/BLI_string_utf8.h
@@ -36,8 +36,8 @@ extern "C" {
char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL();
size_t BLI_strncpy_utf8_rlen(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL();
char *BLI_strncat_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL();
-int BLI_utf8_invalid_byte(const char *str, int length) ATTR_NONNULL();
-int BLI_utf8_invalid_strip(char *str, int length) ATTR_NONNULL();
+ptrdiff_t BLI_utf8_invalid_byte(const char *str, size_t length) ATTR_NONNULL();
+int BLI_utf8_invalid_strip(char *str, size_t length) ATTR_NONNULL();
int BLI_str_utf8_size(const char *p) ATTR_NONNULL(); /* warning, can return -1 on bad chars */
int BLI_str_utf8_size_safe(const char *p) ATTR_NONNULL();
diff --git a/source/blender/blenlib/BLI_string_utils.h b/source/blender/blenlib/BLI_string_utils.h
new file mode 100644
index 00000000000..bb19ed574bb
--- /dev/null
+++ b/source/blender/blenlib/BLI_string_utils.h
@@ -0,0 +1,63 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2017 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLI_STRING_UTILS_H__
+#define __BLI_STRING_UTILS_H__
+
+/** \file BLI_string_utils.h
+ * \ingroup bli
+ */
+
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "BLI_compiler_attrs.h"
+
+struct ListBase;
+
+typedef bool (*UniquenameCheckCallback)(void *arg, const char *name);
+
+size_t BLI_split_name_num(char *left, int *nr, const char *name, const char delim);
+
+void BLI_string_split_suffix(const char *string, char *r_body, char *r_suf, const size_t str_len);
+void BLI_string_split_prefix(const char *string, char *r_pre, char *r_body, const size_t str_len);
+
+void BLI_string_flip_side_name(char *r_name, const char *from_name, const bool strip_number, const size_t name_len);
+
+bool BLI_uniquename_cb(
+ UniquenameCheckCallback unique_check, void *arg, const char *defname, char delim, char *name, size_t name_len);
+bool BLI_uniquename(
+ struct ListBase *list, void *vlink, const char *defname, char delim, int name_offs, size_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BLI_STRING_UTILS_H__ */
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 38302201815..97225170f67 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -109,6 +109,7 @@ set(SRC
intern/string.c
intern/string_cursor_utf8.c
intern/string_utf8.c
+ intern/string_utils.c
intern/system.c
intern/task.c
intern/threads.c
@@ -196,6 +197,7 @@ set(SRC
BLI_string.h
BLI_string_cursor_utf8.h
BLI_string_utf8.h
+ BLI_string_utils.h
BLI_sys_types.h
BLI_system.h
BLI_task.h
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 76dac5487f2..8f5d84dfa08 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -2950,7 +2950,15 @@ static bool barycentric_weights(const float v1[3], const float v2[3], const floa
}
}
-void interp_weights_face_v3(float w[4], const float v1[3], const float v2[3], const float v3[3], const float v4[3], const float co[3])
+void interp_weights_tri_v3(float w[3], const float v1[3], const float v2[3], const float v3[3], const float co[3])
+{
+ float n[3];
+
+ normal_tri_v3(n, v1, v2, v3);
+ barycentric_weights(v1, v2, v3, co, n, w);
+}
+
+void interp_weights_quad_v3(float w[4], const float v1[3], const float v2[3], const float v3[3], const float v4[3], const float co[3])
{
float w2[3];
@@ -2963,7 +2971,7 @@ void interp_weights_face_v3(float w[4], const float v1[3], const float v2[3], co
w[1] = 1.0f;
else if (equals_v3v3(co, v3))
w[2] = 1.0f;
- else if (v4 && equals_v3v3(co, v4))
+ else if (equals_v3v3(co, v4))
w[3] = 1.0f;
else {
/* otherwise compute barycentric interpolation weights */
@@ -2971,35 +2979,24 @@ void interp_weights_face_v3(float w[4], const float v1[3], const float v2[3], co
bool degenerate;
sub_v3_v3v3(n1, v1, v3);
- if (v4) {
- sub_v3_v3v3(n2, v2, v4);
- }
- else {
- sub_v3_v3v3(n2, v2, v3);
- }
+ sub_v3_v3v3(n2, v2, v4);
cross_v3_v3v3(n, n1, n2);
- /* OpenGL seems to split this way, so we do too */
- if (v4) {
- degenerate = barycentric_weights(v1, v2, v4, co, n, w);
- SWAP(float, w[2], w[3]);
-
- if (degenerate || (w[0] < 0.0f)) {
- /* if w[1] is negative, co is on the other side of the v1-v3 edge,
- * so we interpolate using the other triangle */
- degenerate = barycentric_weights(v2, v3, v4, co, n, w2);
-
- if (!degenerate) {
- w[0] = 0.0f;
- w[1] = w2[0];
- w[2] = w2[1];
- w[3] = w2[2];
- }
+ degenerate = barycentric_weights(v1, v2, v4, co, n, w);
+ SWAP(float, w[2], w[3]);
+
+ if (degenerate || (w[0] < 0.0f)) {
+ /* if w[1] is negative, co is on the other side of the v1-v3 edge,
+ * so we interpolate using the other triangle */
+ degenerate = barycentric_weights(v2, v3, v4, co, n, w2);
+
+ if (!degenerate) {
+ w[0] = 0.0f;
+ w[1] = w2[0];
+ w[2] = w2[1];
+ w[3] = w2[2];
}
}
- else {
- barycentric_weights(v1, v2, v3, co, n, w);
- }
}
}
@@ -4051,6 +4048,26 @@ void map_to_sphere(float *r_u, float *r_v, const float x, const float y, const f
}
}
+void map_to_plane_v2_v3v3(float r_co[2], const float co[3], const float no[3])
+{
+ float target[3] = {0.0f, 0.0f, 1.0f};
+ float axis[3];
+
+ cross_v3_v3v3(axis, no, target);
+ normalize_v3(axis);
+
+ map_to_plane_axis_angle_v2_v3v3fl(r_co, co, axis, angle_normalized_v3v3(no, target));
+}
+
+void map_to_plane_axis_angle_v2_v3v3fl(float r_co[2], const float co[3], const float axis[3], const float angle)
+{
+ float tmp[3];
+
+ rotate_normalized_v3_v3v3fl(tmp, co, axis, angle);
+
+ copy_v2_v2(r_co, tmp);
+}
+
/********************************* Normals **********************************/
void accumulate_vertex_normals_tri(
diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c
index ee5e8651bd3..4389cd29034 100644
--- a/source/blender/blenlib/intern/math_vector_inline.c
+++ b/source/blender/blenlib/intern/math_vector_inline.c
@@ -491,7 +491,7 @@ MINLINE void mul_v2_v2_ccw(float r[2], const float mat[2], const float vec[2])
* return co_4d[3];
* \endcode
*/
-MINLINE float mul_project_m4_v3_zfac(float mat[4][4], const float co[3])
+MINLINE float mul_project_m4_v3_zfac(const float mat[4][4], const float co[3])
{
return (mat[0][3] * co[0]) +
(mat[1][3] * co[1]) +
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index f0d0bd00dea..6644e6605a1 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -63,9 +63,6 @@
#include "MEM_guardedalloc.h"
-/* local */
-#define UNIQUE_NAME_MAX 128
-
/* Declarations */
#ifdef WIN32
@@ -147,162 +144,6 @@ void BLI_stringenc(char *string, const char *head, const char *tail, unsigned sh
sprintf(string, "%s%.*d%s", head, numlen, MAX2(0, pic), tail);
}
-/**
- * Looks for a numeric suffix preceded by delim character on the end of
- * name, puts preceding part into *left and value of suffix into *nr.
- * Returns the length of *left.
- *
- * Foo.001 -> "Foo", 1
- * Returning the length of "Foo"
- *
- * \param left Where to return copy of part preceding delim
- * \param nr Where to return value of numeric suffix
- * \param name String to split
- * \param delim Delimiter character
- * \return Length of \a left
- */
-int BLI_split_name_num(char *left, int *nr, const char *name, const char delim)
-{
- const int name_len = strlen(name);
-
- *nr = 0;
- memcpy(left, name, (name_len + 1) * sizeof(char));
-
- /* name doesn't end with a delimiter "foo." */
- if ((name_len > 1 && name[name_len - 1] == delim) == 0) {
- int a = name_len;
- while (a--) {
- if (name[a] == delim) {
- left[a] = '\0'; /* truncate left part here */
- *nr = atol(name + a + 1);
- /* casting down to an int, can overflow for large numbers */
- if (*nr < 0)
- *nr = 0;
- return a;
- }
- else if (isdigit(name[a]) == 0) {
- /* non-numeric suffix - give up */
- break;
- }
- }
- }
-
- return name_len;
-}
-
-/**
- * Ensures name is unique (according to criteria specified by caller in unique_check callback),
- * incrementing its numeric suffix as necessary. Returns true if name had to be adjusted.
- *
- * \param unique_check Return true if name is not unique
- * \param arg Additional arg to unique_check--meaning is up to caller
- * \param defname To initialize name if latter is empty
- * \param delim Delimits numeric suffix in name
- * \param name Name to be ensured unique
- * \param name_len Maximum length of name area
- * \return true if there if the name was changed
- */
-bool BLI_uniquename_cb(bool (*unique_check)(void *arg, const char *name),
- void *arg, const char *defname, char delim, char *name, int name_len)
-{
- if (name[0] == '\0') {
- BLI_strncpy(name, defname, name_len);
- }
-
- if (unique_check(arg, name)) {
- char numstr[16];
- char tempname[UNIQUE_NAME_MAX];
- char left[UNIQUE_NAME_MAX];
- int number;
- int len = BLI_split_name_num(left, &number, name, delim);
- do {
- /* add 1 to account for \0 */
- const int numlen = BLI_snprintf(numstr, sizeof(numstr), "%c%03d", delim, ++number) + 1;
-
- /* highly unlikely the string only has enough room for the number
- * but support anyway */
- if ((len == 0) || (numlen >= name_len)) {
- /* number is know not to be utf-8 */
- BLI_strncpy(tempname, numstr, name_len);
- }
- else {
- char *tempname_buf;
- tempname_buf = tempname + BLI_strncpy_utf8_rlen(tempname, left, name_len - numlen);
- memcpy(tempname_buf, numstr, numlen);
- }
- } while (unique_check(arg, tempname));
-
- BLI_strncpy(name, tempname, name_len);
-
- return true;
- }
-
- return false;
-}
-
-/* little helper macro for BLI_uniquename */
-#ifndef GIVE_STRADDR
-# define GIVE_STRADDR(data, offset) ( ((char *)data) + offset)
-#endif
-
-/* Generic function to set a unique name. It is only designed to be used in situations
- * where the name is part of the struct, and also that the name is at most UNIQUE_NAME_MAX chars long.
- *
- * For places where this is used, see constraint.c for example...
- *
- * name_offs: should be calculated using offsetof(structname, membername) macro from stddef.h
- * len: maximum length of string (to prevent overflows, etc.)
- * defname: the name that should be used by default if none is specified already
- * delim: the character which acts as a delimiter between parts of the name
- */
-static bool uniquename_find_dupe(ListBase *list, void *vlink, const char *name, int name_offs)
-{
- Link *link;
-
- for (link = list->first; link; link = link->next) {
- if (link != vlink) {
- if (STREQ(GIVE_STRADDR(link, name_offs), name)) {
- return true;
- }
- }
- }
-
- return false;
-}
-
-static bool uniquename_unique_check(void *arg, const char *name)
-{
- struct {ListBase *lb; void *vlink; int name_offs; } *data = arg;
- return uniquename_find_dupe(data->lb, data->vlink, name, data->name_offs);
-}
-
-/**
- * Ensures that the specified block has a unique name within the containing list,
- * incrementing its numeric suffix as necessary. Returns true if name had to be adjusted.
- *
- * \param list List containing the block
- * \param vlink The block to check the name for
- * \param defname To initialize block name if latter is empty
- * \param delim Delimits numeric suffix in name
- * \param name_offs Offset of name within block structure
- * \param name_len Maximum length of name area
- */
-bool BLI_uniquename(ListBase *list, void *vlink, const char *defname, char delim, int name_offs, int name_len)
-{
- struct {ListBase *lb; void *vlink; int name_offs; } data;
- data.lb = list;
- data.vlink = vlink;
- data.name_offs = name_offs;
-
- assert((name_len > 1) && (name_len <= UNIQUE_NAME_MAX));
-
- /* See if we are given an empty string */
- if (ELEM(NULL, vlink, defname))
- return false;
-
- return BLI_uniquename_cb(uniquename_unique_check, &data, defname, delim, GIVE_STRADDR(vlink, name_offs), name_len);
-}
-
static int BLI_path_unc_prefix_len(const char *path); /* defined below in same file */
/* ******************** string encoding ***************** */
diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c
index 0ab11810b48..83d4a75952f 100644
--- a/source/blender/blenlib/intern/string_utf8.c
+++ b/source/blender/blenlib/intern/string_utf8.c
@@ -74,7 +74,7 @@ static const size_t utf8_skip_data[256] = {
*
* \return the offset of the first invalid byte.
*/
-int BLI_utf8_invalid_byte(const char *str, int length)
+ptrdiff_t BLI_utf8_invalid_byte(const char *str, size_t length)
{
const unsigned char *p, *perr, *pend = (const unsigned char *)str + length;
unsigned char c;
@@ -161,18 +161,24 @@ int BLI_utf8_invalid_byte(const char *str, int length)
utf8_error:
- return (int)((const char *)perr - (const char *)str);
+ return ((const char *)perr - (const char *)str);
}
-int BLI_utf8_invalid_strip(char *str, int length)
+/**
+ * Remove any invalid utf-8 byte (taking into account multi-bytes sequence of course).
+ *
+ * @return number of stripped bytes.
+ */
+int BLI_utf8_invalid_strip(char *str, size_t length)
{
- int bad_char, tot = 0;
+ ptrdiff_t bad_char;
+ int tot = 0;
BLI_assert(str[length] == '\0');
while ((bad_char = BLI_utf8_invalid_byte(str, length)) != -1) {
str += bad_char;
- length -= (bad_char + 1);
+ length -= (size_t)(bad_char + 1);
if (length == 0) {
/* last character bad, strip it */
@@ -182,7 +188,7 @@ int BLI_utf8_invalid_strip(char *str, int length)
}
else {
/* strip, keep looking */
- memmove(str, str + 1, (size_t)length + 1); /* +1 for NULL char! */
+ memmove(str, str + 1, length + 1); /* +1 for NULL char! */
tot++;
}
}
diff --git a/source/blender/blenlib/intern/string_utils.c b/source/blender/blenlib/intern/string_utils.c
new file mode 100644
index 00000000000..8d91a55a5ad
--- /dev/null
+++ b/source/blender/blenlib/intern/string_utils.c
@@ -0,0 +1,385 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2017 by the Blender FOundation.
+ * All rights reserved.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/blenlib/intern/string_utils.c
+ * \ingroup bli
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+#include "BLI_string_utf8.h"
+#include "BLI_string_utils.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_listBase.h"
+
+
+#ifdef __GNUC__
+# pragma GCC diagnostic error "-Wsign-conversion"
+#endif
+
+/**
+ * Looks for a numeric suffix preceded by delim character on the end of
+ * name, puts preceding part into *left and value of suffix into *nr.
+ * Returns the length of *left.
+ *
+ * Foo.001 -> "Foo", 1
+ * Returning the length of "Foo"
+ *
+ * \param left Where to return copy of part preceding delim
+ * \param nr Where to return value of numeric suffix
+ * \param name String to split
+ * \param delim Delimiter character
+ * \return Length of \a left
+ */
+size_t BLI_split_name_num(char *left, int *nr, const char *name, const char delim)
+{
+ const size_t name_len = strlen(name);
+
+ *nr = 0;
+ memcpy(left, name, (name_len + 1) * sizeof(char));
+
+ /* name doesn't end with a delimiter "foo." */
+ if ((name_len > 1 && name[name_len - 1] == delim) == 0) {
+ size_t a = name_len;
+ while (a--) {
+ if (name[a] == delim) {
+ left[a] = '\0'; /* truncate left part here */
+ *nr = atol(name + a + 1);
+ /* casting down to an int, can overflow for large numbers */
+ if (*nr < 0)
+ *nr = 0;
+ return a;
+ }
+ else if (isdigit(name[a]) == 0) {
+ /* non-numeric suffix - give up */
+ break;
+ }
+ }
+ }
+
+ return name_len;
+}
+
+static bool is_char_sep(const char c)
+{
+ return ELEM(c, '.', ' ', '-', '_');
+}
+
+/**
+ * based on `BLI_split_dirfile()` / `os.path.splitext()`,
+ * `"a.b.c"` -> (`"a.b"`, `".c"`).
+ */
+void BLI_string_split_suffix(const char *string, char *r_body, char *r_suf, const size_t str_len)
+{
+ size_t len = BLI_strnlen(string, str_len);
+ size_t i;
+
+ r_body[0] = r_suf[0] = '\0';
+
+ for (i = len; i > 0; i--) {
+ if (is_char_sep(string[i])) {
+ BLI_strncpy(r_body, string, i + 1);
+ BLI_strncpy(r_suf, string + i, (len + 1) - i);
+ return;
+ }
+ }
+
+ memcpy(r_body, string, len + 1);
+}
+
+/**
+ * `"a.b.c"` -> (`"a."`, `"b.c"`)
+ */
+void BLI_string_split_prefix(const char *string, char *r_pre, char *r_body, const size_t str_len)
+{
+ size_t len = BLI_strnlen(string, str_len);
+ size_t i;
+
+ r_body[0] = r_pre[0] = '\0';
+
+ for (i = 1; i < len; i++) {
+ if (is_char_sep(string[i])) {
+ i++;
+ BLI_strncpy(r_pre, string, i + 1);
+ BLI_strncpy(r_body, string + i, (len + 1) - i);
+ return;
+ }
+ }
+
+ BLI_strncpy(r_body, string, len);
+}
+
+/**
+ * Finds the best possible flipped (left/right) name. For renaming; check for unique names afterwards.
+ *
+ * \param r_name flipped name, assumed to be a pointer to a string of at least \a name_len size.
+ * \param from_name original name, assumed to be a pointer to a string of at least \a name_len size.
+ * \param strip_number If set, remove number extensions.
+ */
+void BLI_string_flip_side_name(char *r_name, const char *from_name, const bool strip_number, const size_t name_len)
+{
+ size_t len;
+ char *prefix = alloca(name_len); /* The part before the facing */
+ char *suffix = alloca(name_len); /* The part after the facing */
+ char *replace = alloca(name_len); /* The replacement string */
+ char *number = alloca(name_len); /* The number extension string */
+ char *index = NULL;
+ bool is_set = false;
+
+ *prefix = *suffix = *replace = *number = '\0';
+
+ /* always copy the name, since this can be called with an uninitialized string */
+ BLI_strncpy(r_name, from_name, name_len);
+
+ len = BLI_strnlen(from_name, name_len);
+ if (len < 3) {
+ /* we don't do names like .R or .L */
+ return;
+ }
+
+ /* We first check the case with a .### extension, let's find the last period */
+ if (isdigit(r_name[len - 1])) {
+ index = strrchr(r_name, '.'); // last occurrence
+ if (index && isdigit(index[1])) { // doesnt handle case bone.1abc2 correct..., whatever!
+ if (strip_number == false) {
+ BLI_strncpy(number, index, name_len);
+ }
+ *index = 0;
+ len = BLI_strnlen(r_name, name_len);
+ }
+ }
+
+ BLI_strncpy(prefix, r_name, name_len);
+
+ /* first case; separator . - _ with extensions r R l L */
+ if ((len > 1) && is_char_sep(r_name[len - 2])) {
+ is_set = true;
+ switch (r_name[len - 1]) {
+ case 'l':
+ prefix[len - 1] = 0;
+ strcpy(replace, "r");
+ break;
+ case 'r':
+ prefix[len - 1] = 0;
+ strcpy(replace, "l");
+ break;
+ case 'L':
+ prefix[len - 1] = 0;
+ strcpy(replace, "R");
+ break;
+ case 'R':
+ prefix[len - 1] = 0;
+ strcpy(replace, "L");
+ break;
+ default:
+ is_set = false;
+ }
+ }
+
+ /* case; beginning with r R l L, with separator after it */
+ if (!is_set && is_char_sep(r_name[1])) {
+ is_set = true;
+ switch (r_name[0]) {
+ case 'l':
+ strcpy(replace, "r");
+ BLI_strncpy(suffix, r_name + 1, name_len);
+ prefix[0] = 0;
+ break;
+ case 'r':
+ strcpy(replace, "l");
+ BLI_strncpy(suffix, r_name + 1, name_len);
+ prefix[0] = 0;
+ break;
+ case 'L':
+ strcpy(replace, "R");
+ BLI_strncpy(suffix, r_name + 1, name_len);
+ prefix[0] = 0;
+ break;
+ case 'R':
+ strcpy(replace, "L");
+ BLI_strncpy(suffix, r_name + 1, name_len);
+ prefix[0] = 0;
+ break;
+ default:
+ is_set = false;
+ }
+ }
+
+ if (!is_set && len > 5) {
+ /* hrms, why test for a separator? lets do the rule 'ultimate left or right' */
+ if (((index = BLI_strcasestr(prefix, "right")) == prefix) ||
+ (index == prefix + len - 5))
+ {
+ is_set = true;
+ if (index[0] == 'r') {
+ strcpy(replace, "left");
+ }
+ else {
+ strcpy(replace, (index[1] == 'I') ? "LEFT" : "Left");
+ }
+ *index = 0;
+ BLI_strncpy(suffix, index + 5, name_len);
+ }
+ else if (((index = BLI_strcasestr(prefix, "left")) == prefix) ||
+ (index == prefix + len - 4))
+ {
+ is_set = true;
+ if (index[0] == 'l') {
+ strcpy(replace, "right");
+ }
+ else {
+ strcpy(replace, (index[1] == 'E') ? "RIGHT" : "Right");
+ }
+ *index = 0;
+ BLI_strncpy(suffix, index + 4, name_len);
+ }
+ }
+
+ BLI_snprintf(r_name, name_len, "%s%s%s%s", prefix, replace, suffix, number);
+}
+
+
+/* Unique name utils. */
+
+/**
+ * Ensures name is unique (according to criteria specified by caller in unique_check callback),
+ * incrementing its numeric suffix as necessary. Returns true if name had to be adjusted.
+ *
+ * \param unique_check Return true if name is not unique
+ * \param arg Additional arg to unique_check--meaning is up to caller
+ * \param defname To initialize name if latter is empty
+ * \param delim Delimits numeric suffix in name
+ * \param name Name to be ensured unique
+ * \param name_len Maximum length of name area
+ * \return true if there if the name was changed
+ */
+bool BLI_uniquename_cb(
+ UniquenameCheckCallback unique_check, void *arg, const char *defname, char delim, char *name, size_t name_len)
+{
+ if (name[0] == '\0') {
+ BLI_strncpy(name, defname, name_len);
+ }
+
+ if (unique_check(arg, name)) {
+ char numstr[16];
+ char *tempname = alloca(name_len);
+ char *left = alloca(name_len);
+ int number;
+ size_t len = BLI_split_name_num(left, &number, name, delim);
+ do {
+ /* add 1 to account for \0 */
+ const size_t numlen = BLI_snprintf(numstr, sizeof(numstr), "%c%03d", delim, ++number) + 1;
+
+ /* highly unlikely the string only has enough room for the number
+ * but support anyway */
+ if ((len == 0) || (numlen >= name_len)) {
+ /* number is know not to be utf-8 */
+ BLI_strncpy(tempname, numstr, name_len);
+ }
+ else {
+ char *tempname_buf;
+ tempname_buf = tempname + BLI_strncpy_utf8_rlen(tempname, left, name_len - numlen);
+ memcpy(tempname_buf, numstr, numlen);
+ }
+ } while (unique_check(arg, tempname));
+
+ BLI_strncpy(name, tempname, name_len);
+
+ return true;
+ }
+
+ return false;
+}
+
+/* little helper macro for BLI_uniquename */
+#ifndef GIVE_STRADDR
+# define GIVE_STRADDR(data, offset) ( ((char *)data) + offset)
+#endif
+
+/* Generic function to set a unique name. It is only designed to be used in situations
+ * where the name is part of the struct.
+ *
+ * For places where this is used, see constraint.c for example...
+ *
+ * name_offs: should be calculated using offsetof(structname, membername) macro from stddef.h
+ * len: maximum length of string (to prevent overflows, etc.)
+ * defname: the name that should be used by default if none is specified already
+ * delim: the character which acts as a delimiter between parts of the name
+ */
+static bool uniquename_find_dupe(ListBase *list, void *vlink, const char *name, int name_offs)
+{
+ Link *link;
+
+ for (link = list->first; link; link = link->next) {
+ if (link != vlink) {
+ if (STREQ(GIVE_STRADDR(link, name_offs), name)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static bool uniquename_unique_check(void *arg, const char *name)
+{
+ struct {ListBase *lb; void *vlink; int name_offs; } *data = arg;
+ return uniquename_find_dupe(data->lb, data->vlink, name, data->name_offs);
+}
+
+/**
+ * Ensures that the specified block has a unique name within the containing list,
+ * incrementing its numeric suffix as necessary. Returns true if name had to be adjusted.
+ *
+ * \param list List containing the block
+ * \param vlink The block to check the name for
+ * \param defname To initialize block name if latter is empty
+ * \param delim Delimits numeric suffix in name
+ * \param name_offs Offset of name within block structure
+ * \param name_len Maximum length of name area
+ */
+bool BLI_uniquename(ListBase *list, void *vlink, const char *defname, char delim, int name_offs, size_t name_len)
+{
+ struct {ListBase *lb; void *vlink; int name_offs; } data;
+ data.lb = list;
+ data.vlink = vlink;
+ data.name_offs = name_offs;
+
+ BLI_assert(name_len > 1);
+
+ /* See if we are given an empty string */
+ if (ELEM(NULL, vlink, defname))
+ return false;
+
+ return BLI_uniquename_cb(uniquename_unique_check, &data, defname, delim, GIVE_STRADDR(vlink, name_offs), name_len);
+}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index d0c5a7ad771..ff363f4b474 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -5992,6 +5992,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
sce->toolsettings->wpaint->wpaint_prev = NULL;
sce->toolsettings->wpaint->tot = 0;
}
+
/* relink grease pencil drawing brushes */
link_list(fd, &sce->toolsettings->gp_brushes);
for (bGPDbrush *brush = sce->toolsettings->gp_brushes.first; brush; brush = brush->next) {
@@ -6008,6 +6009,12 @@ static void direct_link_scene(FileData *fd, Scene *sce)
direct_link_curvemapping(fd, brush->cur_jitter);
}
}
+
+ /* relink grease pencil interpolation curves */
+ sce->toolsettings->gp_interpolate.custom_ipo = newdataadr(fd, sce->toolsettings->gp_interpolate.custom_ipo);
+ if (sce->toolsettings->gp_interpolate.custom_ipo) {
+ direct_link_curvemapping(fd, sce->toolsettings->gp_interpolate.custom_ipo);
+ }
}
if (sce->ed) {
@@ -7519,7 +7526,7 @@ static void lib_link_group(FileData *fd, Main *main)
if (add_us) {
id_us_ensure_real(&group->id);
}
- BKE_group_object_unlink(group, NULL, NULL, NULL); /* removes NULL entries */
+ BKE_group_object_unlink(group, NULL); /* removes NULL entries */
}
}
}
@@ -9915,7 +9922,7 @@ static void give_base_to_objects(Main *mainvar, Scene *scene, View3D *v3d, Libra
base->object = ob;
base->lay = ob->lay;
- base->flag = ob->flag;
+ BKE_scene_base_flag_sync_from_object(base);
CLAMP_MIN(ob->id.us, 0);
id_us_plus_no_lib((ID *)ob);
@@ -9949,7 +9956,7 @@ static void give_base_to_groups(
/* assign the base */
base = BKE_scene_base_add(scene, ob);
base->flag |= SELECT;
- base->object->flag = base->flag;
+ BKE_scene_base_flag_sync_from_base(base);
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
scene->basact = base;
@@ -10052,7 +10059,7 @@ static void link_object_postprocess(ID *id, Scene *scene, View3D *v3d, const sho
if (flag & FILE_AUTOSELECT) {
base->flag |= SELECT;
- base->object->flag = base->flag;
+ BKE_scene_base_flag_sync_from_base(base);
/* do NOT make base active here! screws up GUI stuff, if you want it do it on src/ level */
}
}
diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c
index 907baab0aee..ab3d14af882 100644
--- a/source/blender/blenloader/intern/versioning_260.c
+++ b/source/blender/blenloader/intern/versioning_260.c
@@ -56,6 +56,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_string_utils.h"
#include "BLT_translation.h"
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index ea654ad6906..58cc06ddec6 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -1474,6 +1474,36 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
for (Brush *br = main->brush.first; br; br = br->id.next) {
br->fill_threshold /= sqrt_3;
}
+
+ /* Custom motion paths */
+ if (!DNA_struct_elem_find(fd->filesdna, "bMotionPath", "int", "line_thickness")) {
+ Object *ob;
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ bMotionPath *mpath;
+ bPoseChannel *pchan;
+ mpath = ob->mpath;
+ if (mpath) {
+ mpath->color[0] = 1.0f;
+ mpath->color[1] = 0.0f;
+ mpath->color[2] = 0.0f;
+ mpath->line_thickness = 1;
+ mpath->flag |= MOTIONPATH_FLAG_LINES;
+ }
+ /* bones motion path */
+ if (ob->pose) {
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ mpath = pchan->mpath;
+ if (mpath) {
+ mpath->color[0] = 1.0f;
+ mpath->color[1] = 0.0f;
+ mpath->color[2] = 0.0f;
+ mpath->line_thickness = 1;
+ mpath->flag |= MOTIONPATH_FLAG_LINES;
+ }
+ }
+ }
+ }
+ }
}
/* To be added to next subversion bump! */
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index b9fc22bc77e..f9afa33ae79 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -129,7 +129,7 @@ void blo_do_versions_after_linking_280(Main *main)
/* convert selected bases */
for (Base *base = scene->base.first; base; base = base->next) {
ObjectBase *ob_base = BKE_scene_layer_base_find(sl, base->object);
- if ((base->flag & BA_SELECT) != 0) {
+ if ((base->flag & SELECT) != 0) {
ob_base->flag |= BASE_SELECTED;
}
else {
@@ -145,6 +145,13 @@ void blo_do_versions_after_linking_280(Main *main)
BKE_collection_remove(scene, collections[i]);
}
}
+
+ /* remove bases once and for all */
+ for (Base *base = scene->base.first; base; base = base->next) {
+ id_us_min(&base->object->id);
+ }
+ BLI_freelistN(&scene->base);
+ scene->basact = NULL;
}
}
}
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 8b46768bab1..1621bb78432 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -2716,6 +2716,10 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
write_curvemapping(wd, brush->cur_jitter);
}
}
+ /* write grease-pencil custom ipo curve to file */
+ if (tos->gp_interpolate.custom_ipo) {
+ write_curvemapping(wd, tos->gp_interpolate.custom_ipo);
+ }
write_paint(wd, &tos->imapaint.paint);
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c
index 132a7ccd4fa..e46a31cb2e9 100644
--- a/source/blender/bmesh/intern/bmesh_construct.c
+++ b/source/blender/bmesh/intern/bmesh_construct.c
@@ -387,15 +387,11 @@ BMFace *BM_face_create_ngon_verts(
*
* \note Since this is a vcloud there is no direction.
*/
-BMFace *BM_face_create_ngon_vcloud(
- BMesh *bm, BMVert **vert_arr, int len,
- const BMFace *f_example, const eBMCreateFlag create_flag)
+void BM_verts_sort_radial_plane(BMVert **vert_arr, int len)
{
struct SortIntByFloat *vang = BLI_array_alloca(vang, len);
BMVert **vert_arr_map = BLI_array_alloca(vert_arr_map, len);
- BMFace *f;
-
float totv_inv = 1.0f / (float)len;
int i = 0;
@@ -470,26 +466,9 @@ BMFace *BM_face_create_ngon_vcloud(
/* now calculate every points angle around the normal (signed) */
for (i = 0; i < len; i++) {
- float co[3];
- float proj_vec[3];
- float angle;
-
- /* center relative vec */
- sub_v3_v3v3(co, vert_arr[i]->co, cent);
-
- /* align to plane */
- project_v3_v3v3(proj_vec, co, nor);
- sub_v3_v3(co, proj_vec);
-
- /* now 'co' is valid - we can compare its angle against the far vec */
- angle = angle_v3v3(far_vec, co);
-
- if (dot_v3v3(co, sign_vec) < 0.0f) {
- angle = -angle;
- }
-
- vang[i].sort_value = angle;
+ vang[i].sort_value = angle_signed_on_axis_v3v3v3_v3(far, cent, vert_arr[i]->co, nor);
vang[i].data = i;
+ vert_arr_map[i] = vert_arr[i];
}
/* sort by angle and magic! - we have our ngon */
@@ -497,14 +476,9 @@ BMFace *BM_face_create_ngon_vcloud(
/* --- */
- /* create edges and find the winding (if faces are attached to any existing edges) */
for (i = 0; i < len; i++) {
- vert_arr_map[i] = vert_arr[vang[i].data];
+ vert_arr[i] = vert_arr_map[vang[i].data];
}
-
- f = BM_face_create_ngon_verts(bm, vert_arr_map, len, f_example, create_flag, true, true);
-
- return f;
}
/*************************************************************/
diff --git a/source/blender/bmesh/intern/bmesh_construct.h b/source/blender/bmesh/intern/bmesh_construct.h
index 9c6483de42b..a52a17cd2f3 100644
--- a/source/blender/bmesh/intern/bmesh_construct.h
+++ b/source/blender/bmesh/intern/bmesh_construct.h
@@ -34,6 +34,9 @@ bool BM_verts_from_edges(BMVert **vert_arr, BMEdge **edge_arr, const int len);
bool BM_edges_from_verts(BMEdge **edge_arr, BMVert **vert_arr, const int len);
void BM_edges_from_verts_ensure(BMesh *bm, BMEdge **edge_arr, BMVert **vert_arr, const int len);
+/* sort before creation */
+void BM_verts_sort_radial_plane(BMVert **vert_arr, int len);
+
BMFace *BM_face_create_quad_tri(
BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
const BMFace *f_example, const eBMCreateFlag create_flag);
@@ -50,10 +53,6 @@ BMFace *BM_face_create_ngon_verts(
const BMFace *f_example, const eBMCreateFlag create_flag,
const bool calc_winding, const bool create_edges);
-BMFace *BM_face_create_ngon_vcloud(
- BMesh *bm, BMVert **vert_arr, int len,
- const BMFace *f_example, const eBMCreateFlag create_flag);
-
void BM_elem_attrs_copy_ex(
BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v,
const char hflag_mask);
diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
index 7178a8132d2..7f2032d5f53 100644
--- a/source/blender/bmesh/intern/bmesh_marking.c
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -70,7 +70,7 @@ static void recount_totsels(BMesh *bm)
}
}
-/** \name BMesh helper functions for selection flushing.
+/** \name BMesh helper functions for selection & hide flushing.
* \{ */
static bool bm_vert_is_edge_select_any_other(const BMVert *v, const BMEdge *e_first)
@@ -102,6 +102,20 @@ static bool bm_vert_is_edge_select_any(const BMVert *v)
}
#endif
+static bool bm_vert_is_edge_visible_any(const BMVert *v)
+{
+ if (v->e) {
+ const BMEdge *e_iter, *e_first;
+ e_iter = e_first = v->e;
+ do {
+ if (!BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN)) {
+ return true;
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
+ }
+ return false;
+}
+
static bool bm_edge_is_face_select_any_other(BMLoop *l_first)
{
const BMLoop *l_iter = l_first;
@@ -131,6 +145,20 @@ static bool bm_edge_is_face_select_any(const BMEdge *e)
}
#endif
+static bool bm_edge_is_face_visible_any(const BMEdge *e)
+{
+ if (e->l) {
+ const BMLoop *l_iter, *l_first;
+ l_iter = l_first = e->l;
+ do {
+ if (!BM_elem_flag_test(l_iter->f, BM_ELEM_HIDDEN)) {
+ return true;
+ }
+ } while ((l_iter = l_iter->radial_next) != l_first);
+ }
+ return false;
+}
+
/** \} */
/**
@@ -1198,87 +1226,111 @@ void BM_mesh_elem_hflag_enable_all(
/***************** Mesh Hiding stuff *********** */
+/**
+ * Hide unless any connected elements are visible.
+ * Run this after hiding a connected edge or face.
+ */
static void vert_flush_hide_set(BMVert *v)
{
- BMIter iter;
- BMEdge *e;
- bool hide = true;
-
- BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- hide = hide && BM_elem_flag_test(e, BM_ELEM_HIDDEN);
- }
-
- BM_elem_flag_set(v, BM_ELEM_HIDDEN, hide);
+ BM_elem_flag_set(v, BM_ELEM_HIDDEN, !bm_vert_is_edge_visible_any(v));
}
-static void edge_flush_hide(BMEdge *e)
+/**
+ * Hide unless any connected elements are visible.
+ * Run this after hiding a connected face.
+ */
+static void edge_flush_hide_set(BMEdge *e)
{
- BMIter iter;
- BMFace *f;
- bool hide = true;
-
- BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) {
- hide = hide && BM_elem_flag_test(f, BM_ELEM_HIDDEN);
- }
-
- BM_elem_flag_set(e, BM_ELEM_HIDDEN, hide);
+ BM_elem_flag_set(e, BM_ELEM_HIDDEN, !bm_edge_is_face_visible_any(e));
}
void BM_vert_hide_set(BMVert *v, const bool hide)
{
/* vert hiding: vert + surrounding edges and faces */
- BMIter iter, fiter;
- BMEdge *e;
- BMFace *f;
-
BLI_assert(v->head.htype == BM_VERT);
+ if (hide) {
+ BLI_assert(!BM_elem_flag_test(v, BM_ELEM_SELECT));
+ }
BM_elem_flag_set(v, BM_ELEM_HIDDEN, hide);
- BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
- BM_elem_flag_set(e, BM_ELEM_HIDDEN, hide);
-
- BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
- BM_elem_flag_set(f, BM_ELEM_HIDDEN, hide);
- }
+ if (v->e) {
+ BMEdge *e_iter, *e_first;
+ e_iter = e_first = v->e;
+ do {
+ BM_elem_flag_set(e_iter, BM_ELEM_HIDDEN, hide);
+ if (e_iter->l) {
+ const BMLoop *l_radial_iter, *l_radial_first;
+ l_radial_iter = l_radial_first = e_iter->l;
+ do {
+ BM_elem_flag_set(l_radial_iter->f, BM_ELEM_HIDDEN, hide);
+ } while ((l_radial_iter = l_radial_iter->radial_next) != l_radial_first);
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
}
}
void BM_edge_hide_set(BMEdge *e, const bool hide)
{
- BMIter iter;
- BMFace *f;
- /* BMVert *v; */
-
BLI_assert(e->head.htype == BM_EDGE);
+ if (hide) {
+ BLI_assert(!BM_elem_flag_test(e, BM_ELEM_SELECT));
+ }
/* edge hiding: faces around the edge */
- BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) {
- BM_elem_flag_set(f, BM_ELEM_HIDDEN, hide);
+ if (e->l) {
+ const BMLoop *l_iter, *l_first;
+ l_iter = l_first = e->l;
+ do {
+ BM_elem_flag_set(l_iter->f, BM_ELEM_HIDDEN, hide);
+ } while ((l_iter = l_iter->radial_next) != l_first);
}
BM_elem_flag_set(e, BM_ELEM_HIDDEN, hide);
/* hide vertices if necessary */
- vert_flush_hide_set(e->v1);
- vert_flush_hide_set(e->v2);
+ if (hide) {
+ vert_flush_hide_set(e->v1);
+ vert_flush_hide_set(e->v2);
+ }
+ else {
+ BM_elem_flag_disable(e->v1, BM_ELEM_HIDDEN);
+ BM_elem_flag_disable(e->v2, BM_ELEM_HIDDEN);
+ }
}
void BM_face_hide_set(BMFace *f, const bool hide)
{
- BMIter iter;
- BMLoop *l;
-
BLI_assert(f->head.htype == BM_FACE);
+ if (hide) {
+ BLI_assert(!BM_elem_flag_test(f, BM_ELEM_SELECT));
+ }
BM_elem_flag_set(f, BM_ELEM_HIDDEN, hide);
- BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) {
- edge_flush_hide(l->e);
+ if (hide) {
+ BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_iter;
+
+ l_iter = l_first;
+ do {
+ edge_flush_hide_set(l_iter->e);
+ } while ((l_iter = l_iter->next) != l_first);
+
+ l_iter = l_first;
+ do {
+ vert_flush_hide_set(l_iter->v);
+ } while ((l_iter = l_iter->next) != l_first);
}
+ else {
+ BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_iter;
- BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) {
- vert_flush_hide_set(l->v);
+ l_iter = l_first;
+ do {
+ BM_elem_flag_disable(l_iter->e, BM_ELEM_HIDDEN);
+ BM_elem_flag_disable(l_iter->v, BM_ELEM_HIDDEN);
+ } while ((l_iter = l_iter->next) != l_first);
}
}
diff --git a/source/blender/bmesh/operators/bmo_create.c b/source/blender/bmesh/operators/bmo_create.c
index 7b8cb36ab59..a980baf8626 100644
--- a/source/blender/bmesh/operators/bmo_create.c
+++ b/source/blender/bmesh/operators/bmo_create.c
@@ -290,7 +290,11 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
BMFace *f;
BMO_iter_as_array(op->slots_in, "geom", BM_VERT, (void **)vert_arr, totv);
- f = BM_face_create_ngon_vcloud(bm, vert_arr, totv, NULL, BM_CREATE_NO_DOUBLE);
+
+ BM_verts_sort_radial_plane(vert_arr, totv);
+
+ /* create edges and find the winding (if faces are attached to any existing edges) */
+ f = BM_face_create_ngon_verts(bm, vert_arr, totv, NULL, BM_CREATE_NO_DOUBLE, true, true);
if (f) {
BMO_face_flag_enable(bm, f, ELE_OUT);
diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c
index c52c608e671..e2ff09669d7 100644
--- a/source/blender/bmesh/operators/bmo_inset.c
+++ b/source/blender/bmesh/operators/bmo_inset.c
@@ -647,6 +647,10 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
} (void)0
#define VERT_ORIG_GET(_v) \
(const float *)BLI_ghash_lookup_default(vert_coords, (_v), (_v)->co)
+ /* memory for the coords isn't given back to the arena,
+ * acceptable in this case since it runs a fixed number of times. */
+#define VERT_ORIG_REMOVE(_v) \
+ BLI_ghash_remove(vert_coords, (_v), NULL, NULL)
for (i = 0, es = edge_info; i < edge_info_len; i++, es++) {
@@ -972,7 +976,11 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
v_glue = v_split;
}
else {
- BM_vert_splice(bm, v_glue, v_split);
+ if (BM_vert_splice(bm, v_glue, v_split)) {
+ if (use_vert_coords_orig) {
+ VERT_ORIG_REMOVE(v_split);
+ }
+ }
}
}
}
diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp
index 5cd01eff263..3801c9300df 100644
--- a/source/blender/collada/AnimationImporter.cpp
+++ b/source/blender/collada/AnimationImporter.cpp
@@ -35,8 +35,8 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BLI_path_util.h"
#include "BLI_string.h"
+#include "BLI_string_utils.h"
#include "BLT_translation.h"
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index 226f319cefd..f42691cf702 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -57,6 +57,7 @@ extern "C" {
#include "BLI_fileops.h"
#include "BKE_camera.h"
+#include "BKE_collection.h"
#include "BKE_main.h"
#include "BKE_lamp.h"
#include "BKE_library.h"
@@ -418,7 +419,7 @@ Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Nod
Object *obn = BKE_object_copy(G.main, source_ob);
DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
- BKE_scene_base_add(sce, obn);
+ BKE_collection_object_add_from(sce, source_ob, obn);
if (instance_node) {
anim_importer.read_node_transform(instance_node, obn);
diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt
index e635256cda6..2d32e85bf64 100644
--- a/source/blender/depsgraph/CMakeLists.txt
+++ b/source/blender/depsgraph/CMakeLists.txt
@@ -113,10 +113,6 @@ else()
endif()
endif()
-if(WITH_LEGACY_DEPSGRAPH)
- add_definitions(-DWITH_LEGACY_DEPSGRAPH)
-endif()
-
if(WITH_BOOST)
list(APPEND INC_SYS
${BOOST_INCLUDE_DIR}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
index 4a5f3dc8664..c1d51c1ace9 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
@@ -123,7 +123,7 @@ void DepsgraphNodeBuilder::build_rig(Scene *scene, Object *ob)
/* Rebuild pose if not up to date. */
if (ob->pose == NULL || (ob->pose->flag & POSE_RECALC)) {
- BKE_pose_rebuild_ex(ob, arm, false);
+ BKE_pose_rebuild(ob, arm);
/* XXX: Without this animation gets lost in certain circumstances
* after loading file. Need to investigate further since it does
* not happen with simple scenes..
diff --git a/source/blender/depsgraph/intern/depsgraph_eval.cc b/source/blender/depsgraph/intern/depsgraph_eval.cc
index c41f28b07e8..ebaf0089835 100644
--- a/source/blender/depsgraph/intern/depsgraph_eval.cc
+++ b/source/blender/depsgraph/intern/depsgraph_eval.cc
@@ -52,43 +52,9 @@ extern "C" {
#include "intern/depsgraph.h"
-#ifdef WITH_LEGACY_DEPSGRAPH
-static bool use_legacy_depsgraph = true;
-#endif
-
/* Unfinished and unused, and takes quite some pre-processing time. */
#undef USE_EVAL_PRIORITY
-bool DEG_depsgraph_use_legacy(void)
-{
-#ifdef DISABLE_NEW_DEPSGRAPH
- return true;
-#elif defined(WITH_LEGACY_DEPSGRAPH)
- return use_legacy_depsgraph;
-#else
- BLI_assert(!"Should not be used with new depsgraph");
- return false;
-#endif
-}
-
-void DEG_depsgraph_switch_to_legacy(void)
-{
-#ifdef WITH_LEGACY_DEPSGRAPH
- use_legacy_depsgraph = true;
-#else
- BLI_assert(!"Should not be used with new depsgraph");
-#endif
-}
-
-void DEG_depsgraph_switch_to_new(void)
-{
-#ifdef WITH_LEGACY_DEPSGRAPH
- use_legacy_depsgraph = false;
-#else
- BLI_assert(!"Should not be used with new depsgraph");
-#endif
-}
-
/* ****************** */
/* Evaluation Context */
diff --git a/source/blender/depsgraph/util/deg_util_foreach.h b/source/blender/depsgraph/util/deg_util_foreach.h
index 87d37168d51..8c234eae7de 100644
--- a/source/blender/depsgraph/util/deg_util_foreach.h
+++ b/source/blender/depsgraph/util/deg_util_foreach.h
@@ -36,15 +36,7 @@
# include <boost/foreach.hpp>
# define foreach BOOST_FOREACH
#else
-#pragma message("No available foreach() implementation. Using stub instead, disabling new depsgraph")
-
-#ifndef WITH_LEGACY_DEPSGRAPH
-# error "Unable to build new depsgraph and legacy one is disabled."
-#endif
-
-#define DISABLE_NEW_DEPSGRAPH
-
-# define foreach(x, y) for (x; false; (void)y)
+# error "Depsgraph requires either Boost or C++11 for range-based loops."
#endif
#define GHASH_FOREACH_BEGIN(type, var, what) \
diff --git a/source/blender/depsgraph/util/deg_util_function.h b/source/blender/depsgraph/util/deg_util_function.h
index 1e34ae04d9a..da31bb037f9 100644
--- a/source/blender/depsgraph/util/deg_util_function.h
+++ b/source/blender/depsgraph/util/deg_util_function.h
@@ -47,64 +47,5 @@ using boost::function;
#define function_bind boost::bind
#else
-
-#pragma message("No available function binding implementation. Using stub instead, disabling new depsgraph")
-
-#ifndef WITH_LEGACY_DEPSGRAPH
-# error "Unable to build new depsgraph and legacy one is disabled."
-#endif
-
-#define DISABLE_NEW_DEPSGRAPH
-
-#include "BLI_utildefines.h"
-#include <cstdlib>
-
-template<typename T>
-class function {
-public:
- function() {};
- function(void *) {}
- operator bool() const { return false; }
- bool operator== (void *) { return false; }
-
- template<typename T1>
- void operator() (T1) {
- BLI_assert(!"Should not be used");
- }
-};
-
-class Wrap {
-public:
- Wrap() {}
- template <typename T>
- Wrap(T /*arg*/) {}
-};
-
-template <typename T>
-void *function_bind(T func,
- Wrap arg1 = Wrap(),
- Wrap arg2 = Wrap(),
- Wrap arg3 = Wrap(),
- Wrap arg4 = Wrap(),
- Wrap arg5 = Wrap(),
- Wrap arg6 = Wrap(),
- Wrap arg7 = Wrap())
-{
- BLI_assert(!"Should not be used");
- (void)func;
- (void)arg1;
- (void)arg2;
- (void)arg3;
- (void)arg4;
- (void)arg5;
- (void)arg6;
- (void)arg7;
- return NULL;
-}
-
-#define _1 Wrap()
-#define _2 Wrap()
-#define _3 Wrap()
-#define _4 Wrap()
-
+# error "Depsgraph requires either Boost or C++11 for function bindings."
#endif
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index f05932db1b2..26674278a5e 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -68,6 +68,8 @@
#include "BKE_nla.h"
#include "BKE_context.h"
+#include "GPU_immediate.h"
+
#include "UI_interface.h"
#include "UI_interface_icons.h"
#include "UI_resources.h"
@@ -140,13 +142,20 @@ static void acf_generic_dataexpand_backdrop(bAnimContext *ac, bAnimListElem *ale
View2D *v2d = &ac->ar->v2d;
short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
float color[3];
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
/* set backdrop drawing color */
acf->get_backdrop_color(ac, ale, color);
- glColor3fv(color);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3fv(color);
/* no rounded corner - just rectangular box */
- glRectf(offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
+ immRectf(pos, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
+
+ immUnbindProgram();
}
/* helper method to test if group colors should be drawn */
@@ -223,13 +232,20 @@ static void acf_generic_channel_backdrop(bAnimContext *ac, bAnimListElem *ale, f
View2D *v2d = &ac->ar->v2d;
short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
float color[3];
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
/* set backdrop drawing color */
acf->get_backdrop_color(ac, ale, color);
- glColor3fv(color);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3fv(color);
/* no rounded corners - just rectangular box */
- glRectf(offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
+ immRectf(pos, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
+
+ immUnbindProgram();
}
/* Indention + Offset ------------------------------------------- */
@@ -1998,6 +2014,79 @@ static bAnimChannelType ACF_DSWOR =
acf_dswor_setting_ptr /* pointer for setting */
};
+/* Particle Expander ------------------------------------------- */
+
+// TODO: just get this from RNA?
+static int acf_dspart_icon(bAnimListElem *UNUSED(ale))
+{
+ return ICON_PARTICLE_DATA;
+}
+
+/* get the appropriate flag(s) for the setting when it is valid */
+static int acf_dspart_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+{
+ /* clear extra return data first */
+ *neg = false;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return 0;
+
+ case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
+ return ADT_NLA_EVAL_OFF;
+
+ case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
+
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
+
+ default: /* unsupported */
+ return 0;
+ }
+}
+
+/* get pointer to the setting */
+static void *acf_dspart_setting_ptr(bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting, short *type)
+{
+ /* clear extra return data first */
+ *type = 0;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return NULL;
+
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ return NULL;
+
+ default: /* unsupported */
+ return NULL;
+ }
+}
+
+/* particle expander type define */
+static bAnimChannelType ACF_DSPART =
+{
+ "Particle Data Expander", /* type name */
+ ACHANNEL_ROLE_EXPANDER, /* role */
+
+ acf_generic_dataexpand_color, /* backdrop color */
+ acf_generic_dataexpand_backdrop, /* backdrop */
+ acf_generic_indention_1, /* indent level */
+ acf_generic_basic_offset, /* offset */
+
+ acf_generic_idblock_name, /* name */
+ acf_generic_idblock_name_prop, /* name prop */
+ acf_dspart_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dspart_setting_flag, /* flag for setting */
+ acf_dspart_setting_ptr /* pointer for setting */
+};
+
/* MetaBall Expander ------------------------------------------- */
// TODO: just get this from RNA?
@@ -3495,6 +3584,7 @@ static void ANIM_init_channel_typeinfo_data(void)
animchannelTypeInfo[type++] = &ACF_DSSKEY; /* ShapeKey Channel */
animchannelTypeInfo[type++] = &ACF_DSWOR; /* World Channel */
animchannelTypeInfo[type++] = &ACF_DSNTREE; /* NodeTree Channel */
+ animchannelTypeInfo[type++] = &ACF_DSPART; /* Particle Channel */
animchannelTypeInfo[type++] = &ACF_DSMBALL; /* MetaBall Channel */
animchannelTypeInfo[type++] = &ACF_DSARM; /* Armature Channel */
animchannelTypeInfo[type++] = &ACF_DSMESH; /* Mesh Channel */
@@ -3774,15 +3864,21 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
/* for F-Curves, draw color-preview of curve behind checkbox */
if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
FCurve *fcu = (FCurve *)ale->data;
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* F-Curve channels need to have a special 'color code' box drawn, which is colored with whatever
* color the curve has stored
*/
- glColor3fv(fcu->color);
+ immUniformColor3fv(fcu->color);
/* just a solid color rect
*/
- glRectf(offset, yminc, offset + ICON_WIDTH, ymaxc);
+ immRectf(pos, offset, yminc, offset + ICON_WIDTH, ymaxc);
+
+ immUnbindProgram();
}
/* icon is drawn as widget now... */
if (acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
@@ -3823,11 +3919,22 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
/* draw red underline if channel is disabled */
if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE) && (ale->flag & FCURVE_DISABLED)) {
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* FIXME: replace hardcoded color here, and check on extents! */
- glColor3f(1.0f, 0.0f, 0.0f);
+ immUniformColor3f(1.0f, 0.0f, 0.0f);
+
glLineWidth(2.0);
- fdrawline((float)(offset), yminc,
- (float)(v2d->cur.xmax), yminc);
+
+ immBegin(GL_LINES, 2);
+ immVertex2f(pos, (float)offset, yminc);
+ immVertex2f(pos, (float)v2d->cur.xmax, yminc);
+ immEnd();
+
+ immUnbindProgram();
}
}
@@ -3841,10 +3948,14 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
short draw_sliders = 0;
float ymin_ofs = 0.0f;
float color[3];
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* get and set backdrop color */
acf->get_backdrop_color(ac, ale, color);
- glColor3fv(color);
+ immUniformColor3fv(color);
/* check if we need to show the sliders */
if ((ac->sl) && ELEM(ac->spacetype, SPACE_ACTION, SPACE_IPO)) {
@@ -3902,7 +4013,9 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
* - starts from the point where the first toggle/slider starts,
* - ends past the space that might be reserved for a scroller
*/
- glRectf(v2d->cur.xmax - (float)offset, yminc + ymin_ofs, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
+ immRectf(pos, v2d->cur.xmax - (float)offset, yminc + ymin_ofs, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
+
+ immUnbindProgram();
}
}
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 117b8549712..985ef1e13d2 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -57,6 +57,7 @@
#include "BKE_context.h"
#include "BKE_mask.h"
#include "BKE_global.h"
+#include "BKE_scene.h"
#include "UI_view2d.h"
@@ -2690,7 +2691,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
if (selectmode == SELECT_INVERT) {
/* swap select */
base->flag ^= SELECT;
- ob->flag = base->flag;
+ BKE_scene_base_flag_sync_from_base(base);
if (adt) adt->flag ^= ADT_UI_SELECTED;
}
@@ -2701,7 +2702,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
/* TODO: should this deselect all other types of channels too? */
for (b = sce->base.first; b; b = b->next) {
b->flag &= ~SELECT;
- b->object->flag = b->flag;
+ BKE_scene_base_flag_sync_from_base(b);
if (b->object->adt) b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE);
}
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c
index 1703210f0b6..c1e82583521 100644
--- a/source/blender/editors/animation/keyframes_general.c
+++ b/source/blender/editors/animation/keyframes_general.c
@@ -37,6 +37,7 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_string_utils.h"
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
@@ -668,7 +669,7 @@ static void flip_names(tAnimCopybufItem *aci, char **name)
/* more ninja stuff, temporary substitute with NULL terminator */
str_start[length] = 0;
- BKE_deform_flip_side_name(bname_new, str_start, false);
+ BLI_string_flip_side_name(bname_new, str_start, false, sizeof(bname_new));
str_start[length] = '\"';
str_iter = *name = MEM_mallocN(sizeof(char) * (prefix_l + postfix_l + length + 1), "flipped_path");
diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c
index 6228874343b..bbc81f522fa 100644
--- a/source/blender/editors/armature/armature_add.c
+++ b/source/blender/editors/armature/armature_add.c
@@ -39,6 +39,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_ghash.h"
+#include "BLI_string_utils.h"
#include "BKE_action.h"
#include "BKE_constraint.h"
@@ -619,9 +620,9 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op)
if (EBONE_VISIBLE(arm, ebone_iter) &&
(ebone_iter->flag & BONE_SELECTED))
{
- char name_flip[MAX_VGROUP_NAME];
+ char name_flip[MAXBONENAME];
- BKE_deform_flip_side_name(name_flip, ebone_iter->name, false);
+ BLI_string_flip_side_name(name_flip, ebone_iter->name, false, sizeof(name_flip));
if (STREQ(name_flip, ebone_iter->name)) {
/* if the name matches, we don't have the potential to be mirrored, just skip */
@@ -679,9 +680,9 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op)
/* will be set if the mirror bone already exists (no need to make a new one) */
(ebone_iter->temp.ebone == NULL))
{
- char name_flip[MAX_VGROUP_NAME];
+ char name_flip[MAXBONENAME];
- BKE_deform_flip_side_name(name_flip, ebone_iter->name, false);
+ BLI_string_flip_side_name(name_flip, ebone_iter->name, false, sizeof(name_flip));
/* bones must have a side-suffix */
if (!STREQ(name_flip, ebone_iter->name)) {
diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c
index 56dbdb3a639..fa192ed6f36 100644
--- a/source/blender/editors/armature/armature_naming.c
+++ b/source/blender/editors/armature/armature_naming.c
@@ -37,6 +37,8 @@
#include "BLI_blenlib.h"
#include "BLI_ghash.h"
+#include "BLI_string_utils.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -297,6 +299,55 @@ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *n
}
}
+typedef struct BoneFlipNameData {
+ struct BoneFlipNameData *next, *prev;
+ char *name;
+ char name_flip[MAXBONENAME];
+} BoneFlipNameData;
+
+/**
+ * Renames (by flipping) all selected bones at once.
+ *
+ * This way if we are flipping related bones (e.g., Bone.L, Bone.R) at the same time
+ * all the bones are safely renamed, without conflicting with each other.
+ *
+ * \param arm Armature the bones belong to
+ * \param bones ListBase of BoneConflict elems, populated via ED_armature_bones_flip_names_add
+ */
+void ED_armature_bones_flip_names(bArmature *arm, ListBase *bones_names)
+{
+ ListBase bones_names_conflicts = {NULL};
+ BoneFlipNameData *bfn;
+
+ /* First pass: generate flip names, and blindly rename.
+ * If rename did not yield expected result, store both bone's name and expected flipped one into temp list
+ * for second pass. */
+ for (LinkData *link = bones_names->first; link; link = link->next) {
+ char name_flip[MAXBONENAME];
+ char *name = link->data;
+
+ /* Do not strip numbers, otherwise we'll end up with completely mismatched names in cases like
+ * Bone.R, Bone.R.001, Bone.R.002, etc. */
+ BLI_string_flip_side_name(name_flip, name, false, sizeof(name_flip));
+
+ ED_armature_bone_rename(arm, name, name_flip);
+
+ if (!STREQ(name, name_flip)) {
+ bfn = alloca(sizeof(BoneFlipNameData));
+ bfn->name = name;
+ BLI_strncpy(bfn->name_flip, name_flip, sizeof(bfn->name_flip));
+ BLI_addtail(&bones_names_conflicts, bfn);
+ }
+ }
+
+ /* Second pass to handle the bones that have naming conflicts with other bones.
+ * Note that if the other bone was not selected, its name was not flipped, so conflict remains and that second
+ * rename simply generates a new numbered alternative name. */
+ for (bfn = bones_names_conflicts.first; bfn; bfn = bfn->next) {
+ ED_armature_bone_rename(arm, bfn->name, bfn->name_flip);
+ }
+}
+
/* ************************************************** */
/* Bone Renaming - EditMode */
@@ -304,20 +355,24 @@ static int armature_flip_names_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = CTX_data_edit_object(C);
bArmature *arm;
-
+
/* paranoia checks */
- if (ELEM(NULL, ob, ob->pose))
+ if (ELEM(NULL, ob, ob->pose))
return OPERATOR_CANCELLED;
+
arm = ob->data;
-
- /* loop through selected bones, auto-naming them */
+
+ ListBase bones_names= {NULL};
+
CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
{
- char name_flip[MAXBONENAME];
- BKE_deform_flip_side_name(name_flip, ebone->name, true);
- ED_armature_bone_rename(arm, ebone->name, name_flip);
+ BLI_addtail(&bones_names, BLI_genericNodeN(ebone->name));
}
CTX_DATA_END;
+
+ ED_armature_bones_flip_names(arm, &bones_names);
+
+ BLI_freelistN(&bones_names);
/* since we renamed stuff... */
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c
index b8127f68124..c913669a133 100644
--- a/source/blender/editors/armature/armature_relations.c
+++ b/source/blender/editors/armature/armature_relations.c
@@ -269,7 +269,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
if (!arm || arm->edbo)
return OPERATOR_CANCELLED;
- CTX_DATA_BEGIN(C, Base *, base, selected_editable_bases)
+ CTX_DATA_BEGIN(C, ObjectBase *, base, selected_editable_bases)
{
if (base->object == ob) {
ok = true;
@@ -291,7 +291,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
pose = ob->pose;
ob->mode &= ~OB_MODE_POSE;
- CTX_DATA_BEGIN(C, Base *, base, selected_editable_bases)
+ CTX_DATA_BEGIN(C, ObjectBase *, base, selected_editable_bases)
{
if ((base->object->type == OB_ARMATURE) && (base->object != ob)) {
tJoinArmature_AdtFixData afd = {NULL};
@@ -401,7 +401,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
}
/* Free the old object data */
- ED_base_object_free_and_unlink(bmain, scene, base);
+ ED_base_object_free_and_unlink(bmain, scene, base->object);
}
}
CTX_DATA_END;
@@ -578,7 +578,6 @@ static void separate_armature_bones(Object *ob, short sel)
/* separate selected bones into their armature */
static int separate_armature_exec(bContext *C, wmOperator *op)
{
-#if 0 /* TODO_LAYER */
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
SceneLayer *sl = CTX_data_scene_layer(C);
@@ -603,10 +602,14 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
/* 1) only edit-base selected */
/* TODO: use context iterators for this? */
- CTX_DATA_BEGIN(C, Base *, base, visible_bases)
+ CTX_DATA_BEGIN(C, ObjectBase *, base, visible_bases)
{
- if (base->object == obedit) base->flag |= SELECT;
- else base->flag &= ~SELECT;
+ if (base->object == obedit) {
+ ED_object_base_select(base, BA_SELECT);
+ }
+ else {
+ ED_object_base_select(base, BA_DESELECT);
+ }
}
CTX_DATA_END;
@@ -620,7 +623,7 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
ED_armature_edit_free(obedit->data);
/* 2) duplicate base */
- newbase = ED_object_add_duplicate(bmain, scene, oldbase, USER_DUP_ARM); /* only duplicate linked armature */
+ newbase = ED_object_add_duplicate(bmain, scene, sl, oldbase, USER_DUP_ARM); /* only duplicate linked armature */
DAG_relations_tag_update(bmain);
newob = newbase->object;
@@ -656,13 +659,6 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
WM_cursor_wait(0);
return OPERATOR_FINISHED;
-#else
- (void)C;
- (void)op;
- (void)separate_armature_bones;
- (void)separated_armature_fix_links;
- return OPERATOR_CANCELLED;
-#endif
}
void ARMATURE_OT_separate(wmOperatorType *ot)
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index 5a70a45fad4..e9946abba0b 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -35,9 +35,10 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_string_utils.h"
#include "BKE_context.h"
-#include "BKE_deform.h"
+//#include "BKE_deform.h"
#include "BKE_report.h"
#include "BIF_gl.h"
@@ -817,10 +818,10 @@ static void select_similar_prefix(bArmature *arm, EditBone *ebone_act)
{
EditBone *ebone;
- char body_tmp[MAX_VGROUP_NAME];
- char prefix_act[MAX_VGROUP_NAME];
+ char body_tmp[MAXBONENAME];
+ char prefix_act[MAXBONENAME];
- BKE_deform_split_prefix(ebone_act->name, prefix_act, body_tmp);
+ BLI_string_split_prefix(ebone_act->name, prefix_act, body_tmp, sizeof(ebone_act->name));
if (prefix_act[0] == '\0')
return;
@@ -828,8 +829,8 @@ static void select_similar_prefix(bArmature *arm, EditBone *ebone_act)
/* Find matches */
for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
if (EBONE_SELECTABLE(arm, ebone)) {
- char prefix_other[MAX_VGROUP_NAME];
- BKE_deform_split_prefix(ebone->name, prefix_other, body_tmp);
+ char prefix_other[MAXBONENAME];
+ BLI_string_split_prefix(ebone->name, prefix_other, body_tmp, sizeof(ebone->name));
if (STREQ(prefix_act, prefix_other)) {
ED_armature_ebone_select_set(ebone, true);
}
@@ -841,10 +842,10 @@ static void select_similar_suffix(bArmature *arm, EditBone *ebone_act)
{
EditBone *ebone;
- char body_tmp[MAX_VGROUP_NAME];
- char suffix_act[MAX_VGROUP_NAME];
+ char body_tmp[MAXBONENAME];
+ char suffix_act[MAXBONENAME];
- BKE_deform_split_suffix(ebone_act->name, body_tmp, suffix_act);
+ BLI_string_split_suffix(ebone_act->name, body_tmp, suffix_act, sizeof(ebone_act->name));
if (suffix_act[0] == '\0')
return;
@@ -852,8 +853,8 @@ static void select_similar_suffix(bArmature *arm, EditBone *ebone_act)
/* Find matches */
for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
if (EBONE_SELECTABLE(arm, ebone)) {
- char suffix_other[MAX_VGROUP_NAME];
- BKE_deform_split_suffix(ebone->name, body_tmp, suffix_other);
+ char suffix_other[MAXBONENAME];
+ BLI_string_split_suffix(ebone->name, body_tmp, suffix_other, sizeof(ebone->name));
if (STREQ(suffix_act, suffix_other)) {
ED_armature_ebone_select_set(ebone, true);
}
diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c
index 28fddbab796..e8d41f722d7 100644
--- a/source/blender/editors/armature/armature_skinning.c
+++ b/source/blender/editors/armature/armature_skinning.c
@@ -39,6 +39,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_string_utils.h"
#include "BKE_action.h"
#include "BKE_armature.h"
@@ -360,7 +361,7 @@ static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob,
if (dgroup && mirror) {
char name_flip[MAXBONENAME];
- BKE_deform_flip_side_name(name_flip, dgroup->name, false);
+ BLI_string_flip_side_name(name_flip, dgroup->name, false, sizeof(name_flip));
dgroupflip[j] = defgroup_find_name(ob, name_flip);
}
}
diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c
index 6979a324b69..a3b439536b7 100644
--- a/source/blender/editors/armature/armature_utils.c
+++ b/source/blender/editors/armature/armature_utils.c
@@ -34,6 +34,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_string_utils.h"
#include "BKE_armature.h"
#include "BKE_context.h"
@@ -262,7 +263,7 @@ EditBone *ED_armature_bone_get_mirrored(const ListBase *edbo, EditBone *ebo)
if (ebo == NULL)
return NULL;
- BKE_deform_flip_side_name(name_flip, ebo->name, false);
+ BLI_string_flip_side_name(name_flip, ebo->name, false, sizeof(name_flip));
if (!STREQ(name_flip, ebo->name)) {
return ED_armature_bone_find_name(edbo, name_flip);
diff --git a/source/blender/editors/armature/editarmature_retarget.c b/source/blender/editors/armature/editarmature_retarget.c
index fa7bf6e7ad4..a81f0f9d67d 100644
--- a/source/blender/editors/armature/editarmature_retarget.c
+++ b/source/blender/editors/armature/editarmature_retarget.c
@@ -2518,7 +2518,7 @@ void BIF_retargetArmature(bContext *C)
printf("Reeb Graph created\n");
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
Object *ob = base->object;
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index 1c1d7297e63..d54da7830d4 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -593,20 +593,24 @@ static int pose_flip_names_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
bArmature *arm;
-
+
/* paranoia checks */
if (ELEM(NULL, ob, ob->pose))
return OPERATOR_CANCELLED;
+
arm = ob->data;
-
- /* loop through selected bones, auto-naming them */
+
+ ListBase bones_names = {NULL};
+
CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
{
- char name_flip[MAXBONENAME];
- BKE_deform_flip_side_name(name_flip, pchan->name, true);
- ED_armature_bone_rename(arm, pchan->name, name_flip);
+ BLI_addtail(&bones_names, BLI_genericNodeN(pchan->name));
}
CTX_DATA_END;
+
+ ED_armature_bones_flip_names(arm, &bones_names);
+
+ BLI_freelistN(&bones_names);
/* since we renamed stuff... */
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c
index 9309592bb46..e3c64b523b1 100644
--- a/source/blender/editors/armature/pose_lib.c
+++ b/source/blender/editors/armature/pose_lib.c
@@ -34,6 +34,7 @@
#include "BLI_blenlib.h"
#include "BLI_dlrbTree.h"
+#include "BLI_string_utils.h"
#include "BLT_translation.h"
diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c
index b645f1fb2f3..063ba37f20d 100644
--- a/source/blender/editors/armature/pose_transform.c
+++ b/source/blender/editors/armature/pose_transform.c
@@ -36,6 +36,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_string_utils.h"
#include "BKE_animsys.h"
#include "BKE_action.h"
@@ -286,7 +287,7 @@ static bPoseChannel *pose_bone_do_paste(Object *ob, bPoseChannel *chan, const bo
/* get the name - if flipping, we must flip this first */
if (flip)
- BKE_deform_flip_side_name(name, chan->name, false);
+ BLI_string_flip_side_name(name, chan->name, false, sizeof(name));
else
BLI_strncpy(name, chan->name, sizeof(name));
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 7f8199300d6..cd153b2855c 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -1269,9 +1269,9 @@ void ED_curve_editnurb_free(Object *obedit)
static int separate_exec(bContext *C, wmOperator *op)
{
-#if 0
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *oldob, *newob;
ObjectBase *oldbase, *newbase;
Curve *oldcu, *newcu;
@@ -1299,7 +1299,7 @@ static int separate_exec(bContext *C, wmOperator *op)
}
/* 2. duplicate the object and data */
- newbase = ED_object_add_duplicate(bmain, scene, oldbase, 0); /* 0 = fully linked */
+ newbase = ED_object_add_duplicate(bmain, scene, sl, oldbase, 0); /* 0 = fully linked */
DAG_relations_tag_update(bmain);
newob = newbase->object;
@@ -1329,13 +1329,6 @@ static int separate_exec(bContext *C, wmOperator *op)
WM_cursor_wait(0);
return OPERATOR_FINISHED;
-#else
- /* need to refactor this to use ObjectBase and create a new object in the correct SceneCollection */
- TODO_LAYER_BASE
- (void)C;
- BKE_report(op->reports, RPT_ERROR, "CURVE_OT_separate not supported at the moment");
- return OPERATOR_CANCELLED;
-#endif
}
void CURVE_OT_separate(wmOperatorType *ot)
@@ -5970,7 +5963,7 @@ int join_curve_exec(bContext *C, wmOperator *op)
int a;
bool ok = false;
- CTX_DATA_BEGIN(C, Base *, base, selected_editable_bases)
+ CTX_DATA_BEGIN(C, ObjectBase *, base, selected_editable_bases)
{
if (base->object == ob) {
ok = true;
@@ -5990,7 +5983,7 @@ int join_curve_exec(bContext *C, wmOperator *op)
/* trasnform all selected curves inverse in obact */
invert_m4_m4(imat, ob->obmat);
- CTX_DATA_BEGIN(C, Base *, base, selected_editable_bases)
+ CTX_DATA_BEGIN(C, ObjectBase *, base, selected_editable_bases)
{
if (base->object->type == ob->type) {
if (base->object != ob) {
@@ -6033,7 +6026,7 @@ int join_curve_exec(bContext *C, wmOperator *op)
}
}
- ED_base_object_free_and_unlink(bmain, scene, base);
+ ED_base_object_free_and_unlink(bmain, scene, base->object);
}
}
}
diff --git a/source/blender/editors/gpencil/CMakeLists.txt b/source/blender/editors/gpencil/CMakeLists.txt
index 6604d595573..3d5317b2ebd 100644
--- a/source/blender/editors/gpencil/CMakeLists.txt
+++ b/source/blender/editors/gpencil/CMakeLists.txt
@@ -44,6 +44,7 @@ set(SRC
gpencil_convert.c
gpencil_data.c
gpencil_edit.c
+ gpencil_interpolate.c
gpencil_ops.c
gpencil_paint.c
gpencil_select.c
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index 8a4ba6687cd..e8a812817d1 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -1632,7 +1632,7 @@ static void gp_draw_data_all(Scene *scene, bGPdata *gpd, int offsx, int offsy, i
{
bGPdata *gpd_source = NULL;
ToolSettings *ts;
- bGPDbrush *brush;
+ bGPDbrush *brush = NULL;
if (scene) {
ts = scene->toolsettings;
brush = BKE_gpencil_brush_getactive(ts);
@@ -1641,8 +1641,7 @@ static void gp_draw_data_all(Scene *scene, bGPdata *gpd, int offsx, int offsy, i
BKE_gpencil_brush_init_presets(ts);
brush = BKE_gpencil_brush_getactive(ts);
}
- }
- if (scene) {
+
if (spacetype == SPACE_VIEW3D) {
gpd_source = (scene->gpd ? scene->gpd : NULL);
}
diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c
index d0f68c4b8f3..a004d7806b2 100644
--- a/source/blender/editors/gpencil/gpencil_convert.c
+++ b/source/blender/editors/gpencil/gpencil_convert.c
@@ -1217,7 +1217,8 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
/* set the layer and select */
base_new->lay = ob->lay = base_orig ? base_orig->lay : BKE_screen_view3d_layer_active(v3d, scene);
- base_new->flag = ob->flag = base_new->flag | SELECT;
+ base_new->flag |= SELECT;
+ BKE_scene_base_flag_sync_from_base(base_new);
}
/* --- */
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index ae83e899649..6980ad46241 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -42,6 +42,7 @@
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "BLI_math.h"
+#include "BLI_string_utils.h"
#include "BLT_translation.h"
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 15f65b394a9..5b011b679a6 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -682,6 +682,87 @@ void GPENCIL_OT_move_to_layer(wmOperatorType *ot)
RNA_def_enum_funcs(ot->prop, ED_gpencil_layers_with_new_enum_itemf);
}
+/* ********************* Add Blank Frame *************************** */
+
+/* Basically the same as the drawing op */
+static int UNUSED_FUNCTION(gp_blank_frame_add_poll)(bContext *C)
+{
+ if (ED_operator_regionactive(C)) {
+ /* check if current context can support GPencil data */
+ if (ED_gpencil_data_get_pointers(C, NULL) != NULL) {
+ return 1;
+ }
+ else {
+ CTX_wm_operator_poll_msg_set(C, "Failed to find Grease Pencil data to draw into");
+ }
+ }
+ else {
+ CTX_wm_operator_poll_msg_set(C, "Active region not set");
+ }
+
+ return 0;
+}
+
+static int gp_blank_frame_add_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+ bGPDlayer *active_gpl = BKE_gpencil_layer_getactive(gpd);
+
+ const bool all_layers = RNA_boolean_get(op->ptr, "all_layers");
+
+ /* Initialise datablock and an active layer if nothing exists yet */
+ if (ELEM(NULL, gpd, active_gpl)) {
+ /* let's just be lazy, and call the "Add New Layer" operator, which sets everything up as required */
+ WM_operator_name_call(C, "GPENCIL_OT_layer_add", WM_OP_EXEC_DEFAULT, NULL);
+ }
+
+ /* Go through each layer, adding a frame after the active one
+ * and/or shunting all the others out of the way
+ */
+ CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
+ {
+ if ((all_layers == false) && (gpl != active_gpl)) {
+ continue;
+ }
+
+ /* 1) Check for an existing frame on the current frame */
+ bGPDframe *gpf = BKE_gpencil_layer_find_frame(gpl, CFRA);
+ if (gpf) {
+ /* Shunt all frames after (and including) the existing one later by 1-frame */
+ for (; gpf; gpf = gpf->next) {
+ gpf->framenum += 1;
+ }
+ }
+
+ /* 2) Now add a new frame, with nothing in it */
+ gpl->actframe = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_NEW);
+ }
+ CTX_DATA_END;
+
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_blank_frame_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Blank Frame";
+ ot->idname = "GPENCIL_OT_blank_frame_add";
+ ot->description = "Add a new frame with nothing in it on the current frame. "
+ "If there is already a frame, all existing frames are shifted one frame later";
+
+ /* callbacks */
+ ot->exec = gp_blank_frame_add_exec;
+ ot->poll = gp_add_poll;
+
+ /* properties */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ RNA_def_boolean(ot->srna, "all_layers", false, "All Layers", "Create blank frame in all layers, not only active");
+}
+
/* ******************* Delete Active Frame ************************ */
static int gp_actframe_delete_poll(bContext *C)
@@ -1897,6 +1978,13 @@ void GPENCIL_OT_stroke_flip(wmOperatorType *ot)
/* ***************** Reproject Strokes ********************** */
+typedef enum eGP_ReprojectModes {
+ /* On same plane, parallel to viewplane */
+ GP_REPROJECT_PLANAR = 0,
+ /* Reprojected on to the scene geometry */
+ GP_REPROJECT_SURFACE,
+} eGP_ReprojectModes;
+
static int gp_strokes_reproject_poll(bContext *C)
{
/* 2 Requirements:
@@ -1906,14 +1994,23 @@ static int gp_strokes_reproject_poll(bContext *C)
return (gp_stroke_edit_poll(C) && ED_operator_view3d_active(C));
}
-static int gp_strokes_reproject_exec(bContext *C, wmOperator *UNUSED(op))
+static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
GP_SpaceConversion gsc = {NULL};
+ eGP_ReprojectModes mode = RNA_boolean_get(op->ptr, "type");
/* init space conversion stuff */
gp_point_conversion_init(C, &gsc);
+ /* init autodist for geometry projection */
+ if (mode == GP_REPROJECT_SURFACE) {
+ view3d_region_operator_needs_opengl(CTX_wm_window(C), gsc.ar);
+ ED_view3d_autodist_init(scene, gsc.ar, CTX_wm_view3d(C), 0);
+ }
+
+ // TODO: For deforming geometry workflow, create new frames?
+
/* Go through each editable + selected stroke, adjusting each of its points one by one... */
GP_EDITABLE_STROKES_BEGIN(C, gpl, gps)
{
@@ -1949,7 +2046,27 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *UNUSED(op))
/* Project screenspace back to 3D space (from current perspective)
* so that all points have been treated the same way
*/
- gp_point_xy_to_3d(&gsc, scene, xy, &pt->x);
+ if (mode == GP_REPROJECT_PLANAR) {
+ /* Planar - All on same plane parallel to the viewplane */
+ gp_point_xy_to_3d(&gsc, scene, xy, &pt->x);
+ }
+ else {
+ /* Geometry - Snap to surfaces of visible geometry */
+ /* XXX: There will be precision loss (possible stairstep artifacts) from this conversion to satisfy the API's */
+ const int screen_co[2] = {(int)xy[0], (int)xy[1]};
+
+ int depth_margin = 0; // XXX: 4 for strokes, 0 for normal
+ float depth;
+
+ /* XXX: The proper procedure computes the depths into an array, to have smooth transitions when all else fails... */
+ if (ED_view3d_autodist_depth(gsc.ar, screen_co, depth_margin, &depth)) {
+ ED_view3d_autodist_simple(gsc.ar, screen_co, &pt->x, 0, &depth);
+ }
+ else {
+ /* Default to planar */
+ gp_point_xy_to_3d(&gsc, scene, xy, &pt->x);
+ }
+ }
/* Unapply parent corrections */
if (gpl->parent) {
@@ -1966,21 +2083,36 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *UNUSED(op))
void GPENCIL_OT_reproject(wmOperatorType *ot)
{
+ static EnumPropertyItem reproject_type[] = {
+ {GP_REPROJECT_PLANAR, "PLANAR", 0, "Planar",
+ "Reproject the strokes to end up on the same plane, as if drawn from the current viewpoint "
+ "using 'Cursor' Stroke Placement"},
+ {GP_REPROJECT_SURFACE, "SURFACE", 0, "Surface",
+ "Reproject the strokes on to the scene geometry, as if drawn using 'Surface' placement"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
/* identifiers */
ot->name = "Reproject Strokes";
ot->idname = "GPENCIL_OT_reproject";
- ot->description = "Reproject the selected strokes from the current viewpoint to get all points on the same plane again "
- "(e.g. to fix problems from accidental 3D cursor movement, or viewport changes)";
+ ot->description = "Reproject the selected strokes from the current viewpoint as if they had been newly drawn "
+ "(e.g. to fix problems from accidental 3D cursor movement or accidental viewport changes, "
+ "or for matching deforming geometry)";
/* callbacks */
+ ot->invoke = WM_menu_invoke;
ot->exec = gp_strokes_reproject_exec;
ot->poll = gp_strokes_reproject_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "type", reproject_type, GP_REPROJECT_PLANAR, "Projection Type", "");
}
/* ******************* Stroke subdivide ************************** */
+
/* helper: Count how many points need to be inserted */
static int gp_count_subdivision_cuts(bGPDstroke *gps)
{
@@ -2098,673 +2230,3 @@ void GPENCIL_OT_stroke_subdivide(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-
-/* ========= Interpolation operators ========================== */
-/* Helper: Update point with interpolation */
-static void gp_interpolate_update_points(bGPDstroke *gps_from, bGPDstroke *gps_to, bGPDstroke *new_stroke, float factor)
-{
- bGPDspoint *prev, *pt, *next;
-
- /* update points */
- for (int i = 0; i < new_stroke->totpoints; i++) {
- prev = &gps_from->points[i];
- pt = &new_stroke->points[i];
- next = &gps_to->points[i];
-
- /* Interpolate all values */
- interp_v3_v3v3(&pt->x, &prev->x, &next->x, factor);
- pt->pressure = interpf(prev->pressure, next->pressure, factor);
- pt->strength = interpf(prev->strength, next->strength, factor);
- CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
- }
-}
-
-/* Helper: Update all strokes interpolated */
-static void gp_interpolate_update_strokes(bContext *C, tGPDinterpolate *tgpi)
-{
- tGPDinterpolate_layer *tgpil;
- bGPDstroke *new_stroke, *gps_from, *gps_to;
- int cStroke;
- float factor;
- float shift = tgpi->shift;
-
- for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) {
- factor = tgpil->factor + shift;
- for (new_stroke = tgpil->interFrame->strokes.first; new_stroke; new_stroke = new_stroke->next) {
- if (new_stroke->totpoints == 0) {
- continue;
- }
- /* get strokes to interpolate */
- cStroke = BLI_findindex(&tgpil->interFrame->strokes, new_stroke);
- gps_from = BLI_findlink(&tgpil->prevFrame->strokes, cStroke);
- gps_to = BLI_findlink(&tgpil->nextFrame->strokes, cStroke);
- /* update points position */
- if ((gps_from) && (gps_to)) {
- gp_interpolate_update_points(gps_from, gps_to, new_stroke, factor);
- }
- }
- }
-
- WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
-}
-
-/* Helper: Verify valid strokes for interpolation */
-static bool gp_interpolate_check_todo(bContext *C, bGPdata *gpd)
-{
- ToolSettings *ts = CTX_data_tool_settings(C);
- int flag = ts->gp_sculpt.flag;
-
- bGPDlayer *gpl;
- bGPDlayer *active_gpl = CTX_data_active_gpencil_layer(C);
- bGPDstroke *gps_from, *gps_to;
- int fFrame;
-
- /* get layers */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* all layers or only active */
- if (((flag & GP_BRUSHEDIT_FLAG_INTERPOLATE_ALL_LAYERS) == 0) && (gpl != active_gpl)) {
- continue;
- }
- /* only editable and visible layers are considered */
- if (!gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
- continue;
- }
- /* read strokes */
- for (gps_from = gpl->actframe->strokes.first; gps_from; gps_from = gps_from->next) {
- /* only selected */
- if ((flag & GP_BRUSHEDIT_FLAG_INTERPOLATE_ONLY_SELECTED) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) {
- continue;
- }
- /* skip strokes that are invalid for current view */
- if (ED_gpencil_stroke_can_use(C, gps_from) == false) {
- continue;
- }
- /* check if the color is editable */
- if (ED_gpencil_stroke_color_use(gpl, gps_from) == false) {
- continue;
- }
- /* get final stroke to interpolate */
- fFrame = BLI_findindex(&gpl->actframe->strokes, gps_from);
- gps_to = BLI_findlink(&gpl->actframe->next->strokes, fFrame);
- if (gps_to == NULL) {
- continue;
- }
- return 1;
- }
- }
- return 0;
-}
-
-/* Helper: Create internal strokes interpolated */
-static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
-{
- bGPDlayer *gpl;
- bGPdata *gpd = tgpi->gpd;
- tGPDinterpolate_layer *tgpil;
- bGPDlayer *active_gpl = CTX_data_active_gpencil_layer(C);
- bGPDstroke *gps_from, *gps_to, *new_stroke;
- int fFrame;
-
- /* save initial factor for active layer to define shift limits */
- tgpi->init_factor = (float)(tgpi->cframe - active_gpl->actframe->framenum) / (active_gpl->actframe->next->framenum - active_gpl->actframe->framenum + 1);
- /* limits are 100% below 0 and 100% over the 100% */
- tgpi->low_limit = -1.0f - tgpi->init_factor;
- tgpi->high_limit = 2.0f - tgpi->init_factor;
-
- /* set layers */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* all layers or only active */
- if (((tgpi->flag & GP_BRUSHEDIT_FLAG_INTERPOLATE_ALL_LAYERS) == 0) && (gpl != active_gpl)) {
- continue;
- }
- /* only editable and visible layers are considered */
- if (!gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
- continue;
- }
- /* create temp data for each layer */
- tgpil = NULL;
- tgpil = MEM_callocN(sizeof(tGPDinterpolate_layer), "GPencil Interpolate Layer");
-
- tgpil->gpl = gpl;
- tgpil->prevFrame = gpl->actframe;
- tgpil->nextFrame = gpl->actframe->next;
-
- BLI_addtail(&tgpi->ilayers, tgpil);
- /* create a new temporary frame */
- tgpil->interFrame = MEM_callocN(sizeof(bGPDframe), "bGPDframe");
- tgpil->interFrame->framenum = tgpi->cframe;
-
- /* get interpolation factor by layer (usually must be equal for all layers, but not sure) */
- tgpil->factor = (float)(tgpi->cframe - tgpil->prevFrame->framenum) / (tgpil->nextFrame->framenum - tgpil->prevFrame->framenum + 1);
- /* create new strokes data with interpolated points reading original stroke */
- for (gps_from = tgpil->prevFrame->strokes.first; gps_from; gps_from = gps_from->next) {
- bool valid = true;
- /* only selected */
- if ((tgpi->flag & GP_BRUSHEDIT_FLAG_INTERPOLATE_ONLY_SELECTED) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) {
- valid = false;
- }
-
- /* skip strokes that are invalid for current view */
- if (ED_gpencil_stroke_can_use(C, gps_from) == false) {
- valid = false;
- }
- /* check if the color is editable */
- if (ED_gpencil_stroke_color_use(tgpil->gpl, gps_from) == false) {
- valid = false;
- }
- /* get final stroke to interpolate */
- fFrame = BLI_findindex(&tgpil->prevFrame->strokes, gps_from);
- gps_to = BLI_findlink(&tgpil->nextFrame->strokes, fFrame);
- if (gps_to == NULL) {
- valid = false;
- }
- /* create new stroke */
- new_stroke = MEM_dupallocN(gps_from);
- new_stroke->points = MEM_dupallocN(gps_from->points);
- new_stroke->triangles = MEM_dupallocN(gps_from->triangles);
- if (valid) {
- /* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */
- if (gps_from->totpoints > gps_to->totpoints) {
- new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points) * gps_to->totpoints);
- new_stroke->totpoints = gps_to->totpoints;
- new_stroke->tot_triangles = 0;
- new_stroke->flag |= GP_STROKE_RECALC_CACHES;
- }
- /* update points position */
- gp_interpolate_update_points(gps_from, gps_to, new_stroke, tgpil->factor);
- }
- else {
- /* need an empty stroke to keep index correct for lookup, but resize to smallest size */
- new_stroke->totpoints = 0;
- new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points));
- new_stroke->tot_triangles = 0;
- new_stroke->triangles = MEM_recallocN(new_stroke->triangles, sizeof(*new_stroke->triangles));
- }
- /* add to strokes */
- BLI_addtail(&tgpil->interFrame->strokes, new_stroke);
- }
- }
-}
-
-/* Helper: calculate shift based on position of mouse (we only use x-axis for now.
-* since this is more convenient for users to do), and store new shift value
-*/
-static void gpencil_mouse_update_shift(tGPDinterpolate *tgpi, wmOperator *op, const wmEvent *event)
-{
- float mid = (float)(tgpi->ar->winx - tgpi->ar->winrct.xmin) / 2.0f;
- float mpos = event->x - tgpi->ar->winrct.xmin;
- if (mpos >= mid) {
- tgpi->shift = ((mpos - mid) * tgpi->high_limit) / mid;
- }
- else {
- tgpi->shift = tgpi->low_limit - ((mpos * tgpi->low_limit) / mid);
- }
-
- CLAMP(tgpi->shift, tgpi->low_limit, tgpi->high_limit);
- RNA_float_set(op->ptr, "shift", tgpi->shift);
-}
-
-/* Helper: Draw status message while the user is running the operator */
-static void gpencil_interpolate_status_indicators(tGPDinterpolate *p)
-{
- Scene *scene = p->scene;
- char status_str[UI_MAX_DRAW_STR];
- char msg_str[UI_MAX_DRAW_STR];
- BLI_strncpy(msg_str, IFACE_("GPencil Interpolation: ESC/RMB to cancel, Enter/LMB to confirm, WHEEL/MOVE to adjust, Factor"), UI_MAX_DRAW_STR);
-
- if (hasNumInput(&p->num)) {
- char str_offs[NUM_STR_REP_LEN];
-
- outputNumInput(&p->num, str_offs, &scene->unit);
-
- BLI_snprintf(status_str, sizeof(status_str), "%s: %s", msg_str, str_offs);
- }
- else {
- BLI_snprintf(status_str, sizeof(status_str), "%s: %d %%", msg_str, (int)((p->init_factor + p->shift) * 100.0f));
- }
-
- ED_area_headerprint(p->sa, status_str);
-}
-
-/* Helper: Update screen and stroke */
-static void gpencil_interpolate_update(bContext *C, wmOperator *op, tGPDinterpolate *tgpi)
-{
- /* update shift indicator in header */
- gpencil_interpolate_status_indicators(tgpi);
- /* apply... */
- tgpi->shift = RNA_float_get(op->ptr, "shift");
- /* update points position */
- gp_interpolate_update_strokes(C, tgpi);
-}
-
-/* init new temporary interpolation data */
-static bool gp_interpolate_set_init_values(bContext *C, wmOperator *op, tGPDinterpolate *tgpi)
-{
- ToolSettings *ts = CTX_data_tool_settings(C);
- bGPdata *gpd = CTX_data_gpencil_data(C);
-
- /* set current scene and window */
- tgpi->scene = CTX_data_scene(C);
- tgpi->sa = CTX_wm_area(C);
- tgpi->ar = CTX_wm_region(C);
- tgpi->flag = ts->gp_sculpt.flag;
-
- /* set current frame number */
- tgpi->cframe = tgpi->scene->r.cfra;
-
- /* set GP datablock */
- tgpi->gpd = gpd;
-
- /* set interpolation weight */
- tgpi->shift = RNA_float_get(op->ptr, "shift");
- /* set layers */
- gp_interpolate_set_points(C, tgpi);
-
- return 1;
-}
-
-/* Poll handler: check if context is suitable for interpolation */
-static int gpencil_interpolate_poll(bContext *C)
-{
- bGPdata * gpd = CTX_data_gpencil_data(C);
- bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
- /* only 3D view */
- if (CTX_wm_area(C)->spacetype != SPACE_VIEW3D) {
- return 0;
- }
- /* need data to interpolate */
- if (ELEM(NULL, gpd, gpl)) {
- return 0;
- }
-
- return 1;
-}
-
-/* Allocate memory and initialize values */
-static tGPDinterpolate *gp_session_init_interpolation(bContext *C, wmOperator *op)
-{
- tGPDinterpolate *tgpi = NULL;
-
- /* create new context data */
- tgpi = MEM_callocN(sizeof(tGPDinterpolate), "GPencil Interpolate Data");
-
- /* define initial values */
- gp_interpolate_set_init_values(C, op, tgpi);
-
- /* return context data for running operator */
- return tgpi;
-}
-
-/* Exit and free memory */
-static void gpencil_interpolate_exit(bContext *C, wmOperator *op)
-{
- tGPDinterpolate *tgpi = op->customdata;
- tGPDinterpolate_layer *tgpil;
-
- /* don't assume that operator data exists at all */
- if (tgpi) {
- /* remove drawing handler */
- if (tgpi->draw_handle_screen) {
- ED_region_draw_cb_exit(tgpi->ar->type, tgpi->draw_handle_screen);
- }
- if (tgpi->draw_handle_3d) {
- ED_region_draw_cb_exit(tgpi->ar->type, tgpi->draw_handle_3d);
- }
- /* clear status message area */
- ED_area_headerprint(tgpi->sa, NULL);
- /* finally, free memory used by temp data */
- for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) {
- BKE_gpencil_free_strokes(tgpil->interFrame);
- MEM_freeN(tgpil->interFrame);
- }
-
- BLI_freelistN(&tgpi->ilayers);
- MEM_freeN(tgpi);
- }
- WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
-
- /* clear pointer */
- op->customdata = NULL;
-}
-
-/* Cancel handler */
-static void gpencil_interpolate_cancel(bContext *C, wmOperator *op)
-{
- /* this is just a wrapper around exit() */
- gpencil_interpolate_exit(C, op);
-}
-
-/* Init interpolation: Allocate memory and set init values */
-static int gpencil_interpolate_init(bContext *C, wmOperator *op)
-{
- tGPDinterpolate *tgpi;
- /* check context */
- tgpi = op->customdata = gp_session_init_interpolation(C, op);
- if (tgpi == NULL) {
- /* something wasn't set correctly in context */
- gpencil_interpolate_exit(C, op);
- return 0;
- }
-
- /* everything is now setup ok */
- return 1;
-}
-
-/* ********************** custom drawcall api ***************** */
-/* Helper: drawing callback for modal operator in screen mode */
-static void gpencil_interpolate_draw_screen(const struct bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg)
-{
- wmOperator *op = arg;
- struct tGPDinterpolate *tgpi = op->customdata;
- ED_gp_draw_interpolation(tgpi, REGION_DRAW_POST_PIXEL);
-}
-
-/* Helper: drawing callback for modal operator in 3d mode */
-static void gpencil_interpolate_draw_3d(const struct bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg)
-{
- wmOperator *op = arg;
- struct tGPDinterpolate *tgpi = op->customdata;
- ED_gp_draw_interpolation(tgpi, REGION_DRAW_POST_VIEW);
-}
-
-/* Invoke handler: Initialize the operator */
-static int gpencil_interpolate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
-{
- wmWindow *win = CTX_wm_window(C);
- Scene *scene = CTX_data_scene(C);
- bGPdata * gpd = CTX_data_gpencil_data(C);
- bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
- tGPDinterpolate *tgpi = NULL;
-
- /* cannot interpolate if not between 2 frames */
- if ((gpl->actframe == NULL) || (gpl->actframe->next == NULL)) {
- BKE_report(op->reports, RPT_ERROR, "Interpolation requires to be between two grease pencil frames in active layer");
- return OPERATOR_CANCELLED;
- }
-
- /* cannot interpolate in extremes */
- if ((gpl->actframe->framenum == scene->r.cfra) || (gpl->actframe->next->framenum == scene->r.cfra)) {
- BKE_report(op->reports, RPT_ERROR, "Interpolation requires to be between two grease pencil frames in active layer");
- return OPERATOR_CANCELLED;
- }
-
- /* need editable strokes */
- if (!gp_interpolate_check_todo(C, gpd)) {
- BKE_report(op->reports, RPT_ERROR, "Interpolation requires some editable stroke");
- return OPERATOR_CANCELLED;
- }
-
- /* try to initialize context data needed */
- if (!gpencil_interpolate_init(C, op)) {
- if (op->customdata)
- MEM_freeN(op->customdata);
- return OPERATOR_CANCELLED;
- }
- else
- tgpi = op->customdata;
-
- /* enable custom drawing handlers. It needs 2 handlers because can be strokes in 3d space and screen space and each handler use different
- coord system */
- tgpi->draw_handle_screen = ED_region_draw_cb_activate(tgpi->ar->type, gpencil_interpolate_draw_screen, op, REGION_DRAW_POST_PIXEL);
- tgpi->draw_handle_3d = ED_region_draw_cb_activate(tgpi->ar->type, gpencil_interpolate_draw_3d, op, REGION_DRAW_POST_VIEW);
- /* set cursor to indicate modal */
- WM_cursor_modal_set(win, BC_EW_SCROLLCURSOR);
- /* update shift indicator in header */
- gpencil_interpolate_status_indicators(tgpi);
- WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
-
- /* add a modal handler for this operator */
- WM_event_add_modal_handler(C, op);
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-/* Modal handler: Events handling during interactive part */
-static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- tGPDinterpolate *tgpi = op->customdata;
- wmWindow *win = CTX_wm_window(C);
- bGPDframe *gpf_dst;
- bGPDstroke *gps_src, *gps_dst;
- tGPDinterpolate_layer *tgpil;
- const bool has_numinput = hasNumInput(&tgpi->num);
-
- switch (event->type) {
- case LEFTMOUSE: /* confirm */
- case RETKEY:
- {
- /* return to normal cursor and header status */
- ED_area_headerprint(tgpi->sa, NULL);
- WM_cursor_modal_restore(win);
-
- /* insert keyframes as required... */
- for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) {
- gpf_dst = BKE_gpencil_layer_getframe(tgpil->gpl, tgpi->cframe, GP_GETFRAME_ADD_NEW);
- gpf_dst->key_type = BEZT_KEYTYPE_BREAKDOWN;
-
- /* copy strokes */
- BLI_listbase_clear(&gpf_dst->strokes);
- for (gps_src = tgpil->interFrame->strokes.first; gps_src; gps_src = gps_src->next) {
- if (gps_src->totpoints == 0) {
- continue;
- }
- /* make copy of source stroke, then adjust pointer to points too */
- gps_dst = MEM_dupallocN(gps_src);
- gps_dst->points = MEM_dupallocN(gps_src->points);
- gps_dst->triangles = MEM_dupallocN(gps_src->triangles);
- gps_dst->flag |= GP_STROKE_RECALC_CACHES;
- BLI_addtail(&gpf_dst->strokes, gps_dst);
- }
- }
- /* clean up temp data */
- gpencil_interpolate_exit(C, op);
-
- /* done! */
- return OPERATOR_FINISHED;
- }
-
- case ESCKEY: /* cancel */
- case RIGHTMOUSE:
- {
- /* return to normal cursor and header status */
- ED_area_headerprint(tgpi->sa, NULL);
- WM_cursor_modal_restore(win);
-
- /* clean up temp data */
- gpencil_interpolate_exit(C, op);
-
- /* canceled! */
- return OPERATOR_CANCELLED;
- }
- case WHEELUPMOUSE:
- {
- tgpi->shift = tgpi->shift + 0.01f;
- CLAMP(tgpi->shift, tgpi->low_limit, tgpi->high_limit);
- RNA_float_set(op->ptr, "shift", tgpi->shift);
- /* update screen */
- gpencil_interpolate_update(C, op, tgpi);
- break;
- }
- case WHEELDOWNMOUSE:
- {
- tgpi->shift = tgpi->shift - 0.01f;
- CLAMP(tgpi->shift, tgpi->low_limit, tgpi->high_limit);
- RNA_float_set(op->ptr, "shift", tgpi->shift);
- /* update screen */
- gpencil_interpolate_update(C, op, tgpi);
- break;
- }
- case MOUSEMOVE: /* calculate new position */
- {
- /* only handle mousemove if not doing numinput */
- if (has_numinput == false) {
- /* update shift based on position of mouse */
- gpencil_mouse_update_shift(tgpi, op, event);
- /* update screen */
- gpencil_interpolate_update(C, op, tgpi);
- }
- break;
- }
- default:
- if ((event->val == KM_PRESS) && handleNumInput(C, &tgpi->num, event)) {
- float value;
- float factor = tgpi->init_factor;
-
- /* Grab shift from numeric input, and store this new value (the user see an int) */
- value = (factor + tgpi->shift) * 100.0f;
- applyNumInput(&tgpi->num, &value);
- tgpi->shift = value / 100.0f;
- /* recalculate the shift to get the right value in the frame scale */
- tgpi->shift = tgpi->shift - factor;
-
- CLAMP(tgpi->shift, tgpi->low_limit, tgpi->high_limit);
- RNA_float_set(op->ptr, "shift", tgpi->shift);
-
- /* update screen */
- gpencil_interpolate_update(C, op, tgpi);
-
- break;
- }
- else {
- /* unhandled event - allow to pass through */
- return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH;
- }
- }
-
- /* still running... */
- return OPERATOR_RUNNING_MODAL;
-}
-
-/* Define modal operator for interpolation */
-void GPENCIL_OT_interpolate(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Grease Pencil Interpolation";
- ot->idname = "GPENCIL_OT_interpolate";
- ot->description = "Interpolate grease pencil strokes between frames";
-
- /* api callbacks */
- ot->invoke = gpencil_interpolate_invoke;
- ot->modal = gpencil_interpolate_modal;
- ot->cancel = gpencil_interpolate_cancel;
- ot->poll = gpencil_interpolate_poll;
-
- /* flags */
- ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
-
- RNA_def_float_percentage(ot->srna, "shift", 0.0f, -1.0f, 1.0f, "Shift", "Displacement factor for the interpolate operation", -0.9f, 0.9f);
-}
-
-/* =============== Interpolate sequence ===============*/
-/* Create Sequence Interpolation */
-static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
-{
- Scene *scene = CTX_data_scene(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
- bGPdata * gpd = CTX_data_gpencil_data(C);
- bGPDlayer *active_gpl = CTX_data_active_gpencil_layer(C);
- bGPDlayer *gpl;
- bGPDframe *prevFrame, *nextFrame, *interFrame;
- bGPDstroke *gps_from, *gps_to, *new_stroke;
- float factor;
- int cframe, fFrame;
- int flag = ts->gp_sculpt.flag;
-
- /* cannot interpolate if not between 2 frames */
- if ((active_gpl->actframe == NULL) || (active_gpl->actframe->next == NULL)) {
- BKE_report(op->reports, RPT_ERROR, "Interpolation requires to be between two grease pencil frames");
- return OPERATOR_CANCELLED;
- }
- /* cannot interpolate in extremes */
- if ((active_gpl->actframe->framenum == scene->r.cfra) || (active_gpl->actframe->next->framenum == scene->r.cfra)) {
- BKE_report(op->reports, RPT_ERROR, "Interpolation requires to be between two grease pencil frames");
- return OPERATOR_CANCELLED;
- }
-
- /* loop all layer to check if need interpolation */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* all layers or only active */
- if (((flag & GP_BRUSHEDIT_FLAG_INTERPOLATE_ALL_LAYERS) == 0) && (gpl != active_gpl)) {
- continue;
- }
- /* only editable and visible layers are considered */
- if (!gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
- continue;
- }
- /* store extremes */
- prevFrame = gpl->actframe;
- nextFrame = gpl->actframe->next;
- /* Loop over intermediary frames and create the interpolation */
- for (cframe = prevFrame->framenum + 1; cframe < nextFrame->framenum; cframe++) {
- interFrame = NULL;
-
- /* get interpolation factor */
- factor = (float)(cframe - prevFrame->framenum) / (nextFrame->framenum - prevFrame->framenum + 1);
-
- /* create new strokes data with interpolated points reading original stroke */
- for (gps_from = prevFrame->strokes.first; gps_from; gps_from = gps_from->next) {
- /* only selected */
- if ((flag & GP_BRUSHEDIT_FLAG_INTERPOLATE_ONLY_SELECTED) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) {
- continue;
- }
- /* skip strokes that are invalid for current view */
- if (ED_gpencil_stroke_can_use(C, gps_from) == false) {
- continue;
- }
- /* check if the color is editable */
- if (ED_gpencil_stroke_color_use(gpl, gps_from) == false) {
- continue;
- }
- /* get final stroke to interpolate */
- fFrame = BLI_findindex(&prevFrame->strokes, gps_from);
- gps_to = BLI_findlink(&nextFrame->strokes, fFrame);
- if (gps_to == NULL) {
- continue;
- }
- /* create a new frame if needed */
- if (interFrame == NULL) {
- interFrame = BKE_gpencil_layer_getframe(gpl, cframe, GP_GETFRAME_ADD_NEW);
- interFrame->key_type = BEZT_KEYTYPE_BREAKDOWN;
- }
- /* create new stroke */
- new_stroke = MEM_dupallocN(gps_from);
- new_stroke->points = MEM_dupallocN(gps_from->points);
- new_stroke->triangles = MEM_dupallocN(gps_from->triangles);
- /* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */
- if (gps_from->totpoints > gps_to->totpoints) {
- new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points) * gps_to->totpoints);
- new_stroke->totpoints = gps_to->totpoints;
- new_stroke->tot_triangles = 0;
- new_stroke->flag |= GP_STROKE_RECALC_CACHES;
- }
- /* update points position */
- gp_interpolate_update_points(gps_from, gps_to, new_stroke, factor);
-
- /* add to strokes */
- BLI_addtail(&interFrame->strokes, new_stroke);
- }
- }
- }
-
- /* notifiers */
- WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
-}
-
-/* Define sequence interpolation */
-void GPENCIL_OT_interpolate_sequence(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Grease Pencil Sequence Interpolation";
- ot->idname = "GPENCIL_OT_interpolate_sequence";
- ot->description = "Interpolate full grease pencil strokes sequence between frames";
-
- /* api callbacks */
- ot->exec = gpencil_interpolate_seq_exec;
- ot->poll = gpencil_interpolate_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-/* ========= End Interpolation operators ========================== */
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index e2e5fc28710..5c7c9b84adb 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -287,6 +287,8 @@ void GPENCIL_OT_unlock_all(struct wmOperatorType *ot);
void GPENCIL_OT_layer_isolate(struct wmOperatorType *ot);
void GPENCIL_OT_layer_merge(struct wmOperatorType *ot);
+void GPENCIL_OT_blank_frame_add(struct wmOperatorType *ot);
+
void GPENCIL_OT_active_frame_delete(struct wmOperatorType *ot);
void GPENCIL_OT_active_frames_delete_all(struct wmOperatorType *ot);
@@ -340,6 +342,7 @@ void gpencil_undo_finish(void);
void GPENCIL_OT_interpolate(struct wmOperatorType *ot);
void GPENCIL_OT_interpolate_sequence(struct wmOperatorType *ot);
+void GPENCIL_OT_interpolate_reverse(struct wmOperatorType *ot);
/* ****************************************************** */
/* FILTERED ACTION DATA - TYPES ---> XXX DEPRECEATED OLD ANIM SYSTEM CODE! */
diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c
new file mode 100644
index 00000000000..297058168a0
--- /dev/null
+++ b/source/blender/editors/gpencil/gpencil_interpolate.c
@@ -0,0 +1,1145 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016, Blender Foundation
+ * This is a new part of Blender
+ *
+ * Contributor(s): Antonio Vazquez, Joshua Leung
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Operators for interpolating new Grease Pencil frames from existing strokes
+ */
+
+/** \file blender/editors/gpencil/gpencil_interpolate.c
+ * \ingroup edgpencil
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+#include "BLI_easing.h"
+#include "BLI_math.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_color_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
+
+#include "BKE_colortools.h"
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_gpencil.h"
+#include "BKE_library.h"
+#include "BKE_report.h"
+#include "BKE_screen.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "UI_view2d.h"
+
+#include "ED_gpencil.h"
+#include "ED_object.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+#include "ED_screen.h"
+#include "ED_space_api.h"
+
+#include "gpencil_intern.h"
+
+/* ************************************************ */
+/* Core/Shared Utilities */
+
+/* Poll callback for interpolation operators */
+static int gpencil_interpolate_poll(bContext *C)
+{
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
+
+ /* only 3D view */
+ if (CTX_wm_area(C)->spacetype != SPACE_VIEW3D) {
+ return 0;
+ }
+
+ /* need data to interpolate */
+ if (ELEM(NULL, gpd, gpl)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Perform interpolation */
+static void gp_interpolate_update_points(bGPDstroke *gps_from, bGPDstroke *gps_to, bGPDstroke *new_stroke, float factor)
+{
+ bGPDspoint *prev, *pt, *next;
+
+ /* update points */
+ for (int i = 0; i < new_stroke->totpoints; i++) {
+ prev = &gps_from->points[i];
+ pt = &new_stroke->points[i];
+ next = &gps_to->points[i];
+
+ /* Interpolate all values */
+ interp_v3_v3v3(&pt->x, &prev->x, &next->x, factor);
+ pt->pressure = interpf(prev->pressure, next->pressure, factor);
+ pt->strength = interpf(prev->strength, next->strength, factor);
+ CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
+ }
+}
+
+/* ****************** Interpolate Interactive *********************** */
+
+/* Helper: Update all strokes interpolated */
+static void gp_interpolate_update_strokes(bContext *C, tGPDinterpolate *tgpi)
+{
+ tGPDinterpolate_layer *tgpil;
+ const float shift = tgpi->shift;
+
+ for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) {
+ bGPDstroke *new_stroke;
+ const float factor = tgpil->factor + shift;
+
+ for (new_stroke = tgpil->interFrame->strokes.first; new_stroke; new_stroke = new_stroke->next) {
+ bGPDstroke *gps_from, *gps_to;
+ int stroke_idx;
+
+ if (new_stroke->totpoints == 0) {
+ continue;
+ }
+
+ /* get strokes to interpolate */
+ stroke_idx = BLI_findindex(&tgpil->interFrame->strokes, new_stroke);
+
+ gps_from = BLI_findlink(&tgpil->prevFrame->strokes, stroke_idx);
+ gps_to = BLI_findlink(&tgpil->nextFrame->strokes, stroke_idx);
+
+ /* update points position */
+ if ((gps_from) && (gps_to)) {
+ gp_interpolate_update_points(gps_from, gps_to, new_stroke, factor);
+ }
+ }
+ }
+
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+}
+
+/* Helper: Verify valid strokes for interpolation */
+static bool gp_interpolate_check_todo(bContext *C, bGPdata *gpd)
+{
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ eGP_Interpolate_SettingsFlag flag = ts->gp_interpolate.flag;
+
+ /* get layers */
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* all layers or only active */
+ if (!(flag & GP_TOOLFLAG_INTERPOLATE_ALL_LAYERS) && !(gpl->flag & GP_LAYER_ACTIVE)) {
+ continue;
+ }
+ /* only editable and visible layers are considered */
+ if (!gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
+ continue;
+ }
+
+ /* read strokes */
+ for (bGPDstroke *gps_from = gpl->actframe->strokes.first; gps_from; gps_from = gps_from->next) {
+ bGPDstroke *gps_to;
+ int fFrame;
+
+ /* only selected */
+ if ((flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) {
+ continue;
+ }
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps_from) == false) {
+ continue;
+ }
+ /* check if the color is editable */
+ if (ED_gpencil_stroke_color_use(gpl, gps_from) == false) {
+ continue;
+ }
+
+ /* get final stroke to interpolate */
+ fFrame = BLI_findindex(&gpl->actframe->strokes, gps_from);
+ gps_to = BLI_findlink(&gpl->actframe->next->strokes, fFrame);
+ if (gps_to == NULL) {
+ continue;
+ }
+
+ return true;
+ }
+ }
+ return false;
+}
+
+/* Helper: Create internal strokes interpolated */
+static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
+{
+ bGPdata *gpd = tgpi->gpd;
+ bGPDlayer *active_gpl = CTX_data_active_gpencil_layer(C);
+ bGPDframe *actframe = active_gpl->actframe;
+
+ /* save initial factor for active layer to define shift limits */
+ tgpi->init_factor = (float)(tgpi->cframe - actframe->framenum) / (actframe->next->framenum - actframe->framenum + 1);
+
+ /* limits are 100% below 0 and 100% over the 100% */
+ tgpi->low_limit = -1.0f - tgpi->init_factor;
+ tgpi->high_limit = 2.0f - tgpi->init_factor;
+
+ /* set layers */
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ tGPDinterpolate_layer *tgpil;
+
+ /* all layers or only active */
+ if (!(tgpi->flag & GP_TOOLFLAG_INTERPOLATE_ALL_LAYERS) && (gpl != active_gpl)) {
+ continue;
+ }
+ /* only editable and visible layers are considered */
+ if (!gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
+ continue;
+ }
+
+ /* create temp data for each layer */
+ tgpil = MEM_callocN(sizeof(tGPDinterpolate_layer), "GPencil Interpolate Layer");
+
+ tgpil->gpl = gpl;
+ tgpil->prevFrame = gpl->actframe;
+ tgpil->nextFrame = gpl->actframe->next;
+
+ BLI_addtail(&tgpi->ilayers, tgpil);
+
+ /* create a new temporary frame */
+ tgpil->interFrame = MEM_callocN(sizeof(bGPDframe), "bGPDframe");
+ tgpil->interFrame->framenum = tgpi->cframe;
+
+ /* get interpolation factor by layer (usually must be equal for all layers, but not sure) */
+ tgpil->factor = (float)(tgpi->cframe - tgpil->prevFrame->framenum) / (tgpil->nextFrame->framenum - tgpil->prevFrame->framenum + 1);
+
+ /* create new strokes data with interpolated points reading original stroke */
+ for (bGPDstroke *gps_from = tgpil->prevFrame->strokes.first; gps_from; gps_from = gps_from->next) {
+ bGPDstroke *gps_to;
+ int fFrame;
+
+ bGPDstroke *new_stroke;
+ bool valid = true;
+
+
+ /* only selected */
+ if ((tgpi->flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) {
+ valid = false;
+ }
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps_from) == false) {
+ valid = false;
+ }
+
+ /* check if the color is editable */
+ if (ED_gpencil_stroke_color_use(tgpil->gpl, gps_from) == false) {
+ valid = false;
+ }
+
+ /* get final stroke to interpolate */
+ fFrame = BLI_findindex(&tgpil->prevFrame->strokes, gps_from);
+ gps_to = BLI_findlink(&tgpil->nextFrame->strokes, fFrame);
+ if (gps_to == NULL) {
+ valid = false;
+ }
+
+ /* create new stroke */
+ new_stroke = MEM_dupallocN(gps_from);
+ new_stroke->points = MEM_dupallocN(gps_from->points);
+ new_stroke->triangles = MEM_dupallocN(gps_from->triangles);
+
+ if (valid) {
+ /* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */
+ if (gps_from->totpoints > gps_to->totpoints) {
+ new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points) * gps_to->totpoints);
+ new_stroke->totpoints = gps_to->totpoints;
+ new_stroke->tot_triangles = 0;
+ new_stroke->flag |= GP_STROKE_RECALC_CACHES;
+ }
+ /* update points position */
+ gp_interpolate_update_points(gps_from, gps_to, new_stroke, tgpil->factor);
+ }
+ else {
+ /* need an empty stroke to keep index correct for lookup, but resize to smallest size */
+ new_stroke->totpoints = 0;
+ new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points));
+ new_stroke->tot_triangles = 0;
+ new_stroke->triangles = MEM_recallocN(new_stroke->triangles, sizeof(*new_stroke->triangles));
+ }
+
+ /* add to strokes */
+ BLI_addtail(&tgpil->interFrame->strokes, new_stroke);
+ }
+ }
+}
+
+/* ----------------------- */
+/* Drawing Callbacks */
+
+/* Drawing callback for modal operator in screen mode */
+static void gpencil_interpolate_draw_screen(const struct bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg)
+{
+ tGPDinterpolate *tgpi = (tGPDinterpolate *)arg;
+ ED_gp_draw_interpolation(tgpi, REGION_DRAW_POST_PIXEL);
+}
+
+/* Drawing callback for modal operator in 3d mode */
+static void gpencil_interpolate_draw_3d(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg)
+{
+ tGPDinterpolate *tgpi = (tGPDinterpolate *)arg;
+ ED_gp_draw_interpolation(tgpi, REGION_DRAW_POST_VIEW);
+}
+
+/* ----------------------- */
+
+/* Helper: calculate shift based on position of mouse (we only use x-axis for now.
+ * since this is more convenient for users to do), and store new shift value
+ */
+static void gpencil_mouse_update_shift(tGPDinterpolate *tgpi, wmOperator *op, const wmEvent *event)
+{
+ float mid = (float)(tgpi->ar->winx - tgpi->ar->winrct.xmin) / 2.0f;
+ float mpos = event->x - tgpi->ar->winrct.xmin;
+
+ if (mpos >= mid) {
+ tgpi->shift = ((mpos - mid) * tgpi->high_limit) / mid;
+ }
+ else {
+ tgpi->shift = tgpi->low_limit - ((mpos * tgpi->low_limit) / mid);
+ }
+
+ CLAMP(tgpi->shift, tgpi->low_limit, tgpi->high_limit);
+ RNA_float_set(op->ptr, "shift", tgpi->shift);
+}
+
+/* Helper: Draw status message while the user is running the operator */
+static void gpencil_interpolate_status_indicators(tGPDinterpolate *p)
+{
+ Scene *scene = p->scene;
+ char status_str[UI_MAX_DRAW_STR];
+ char msg_str[UI_MAX_DRAW_STR];
+
+ BLI_strncpy(msg_str, IFACE_("GPencil Interpolation: ESC/RMB to cancel, Enter/LMB to confirm, WHEEL/MOVE to adjust factor"), UI_MAX_DRAW_STR);
+
+ if (hasNumInput(&p->num)) {
+ char str_offs[NUM_STR_REP_LEN];
+
+ outputNumInput(&p->num, str_offs, &scene->unit);
+ BLI_snprintf(status_str, sizeof(status_str), "%s: %s", msg_str, str_offs);
+ }
+ else {
+ BLI_snprintf(status_str, sizeof(status_str), "%s: %d %%", msg_str, (int)((p->init_factor + p->shift) * 100.0f));
+ }
+
+ ED_area_headerprint(p->sa, status_str);
+}
+
+/* Update screen and stroke */
+static void gpencil_interpolate_update(bContext *C, wmOperator *op, tGPDinterpolate *tgpi)
+{
+ /* update shift indicator in header */
+ gpencil_interpolate_status_indicators(tgpi);
+ /* apply... */
+ tgpi->shift = RNA_float_get(op->ptr, "shift");
+ /* update points position */
+ gp_interpolate_update_strokes(C, tgpi);
+}
+
+/* ----------------------- */
+
+/* Exit and free memory */
+static void gpencil_interpolate_exit(bContext *C, wmOperator *op)
+{
+ tGPDinterpolate *tgpi = op->customdata;
+ tGPDinterpolate_layer *tgpil;
+
+ /* don't assume that operator data exists at all */
+ if (tgpi) {
+ /* remove drawing handler */
+ if (tgpi->draw_handle_screen) {
+ ED_region_draw_cb_exit(tgpi->ar->type, tgpi->draw_handle_screen);
+ }
+ if (tgpi->draw_handle_3d) {
+ ED_region_draw_cb_exit(tgpi->ar->type, tgpi->draw_handle_3d);
+ }
+
+ /* clear status message area */
+ ED_area_headerprint(tgpi->sa, NULL);
+
+ /* finally, free memory used by temp data */
+ for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) {
+ BKE_gpencil_free_strokes(tgpil->interFrame);
+ MEM_freeN(tgpil->interFrame);
+ }
+
+ BLI_freelistN(&tgpi->ilayers);
+ MEM_freeN(tgpi);
+ }
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+
+ /* clear pointer */
+ op->customdata = NULL;
+}
+
+/* Init new temporary interpolation data */
+static bool gp_interpolate_set_init_values(bContext *C, wmOperator *op, tGPDinterpolate *tgpi)
+{
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+
+ /* set current scene and window */
+ tgpi->scene = CTX_data_scene(C);
+ tgpi->sa = CTX_wm_area(C);
+ tgpi->ar = CTX_wm_region(C);
+ tgpi->flag = ts->gp_interpolate.flag;
+
+ /* set current frame number */
+ tgpi->cframe = tgpi->scene->r.cfra;
+
+ /* set GP datablock */
+ tgpi->gpd = gpd;
+
+ /* set interpolation weight */
+ tgpi->shift = RNA_float_get(op->ptr, "shift");
+ /* set layers */
+ gp_interpolate_set_points(C, tgpi);
+
+ return 1;
+}
+
+/* Allocate memory and initialize values */
+static tGPDinterpolate *gp_session_init_interpolation(bContext *C, wmOperator *op)
+{
+ tGPDinterpolate *tgpi = MEM_callocN(sizeof(tGPDinterpolate), "GPencil Interpolate Data");
+
+ /* define initial values */
+ gp_interpolate_set_init_values(C, op, tgpi);
+
+ /* return context data for running operator */
+ return tgpi;
+}
+
+/* Init interpolation: Allocate memory and set init values */
+static int gpencil_interpolate_init(bContext *C, wmOperator *op)
+{
+ tGPDinterpolate *tgpi;
+
+ /* check context */
+ tgpi = op->customdata = gp_session_init_interpolation(C, op);
+ if (tgpi == NULL) {
+ /* something wasn't set correctly in context */
+ gpencil_interpolate_exit(C, op);
+ return 0;
+ }
+
+ /* everything is now setup ok */
+ return 1;
+}
+
+/* ----------------------- */
+
+/* Invoke handler: Initialize the operator */
+static int gpencil_interpolate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ wmWindow *win = CTX_wm_window(C);
+ Scene *scene = CTX_data_scene(C);
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
+ bGPDframe *actframe = gpl->actframe;
+ tGPDinterpolate *tgpi = NULL;
+
+ /* cannot interpolate if not between 2 frames */
+ if (ELEM(NULL, actframe, actframe->next)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot find a pair of grease pencil frames to interpolate between in active layer");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* cannot interpolate in extremes */
+ if (ELEM(CFRA, actframe->framenum, actframe->next->framenum)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot interpolate as current frame already has existing grease pencil frames");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* need editable strokes */
+ if (!gp_interpolate_check_todo(C, gpd)) {
+ BKE_report(op->reports, RPT_ERROR, "Interpolation requires some editable strokes");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* try to initialize context data needed */
+ if (!gpencil_interpolate_init(C, op)) {
+ if (op->customdata)
+ MEM_freeN(op->customdata);
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ tgpi = op->customdata;
+ }
+
+ /* Enable custom drawing handlers
+ * It needs 2 handlers because strokes can in 3d space and screen space
+ * and each handler use different coord system
+ */
+ tgpi->draw_handle_screen = ED_region_draw_cb_activate(tgpi->ar->type, gpencil_interpolate_draw_screen, tgpi, REGION_DRAW_POST_PIXEL);
+ tgpi->draw_handle_3d = ED_region_draw_cb_activate(tgpi->ar->type, gpencil_interpolate_draw_3d, tgpi, REGION_DRAW_POST_VIEW);
+
+ /* set cursor to indicate modal */
+ WM_cursor_modal_set(win, BC_EW_SCROLLCURSOR);
+
+ /* update shift indicator in header */
+ gpencil_interpolate_status_indicators(tgpi);
+ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL);
+
+ /* add a modal handler for this operator */
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* Modal handler: Events handling during interactive part */
+static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ tGPDinterpolate *tgpi = op->customdata;
+ wmWindow *win = CTX_wm_window(C);
+ bGPDframe *gpf_dst;
+ bGPDstroke *gps_src, *gps_dst;
+ tGPDinterpolate_layer *tgpil;
+ const bool has_numinput = hasNumInput(&tgpi->num);
+
+ switch (event->type) {
+ case LEFTMOUSE: /* confirm */
+ case RETKEY:
+ {
+ /* return to normal cursor and header status */
+ ED_area_headerprint(tgpi->sa, NULL);
+ WM_cursor_modal_restore(win);
+
+ /* insert keyframes as required... */
+ for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) {
+ gpf_dst = BKE_gpencil_layer_getframe(tgpil->gpl, tgpi->cframe, GP_GETFRAME_ADD_NEW);
+ gpf_dst->key_type = BEZT_KEYTYPE_BREAKDOWN;
+
+ /* copy strokes */
+ BLI_listbase_clear(&gpf_dst->strokes);
+ for (gps_src = tgpil->interFrame->strokes.first; gps_src; gps_src = gps_src->next) {
+ if (gps_src->totpoints == 0) {
+ continue;
+ }
+
+ /* make copy of source stroke, then adjust pointer to points too */
+ gps_dst = MEM_dupallocN(gps_src);
+ gps_dst->points = MEM_dupallocN(gps_src->points);
+ gps_dst->triangles = MEM_dupallocN(gps_src->triangles);
+ gps_dst->flag |= GP_STROKE_RECALC_CACHES;
+ BLI_addtail(&gpf_dst->strokes, gps_dst);
+ }
+ }
+
+ /* clean up temp data */
+ gpencil_interpolate_exit(C, op);
+
+ /* done! */
+ return OPERATOR_FINISHED;
+ }
+
+ case ESCKEY: /* cancel */
+ case RIGHTMOUSE:
+ {
+ /* return to normal cursor and header status */
+ ED_area_headerprint(tgpi->sa, NULL);
+ WM_cursor_modal_restore(win);
+
+ /* clean up temp data */
+ gpencil_interpolate_exit(C, op);
+
+ /* canceled! */
+ return OPERATOR_CANCELLED;
+ }
+
+ case WHEELUPMOUSE:
+ {
+ tgpi->shift = tgpi->shift + 0.01f;
+ CLAMP(tgpi->shift, tgpi->low_limit, tgpi->high_limit);
+ RNA_float_set(op->ptr, "shift", tgpi->shift);
+
+ /* update screen */
+ gpencil_interpolate_update(C, op, tgpi);
+ break;
+ }
+ case WHEELDOWNMOUSE:
+ {
+ tgpi->shift = tgpi->shift - 0.01f;
+ CLAMP(tgpi->shift, tgpi->low_limit, tgpi->high_limit);
+ RNA_float_set(op->ptr, "shift", tgpi->shift);
+
+ /* update screen */
+ gpencil_interpolate_update(C, op, tgpi);
+ break;
+ }
+ case MOUSEMOVE: /* calculate new position */
+ {
+ /* only handle mousemove if not doing numinput */
+ if (has_numinput == false) {
+ /* update shift based on position of mouse */
+ gpencil_mouse_update_shift(tgpi, op, event);
+
+ /* update screen */
+ gpencil_interpolate_update(C, op, tgpi);
+ }
+ break;
+ }
+ default:
+ if ((event->val == KM_PRESS) && handleNumInput(C, &tgpi->num, event)) {
+ const float factor = tgpi->init_factor;
+ float value;
+
+ /* Grab shift from numeric input, and store this new value (the user see an int) */
+ value = (factor + tgpi->shift) * 100.0f;
+ applyNumInput(&tgpi->num, &value);
+ tgpi->shift = value / 100.0f;
+
+ /* recalculate the shift to get the right value in the frame scale */
+ tgpi->shift = tgpi->shift - factor;
+
+ CLAMP(tgpi->shift, tgpi->low_limit, tgpi->high_limit);
+ RNA_float_set(op->ptr, "shift", tgpi->shift);
+
+ /* update screen */
+ gpencil_interpolate_update(C, op, tgpi);
+
+ break;
+ }
+ else {
+ /* unhandled event - allow to pass through */
+ return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH;
+ }
+ }
+
+ /* still running... */
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* Cancel handler */
+static void gpencil_interpolate_cancel(bContext *C, wmOperator *op)
+{
+ /* this is just a wrapper around exit() */
+ gpencil_interpolate_exit(C, op);
+}
+
+void GPENCIL_OT_interpolate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Grease Pencil Interpolation";
+ ot->idname = "GPENCIL_OT_interpolate";
+ ot->description = "Interpolate grease pencil strokes between frames";
+
+ /* callbacks */
+ ot->invoke = gpencil_interpolate_invoke;
+ ot->modal = gpencil_interpolate_modal;
+ ot->cancel = gpencil_interpolate_cancel;
+ ot->poll = gpencil_interpolate_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* properties */
+ RNA_def_float_percentage(ot->srna, "shift", 0.0f, -1.0f, 1.0f, "Shift", "Bias factor for which frame has more influence on the interpolated strokes", -0.9f, 0.9f);
+}
+
+/* ****************** Interpolate Sequence *********************** */
+
+/* Helper: Perform easing equation calculations for GP interpolation operator */
+static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_settings, float time)
+{
+ const float begin = 0.0f;
+ const float change = 1.0f;
+ const float duration = 1.0f;
+
+ const float back = ipo_settings->back;
+ const float amplitude = ipo_settings->amplitude;
+ const float period = ipo_settings->period;
+
+ eBezTriple_Easing easing = ipo_settings->easing;
+ float result = time;
+
+ switch (ipo_settings->type) {
+ case GP_IPO_BACK:
+ switch (easing) {
+ case BEZT_IPO_EASE_IN:
+ result = BLI_easing_back_ease_in(time, begin, change, duration, back);
+ break;
+ case BEZT_IPO_EASE_OUT:
+ result = BLI_easing_back_ease_out(time, begin, change, duration, back);
+ break;
+ case BEZT_IPO_EASE_IN_OUT:
+ result = BLI_easing_back_ease_in_out(time, begin, change, duration, back);
+ break;
+
+ default: /* default/auto: same as ease out */
+ result = BLI_easing_back_ease_out(time, begin, change, duration, back);
+ break;
+ }
+ break;
+
+ case GP_IPO_BOUNCE:
+ switch (easing) {
+ case BEZT_IPO_EASE_IN:
+ result = BLI_easing_bounce_ease_in(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_OUT:
+ result = BLI_easing_bounce_ease_out(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_IN_OUT:
+ result = BLI_easing_bounce_ease_in_out(time, begin, change, duration);
+ break;
+
+ default: /* default/auto: same as ease out */
+ result = BLI_easing_bounce_ease_out(time, begin, change, duration);
+ break;
+ }
+ break;
+
+ case GP_IPO_CIRC:
+ switch (easing) {
+ case BEZT_IPO_EASE_IN:
+ result = BLI_easing_circ_ease_in(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_OUT:
+ result = BLI_easing_circ_ease_out(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_IN_OUT:
+ result = BLI_easing_circ_ease_in_out(time, begin, change, duration);
+ break;
+
+ default: /* default/auto: same as ease in */
+ result = BLI_easing_circ_ease_in(time, begin, change, duration);
+ break;
+ }
+ break;
+
+ case GP_IPO_CUBIC:
+ switch (easing) {
+ case BEZT_IPO_EASE_IN:
+ result = BLI_easing_cubic_ease_in(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_OUT:
+ result = BLI_easing_cubic_ease_out(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_IN_OUT:
+ result = BLI_easing_cubic_ease_in_out(time, begin, change, duration);
+ break;
+
+ default: /* default/auto: same as ease in */
+ result = BLI_easing_cubic_ease_in(time, begin, change, duration);
+ break;
+ }
+ break;
+
+ case GP_IPO_ELASTIC:
+ switch (easing) {
+ case BEZT_IPO_EASE_IN:
+ result = BLI_easing_elastic_ease_in(time, begin, change, duration, amplitude, period);
+ break;
+ case BEZT_IPO_EASE_OUT:
+ result = BLI_easing_elastic_ease_out(time, begin, change, duration, amplitude, period);
+ break;
+ case BEZT_IPO_EASE_IN_OUT:
+ result = BLI_easing_elastic_ease_in_out(time, begin, change, duration, amplitude, period);
+ break;
+
+ default: /* default/auto: same as ease out */
+ result = BLI_easing_elastic_ease_out(time, begin, change, duration, amplitude, period);
+ break;
+ }
+ break;
+
+ case GP_IPO_EXPO:
+ switch (easing) {
+ case BEZT_IPO_EASE_IN:
+ result = BLI_easing_expo_ease_in(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_OUT:
+ result = BLI_easing_expo_ease_out(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_IN_OUT:
+ result = BLI_easing_expo_ease_in_out(time, begin, change, duration);
+ break;
+
+ default: /* default/auto: same as ease in */
+ result = BLI_easing_expo_ease_in(time, begin, change, duration);
+ break;
+ }
+ break;
+
+ case GP_IPO_QUAD:
+ switch (easing) {
+ case BEZT_IPO_EASE_IN:
+ result = BLI_easing_quad_ease_in(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_OUT:
+ result = BLI_easing_quad_ease_out(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_IN_OUT:
+ result = BLI_easing_quad_ease_in_out(time, begin, change, duration);
+ break;
+
+ default: /* default/auto: same as ease in */
+ result = BLI_easing_quad_ease_in(time, begin, change, duration);
+ break;
+ }
+ break;
+
+ case GP_IPO_QUART:
+ switch (easing) {
+ case BEZT_IPO_EASE_IN:
+ result = BLI_easing_quart_ease_in(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_OUT:
+ result = BLI_easing_quart_ease_out(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_IN_OUT:
+ result = BLI_easing_quart_ease_in_out(time, begin, change, duration);
+ break;
+
+ default: /* default/auto: same as ease in */
+ result = BLI_easing_quart_ease_in(time, begin, change, duration);
+ break;
+ }
+ break;
+
+ case GP_IPO_QUINT:
+ switch (easing) {
+ case BEZT_IPO_EASE_IN:
+ result = BLI_easing_quint_ease_in(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_OUT:
+ result = BLI_easing_quint_ease_out(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_IN_OUT:
+ result = BLI_easing_quint_ease_in_out(time, begin, change, duration);
+ break;
+
+ default: /* default/auto: same as ease in */
+ result = BLI_easing_quint_ease_in(time, begin, change, duration);
+ break;
+ }
+ break;
+
+ case GP_IPO_SINE:
+ switch (easing) {
+ case BEZT_IPO_EASE_IN:
+ result = BLI_easing_sine_ease_in(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_OUT:
+ result = BLI_easing_sine_ease_out(time, begin, change, duration);
+ break;
+ case BEZT_IPO_EASE_IN_OUT:
+ result = BLI_easing_sine_ease_in_out(time, begin, change, duration);
+ break;
+
+ default: /* default/auto: same as ease in */
+ result = BLI_easing_sine_ease_in(time, begin, change, duration);
+ break;
+ }
+ break;
+
+ default:
+ printf("%s: Unknown interpolation type - %d\n", __func__, ipo_settings->type);
+ break;
+ }
+
+ return result;
+}
+
+static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
+{
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ bGPDlayer *active_gpl = CTX_data_active_gpencil_layer(C);
+ bGPDframe *actframe = active_gpl->actframe;
+
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ GP_Interpolate_Settings *ipo_settings = &ts->gp_interpolate;
+ eGP_Interpolate_SettingsFlag flag = ipo_settings->flag;
+
+ /* cannot interpolate if not between 2 frames */
+ if (ELEM(NULL, actframe, actframe->next)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot find a pair of grease pencil frames to interpolate between in active layer");
+ return OPERATOR_CANCELLED;
+ }
+ /* cannot interpolate in extremes */
+ if (ELEM(CFRA, actframe->framenum, actframe->next->framenum)) {
+ BKE_report(op->reports, RPT_ERROR, "Cannot interpolate as current frame already has existing grease pencil frames");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* loop all layer to check if need interpolation */
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ bGPDframe *prevFrame, *nextFrame;
+ bGPDstroke *gps_from, *gps_to;
+ int cframe, fFrame;
+
+ /* all layers or only active */
+ if (((flag & GP_TOOLFLAG_INTERPOLATE_ALL_LAYERS) == 0) && (gpl != active_gpl)) {
+ continue;
+ }
+ /* only editable and visible layers are considered */
+ if (!gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) {
+ continue;
+ }
+
+ /* store extremes */
+ prevFrame = gpl->actframe;
+ nextFrame = gpl->actframe->next;
+
+ /* Loop over intermediary frames and create the interpolation */
+ for (cframe = prevFrame->framenum + 1; cframe < nextFrame->framenum; cframe++) {
+ bGPDframe *interFrame = NULL;
+ float factor;
+
+ /* get interpolation factor */
+ factor = (float)(cframe - prevFrame->framenum) / (nextFrame->framenum - prevFrame->framenum + 1);
+
+ if (ipo_settings->type == GP_IPO_CURVEMAP) {
+ /* custom curvemap */
+ if (ipo_settings->custom_ipo) {
+ factor = curvemapping_evaluateF(ipo_settings->custom_ipo, 0, factor);
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Custom interpolation curve does not exist");
+ }
+ }
+ else if (ipo_settings->type >= GP_IPO_BACK) {
+ /* easing equation... */
+ factor = gp_interpolate_seq_easing_calc(ipo_settings, factor);
+ }
+
+ /* create new strokes data with interpolated points reading original stroke */
+ for (gps_from = prevFrame->strokes.first; gps_from; gps_from = gps_from->next) {
+ bGPDstroke *new_stroke;
+
+ /* only selected */
+ if ((flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) {
+ continue;
+ }
+ /* skip strokes that are invalid for current view */
+ if (ED_gpencil_stroke_can_use(C, gps_from) == false) {
+ continue;
+ }
+ /* check if the color is editable */
+ if (ED_gpencil_stroke_color_use(gpl, gps_from) == false) {
+ continue;
+ }
+
+ /* get final stroke to interpolate */
+ fFrame = BLI_findindex(&prevFrame->strokes, gps_from);
+ gps_to = BLI_findlink(&nextFrame->strokes, fFrame);
+ if (gps_to == NULL) {
+ continue;
+ }
+
+ /* create a new frame if needed */
+ if (interFrame == NULL) {
+ interFrame = BKE_gpencil_layer_getframe(gpl, cframe, GP_GETFRAME_ADD_NEW);
+ interFrame->key_type = BEZT_KEYTYPE_BREAKDOWN;
+ }
+
+ /* create new stroke */
+ new_stroke = MEM_dupallocN(gps_from);
+ new_stroke->points = MEM_dupallocN(gps_from->points);
+ new_stroke->triangles = MEM_dupallocN(gps_from->triangles);
+
+ /* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */
+ if (gps_from->totpoints > gps_to->totpoints) {
+ new_stroke->points = MEM_recallocN(new_stroke->points, sizeof(*new_stroke->points) * gps_to->totpoints);
+ new_stroke->totpoints = gps_to->totpoints;
+ new_stroke->tot_triangles = 0;
+ new_stroke->flag |= GP_STROKE_RECALC_CACHES;
+ }
+
+ /* update points position */
+ gp_interpolate_update_points(gps_from, gps_to, new_stroke, factor);
+
+ /* add to strokes */
+ BLI_addtail(&interFrame->strokes, new_stroke);
+ }
+ }
+ }
+
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_interpolate_sequence(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Interpolate Sequence";
+ ot->idname = "GPENCIL_OT_interpolate_sequence";
+ ot->description = "Generate 'in-betweens' to smoothly interpolate between Grease Pencil frames";
+
+ /* api callbacks */
+ ot->exec = gpencil_interpolate_seq_exec;
+ ot->poll = gpencil_interpolate_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ******************** Remove Breakdowns ************************ */
+
+/* Same as gpencil_interpolate_poll(),
+ * except we ALSO need to have an active frame that is a breakdown
+ */
+static int gpencil_interpolate_reverse_poll(bContext *C)
+{
+ bGPdata *gpd = CTX_data_gpencil_data(C);
+ bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
+
+ /* only 3D view */
+ if (CTX_wm_area(C)->spacetype != SPACE_VIEW3D) {
+ return 0;
+ }
+
+ /* need data to interpolate */
+ if (ELEM(NULL, gpd, gpl)) {
+ return 0;
+ }
+
+ /* need to be on a breakdown frame */
+ if ((gpl->actframe == NULL) || (gpl->actframe->key_type != BEZT_KEYTYPE_BREAKDOWN)) {
+ CTX_wm_operator_poll_msg_set(C, "Expected current frame to be a breakdown");
+ return 0;
+ }
+
+ return 1;
+}
+
+static int gpencil_interpolate_reverse_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ /* Go through each layer, deleting the breakdowns around the current frame,
+ * but only if there is a keyframe nearby to stop at
+ */
+ CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
+ {
+ bGPDframe *start_key = NULL;
+ bGPDframe *end_key = NULL;
+ bGPDframe *gpf, *gpfn;
+
+ /* Only continue if we're currently on a breakdown keyframe */
+ if ((gpl->actframe == NULL) || (gpl->actframe->key_type != BEZT_KEYTYPE_BREAKDOWN))
+ continue;
+
+ /* Search left for "start_key" (i.e. the first breakdown to remove) */
+ gpf = gpl->actframe;
+ while (gpf) {
+ if (gpf->key_type == BEZT_KEYTYPE_BREAKDOWN) {
+ /* A breakdown... keep going left */
+ start_key = gpf;
+ gpf = gpf->prev;
+ }
+ else {
+ /* Not a breakdown (may be a key, or an extreme, or something else that wasn't generated)... stop */
+ break;
+ }
+ }
+
+ /* Search right for "end_key" (i.e. the last breakdown to remove) */
+ gpf = gpl->actframe;
+ while (gpf) {
+ if (gpf->key_type == BEZT_KEYTYPE_BREAKDOWN) {
+ /* A breakdown... keep going right */
+ end_key = gpf;
+ gpf = gpf->next;
+ }
+ else {
+ /* Not a breakdown... stop */
+ break;
+ }
+ }
+
+ /* Did we find anything? */
+ /* NOTE: We should only proceed if there's something before/after these extents...
+ * Otherwise, there's just an extent of breakdowns with no keys to interpolate between
+ */
+ if ((start_key && end_key) &&
+ ELEM(NULL, start_key->prev, end_key->next) == false)
+ {
+ /* Set actframe to the key before start_key, since the keys have been removed now */
+ gpl->actframe = start_key->prev;
+
+ /* Free each frame we're removing (except the last one) */
+ for (gpf = start_key; gpf && gpf != end_key; gpf = gpfn) {
+ gpfn = gpf->next;
+
+ /* free strokes and their associated memory */
+ BKE_gpencil_free_strokes(gpf);
+ BLI_freelinkN(&gpl->frames, gpf);
+ }
+
+ /* Now free the last one... */
+ BKE_gpencil_free_strokes(end_key);
+ BLI_freelinkN(&gpl->frames, end_key);
+ }
+ }
+ CTX_DATA_END;
+
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_interpolate_reverse(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Breakdowns";
+ ot->idname = "GPENCIL_OT_interpolate_reverse";
+ ot->description = "Remove breakdown frames generated by interpolating between two Grease Pencil frames";
+
+ /* callbacks */
+ ot->exec = gpencil_interpolate_reverse_exec;
+ ot->poll = gpencil_interpolate_reverse_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* *************************************************************** */
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index 057d53ea458..78e1a0dda36 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -102,6 +102,10 @@ static void ed_keymap_gpencil_general(wmKeyConfig *keyconf)
WM_keymap_add_menu_pie(keymap, "GPENCIL_PIE_tool_palette", QKEY, KM_PRESS, 0, DKEY);
WM_keymap_add_menu_pie(keymap, "GPENCIL_PIE_settings_palette", WKEY, KM_PRESS, 0, DKEY);
+ /* Add Blank Frame */
+ /* XXX: BKEY or NKEY? BKEY is easier to reach from DKEY, so we'll use that for now */
+ WM_keymap_add_item(keymap, "GPENCIL_OT_blank_frame_add", BKEY, KM_PRESS, 0, DKEY);
+
/* Delete Active Frame - For easier video tutorials/review sessions */
/* NOTE: This works even when not in EditMode */
WM_keymap_add_item(keymap, "GPENCIL_OT_active_frames_delete_all", XKEY, KM_PRESS, 0, DKEY);
@@ -401,6 +405,8 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_layer_isolate);
WM_operatortype_append(GPENCIL_OT_layer_merge);
+ WM_operatortype_append(GPENCIL_OT_blank_frame_add);
+
WM_operatortype_append(GPENCIL_OT_active_frame_delete);
WM_operatortype_append(GPENCIL_OT_active_frames_delete_all);
@@ -443,6 +449,7 @@ void ED_operatortypes_gpencil(void)
/* Interpolation */
WM_operatortype_append(GPENCIL_OT_interpolate);
WM_operatortype_append(GPENCIL_OT_interpolate_sequence);
+ WM_operatortype_append(GPENCIL_OT_interpolate_reverse);
}
void ED_operatormacros_gpencil(void)
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index b483402d6c8..73f393537ba 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -1625,16 +1625,24 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode)
* 2) Ensure that p->gpf refers to the frame used for the active layer
* (to avoid problems with other tools which expect it to exist)
*/
- bGPDlayer *gpl;
- for (gpl = p->gpd->layers.first; gpl; gpl = gpl->next) {
+ bool has_layer_to_erase = false;
+
+ for (bGPDlayer *gpl = p->gpd->layers.first; gpl; gpl = gpl->next) {
/* Skip if layer not editable */
if (gpencil_layer_is_editable(gpl) == false)
continue;
/* Add a new frame if needed (and based off the active frame,
* as we need some existing strokes to erase)
+ *
+ * Note: We don't add a new frame if there's nothing there now, so
+ * -> If there are no frames at all, don't add one
+ * -> If there are no strokes in that frame, don't add a new empty frame
*/
- gpl->actframe = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_COPY);
+ if (gpl->actframe && gpl->actframe->strokes.first) {
+ gpl->actframe = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_COPY);
+ has_layer_to_erase = true;
+ }
/* XXX: we omit GP_FRAME_PAINT here for now,
* as it is only really useful for doing
@@ -1654,10 +1662,10 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode)
}
}
- if (p->gpf == NULL) {
+ if (has_layer_to_erase == false) {
p->status = GP_STATUS_ERROR;
//if (G.debug & G_DEBUG)
- printf("Error: No frame created (gpencil_paint_init)\n");
+ printf("Error: Eraser will not be affecting anything (gpencil_paint_init)\n");
return;
}
}
@@ -2434,6 +2442,14 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* enable continuous if release D key in mid drawing */
p->scene->toolsettings->gpencil_flags |= GP_TOOL_FLAG_PAINTSESSIONS_ON;
}
+ else if ((event->type == BKEY) && (event->val == KM_RELEASE)) {
+ /* Add Blank Frame
+ * - Since this operator is non-modal, we can just call it here, and keep going...
+ * - This operator is especially useful when animating
+ */
+ WM_operator_name_call(C, "GPENCIL_OT_blank_frame_add", WM_OP_EXEC_DEFAULT, NULL);
+ estate = OPERATOR_RUNNING_MODAL;
+ }
else {
estate = OPERATOR_RUNNING_MODAL;
}
@@ -2596,7 +2612,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
else if (p->status != GP_STATUS_ERROR) {
/* User clicked outside bounds of window while idling, so exit paintmode
- * NOTE: Don't eter this case if an error occurred while finding the
+ * NOTE: Don't enter this case if an error occurred while finding the
* region (as above)
*/
/* if drawing polygon and enable on back, must move stroke */
diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h
index 25fcdf33524..35d38bf4ca1 100644
--- a/source/blender/editors/include/BIF_glutil.h
+++ b/source/blender/editors/include/BIF_glutil.h
@@ -128,6 +128,7 @@ void imm_draw_line_box(unsigned pos, float x1, float y1, float x2, float y2);
/* use this version when VertexFormat has a vec3 position */
void imm_draw_line_box_3D(unsigned pos, float x1, float y1, float x2, float y2);
+void imm_draw_line(unsigned pos, float x1, float y1, float x2, float y2);
/**
* Pack color into 3 bytes
*
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
index 5bedf62638b..c028c887af3 100644
--- a/source/blender/editors/include/ED_armature.h
+++ b/source/blender/editors/include/ED_armature.h
@@ -172,6 +172,7 @@ void create_vgroups_from_armature(struct ReportList *reports, struct Scene *scen
/* if bone is already in list, pass it as param to ignore it */
void unique_editbone_name(struct ListBase *ebones, char *name, EditBone *bone);
void ED_armature_bone_rename(struct bArmature *arm, const char *oldnamep, const char *newnamep);
+void ED_armature_bones_flip_names(struct bArmature *arm, struct ListBase *bones_names);
void undo_push_armature(struct bContext *C, const char *name);
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index e04e8341651..40112bc20fc 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -91,7 +91,6 @@ bool ED_object_parent_set(struct ReportList *reports, struct Main *bmain, struct
struct Object *par, int partype, const bool xmirror, const bool keep_transform,
const int vert_par[3]);
void ED_object_parent_clear(struct Object *ob, const int type);
-struct Base *ED_object_scene_link(struct Scene *scene, struct Object *ob);
void ED_keymap_proportional_cycle(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap);
void ED_keymap_proportional_obmode(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap);
@@ -107,10 +106,13 @@ void ED_base_object_activate(struct bContext *C, struct Base *base);
void ED_object_base_select(struct ObjectBase *base, short mode);
void ED_object_base_activate(struct bContext *C, struct ObjectBase *base);
-void ED_base_object_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Base *base);
+void ED_base_object_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Object *ob);
+
+void ED_base_object_sync_from_base(struct Base *base, struct Object *ob);
+void ED_base_object_sync_from_object(struct Base *base, struct Object *ob);
/* single object duplicate, if (dupflag == 0), fully linked, else it uses the flags given */
-struct Base *ED_object_add_duplicate(struct Main *bmain, struct Scene *scene, struct Base *base, int dupflag);
+struct ObjectBase *ED_object_add_duplicate(struct Main *bmain, struct Scene *scene, struct SceneLayer *sl, struct ObjectBase *base, int dupflag);
void ED_object_parent(struct Object *ob, struct Object *parent, const int type, const char *substr);
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index be03647d6f4..b7a5217a862 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -353,6 +353,10 @@ void UI_GetThemeColor4fv(int colorid, float col[4]);
// get four color values, range 0.0-1.0, complete with shading offset for the RGB components
void UI_GetThemeColorShade4fv(int colorid, int offset, float col[4]);
void UI_GetThemeColorShadeAlpha4fv(int colorid, int coloffset, int alphaoffset, float col[4]);
+
+// get four colour values ranged between 0 and 255; includes the alpha channel
+void UI_GetThemeColorShadeAlpha4ubv(int colorid, int coloffset, int alphaoffset, unsigned char col[4]);
+
// get four color values, range 0.0-1.0, complete with shading offset for the RGB components and blending
void UI_GetThemeColorBlendShade4fv(int colorid1, int colorid2, float fac, int offset, float col[4]);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index a913421d12c..682db20af55 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -1993,7 +1993,7 @@ uiBut *ui_but_drag_multi_edit_get(uiBut *but)
static bool ui_but_icon_extra_is_visible_text_clear(const uiBut *but)
{
BLI_assert(but->type == UI_BTYPE_TEXT);
- return ((but->flag & UI_BUT_VALUE_CLEAR) && but->drawstr && but->drawstr[0]);
+ return ((but->flag & UI_BUT_VALUE_CLEAR) && but->drawstr[0]);
}
static bool ui_but_icon_extra_is_visible_search_unlink(const uiBut *but)
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 241ac99edde..9bdc4d29807 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -2954,7 +2954,7 @@ static bool ui_textedit_copypaste(uiBut *but, uiHandleButtonData *data, const in
if (pbuf) {
if (ui_but_is_utf8(but)) {
- buf_len -= BLI_utf8_invalid_strip(pbuf, buf_len);
+ buf_len -= BLI_utf8_invalid_strip(pbuf, (size_t)buf_len);
}
ui_textedit_insert_buf(but, data, pbuf, buf_len);
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index 8dfbbdd02eb..df6f098ee81 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -119,12 +119,10 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
else
but = uiDefButR_prop(block, UI_BTYPE_TEXT, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
- PropertySubType subtype = RNA_property_subtype(prop);
- if (!(ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME) || (block->flag & UI_BLOCK_LIST_ITEM))) {
- UI_but_flag_enable(but, UI_BUT_VALUE_CLEAR);
- }
if (RNA_property_flag(prop) & PROP_TEXTEDIT_UPDATE) {
- UI_but_flag_enable(but, UI_BUT_TEXTEDIT_UPDATE);
+ /* TEXTEDIT_UPDATE is usally used for search buttons. For these we also want
+ * the 'x' icon to clear search string, so setting VALUE_CLEAR flag, too. */
+ UI_but_flag_enable(but, UI_BUT_TEXTEDIT_UPDATE | UI_BUT_VALUE_CLEAR);
}
break;
case PROP_POINTER:
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 73a9ea928cc..999556025db 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -1307,6 +1307,27 @@ void UI_ThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset)
glColor4ub(r, g, b, a);
}
+void UI_GetThemeColorShadeAlpha4ubv(int colorid, int coloffset, int alphaoffset, unsigned char col[4])
+{
+ int r, g, b, a;
+ const unsigned char *cp;
+
+ cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ r = coloffset + (int) cp[0];
+ CLAMP(r, 0, 255);
+ g = coloffset + (int) cp[1];
+ CLAMP(g, 0, 255);
+ b = coloffset + (int) cp[2];
+ CLAMP(b, 0, 255);
+ a = alphaoffset + (int) cp[3];
+ CLAMP(a, 0, 255);
+
+ col[0] = r;
+ col[1] = g;
+ col[2] = b;
+ col[3] = a;
+}
+
void UI_GetThemeColorBlend3ubv(int colorid1, int colorid2, float fac, unsigned char col[3])
{
const unsigned char *cp1, *cp2;
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 87b7b25f164..445c5e42b2b 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -685,27 +685,38 @@ static void edbm_add_edge_face_exec__tricky_finalize_sel(BMesh *bm, BMElem *ele_
/* now we need to find the edge that isnt connected to this element */
BM_select_history_clear(bm);
+ /* Notes on hidden geometry:
+ * - un-hide the face since its possible hidden was copied when copying surrounding face attributes.
+ * - un-hide before adding to select history
+ * since we may extend into an existing, hidden vert/edge.
+ */
+
+ BM_elem_flag_disable(f, BM_ELEM_HIDDEN);
+ BM_face_select_set(bm, f, false);
+
if (ele_desel->head.htype == BM_VERT) {
BMLoop *l = BM_face_vert_share_loop(f, (BMVert *)ele_desel);
BLI_assert(f->len == 3);
- BM_face_select_set(bm, f, false);
BM_vert_select_set(bm, (BMVert *)ele_desel, false);
-
BM_edge_select_set(bm, l->next->e, true);
BM_select_history_store(bm, l->next->e);
}
else {
BMLoop *l = BM_face_edge_share_loop(f, (BMEdge *)ele_desel);
BLI_assert(f->len == 4 || f->len == 3);
- BM_face_select_set(bm, f, false);
+
BM_edge_select_set(bm, (BMEdge *)ele_desel, false);
if (f->len == 4) {
- BM_edge_select_set(bm, l->next->next->e, true);
- BM_select_history_store(bm, l->next->next->e);
+ BMEdge *e_active = l->next->next->e;
+ BM_elem_flag_disable(e_active, BM_ELEM_HIDDEN);
+ BM_edge_select_set(bm, e_active, true);
+ BM_select_history_store(bm, e_active);
}
else {
- BM_vert_select_set(bm, l->next->next->v, true);
- BM_select_history_store(bm, l->next->next->v);
+ BMVert *v_active = l->next->next->v;
+ BM_elem_flag_disable(v_active, BM_ELEM_HIDDEN);
+ BM_vert_select_set(bm, v_active, true);
+ BM_select_history_store(bm, v_active);
}
}
}
@@ -759,6 +770,14 @@ static int edbm_add_edge_face_exec(bContext *C, wmOperator *op)
else
#endif
{
+ /* Newly created faces may include existing hidden edges,
+ * copying face data from surrounding, may have copied hidden face flag too.
+ *
+ * Important that faces use flushing since 'edges.out' wont include hidden edges that already existed.
+ */
+ BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_HIDDEN, true);
+ BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_HIDDEN, false);
+
BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true);
}
@@ -2992,9 +3011,9 @@ enum {
MESH_SEPARATE_LOOSE = 2,
};
-static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
+static ObjectBase *mesh_separate_tagged(Main *bmain, Scene *scene, SceneLayer *sl, ObjectBase *base_old, BMesh *bm_old)
{
- Base *base_new;
+ ObjectBase *base_new;
Object *obedit = base_old->object;
BMesh *bm_new;
@@ -3013,11 +3032,11 @@ static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMe
CustomData_bmesh_init_pool(&bm_new->ldata, bm_mesh_allocsize_default.totloop, BM_LOOP);
CustomData_bmesh_init_pool(&bm_new->pdata, bm_mesh_allocsize_default.totface, BM_FACE);
- base_new = ED_object_add_duplicate(bmain, scene, base_old, USER_DUP_MESH);
+ base_new = ED_object_add_duplicate(bmain, scene, sl, base_old, USER_DUP_MESH);
/* DAG_relations_tag_update(bmain); */ /* normally would call directly after but in this case delay recalc */
assign_matarar(base_new->object, give_matarar(obedit), *give_totcolp(obedit)); /* new in 2.5 */
- ED_base_object_select(base_new, BA_SELECT);
+ ED_object_base_select(base_new, BA_SELECT);
BMO_op_callf(bm_old, (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE),
"duplicate geom=%hvef dest=%p", BM_ELEM_TAG, bm_new);
@@ -3039,7 +3058,7 @@ static Base *mesh_separate_tagged(Main *bmain, Scene *scene, Base *base_old, BMe
return base_new;
}
-static bool mesh_separate_selected(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
+static bool mesh_separate_selected(Main *bmain, Scene *scene, SceneLayer *sl, ObjectBase *base_old, BMesh *bm_old)
{
/* we may have tags from previous operators */
BM_mesh_elem_hflag_disable_all(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, false);
@@ -3047,7 +3066,7 @@ static bool mesh_separate_selected(Main *bmain, Scene *scene, Base *base_old, BM
/* sel -> tag */
BM_mesh_elem_hflag_enable_test(bm_old, BM_FACE | BM_EDGE | BM_VERT, BM_ELEM_TAG, true, false, BM_ELEM_SELECT);
- return (mesh_separate_tagged(bmain, scene, base_old, bm_old) != NULL);
+ return (mesh_separate_tagged(bmain, scene, sl, base_old, bm_old) != NULL);
}
/* flush a hflag to from verts to edges/faces */
@@ -3146,14 +3165,14 @@ static void mesh_separate_material_assign_mat_nr(Main *bmain, Object *ob, const
}
}
-static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
+static bool mesh_separate_material(Main *bmain, Scene *scene, SceneLayer *sl, ObjectBase *base_old, BMesh *bm_old)
{
BMFace *f_cmp, *f;
BMIter iter;
bool result = false;
while ((f_cmp = BM_iter_at_index(bm_old, BM_FACES_OF_MESH, NULL, 0))) {
- Base *base_new;
+ ObjectBase *base_new;
const short mat_nr = f_cmp->mat_nr;
int tot = 0;
@@ -3187,7 +3206,7 @@ static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BM
}
/* Move selection into a separate object */
- base_new = mesh_separate_tagged(bmain, scene, base_old, bm_old);
+ base_new = mesh_separate_tagged(bmain, scene, sl, base_old, bm_old);
if (base_new) {
mesh_separate_material_assign_mat_nr(bmain, base_new->object, mat_nr);
}
@@ -3198,7 +3217,7 @@ static bool mesh_separate_material(Main *bmain, Scene *scene, Base *base_old, BM
return result;
}
-static bool mesh_separate_loose(Main *bmain, Scene *scene, Base *base_old, BMesh *bm_old)
+static bool mesh_separate_loose(Main *bmain, Scene *scene, SceneLayer *sl, ObjectBase *base_old, BMesh *bm_old)
{
int i;
BMEdge *e;
@@ -3251,7 +3270,7 @@ static bool mesh_separate_loose(Main *bmain, Scene *scene, Base *base_old, BMesh
bm_mesh_hflag_flush_vert(bm_old, BM_ELEM_TAG);
/* Move selection into a separate object */
- result |= (mesh_separate_tagged(bmain, scene, base_old, bm_old) != NULL);
+ result |= (mesh_separate_tagged(bmain, scene, sl, base_old, bm_old) != NULL);
}
return result;
@@ -3259,14 +3278,14 @@ static bool mesh_separate_loose(Main *bmain, Scene *scene, Base *base_old, BMesh
static int edbm_separate_exec(bContext *C, wmOperator *op)
{
-#if 0
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
const int type = RNA_enum_get(op->ptr, "type");
int retval = 0;
if (ED_operator_editmesh(C)) {
- Base *base = CTX_data_active_base(C);
+ ObjectBase *base = CTX_data_active_base(C);
BMEditMesh *em = BKE_editmesh_from_object(base->object);
if (type == 0) {
@@ -3282,13 +3301,13 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
/* editmode separate */
switch (type) {
case MESH_SEPARATE_SELECTED:
- retval = mesh_separate_selected(bmain, scene, base, em->bm);
+ retval = mesh_separate_selected(bmain, scene, sl, base, em->bm);
break;
case MESH_SEPARATE_MATERIAL:
- retval = mesh_separate_material(bmain, scene, base, em->bm);
+ retval = mesh_separate_material(bmain, scene, sl, base, em->bm);
break;
case MESH_SEPARATE_LOOSE:
- retval = mesh_separate_loose(bmain, scene, base, em->bm);
+ retval = mesh_separate_loose(bmain, scene, sl, base, em->bm);
break;
default:
BLI_assert(0);
@@ -3306,7 +3325,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
}
/* object mode separate */
- CTX_DATA_BEGIN(C, Base *, base_iter, selected_editable_bases)
+ CTX_DATA_BEGIN(C, ObjectBase *, base_iter, selected_editable_bases)
{
Object *ob = base_iter->object;
if (ob->type == OB_MESH) {
@@ -3323,10 +3342,10 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
switch (type) {
case MESH_SEPARATE_MATERIAL:
- retval_iter = mesh_separate_material(bmain, scene, base_iter, bm_old);
+ retval_iter = mesh_separate_material(bmain, scene, sl, base_iter, bm_old);
break;
case MESH_SEPARATE_LOOSE:
- retval_iter = mesh_separate_loose(bmain, scene, base_iter, bm_old);
+ retval_iter = mesh_separate_loose(bmain, scene, sl, base_iter, bm_old);
break;
default:
BLI_assert(0);
@@ -3358,16 +3377,6 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
}
return OPERATOR_CANCELLED;
-#else
- /* need to refactor this to use ObjectBase and create a new object in the correct SceneCollection */
- TODO_LAYER_BASE
- (void)C;
- (void)mesh_separate_loose;
- (void)mesh_separate_material;
- (void)mesh_separate_selected;
- BKE_report(op->reports, RPT_ERROR, "MESH_OT_separate not supported at the moment");
- return OPERATOR_CANCELLED;
-#endif
}
void MESH_OT_separate(wmOperatorType *ot)
diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c
index b95921964eb..cc6a5d578a8 100644
--- a/source/blender/editors/mesh/mesh_navmesh.c
+++ b/source/blender/editors/mesh/mesh_navmesh.c
@@ -461,14 +461,15 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh,
static int navmesh_create_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
LinkNode *obs = NULL;
Base *navmeshBase = NULL;
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
if (base->object->type == OB_MESH) {
if (base->object->body_type == OB_BODY_TYPE_NAVMESH) {
- if (!navmeshBase || base == scene->basact) {
+ if (!navmeshBase || base == sl->basact) {
navmeshBase = base;
}
}
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index b26989113d4..059626ac0d6 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -109,7 +109,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
}
/* count & check */
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
if (base->object->type == OB_MESH) {
me = base->object->data;
@@ -188,7 +188,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
}
/* first pass over objects - copying materials and vertexgroups across */
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
/* only act if a mesh, and not the one we're joining to */
if ((ob != base->object) && (base->object->type == OB_MESH)) {
@@ -302,7 +302,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
/* inverse transform for all selected meshes in this object */
invert_m4_m4(imat, ob->obmat);
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
/* only join if this is a mesh */
if (base->object->type == OB_MESH) {
@@ -481,7 +481,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
/* free base, now that data is merged */
if (base->object != ob)
- ED_base_object_free_and_unlink(bmain, scene, base);
+ ED_base_object_free_and_unlink(bmain, scene, base->object);
}
}
CTX_DATA_END;
@@ -589,7 +589,7 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op)
KeyBlock *kb;
bool ok = false, nonequal_verts = false;
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
if (base->object == ob) continue;
@@ -622,7 +622,7 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op)
}
/* now ready to add new keys from selected meshes */
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
if (base->object == ob) continue;
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 8c06d759555..819b3b91b90 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1111,22 +1111,19 @@ static void object_delete_check_glsl_update(Object *ob)
/* remove base from a specific scene */
/* note: now unlinks constraints as well */
-void ED_base_object_free_and_unlink(Main *bmain, Scene *scene, Base *base)
+void ED_base_object_free_and_unlink(Main *bmain, Scene *scene, Object *ob)
{
- if (BKE_library_ID_is_indirectly_used(bmain, base->object) &&
- ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0)
+ if (BKE_library_ID_is_indirectly_used(bmain, ob) &&
+ ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0)
{
/* We cannot delete indirectly used object... */
printf("WARNING, undeletable object '%s', should have been catched before reaching this function!",
- base->object->id.name + 2);
+ ob->id.name + 2);
return;
}
- BKE_scene_base_unlink(scene, base);
- BKE_collections_object_remove(scene, base->object);
- object_delete_check_glsl_update(base->object);
- BKE_libblock_free_us(bmain, base->object);
- MEM_freeN(base);
+ object_delete_check_glsl_update(ob);
+ BKE_collections_object_remove(bmain, scene, ob, true);
DAG_id_type_tag(bmain, ID_OB);
}
@@ -1142,56 +1139,46 @@ static int object_delete_exec(bContext *C, wmOperator *op)
if (CTX_data_edit_object(C))
return OPERATOR_CANCELLED;
- CTX_DATA_BEGIN (C, Base *, base, selected_bases)
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
{
- const bool is_indirectly_used = BKE_library_ID_is_indirectly_used(bmain, base->object);
- if (base->object->id.tag & LIB_TAG_INDIRECT) {
+ const bool is_indirectly_used = BKE_library_ID_is_indirectly_used(bmain, ob);
+ if (ob->id.tag & LIB_TAG_INDIRECT) {
/* Can this case ever happen? */
- BKE_reportf(op->reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", base->object->id.name + 2);
+ BKE_reportf(op->reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", ob->id.name + 2);
continue;
}
- else if (is_indirectly_used && ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0) {
+ else if (is_indirectly_used && ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) {
BKE_reportf(op->reports, RPT_WARNING,
"Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user",
- base->object->id.name + 2, scene->id.name + 2);
+ ob->id.name + 2, scene->id.name + 2);
continue;
}
/* remove from Grease Pencil parent */
for (bGPdata *gpd = bmain->gpencil.first; gpd; gpd = gpd->id.next) {
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
if (gpl->parent != NULL) {
- Object *ob = gpl->parent;
- Object *curob = base->object;
- if (ob == curob) {
+ if (gpl->parent == ob) {
gpl->parent = NULL;
}
}
}
}
- /* deselect object -- it could be used in other scenes */
- base->object->flag &= ~SELECT;
-
/* remove from current scene only */
- ED_base_object_free_and_unlink(bmain, scene, base);
+ ED_base_object_free_and_unlink(bmain, scene, ob);
changed = true;
if (use_global) {
Scene *scene_iter;
- Base *base_other;
-
for (scene_iter = bmain->scene.first; scene_iter; scene_iter = scene_iter->id.next) {
if (scene_iter != scene && !ID_IS_LINKED_DATABLOCK(scene_iter)) {
- base_other = BKE_scene_base_find(scene_iter, base->object);
- if (base_other) {
- if (is_indirectly_used && ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0) {
- BKE_reportf(op->reports, RPT_WARNING,
- "Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user",
- base->object->id.name + 2, scene_iter->id.name + 2);
- break;
- }
- ED_base_object_free_and_unlink(bmain, scene_iter, base_other);
+ if (is_indirectly_used && ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0) {
+ BKE_reportf(op->reports, RPT_WARNING,
+ "Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user",
+ ob->id.name + 2, scene_iter->id.name + 2);
+ break;
}
+ ED_base_object_free_and_unlink(bmain, scene_iter, ob);
}
}
}
@@ -1327,11 +1314,12 @@ static bool dupliobject_cmp(const void *a_, const void *b_)
return false;
}
-static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
+static void make_object_duplilist_real(bContext *C, Scene *scene, ObjectBase *base,
const bool use_base_parent,
const bool use_hierarchy)
{
Main *bmain = CTX_data_main(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
ListBase *lb;
DupliObject *dob;
GHash *dupli_gh = NULL, *parent_gh = NULL;
@@ -1355,7 +1343,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
}
for (dob = lb->first; dob; dob = dob->next) {
- Base *basen;
+ ObjectBase *basen;
Object *ob = ID_NEW_SET(dob->ob, BKE_object_copy(bmain, dob->ob));
/* font duplis can have a totcol without material, we get them from parent
@@ -1363,12 +1351,10 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
*/
if (ob->mat == NULL) ob->totcol = 0;
- basen = MEM_dupallocN(base);
- basen->flag &= ~(OB_FROMDUPLI | OB_FROMGROUP);
- ob->flag = basen->flag;
- basen->lay = base->lay;
- BLI_addhead(&scene->base, basen); /* addhead: othwise eternal loop */
- basen->object = ob;
+ BKE_collection_object_add_from(scene, dob->ob, ob);
+ basen = BKE_scene_layer_base_find(sl, ob);
+
+ BKE_scene_object_base_flag_sync_from_base(basen);
/* make sure apply works */
BKE_animdata_free(&ob->id, true);
@@ -1383,7 +1369,6 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
BLI_listbase_clear(&ob->constraints);
ob->curve_cache = NULL;
ob->transflag &= ~OB_DUPLI;
- ob->lay = base->lay;
copy_m4_m4(ob->obmat, dob->mat);
BKE_object_apply_mat4(ob, ob->obmat, false, false);
@@ -1510,7 +1495,7 @@ static int object_duplicates_make_real_exec(bContext *C, wmOperator *op)
BKE_main_id_clear_newpoins(bmain);
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
make_object_duplilist_real(C, scene, base, use_base_parent, use_hierarchy);
@@ -1592,10 +1577,10 @@ static int convert_poll(bContext *C)
}
/* Helper for convert_exec */
-static Base *duplibase_for_convert(Main *bmain, Scene *scene, Base *base, Object *ob)
+static ObjectBase *duplibase_for_convert(Main *bmain, Scene *scene, SceneLayer *sl, ObjectBase *base, Object *ob)
{
Object *obn;
- Base *basen;
+ ObjectBase *basen;
if (ob == NULL) {
ob = base->object;
@@ -1603,16 +1588,11 @@ static Base *duplibase_for_convert(Main *bmain, Scene *scene, Base *base, Object
obn = BKE_object_copy(bmain, ob);
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ BKE_collection_object_add_from(scene, ob, obn);
- basen = MEM_mallocN(sizeof(Base), "duplibase");
- *basen = *base;
- BLI_addhead(&scene->base, basen); /* addhead: otherwise eternal loop */
- basen->object = obn;
- basen->flag |= SELECT;
- obn->flag |= SELECT;
- base->flag &= ~SELECT;
- ob->flag &= ~SELECT;
-
+ basen = BKE_scene_layer_base_find(sl, obn);
+ ED_object_base_select(basen, BA_SELECT);
+ ED_object_base_select(basen, BA_DESELECT);
return basen;
}
@@ -1620,7 +1600,8 @@ static int convert_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Base *basen = NULL, *basact = NULL;
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ ObjectBase *basen = NULL, *basact = NULL;
Object *ob, *ob1, *newob, *obact = CTX_data_active_object(C);
DerivedMesh *dm;
Curve *cu;
@@ -1658,7 +1639,7 @@ static int convert_exec(bContext *C, wmOperator *op)
}
}
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
ob = base->object;
@@ -1681,7 +1662,7 @@ static int convert_exec(bContext *C, wmOperator *op)
ob->flag |= OB_DONE;
if (keep_original) {
- basen = duplibase_for_convert(bmain, scene, base, NULL);
+ basen = duplibase_for_convert(bmain, scene, sl, base, NULL);
newob = basen->object;
/* decrement original mesh's usage count */
@@ -1706,7 +1687,7 @@ static int convert_exec(bContext *C, wmOperator *op)
ob->flag |= OB_DONE;
if (keep_original) {
- basen = duplibase_for_convert(bmain, scene, base, NULL);
+ basen = duplibase_for_convert(bmain, scene, sl, base, NULL);
newob = basen->object;
/* decrement original mesh's usage count */
@@ -1738,7 +1719,7 @@ static int convert_exec(bContext *C, wmOperator *op)
ob->flag |= OB_DONE;
if (keep_original) {
- basen = duplibase_for_convert(bmain, scene, base, NULL);
+ basen = duplibase_for_convert(bmain, scene, sl, base, NULL);
newob = basen->object;
/* decrement original curve's usage count */
@@ -1809,7 +1790,7 @@ static int convert_exec(bContext *C, wmOperator *op)
if (target == OB_MESH) {
if (keep_original) {
- basen = duplibase_for_convert(bmain, scene, base, NULL);
+ basen = duplibase_for_convert(bmain, scene, sl, base, NULL);
newob = basen->object;
/* decrement original curve's usage count */
@@ -1844,7 +1825,7 @@ static int convert_exec(bContext *C, wmOperator *op)
if (!(baseob->flag & OB_DONE)) {
baseob->flag |= OB_DONE;
- basen = duplibase_for_convert(bmain, scene, base, baseob);
+ basen = duplibase_for_convert(bmain, scene, sl, base, baseob);
newob = basen->object;
mb = newob->data;
@@ -1895,23 +1876,21 @@ static int convert_exec(bContext *C, wmOperator *op)
if (!keep_original) {
if (mballConverted) {
- Base *base, *base_next;
-
- for (base = scene->base.first; base; base = base_next) {
- base_next = base->next;
-
- ob = base->object;
+ Object *ob_mball;
+ FOREACH_SCENE_OBJECT(scene, ob_mball)
+ {
if (ob->type == OB_MBALL) {
if (ob->flag & OB_DONE) {
Object *ob_basis = NULL;
- if (BKE_mball_is_basis(ob) ||
- ((ob_basis = BKE_mball_basis_find(scene, ob)) && (ob_basis->flag & OB_DONE)))
+ if (BKE_mball_is_basis(ob_mball) ||
+ ((ob_basis = BKE_mball_basis_find(scene, ob_mball)) && (ob_basis->flag & OB_DONE)))
{
- ED_base_object_free_and_unlink(bmain, scene, base);
+ ED_base_object_free_and_unlink(bmain, scene, ob_mball);
}
}
}
}
+ FOREACH_SCENE_OBJECT_END
}
/* delete object should renew depsgraph */
@@ -1923,12 +1902,12 @@ static int convert_exec(bContext *C, wmOperator *op)
if (basact) {
/* active base was changed */
- ED_base_object_activate(C, basact);
- BASACT = basact;
+ ED_object_base_activate(C, basact);
+ BASACT_NEW = basact;
}
- else if (BASACT->object->flag & OB_DONE) {
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, BASACT->object);
- WM_event_add_notifier(C, NC_OBJECT | ND_DATA, BASACT->object);
+ else if (BASACT_NEW->object->flag & OB_DONE) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, BASACT_NEW->object);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DATA, BASACT_NEW->object);
}
DAG_relations_tag_update(bmain);
@@ -1970,18 +1949,17 @@ void OBJECT_OT_convert(wmOperatorType *ot)
/* used below, assumes id.new is correct */
/* leaves selection of base/object unaltered */
/* Does set ID->newid pointers. */
-static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base, int dupflag)
+static ObjectBase *object_add_duplicate_internal(Main *bmain, Scene *scene, SceneLayer *sl, Object *ob, int dupflag)
{
#define ID_NEW_REMAP_US(a) if ( (a)->id.newid) { (a) = (void *)(a)->id.newid; (a)->id.us++; }
#define ID_NEW_REMAP_US2(a) if (((ID *)a)->newid) { (a) = ((ID *)a)->newid; ((ID *)a)->us++; }
- Base *basen = NULL;
+ ObjectBase *basen = NULL;
Material ***matarar;
- Object *ob, *obn;
+ Object *obn;
ID *id;
int a, didit;
- ob = base->object;
if (ob->mode & OB_MODE_POSE) {
; /* nothing? */
}
@@ -1989,20 +1967,18 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
- basen = MEM_mallocN(sizeof(Base), "duplibase");
- *basen = *base;
- BLI_addhead(&scene->base, basen); /* addhead: prevent eternal loop */
- basen->object = obn;
+ BKE_collection_object_add_from(scene, ob, obn);
+ basen = BKE_scene_layer_base_find(sl, obn);
/* 1) duplis should end up in same group as the original
* 2) Rigid Body sim participants MUST always be part of a group...
*/
// XXX: is 2) really a good measure here?
- if ((basen->flag & OB_FROMGROUP) || ob->rigidbody_object || ob->rigidbody_constraint) {
+ if ((ob->flag & OB_FROMGROUP) != 0 || ob->rigidbody_object || ob->rigidbody_constraint) {
Group *group;
for (group = bmain->group.first; group; group = group->id.next) {
if (BKE_group_object_exists(group, ob))
- BKE_group_object_add(group, obn, scene, basen);
+ BKE_group_object_add(group, obn);
}
}
@@ -2210,15 +2186,14 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
* note: don't call this within a loop since clear_* funcs loop over the entire database.
* note: caller must do DAG_relations_tag_update(bmain);
* this is not done automatic since we may duplicate many objects in a batch */
-Base *ED_object_add_duplicate(Main *bmain, Scene *scene, Base *base, int dupflag)
+ObjectBase *ED_object_add_duplicate(Main *bmain, Scene *scene, SceneLayer *sl, ObjectBase *base, int dupflag)
{
-#if 0
ObjectBase *basen;
Object *ob;
clear_sca_new_poins(); /* BGE logic */
- basen = object_add_duplicate_internal(bmain, scene, base, dupflag);
+ basen = object_add_duplicate_internal(bmain, scene, sl, base->object, dupflag);
if (basen == NULL) {
return NULL;
}
@@ -2238,15 +2213,6 @@ Base *ED_object_add_duplicate(Main *bmain, Scene *scene, Base *base, int dupflag
BKE_main_id_clear_newpoins(bmain);
return basen;
-#else
- /* handle duplicate */
- TODO_LAYER_BASE
- (void)bmain;
- (void)scene;
- (void)base;
- (void)dupflag;
- return NULL;
-#endif
}
/* contextual operator dupli */
@@ -2254,26 +2220,27 @@ static int duplicate_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
const bool linked = RNA_boolean_get(op->ptr, "linked");
int dupflag = (linked) ? 0 : U.dupflag;
clear_sca_new_poins(); /* BGE logic */
- CTX_DATA_BEGIN (C, Base *, base, selected_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selected_bases)
{
- Base *basen = object_add_duplicate_internal(bmain, scene, base, dupflag);
+ ObjectBase *basen = object_add_duplicate_internal(bmain, scene, sl, base->object, dupflag);
/* note that this is safe to do with this context iterator,
* the list is made in advance */
- ED_base_object_select(base, BA_DESELECT);
+ ED_object_base_select(base, BA_DESELECT);
if (basen == NULL) {
continue;
}
/* new object becomes active */
- if (BASACT == base)
- ED_base_object_activate(C, basen);
+ if (BASACT_NEW == base)
+ ED_object_base_activate(C, basen);
if (basen->object->data) {
DAG_id_tag_update(basen->object->data, 0);
@@ -2321,9 +2288,9 @@ static int add_named_exec(bContext *C, wmOperator *op)
wmWindow *win = CTX_wm_window(C);
const wmEvent *event = win ? win->eventstate : NULL;
Main *bmain = CTX_data_main(C);
- View3D *v3d = CTX_wm_view3d(C); /* may be NULL */
Scene *scene = CTX_data_scene(C);
- Base *basen, *base;
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ ObjectBase *basen;
Object *ob;
const bool linked = RNA_boolean_get(op->ptr, "linked");
int dupflag = (linked) ? 0 : U.dupflag;
@@ -2338,22 +2305,17 @@ static int add_named_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- base = MEM_callocN(sizeof(Base), "duplibase");
- base->object = ob;
- base->flag = ob->flag;
-
/* prepare dupli */
clear_sca_new_poins(); /* BGE logic */
- basen = object_add_duplicate_internal(bmain, scene, base, dupflag);
+ basen = object_add_duplicate_internal(bmain, scene, sl, ob, dupflag);
+ BKE_scene_object_base_flag_sync_from_object(basen);
if (basen == NULL) {
- MEM_freeN(base);
BKE_report(op->reports, RPT_ERROR, "Object could not be duplicated");
return OPERATOR_CANCELLED;
}
- basen->lay = basen->object->lay = BKE_screen_view3d_layer_active(v3d, scene);
basen->object->restrictflag &= ~OB_RESTRICT_VIEW;
if (event) {
@@ -2364,8 +2326,8 @@ static int add_named_exec(bContext *C, wmOperator *op)
ED_view3d_cursor3d_position(C, basen->object->loc, mval);
}
- ED_base_object_select(basen, BA_SELECT);
- ED_base_object_activate(C, basen);
+ ED_object_base_select(basen, BA_SELECT);
+ ED_object_base_activate(C, basen);
copy_object_set_idnew(C);
@@ -2373,8 +2335,6 @@ static int add_named_exec(bContext *C, wmOperator *op)
DAG_relations_tag_update(bmain);
- MEM_freeN(base);
-
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT | ND_OB_ACTIVE, scene);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index 11d96da5786..fcc1c003b92 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -116,7 +116,7 @@ static bool multiresbake_check(bContext *C, wmOperator *op)
bool ok = true;
int a;
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
ob = base->object;
@@ -310,7 +310,7 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
if (scene->r.bake_flag & R_BAKE_CLEAR) { /* clear images */
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
Mesh *me;
ClearFlag clear_flag = 0;
@@ -330,7 +330,7 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op)
CTX_DATA_END;
}
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
MultiresBakeRender bkr = {NULL};
@@ -390,7 +390,7 @@ static void init_multiresbake_job(bContext *C, MultiresBakeJob *bkj)
bkj->user_scale = (scene->r.bake_flag & R_BAKE_USERSCALE) ? scene->r.bake_user_scale : -1.0f;
//bkj->reports = op->reports;
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
MultiresBakerJobData *data;
int lvl;
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 51fa05136a2..887c78ba47a 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -41,6 +41,7 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
+#include "BLI_string_utils.h"
#include "BLT_translation.h"
@@ -131,189 +132,6 @@ Object *ED_object_active_context(bContext *C)
}
-/* ********* clear/set restrict view *********/
-static int object_hide_view_clear_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Main *bmain = CTX_data_main(C);
- ScrArea *sa = CTX_wm_area(C);
- View3D *v3d = sa->spacedata.first;
- Scene *scene = CTX_data_scene(C);
- Base *base;
- bool changed = false;
-
- /* XXX need a context loop to handle such cases */
- for (base = FIRSTBASE; base; base = base->next) {
- if ((base->lay & v3d->lay) && base->object->restrictflag & OB_RESTRICT_VIEW) {
- if (!(base->object->restrictflag & OB_RESTRICT_SELECT)) {
- base->flag |= SELECT;
- }
- base->object->flag = base->flag;
- base->object->restrictflag &= ~OB_RESTRICT_VIEW;
- changed = true;
- }
- }
- if (changed) {
- DAG_id_type_tag(bmain, ID_OB);
- DAG_relations_tag_update(bmain);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- }
-
- return OPERATOR_FINISHED;
-}
-
-void OBJECT_OT_hide_view_clear(wmOperatorType *ot)
-{
-
- /* identifiers */
- ot->name = "Clear Restrict View";
- ot->description = "Reveal the object by setting the hide flag";
- ot->idname = "OBJECT_OT_hide_view_clear";
-
- /* api callbacks */
- ot->exec = object_hide_view_clear_exec;
- ot->poll = ED_operator_view3d_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-static int object_hide_view_set_exec(bContext *C, wmOperator *op)
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- bool changed = false;
- const bool unselected = RNA_boolean_get(op->ptr, "unselected");
-
- CTX_DATA_BEGIN(C, Base *, base, visible_bases)
- {
- if (!unselected) {
- if (base->flag & SELECT) {
- base->flag &= ~SELECT;
- base->object->flag = base->flag;
- base->object->restrictflag |= OB_RESTRICT_VIEW;
- changed = true;
- if (base == BASACT) {
- ED_base_object_activate(C, NULL);
- }
- }
- }
- else {
- if (!(base->flag & SELECT)) {
- base->object->restrictflag |= OB_RESTRICT_VIEW;
- changed = true;
- if (base == BASACT) {
- ED_base_object_activate(C, NULL);
- }
- }
- }
- }
- CTX_DATA_END;
-
- if (changed) {
- DAG_id_type_tag(bmain, ID_OB);
- DAG_relations_tag_update(bmain);
-
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
-
- }
-
- return OPERATOR_FINISHED;
-}
-
-void OBJECT_OT_hide_view_set(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Set Restrict View";
- ot->description = "Hide the object by setting the hide flag";
- ot->idname = "OBJECT_OT_hide_view_set";
-
- /* api callbacks */
- ot->exec = object_hide_view_set_exec;
- ot->poll = ED_operator_view3d_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");
-
-}
-
-/* 99% same as above except no need for scene refreshing (TODO, update render preview) */
-static int object_hide_render_clear_exec(bContext *C, wmOperator *UNUSED(op))
-{
- bool changed = false;
-
- /* XXX need a context loop to handle such cases */
- CTX_DATA_BEGIN(C, Object *, ob, selected_editable_objects)
- {
- if (ob->restrictflag & OB_RESTRICT_RENDER) {
- ob->restrictflag &= ~OB_RESTRICT_RENDER;
- changed = true;
- }
- }
- CTX_DATA_END;
-
- if (changed)
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL);
-
- return OPERATOR_FINISHED;
-}
-
-void OBJECT_OT_hide_render_clear(wmOperatorType *ot)
-{
-
- /* identifiers */
- ot->name = "Clear Restrict Render";
- ot->description = "Reveal the render object by setting the hide render flag";
- ot->idname = "OBJECT_OT_hide_render_clear";
-
- /* api callbacks */
- ot->exec = object_hide_render_clear_exec;
- ot->poll = ED_operator_view3d_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-static int object_hide_render_set_exec(bContext *C, wmOperator *op)
-{
- const bool unselected = RNA_boolean_get(op->ptr, "unselected");
-
- CTX_DATA_BEGIN(C, Base *, base, visible_bases)
- {
- if (!unselected) {
- if (base->flag & SELECT) {
- base->object->restrictflag |= OB_RESTRICT_RENDER;
- }
- }
- else {
- if (!(base->flag & SELECT)) {
- base->object->restrictflag |= OB_RESTRICT_RENDER;
- }
- }
- }
- CTX_DATA_END;
- WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL);
- return OPERATOR_FINISHED;
-}
-
-void OBJECT_OT_hide_render_set(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Set Restrict Render";
- ot->description = "Hide the render object by setting the hide render flag";
- ot->idname = "OBJECT_OT_hide_render_set";
-
- /* api callbacks */
- ot->exec = object_hide_render_set_exec;
- ot->poll = ED_operator_view3d_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");
-}
-
/* ******************* toggle editmode operator ***************** */
static bool mesh_needs_keyindex(const Mesh *me)
diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c
index 0fe43c44d7d..91e2d6872f3 100644
--- a/source/blender/editors/object/object_group.c
+++ b/source/blender/editors/object/object_group.c
@@ -128,7 +128,6 @@ static int objects_add_active_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
int single_group_index = RNA_enum_get(op->ptr, "group");
Group *single_group = group_object_active_find_index(ob, single_group_index);
Group *group;
@@ -145,13 +144,13 @@ static int objects_add_active_exec(bContext *C, wmOperator *op)
if (!BKE_group_object_exists(group, ob))
continue;
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
if (BKE_group_object_exists(group, base->object))
continue;
if (!BKE_group_object_cyclic_check(bmain, base->object, group)) {
- BKE_group_object_add(group, base->object, scene, base);
+ BKE_group_object_add(group, base->object);
updated = true;
}
else {
@@ -200,8 +199,8 @@ void GROUP_OT_objects_add_active(wmOperatorType *ot)
static int objects_remove_active_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- Object *ob = OBACT;
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Object *ob = OBACT_NEW;
int single_group_index = RNA_enum_get(op->ptr, "group");
Group *single_group = group_object_active_find_index(ob, single_group_index);
Group *group;
@@ -219,9 +218,9 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op)
if (BKE_group_object_exists(group, ob)) {
/* Remove groups from selected objects */
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
- BKE_group_object_unlink(group, base->object, scene, base);
+ BKE_group_object_unlink(group, base->object);
ok = 1;
}
CTX_DATA_END;
@@ -264,11 +263,10 @@ void GROUP_OT_objects_remove_active(wmOperatorType *ot)
static int group_objects_remove_all_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
- BKE_object_groups_clear(scene, base, base->object);
+ BKE_object_groups_clear(base->object);
}
CTX_DATA_END;
@@ -297,7 +295,6 @@ static int group_objects_remove_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
int single_group_index = RNA_enum_get(op->ptr, "group");
Group *single_group = group_object_active_find_index(ob, single_group_index);
Group *group;
@@ -313,9 +310,9 @@ static int group_objects_remove_exec(bContext *C, wmOperator *op)
continue;
/* now remove all selected objects from the group */
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selected_editable_bases)
{
- BKE_group_object_unlink(group, base->object, scene, base);
+ BKE_group_object_unlink(group, base->object);
updated = true;
}
CTX_DATA_END;
@@ -357,7 +354,6 @@ void GROUP_OT_objects_remove(wmOperatorType *ot)
static int group_create_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
Group *group = NULL;
char name[MAX_ID_NAME - 2]; /* id name */
@@ -365,9 +361,9 @@ static int group_create_exec(bContext *C, wmOperator *op)
group = BKE_group_add(bmain, name);
- CTX_DATA_BEGIN (C, Base *, base, selected_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selected_bases)
{
- BKE_group_object_add(group, base->object, scene, base);
+ BKE_group_object_add(group, base->object);
}
CTX_DATA_END;
@@ -398,7 +394,6 @@ void GROUP_OT_create(wmOperatorType *ot)
static int group_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_context(C);
Main *bmain = CTX_data_main(C);
Group *group;
@@ -407,7 +402,7 @@ static int group_add_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
group = BKE_group_add(bmain, "Group");
- BKE_group_object_add(group, ob, scene, NULL);
+ BKE_group_object_add(group, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
@@ -432,7 +427,6 @@ void OBJECT_OT_group_add(wmOperatorType *ot)
static int group_link_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_context(C);
Group *group = BLI_findlink(&bmain->group, RNA_enum_get(op->ptr, "group"));
@@ -457,7 +451,7 @@ static int group_link_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- BKE_group_object_add(group, ob, scene, NULL);
+ BKE_group_object_add(group, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
@@ -490,14 +484,13 @@ void OBJECT_OT_group_link(wmOperatorType *ot)
static int group_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_context(C);
Group *group = CTX_data_pointer_get_type(C, "group", &RNA_Group).data;
if (!ob || !group)
return OPERATOR_CANCELLED;
- BKE_group_object_unlink(group, ob, scene, NULL); /* base will be used if found */
+ BKE_group_object_unlink(group, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
@@ -558,10 +551,12 @@ static int select_grouped_exec(bContext *C, wmOperator *UNUSED(op)) /* Select o
if (!group)
return OPERATOR_CANCELLED;
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
- if (!(base->flag & SELECT) && BKE_group_object_exists(group, base->object)) {
- ED_base_object_select(base, BA_SELECT);
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
+ if (BKE_group_object_exists(group, base->object)) {
+ ED_object_base_select(base, BA_SELECT);
+ }
}
}
CTX_DATA_END;
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index 9710e4f843d..fe0ceb15d70 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -70,7 +70,6 @@ void OBJECT_OT_make_local(struct wmOperatorType *ot);
void OBJECT_OT_make_single_user(struct wmOperatorType *ot);
void OBJECT_OT_make_links_scene(struct wmOperatorType *ot);
void OBJECT_OT_make_links_data(struct wmOperatorType *ot);
-void OBJECT_OT_move_to_layer(struct wmOperatorType *ot);
void OBJECT_OT_drop_named_material(struct wmOperatorType *ot);
void OBJECT_OT_unlink_data(struct wmOperatorType *ot);
@@ -78,10 +77,6 @@ void OBJECT_OT_unlink_data(struct wmOperatorType *ot);
void OBJECT_OT_mode_set(struct wmOperatorType *ot);
void OBJECT_OT_editmode_toggle(struct wmOperatorType *ot);
void OBJECT_OT_posemode_toggle(struct wmOperatorType *ot);
-void OBJECT_OT_hide_view_set(struct wmOperatorType *ot);
-void OBJECT_OT_hide_view_clear(struct wmOperatorType *ot);
-void OBJECT_OT_hide_render_set(struct wmOperatorType *ot);
-void OBJECT_OT_hide_render_clear(struct wmOperatorType *ot);
void OBJECT_OT_proxy_make(struct wmOperatorType *ot);
void OBJECT_OT_shade_smooth(struct wmOperatorType *ot);
void OBJECT_OT_shade_flat(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index 7e7e1ef182c..19526db2ce8 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -67,10 +67,6 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_editmode_toggle);
WM_operatortype_append(OBJECT_OT_posemode_toggle);
WM_operatortype_append(OBJECT_OT_proxy_make);
- WM_operatortype_append(OBJECT_OT_hide_view_clear);
- WM_operatortype_append(OBJECT_OT_hide_view_set);
- WM_operatortype_append(OBJECT_OT_hide_render_clear);
- WM_operatortype_append(OBJECT_OT_hide_render_set);
WM_operatortype_append(OBJECT_OT_shade_smooth);
WM_operatortype_append(OBJECT_OT_shade_flat);
WM_operatortype_append(OBJECT_OT_paths_calculate);
@@ -90,13 +86,11 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_make_single_user);
WM_operatortype_append(OBJECT_OT_make_links_scene);
WM_operatortype_append(OBJECT_OT_make_links_data);
- WM_operatortype_append(OBJECT_OT_move_to_layer);
WM_operatortype_append(OBJECT_OT_select_random);
WM_operatortype_append(OBJECT_OT_select_all);
WM_operatortype_append(OBJECT_OT_select_same_group);
WM_operatortype_append(OBJECT_OT_select_by_type);
- WM_operatortype_append(OBJECT_OT_select_by_layer);
WM_operatortype_append(OBJECT_OT_select_linked);
WM_operatortype_append(OBJECT_OT_select_grouped);
WM_operatortype_append(OBJECT_OT_select_mirror);
@@ -382,25 +376,6 @@ void ED_keymap_object(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "OBJECT_OT_origin_clear", OKEY, KM_PRESS, KM_ALT, 0);
- WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_clear", HKEY, KM_PRESS, KM_ALT, 0);
- kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, 0, 0);
- RNA_boolean_set(kmi->ptr, "unselected", false);
-
- kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "unselected", true);
-
- /* same as above but for rendering */
- WM_keymap_add_item(keymap, "OBJECT_OT_hide_render_clear", HKEY, KM_PRESS, KM_ALT | KM_CTRL, 0);
- WM_keymap_add_item(keymap, "OBJECT_OT_hide_render_set", HKEY, KM_PRESS, KM_CTRL, 0);
-
- /* conflicts, removing */
-#if 0
- kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_render_set", HKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0)
- RNA_boolean_set(kmi->ptr, "unselected", true);
-#endif
-
- WM_keymap_add_item(keymap, "OBJECT_OT_move_to_layer", MKEY, KM_PRESS, 0, 0);
-
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_delete", XKEY, KM_PRESS, 0, 0);
RNA_boolean_set(kmi->ptr, "use_global", false);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index a3bd4bc8f4b..bff959b5e5c 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -1308,119 +1308,6 @@ void OBJECT_OT_track_set(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", prop_make_track_types, 0, "Type", "");
}
-/************************** Move to Layer Operator *****************************/
-
-static unsigned int move_to_layer_init(bContext *C, wmOperator *op)
-{
- int values[20], a;
- unsigned int lay = 0;
-
- if (!RNA_struct_property_is_set(op->ptr, "layers")) {
- /* note: layers are set in bases, library objects work for this */
- CTX_DATA_BEGIN (C, Base *, base, selected_bases)
- {
- lay |= base->lay;
- }
- CTX_DATA_END;
-
- for (a = 0; a < 20; a++)
- values[a] = (lay & (1 << a)) != 0;
-
- RNA_boolean_set_array(op->ptr, "layers", values);
- }
- else {
- RNA_boolean_get_array(op->ptr, "layers", values);
-
- for (a = 0; a < 20; a++)
- if (values[a])
- lay |= (1 << a);
- }
-
- return lay;
-}
-
-static int move_to_layer_invoke(bContext *C, wmOperator *op, const wmEvent *event)
-{
- View3D *v3d = CTX_wm_view3d(C);
- if (v3d && v3d->localvd) {
- return WM_operator_confirm_message(C, op, "Move out of Local View");
- }
- else {
- move_to_layer_init(C, op);
- return WM_operator_props_popup(C, op, event);
- }
-}
-
-static int move_to_layer_exec(bContext *C, wmOperator *op)
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- unsigned int lay, local;
- /* bool is_lamp = false; */ /* UNUSED */
-
- lay = move_to_layer_init(C, op);
- lay &= 0xFFFFFF;
-
- if (lay == 0) return OPERATOR_CANCELLED;
-
- if (v3d && v3d->localvd) {
- /* now we can move out of localview. */
- /* note: layers are set in bases, library objects work for this */
- CTX_DATA_BEGIN (C, Base *, base, selected_bases)
- {
- lay = base->lay & ~v3d->lay;
- base->lay = lay;
- base->object->lay = lay;
- base->object->flag &= ~SELECT;
- base->flag &= ~SELECT;
- /* if (base->object->type == OB_LAMP) is_lamp = true; */
- }
- CTX_DATA_END;
- }
- else {
- /* normal non localview operation */
- /* note: layers are set in bases, library objects work for this */
- CTX_DATA_BEGIN (C, Base *, base, selected_bases)
- {
- /* upper byte is used for local view */
- local = base->lay & 0xFF000000;
- base->lay = lay + local;
- base->object->lay = base->lay;
- /* if (base->object->type == OB_LAMP) is_lamp = true; */
- }
- CTX_DATA_END;
- }
-
- /* warning, active object may be hidden now */
-
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene);
- WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
-
- DAG_relations_tag_update(bmain);
-
- return OPERATOR_FINISHED;
-}
-
-void OBJECT_OT_move_to_layer(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Move to Layer";
- ot->description = "Move the object to different layers";
- ot->idname = "OBJECT_OT_move_to_layer";
-
- /* api callbacks */
- ot->invoke = move_to_layer_invoke;
- ot->exec = move_to_layer_exec;
- ot->poll = ED_operator_objectmode;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_boolean_layer_member(ot->srna, "layers", 20, NULL, "Layer", "");
-}
-
/************************** Link to Scene Operator *****************************/
#if 0
@@ -1443,20 +1330,6 @@ static void link_to_scene(Main *UNUSED(bmain), unsigned short UNUSED(nr))
}
#endif
-Base *ED_object_scene_link(Scene *scene, Object *ob)
-{
- Base *base;
-
- if (BKE_scene_base_find(scene, ob)) {
- return NULL;
- }
-
- base = BKE_scene_base_add(scene, ob);
- id_us_plus(&ob->id);
-
- return base;
-}
-
static int make_links_scene_exec(bContext *C, wmOperator *op)
{
Scene *scene_to = BLI_findlink(&CTX_data_main(C)->scene, RNA_enum_get(op->ptr, "scene"));
@@ -1476,9 +1349,10 @@ static int make_links_scene_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- CTX_DATA_BEGIN (C, Base *, base, selected_bases)
+ SceneCollection *sc_to = BKE_collection_master(scene_to);
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selected_bases)
{
- ED_object_scene_link(scene_to, base->object);
+ BKE_collection_object_add(scene_to, sc_to, base->object);
}
CTX_DATA_END;
@@ -1534,7 +1408,6 @@ static bool allow_make_links_data(const int type, Object *ob_src, Object *ob_dst
static int make_links_data_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
const int type = RNA_enum_get(op->ptr, "type");
Object *ob_src;
ID *obdata_id;
@@ -1552,7 +1425,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
ob_groups = BKE_object_groups(ob_src);
}
- CTX_DATA_BEGIN (C, Base *, base_dst, selected_editable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base_dst, selected_editable_bases)
{
Object *ob_dst = base_dst->object;
@@ -1597,12 +1470,12 @@ static int make_links_data_exec(bContext *C, wmOperator *op)
LinkNode *group_node;
/* first clear groups */
- BKE_object_groups_clear(scene, base_dst, ob_dst);
+ BKE_object_groups_clear(ob_dst);
/* now add in the groups from the link nodes */
for (group_node = ob_groups; group_node; group_node = group_node->next) {
if (ob_dst->dup_group != group_node->link) {
- BKE_group_object_add(group_node->link, ob_dst, scene, base_dst);
+ BKE_group_object_add(group_node->link, ob_dst);
}
else {
is_cycle = true;
@@ -2237,7 +2110,7 @@ static bool make_local_all__instance_indirect_unused(Main *bmain, Scene *scene)
base = BKE_scene_base_add(scene, ob);
base->flag |= SELECT;
- base->object->flag = base->flag;
+ BKE_scene_base_flag_sync_from_base(base);
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
changed = true;
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index f6f101b98c1..3d770983681 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -45,6 +45,7 @@
#include "BLI_math.h"
#include "BLI_listbase.h"
#include "BLI_rand.h"
+#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -96,7 +97,7 @@ void ED_base_object_select(Base *base, short mode)
else if (mode == BA_DESELECT) {
base->flag &= ~SELECT;
}
- base->object->flag = base->flag;
+ BKE_scene_base_flag_sync_from_base(base);
}
}
@@ -123,8 +124,9 @@ void ED_object_base_select(ObjectBase *base, short mode)
{
if (base) {
if (mode == BA_SELECT) {
- if (!(base->object->restrictflag & OB_RESTRICT_SELECT))
+ if ((base->flag & BASE_SELECTABLED) != 0) {
base->flag |= BASE_SELECTED;
+ }
}
else if (mode == BA_DESELECT) {
base->flag &= ~BASE_SELECTED;
@@ -171,17 +173,17 @@ static int object_select_by_type_exec(bContext *C, wmOperator *op)
extend = RNA_boolean_get(op->ptr, "extend");
if (extend == 0) {
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
- ED_base_object_select(base, BA_DESELECT);
+ ED_object_base_select(base, BA_DESELECT);
}
CTX_DATA_END;
}
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
if (base->object->type == obtype) {
- ED_base_object_select(base, BA_SELECT);
+ ED_object_base_select(base, BA_SELECT);
}
}
CTX_DATA_END;
@@ -236,38 +238,15 @@ static EnumPropertyItem prop_select_linked_types[] = {
{0, NULL, 0, NULL, NULL}
};
-// XXX old animation system
-#if 0
-static int object_select_all_by_ipo(bContext *C, Ipo *ipo)
-{
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- if (base->object->ipo == ipo) {
- base->flag |= SELECT;
- base->object->flag = base->flag;
-
- changed = true;
- }
- }
- CTX_DATA_END;
-
- return changed;
-}
-#endif
-
static bool object_select_all_by_obdata(bContext *C, void *obdata)
{
bool changed = false;
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
- if ((base->flag & SELECT) == 0) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
if (base->object->data == obdata) {
- base->flag |= SELECT;
- base->object->flag = base->flag;
-
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -281,9 +260,9 @@ static bool object_select_all_by_material_texture(bContext *C, int use_texture,
{
bool changed = false;
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
- if ((base->flag & SELECT) == 0) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
Object *ob = base->object;
Material *mat1;
int a, b;
@@ -293,7 +272,7 @@ static bool object_select_all_by_material_texture(bContext *C, int use_texture,
if (!use_texture) {
if (mat1 == mat) {
- base->flag |= SELECT;
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -301,7 +280,7 @@ static bool object_select_all_by_material_texture(bContext *C, int use_texture,
for (b = 0; b < MAX_MTEX; b++) {
if (mat1->mtex[b]) {
if (tex == mat1->mtex[b]->tex) {
- base->flag |= SELECT;
+ ED_object_base_select(base, BA_SELECT);
changed = true;
break;
}
@@ -309,8 +288,6 @@ static bool object_select_all_by_material_texture(bContext *C, int use_texture,
}
}
}
-
- base->object->flag = base->flag;
}
}
CTX_DATA_END;
@@ -323,14 +300,12 @@ static bool object_select_all_by_dup_group(bContext *C, Object *ob)
bool changed = false;
Group *dup_group = (ob->transflag & OB_DUPLIGROUP) ? ob->dup_group : NULL;
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
- if ((base->flag & SELECT) == 0) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
Group *dup_group_other = (base->object->transflag & OB_DUPLIGROUP) ? base->object->dup_group : NULL;
if (dup_group == dup_group_other) {
- base->flag |= SELECT;
- base->object->flag = base->flag;
-
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -345,25 +320,23 @@ static bool object_select_all_by_particle(bContext *C, Object *ob)
ParticleSystem *psys_act = psys_get_current(ob);
bool changed = false;
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
- if ((base->flag & SELECT) == 0) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
/* loop through other particles*/
ParticleSystem *psys;
for (psys = base->object->particlesystem.first; psys; psys = psys->next) {
if (psys->part == psys_act->part) {
- base->flag |= SELECT;
+ ED_object_base_select(base, BA_SELECT);
changed = true;
break;
}
- if (base->flag & SELECT) {
+ if (base->flag & BASE_SELECTED) {
break;
}
}
-
- base->object->flag = base->flag;
}
}
CTX_DATA_END;
@@ -375,13 +348,11 @@ static bool object_select_all_by_library(bContext *C, Library *lib)
{
bool changed = false;
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
- if ((base->flag & SELECT) == 0) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
if (lib == base->object->id.lib) {
- base->flag |= SELECT;
- base->object->flag = base->flag;
-
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -395,13 +366,11 @@ static bool object_select_all_by_library_obdata(bContext *C, Library *lib)
{
bool changed = false;
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
- if ((base->flag & SELECT) == 0) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
if (base->object->data && lib == ((ID *)base->object->data)->lib) {
- base->flag |= SELECT;
- base->object->flag = base->flag;
-
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -441,9 +410,9 @@ static int object_select_linked_exec(bContext *C, wmOperator *op)
extend = RNA_boolean_get(op->ptr, "extend");
if (extend == 0) {
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
- ED_base_object_select(base, BA_DESELECT);
+ ED_object_base_select(base, BA_DESELECT);
}
CTX_DATA_END;
}
@@ -543,7 +512,7 @@ enum {
OBJECT_GRPSEL_PARENT = 2,
OBJECT_GRPSEL_SIBLINGS = 3,
OBJECT_GRPSEL_TYPE = 4,
- OBJECT_GRPSEL_LAYER = 5,
+ /*OBJECT_GRPSEL_LAYER = 5,*/
OBJECT_GRPSEL_GROUP = 6,
OBJECT_GRPSEL_HOOK = 7,
OBJECT_GRPSEL_PASS = 8,
@@ -559,7 +528,6 @@ static EnumPropertyItem prop_select_grouped_types[] = {
{OBJECT_GRPSEL_PARENT, "PARENT", 0, "Parent", ""},
{OBJECT_GRPSEL_SIBLINGS, "SIBLINGS", 0, "Siblings", "Shared Parent"},
{OBJECT_GRPSEL_TYPE, "TYPE", 0, "Type", "Shared object type"},
- {OBJECT_GRPSEL_LAYER, "LAYER", 0, "Layer", "Shared layers"},
{OBJECT_GRPSEL_GROUP, "GROUP", 0, "Group", "Shared group"},
{OBJECT_GRPSEL_HOOK, "HOOK", 0, "Hook", ""},
{OBJECT_GRPSEL_PASS, "PASS", 0, "Pass", "Render pass Index"},
@@ -574,16 +542,17 @@ static bool select_grouped_children(bContext *C, Object *ob, const bool recursiv
{
bool changed = false;
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selectable_bases)
{
if (ob == base->object->parent) {
- if (!(base->flag & SELECT)) {
- ED_base_object_select(base, BA_SELECT);
+ if ((base->flag & BASE_SELECTED) == 0) {
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
- if (recursive)
+ if (recursive) {
changed |= select_grouped_children(C, base->object, 1);
+ }
}
}
CTX_DATA_END;
@@ -633,11 +602,13 @@ static bool select_grouped_group(bContext *C, Object *ob) /* Select objects in
return 0;
else if (group_count == 1) {
group = ob_groups[0];
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
- if (!(base->flag & SELECT) && BKE_group_object_exists(group, base->object)) {
- ED_base_object_select(base, BA_SELECT);
- changed = true;
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
+ if (BKE_group_object_exists(group, base->object)) {
+ ED_object_base_select(base, BA_SELECT);
+ changed = true;
+ }
}
}
CTX_DATA_END;
@@ -688,10 +659,10 @@ static bool select_grouped_siblings(bContext *C, Object *ob)
{
bool changed = false;
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selectable_bases)
{
- if ((base->object->parent == ob->parent) && !(base->flag & SELECT)) {
- ED_base_object_select(base, BA_SELECT);
+ if ((base->object->parent == ob->parent) && ((base->flag & BASE_SELECTED) == 0)) {
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -704,12 +675,12 @@ static bool select_grouped_lamptype(bContext *C, Object *ob)
bool changed = false;
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selectable_bases)
{
if (base->object->type == OB_LAMP) {
Lamp *la_test = base->object->data;
- if ((la->type == la_test->type) && !(base->flag & SELECT)) {
- ED_base_object_select(base, BA_SELECT);
+ if ((la->type == la_test->type) && ((base->flag & BASE_SELECTED) == 0)) {
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -721,25 +692,10 @@ static bool select_grouped_type(bContext *C, Object *ob)
{
bool changed = false;
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selectable_bases)
{
- if ((base->object->type == ob->type) && !(base->flag & SELECT)) {
- ED_base_object_select(base, BA_SELECT);
- changed = true;
- }
- }
- CTX_DATA_END;
- return changed;
-}
-
-static bool select_grouped_layer(bContext *C, Object *ob)
-{
- bool changed = false;
-
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
- {
- if ((base->lay & ob->lay) && !(base->flag & SELECT)) {
- ED_base_object_select(base, BA_SELECT);
+ if ((base->object->type == ob->type) && ((base->flag & BASE_SELECTED) == 0)) {
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -751,10 +707,10 @@ static bool select_grouped_index_object(bContext *C, Object *ob)
{
bool changed = false;
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selectable_bases)
{
- if ((base->object->index == ob->index) && !(base->flag & SELECT)) {
- ED_base_object_select(base, BA_SELECT);
+ if ((base->object->index == ob->index) && ((base->flag & BASE_SELECTED) == 0)) {
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -766,10 +722,10 @@ static bool select_grouped_color(bContext *C, Object *ob)
{
bool changed = false;
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selectable_bases)
{
- if (!(base->flag & SELECT) && (compare_v3v3(base->object->col, ob->col, 0.005f))) {
- ED_base_object_select(base, BA_SELECT);
+ if (((base->flag & BASE_SELECTED) == 0) && (compare_v3v3(base->object->col, ob->col, 0.005f))) {
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -793,10 +749,10 @@ static bool select_grouped_gameprops(bContext *C, Object *ob)
{
bool changed = false;
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selectable_bases)
{
- if (!(base->flag & SELECT) && (objects_share_gameprop(base->object, ob))) {
- ED_base_object_select(base, BA_SELECT);
+ if (((base->flag & BASE_SELECTED) == 0) && (objects_share_gameprop(base->object, ob))) {
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -831,10 +787,10 @@ static bool select_grouped_keyingset(bContext *C, Object *UNUSED(ob), ReportList
/* select each object that Keying Set refers to */
/* TODO: perhaps to be more in line with the rest of these, we should only take objects
* if the passed in object is included in this too */
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selectable_bases)
{
/* only check for this object if it isn't selected already, to limit time wasted */
- if ((base->flag & SELECT) == 0) {
+ if ((base->flag & BASE_SELECTED) == 0) {
KS_Path *ksp;
/* this is the slow way... we could end up with > 500 items here,
@@ -843,7 +799,7 @@ static bool select_grouped_keyingset(bContext *C, Object *UNUSED(ob), ReportList
for (ksp = ks->paths.first; ksp; ksp = ksp->next) {
/* if id matches, select then stop looping (match found) */
if (ksp->id == (ID *)base->object) {
- ED_base_object_select(base, BA_SELECT);
+ ED_object_base_select(base, BA_SELECT);
changed = true;
break;
}
@@ -865,9 +821,9 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op)
extend = RNA_boolean_get(op->ptr, "extend");
if (extend == 0) {
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
- ED_base_object_select(base, BA_DESELECT);
+ ED_object_base_select(base, BA_DESELECT);
changed = true;
}
CTX_DATA_END;
@@ -895,9 +851,6 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op)
case OBJECT_GRPSEL_TYPE:
changed |= select_grouped_type(C, ob);
break;
- case OBJECT_GRPSEL_LAYER:
- changed |= select_grouped_layer(C, ob);
- break;
case OBJECT_GRPSEL_GROUP:
changed |= select_grouped_group(C, ob);
break;
@@ -955,85 +908,6 @@ void OBJECT_OT_select_grouped(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", "");
}
-/************************* Select by Layer **********************/
-enum {
- OB_SEL_LAYERMATCH_EXACT = 1,
- OB_SEL_LAYERMATCH_SHARED = 2,
-};
-
-static int object_select_by_layer_exec(bContext *C, wmOperator *op)
-{
- unsigned int layernum;
- bool extend;
- int match;
-
- extend = RNA_boolean_get(op->ptr, "extend");
- layernum = RNA_int_get(op->ptr, "layers");
- match = RNA_enum_get(op->ptr, "match");
-
- if (extend == false) {
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- ED_base_object_select(base, BA_DESELECT);
- }
- CTX_DATA_END;
- }
-
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
- {
- bool ok = false;
-
- switch (match) {
- case OB_SEL_LAYERMATCH_EXACT:
- /* Mask out bits used for local view, only work on real layer ones, see T45783. */
- ok = ((base->lay & ((1 << 20) - 1)) == (1 << (layernum - 1)));
- break;
- case OB_SEL_LAYERMATCH_SHARED:
- ok = (base->lay & (1 << (layernum - 1))) != 0;
- break;
- default:
- break;
- }
-
- if (ok) {
- ED_base_object_select(base, BA_SELECT);
- }
- }
- CTX_DATA_END;
-
- /* undo? */
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
-
- return OPERATOR_FINISHED;
-}
-
-void OBJECT_OT_select_by_layer(wmOperatorType *ot)
-{
- static EnumPropertyItem match_items[] = {
- {OB_SEL_LAYERMATCH_EXACT, "EXACT", 0, "Exact Match", ""},
- {OB_SEL_LAYERMATCH_SHARED, "SHARED", 0, "Shared Layers", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- /* identifiers */
- ot->name = "Select by Layer";
- ot->description = "Select all visible objects on a layer";
- ot->idname = "OBJECT_OT_select_by_layer";
-
- /* api callbacks */
- /*ot->invoke = XXX - need a int grid popup*/
- ot->exec = object_select_by_layer_exec;
- ot->poll = objects_selectable_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- /* properties */
- RNA_def_enum(ot->srna, "match", match_items, OB_SEL_LAYERMATCH_EXACT, "Match", "");
- RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
- RNA_def_int(ot->srna, "layers", 1, 1, 20, "Layer", "", 1, 20);
-}
-
/**************************** (De)select All ****************************/
static int object_select_all_exec(bContext *C, wmOperator *op)
@@ -1045,9 +919,9 @@ static int object_select_all_exec(bContext *C, wmOperator *op)
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
- if (base->flag & SELECT) {
+ if ((base->flag & BASE_SELECTED) != 0) {
action = SEL_DESELECT;
break;
}
@@ -1055,21 +929,21 @@ static int object_select_all_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
}
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
switch (action) {
case SEL_SELECT:
- ED_base_object_select(base, BA_SELECT);
+ ED_object_base_select(base, BA_SELECT);
break;
case SEL_DESELECT:
- ED_base_object_select(base, BA_DESELECT);
+ ED_object_base_select(base, BA_DESELECT);
break;
case SEL_INVERT:
- if (base->flag & SELECT) {
- ED_base_object_select(base, BA_DESELECT);
+ if ((base->flag & BASE_SELECTED) != 0) {
+ ED_object_base_select(base, BA_DESELECT);
}
else {
- ED_base_object_select(base, BA_SELECT);
+ ED_object_base_select(base, BA_SELECT);
}
break;
}
@@ -1117,10 +991,13 @@ static int object_select_same_group_exec(bContext *C, wmOperator *op)
return OPERATOR_PASS_THROUGH;
}
- CTX_DATA_BEGIN (C, Base *, base, visible_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, visible_bases)
{
- if (!(base->flag & SELECT) && BKE_group_object_exists(group, base->object))
- ED_base_object_select(base, BA_SELECT);
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
+ if (BKE_group_object_exists(group, base->object)) {
+ ED_object_base_select(base, BA_SELECT);
+ }
+ }
}
CTX_DATA_END;
@@ -1151,28 +1028,29 @@ void OBJECT_OT_select_same_group(wmOperatorType *ot)
static int object_select_mirror_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
bool extend;
extend = RNA_boolean_get(op->ptr, "extend");
- CTX_DATA_BEGIN (C, Base *, primbase, selected_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, primbase, selected_bases)
{
char name_flip[MAXBONENAME];
- BKE_deform_flip_side_name(name_flip, primbase->object->id.name + 2, true);
+ BLI_string_flip_side_name(name_flip, primbase->object->id.name + 2, true, sizeof(name_flip));
if (!STREQ(name_flip, primbase->object->id.name + 2)) {
Object *ob = (Object *)BKE_libblock_find_name(ID_OB, name_flip);
if (ob) {
- Base *secbase = BKE_scene_base_find(scene, ob);
+ ObjectBase *secbase = BKE_scene_layer_base_find(sl, ob);
if (secbase) {
- ED_base_object_select(secbase, BA_SELECT);
+ ED_object_base_select(secbase, BA_SELECT);
}
}
}
- if (extend == false) ED_base_object_select(primbase, BA_DESELECT);
+ if (extend == false) ED_object_base_select(primbase, BA_DESELECT);
}
CTX_DATA_END;
@@ -1207,9 +1085,9 @@ void OBJECT_OT_select_mirror(wmOperatorType *ot)
static bool object_select_more_less(bContext *C, const bool select)
{
- Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
- for (Base *base = scene->base.first; base; base = base->next) {
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
Object *ob = base->object;
ob->flag &= ~OB_DONE;
ob->id.tag &= ~LIB_TAG_DOIT;
@@ -1233,7 +1111,7 @@ static bool object_select_more_less(bContext *C, const bool select)
for (ctx_base = ctx_base_list.first; ctx_base; ctx_base = ctx_base->next) {
- Object *ob = ((Base *)ctx_base->ptr.data)->object;
+ Object *ob = ((ObjectBase *)ctx_base->ptr.data)->object;
if (ob->parent) {
if ((ob->flag & OB_DONE) != (ob->parent->flag & OB_DONE)) {
ob->id.tag |= LIB_TAG_DOIT;
@@ -1247,10 +1125,10 @@ static bool object_select_more_less(bContext *C, const bool select)
const short select_flag = select ? SELECT : 0;
for (ctx_base = ctx_base_list.first; ctx_base; ctx_base = ctx_base->next) {
- Base *base = ctx_base->ptr.data;
+ ObjectBase *base = ctx_base->ptr.data;
Object *ob = base->object;
if ((ob->id.tag & LIB_TAG_DOIT) && ((ob->flag & SELECT) != select_flag)) {
- ED_base_object_select(base, select_mode);
+ ED_object_base_select(base, select_mode);
changed = true;
}
}
@@ -1329,10 +1207,10 @@ static int object_select_random_exec(bContext *C, wmOperator *op)
RNG *rng = BLI_rng_new_srandom(seed);
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selectable_bases)
{
if (BLI_rng_get_float(rng) < randfac) {
- ED_base_object_select(base, select);
+ ED_object_base_select(base, select);
}
}
CTX_DATA_END;
diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c
index 1bfc162a331..b7be31602d9 100644
--- a/source/blender/editors/physics/rigidbody_constraint.c
+++ b/source/blender/editors/physics/rigidbody_constraint.c
@@ -89,7 +89,7 @@ bool ED_rigidbody_constraint_add(Main *bmain, Scene *scene, Object *ob, int type
ob->rigidbody_constraint->flag |= RBC_FLAG_NEEDS_VALIDATE;
/* add constraint to rigid body constraint group */
- BKE_group_object_add(rbw->constraints, ob, scene, NULL);
+ BKE_group_object_add(rbw->constraints, ob);
DAG_relations_tag_update(bmain);
DAG_id_tag_update(&ob->id, OB_RECALC_OB);
@@ -102,7 +102,7 @@ void ED_rigidbody_constraint_remove(Main *bmain, Scene *scene, Object *ob)
BKE_rigidbody_remove_constraint(scene, ob);
if (rbw)
- BKE_group_object_unlink(rbw->constraints, ob, scene, NULL);
+ BKE_group_object_unlink(rbw->constraints, ob);
DAG_relations_tag_update(bmain);
DAG_id_tag_update(&ob->id, OB_RECALC_OB);
diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c
index 30597d95497..c9e32fa5194 100644
--- a/source/blender/editors/physics/rigidbody_object.c
+++ b/source/blender/editors/physics/rigidbody_object.c
@@ -119,7 +119,7 @@ bool ED_rigidbody_object_add(Main *bmain, Scene *scene, Object *ob, int type, Re
ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_VALIDATE;
/* add object to rigid body group */
- BKE_group_object_add(rbw->group, ob, scene, NULL);
+ BKE_group_object_add(rbw->group, ob);
DAG_relations_tag_update(bmain);
DAG_id_tag_update(&ob->id, OB_RECALC_OB);
@@ -133,7 +133,7 @@ void ED_rigidbody_object_remove(Main *bmain, Scene *scene, Object *ob)
BKE_rigidbody_remove_object(scene, ob);
if (rbw)
- BKE_group_object_unlink(rbw->group, ob, scene, NULL);
+ BKE_group_object_unlink(rbw->group, ob);
DAG_relations_tag_update(bmain);
DAG_id_tag_update(&ob->id, OB_RECALC_OB);
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index fe734954bba..7f91cd42d27 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -2521,9 +2521,7 @@ void ED_region_visible_rect(ARegion *ar, rcti *rect)
void ED_region_cache_draw_background(const ARegion *ar)
{
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
-
+ unsigned pos = add_attrib(immVertexFormat(), "pos", COMP_I32, 2, CONVERT_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4ub(128, 128, 255, 64);
immRecti(pos, 0, 0, ar->winx, 8 * UI_DPI_FAC);
@@ -2543,7 +2541,11 @@ void ED_region_cache_draw_curfra_label(const int framenr, const float x, const f
BLF_width_and_height(fontid, numstr, sizeof(numstr), &font_dims[0], &font_dims[1]);
- glRecti(x, y, x + font_dims[0] + 6.0f, y + font_dims[1] + 4.0f);
+ unsigned pos = add_attrib(immVertexFormat(), "pos", COMP_I32, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_CFRAME);
+ immRecti(pos, x, y, x + font_dims[0] + 6.0f, y + font_dims[1] + 4.0f);
+ immUnbindProgram();
UI_ThemeColor(TH_TEXT);
BLF_position(fontid, x + 2.0f, y + 2.0f, 0.0f);
@@ -2553,17 +2555,18 @@ void ED_region_cache_draw_curfra_label(const int framenr, const float x, const f
void ED_region_cache_draw_cached_segments(const ARegion *ar, const int num_segments, const int *points, const int sfra, const int efra)
{
if (num_segments) {
- int a;
-
- glColor4ub(128, 128, 255, 128);
-
- for (a = 0; a < num_segments; a++) {
- float x1, x2;
+ unsigned pos = add_attrib(immVertexFormat(), "pos", COMP_I32, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ub(128, 128, 255, 128);
- x1 = (float)(points[a * 2] - sfra) / (efra - sfra + 1) * ar->winx;
- x2 = (float)(points[a * 2 + 1] - sfra + 1) / (efra - sfra + 1) * ar->winx;
+ for (int a = 0; a < num_segments; a++) {
+ float x1 = (float)(points[a * 2] - sfra) / (efra - sfra + 1) * ar->winx;
+ float x2 = (float)(points[a * 2 + 1] - sfra + 1) / (efra - sfra + 1) * ar->winx;
- glRecti(x1, 0, x2, 8 * UI_DPI_FAC);
+ immRecti(pos, x1, 0, x2, 8 * UI_DPI_FAC);
+ /* TODO(merwin): use primitive restart to draw multiple rects more efficiently */
}
+
+ immUnbindProgram();
}
}
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index 47593252ecb..ef514dd5e84 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -53,8 +53,8 @@
#include "UI_interface.h"
-
-void fdrawline(float x1, float y1, float x2, float y2) /* DEPRECATED */
+/* DEPRECATED: use imm_draw_line instead */
+void fdrawline(float x1, float y1, float x2, float y2)
{
glBegin(GL_LINES);
glVertex2f(x1, y1);
@@ -213,6 +213,14 @@ void imm_draw_line_box(unsigned pos, float x1, float y1, float x2, float y2)
immEnd();
}
+void imm_draw_line(unsigned pos, float x1, float y1, float x2, float y2)
+{
+ immBegin(PRIM_LINES, 2);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x2, y2);
+ immEnd();
+}
+
void imm_draw_line_box_3D(unsigned pos, float x1, float y1, float x2, float y2)
{
/* use this version when VertexFormat has a vec3 position */
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
index ebf229f2fbb..c844f56cfc2 100644
--- a/source/blender/editors/screen/screen_context.c
+++ b/source/blender/editors/screen/screen_context.c
@@ -61,18 +61,6 @@
#include "screen_intern.h"
-static unsigned int context_layers(bScreen *sc, Scene *scene, ScrArea *sa_ctx)
-{
- /* needed for 'USE_ALLSELECT' define, otherwise we end up editing off-screen layers. */
- if (sc && sa_ctx && (sa_ctx->spacetype == SPACE_BUTS)) {
- const unsigned int lay = BKE_screen_view3d_layer_all(sc);
- if (lay) {
- return lay;
- }
- }
- return scene->lay;
-}
-
const char *screen_context_dir[] = {
"scene", "render_layer", "visible_objects", "visible_bases", "selectable_objects", "selectable_bases",
"selected_objects", "selected_bases",
@@ -109,17 +97,18 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
return 1;
}
else if (CTX_data_equals(member, "visible_objects")) {
- for (ObjectBase *base = sl->object_bases.first; base; base = base->next) {
- if (((base->object->restrictflag & OB_RESTRICT_VIEW) == 0)) {
- CTX_data_id_list_add(result, &base->object->id);
- }
+ Object *ob;
+ FOREACH_VISIBLE_OBJECT(sl, ob)
+ {
+ CTX_data_id_list_add(result, &ob->id);
}
+ FOREACH_VISIBLE_BASE_END
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return 1;
}
else if (CTX_data_equals(member, "selectable_objects")) {
for (ObjectBase *base = sl->object_bases.first; base; base = base->next) {
- if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0 && (base->object->restrictflag & OB_RESTRICT_SELECT) == 0) {
+ if (((base->flag & BASE_VISIBLED) != 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
CTX_data_id_list_add(result, &base->object->id);
}
}
@@ -140,10 +129,8 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
Object *ob;
FOREACH_SELECTED_OBJECT(sl, ob)
{
- if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0) {
- if (0 == BKE_object_is_libdata(ob)) {
- CTX_data_id_list_add(result, &ob->id);
- }
+ if (0 == BKE_object_is_libdata(ob)) {
+ CTX_data_id_list_add(result, &ob->id);
}
}
FOREACH_SELECTED_OBJECT_END
@@ -152,45 +139,39 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
}
else if (CTX_data_equals(member, "editable_objects")) {
/* Visible + Editable, but not necessarily selected */
- for (ObjectBase *base = sl->object_bases.first; base; base = base->next) {
- if (((base->object->restrictflag & OB_RESTRICT_VIEW) == 0)) {
- if (0 == BKE_object_is_libdata(base->object)) {
- CTX_data_id_list_add(result, &base->object->id);
- }
+ Object *ob;
+ FOREACH_VISIBLE_OBJECT(sl, ob)
+ {
+ if (0 == BKE_object_is_libdata(ob)) {
+ CTX_data_id_list_add(result, &ob->id);
}
}
+ FOREACH_VISIBLE_OBJECT_END
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return 1;
}
else if ( CTX_data_equals(member, "visible_bases")) {
- const unsigned int lay = context_layers(sc, scene, sa);
-
- for (Base *base = scene->base.first; base; base = base->next) {
- if (((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) && (base->lay & lay)) {
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
- }
+ ObjectBase *base;
+ FOREACH_VISIBLE_BASE(sl, base)
+ {
+ CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
}
+ FOREACH_VISIBLE_BASE_END
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return 1;
}
else if (CTX_data_equals(member, "selectable_bases")) {
- const unsigned int lay = context_layers(sc, scene, sa);
-
- for (Base *base = scene->base.first; base; base = base->next) {
- if (base->lay & lay) {
- if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0 && (base->object->restrictflag & OB_RESTRICT_SELECT) == 0) {
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
- }
+ for (ObjectBase *base = sl->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_SELECTABLED) != 0) {
+ CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
}
}
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return 1;
}
else if (CTX_data_equals(member, "selected_bases")) {
- const unsigned int lay = context_layers(sc, scene, sa);
-
- for (Base *base = scene->base.first; base; base = base->next) {
- if ((base->flag & SELECT) && (base->lay & lay)) {
+ for (ObjectBase *base = sl->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_SELECTED) != 0) {
CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
}
}
@@ -198,14 +179,10 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
return 1;
}
else if (CTX_data_equals(member, "selected_editable_bases")) {
- const unsigned int lay = context_layers(sc, scene, sa);
-
- for (Base *base = scene->base.first; base; base = base->next) {
- if ((base->flag & SELECT) && (base->lay & lay)) {
- if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) {
- if (0 == BKE_object_is_libdata(base->object)) {
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
- }
+ for (ObjectBase *base = sl->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_SELECTED) != 0) {
+ if (0 == BKE_object_is_libdata(base->object)) {
+ CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
}
}
}
@@ -213,11 +190,9 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
return 1;
}
else if (CTX_data_equals(member, "editable_bases")) {
- const unsigned int lay = context_layers(sc, scene, sa);
-
/* Visible + Editable, but not necessarily selected */
- for (Base *base = scene->base.first; base; base = base->next) {
- if (((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) && (base->lay & lay)) {
+ for (ObjectBase *base = sl->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_VISIBLED) != 0) {
if (0 == BKE_object_is_libdata(base->object)) {
CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
}
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 991025a4d5d..729dd9dc57b 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -36,6 +36,7 @@
#include "BLI_array_utils.h"
#include "BLI_bitmap.h"
#include "BLI_stack.h"
+#include "BLI_string_utils.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -275,7 +276,7 @@ static int wpaint_mirror_vgroup_ensure(Object *ob, const int vgroup_active)
int mirrdef;
char name_flip[MAXBONENAME];
- BKE_deform_flip_side_name(name_flip, defgroup->name, false);
+ BLI_string_flip_side_name(name_flip, defgroup->name, false, sizeof(name_flip));
mirrdef = defgroup_name_index(ob, name_flip);
if (mirrdef == -1) {
if (BKE_defgroup_new(ob, name_flip)) {
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 47f0220726b..84e98181dfb 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -5693,11 +5693,11 @@ static int sculpt_set_detail_size_exec(bContext *C, wmOperator *UNUSED(op))
WM_operator_properties_create_ptr(&props_ptr, ot);
if (sd->flags & SCULPT_DYNTOPO_DETAIL_CONSTANT) {
- set_brush_rc_props(&props_ptr, "sculpt", "constant_detail", NULL, 0);
- RNA_string_set(&props_ptr, "data_path_primary", "tool_settings.sculpt.constant_detail");
+ set_brush_rc_props(&props_ptr, "sculpt", "constant_detail_resolution", NULL, 0);
+ RNA_string_set(&props_ptr, "data_path_primary", "tool_settings.sculpt.constant_detail_resolution");
}
else if (sd->flags & SCULPT_DYNTOPO_DETAIL_BRUSH) {
- set_brush_rc_props(&props_ptr, "sculpt", "constant_detail", NULL, 0);
+ set_brush_rc_props(&props_ptr, "sculpt", "constant_detail_resolution", NULL, 0);
RNA_string_set(&props_ptr, "data_path_primary", "tool_settings.sculpt.detail_percent");
}
else {
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index df9c67b1f2e..feea9cf5b13 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -171,6 +171,8 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
unsigned char col1a[3], col2a[3];
unsigned char col1b[3], col2b[3];
+ const bool show_group_colors = !(saction->flag & SACTION_NODRAWGCOLORS);
+
/* get theme colors */
UI_GetThemeColor3ubv(TH_BACK, col2);
@@ -254,8 +256,36 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
}
case ANIMTYPE_GROUP:
{
- if (sel) immUniformColor4ub(col1a[0], col1a[1], col1a[2], 0x22);
- else immUniformColor4ub(col2a[0], col2a[1], col2a[2], 0x22);
+ bActionGroup *agrp = ale->data;
+ if (show_group_colors && agrp->customCol) {
+ if (sel) {
+ unsigned char *cp = agrp->cs.select;
+ immUniformColor4ub(cp[0], cp[1], cp[2], 0x45);
+ }
+ else {
+ unsigned char *cp = agrp->cs.solid;
+ immUniformColor4ub(cp[0], cp[1], cp[2], 0x1D);
+ }
+ }
+ else {
+ if (sel) immUniformColor4ub(col1a[0], col1a[1], col1a[2], 0x22);
+ else immUniformColor4ub(col2a[0], col2a[1], col2a[2], 0x22);
+ }
+ break;
+ }
+ case ANIMTYPE_FCURVE:
+ {
+ FCurve *fcu = ale->data;
+ if (show_group_colors && fcu->grp && fcu->grp->customCol) {
+ unsigned char *cp = (unsigned char *)fcu->grp->cs.active;
+
+ if (sel) immUniformColor4ub(cp[0], cp[1], cp[2], 0x65);
+ else immUniformColor4ub(cp[0], cp[1], cp[2], 0x0B);
+ }
+ else {
+ if (sel) immUniformColor4ub(col1[0], col1[1], col1[2], 0x22);
+ else immUniformColor4ub(col2[0], col2[1], col2[2], 0x22);
+ }
break;
}
default:
diff --git a/source/blender/editors/space_logic/logic_ops.c b/source/blender/editors/space_logic/logic_ops.c
index 074368a82c5..1559515221e 100644
--- a/source/blender/editors/space_logic/logic_ops.c
+++ b/source/blender/editors/space_logic/logic_ops.c
@@ -37,6 +37,7 @@
#include "DNA_scene_types.h"
#include "BLI_blenlib.h"
+#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c
index 874e54ba5e7..3de44174d6a 100644
--- a/source/blender/editors/space_logic/logic_window.c
+++ b/source/blender/editors/space_logic/logic_window.c
@@ -47,8 +47,8 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
+#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
-#include "BLI_path_util.h"
#include "BKE_action.h"
#include "BKE_context.h"
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index 3243579f7d0..5355b8012db 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -502,51 +502,57 @@ static void nla_panel_modifiers(const bContext *C, Panel *pa)
void nla_buttons_register(ARegionType *art)
{
PanelType *pt;
-
+
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel animdata");
strcpy(pt->idname, "NLA_PT_animdata");
strcpy(pt->label, N_("Animation Data"));
+ strcpy(pt->category, "Animations");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_animdata;
pt->poll = nla_animdata_panel_poll;
pt->flag = PNL_DEFAULT_CLOSED;
BLI_addtail(&art->paneltypes, pt);
-
+
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel track");
strcpy(pt->idname, "NLA_PT_track");
strcpy(pt->label, N_("Active Track"));
+ strcpy(pt->category, "Animations");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_track;
pt->poll = nla_track_panel_poll;
BLI_addtail(&art->paneltypes, pt);
-
+
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel properties");
strcpy(pt->idname, "NLA_PT_properties");
strcpy(pt->label, N_("Active Strip"));
+ strcpy(pt->category, "Animations");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_properties;
pt->poll = nla_strip_panel_poll;
BLI_addtail(&art->paneltypes, pt);
-
+
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel properties");
strcpy(pt->idname, "NLA_PT_actionclip");
strcpy(pt->label, N_("Action Clip"));
+ strcpy(pt->category, "Animations");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_actclip;
pt->poll = nla_strip_actclip_panel_poll;
BLI_addtail(&art->paneltypes, pt);
-
+
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel evaluation");
strcpy(pt->idname, "NLA_PT_evaluation");
strcpy(pt->label, N_("Evaluation"));
+ strcpy(pt->category, "Animations");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_evaluation;
pt->poll = nla_strip_eval_panel_poll;
BLI_addtail(&art->paneltypes, pt);
-
+
pt = MEM_callocN(sizeof(PanelType), "spacetype nla panel modifiers");
strcpy(pt->idname, "NLA_PT_modifiers");
strcpy(pt->label, N_("Modifiers"));
+ strcpy(pt->category, "Modifiers");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
pt->draw = nla_panel_modifiers;
pt->poll = nla_strip_eval_panel_poll;
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index e9c46e9d04b..70dd80540ec 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -45,6 +45,7 @@
#include "BKE_nla.h"
#include "BKE_context.h"
#include "BKE_global.h"
+#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_report.h"
@@ -134,7 +135,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
if (selectmode == SELECT_INVERT) {
/* swap select */
base->flag ^= SELECT;
- ob->flag = base->flag;
+ BKE_scene_base_flag_sync_from_base(base);
if (adt) adt->flag ^= ADT_UI_SELECTED;
}
@@ -145,7 +146,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
/* TODO: should this deselect all other types of channels too? */
for (b = sce->base.first; b; b = b->next) {
b->flag &= ~SELECT;
- b->object->flag = b->flag;
+ BKE_scene_base_flag_sync_from_base(b);
if (b->object->adt) b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE);
}
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 18f4a02ab72..d7229729e26 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -40,6 +40,7 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
#include "BLI_mempool.h"
@@ -173,116 +174,6 @@ static void restrictbutton_recursive_bone(Bone *bone_parent, int flag, bool set_
}
-static void restrictbutton_recursive_child(bContext *C, Scene *scene, Object *ob_parent, char flag,
- bool state, bool deselect, const char *rnapropname)
-{
- Main *bmain = CTX_data_main(C);
- Object *ob;
-
- for (ob = bmain->object.first; ob; ob = ob->id.next) {
- if (BKE_object_is_child_recursive(ob_parent, ob)) {
- /* only do if child object is selectable */
- if ((flag == OB_RESTRICT_SELECT) || (ob->restrictflag & OB_RESTRICT_SELECT) == 0) {
- if (state) {
- ob->restrictflag |= flag;
- if (deselect) {
- ED_base_object_select(BKE_scene_base_find(scene, ob), BA_DESELECT);
- }
- }
- else {
- ob->restrictflag &= ~flag;
- }
- }
-
- if (rnapropname) {
- PointerRNA ptr;
- PropertyRNA *prop;
- ID *id;
- bAction *action;
- FCurve *fcu;
- bool driven, special;
-
- RNA_id_pointer_create(&ob->id, &ptr);
- prop = RNA_struct_find_property(&ptr, rnapropname);
- fcu = rna_get_fcurve_context_ui(C, &ptr, prop, 0, NULL, &action, &driven, &special);
-
- if (fcu && !driven) {
- id = ptr.id.data;
- if (autokeyframe_cfra_can_key(scene, id)) {
- ReportList *reports = CTX_wm_reports(C);
- ToolSettings *ts = scene->toolsettings;
- eInsertKeyFlags key_flag = ANIM_get_keyframing_flags(scene, 1);
-
- fcu->flag &= ~FCURVE_SELECTED;
- insert_keyframe(reports, id, action, ((fcu->grp) ? (fcu->grp->name) : (NULL)),
- fcu->rna_path, fcu->array_index, CFRA, ts->keyframe_type, key_flag);
- /* Assuming this is not necessary here, since 'ancestor' object button will do it anyway. */
- /* WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); */
- }
- }
- }
- }
- }
-}
-
-static void restrictbutton_view_cb(bContext *C, void *poin, void *poin2)
-{
- Scene *scene = (Scene *)poin;
- Object *ob = (Object *)poin2;
-
- if (!common_restrict_check(C, ob)) return;
-
- /* deselect objects that are invisible */
- if (ob->restrictflag & OB_RESTRICT_VIEW) {
- /* Ouch! There is no backwards pointer from Object to Base,
- * so have to do loop to find it. */
- ED_base_object_select(BKE_scene_base_find(scene, ob), BA_DESELECT);
- }
-
- if (CTX_wm_window(C)->eventstate->ctrl) {
- restrictbutton_recursive_child(C, scene, ob, OB_RESTRICT_VIEW,
- (ob->restrictflag & OB_RESTRICT_VIEW) != 0, true, "hide");
- }
-
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
-
-}
-
-static void restrictbutton_sel_cb(bContext *C, void *poin, void *poin2)
-{
- Scene *scene = (Scene *)poin;
- Object *ob = (Object *)poin2;
-
- if (!common_restrict_check(C, ob)) return;
-
- /* if select restriction has just been turned on */
- if (ob->restrictflag & OB_RESTRICT_SELECT) {
- /* Ouch! There is no backwards pointer from Object to Base,
- * so have to do loop to find it. */
- ED_base_object_select(BKE_scene_base_find(scene, ob), BA_DESELECT);
- }
-
- if (CTX_wm_window(C)->eventstate->ctrl) {
- restrictbutton_recursive_child(C, scene, ob, OB_RESTRICT_SELECT,
- (ob->restrictflag & OB_RESTRICT_SELECT) != 0, true, NULL);
- }
-
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
-
-}
-
-static void restrictbutton_rend_cb(bContext *C, void *poin, void *poin2)
-{
- Object *ob = (Object *)poin2;
-
- if (CTX_wm_window(C)->eventstate->ctrl) {
- restrictbutton_recursive_child(C, (Scene *)poin, ob, OB_RESTRICT_RENDER,
- (ob->restrictflag & OB_RESTRICT_RENDER) != 0, false, "hide_render");
- }
-
- WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, poin);
-}
-
static void restrictbutton_r_lay_cb(bContext *C, void *poin, void *UNUSED(poin2))
{
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, poin);
@@ -356,98 +247,6 @@ static void restrictbutton_gp_layer_flag_cb(bContext *C, void *UNUSED(poin), voi
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
}
-static int group_restrict_flag(Group *gr, int flag)
-{
- GroupObject *gob;
-
-#ifdef USE_GROUP_SELECT
- for (gob = gr->gobject.first; gob; gob = gob->next) {
- if ((gob->ob->restrictflag & flag) == 0)
- return 0;
- }
- return 1;
-#else
- /* weak but fast */
- if ((gob = gr->gobject.first))
- if ((gob->ob->restrictflag & flag) == 0)
- return 0;
- return 1;
-#endif
-}
-
-static int group_select_flag(Group *gr)
-{
- GroupObject *gob;
-
-#ifdef USE_GROUP_SELECT
- for (gob = gr->gobject.first; gob; gob = gob->next)
- if ((gob->ob->flag & SELECT))
- return 1;
-
- return 0;
-#else
- /* weak but fast */
- if ((gob = gr->gobject.first))
- if (gob->ob->flag & SELECT)
- return 1;
- return 0;
-#endif
-}
-
-void restrictbutton_gr_restrict_flag(void *poin, void *poin2, int flag)
-{
- Scene *scene = (Scene *)poin;
- GroupObject *gob;
- Group *gr = (Group *)poin2;
-
- if (group_restrict_flag(gr, flag)) {
- for (gob = gr->gobject.first; gob; gob = gob->next) {
- if (ID_IS_LINKED_DATABLOCK(gob->ob))
- continue;
-
- gob->ob->restrictflag &= ~flag;
-
- if (flag == OB_RESTRICT_VIEW)
- if (gob->ob->flag & SELECT)
- ED_base_object_select(BKE_scene_base_find(scene, gob->ob), BA_DESELECT);
- }
- }
- else {
- for (gob = gr->gobject.first; gob; gob = gob->next) {
- if (ID_IS_LINKED_DATABLOCK(gob->ob))
- continue;
-
- /* not in editmode */
- if (scene->obedit != gob->ob) {
- gob->ob->restrictflag |= flag;
-
- if (ELEM(flag, OB_RESTRICT_SELECT, OB_RESTRICT_VIEW)) {
- if ((gob->ob->flag & SELECT)) {
- ED_base_object_select(BKE_scene_base_find(scene, gob->ob), BA_DESELECT);
- }
- }
- }
- }
- }
-}
-
-static void restrictbutton_gr_restrict_view(bContext *C, void *poin, void *poin2)
-{
- restrictbutton_gr_restrict_flag(poin, poin2, OB_RESTRICT_VIEW);
- WM_event_add_notifier(C, NC_GROUP, NULL);
- DAG_id_type_tag(CTX_data_main(C), ID_OB);
-}
-static void restrictbutton_gr_restrict_select(bContext *C, void *poin, void *poin2)
-{
- restrictbutton_gr_restrict_flag(poin, poin2, OB_RESTRICT_SELECT);
- WM_event_add_notifier(C, NC_GROUP, NULL);
-}
-static void restrictbutton_gr_restrict_render(bContext *C, void *poin, void *poin2)
-{
- restrictbutton_gr_restrict_flag(poin, poin2, OB_RESTRICT_RENDER);
- WM_event_add_notifier(C, NC_GROUP, NULL);
-}
-
static void restrictbutton_id_user_toggle(bContext *UNUSED(C), void *poin, void *UNUSED(poin2))
{
ID *id = (ID *)poin;
@@ -604,7 +403,6 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
TreeElement *te;
TreeStoreElem *tselem;
Object *ob = NULL;
- Group *gr = NULL;
PropertyRNA *object_prop_hide, *object_prop_hide_select, *object_prop_hide_render;
@@ -618,73 +416,8 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
for (te = lb->first; te; te = te->next) {
tselem = TREESTORE(te);
if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
- /* objects have toggle-able restriction flags */
- if (tselem->type == 0 && te->idcode == ID_OB) {
- PointerRNA ptr;
-
- ob = (Object *)tselem->id;
- RNA_pointer_create((ID *)ob, &RNA_Object, ob, &ptr);
-
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_VIEW_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y,
- &ptr, object_prop_hide, -1, 0, 0, -1, -1,
- TIP_("Restrict viewport visibility (Ctrl - Recursive)"));
- UI_but_func_set(bt, restrictbutton_view_cb, scene, ob);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
-
- bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_SELECT_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, UI_UNIT_Y,
- &ptr, object_prop_hide_select, -1, 0, 0, -1, -1,
- TIP_("Restrict viewport selection (Ctrl - Recursive)"));
- UI_but_func_set(bt, restrictbutton_sel_cb, scene, ob);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
-
- bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_RENDER_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, UI_UNIT_Y,
- &ptr, object_prop_hide_render, -1, 0, 0, -1, -1,
- TIP_("Restrict rendering (Ctrl - Recursive)"));
- UI_but_func_set(bt, restrictbutton_rend_cb, scene, ob);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
-
- UI_block_emboss_set(block, UI_EMBOSS);
-
- }
- if (tselem->type == 0 && te->idcode == ID_GR) {
- int restrict_bool;
- int but_flag = UI_BUT_DRAG_LOCK;
- gr = (Group *)tselem->id;
-
- if (ID_IS_LINKED_DATABLOCK(gr))
- but_flag |= UI_BUT_DISABLED;
-
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
-
- restrict_bool = group_restrict_flag(gr, OB_RESTRICT_VIEW);
- bt = uiDefIconBut(block, UI_BTYPE_ICON_TOGGLE, 0, restrict_bool ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0, 0, 0, 0, TIP_("Restrict/Allow visibility in the 3D View"));
- UI_but_func_set(bt, restrictbutton_gr_restrict_view, scene, gr);
- UI_but_flag_enable(bt, but_flag);
-
- restrict_bool = group_restrict_flag(gr, OB_RESTRICT_SELECT);
- bt = uiDefIconBut(block, UI_BTYPE_ICON_TOGGLE, 0, restrict_bool ? ICON_RESTRICT_SELECT_ON : ICON_RESTRICT_SELECT_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0, 0, 0, 0, TIP_("Restrict/Allow selection in the 3D View"));
- UI_but_func_set(bt, restrictbutton_gr_restrict_select, scene, gr);
- UI_but_flag_enable(bt, but_flag);
-
- restrict_bool = group_restrict_flag(gr, OB_RESTRICT_RENDER);
- bt = uiDefIconBut(block, UI_BTYPE_ICON_TOGGLE, 0, restrict_bool ? ICON_RESTRICT_RENDER_ON : ICON_RESTRICT_RENDER_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0, 0, 0, 0, TIP_("Restrict/Allow renderability"));
- UI_but_func_set(bt, restrictbutton_gr_restrict_render, scene, gr);
- UI_but_flag_enable(bt, but_flag);
-
- UI_block_emboss_set(block, UI_EMBOSS);
- }
/* scene render layers and passes have toggle-able flags too! */
- else if (tselem->type == TSE_R_LAYER) {
+ if (tselem->type == TSE_R_LAYER) {
UI_block_emboss_set(block, UI_EMBOSS_NONE);
bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE_N, SCE_LAY_DISABLE, 0, ICON_CHECKBOX_HLT - 1,
@@ -1466,16 +1199,6 @@ static void outliner_draw_tree_element(
active = OL_DRAWSEL_ACTIVE;
}
}
- else if (te->idcode == ID_GR) {
- Group *gr = (Group *)tselem->id;
- if (group_select_flag(gr)) {
- char col[4];
- UI_GetThemeColorType4ubv(TH_SELECT, SPACE_VIEW3D, col);
- rgba_float_args_set(color, (float)col[0] / 255, (float)col[1] / 255, (float)col[2] / 255, alpha);
-
- active = OL_DRAWSEL_ACTIVE;
- }
- }
else if (te->idcode == ID_OB) {
Object *ob = (Object *)tselem->id;
@@ -1681,20 +1404,32 @@ static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase *
{
TreeElement *te;
TreeStoreElem *tselem;
-
+
for (te = lb->first; te; te = te->next) {
tselem = TREESTORE(te);
/* selection status */
if (TSELEM_OPEN(tselem, soops))
- if (tselem->type == TSE_RNA_STRUCT)
- glRecti(0, *starty + 1, (int)ar->v2d.cur.xmax, *starty + UI_UNIT_Y - 1);
+ if (tselem->type == TSE_RNA_STRUCT) {
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immThemeColorShadeAlpha(TH_BACK, -15, -200);
+ immRecti(pos, 0, *starty + 1, (int)ar->v2d.cur.xmax, *starty + UI_UNIT_Y - 1);
+ immUnbindProgram();
+ }
*starty -= UI_UNIT_Y;
if (TSELEM_OPEN(tselem, soops)) {
outliner_draw_struct_marks(ar, soops, &te->subtree, starty);
- if (tselem->type == TSE_RNA_STRUCT)
- fdrawline(0, (float)*starty + UI_UNIT_Y, ar->v2d.cur.xmax, (float)*starty + UI_UNIT_Y);
+ if (tselem->type == TSE_RNA_STRUCT) {
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immThemeColorShadeAlpha(TH_BACK, -15, -200);
+ imm_draw_line(pos, 0, (float)*starty + UI_UNIT_Y, ar->v2d.cur.xmax, (float)*starty + UI_UNIT_Y);
+ immUnbindProgram();
+ }
}
}
}
@@ -1768,8 +1503,6 @@ static void outliner_draw_tree(
if (ELEM(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF)) {
/* struct marks */
- UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
- //UI_ThemeColorShade(TH_BACK, -20);
starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
outliner_draw_struct_marks(ar, soops, &soops->tree, &starty);
}
@@ -1871,6 +1604,7 @@ void draw_outliner(const bContext *C)
{
Main *mainvar = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
ARegion *ar = CTX_wm_region(C);
View2D *v2d = &ar->v2d;
SpaceOops *soops = CTX_wm_space_outliner(C);
@@ -1879,7 +1613,7 @@ void draw_outliner(const bContext *C)
TreeElement *te_edit = NULL;
bool has_restrict_icons;
- outliner_build_tree(mainvar, scene, soops); // always
+ outliner_build_tree(mainvar, scene, sl, soops); // always
/* get extents of data */
outliner_height(soops, &soops->tree, &sizey);
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 4dcdcc69d6d..365797501a4 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -54,6 +54,7 @@
#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_idcode.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_library_remap.h"
@@ -882,181 +883,6 @@ int common_restrict_check(bContext *C, Object *ob)
}
/* =============================================== */
-/* Restriction toggles */
-
-/* Toggle Visibility ---------------------------------------- */
-
-void object_toggle_visibility_cb(
- bContext *C, ReportList *reports, Scene *scene, TreeElement *te,
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- Base *base = (Base *)te->directdata;
- Object *ob = (Object *)tselem->id;
-
- if (ID_IS_LINKED_DATABLOCK(tselem->id)) {
- BKE_report(reports, RPT_WARNING, "Cannot edit external libdata");
- return;
- }
-
- /* add check for edit mode */
- if (!common_restrict_check(C, ob)) return;
-
- if (base || (base = BKE_scene_base_find(scene, ob))) {
- if ((base->object->restrictflag ^= OB_RESTRICT_VIEW)) {
- ED_base_object_select(base, BA_DESELECT);
- }
- }
-}
-
-void group_toggle_visibility_cb(
- bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- Group *group = (Group *)tselem->id;
- restrictbutton_gr_restrict_flag(scene, group, OB_RESTRICT_VIEW);
-}
-
-static int outliner_toggle_visibility_exec(bContext *C, wmOperator *op)
-{
- Main *bmain = CTX_data_main(C);
- SpaceOops *soops = CTX_wm_space_outliner(C);
- Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
-
- outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_visibility_cb);
-
- DAG_id_type_tag(bmain, ID_OB);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene);
- ED_region_tag_redraw(ar);
-
- return OPERATOR_FINISHED;
-}
-
-void OUTLINER_OT_visibility_toggle(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Toggle Visibility";
- ot->idname = "OUTLINER_OT_visibility_toggle";
- ot->description = "Toggle the visibility of selected items";
-
- /* callbacks */
- ot->exec = outliner_toggle_visibility_exec;
- ot->poll = ED_operator_outliner_active_no_editobject;
-
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* Toggle Selectability ---------------------------------------- */
-
-void object_toggle_selectability_cb(
- bContext *UNUSED(C), ReportList *reports, Scene *scene, TreeElement *te,
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- Base *base = (Base *)te->directdata;
-
- if (ID_IS_LINKED_DATABLOCK(tselem->id)) {
- BKE_report(reports, RPT_WARNING, "Cannot edit external libdata");
- return;
- }
-
- if (base == NULL) base = BKE_scene_base_find(scene, (Object *)tselem->id);
- if (base) {
- base->object->restrictflag ^= OB_RESTRICT_SELECT;
- }
-}
-
-void group_toggle_selectability_cb(
- bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- Group *group = (Group *)tselem->id;
- restrictbutton_gr_restrict_flag(scene, group, OB_RESTRICT_SELECT);
-}
-
-static int outliner_toggle_selectability_exec(bContext *C, wmOperator *op)
-{
- SpaceOops *soops = CTX_wm_space_outliner(C);
- Scene *scene = CTX_data_scene(C);
- ARegion *ar = CTX_wm_region(C);
-
- outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_selectability_cb);
-
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- ED_region_tag_redraw(ar);
-
- return OPERATOR_FINISHED;
-}
-
-void OUTLINER_OT_selectability_toggle(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Toggle Selectability";
- ot->idname = "OUTLINER_OT_selectability_toggle";
- ot->description = "Toggle the selectability";
-
- /* callbacks */
- ot->exec = outliner_toggle_selectability_exec;
- ot->poll = ED_operator_outliner_active_no_editobject;
-
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* Toggle Renderability ---------------------------------------- */
-
-void object_toggle_renderability_cb(
- bContext *UNUSED(C), ReportList *reports, Scene *scene, TreeElement *te,
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- Base *base = (Base *)te->directdata;
-
- if (ID_IS_LINKED_DATABLOCK(tselem->id)) {
- BKE_report(reports, RPT_WARNING, "Cannot edit external libdata");
- return;
- }
-
- if (base == NULL) base = BKE_scene_base_find(scene, (Object *)tselem->id);
- if (base) {
- base->object->restrictflag ^= OB_RESTRICT_RENDER;
- }
-}
-
-void group_toggle_renderability_cb(
- bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
-{
- Group *group = (Group *)tselem->id;
- restrictbutton_gr_restrict_flag(scene, group, OB_RESTRICT_RENDER);
-}
-
-static int outliner_toggle_renderability_exec(bContext *C, wmOperator *op)
-{
- Main *bmain = CTX_data_main(C);
- SpaceOops *soops = CTX_wm_space_outliner(C);
- Scene *scene = CTX_data_scene(C);
-
- outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_renderability_cb);
-
- DAG_id_type_tag(bmain, ID_OB);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, scene);
-
- return OPERATOR_FINISHED;
-}
-
-void OUTLINER_OT_renderability_toggle(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Toggle Renderability";
- ot->idname = "OUTLINER_OT_renderability_toggle";
- ot->description = "Toggle the renderability of selected items";
-
- /* callbacks */
- ot->exec = outliner_toggle_renderability_exec;
- ot->poll = ED_operator_outliner_active;
-
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* =============================================== */
/* Outliner setting toggles */
/* Toggle Expanded (Outliner) ---------------------------------------- */
@@ -2345,8 +2171,6 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
te = outliner_dropzone_find(soops, fmval, false);
if (te) {
- Base *base;
-
RNA_string_set(op->ptr, "scene", te->name);
scene = (Scene *)BKE_libblock_find_name(ID_SCE, te->name);
@@ -2357,16 +2181,26 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
}
- base = ED_object_scene_link(scene, ob);
-
- if (base == NULL) {
+ if (BKE_scene_has_object(scene, ob)) {
return OPERATOR_CANCELLED;
}
- if (scene == CTX_data_scene(C)) {
- /* when linking to an inactive scene don't touch the layer */
- ob->lay = base->lay;
- ED_base_object_select(base, BA_SELECT);
+ SceneCollection *sc;
+ if (scene != CTX_data_scene(C)) {
+ /* when linking to an inactive scene link to the master collection */
+ sc = BKE_collection_master(scene);
+ }
+ else {
+ sc = CTX_data_scene_collection(C);
+ }
+
+ BKE_collection_object_add(scene, sc, ob);
+
+ for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+ ObjectBase *base = BKE_scene_layer_base_find(sl, ob);
+ if (base) {
+ ED_object_base_select(base, BA_SELECT);
+ }
}
DAG_relations_tag_update(bmain);
@@ -2461,7 +2295,6 @@ static int group_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Main *bmain = CTX_data_main(C);
Group *group = NULL;
Object *ob = NULL;
- Scene *scene = CTX_data_scene(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
ARegion *ar = CTX_wm_region(C);
TreeElement *te = NULL;
@@ -2491,7 +2324,7 @@ static int group_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
}
- BKE_group_object_add(group, ob, scene, NULL);
+ BKE_group_object_add(group, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index f23c294c488..67af793a412 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -40,6 +40,7 @@ struct wmOperatorType;
struct TreeStoreElem;
struct bContext;
struct Scene;
+struct SceneLayer;
struct ID;
struct Object;
struct bPoseChannel;
@@ -141,7 +142,7 @@ TreeElement *outliner_find_posechannel(ListBase *lb, const struct bPoseChannel *
TreeElement *outliner_find_editbone(ListBase *lb, const struct EditBone *ebone);
struct ID *outliner_search_back(SpaceOops *soops, TreeElement *te, short idcode);
-void outliner_build_tree(struct Main *mainvar, struct Scene *scene, struct SpaceOops *soops);
+void outliner_build_tree(struct Main *mainvar, struct Scene *scene, struct SceneLayer *sl, struct SpaceOops *soops);
/* outliner_draw.c ---------------------------------------------- */
@@ -239,10 +240,6 @@ void OUTLINER_OT_expanded_toggle(struct wmOperatorType *ot);
void OUTLINER_OT_scroll_page(struct wmOperatorType *ot);
-void OUTLINER_OT_renderability_toggle(struct wmOperatorType *ot);
-void OUTLINER_OT_selectability_toggle(struct wmOperatorType *ot);
-void OUTLINER_OT_visibility_toggle(struct wmOperatorType *ot);
-
void OUTLINER_OT_keyingset_add_selected(struct wmOperatorType *ot);
void OUTLINER_OT_keyingset_remove_selected(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index f0c2d848f7a..5ddfdddc80d 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -71,10 +71,6 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_selected_toggle);
WM_operatortype_append(OUTLINER_OT_expanded_toggle);
- WM_operatortype_append(OUTLINER_OT_renderability_toggle);
- WM_operatortype_append(OUTLINER_OT_selectability_toggle);
- WM_operatortype_append(OUTLINER_OT_visibility_toggle);
-
WM_operatortype_append(OUTLINER_OT_keyingset_add_selected);
WM_operatortype_append(OUTLINER_OT_keyingset_remove_selected);
@@ -143,11 +139,6 @@ void outliner_keymap(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "OUTLINER_OT_selected_toggle", AKEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "OUTLINER_OT_expanded_toggle", AKEY, KM_PRESS, KM_SHIFT, 0);
- WM_keymap_verify_item(keymap, "OUTLINER_OT_renderability_toggle", RKEY, KM_PRESS, 0, 0);
- WM_keymap_verify_item(keymap, "OUTLINER_OT_selectability_toggle", SKEY, KM_PRESS, 0, 0);
- WM_keymap_verify_item(keymap, "OUTLINER_OT_visibility_toggle", VKEY, KM_PRESS, 0, 0);
-
-
/* keying sets - only for databrowse */
WM_keymap_verify_item(keymap, "OUTLINER_OT_keyingset_add_selected", KKEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "OUTLINER_OT_keyingset_remove_selected", KKEY, KM_PRESS, KM_ALT, 0);
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 4560b7cd6e7..09dab1508b4 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -56,6 +56,7 @@
#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_group.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_library_remap.h"
@@ -360,15 +361,15 @@ void OUTLINER_OT_scene_operation(wmOperatorType *ot)
/* ******************************************** */
static void object_select_cb(
- bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *te,
+ bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te),
TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
{
- Base *base = (Base *)te->directdata;
-
- if (base == NULL) base = BKE_scene_base_find(scene, (Object *)tselem->id);
- if (base && ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0)) {
- base->flag |= SELECT;
- base->object->flag |= SELECT;
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Object *ob = (Object *)tselem->id;
+ ObjectBase *base = BKE_scene_layer_base_find(sl, ob);
+
+ if (base && ((base->flag & BASE_VISIBLED) != 0)) {
+ base->flag |= BASE_SELECTED;
}
}
@@ -385,46 +386,43 @@ static void object_select_hierarchy_cb(
static void object_deselect_cb(
- bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *te,
+ bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te),
TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
{
- Base *base = (Base *)te->directdata;
-
- if (base == NULL) base = BKE_scene_base_find(scene, (Object *)tselem->id);
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Object *ob = (Object *)tselem->id;
+ ObjectBase *base = BKE_scene_layer_base_find(sl, ob);
+
if (base) {
- base->flag &= ~SELECT;
- base->object->flag &= ~SELECT;
+ base->flag &= ~BASE_SELECTED;
}
}
static void object_delete_cb(
- bContext *C, ReportList *reports, Scene *scene, TreeElement *te,
+ bContext *C, ReportList *reports, Scene *scene, TreeElement *UNUSED(te),
TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
{
- Base *base = (Base *)te->directdata;
-
- if (base == NULL)
- base = BKE_scene_base_find(scene, (Object *)tselem->id);
- if (base) {
+ Object *ob = (Object *)tselem->id;
+ if (ob) {
Main *bmain = CTX_data_main(C);
- if (base->object->id.tag & LIB_TAG_INDIRECT) {
- BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", base->object->id.name + 2);
+ if (ob->id.tag & LIB_TAG_INDIRECT) {
+ BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", ob->id.name + 2);
return;
}
- else if (BKE_library_ID_is_indirectly_used(bmain, base->object) &&
- ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0)
+ else if (BKE_library_ID_is_indirectly_used(bmain, ob) &&
+ ID_REAL_USERS(ob) <= 1 && ID_EXTRA_USERS(ob) == 0)
{
BKE_reportf(reports, RPT_WARNING,
"Cannot delete object '%s' from scene '%s', indirectly used objects need at least one user",
- base->object->id.name + 2, scene->id.name + 2);
+ ob->id.name + 2, scene->id.name + 2);
return;
}
// check also library later
- if (scene->obedit == base->object)
+ if (scene->obedit == ob)
ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO);
- ED_base_object_free_and_unlink(CTX_data_main(C), scene, base);
+ ED_base_object_free_and_unlink(CTX_data_main(C), scene, ob);
/* leave for ED_outliner_id_unref to handle */
#if 0
te->directdata = NULL;
@@ -852,7 +850,7 @@ static Base *outline_delete_hierarchy(bContext *C, ReportList *reports, Scene *s
base->object->id.name + 2, scene->id.name + 2);
return base_next;
}
- ED_base_object_free_and_unlink(CTX_data_main(C), scene, base);
+ ED_base_object_free_and_unlink(CTX_data_main(C), scene, base->object);
return base_next;
}
@@ -860,6 +858,7 @@ static void object_delete_hierarchy_cb(
bContext *C, ReportList *reports, Scene *scene,
TreeElement *te, TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
{
+#if 0
Base *base = (Base *)te->directdata;
Object *obedit = scene->obedit;
@@ -882,6 +881,15 @@ static void object_delete_hierarchy_cb(
}
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
+#else
+ (void) C;
+ (void) scene;
+ (void) te;
+ (void) tselem;
+ (void) outline_delete_hierarchy;
+ BKE_reportf(reports, RPT_ERROR, "Delete from outliner not supported at the moment");
+ TODO_LAYER_BASE
+#endif
}
/* **************************************** */
@@ -985,21 +993,6 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, id_local_cb);
str = "Localized Objects";
}
- else if (event == OL_OP_TOGVIS) {
- outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_visibility_cb);
- str = "Toggle Visibility";
- WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene);
- }
- else if (event == OL_OP_TOGSEL) {
- outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_selectability_cb);
- str = "Toggle Selectability";
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- }
- else if (event == OL_OP_TOGREN) {
- outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_renderability_cb);
- str = "Toggle Renderability";
- WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, scene);
- }
else if (event == OL_OP_RENAME) {
outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, item_rename_cb);
str = "Rename Object";
@@ -1095,15 +1088,6 @@ static int outliner_group_operation_exec(bContext *C, wmOperator *op)
case OL_GROUPOP_REMAP:
outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL);
break;
- case OL_GROUPOP_TOGVIS:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_toggle_visibility_cb, NULL);
- break;
- case OL_GROUPOP_TOGSEL:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_toggle_selectability_cb, NULL);
- break;
- case OL_GROUPOP_TOGREN:
- outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_toggle_renderability_cb, NULL);
- break;
case OL_GROUPOP_RENAME:
outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, item_rename_cb, NULL);
break;
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index ec46c5df9a0..a4f59f60f31 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -63,6 +63,7 @@
#include "BKE_fcurve.h"
#include "BKE_main.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_modifier.h"
#include "BKE_sequencer.h"
@@ -1619,9 +1620,8 @@ static int outliner_filter_tree(SpaceOops *soops, ListBase *lb)
/* Main entry point for building the tree data-structure that the outliner represents */
// TODO: split each mode into its own function?
-void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
+void outliner_build_tree(Main *mainvar, Scene *scene, SceneLayer *sl, SpaceOops *soops)
{
- Base *base;
TreeElement *te = NULL, *ten;
TreeStoreElem *tselem;
int show_opened = !soops->treestore || !BLI_mempool_count(soops->treestore); /* on first view, we open scenes */
@@ -1702,31 +1702,43 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
tselem = TREESTORE(te);
if (sce == scene && show_opened)
tselem->flag &= ~TSE_CLOSED;
-
- for (base = sce->base.first; base; base = base->next) {
- ten = outliner_add_element(soops, &te->subtree, base->object, te, 0, 0);
- ten->directdata = base;
+
+ Object *ob;
+ FOREACH_SCENE_OBJECT(scene, ob)
+ {
+ ten = outliner_add_element(soops, &te->subtree, ob, te, 0, 0);
}
+ FOREACH_SCENE_OBJECT_END
+
outliner_make_hierarchy(&te->subtree);
+
/* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */
- for (base = sce->base.first; base; base = base->next) base->object->id.newid = NULL;
+ FOREACH_SCENE_OBJECT(scene, ob)
+ {
+ ob->id.newid = NULL;
+ }
+ FOREACH_SCENE_OBJECT_END
}
}
else if (soops->outlinevis == SO_CUR_SCENE) {
outliner_add_scene_contents(soops, &soops->tree, scene, NULL);
-
- for (base = scene->base.first; base; base = base->next) {
- ten = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
- ten->directdata = base;
+
+ Object *ob;
+ FOREACH_SCENE_OBJECT(scene, ob)
+ {
+ ten = outliner_add_element(soops, &soops->tree, ob, NULL, 0, 0);
}
+ FOREACH_SCENE_OBJECT_END
outliner_make_hierarchy(&soops->tree);
}
else if (soops->outlinevis == SO_VISIBLE) {
- for (base = scene->base.first; base; base = base->next) {
- if (base->lay & scene->lay)
- outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
+ Object *ob;
+ FOREACH_VISIBLE_OBJECT(sl, ob)
+ {
+ outliner_add_element(soops, &soops->tree, ob, NULL, 0, 0);
}
+ FOREACH_VISIBLE_OBJECT_END
outliner_make_hierarchy(&soops->tree);
}
else if (soops->outlinevis == SO_GROUPS) {
@@ -1739,7 +1751,6 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
for (go = group->gobject.first; go; go = go->next) {
ten = outliner_add_element(soops, &te->subtree, go->ob, te, 0, 0);
- ten->directdata = NULL; /* eh, why? */
}
outliner_make_hierarchy(&te->subtree);
/* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */
@@ -1748,26 +1759,26 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
}
}
else if (soops->outlinevis == SO_SAME_TYPE) {
- Object *ob = OBACT;
- if (ob) {
- for (base = scene->base.first; base; base = base->next) {
- if (base->object->type == ob->type) {
- ten = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
- ten->directdata = base;
+ Object *ob_active = OBACT_NEW;
+ if (ob_active) {
+ Object *ob;
+ FOREACH_SCENE_OBJECT(scene, ob)
+ {
+ if (ob->type == ob_active->type) {
+ ten = outliner_add_element(soops, &soops->tree, ob, NULL, 0, 0);
}
}
+ FOREACH_SCENE_OBJECT_END
outliner_make_hierarchy(&soops->tree);
}
}
else if (soops->outlinevis == SO_SELECTED) {
- for (base = scene->base.first; base; base = base->next) {
- if (base->lay & scene->lay) {
- if (base->flag & SELECT) {
- ten = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
- ten->directdata = base;
- }
- }
+ Object *ob;
+ FOREACH_SELECTED_OBJECT(sl, ob)
+ {
+ ten = outliner_add_element(soops, &soops->tree, ob, NULL, 0, 0);
}
+ FOREACH_SELECTED_OBJECT_END
outliner_make_hierarchy(&soops->tree);
}
else if (soops->outlinevis == SO_SEQUENCE) {
@@ -1822,8 +1833,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
outliner_add_orphaned_datablocks(mainvar, soops);
}
else {
- ten = outliner_add_element(soops, &soops->tree, OBACT, NULL, 0, 0);
- if (ten) ten->directdata = BASACT;
+ ten = outliner_add_element(soops, &soops->tree, OBACT_NEW, NULL, 0, 0);
}
if ((soops->flag & SO_SKIP_SORT_ALPHA) == 0) {
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index df3620843ad..f603fa1b0f1 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -248,6 +248,7 @@ static int text_open_exec(bContext *C, wmOperator *op)
pprop = op->customdata;
if (pprop->prop) {
+ id_us_ensure_real(&text->id);
RNA_id_pointer_create(&text->id, &idptr);
RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr);
RNA_property_update(C, &pprop->ptr, pprop->prop);
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt
index 8fca2ed564e..f6d5cf6e5d2 100644
--- a/source/blender/editors/space_view3d/CMakeLists.txt
+++ b/source/blender/editors/space_view3d/CMakeLists.txt
@@ -95,8 +95,4 @@ if(WITH_MOD_SMOKE)
add_definitions(-DWITH_SMOKE)
endif()
-if(WITH_LEGACY_DEPSGRAPH)
- add_definitions(-DWITH_LEGACY_DEPSGRAPH)
-endif()
-
blender_add_lib(bf_editor_space_view3d "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/space_view3d/drawanimviz.c b/source/blender/editors/space_view3d/drawanimviz.c
index cf738de0202..f0e65f84205 100644
--- a/source/blender/editors/space_view3d/drawanimviz.c
+++ b/source/blender/editors/space_view3d/drawanimviz.c
@@ -75,6 +75,80 @@ void draw_motion_paths_init(View3D *v3d, ARegion *ar)
glLoadMatrixf(rv3d->viewmat);
}
+/* set color
+* - more intense for active/selected bones, less intense for unselected bones
+* - black for before current frame, green for current frame, blue for after current frame
+* - intensity decreases as distance from current frame increases
+*
+* If the user select custom color, the color is replaced for the color selected in UI panel
+* - 75% Darker color is used for previous frames
+* - 50% Darker color for current frame
+* - User selected color for next frames
+*/
+static void set_motion_path_color(Scene *scene, bMotionPath *mpath, int i, short sel, int sfra, int efra,
+ float prev_color[3], float frame_color[3], float next_color[3])
+{
+ int frame = sfra + i;
+ int blend_base = (abs(frame - CFRA) == 1) ? TH_CFRAME : TH_BACK; /* "bleed" cframe color to ease color blending */
+
+#define SET_INTENSITY(A, B, C, min, max) (((1.0f - ((C - B) / (C - A))) * (max - min)) + min)
+ float intensity; /* how faint */
+
+ if (frame < CFRA) {
+ if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) {
+ /* Custom color: previous frames color is darker than current frame */
+ glColor3fv(prev_color);
+ }
+ else {
+ /* black - before cfra */
+ if (sel) {
+ /* intensity = 0.5f; */
+ intensity = SET_INTENSITY(sfra, i, CFRA, 0.25f, 0.75f);
+ }
+ else {
+ /* intensity = 0.8f; */
+ intensity = SET_INTENSITY(sfra, i, CFRA, 0.68f, 0.92f);
+ }
+ UI_ThemeColorBlend(TH_WIRE, blend_base, intensity);
+ }
+ }
+ else if (frame > CFRA) {
+ if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) {
+ /* Custom color: next frames color is equal to user selected color */
+ glColor3fv(next_color);
+ }
+ else {
+ /* blue - after cfra */
+ if (sel) {
+ /* intensity = 0.5f; */
+ intensity = SET_INTENSITY(CFRA, i, efra, 0.25f, 0.75f);
+ }
+ else {
+ /* intensity = 0.8f; */
+ intensity = SET_INTENSITY(CFRA, i, efra, 0.68f, 0.92f);
+ }
+ UI_ThemeColorBlend(TH_BONE_POSE, blend_base, intensity);
+ }
+ }
+ else {
+ if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) {
+ /* Custom color: current frame color is slightly darker than user selected color */
+ glColor3fv(frame_color);
+ }
+ else {
+ /* green - on cfra */
+ if (sel) {
+ intensity = 0.5f;
+ }
+ else {
+ intensity = 0.99f;
+ }
+ UI_ThemeColorBlendShade(TH_CFRAME, TH_BACK, intensity, 10);
+ }
+ }
+#undef SET_INTENSITY
+}
+
/* Draw the given motion path for an Object or a Bone
* - assumes that the viewport has already been initialized properly
* i.e. draw_motion_paths_init() has been called
@@ -86,6 +160,28 @@ void draw_motion_path_instance(Scene *scene,
bMotionPathVert *mpv, *mpv_start;
int i, stepsize = avs->path_step;
int sfra, efra, sind, len;
+ float prev_color[3];
+ float frame_color[3];
+ float next_color[3];
+
+ /* Custom color - Previous frames: color is darker than current frame */
+ prev_color[0] = mpath->color[0] * 0.25f;
+ prev_color[1] = mpath->color[1] * 0.25f;
+ prev_color[2] = mpath->color[2] * 0.25f;
+
+ /* Custom color - Current frame: color is slightly darker than user selected color */
+ frame_color[0] = mpath->color[0] * 0.50f;
+ frame_color[1] = mpath->color[1] * 0.50f;
+ frame_color[2] = mpath->color[2] * 0.50f;
+
+ /* Custom color - Next frames: color is equal to user selection */
+ next_color[0] = mpath->color[0];
+ next_color[1] = mpath->color[1];
+ next_color[2] = mpath->color[2];
+
+ /* Save old line width */
+ GLfloat old_width;
+ glGetFloatv(GL_LINE_WIDTH, &old_width);
/* get frame ranges */
if (avs->path_type == MOTIONPATH_TYPE_ACFRA) {
@@ -130,64 +226,27 @@ void draw_motion_path_instance(Scene *scene,
mpv_start = (mpath->points + sind);
/* draw curve-line of path */
-
- glBegin(GL_LINE_STRIP);
- for (i = 0, mpv = mpv_start; i < len; i++, mpv++) {
- short sel = (pchan) ? (pchan->bone->flag & BONE_SELECTED) : (ob->flag & SELECT);
- float intensity; /* how faint */
-
- int frame = sfra + i;
- int blend_base = (abs(frame - CFRA) == 1) ? TH_CFRAME : TH_BACK; /* "bleed" cframe color to ease color blending */
-
- /* set color
- * - more intense for active/selected bones, less intense for unselected bones
- * - black for before current frame, green for current frame, blue for after current frame
- * - intensity decreases as distance from current frame increases
- */
-#define SET_INTENSITY(A, B, C, min, max) (((1.0f - ((C - B) / (C - A))) * (max - min)) + min)
- if (frame < CFRA) {
- /* black - before cfra */
- if (sel) {
- /* intensity = 0.5f; */
- intensity = SET_INTENSITY(sfra, i, CFRA, 0.25f, 0.75f);
- }
- else {
- /* intensity = 0.8f; */
- intensity = SET_INTENSITY(sfra, i, CFRA, 0.68f, 0.92f);
- }
- UI_ThemeColorBlend(TH_WIRE, blend_base, intensity);
- }
- else if (frame > CFRA) {
- /* blue - after cfra */
- if (sel) {
- /* intensity = 0.5f; */
- intensity = SET_INTENSITY(CFRA, i, efra, 0.25f, 0.75f);
- }
- else {
- /* intensity = 0.8f; */
- intensity = SET_INTENSITY(CFRA, i, efra, 0.68f, 0.92f);
- }
- UI_ThemeColorBlend(TH_BONE_POSE, blend_base, intensity);
- }
- else {
- /* green - on cfra */
- if (sel) {
- intensity = 0.5f;
- }
- else {
- intensity = 0.99f;
- }
- UI_ThemeColorBlendShade(TH_CFRAME, TH_BACK, intensity, 10);
+ /* Draw lines only if line drawing option is enabled */
+ if (mpath->flag & MOTIONPATH_FLAG_LINES) {
+ /* set line thickness */
+ glLineWidth(mpath->line_thickness);
+
+ glBegin(GL_LINE_STRIP);
+ for (i = 0, mpv = mpv_start; i < len; i++, mpv++) {
+ short sel = (pchan) ? (pchan->bone->flag & BONE_SELECTED) : (ob->flag & SELECT);
+ /* Set color */
+ set_motion_path_color(scene, mpath, i, sel, sfra, efra, prev_color, frame_color, next_color);
+ /* draw a vertex with this color */
+ glVertex3fv(mpv->co);
}
-#undef SET_INTENSITY
- /* draw a vertex with this color */
- glVertex3fv(mpv->co);
+ glEnd();
+ /* back to old line thickness */
+ glLineWidth(old_width);
}
-
- glEnd();
-
- glPointSize(1.0);
+
+ /* Point must be bigger than line thickness */
+ glPointSize(mpath->line_thickness + 1.0);
/* draw little black point at each frame
* NOTE: this is not really visible/noticeable
@@ -197,8 +256,13 @@ void draw_motion_path_instance(Scene *scene,
glVertex3fv(mpv->co);
glEnd();
- /* Draw little white dots at each framestep value */
- UI_ThemeColor(TH_TEXT_HI);
+ /* Draw little white dots at each framestep value or replace with custom color */
+ if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) {
+ glColor4fv(mpath->color);
+ }
+ else {
+ UI_ThemeColor(TH_TEXT_HI);
+ }
glBegin(GL_POINTS);
for (i = 0, mpv = mpv_start; i < len; i += stepsize, mpv += stepsize)
glVertex3fv(mpv->co);
@@ -208,11 +272,11 @@ void draw_motion_path_instance(Scene *scene,
* NOTE: this is only done when keyframes are shown, since this adds similar types of clutter
*/
if ((avs->path_viewflag & MOTIONPATH_VIEW_KFRAS) &&
- (sfra < CFRA) && (CFRA <= efra))
+ (sfra < CFRA) && (CFRA <= efra))
{
UI_ThemeColor(TH_CFRAME);
- glPointSize(6.0f);
+ glPointSize(mpath->line_thickness + 5.0);
glBegin(GL_POINTS);
mpv = mpv_start + (CFRA - sfra);
glVertex3fv(mpv->co);
@@ -289,7 +353,13 @@ void draw_motion_path_instance(Scene *scene,
UI_GetThemeColor3ubv(TH_VERTEX_SELECT, col);
col[3] = 255;
- glPointSize(4.0f);
+ /* if custom, point must be bigger than line */
+ if (mpath->flag & MOTIONPATH_FLAG_CUSTOM) {
+ glPointSize(mpath->line_thickness + 3.0);
+ }
+ else {
+ glPointSize(4.0f);
+ }
glColor3ubv(col);
glBegin(GL_POINTS);
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index 7ac176f82b1..af041e392c5 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -2459,6 +2459,10 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base
if (end <= start)
return;
+ /* prevent infinite loops if this is set to 0 - T49527 */
+ if (arm->ghostsize < 1)
+ arm->ghostsize = 1;
+
stepsize = (float)(arm->ghostsize);
range = (float)(end - start);
@@ -2604,7 +2608,11 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
calc_action_range(adt->action, &start, &end, 0);
if (start == end)
return;
-
+
+ /* prevent infinite loops if this is set to 0 - T49527 */
+ if (arm->ghostsize < 1)
+ arm->ghostsize = 1;
+
stepsize = (float)(arm->ghostsize);
range = (float)(arm->ghostep) * stepsize + 0.5f; /* plus half to make the for loop end correct */
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 20690411b90..5aca365886d 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -65,6 +65,7 @@
#include "BKE_lattice.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
+#include "BKE_mesh_render.h"
#include "BKE_material.h"
#include "BKE_mball.h"
#include "BKE_modifier.h"
@@ -214,358 +215,6 @@ typedef struct drawBMSelect_userData {
bool select;
} drawBMSelect_userData;
-typedef struct {
- VertexBuffer *pos_in_order;
- ElementList *edges_in_order;
- ElementList *triangles_in_order;
-
- Batch *all_verts;
- Batch *all_edges;
- Batch *all_triangles;
-
- Batch *fancy_edges; /* owns its vertex buffer (not shared) */
- Batch *overlay_edges; /* owns its vertex buffer */
-} MeshBatchCache;
-
-static void MBC_discard(MeshBatchCache *cache)
-{
- if (cache->all_verts) Batch_discard(cache->all_verts);
- if (cache->all_edges) Batch_discard(cache->all_edges);
- if (cache->all_triangles) Batch_discard(cache->all_triangles);
-
- if (cache->pos_in_order) VertexBuffer_discard(cache->pos_in_order);
- if (cache->edges_in_order) ElementList_discard(cache->edges_in_order);
- if (cache->triangles_in_order) ElementList_discard(cache->triangles_in_order);
-
- if (cache->fancy_edges) {
- Batch_discard_all(cache->fancy_edges);
- }
-
- if (cache->overlay_edges) {
- Batch_discard_all(cache->overlay_edges);
- }
-
- MEM_freeN(cache);
-}
-
-static MeshBatchCache *MBC_get(DerivedMesh *dm)
-{
- if (dm->batchCache == NULL) {
- /* create cache */
- dm->batchCache = MEM_callocN(sizeof(MeshBatchCache), "MeshBatchCache");
- /* init everything to 0 is ok for now */
-
-
- /* tell DerivedMesh how to clean up these caches (just once) */
- /* TODO: find a better place for this w/out exposing internals to DM */
- /* TODO (long term): replace DM with something less messy */
- static bool first = true;
- if (first) {
- DM_set_batch_cleanup_callback((DMCleanupBatchCache)MBC_discard);
- first = false;
- }
- }
-
- return dm->batchCache;
-}
-
-static VertexBuffer *MBC_get_pos_in_order(DerivedMesh *dm)
-{
- MeshBatchCache *cache = MBC_get(dm);
-
- if (cache->pos_in_order == NULL) {
- static VertexFormat format = { 0 };
- static unsigned pos_id;
- if (format.attrib_ct == 0) {
- /* initialize vertex format */
- pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
- }
-
- const int vertex_ct = dm->getNumVerts(dm);
- const MVert *verts = dm->getVertArray(dm);
- const unsigned stride = (verts + 1) - verts; /* or sizeof(MVert) */
-
- cache->pos_in_order = VertexBuffer_create_with_format(&format);
- VertexBuffer_allocate_data(cache->pos_in_order, vertex_ct);
-#if 0
- fillAttribStride(cache->pos_in_order, pos_id, stride, &verts[0].co);
-#else
- for (int i = 0; i < vertex_ct; ++i) {
- setAttrib(cache->pos_in_order, pos_id, i, &verts[i].co);
- }
-#endif
- }
-
- return cache->pos_in_order;
-}
-
-static Batch *MBC_get_all_verts(DerivedMesh *dm)
-{
- MeshBatchCache *cache = MBC_get(dm);
-
- if (cache->all_verts == NULL) {
- /* create batch from DM */
- cache->all_verts = Batch_create(GL_POINTS, MBC_get_pos_in_order(dm), NULL);
- Batch_set_builtin_program(cache->all_verts, GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR);
- }
-
- return cache->all_verts;
-}
-
-/* Short term function TODO */
-void MBC_cache_get_all_verts(struct DerivedMesh *dm, struct Batch **batch)
-{
- *batch = MBC_get_all_verts(dm);
-}
-
-static ElementList *MBC_get_edges_in_order(DerivedMesh *dm)
-{
- MeshBatchCache *cache = MBC_get(dm);
-
- if (cache->edges_in_order == NULL) {
- const int vertex_ct = dm->getNumVerts(dm);
- const int edge_ct = dm->getNumEdges(dm);
- const MEdge *edges = dm->getEdgeArray(dm);
- ElementListBuilder elb;
- ElementListBuilder_init(&elb, GL_LINES, edge_ct, vertex_ct);
- for (int i = 0; i < edge_ct; ++i) {
- const MEdge *edge = edges + i;
- add_line_vertices(&elb, edge->v1, edge->v2);
- }
- cache->edges_in_order = ElementList_build(&elb);
- }
-
- return cache->edges_in_order;
-}
-
-static ElementList *MBC_get_triangles_in_order(DerivedMesh *dm)
-{
- MeshBatchCache *cache = MBC_get(dm);
-
- if (cache->triangles_in_order == NULL) {
- const int vertex_ct = dm->getNumVerts(dm);
- const int tessface_ct = dm->getNumTessFaces(dm);
- const MFace *tessfaces = dm->getTessFaceArray(dm);
- ElementListBuilder elb;
- ElementListBuilder_init(&elb, GL_TRIANGLES, tessface_ct, vertex_ct);
- for (int i = 0; i < tessface_ct; ++i) {
- const MFace *tess = tessfaces + i;
- add_triangle_vertices(&elb, tess->v1, tess->v2, tess->v3);
- /* tessface can be triangle or quad */
- if (tess->v4) {
- add_triangle_vertices(&elb, tess->v3, tess->v2, tess->v4);
- }
- }
- cache->triangles_in_order = ElementList_build(&elb);
- }
-
- return cache->triangles_in_order;
-}
-
-static Batch *MBC_get_all_edges(DerivedMesh *dm)
-{
- MeshBatchCache *cache = MBC_get(dm);
-
- if (cache->all_edges == NULL) {
- /* create batch from DM */
- cache->all_edges = Batch_create(GL_LINES, MBC_get_pos_in_order(dm), MBC_get_edges_in_order(dm));
- }
-
- return cache->all_edges;
-}
-
-static Batch *MBC_get_all_triangles(DerivedMesh *dm)
-{
- MeshBatchCache *cache = MBC_get(dm);
-
- if (cache->all_triangles == NULL) {
- /* create batch from DM */
- cache->all_triangles = Batch_create(GL_TRIANGLES, MBC_get_pos_in_order(dm), MBC_get_triangles_in_order(dm));
- }
-
- return cache->all_triangles;
-}
-
-/* Short term function TODO */
-void MBC_cache_get_all_triangles(struct DerivedMesh *dm, struct Batch **batch)
-{
- *batch = MBC_get_all_triangles(dm);
-}
-
-static Batch *MBC_get_fancy_edges(DerivedMesh *dm)
-{
- MeshBatchCache *cache = MBC_get(dm);
-
- if (cache->fancy_edges == NULL) {
- /* create batch from DM */
- static VertexFormat format = { 0 };
- static unsigned pos_id, n1_id, n2_id;
- if (format.attrib_ct == 0) {
- /* initialize vertex format */
- pos_id = add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
-
-#if USE_10_10_10 /* takes 1/3 the space */
- n1_id = add_attrib(&format, "N1", COMP_I10, 3, NORMALIZE_INT_TO_FLOAT);
- n2_id = add_attrib(&format, "N2", COMP_I10, 3, NORMALIZE_INT_TO_FLOAT);
-#else
- n1_id = add_attrib(&format, "N1", COMP_F32, 3, KEEP_FLOAT);
- n2_id = add_attrib(&format, "N2", COMP_F32, 3, KEEP_FLOAT);
-#endif
- }
- VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
-
- const MVert *verts = dm->getVertArray(dm);
- const MEdge *edges = dm->getEdgeArray(dm);
- const MPoly *polys = dm->getPolyArray(dm);
- const MLoop *loops = dm->getLoopArray(dm);
- const int edge_ct = dm->getNumEdges(dm);
- const int poly_ct = dm->getNumPolys(dm);
-
- /* need normal of each face, and which faces are adjacent to each edge */
- typedef struct {
- int count;
- int face_index[2];
- } AdjacentFaces;
-
- float (*face_normal)[3] = MEM_mallocN(poly_ct * 3 * sizeof(float), "face_normal");
- AdjacentFaces *adj_faces = MEM_callocN(edge_ct * sizeof(AdjacentFaces), "adj_faces");
-
- for (int i = 0; i < poly_ct; ++i) {
- const MPoly *poly = polys + i;
-
- BKE_mesh_calc_poly_normal(poly, loops + poly->loopstart, verts, face_normal[i]);
-
- for (int j = poly->loopstart; j < (poly->loopstart + poly->totloop); ++j) {
- AdjacentFaces *adj = adj_faces + loops[j].e;
- if (adj->count < 2)
- adj->face_index[adj->count] = i;
- adj->count++;
- }
- }
-
- const int vertex_ct = edge_ct * 2; /* these are GL_LINE verts, not mesh verts */
- VertexBuffer_allocate_data(vbo, vertex_ct);
- for (int i = 0; i < edge_ct; ++i) {
- const MEdge *edge = edges + i;
- const AdjacentFaces *adj = adj_faces + i;
-
-#if USE_10_10_10
- PackedNormal n1value = { .x = 0, .y = 0, .z = +511 };
- PackedNormal n2value = { .x = 0, .y = 0, .z = -511 };
-
- if (adj->count == 2) {
- n1value = convert_i10_v3(face_normal[adj->face_index[0]]);
- n2value = convert_i10_v3(face_normal[adj->face_index[1]]);
- }
-
- const PackedNormal *n1 = &n1value;
- const PackedNormal *n2 = &n2value;
-#else
- const float dummy1[3] = { 0.0f, 0.0f, +1.0f };
- const float dummy2[3] = { 0.0f, 0.0f, -1.0f };
-
- const float *n1 = (adj->count == 2) ? face_normal[adj->face_index[0]] : dummy1;
- const float *n2 = (adj->count == 2) ? face_normal[adj->face_index[1]] : dummy2;
-#endif
-
- setAttrib(vbo, pos_id, 2 * i, &verts[edge->v1].co);
- setAttrib(vbo, n1_id, 2 * i, n1);
- setAttrib(vbo, n2_id, 2 * i, n2);
-
- setAttrib(vbo, pos_id, 2 * i + 1, &verts[edge->v2].co);
- setAttrib(vbo, n1_id, 2 * i + 1, n1);
- setAttrib(vbo, n2_id, 2 * i + 1, n2);
- }
-
- MEM_freeN(adj_faces);
- MEM_freeN(face_normal);
-
- cache->fancy_edges = Batch_create(GL_LINES, vbo, NULL);
- }
-
- return cache->fancy_edges;
-}
-
-/* Short term function TODO */
-void MBC_cache_get_fancy_edges(struct DerivedMesh *dm, struct Batch **batch)
-{
- *batch = MBC_get_fancy_edges(dm);
-}
-
-static bool edge_is_real(const MEdge *edges, int edge_ct, int v1, int v2)
-{
- /* TODO: same thing, except not ridiculously slow */
-
- for (int e = 0; e < edge_ct; ++e) {
- const MEdge *edge = edges + e;
- if ((edge->v1 == v1 && edge->v2 == v2) || (edge->v1 == v2 && edge->v2 == v1)) {
- return true;
- }
- }
-
- return false;
-}
-
-static void add_overlay_tri(VertexBuffer *vbo, unsigned pos_id, unsigned edgeMod_id, const MVert *verts, const MEdge *edges, int edge_ct, int v1, int v2, int v3, int base_vert_idx)
-{
- const float edgeMods[2] = { 0.0f, 1.0f };
-
- const float *pos = verts[v1].co;
- setAttrib(vbo, pos_id, base_vert_idx + 0, pos);
- setAttrib(vbo, edgeMod_id, base_vert_idx + 0, edgeMods + (edge_is_real(edges, edge_ct, v2, v3) ? 1 : 0));
-
- pos = verts[v2].co;
- setAttrib(vbo, pos_id, base_vert_idx + 1, pos);
- setAttrib(vbo, edgeMod_id, base_vert_idx + 1, edgeMods + (edge_is_real(edges, edge_ct, v3, v1) ? 1 : 0));
-
- pos = verts[v3].co;
- setAttrib(vbo, pos_id, base_vert_idx + 2, pos);
- setAttrib(vbo, edgeMod_id, base_vert_idx + 2, edgeMods + (edge_is_real(edges, edge_ct, v1, v2) ? 1 : 0));
-}
-
-static Batch *MBC_get_overlay_edges(DerivedMesh *dm)
-{
- MeshBatchCache *cache = MBC_get(dm);
-
- if (cache->overlay_edges == NULL) {
- /* create batch from DM */
- static VertexFormat format = { 0 };
- static unsigned pos_id, edgeMod_id;
- if (format.attrib_ct == 0) {
- /* initialize vertex format */
- pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
- edgeMod_id = add_attrib(&format, "edgeWidthModulator", GL_FLOAT, 1, KEEP_FLOAT);
- }
- VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
-
- const int vertex_ct = dm->getNumVerts(dm);
- const int edge_ct = dm->getNumEdges(dm);
- const int tessface_ct = dm->getNumTessFaces(dm);
- const MVert *verts = dm->getVertArray(dm);
- const MEdge *edges = dm->getEdgeArray(dm);
- const MFace *tessfaces = dm->getTessFaceArray(dm);
-
- VertexBuffer_allocate_data(vbo, tessface_ct * 6); /* up to 2 triangles per tessface */
-
- int gpu_vert_idx = 0;
- for (int i = 0; i < tessface_ct; ++i) {
- const MFace *tess = tessfaces + i;
- add_overlay_tri(vbo, pos_id, edgeMod_id, verts, edges, edge_ct, tess->v1, tess->v2, tess->v3, gpu_vert_idx);
- gpu_vert_idx += 3;
- /* tessface can be triangle or quad */
- if (tess->v4) {
- add_overlay_tri(vbo, pos_id, edgeMod_id, verts, edges, edge_ct, tess->v3, tess->v2, tess->v4, gpu_vert_idx);
- gpu_vert_idx += 3;
- }
- }
-
- VertexBuffer_resize_data(vbo, gpu_vert_idx);
-
- cache->overlay_edges = Batch_create(GL_TRIANGLES, vbo, NULL);
- }
-
- return cache->overlay_edges;
-}
static void drawcube_size(float size, unsigned pos);
static void drawcircle_size(float size, unsigned pos);
@@ -4388,11 +4037,10 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
}
static void draw_em_fancy_new(Scene *UNUSED(scene), ARegion *ar, View3D *UNUSED(v3d),
- Object *UNUSED(ob), BMEditMesh *UNUSED(em), DerivedMesh *cageDM, DerivedMesh *UNUSED(finalDM), const char UNUSED(dt))
+ Object *UNUSED(ob), Mesh *me, BMEditMesh *UNUSED(em), DerivedMesh *UNUSED(cageDM), DerivedMesh *UNUSED(finalDM), const char UNUSED(dt))
{
/* for now... something simple! */
-
- Batch *surface = MBC_get_all_triangles(cageDM);
+ Batch *surface = BKE_mesh_batch_cache_get_all_triangles(me);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
@@ -4426,7 +4074,7 @@ static void draw_em_fancy_new(Scene *UNUSED(scene), ARegion *ar, View3D *UNUSED(
Batch_draw(surface);
if (GLEW_VERSION_3_2) {
- Batch *overlay = MBC_get_overlay_edges(cageDM);
+ Batch *overlay = BKE_mesh_batch_cache_get_overlay_edges(me);
Batch_set_builtin_program(overlay, GPU_SHADER_EDGES_OVERLAY);
Batch_Uniform2f(overlay, "viewportSize", ar->winx, ar->winy);
Batch_draw(overlay);
@@ -4444,7 +4092,7 @@ static void draw_em_fancy_new(Scene *UNUSED(scene), ARegion *ar, View3D *UNUSED(
#endif
}
else {
- Batch *edges = MBC_get_all_edges(cageDM);
+ Batch *edges = BKE_mesh_batch_cache_get_all_edges(me);
Batch_set_builtin_program(edges, GPU_SHADER_3D_UNIFORM_COLOR);
Batch_Uniform4f(edges, "color", 0.0f, 0.0f, 0.0f, 1.0f);
glEnable(GL_LINE_SMOOTH);
@@ -4454,7 +4102,7 @@ static void draw_em_fancy_new(Scene *UNUSED(scene), ARegion *ar, View3D *UNUSED(
}
#if 0 /* looks good even without points */
- Batch *verts = MBC_get_all_verts(cageDM);
+ Batch *verts = MBC_get_all_verts(me);
glEnable(GL_BLEND);
Batch_set_builtin_program(verts, GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH);
@@ -4492,7 +4140,7 @@ void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm) /* LEGAC
}
}
-static void draw_mesh_object_outline_new(View3D *v3d, RegionView3D *rv3d, Object *ob, DerivedMesh *dm, const bool is_active)
+static void draw_mesh_object_outline_new(View3D *v3d, RegionView3D *rv3d, Object *ob, Mesh *me, const bool is_active)
{
if ((v3d->transp == false) && /* not when we draw the transparent pass */
(ob->mode & OB_MODE_ALL_PAINT) == false) /* not when painting (its distracting) - campbell */
@@ -4504,7 +4152,7 @@ static void draw_mesh_object_outline_new(View3D *v3d, RegionView3D *rv3d, Object
UI_GetThemeColor4fv((is_active ? TH_ACTIVE : TH_SELECT), outline_color);
#if 1 /* new version that draws only silhouette edges */
- Batch *fancy_edges = MBC_get_fancy_edges(dm);
+ Batch *fancy_edges = BKE_mesh_batch_cache_get_fancy_edges(me);
if (rv3d->persp == RV3D_ORTHO) {
Batch_set_builtin_program(fancy_edges, GPU_SHADER_EDGES_FRONT_BACK_ORTHO);
@@ -5027,7 +4675,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi
#if 1 /* fancy wireframes */
- Batch *fancy_edges = MBC_get_fancy_edges(dm);
+ Batch *fancy_edges = BKE_mesh_batch_cache_get_fancy_edges(me);
if (rv3d->persp == RV3D_ORTHO) {
Batch_set_builtin_program(fancy_edges, GPU_SHADER_EDGES_FRONT_BACK_ORTHO);
@@ -5062,7 +4710,6 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi
Batch_Uniform4fv(fancy_edges, "silhouetteColor", outlineColor);
Batch_draw(fancy_edges);
-
#else /* simple wireframes */
@@ -5088,7 +4735,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi
!(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) &&
(draw_wire == OBDRAW_WIRE_OFF))
{
- draw_mesh_object_outline_new(v3d, rv3d, ob, dm, (ob == OBACT));
+ draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT));
}
if (draw_glsl_material(scene, ob, v3d, dt) && !(draw_flags & DRAW_MODIFIERS_PREVIEW)) {
@@ -5155,7 +4802,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi
(draw_wire == OBDRAW_WIRE_OFF) &&
(ob->sculpt == NULL))
{
- draw_mesh_object_outline_new(v3d, rv3d, ob, dm, (ob == OBACT));
+ draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT));
}
/* materials arent compatible with vertex colors */
@@ -5180,7 +4827,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi
(ob->sculpt == NULL))
{
/* TODO: move this into a separate pass */
- draw_mesh_object_outline_new(v3d, rv3d, ob, dm, (ob == OBACT));
+ draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT));
}
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
@@ -5329,7 +4976,7 @@ static bool draw_mesh_object_new(Scene *scene, ARegion *ar, View3D *v3d, RegionV
GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
}
- draw_em_fancy_new(scene, ar, v3d, ob, em, cageDM, finalDM, dt);
+ draw_em_fancy_new(scene, ar, v3d, ob, me, em, cageDM, finalDM, dt);
if (use_material) {
GPU_end_object_materials();
@@ -6121,7 +5768,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
timestep = psys_get_timestep(&sim);
- if ((base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP)) {
+ if ((ob->flag & OB_FROMGROUP) != 0) {
float mat[4][4];
mul_m4_m4m4(mat, ob->obmat, psys->imat);
glMultMatrixf(mat);
@@ -6752,7 +6399,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
pdd->ma_col = NULL;
}
- if ((base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP)) {
+ if ((ob->flag & OB_FROMGROUP) != 0) {
glLoadMatrixf(rv3d->viewmat);
}
}
@@ -8473,7 +8120,7 @@ void draw_object_wire_color(Scene *scene, Base *base, unsigned char r_ob_wire_co
}
/* Sets the 'theme_id' or fallback to wire */
else {
- if (ob->flag & OB_FROMGROUP) {
+ if ((ob->flag & OB_FROMGROUP) != 0) {
if (base->flag & (SELECT + BA_WAS_SEL)) {
/* uses darker active color for non-active + selected */
theme_id = TH_GROUP_ACTIVE;
@@ -8582,7 +8229,6 @@ void draw_rigidbody_shape(Object *ob)
}
}
-
/**
* main object drawing function, draws in selection
* \param dflag (draw flag) can be DRAW_PICKING and/or DRAW_CONSTCOLOR, DRAW_SCENESET
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 14842ab2879..6021f705035 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -939,21 +939,13 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
switch (wmn->data) {
case ND_SHADING:
case ND_NODES:
- {
-#ifdef WITH_LEGACY_DEPSGRAPH
- Object *ob = OBACT;
- if ((v3d->drawtype == OB_MATERIAL) ||
- (ob && (ob->mode == OB_MODE_TEXTURE_PAINT)) ||
- (v3d->drawtype == OB_TEXTURE &&
- (scene->gm.matmode == GAME_MAT_GLSL ||
- BKE_scene_use_new_shading_nodes(scene))) ||
- !DEG_depsgraph_use_legacy())
-#endif
- {
- ED_region_tag_redraw(ar);
- }
+ /* TODO(sergey) This is a bit too much updates, but needed to
+ * have proper material drivers update in the viewport.
+ *
+ * How to solve?
+ */
+ ED_region_tag_redraw(ar);
break;
- }
case ND_SHADING_DRAW:
case ND_SHADING_LINKS:
ED_region_tag_redraw(ar);
@@ -970,12 +962,10 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
case NC_LAMP:
switch (wmn->data) {
case ND_LIGHTING:
- if ((v3d->drawtype == OB_MATERIAL) ||
- (v3d->drawtype == OB_TEXTURE && (scene->gm.matmode == GAME_MAT_GLSL)) ||
- !DEG_depsgraph_use_legacy())
- {
- ED_region_tag_redraw(ar);
- }
+ /* TODO(sergey): This is a bit too much, but needed to
+ * handle updates from new depsgraph.
+ */
+ ED_region_tag_redraw(ar);
break;
case ND_LIGHTING_DRAW:
ED_region_tag_redraw(ar);
@@ -1286,8 +1276,6 @@ static void space_view3d_listener(bScreen *UNUSED(sc), ScrArea *sa, struct wmNot
}
const char *view3d_context_dir[] = {
- "selected_objects", "selected_bases", "selected_editable_objects",
- "selected_editable_bases", "visible_objects", "visible_bases", "selectable_objects", "selectable_bases",
"active_base", "active_object", NULL
};
@@ -1298,109 +1286,27 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
if (CTX_data_dir(member)) {
CTX_data_dir_set(result, view3d_context_dir);
}
- else if (CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) {
- View3D *v3d = CTX_wm_view3d(C);
- Scene *scene = CTX_data_scene(C);
- const unsigned int lay = v3d ? v3d->lay : scene->lay;
- Base *base;
- const bool selected_objects = CTX_data_equals(member, "selected_objects");
-
- for (base = scene->base.first; base; base = base->next) {
- if ((base->flag & SELECT) && (base->lay & lay)) {
- if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) {
- if (selected_objects)
- CTX_data_id_list_add(result, &base->object->id);
- else
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
- }
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- else if (CTX_data_equals(member, "selected_editable_objects") || CTX_data_equals(member, "selected_editable_bases")) {
- View3D *v3d = CTX_wm_view3d(C);
- Scene *scene = CTX_data_scene(C);
- const unsigned int lay = v3d ? v3d->lay : scene->lay;
- Base *base;
- const bool selected_editable_objects = CTX_data_equals(member, "selected_editable_objects");
-
- for (base = scene->base.first; base; base = base->next) {
- if ((base->flag & SELECT) && (base->lay & lay)) {
- if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) {
- if (0 == BKE_object_is_libdata(base->object)) {
- if (selected_editable_objects)
- CTX_data_id_list_add(result, &base->object->id);
- else
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
- }
- }
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- else if (CTX_data_equals(member, "visible_objects") || CTX_data_equals(member, "visible_bases")) {
- View3D *v3d = CTX_wm_view3d(C);
- Scene *scene = CTX_data_scene(C);
- const unsigned int lay = v3d ? v3d->lay : scene->lay;
- Base *base;
- const bool visible_objects = CTX_data_equals(member, "visible_objects");
-
- for (base = scene->base.first; base; base = base->next) {
- if (base->lay & lay) {
- if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0) {
- if (visible_objects)
- CTX_data_id_list_add(result, &base->object->id);
- else
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
- }
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- else if (CTX_data_equals(member, "selectable_objects") || CTX_data_equals(member, "selectable_bases")) {
- View3D *v3d = CTX_wm_view3d(C);
- Scene *scene = CTX_data_scene(C);
- const unsigned int lay = v3d ? v3d->lay : scene->lay;
- Base *base;
- const bool selectable_objects = CTX_data_equals(member, "selectable_objects");
-
- for (base = scene->base.first; base; base = base->next) {
- if (base->lay & lay) {
- if ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0 && (base->object->restrictflag & OB_RESTRICT_SELECT) == 0) {
- if (selectable_objects)
- CTX_data_id_list_add(result, &base->object->id);
- else
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
- }
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
else if (CTX_data_equals(member, "active_base")) {
- View3D *v3d = CTX_wm_view3d(C);
Scene *scene = CTX_data_scene(C);
- const unsigned int lay = v3d ? v3d->lay : scene->lay;
- if (scene->basact && (scene->basact->lay & lay)) {
- Object *ob = scene->basact->object;
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ if (sl->basact) {
+ Object *ob = sl->basact->object;
/* if hidden but in edit mode, we still display, can happen with animation */
- if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0 || (ob->mode & OB_MODE_EDIT))
- CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, scene->basact);
+ if ((sl->basact->flag & BASE_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT)) {
+ CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, sl->basact);
+ }
}
return 1;
}
else if (CTX_data_equals(member, "active_object")) {
- View3D *v3d = CTX_wm_view3d(C);
- Scene *scene = CTX_data_scene(C);
- const unsigned int lay = v3d ? v3d->lay : scene->lay;
- if (scene->basact && (scene->basact->lay & lay)) {
- Object *ob = scene->basact->object;
- if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0 || (ob->mode & OB_MODE_EDIT))
- CTX_data_id_pointer_set(result, &scene->basact->object->id);
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ if (sl->basact) {
+ Object *ob = sl->basact->object;
+ /* if hidden but in edit mode, we still display, can happen with animation */
+ if ((sl->basact->flag & BASE_VISIBLED) != 0 || (ob->mode & OB_MODE_EDIT) != 0) {
+ CTX_data_id_pointer_set(result, &ob->id);
+ }
}
return 1;
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 3239d07553f..cf82ab4f23e 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -64,11 +64,13 @@
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_depsgraph.h"
+#include "BKE_layer.h"
#include "BKE_mball.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_editmesh.h"
+#include "BKE_scene.h"
#include "BKE_tracking.h"
#include "BKE_utildefines.h"
@@ -424,7 +426,6 @@ static void do_lasso_select_objects(ViewContext *vc, const int mcords[][2], cons
if (BLI_lasso_is_point_inside(mcords, moves, base->sx, base->sy, IS_CLIPPED)) {
ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT);
- base->object->flag = base->flag;
}
}
if (vc->obact == base->object && (base->object->mode & OB_MODE_POSE)) {
@@ -1015,22 +1016,22 @@ static int object_select_menu_exec(bContext *C, wmOperator *op)
const char *name = object_mouse_select_menu_data[name_index].idname;
if (!toggle) {
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selectable_bases)
{
- if (base->flag & SELECT) {
- ED_base_object_select(base, BA_DESELECT);
+ if ((base->flag & BASE_SELECTED) != 0) {
+ ED_object_base_select(base, BA_DESELECT);
changed = true;
}
}
CTX_DATA_END;
}
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
+ CTX_DATA_BEGIN (C, ObjectBase *, base, selectable_bases)
{
/* this is a bit dodjy, there should only be ONE object with this name, but library objects can mess this up */
if (STREQ(name, base->object->id.name + 2)) {
- ED_base_object_activate(C, base);
- ED_base_object_select(base, BA_SELECT);
+ ED_object_base_activate(C, base);
+ ED_object_base_select(base, BA_SELECT);
changed = true;
}
}
@@ -1092,7 +1093,11 @@ static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int
short baseCount = 0;
bool ok;
LinkNode *linklist = NULL;
-
+
+ /* handle base->selcol */
+ TODO_LAYER_BASE;
+#if 0
+
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
ok = false;
@@ -1164,6 +1169,19 @@ static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int
BLI_linklist_free(linklist, NULL);
return NULL;
}
+#else
+
+ (void)C;
+ (void)vc,
+ (void)buffer;
+ (void)hits;
+ (void)mval;
+ (void)toggle;
+ (void)baseCount;
+ (void)ok;
+ (void)linklist;
+ return NULL;
+#endif
}
static bool selectbuffer_has_bones(const unsigned int *buffer, const unsigned int hits)
diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt
index b7de49d8158..1a41d9ac95a 100644
--- a/source/blender/editors/transform/CMakeLists.txt
+++ b/source/blender/editors/transform/CMakeLists.txt
@@ -58,10 +58,6 @@ if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
-if(WITH_LEGACY_DEPSGRAPH)
- add_definitions(-DWITH_LEGACY_DEPSGRAPH)
-endif()
-
add_definitions(${GL_DEFINITIONS})
blender_add_lib(bf_editor_transform "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 20c62e91d01..751d750d5ac 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -64,9 +64,11 @@
#include "BKE_mask.h"
#include "BKE_report.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+
#include "ED_image.h"
#include "ED_keyframing.h"
#include "ED_screen.h"
@@ -1598,8 +1600,16 @@ typedef enum {
LEFT,
RIGHT
} ArrowDirection;
+
+#define POS_INDEX 0
+/* NOTE: this --^ is a bit hackish, but simplifies VertexFormat usage among functions
+ * private to this file - merwin
+ */
+
static void drawArrow(ArrowDirection d, short offset, short length, short size)
{
+ immBegin(PRIM_LINES, 6);
+
switch (d) {
case LEFT:
offset = -offset;
@@ -1607,14 +1617,12 @@ static void drawArrow(ArrowDirection d, short offset, short length, short size)
size = -size;
/* fall-through */
case RIGHT:
- glBegin(GL_LINES);
- glVertex2s(offset, 0);
- glVertex2s(offset + length, 0);
- glVertex2s(offset + length, 0);
- glVertex2s(offset + length - size, -size);
- glVertex2s(offset + length, 0);
- glVertex2s(offset + length - size, size);
- glEnd();
+ immVertex2f(POS_INDEX, offset, 0);
+ immVertex2f(POS_INDEX, offset + length, 0);
+ immVertex2f(POS_INDEX, offset + length, 0);
+ immVertex2f(POS_INDEX, offset + length - size, -size);
+ immVertex2f(POS_INDEX, offset + length, 0);
+ immVertex2f(POS_INDEX, offset + length - size, size);
break;
case DOWN:
@@ -1623,45 +1631,45 @@ static void drawArrow(ArrowDirection d, short offset, short length, short size)
size = -size;
/* fall-through */
case UP:
- glBegin(GL_LINES);
- glVertex2s(0, offset);
- glVertex2s(0, offset + length);
- glVertex2s(0, offset + length);
- glVertex2s(-size, offset + length - size);
- glVertex2s(0, offset + length);
- glVertex2s(size, offset + length - size);
- glEnd();
+ immVertex2f(POS_INDEX, 0, offset);
+ immVertex2f(POS_INDEX, 0, offset + length);
+ immVertex2f(POS_INDEX, 0, offset + length);
+ immVertex2f(POS_INDEX, -size, offset + length - size);
+ immVertex2f(POS_INDEX, 0, offset + length);
+ immVertex2f(POS_INDEX, size, offset + length - size);
break;
}
+
+ immEnd();
}
static void drawArrowHead(ArrowDirection d, short size)
{
+ immBegin(PRIM_LINES, 4);
+
switch (d) {
case LEFT:
size = -size;
/* fall-through */
case RIGHT:
- glBegin(GL_LINES);
- glVertex2s(0, 0);
- glVertex2s(-size, -size);
- glVertex2s(0, 0);
- glVertex2s(-size, size);
- glEnd();
+ immVertex2f(POS_INDEX, 0, 0);
+ immVertex2f(POS_INDEX, -size, -size);
+ immVertex2f(POS_INDEX, 0, 0);
+ immVertex2f(POS_INDEX, -size, size);
break;
case DOWN:
size = -size;
/* fall-through */
case UP:
- glBegin(GL_LINES);
- glVertex2s(0, 0);
- glVertex2s(-size, -size);
- glVertex2s(0, 0);
- glVertex2s(size, -size);
- glEnd();
+ immVertex2f(POS_INDEX, 0, 0);
+ immVertex2f(POS_INDEX, -size, -size);
+ immVertex2f(POS_INDEX, 0, 0);
+ immVertex2f(POS_INDEX, size, -size);
break;
}
+
+ immEnd();
}
static void drawArc(float size, float angle_start, float angle_end, int segments)
@@ -1670,14 +1678,14 @@ static void drawArc(float size, float angle_start, float angle_end, int segments
float angle;
int a;
- glBegin(GL_LINE_STRIP);
+ immBegin(PRIM_LINE_STRIP, segments + 1);
for (angle = angle_start, a = 0; a < segments; angle += delta, a++) {
- glVertex2f(cosf(angle) * size, sinf(angle) * size);
+ immVertex2f(POS_INDEX, cosf(angle) * size, sinf(angle) * size);
}
- glVertex2f(cosf(angle_end) * size, sinf(angle_end) * size);
+ immVertex2f(POS_INDEX, cosf(angle_end) * size, sinf(angle_end) * size);
- glEnd();
+ immEnd();
}
static int helpline_poll(bContext *C)
@@ -1695,10 +1703,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
if (t->helpline != HLP_NONE && !(t->flag & T_USES_MANIPULATOR)) {
float vecrot[3], cent[2];
- int mval[2];
-
- mval[0] = x;
- mval[1] = y;
+ float mval[3] = { x, y, 0.0f };
copy_v3_v3(vecrot, t->center);
if (t->flag & T_EDIT) {
@@ -1712,42 +1717,45 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
projectFloatViewEx(t, vecrot, cent, V3D_PROJ_TEST_CLIP_ZERO);
- glPushMatrix();
+ gpuMatrixBegin3D_legacy(); /* TODO(merwin): finish the 2D matrix API & use here */
+
+ unsigned pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
+ BLI_assert(pos == POS_INDEX);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
switch (t->helpline) {
case HLP_SPRING:
- UI_ThemeColor(TH_VIEW_OVERLAY);
-
+ immUniformThemeColor(TH_VIEW_OVERLAY);
setlinestyle(3);
- glLineWidth(1);
- glBegin(GL_LINES);
- glVertex2iv(t->mval);
- glVertex2fv(cent);
- glEnd();
+ glLineWidth(1.0f);
+
+ immBegin(PRIM_LINES, 2);
+ immVertex2f(POS_INDEX, (float)t->mval[0], (float)t->mval[1]);
+ immVertex2fv(POS_INDEX, cent);
+ immEnd();
- glTranslate2iv(mval);
- glRotatef(-RAD2DEGF(atan2f(cent[0] - t->mval[0], cent[1] - t->mval[1])), 0, 0, 1);
+ gpuTranslate3fv(mval);
+ gpuRotateAxis(-RAD2DEGF(atan2f(cent[0] - t->mval[0], cent[1] - t->mval[1])), 'Z');
setlinestyle(0);
- glLineWidth(3.0);
+ glLineWidth(3.0f);
drawArrow(UP, 5, 10, 5);
drawArrow(DOWN, 5, 10, 5);
break;
case HLP_HARROW:
- UI_ThemeColor(TH_VIEW_OVERLAY);
+ immUniformThemeColor(TH_VIEW_OVERLAY);
+ gpuTranslate3fv(mval);
- glTranslate2iv(mval);
-
- glLineWidth(3.0);
+ glLineWidth(3.0f);
drawArrow(RIGHT, 5, 10, 5);
drawArrow(LEFT, 5, 10, 5);
break;
case HLP_VARROW:
- UI_ThemeColor(TH_VIEW_OVERLAY);
+ immUniformThemeColor(TH_VIEW_OVERLAY);
- glTranslate2iv(mval);
+ gpuTranslate3fv(mval);
- glLineWidth(3.0);
+ glLineWidth(3.0f);
drawArrow(UP, 5, 10, 5);
drawArrow(DOWN, 5, 10, 5);
break;
@@ -1758,33 +1766,35 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
float dist = hypotf(dx, dy);
float delta_angle = min_ff(15.0f / dist, (float)M_PI / 4.0f);
float spacing_angle = min_ff(5.0f / dist, (float)M_PI / 12.0f);
- UI_ThemeColor(TH_VIEW_OVERLAY);
+
+ immUniformThemeColor(TH_VIEW_OVERLAY);
setlinestyle(3);
- glLineWidth(1);
- glBegin(GL_LINES);
- glVertex2iv(t->mval);
- glVertex2fv(cent);
- glEnd();
+ glLineWidth(1.0f);
+
+ immBegin(PRIM_LINES, 2);
+ immVertex2f(POS_INDEX, (float)t->mval[0], (float)t->mval[1]);
+ immVertex2fv(POS_INDEX, cent);
+ immEnd();
- glTranslatef(cent[0] - t->mval[0] + mval[0], cent[1] - t->mval[1] + mval[1], 0);
+ gpuTranslate3f(cent[0] - t->mval[0] + mval[0], cent[1] - t->mval[1] + mval[1], 0);
setlinestyle(0);
- glLineWidth(3.0);
+ glLineWidth(3.0f);
drawArc(dist, angle - delta_angle, angle - spacing_angle, 10);
drawArc(dist, angle + spacing_angle, angle + delta_angle, 10);
- glPushMatrix();
+ gpuPushMatrix();
- glTranslatef(cosf(angle - delta_angle) * dist, sinf(angle - delta_angle) * dist, 0);
- glRotatef(RAD2DEGF(angle - delta_angle), 0, 0, 1);
+ gpuTranslate3f(cosf(angle - delta_angle) * dist, sinf(angle - delta_angle) * dist, 0);
+ gpuRotateAxis(RAD2DEGF(angle - delta_angle), 'Z');
drawArrowHead(DOWN, 5);
- glPopMatrix();
+ gpuPopMatrix();
- glTranslatef(cosf(angle + delta_angle) * dist, sinf(angle + delta_angle) * dist, 0);
- glRotatef(RAD2DEGF(angle + delta_angle), 0, 0, 1);
+ gpuTranslate3f(cosf(angle + delta_angle) * dist, sinf(angle + delta_angle) * dist, 0);
+ gpuRotateAxis(RAD2DEGF(angle + delta_angle), 'Z');
drawArrowHead(UP, 5);
break;
@@ -1794,18 +1804,18 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
unsigned char col[3], col2[3];
UI_GetThemeColor3ubv(TH_GRID, col);
- glTranslate2iv(mval);
+ gpuTranslate3fv(mval);
- glLineWidth(3.0);
+ glLineWidth(3.0f);
UI_make_axis_color(col, col2, 'X');
- glColor3ubv((GLubyte *)col2);
+ immUniformColor3ubv((GLubyte *)col2);
drawArrow(RIGHT, 5, 10, 5);
drawArrow(LEFT, 5, 10, 5);
UI_make_axis_color(col, col2, 'Y');
- glColor3ubv((GLubyte *)col2);
+ immUniformColor3ubv((GLubyte *)col2);
drawArrow(UP, 5, 10, 5);
drawArrow(DOWN, 5, 10, 5);
@@ -1813,7 +1823,8 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
}
}
- glPopMatrix();
+ immUnbindProgram();
+ gpuMatrixEnd();
}
}
@@ -1821,7 +1832,7 @@ static void drawTransformView(const struct bContext *C, ARegion *UNUSED(ar), voi
{
TransInfo *t = arg;
- glLineWidth(1.0);
+ glLineWidth(1.0f);
drawConstraint(t);
drawPropCircle(C, t);
@@ -2176,7 +2187,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
calculateCenter(t);
if (event) {
- initMouseInput(t, &t->mouse, t->center2d, event->mval);
+ initMouseInput(t, &t->mouse, t->center2d, event->mval, event->shift);
}
switch (mode) {
@@ -6831,10 +6842,13 @@ static void drawEdgeSlide(TransInfo *t)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT | GL_POINT_BIT);
- glPushMatrix();
+ gpuMatrixBegin3D_legacy();
- glMultMatrixf(t->obedit->obmat);
+ gpuMultMatrix3D(t->obedit->obmat);
+
+ unsigned pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
if (sld->use_even == true) {
float co_a[3], co_b[3], co_mark[3];
@@ -6848,39 +6862,35 @@ static void drawEdgeSlide(TransInfo *t)
add_v3_v3v3(co_b, curr_sv->v_co_orig, curr_sv->dir_side[1]);
glLineWidth(line_size);
- UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
- glBegin(GL_LINES);
+ immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
+ immBeginAtMost(PRIM_LINES, 4);
if (curr_sv->v_side[0]) {
- glVertex3fv(curr_sv->v_side[0]->co);
- glVertex3fv(curr_sv->v_co_orig);
+ immVertex3fv(pos, curr_sv->v_side[0]->co);
+ immVertex3fv(pos, curr_sv->v_co_orig);
}
if (curr_sv->v_side[1]) {
- glVertex3fv(curr_sv->v_side[1]->co);
- glVertex3fv(curr_sv->v_co_orig);
+ immVertex3fv(pos, curr_sv->v_side[1]->co);
+ immVertex3fv(pos, curr_sv->v_co_orig);
}
- glEnd();
+ immEnd();
- UI_ThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade);
+ immUniformThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade);
glPointSize(ctrl_size);
- glBegin(GL_POINTS);
+ immBegin(PRIM_POINTS, 1);
if (sld->flipped) {
- if (curr_sv->v_side[1]) glVertex3fv(curr_sv->v_side[1]->co);
+ if (curr_sv->v_side[1]) immVertex3fv(pos, curr_sv->v_side[1]->co);
}
else {
- if (curr_sv->v_side[0]) glVertex3fv(curr_sv->v_side[0]->co);
+ if (curr_sv->v_side[0]) immVertex3fv(pos, curr_sv->v_side[0]->co);
}
- glEnd();
+ immEnd();
- UI_ThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade);
+ immUniformThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade);
glPointSize(guide_size);
- glBegin(GL_POINTS);
-#if 0
- interp_v3_v3v3(co_mark, co_b, co_a, fac);
- glVertex3fv(co_mark);
-#endif
+ immBegin(PRIM_POINTS, 1);
interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac);
- glVertex3fv(co_mark);
- glEnd();
+ immVertex3fv(pos, co_mark);
+ immEnd();
}
else {
if (is_clamp == false) {
@@ -6890,8 +6900,8 @@ static void drawEdgeSlide(TransInfo *t)
const int alpha_shade = -160;
glLineWidth(line_size);
- UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
- glBegin(GL_LINES);
+ immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
+ immBegin(PRIM_LINES, sld->totsv * 2);
sv = sld->sv;
for (i = 0; i < sld->totsv; i++, sv++) {
@@ -6909,18 +6919,19 @@ static void drawEdgeSlide(TransInfo *t)
add_v3_v3(a, sv->v_co_orig);
add_v3_v3(b, sv->v_co_orig);
- glVertex3fv(a);
- glVertex3fv(b);
+ immVertex3fv(pos, a);
+ immVertex3fv(pos, b);
}
- glEnd();
+ immEnd();
}
else {
BLI_assert(0);
}
}
- glPopMatrix();
- glPopAttrib();
+ immUnbindProgram();
+
+ gpuMatrixEnd();
glDisable(GL_BLEND);
@@ -7444,19 +7455,23 @@ static void drawVertSlide(TransInfo *t)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT | GL_POINT_BIT);
- glPushMatrix();
+ gpuMatrixBegin3D_legacy();
- glMultMatrixf(t->obedit->obmat);
+ gpuMultMatrix3D(t->obedit->obmat);
glLineWidth(line_size);
- UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
- glBegin(GL_LINES);
+
+ unsigned pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade);
+
+ immBegin(PRIM_LINES, sld->totsv * 2);
if (is_clamp) {
sv = sld->sv;
for (i = 0; i < sld->totsv; i++, sv++) {
- glVertex3fv(sv->co_orig_3d);
- glVertex3fv(sv->co_link_orig_3d[sv->co_link_curr]);
+ immVertex3fv(pos, sv->co_orig_3d);
+ immVertex3fv(pos, sv->co_link_orig_3d[sv->co_link_curr]);
}
}
else {
@@ -7469,19 +7484,19 @@ static void drawVertSlide(TransInfo *t)
add_v3_v3(a, sv->co_orig_3d);
add_v3_v3(b, sv->co_orig_3d);
- glVertex3fv(a);
- glVertex3fv(b);
+ immVertex3fv(pos, a);
+ immVertex3fv(pos, b);
}
}
- glEnd();
+ immEnd();
glPointSize(ctrl_size);
- glBegin(GL_POINTS);
- glVertex3fv((sld->flipped && sld->use_even) ?
+ immBegin(PRIM_POINTS, 1);
+ immVertex3fv(pos, (sld->flipped && sld->use_even) ?
curr_sv->co_link_orig_3d[curr_sv->co_link_curr] :
curr_sv->co_orig_3d);
- glEnd();
+ immEnd();
glDisable(GL_BLEND);
@@ -7507,19 +7522,20 @@ static void drawVertSlide(TransInfo *t)
add_v3_v3(co_dest_3d, curr_sv->co_orig_3d);
- glLineWidth(1);
+ glLineWidth(1.0f);
setlinestyle(1);
- cpack(0xffffff);
- glBegin(GL_LINES);
- glVertex3fv(curr_sv->co_orig_3d);
- glVertex3fv(co_dest_3d);
+ imm_cpack(0xffffff);
- glEnd();
+ immBegin(PRIM_LINES, 2);
+ immVertex3fv(pos, curr_sv->co_orig_3d);
+ immVertex3fv(pos, co_dest_3d);
+ immEnd();
}
- glPopMatrix();
- glPopAttrib();
+ immUnbindProgram();
+
+ gpuMatrixEnd();
if (v3d && v3d->zbuf)
glEnable(GL_DEPTH_TEST);
@@ -8495,7 +8511,7 @@ static void initTimeScale(TransInfo *t)
center[1] = t->mouse.imval[1];
/* force a reinit with the center2d used here */
- initMouseInput(t, &t->mouse, center, t->mouse.imval);
+ initMouseInput(t, &t->mouse, center, t->mouse.imval, false);
initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP);
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index a59f9dc43dd..7ea4448a44e 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -728,7 +728,7 @@ typedef enum {
INPUT_CUSTOM_RATIO_FLIP,
} MouseInputMode;
-void initMouseInput(TransInfo *t, MouseInput *mi, const float center[2], const int mval[2]);
+void initMouseInput(TransInfo *t, MouseInput *mi, const float center[2], const int mval[2], const bool precision);
void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode);
eRedrawFlag handleMouseInput(struct TransInfo *t, struct MouseInput *mi, const struct wmEvent *event);
void applyMouseInput(struct TransInfo *t, struct MouseInput *mi, const int mval[2], float output[3]);
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index beb430deb96..87e720c4484 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -828,7 +828,6 @@ static void pose_grab_with_ik_clear(Object *ob)
bKinematicConstraint *data;
bPoseChannel *pchan;
bConstraint *con, *next;
- bool need_dependency_update = false;
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
/* clear all temporary lock flags */
@@ -843,7 +842,6 @@ static void pose_grab_with_ik_clear(Object *ob)
data = con->data;
if (data->flag & CONSTRAINT_IK_TEMP) {
/* iTaSC needs clear for removed constraints */
- need_dependency_update = true;
BIK_clear_data(ob->pose);
BLI_remlink(&pchan->constraints, con);
@@ -858,13 +856,8 @@ static void pose_grab_with_ik_clear(Object *ob)
}
}
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (!DEG_depsgraph_use_legacy() && need_dependency_update)
-#endif
- {
- /* TODO(sergey): Consider doing partial update only. */
- DAG_relations_tag_update(G.main);
- }
+ /* TODO(sergey): Consider doing partial update only. */
+ DAG_relations_tag_update(G.main);
}
/* adds the IK to pchan - returns if added */
@@ -1017,13 +1010,8 @@ static short pose_grab_with_ik(Object *ob)
/* iTaSC needs clear for new IK constraints */
if (tot_ik) {
BIK_clear_data(ob->pose);
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (!DEG_depsgraph_use_legacy())
-#endif
- {
- /* TODO(sergey): Consuder doing partial update only. */
- DAG_relations_tag_update(G.main);
- }
+ /* TODO(sergey): Consuder doing partial update only. */
+ DAG_relations_tag_update(G.main);
}
return (tot_ik) ? 1 : 0;
@@ -5421,11 +5409,6 @@ static void set_trans_object_base_flags(TransInfo *t)
}
}
- /* all recalc flags get flushed to all layers, so a layer flip later on works fine */
-#ifdef WITH_LEGACY_DEPSGRAPH
- DAG_scene_flush_update(G.main, t->scene, -1, 0);
-#endif
-
/* and we store them temporal in base (only used for transform code) */
/* this because after doing updates, the object->recalc is cleared */
for (base = scene->base.first; base; base = base->next) {
@@ -5503,9 +5486,6 @@ static int count_proportional_objects(TransInfo *t)
/* all recalc flags get flushed to all layers, so a layer flip later on works fine */
DAG_scene_relations_update(G.main, t->scene);
-#ifdef WITH_LEGACY_DEPSGRAPH
- DAG_scene_flush_update(G.main, t->scene, -1, 0);
-#endif
/* and we store them temporal in base (only used for transform code) */
/* this because after doing updates, the object->recalc is cleared */
@@ -6418,7 +6398,7 @@ static void createTransObject(bContext *C, TransInfo *t)
td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransOb");
tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "TransObExtension");
- CTX_DATA_BEGIN(C, Base *, base, selected_bases)
+ CTX_DATA_BEGIN(C, ObjectBase *, base, selected_bases)
{
Object *ob = base->object;
diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c
index 9b7d19eacd5..42cc918ec8c 100644
--- a/source/blender/editors/transform/transform_input.c
+++ b/source/blender/editors/transform/transform_input.c
@@ -234,10 +234,10 @@ static void InputAngleSpring(TransInfo *t, MouseInput *mi, const double mval[2],
output[1] = toutput[0];
}
-void initMouseInput(TransInfo *UNUSED(t), MouseInput *mi, const float center[2], const int mval[2])
+void initMouseInput(TransInfo *UNUSED(t), MouseInput *mi, const float center[2], const int mval[2], const bool precision)
{
mi->factor = 0;
- mi->precision = 0;
+ mi->precision = precision;
mi->center[0] = center[0];
mi->center[1] = center[1];
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index b341415f3b3..a4710b7b747 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -42,7 +42,7 @@
#include "BLI_math.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
-#include "BLI_path_util.h"
+#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
#include "BKE_action.h"
diff --git a/source/blender/gpu/GPU_immediate.h b/source/blender/gpu/GPU_immediate.h
index f601d062d48..4a0840e22c0 100644
--- a/source/blender/gpu/GPU_immediate.h
+++ b/source/blender/gpu/GPU_immediate.h
@@ -46,3 +46,5 @@ void immUniformThemeColorShade(int color_id, int offset);
void immUniformThemeColorShadeAlpha(int color_id, int color_offset, int alpha_offset);
void immUniformThemeColorBlendShade(int color_id1, int color_id2, float fac, int offset);
void immUniformThemeColorBlend(int color_id1, int color_id2, float fac);
+void immThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset);
+
diff --git a/source/blender/gpu/gawain/batch.h b/source/blender/gpu/gawain/batch.h
index 31c05fc17c7..3db910151d9 100644
--- a/source/blender/gpu/gawain/batch.h
+++ b/source/blender/gpu/gawain/batch.h
@@ -21,7 +21,7 @@ typedef enum {
READY_TO_DRAW
} BatchPhase;
-typedef struct {
+typedef struct Batch{
// geometry
VertexBuffer* verts;
ElementList* elem; // NULL if element list not needed
diff --git a/source/blender/gpu/intern/gpu_immediate.c b/source/blender/gpu/intern/gpu_immediate.c
index 685c31dc3e0..5188ca4c0e2 100644
--- a/source/blender/gpu/intern/gpu_immediate.c
+++ b/source/blender/gpu/intern/gpu_immediate.c
@@ -28,6 +28,7 @@
#include "GPU_immediate.h"
#include "GPU_matrix.h"
#include "UI_resources.h"
+#include "BLI_utildefines.h"
#include "gpu_shader_private.h"
@@ -71,3 +72,10 @@ void immUniformThemeColorBlend(int color_id1, int color_id2, float fac)
UI_GetThemeColorBlend3ubv(color_id1, color_id2, fac, color);
immUniformColor3ubv(color);
}
+
+void immThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset)
+{
+ unsigned char col[4];
+ UI_GetThemeColorShadeAlpha4ubv(colorid, coloffset, alphaoffset, col);
+ immUniformColor4ub(col[0], col[1], col[2], col[3]);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
index 054a2f795ee..50c8e255162 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
@@ -27,8 +27,7 @@ vec3 calculate_view_space_normal(in vec3 viewposition)
{
vec3 normal = cross(normalize(dFdx(viewposition)),
ssao_params.w * normalize(dFdy(viewposition)));
- normalize(normal);
- return normal;
+ return normalize(normal);
}
float calculate_ssao_factor(float depth)
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 4416b6494f9..aa583c5ecf8 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -1358,7 +1358,7 @@ void mtex_cube_map_refl_from_refldir(
samplerCube ima, vec3 reflecteddirection, out float value, out vec4 color)
{
color = textureCube(ima, reflecteddirection);
- value = 1.0;
+ value = color.a;
}
void mtex_cube_map_refl(
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index f3df9090d41..1083400ece2 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -76,6 +76,8 @@ typedef struct bMotionPath {
int start_frame; /* for drawing paths, the start frame number */
int end_frame; /* for drawing paths, the end frame number */
+ float color[3]; /* optional custom color */
+ int line_thickness; /* line thickness */
int flag; /* baking settings - eMotionPath_Flag */
} bMotionPath;
@@ -84,7 +86,11 @@ typedef enum eMotionPath_Flag {
/* (for bones) path represents the head of the bone */
MOTIONPATH_FLAG_BHEAD = (1 << 0),
/* motion path is being edited */
- MOTIONPATH_FLAG_EDIT = (1 << 1)
+ MOTIONPATH_FLAG_EDIT = (1 << 1),
+ /* Custom colors */
+ MOTIONPATH_FLAG_CUSTOM = (1 << 2),
+ /* Draw lines or only points */
+ MOTIONPATH_FLAG_LINES = (1 << 3)
} eMotionPath_Flag;
/* Visualization General --------------------------- */
diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h
index 63856d9d3c9..b1f988945f8 100644
--- a/source/blender/makesdna/DNA_layer_types.h
+++ b/source/blender/makesdna/DNA_layer_types.h
@@ -80,6 +80,9 @@ typedef struct SceneCollection {
/* ObjectBase->flag */
enum {
BASE_SELECTED = (1 << 0),
+ BASE_VISIBLED = (1 << 1),
+ BASE_SELECTABLED = (1 << 2),
+ BASE_FROMDUPLI = (1 << 3),
};
/* LayerCollection->flag */
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index 39e56925903..15ea3d4d37a 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -127,6 +127,7 @@ typedef struct Mesh {
short totcol;
struct Multires *mr DNA_DEPRECATED; /* deprecated multiresolution modeling data, only keep for loading old files */
+ void *batch_cache;
} Mesh;
/* deprecated by MTFace, only here for file reading */
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 04a87e156f8..08366af628c 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -1254,12 +1254,51 @@ typedef enum eGP_BrushEdit_SettingsFlag {
GP_BRUSHEDIT_FLAG_APPLY_STRENGTH = (1 << 2),
/* apply brush to thickness */
GP_BRUSHEDIT_FLAG_APPLY_THICKNESS = (1 << 3),
+} eGP_BrushEdit_SettingsFlag;
+
+
+/* Settings for GP Interpolation Operators */
+typedef struct GP_Interpolate_Settings {
+ short flag; /* eGP_Interpolate_SettingsFlag */
+
+ char type; /* eGP_Interpolate_Type - Interpolation Mode */
+ char easing; /* eBezTriple_Easing - Easing mode (if easing equation used) */
+
+ float back; /* BEZT_IPO_BACK */
+ float amplitude, period; /* BEZT_IPO_ELASTIC */
+
+ struct CurveMapping *custom_ipo; /* custom interpolation curve (for use with GP_IPO_CURVEMAP) */
+} GP_Interpolate_Settings;
+
+/* GP_Interpolate_Settings.flag */
+typedef enum eGP_Interpolate_SettingsFlag {
/* apply interpolation to all layers */
- GP_BRUSHEDIT_FLAG_INTERPOLATE_ALL_LAYERS = (1 << 4),
+ GP_TOOLFLAG_INTERPOLATE_ALL_LAYERS = (1 << 0),
/* apply interpolation to only selected */
- GP_BRUSHEDIT_FLAG_INTERPOLATE_ONLY_SELECTED = (1 << 5)
+ GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED = (1 << 1),
+} eGP_Interpolate_SettingsFlag;
+
+/* GP_Interpolate_Settings.type */
+typedef enum eGP_Interpolate_Type {
+ /* Traditional Linear Interpolation */
+ GP_IPO_LINEAR = 0,
+
+ /* CurveMap Defined Interpolation */
+ GP_IPO_CURVEMAP = 1,
+
+ /* Easing Equations */
+ GP_IPO_BACK = 3,
+ GP_IPO_BOUNCE = 4,
+ GP_IPO_CIRC = 5,
+ GP_IPO_CUBIC = 6,
+ GP_IPO_ELASTIC = 7,
+ GP_IPO_EXPO = 8,
+ GP_IPO_QUAD = 9,
+ GP_IPO_QUART = 10,
+ GP_IPO_QUINT = 11,
+ GP_IPO_SINE = 12,
+} eGP_Interpolate_Type;
-} eGP_BrushEdit_SettingsFlag;
/* *************************************************************** */
/* Transform Orientations */
@@ -1477,7 +1516,10 @@ typedef struct ToolSettings {
/* Grease Pencil Sculpt */
struct GP_BrushEdit_Settings gp_sculpt;
-
+
+ /* Grease Pencil Interpolation Tool(s) */
+ struct GP_Interpolate_Settings gp_interpolate;
+
/* Grease Pencil Drawing Brushes (bGPDbrush) */
ListBase gp_brushes;
@@ -1951,6 +1993,8 @@ extern const char *RE_engine_id_CYCLES;
#define LASTBASE scene->base.last
#define BASACT (scene->basact)
#define OBACT (BASACT ? BASACT->object: NULL)
+#define BASACT_NEW (sl->basact)
+#define OBACT_NEW (BASACT_NEW ? BASACT_NEW->object: NULL)
#define V3D_CAMERA_LOCAL(v3d) ((!(v3d)->scenelock && (v3d)->camera) ? (v3d)->camera : NULL)
#define V3D_CAMERA_SCENE(scene, v3d) ((!(v3d)->scenelock && (v3d)->camera) ? (v3d)->camera : (scene)->camera)
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 2c12a0ea2ad..448e5901ec8 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -262,6 +262,7 @@ extern StructRNA RNA_GPencilLayer;
extern StructRNA RNA_GPencilPalette;
extern StructRNA RNA_GPencilPaletteColor;
extern StructRNA RNA_GPencilBrush;
+extern StructRNA RNA_GPencilInterpolateSettings;
extern StructRNA RNA_GPencilStroke;
extern StructRNA RNA_GPencilStrokePoint;
extern StructRNA RNA_GPencilSculptSettings;
diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h
index 1a191a68668..dee8df7d933 100644
--- a/source/blender/makesrna/RNA_types.h
+++ b/source/blender/makesrna/RNA_types.h
@@ -174,8 +174,10 @@ typedef enum PropertyFlag {
* and collections */
PROP_ANIMATABLE = (1 << 1),
- /* This flag means when the property's widget is in 'textedit' mode, it will be updated after every typed char,
- * instead of waiting final validation. Used e.g. for text searchbox. */
+ /* This flag means when the property's widget is in 'textedit' mode, it will be updated
+ * after every typed char, instead of waiting final validation. Used e.g. for text searchbox.
+ * It will also cause UI_BUT_VALUE_CLEAR to be set for text buttons. We could add an own flag
+ * for search/filter properties, but this works just fine for now. */
PROP_TEXTEDIT_UPDATE = (1 << 31),
/* icon */
diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c
index a09853eaddc..004acbe4dbd 100644
--- a/source/blender/makesrna/intern/rna_actuator.c
+++ b/source/blender/makesrna/intern/rna_actuator.c
@@ -32,8 +32,9 @@
#include "DNA_actuator_types.h"
#include "DNA_scene_types.h" /* for MAXFRAME */
-#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BLI_string_utils.h"
+#include "BLI_utildefines.h"
#include "BLT_translation.h"
diff --git a/source/blender/makesrna/intern/rna_animviz.c b/source/blender/makesrna/intern/rna_animviz.c
index 8e42e68ed1e..eea24bfb1e0 100644
--- a/source/blender/makesrna/intern/rna_animviz.c
+++ b/source/blender/makesrna/intern/rna_animviz.c
@@ -153,7 +153,20 @@ static void rna_def_animviz_motion_path(BlenderRNA *brna)
prop = RNA_def_property(srna, "length", PROP_INT, PROP_TIME);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Length", "Number of frames cached");
-
+
+ /* Custom Color */
+ prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Color", "Custom color for motion path");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ /* Line width */
+ prop = RNA_def_property(srna, "line_thickness", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "line_thickness");
+ RNA_def_property_range(prop, 1, 6);
+ RNA_def_property_ui_text(prop, "Line thickness", "Line thickness for drawing path");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
/* Settings */
prop = RNA_def_property(srna, "use_bone_head", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOTIONPATH_FLAG_BHEAD);
@@ -164,6 +177,19 @@ static void rna_def_animviz_motion_path(BlenderRNA *brna)
prop = RNA_def_property(srna, "is_modified", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOTIONPATH_FLAG_EDIT);
RNA_def_property_ui_text(prop, "Edit Path", "Path is being edited");
+
+ /* Use custom color */
+ prop = RNA_def_property(srna, "use_custom_color", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", MOTIONPATH_FLAG_CUSTOM);
+ RNA_def_property_ui_text(prop, "Custom colors", "Use custom color for this motion path");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ /* Draw lines between keyframes */
+ prop = RNA_def_property(srna, "lines", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", MOTIONPATH_FLAG_LINES);
+ RNA_def_property_ui_text(prop, "Lines", "Draw straight lines between keyframe points");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
}
/* --- */
@@ -337,6 +363,7 @@ static void rna_def_animviz_paths(BlenderRNA *brna)
"Number of frames to show after the current frame "
"(only for 'Around Current Frame' Onion-skinning method)");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); /* XXX since this is only for 3d-view drawing */
+
}
/* --- */
diff --git a/source/blender/makesrna/intern/rna_controller.c b/source/blender/makesrna/intern/rna_controller.c
index ed700916584..3fa9d7ef270 100644
--- a/source/blender/makesrna/intern/rna_controller.c
+++ b/source/blender/makesrna/intern/rna_controller.c
@@ -29,6 +29,7 @@
#include "DNA_object_types.h"
#include "DNA_controller_types.h"
+#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index 14da990278c..6e0d6ad2bcd 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -31,6 +31,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -59,6 +60,7 @@ static EnumPropertyItem parent_type_items[] = {
#include "WM_api.h"
+#include "BKE_animsys.h"
#include "BKE_gpencil.h"
#include "BKE_action.h"
@@ -352,10 +354,16 @@ static void rna_GPencilLayer_info_set(PointerRNA *ptr, const char *value)
bGPdata *gpd = ptr->id.data;
bGPDlayer *gpl = ptr->data;
+ char oldname[128] = "";
+ BLI_strncpy(oldname, gpl->info, sizeof(oldname));
+
/* copy the new name into the name slot */
BLI_strncpy_utf8(gpl->info, value, sizeof(gpl->info));
BLI_uniquename(&gpd->layers, gpl, DATA_("GP_Layer"), '.', offsetof(bGPDlayer, info), sizeof(gpl->info));
+
+ /* now fix animation paths */
+ BKE_animdata_fix_paths_rename_all(&gpd->id, "layers", oldname, gpl->info);
}
static void rna_GPencil_use_onion_skinning_set(PointerRNA *ptr, const int value)
@@ -776,11 +784,16 @@ static void rna_GPencilPalette_info_set(PointerRNA *ptr, const char *value)
bGPdata *gpd = ptr->id.data;
bGPDpalette *palette = ptr->data;
+ char oldname[64] = "";
+ BLI_strncpy(oldname, palette->info, sizeof(oldname));
+
/* copy the new name into the name slot */
BLI_strncpy_utf8(palette->info, value, sizeof(palette->info));
BLI_uniquename(&gpd->palettes, palette, DATA_("GP_Palette"), '.', offsetof(bGPDpalette, info),
sizeof(palette->info));
+ /* now fix animation paths */
+ BKE_animdata_fix_paths_rename_all(&gpd->id, "palettes", oldname, palette->info);
}
static char *rna_GPencilPalette_path(PointerRNA *ptr)
@@ -813,14 +826,20 @@ static void rna_GPencilPaletteColor_info_set(PointerRNA *ptr, const char *value)
bGPdata *gpd = ptr->id.data;
bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd);
bGPDpalettecolor *palcolor = ptr->data;
-
- /* rename all strokes */
- BKE_gpencil_palettecolor_changename(gpd, palcolor->info, value);
+
+ char oldname[64] = "";
+ BLI_strncpy(oldname, palcolor->info, sizeof(oldname));
/* copy the new name into the name slot */
BLI_strncpy_utf8(palcolor->info, value, sizeof(palcolor->info));
BLI_uniquename(&palette->colors, palcolor, DATA_("Color"), '.', offsetof(bGPDpalettecolor, info),
sizeof(palcolor->info));
+
+ /* rename all strokes */
+ BKE_gpencil_palettecolor_changename(gpd, oldname, palcolor->info);
+
+ /* now fix animation paths */
+ BKE_animdata_fix_paths_rename_all(&gpd->id, "colors", oldname, palcolor->info);
}
static void rna_GPencilStrokeColor_info_set(PointerRNA *ptr, const char *value)
diff --git a/source/blender/makesrna/intern/rna_group.c b/source/blender/makesrna/intern/rna_group.c
index aa02a3c159d..2a5a0011279 100644
--- a/source/blender/makesrna/intern/rna_group.c
+++ b/source/blender/makesrna/intern/rna_group.c
@@ -53,9 +53,9 @@ static PointerRNA rna_Group_objects_get(CollectionPropertyIterator *iter)
return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, ((GroupObject *)internal->link)->ob);
}
-static void rna_Group_objects_link(Group *group, bContext *C, ReportList *reports, Object *object)
+static void rna_Group_objects_link(Group *group, ReportList *reports, Object *object)
{
- if (!BKE_group_object_add(group, object, CTX_data_scene(C), NULL)) {
+ if (!BKE_group_object_add(group, object)) {
BKE_reportf(reports, RPT_ERROR, "Object '%s' already in group '%s'", object->id.name + 2, group->id.name + 2);
return;
}
@@ -63,9 +63,9 @@ static void rna_Group_objects_link(Group *group, bContext *C, ReportList *report
WM_main_add_notifier(NC_OBJECT | ND_DRAW, &object->id);
}
-static void rna_Group_objects_unlink(Group *group, bContext *C, ReportList *reports, Object *object)
+static void rna_Group_objects_unlink(Group *group, ReportList *reports, Object *object)
{
- if (!BKE_group_object_unlink(group, object, CTX_data_scene(C), NULL)) {
+ if (!BKE_group_object_unlink(group, object)) {
BKE_reportf(reports, RPT_ERROR, "Object '%s' not in group '%s'", object->id.name + 2, group->id.name + 2);
return;
}
@@ -91,7 +91,7 @@ static void rna_def_group_objects(BlenderRNA *brna, PropertyRNA *cprop)
/* add object */
func = RNA_def_function(srna, "link", "rna_Group_objects_link");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Add this object to a group");
/* object to add */
parm = RNA_def_pointer(func, "object", "Object", "", "Object to add");
@@ -100,7 +100,7 @@ static void rna_def_group_objects(BlenderRNA *brna, PropertyRNA *cprop)
/* remove object */
func = RNA_def_function(srna, "unlink", "rna_Group_objects_unlink");
RNA_def_function_ui_description(func, "Remove this object to a group");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
/* object to remove */
parm = RNA_def_pointer(func, "object", "Object", "", "Object to remove");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c
index 2d669986485..a5abc8a3be2 100644
--- a/source/blender/makesrna/intern/rna_key.c
+++ b/source/blender/makesrna/intern/rna_key.c
@@ -33,6 +33,7 @@
#include "DNA_lattice_types.h"
#include "DNA_mesh_types.h"
+#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
diff --git a/source/blender/makesrna/intern/rna_linestyle.c b/source/blender/makesrna/intern/rna_linestyle.c
index 622c61beaeb..1199cccc4e6 100644
--- a/source/blender/makesrna/intern/rna_linestyle.c
+++ b/source/blender/makesrna/intern/rna_linestyle.c
@@ -27,6 +27,9 @@
#include <stdio.h>
#include <stdlib.h>
+#include "BLI_utildefines.h"
+#include "BLI_string_utils.h"
+
#include "RNA_define.h"
#include "RNA_enum_types.h"
diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c
index 4a078ef9182..ff9873fb3d1 100644
--- a/source/blender/makesrna/intern/rna_mesh_api.c
+++ b/source/blender/makesrna/intern/rna_mesh_api.c
@@ -240,6 +240,9 @@ void RNA_api_mesh(StructRNA *srna)
func = RNA_def_function(srna, "free_normals_split", "rna_Mesh_free_normals_split");
RNA_def_function_ui_description(func, "Free split vertex normals");
+ func = RNA_def_function(srna, "split_faces", "BKE_mesh_split_faces");
+ RNA_def_function_ui_description(func, "Split faces based on the edge angle");
+
func = RNA_def_function(srna, "calc_tangents", "rna_Mesh_calc_tangents");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func,
@@ -317,4 +320,3 @@ void RNA_api_mesh(StructRNA *srna)
}
#endif
-
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index 362baed1e7c..95dab13571d 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -45,6 +45,8 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
+#include "BLI_string_utils.h"
+
#include "BLT_translation.h"
#include "rna_internal.h"
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index 99d57147248..28ce63a61bd 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -40,6 +40,7 @@
#include "DNA_scene_types.h"
#include "BLI_math.h"
+#include "BLI_string_utils.h"
#include "BLT_translation.h"
diff --git a/source/blender/makesrna/intern/rna_property.c b/source/blender/makesrna/intern/rna_property.c
index 07bdbb03357..fb70870f49b 100644
--- a/source/blender/makesrna/intern/rna_property.c
+++ b/source/blender/makesrna/intern/rna_property.c
@@ -31,6 +31,7 @@
#include "DNA_object_types.h"
#include "BLI_path_util.h"
+#include "BLI_string_utils.h"
#include "BLT_translation.h"
diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c
index d69ae2b78bb..518c7efd915 100644
--- a/source/blender/makesrna/intern/rna_render.c
+++ b/source/blender/makesrna/intern/rna_render.c
@@ -78,9 +78,14 @@ EnumPropertyItem rna_enum_render_pass_type_items[] = {
};
EnumPropertyItem rna_enum_render_pass_debug_type_items[] = {
- {RENDER_PASS_DEBUG_BVH_TRAVERSAL_STEPS, "BVH_TRAVERSAL_STEPS", 0, "BVH Traversal Steps", ""},
- {RENDER_PASS_DEBUG_BVH_TRAVERSED_INSTANCES, "BVH_TRAVERSED_INSTANCES", 0, "BVH Traversed Instances", ""},
- {RENDER_PASS_DEBUG_RAY_BOUNCES, "RAY_BOUNCES", 0, "Ray Steps", ""},
+ {RENDER_PASS_DEBUG_BVH_TRAVERSED_NODES, "BVH_TRAVERSED_NODES", 0, "BVH Traversed Nodes",
+ "Number of nodes traversed in BVH for the camera rays"},
+ {RENDER_PASS_DEBUG_BVH_TRAVERSED_INSTANCES, "BVH_TRAVERSED_INSTANCES", 0, "BVH Traversed Instances",
+ "Number of BVH instances traversed by camera rays"},
+ {RENDER_PASS_DEBUG_BVH_INTERSECTIONS, "BVH_INTERSECTIONS", 0, "BVH Intersections",
+ "Number of primitive intersections performed by the camera rays"},
+ {RENDER_PASS_DEBUG_RAY_BOUNCES, "RAY_BOUNCES", 0, "Ray Steps",
+ "Number of bounces done by the main integration loop"},
{0, NULL, 0, NULL, NULL}
};
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 77ce5d072ae..5e92772171f 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -41,6 +41,7 @@
#include "IMB_imbuf_types.h"
#include "BLI_math.h"
+#include "BLI_string_utils.h"
#include "BLT_translation.h"
@@ -409,9 +410,34 @@ EnumPropertyItem rna_enum_bake_pass_filter_type_items[] = {
{0, NULL, 0, NULL, NULL}
};
+EnumPropertyItem rna_enum_gpencil_interpolation_mode_items[] = {
+ /* interpolation */
+ {0, "", 0, N_("Interpolation"), "Standard transitions between keyframes"},
+ {GP_IPO_LINEAR, "LINEAR", ICON_IPO_LINEAR, "Linear", "Straight-line interpolation between A and B (i.e. no ease in/out)"},
+ {GP_IPO_CURVEMAP, "CUSTOM", ICON_IPO_BEZIER, "Custom", "Custom interpolation defined using a curvemap"},
+
+ /* easing */
+ {0, "", 0, N_("Easing (by strength)"), "Predefined inertial transitions, useful for motion graphics (from least to most ''dramatic'')"},
+ {GP_IPO_SINE, "SINE", ICON_IPO_SINE, "Sinusoidal", "Sinusoidal easing (weakest, almost linear but with a slight curvature)"},
+ {GP_IPO_QUAD, "QUAD", ICON_IPO_QUAD, "Quadratic", "Quadratic easing"},
+ {GP_IPO_CUBIC, "CUBIC", ICON_IPO_CUBIC, "Cubic", "Cubic easing"},
+ {GP_IPO_QUART, "QUART", ICON_IPO_QUART, "Quartic", "Quartic easing"},
+ {GP_IPO_QUINT, "QUINT", ICON_IPO_QUINT, "Quintic", "Quintic easing"},
+ {GP_IPO_EXPO, "EXPO", ICON_IPO_EXPO, "Exponential", "Exponential easing (dramatic)"},
+ {GP_IPO_CIRC, "CIRC", ICON_IPO_CIRC, "Circular", "Circular easing (strongest and most dynamic)"},
+
+ {0, "", 0, N_("Dynamic Effects"), "Simple physics-inspired easing effects"},
+ {GP_IPO_BACK, "BACK", ICON_IPO_BACK, "Back", "Cubic easing with overshoot and settle"},
+ {GP_IPO_BOUNCE, "BOUNCE", ICON_IPO_BOUNCE, "Bounce", "Exponentially decaying parabolic bounce, like when objects collide"},
+ {GP_IPO_ELASTIC, "ELASTIC", ICON_IPO_ELASTIC, "Elastic", "Exponentially decaying sine wave, like an elastic band"},
+
+ {0, NULL, 0, NULL, NULL}
+};
+
#ifdef RNA_RUNTIME
#include "DNA_anim_types.h"
+#include "DNA_color_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
@@ -423,6 +449,7 @@ EnumPropertyItem rna_enum_bake_pass_filter_type_items[] = {
#include "BKE_brush.h"
#include "BKE_collection.h"
+#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_image.h"
@@ -451,6 +478,29 @@ EnumPropertyItem rna_enum_bake_pass_filter_type_items[] = {
#include "FRS_freestyle.h"
#endif
+/* Grease Pencil Interpolation settings */
+static char *rna_GPencilInterpolateSettings_path(PointerRNA *UNUSED(ptr))
+{
+ return BLI_strdup("tool_settings.gpencil_interpolate");
+}
+
+static void rna_GPencilInterpolateSettings_type_set(PointerRNA *ptr, int value)
+{
+ GP_Interpolate_Settings *settings = (GP_Interpolate_Settings *)ptr->data;
+
+ /* NOTE: This cast should be fine, as we have a small + finite set of values (eGP_Interpolate_Type)
+ * that should fit well within a char
+ */
+ settings->type = (char)value;
+
+ /* init custom interpolation curve here now the first time it's used */
+ if ((settings->type == GP_IPO_CURVEMAP) &&
+ (settings->custom_ipo == NULL))
+ {
+ settings->custom_ipo = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+ }
+}
+
/* Grease pencil Drawing Brushes */
static bGPDbrush *rna_GPencil_brush_new(ToolSettings *ts, const char *name, int setactive)
{
@@ -2246,7 +2296,7 @@ static void rna_SceneCollection_object_unlink(
return;
}
- BKE_collection_object_remove(scene, sc, ob);
+ BKE_collection_object_remove(bmain, scene, sc, ob, false);
/* needed otherwise the depgraph will contain freed objects which can crash, see [#20958] */
DAG_relations_tag_update(bmain);
@@ -2283,6 +2333,31 @@ static PointerRNA rna_LayerCollection_objects_get(CollectionPropertyIterator *it
return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, base->object);
}
+static void rna_LayerCollection_hide_update(bContext *C, PointerRNA *ptr)
+{
+ Scene *scene = CTX_data_scene(C);
+ LayerCollection *lc = ptr->data;
+ SceneLayer *sl = BKE_scene_layer_find_from_collection(scene, lc);
+
+ /* hide and deselect bases that are directly influenced by this LayerCollection */
+ BKE_scene_layer_base_flag_recalculate(sl);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+}
+
+static void rna_LayerCollection_hide_select_update(bContext *C, PointerRNA *ptr)
+{
+ LayerCollection *lc = ptr->data;
+
+ if ((lc->flag & COLLECTION_SELECTABLE) == 0) {
+ Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = BKE_scene_layer_find_from_collection(scene, lc);
+
+ /* deselect bases that are directly influenced by this LayerCollection */
+ BKE_scene_layer_base_flag_recalculate(sl);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
+ }
+}
+
static int rna_LayerCollections_active_collection_index_get(PointerRNA *ptr)
{
SceneLayer *sl = (SceneLayer *)ptr->data;
@@ -2508,6 +2583,73 @@ static void rna_ObjectBase_select_update(Main *UNUSED(bmain), Scene *UNUSED(scen
#else
+/* Grease Pencil Interpolation tool settings */
+static void rna_def_gpencil_interpolate(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "GPencilInterpolateSettings", NULL);
+ RNA_def_struct_sdna(srna, "GP_Interpolate_Settings");
+ RNA_def_struct_path_func(srna, "rna_GPencilInterpolateSettings_path");
+ RNA_def_struct_ui_text(srna, "Grease Pencil Interpolate Settings",
+ "Settings for Grease Pencil interpolation tools");
+
+ /* flags */
+ prop = RNA_def_property(srna, "interpolate_all_layers", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TOOLFLAG_INTERPOLATE_ALL_LAYERS);
+ RNA_def_property_ui_text(prop, "Interpolate All Layers", "Interpolate all layers, not only active");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+ prop = RNA_def_property(srna, "interpolate_selected_only", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED);
+ RNA_def_property_ui_text(prop, "Interpolate Selected Strokes", "Interpolate only selected strokes in the original frame");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+ /* interpolation type */
+ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "type");
+ RNA_def_property_enum_items(prop, rna_enum_gpencil_interpolation_mode_items);
+ RNA_def_property_enum_funcs(prop, NULL, "rna_GPencilInterpolateSettings_type_set", NULL);
+ RNA_def_property_ui_text(prop, "Type",
+ "Interpolation method to use the next time 'Interpolate Sequence' is run");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+ /* easing */
+ prop = RNA_def_property(srna, "easing", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "easing");
+ RNA_def_property_enum_items(prop, rna_enum_beztriple_interpolation_easing_items);
+ RNA_def_property_ui_text(prop, "Easing",
+ "Which ends of the segment between the preceding and following grease pencil frames "
+ "easing interpolation is applied to");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+ /* easing options */
+ prop = RNA_def_property(srna, "back", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "back");
+ RNA_def_property_ui_text(prop, "Back", "Amount of overshoot for 'back' easing");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+ prop = RNA_def_property(srna, "amplitude", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "amplitude");
+ RNA_def_property_range(prop, 0.0f, FLT_MAX); /* only positive values... */
+ RNA_def_property_ui_text(prop, "Amplitude", "Amount to boost elastic bounces for 'elastic' easing");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+ prop = RNA_def_property(srna, "period", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "period");
+ RNA_def_property_ui_text(prop, "Period", "Time between bounces for elastic easing");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+
+ /* custom curvemap */
+ prop = RNA_def_property(srna, "interpolation_curve", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "custom_ipo");
+ RNA_def_property_struct_type(prop, "CurveMapping");
+ RNA_def_property_ui_text(prop, "Interpolation Curve",
+ "Custom curve to control 'sequence' interpolation between Grease Pencil frames");
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
+}
+
/* Grease Pencil Drawing Brushes */
static void rna_def_gpencil_brush(BlenderRNA *brna)
{
@@ -3043,7 +3185,14 @@ static void rna_def_tool_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "gpencil_sculpt", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "gp_sculpt");
RNA_def_property_struct_type(prop, "GPencilSculptSettings");
- RNA_def_property_ui_text(prop, "Grease Pencil Sculpt", "");
+ RNA_def_property_ui_text(prop, "Grease Pencil Sculpt",
+ "Settings for stroke sculpting tools and brushes");
+
+ prop = RNA_def_property(srna, "gpencil_interpolate", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "gp_interpolate");
+ RNA_def_property_struct_type(prop, "GPencilInterpolateSettings");
+ RNA_def_property_ui_text(prop, "Grease Pencil Interpolate",
+ "Settings for Grease Pencil Interpolation tools");
/* Grease Pencil - Drawing brushes */
prop = RNA_def_property(srna, "gpencil_brushes", PROP_COLLECTION, PROP_NONE);
@@ -5419,15 +5568,17 @@ static void rna_def_layer_collection(BlenderRNA *brna)
/* Flags */
prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", COLLECTION_VISIBLE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, 1);
RNA_def_property_ui_text(prop, "Hide", "Restrict visiblity");
- RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollection_hide_update");
prop = RNA_def_property(srna, "hide_select", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", COLLECTION_SELECTABLE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, 1);
RNA_def_property_ui_text(prop, "Hide Selectable", "Restrict selection");
- RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollection_hide_select_update");
prop = RNA_def_property(srna, "is_unfolded", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", COLLECTION_FOLDED);
@@ -8083,6 +8234,7 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_define_animate_sdna(false);
rna_def_tool_settings(brna);
rna_def_gpencil_brush(brna);
+ rna_def_gpencil_interpolate(brna);
rna_def_unified_paint_settings(brna);
rna_def_curve_paint_settings(brna);
rna_def_statvis(brna);
diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c
index 7f405f0fb1f..40aea37d9d2 100644
--- a/source/blender/makesrna/intern/rna_sculpt_paint.c
+++ b/source/blender/makesrna/intern/rna_sculpt_paint.c
@@ -1047,15 +1047,6 @@ static void rna_def_gpencil_sculpt(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Affect Thickness", "The brush affects the thickness of the point");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
- prop = RNA_def_property(srna, "interpolate_all_layers", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSHEDIT_FLAG_INTERPOLATE_ALL_LAYERS);
- RNA_def_property_ui_text(prop, "Interpolate All Layers", "Interpolate all layers, not only active");
- RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
-
- prop = RNA_def_property(srna, "interpolate_selected_only", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSHEDIT_FLAG_INTERPOLATE_ONLY_SELECTED);
- RNA_def_property_ui_text(prop, "Interpolate Selected Strokes", "Interpolate only selected strokes in the original frame");
- RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
prop = RNA_def_property(srna, "selection_alpha", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "alpha");
diff --git a/source/blender/makesrna/intern/rna_sensor.c b/source/blender/makesrna/intern/rna_sensor.c
index ee24a434486..d0afab7a1e3 100644
--- a/source/blender/makesrna/intern/rna_sensor.c
+++ b/source/blender/makesrna/intern/rna_sensor.c
@@ -32,6 +32,7 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BLI_string_utils.h"
#include "BLT_translation.h"
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index e68e67586e9..0eab38faca8 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -3937,7 +3937,7 @@ static void rna_def_userdef_system(BlenderRNA *brna)
prop = RNA_def_property(srna, "dpi", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "dpi");
- RNA_def_property_range(prop, 48, 144);
+ RNA_def_property_range(prop, 16, 256);
RNA_def_property_ui_text(prop, "DPI", "Font size and resolution for display");
RNA_def_property_update(prop, 0, "rna_userdef_dpi_update");
diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c
index 567505ea45d..8efa4d63675 100644
--- a/source/blender/modifiers/intern/MOD_armature.c
+++ b/source/blender/modifiers/intern/MOD_armature.c
@@ -99,22 +99,6 @@ static void foreachObjectLink(
walk(userData, ob, &amd->object, IDWALK_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- ArmatureModifierData *amd = (ArmatureModifierData *) md;
-
- if (amd->object) {
- DagNode *curNode = dag_get_node(forest, amd->object);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Armature Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -221,7 +205,6 @@ ModifierTypeInfo modifierType_Armature = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index b049457e640..6017f964c26 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -101,40 +101,6 @@ static void foreachObjectLink(
walk(userData, ob, &amd->offset_ob, IDWALK_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob), DagNode *obNode)
-{
- ArrayModifierData *amd = (ArrayModifierData *) md;
-
- if (amd->start_cap) {
- DagNode *curNode = dag_get_node(forest, amd->start_cap);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
- }
- if (amd->end_cap) {
- DagNode *curNode = dag_get_node(forest, amd->end_cap);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
- }
- if (amd->curve_ob) {
- DagNode *curNode = dag_get_node(forest, amd->curve_ob);
- curNode->eval_flags |= DAG_EVAL_NEED_CURVE_PATH;
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
- }
- if (amd->offset_ob) {
- DagNode *curNode = dag_get_node(forest, amd->offset_ob);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Array Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *scene,
@@ -797,7 +763,6 @@ ModifierTypeInfo modifierType_Array = {
/* requiredDataMask */ NULL,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c
index 5874029ae08..17b0cd4d7f5 100644
--- a/source/blender/modifiers/intern/MOD_bevel.c
+++ b/source/blender/modifiers/intern/MOD_bevel.c
@@ -213,7 +213,6 @@ ModifierTypeInfo modifierType_Bevel = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ dependsOnNormals,
diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c
index da0f5aa3923..d2f19b78b50 100644
--- a/source/blender/modifiers/intern/MOD_boolean.c
+++ b/source/blender/modifiers/intern/MOD_boolean.c
@@ -104,22 +104,6 @@ static void foreachObjectLink(
walk(userData, ob, &bmd->object, IDWALK_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- BooleanModifierData *bmd = (BooleanModifierData *) md;
-
- if (bmd->object) {
- DagNode *curNode = dag_get_node(forest, bmd->object);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Boolean Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -459,7 +443,6 @@ ModifierTypeInfo modifierType_Boolean = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c
index a364eef2974..d2467a8fc4a 100644
--- a/source/blender/modifiers/intern/MOD_build.c
+++ b/source/blender/modifiers/intern/MOD_build.c
@@ -322,7 +322,6 @@ ModifierTypeInfo modifierType_Build = {
/* requiredDataMask */ NULL,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c
index 2fe27730370..16c5de45c49 100644
--- a/source/blender/modifiers/intern/MOD_cast.c
+++ b/source/blender/modifiers/intern/MOD_cast.c
@@ -105,22 +105,6 @@ static void foreachObjectLink(
walk(userData, ob, &cmd->object, IDWALK_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- CastModifierData *cmd = (CastModifierData *) md;
-
- if (cmd->object) {
- DagNode *curNode = dag_get_node(forest, cmd->object);
-
- dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA,
- "Cast Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -513,7 +497,6 @@ ModifierTypeInfo modifierType_Cast = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c
index d15a6fcb1c8..b6a7b5b57ec 100644
--- a/source/blender/modifiers/intern/MOD_cloth.c
+++ b/source/blender/modifiers/intern/MOD_cloth.c
@@ -117,20 +117,6 @@ static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData,
dm->release(dm);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- Scene *scene, Object *ob, DagNode *obNode)
-{
- ClothModifierData *clmd = (ClothModifierData *) md;
-
- if (clmd) {
- /* Actual code uses get_collisionobjects */
- dag_add_collision_relations(forest, scene, ob, obNode, clmd->coll_parms->group, ob->lay|scene->lay, eModifierType_Collision, NULL, true, "Cloth Collision");
-
- dag_add_forcefield_relations(forest, scene, ob, obNode, clmd->sim_parms->effector_weights, true, 0, "Cloth Field");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *scene,
@@ -256,7 +242,6 @@ ModifierTypeInfo modifierType_Cloth = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c
index e7ff0a90fbc..a2a4b2e1274 100644
--- a/source/blender/modifiers/intern/MOD_collision.c
+++ b/source/blender/modifiers/intern/MOD_collision.c
@@ -265,7 +265,6 @@ ModifierTypeInfo modifierType_Collision = {
/* requiredDataMask */ NULL,
/* freeData */ freeData,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c
index 77fd84a2948..0718b0f85fa 100644
--- a/source/blender/modifiers/intern/MOD_correctivesmooth.c
+++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c
@@ -759,7 +759,6 @@ ModifierTypeInfo modifierType_CorrectiveSmooth = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c
index 9bc96e593fd..3e9b46ad8ea 100644
--- a/source/blender/modifiers/intern/MOD_curve.c
+++ b/source/blender/modifiers/intern/MOD_curve.c
@@ -92,23 +92,6 @@ static void foreachObjectLink(
walk(userData, ob, &cmd->object, IDWALK_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- CurveModifierData *cmd = (CurveModifierData *) md;
-
- if (cmd->object) {
- DagNode *curNode = dag_get_node(forest, cmd->object);
- curNode->eval_flags |= DAG_EVAL_NEED_CURVE_PATH;
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Curve Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *scene,
@@ -178,7 +161,6 @@ ModifierTypeInfo modifierType_Curve = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c
index f5ab28d3d88..26952e1e0d5 100644
--- a/source/blender/modifiers/intern/MOD_datatransfer.c
+++ b/source/blender/modifiers/intern/MOD_datatransfer.c
@@ -127,22 +127,6 @@ static void foreachObjectLink(
walk(userData, ob, &dtmd->ob_source, IDWALK_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob), DagNode *obNode)
-{
- DataTransferModifierData *dtmd = (DataTransferModifierData *) md;
- DagNode *curNode;
-
- if (dtmd->ob_source) {
- curNode = dag_get_node(forest, dtmd->ob_source);
-
- dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
- "DataTransfer Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -251,7 +235,6 @@ ModifierTypeInfo modifierType_DataTransfer = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ dependsOnNormals,
diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c
index 617ae5a89f3..bcb52e4e0ca 100644
--- a/source/blender/modifiers/intern/MOD_decimate.c
+++ b/source/blender/modifiers/intern/MOD_decimate.c
@@ -227,7 +227,6 @@ ModifierTypeInfo modifierType_Decimate = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c
index 059e096ddb4..4b5181e9c61 100644
--- a/source/blender/modifiers/intern/MOD_displace.c
+++ b/source/blender/modifiers/intern/MOD_displace.c
@@ -157,31 +157,6 @@ static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
return ((!dmd->texture && dmd->direction == MOD_DISP_DIR_RGB_XYZ) || dmd->strength == 0.0f);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- DisplaceModifierData *dmd = (DisplaceModifierData *) md;
-
- if (dmd->map_object && dmd->texmapping == MOD_DISP_MAP_OBJECT) {
- DagNode *curNode = dag_get_node(forest, dmd->map_object);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Displace Modifier");
- }
-
-
- if (dmd->texmapping == MOD_DISP_MAP_GLOBAL ||
- (ELEM(dmd->direction, MOD_DISP_DIR_X, MOD_DISP_DIR_Y, MOD_DISP_DIR_Z, MOD_DISP_DIR_RGB_XYZ) &&
- dmd->space == MOD_DISP_SPACE_GLOBAL))
- {
- dag_add_relation(forest, obNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Displace Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -393,7 +368,6 @@ ModifierTypeInfo modifierType_Displace = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ dependsOnNormals,
diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c
index bde20e56748..ee6df153905 100644
--- a/source/blender/modifiers/intern/MOD_dynamicpaint.c
+++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c
@@ -119,27 +119,6 @@ static bool is_brush_cb(Object *UNUSED(ob), ModifierData *pmd)
return ((DynamicPaintModifierData*)pmd)->brush != NULL;
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *scene,
- Object *ob,
- DagNode *obNode)
-{
- DynamicPaintModifierData *pmd = (DynamicPaintModifierData *) md;
-
- /* add relation from canvases to all brush objects */
- if (pmd && pmd->canvas) {
- for (DynamicPaintSurface *surface = pmd->canvas->surfaces.first; surface; surface = surface->next) {
- if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) {
- dag_add_forcefield_relations(forest, scene, ob, obNode, surface->effector_weights, true, 0, "Dynamic Paint Field");
- }
-
- /* Actual code uses custom loop over group/scene without layer checks in dynamicPaint_doStep */
- dag_add_collision_relations(forest, scene, ob, obNode, surface->brush_group, -1, eModifierType_DynamicPaint, is_brush_cb, false, "Dynamic Paint Brush");
- }
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *scene,
@@ -214,7 +193,6 @@ ModifierTypeInfo modifierType_DynamicPaint = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c
index 4441edb299b..f239807a7d3 100644
--- a/source/blender/modifiers/intern/MOD_edgesplit.c
+++ b/source/blender/modifiers/intern/MOD_edgesplit.c
@@ -157,7 +157,6 @@ ModifierTypeInfo modifierType_EdgeSplit = {
/* requiredDataMask */ NULL,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c
index 38ffdaa709b..dea1f9d8d4c 100644
--- a/source/blender/modifiers/intern/MOD_explode.c
+++ b/source/blender/modifiers/intern/MOD_explode.c
@@ -1059,7 +1059,6 @@ ModifierTypeInfo modifierType_Explode = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_fluidsim.c b/source/blender/modifiers/intern/MOD_fluidsim.c
index c202c5e1cb4..bed25fa82db 100644
--- a/source/blender/modifiers/intern/MOD_fluidsim.c
+++ b/source/blender/modifiers/intern/MOD_fluidsim.c
@@ -100,33 +100,6 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
return result ? result : dm;
}
-static void updateDepgraph(
- ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain), Scene *scene,
- Object *ob, DagNode *obNode)
-{
- FluidsimModifierData *fluidmd = (FluidsimModifierData *) md;
- Base *base;
-
- if (fluidmd && fluidmd->fss) {
- if (fluidmd->fss->type == OB_FLUIDSIM_DOMAIN) {
- for (base = scene->base.first; base; base = base->next) {
- Object *ob1 = base->object;
- if (ob1 != ob) {
- FluidsimModifierData *fluidmdtmp =
- (FluidsimModifierData *)modifiers_findByType(ob1, eModifierType_Fluidsim);
-
- /* only put dependencies from NON-DOMAIN fluids in here */
- if (fluidmdtmp && fluidmdtmp->fss && (fluidmdtmp->fss->type != OB_FLUIDSIM_DOMAIN)) {
- DagNode *curNode = dag_get_node(forest, ob1);
- dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Fluidsim Object");
- }
- }
- }
- }
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *scene,
@@ -180,7 +153,6 @@ ModifierTypeInfo modifierType_Fluidsim = {
/* requiredDataMask */ NULL,
/* freeData */ freeData,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c
index 9186b10d8ca..13d94abc92d 100644
--- a/source/blender/modifiers/intern/MOD_hook.c
+++ b/source/blender/modifiers/intern/MOD_hook.c
@@ -118,24 +118,6 @@ static void foreachObjectLink(
walk(userData, ob, &hmd->object, IDWALK_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- HookModifierData *hmd = (HookModifierData *) md;
-
- if (hmd->object) {
- DagNode *curNode = dag_get_node(forest, hmd->object);
-
- if (hmd->subtarget[0])
- dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA | DAG_RL_DATA_DATA, "Hook Modifier");
- else
- dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA, "Hook Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -427,7 +409,6 @@ ModifierTypeInfo modifierType_Hook = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c
index ce3fdc4bbe8..56a2e217a2a 100644
--- a/source/blender/modifiers/intern/MOD_laplaciandeform.c
+++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c
@@ -775,7 +775,6 @@ ModifierTypeInfo modifierType_LaplacianDeform = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
index f1216ff462a..1295a75d9e7 100644
--- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c
+++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
@@ -561,7 +561,6 @@ ModifierTypeInfo modifierType_LaplacianSmooth = {
/* requiredDataMask */ required_data_mask,
/* freeData */ NULL,
/* isDisabled */ is_disabled,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c
index 7d4701e3ef2..292c2db61f8 100644
--- a/source/blender/modifiers/intern/MOD_lattice.c
+++ b/source/blender/modifiers/intern/MOD_lattice.c
@@ -91,22 +91,6 @@ static void foreachObjectLink(
walk(userData, ob, &lmd->object, IDWALK_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- LatticeModifierData *lmd = (LatticeModifierData *) md;
-
- if (lmd->object) {
- DagNode *latNode = dag_get_node(forest, lmd->object);
-
- dag_add_relation(forest, latNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Lattice Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -169,7 +153,6 @@ ModifierTypeInfo modifierType_Lattice = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_mask.c b/source/blender/modifiers/intern/MOD_mask.c
index 5e01a20d93b..7cb2f2c25d5 100644
--- a/source/blender/modifiers/intern/MOD_mask.c
+++ b/source/blender/modifiers/intern/MOD_mask.c
@@ -77,24 +77,6 @@ static void foreachObjectLink(
walk(userData, ob, &mmd->ob_arm, IDWALK_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- MaskModifierData *mmd = (MaskModifierData *)md;
-
- if (mmd->ob_arm) {
- bArmature *arm = (bArmature *)mmd->ob_arm->data;
- DagNode *armNode = dag_get_node(forest, mmd->ob_arm);
-
- /* tag relationship in depsgraph, but also on the armature */
- dag_add_relation(forest, armNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Mask Modifier");
- arm->flag |= ARM_HAS_VIZ_DEPS;
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -401,7 +383,6 @@ ModifierTypeInfo modifierType_Mask = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c
index aa3e3ebcf7e..0d96032c515 100644
--- a/source/blender/modifiers/intern/MOD_meshcache.c
+++ b/source/blender/modifiers/intern/MOD_meshcache.c
@@ -313,7 +313,6 @@ ModifierTypeInfo modifierType_MeshCache = {
/* requiredDataMask */ NULL,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c
index 3f34319d25f..27782b05cd2 100644
--- a/source/blender/modifiers/intern/MOD_meshdeform.c
+++ b/source/blender/modifiers/intern/MOD_meshdeform.c
@@ -122,23 +122,6 @@ static void foreachObjectLink(
walk(userData, ob, &mmd->object, IDWALK_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- MeshDeformModifierData *mmd = (MeshDeformModifierData *) md;
-
- if (mmd->object) {
- DagNode *curNode = dag_get_node(forest, mmd->object);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA | DAG_RL_DATA_OB | DAG_RL_OB_OB,
- "Mesh Deform Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -534,7 +517,6 @@ ModifierTypeInfo modifierType_MeshDeform = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c
index 2f00a7c71b0..985c365bb69 100644
--- a/source/blender/modifiers/intern/MOD_meshsequencecache.c
+++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c
@@ -155,23 +155,6 @@ static void foreachIDLink(ModifierData *md, Object *ob,
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *bmain,
- struct Scene *scene,
- Object *ob, DagNode *obNode)
-{
- MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *) md;
-
- if (mcmd->cache_file != NULL) {
- DagNode *curNode = dag_get_node(forest, mcmd->cache_file);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Cache File Modifier");
- }
-
- UNUSED_VARS(bmain, scene, ob);
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *bmain,
struct Scene *scene,
@@ -205,7 +188,6 @@ ModifierTypeInfo modifierType_MeshSequenceCache = {
/* requiredDataMask */ NULL,
/* freeData */ freeData,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c
index 88facb22e0e..9fdd75aeb68 100644
--- a/source/blender/modifiers/intern/MOD_mirror.c
+++ b/source/blender/modifiers/intern/MOD_mirror.c
@@ -75,21 +75,6 @@ static void foreachObjectLink(
walk(userData, ob, &mmd->mirror_ob, IDWALK_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- MirrorModifierData *mmd = (MirrorModifierData *) md;
-
- if (mmd->mirror_ob) {
- DagNode *latNode = dag_get_node(forest, mmd->mirror_ob);
-
- dag_add_relation(forest, latNode, obNode, DAG_RL_OB_DATA, "Mirror Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -375,7 +360,6 @@ ModifierTypeInfo modifierType_Mirror = {
/* requiredDataMask */ NULL,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c
index 90ad1bdfdc2..aba184b7d40 100644
--- a/source/blender/modifiers/intern/MOD_multires.c
+++ b/source/blender/modifiers/intern/MOD_multires.c
@@ -161,7 +161,6 @@ ModifierTypeInfo modifierType_Multires = {
/* requiredDataMask */ NULL,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_none.c b/source/blender/modifiers/intern/MOD_none.c
index d9d9ba2966d..3fb780f566d 100644
--- a/source/blender/modifiers/intern/MOD_none.c
+++ b/source/blender/modifiers/intern/MOD_none.c
@@ -67,7 +67,6 @@ ModifierTypeInfo modifierType_None = {
/* requiredDataMask */ NULL,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c
index 454c97451a8..eefca658305 100644
--- a/source/blender/modifiers/intern/MOD_normal_edit.c
+++ b/source/blender/modifiers/intern/MOD_normal_edit.c
@@ -511,20 +511,6 @@ static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
return !is_valid_target(enmd);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob), DagNode *obNode)
-{
- NormalEditModifierData *enmd = (NormalEditModifierData *) md;
-
- if (enmd->target) {
- DagNode *Node = dag_get_node(forest, enmd->target);
-
- dag_add_relation(forest, Node, obNode, DAG_RL_OB_DATA, "NormalEdit Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -562,7 +548,6 @@ ModifierTypeInfo modifierType_NormalEdit = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ dependsOnNormals,
diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c
index e77cc655c16..1be603c7ab5 100644
--- a/source/blender/modifiers/intern/MOD_ocean.c
+++ b/source/blender/modifiers/intern/MOD_ocean.c
@@ -597,7 +597,6 @@ ModifierTypeInfo modifierType_Ocean = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ dependsOnNormals,
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
index 4e78e758dc3..a468cc6600d 100644
--- a/source/blender/modifiers/intern/MOD_particleinstance.c
+++ b/source/blender/modifiers/intern/MOD_particleinstance.c
@@ -110,24 +110,6 @@ static bool isDisabled(ModifierData *md, int useRenderParams)
return false;
}
-
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
-
- if (pimd->ob) {
- DagNode *curNode = dag_get_node(forest, pimd->ob);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
- "Particle Instance Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -460,7 +442,6 @@ ModifierTypeInfo modifierType_ParticleInstance = {
/* requiredDataMask */ NULL,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c
index d8cccca415c..a3b9d808b17 100644
--- a/source/blender/modifiers/intern/MOD_particlesystem.c
+++ b/source/blender/modifiers/intern/MOD_particlesystem.c
@@ -231,7 +231,6 @@ ModifierTypeInfo modifierType_ParticleSystem = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_remesh.c b/source/blender/modifiers/intern/MOD_remesh.c
index b85898c07e9..fb5c12399a4 100644
--- a/source/blender/modifiers/intern/MOD_remesh.c
+++ b/source/blender/modifiers/intern/MOD_remesh.c
@@ -231,7 +231,6 @@ ModifierTypeInfo modifierType_Remesh = {
/* requiredDataMask */ NULL,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c
index 290e19736bb..a834d1b5cae 100644
--- a/source/blender/modifiers/intern/MOD_screw.c
+++ b/source/blender/modifiers/intern/MOD_screw.c
@@ -1057,24 +1057,6 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
return result;
}
-
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- ScrewModifierData *ltmd = (ScrewModifierData *) md;
-
- if (ltmd->ob_axis) {
- DagNode *curNode = dag_get_node(forest, ltmd->ob_axis);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
- "Screw Modifier");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -1118,7 +1100,6 @@ ModifierTypeInfo modifierType_Screw = {
/* requiredDataMask */ NULL,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_shapekey.c b/source/blender/modifiers/intern/MOD_shapekey.c
index 97aae733532..6c8bd06c196 100644
--- a/source/blender/modifiers/intern/MOD_shapekey.c
+++ b/source/blender/modifiers/intern/MOD_shapekey.c
@@ -138,7 +138,6 @@ ModifierTypeInfo modifierType_ShapeKey = {
/* requiredDataMask */ NULL,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c
index 633311c2b87..29bce2ef3a4 100644
--- a/source/blender/modifiers/intern/MOD_shrinkwrap.c
+++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c
@@ -143,23 +143,6 @@ static void deformVertsEM(ModifierData *md, Object *ob, struct BMEditMesh *editD
dm->release(dm);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *) md;
-
- if (smd->target)
- dag_add_relation(forest, dag_get_node(forest, smd->target), obNode,
- DAG_RL_OB_DATA | DAG_RL_DATA_DATA, "Shrinkwrap Modifier");
-
- if (smd->auxTarget)
- dag_add_relation(forest, dag_get_node(forest, smd->auxTarget), obNode,
- DAG_RL_OB_DATA | DAG_RL_DATA_DATA, "Shrinkwrap Modifier");
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -209,7 +192,6 @@ ModifierTypeInfo modifierType_Shrinkwrap = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ dependsOnNormals,
diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c
index c68f2651191..118d0117361 100644
--- a/source/blender/modifiers/intern/MOD_simpledeform.c
+++ b/source/blender/modifiers/intern/MOD_simpledeform.c
@@ -293,18 +293,6 @@ static void foreachObjectLink(
walk(userData, ob, &smd->origin, IDWALK_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- SimpleDeformModifierData *smd = (SimpleDeformModifierData *)md;
-
- if (smd->origin)
- dag_add_relation(forest, dag_get_node(forest, smd->origin), obNode, DAG_RL_OB_DATA, "SimpleDeform Modifier");
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -381,7 +369,6 @@ ModifierTypeInfo modifierType_SimpleDeform = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c
index 8ed623734be..4b84aeb335a 100644
--- a/source/blender/modifiers/intern/MOD_skin.c
+++ b/source/blender/modifiers/intern/MOD_skin.c
@@ -1950,7 +1950,6 @@ ModifierTypeInfo modifierType_Skin = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_smoke.c b/source/blender/modifiers/intern/MOD_smoke.c
index f04d7432a8f..637ed3ee390 100644
--- a/source/blender/modifiers/intern/MOD_smoke.c
+++ b/source/blender/modifiers/intern/MOD_smoke.c
@@ -129,22 +129,6 @@ static bool is_coll_cb(Object *UNUSED(ob), ModifierData *md)
return (smd->type & MOD_SMOKE_TYPE_COLL) && smd->coll;
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *scene, struct Object *ob,
- DagNode *obNode)
-{
- SmokeModifierData *smd = (SmokeModifierData *) md;
-
- if (smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
- /* Actual code uses get_collisionobjects */
- dag_add_collision_relations(forest, scene, ob, obNode, smd->domain->fluid_group, ob->lay|scene->lay, eModifierType_Smoke, is_flow_cb, true, "Smoke Flow");
- dag_add_collision_relations(forest, scene, ob, obNode, smd->domain->coll_group, ob->lay|scene->lay, eModifierType_Smoke, is_coll_cb, true, "Smoke Coll");
-
- dag_add_forcefield_relations(forest, scene, ob, obNode, smd->domain->effector_weights, true, PFIELD_SMOKEFLOW, "Smoke Force Field");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *scene,
@@ -202,7 +186,6 @@ ModifierTypeInfo modifierType_Smoke = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c
index d45c8528510..f0f20acb8ea 100644
--- a/source/blender/modifiers/intern/MOD_smooth.c
+++ b/source/blender/modifiers/intern/MOD_smooth.c
@@ -261,7 +261,6 @@ ModifierTypeInfo modifierType_Smooth = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_softbody.c b/source/blender/modifiers/intern/MOD_softbody.c
index 17adc7f1520..412f0a3ce53 100644
--- a/source/blender/modifiers/intern/MOD_softbody.c
+++ b/source/blender/modifiers/intern/MOD_softbody.c
@@ -62,18 +62,6 @@ static bool dependsOnTime(ModifierData *UNUSED(md))
return true;
}
-static void updateDepgraph(ModifierData *UNUSED(md), DagForest *forest,
- struct Main *UNUSED(bmain),
- Scene *scene, Object *ob, DagNode *obNode)
-{
- if (ob->soft) {
- /* Actual code uses ccd_build_deflector_hash */
- dag_add_collision_relations(forest, scene, ob, obNode, ob->soft->collision_group, ob->lay, eModifierType_Collision, NULL, false, "Softbody Collision");
-
- dag_add_forcefield_relations(forest, scene, ob, obNode, ob->soft->effector_weights, true, 0, "Softbody Field");
- }
-}
-
static void updateDepsgraph(ModifierData *UNUSED(md),
struct Main *UNUSED(bmain),
struct Scene *scene,
@@ -109,7 +97,6 @@ ModifierTypeInfo modifierType_Softbody = {
/* requiredDataMask */ NULL,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c
index 911b6997058..e589cb7d713 100644
--- a/source/blender/modifiers/intern/MOD_solidify.c
+++ b/source/blender/modifiers/intern/MOD_solidify.c
@@ -973,7 +973,6 @@ ModifierTypeInfo modifierType_Solidify = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ dependsOnNormals,
diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c
index 8711384e1ee..af3ffb820c1 100644
--- a/source/blender/modifiers/intern/MOD_subsurf.c
+++ b/source/blender/modifiers/intern/MOD_subsurf.c
@@ -211,7 +211,6 @@ ModifierTypeInfo modifierType_Subsurf = {
/* requiredDataMask */ NULL,
/* freeData */ freeData,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ dependsOnNormals,
diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c
index 68987a1d28e..fc02a2e1327 100644
--- a/source/blender/modifiers/intern/MOD_surface.c
+++ b/source/blender/modifiers/intern/MOD_surface.c
@@ -185,7 +185,6 @@ ModifierTypeInfo modifierType_Surface = {
/* requiredDataMask */ NULL,
/* freeData */ freeData,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c
index 6fad2756f82..a5d826a69ba 100644
--- a/source/blender/modifiers/intern/MOD_triangulate.c
+++ b/source/blender/modifiers/intern/MOD_triangulate.c
@@ -118,7 +118,6 @@ ModifierTypeInfo modifierType_Triangulate = {
/* requiredDataMask */ NULL, //requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c
index fb7668d16e0..54c25b687e1 100644
--- a/source/blender/modifiers/intern/MOD_uvproject.c
+++ b/source/blender/modifiers/intern/MOD_uvproject.c
@@ -105,25 +105,6 @@ static void foreachIDLink(ModifierData *md, Object *ob,
foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- UVProjectModifierData *umd = (UVProjectModifierData *) md;
- int i;
-
- for (i = 0; i < umd->num_projectors; ++i) {
- if (umd->projectors[i]) {
- DagNode *curNode = dag_get_node(forest, umd->projectors[i]);
-
- dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "UV Project Modifier");
- }
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -385,7 +366,6 @@ ModifierTypeInfo modifierType_UVProject = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c
index 89994c3ae22..2ac6892b7b8 100644
--- a/source/blender/modifiers/intern/MOD_uvwarp.c
+++ b/source/blender/modifiers/intern/MOD_uvwarp.c
@@ -238,18 +238,6 @@ static void uv_warp_deps_object_bone(DagForest *forest, DagNode *obNode,
}
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- UVWarpModifierData *umd = (UVWarpModifierData *) md;
-
- uv_warp_deps_object_bone(forest, obNode, umd->object_src, umd->bone_src);
- uv_warp_deps_object_bone(forest, obNode, umd->object_dst, umd->bone_dst);
-}
-
static void uv_warp_deps_object_bone_new(struct DepsNodeHandle *node,
Object *object,
const char *bonename)
@@ -293,7 +281,6 @@ ModifierTypeInfo modifierType_UVWarp = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c
index b38de140a91..13ce72ee2f5 100644
--- a/source/blender/modifiers/intern/MOD_warp.c
+++ b/source/blender/modifiers/intern/MOD_warp.c
@@ -135,27 +135,6 @@ static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void
walk(userData, ob, md, "texture");
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob), DagNode *obNode)
-{
- WarpModifierData *wmd = (WarpModifierData *) md;
-
- if (wmd->object_from && wmd->object_to) {
- DagNode *fromNode = dag_get_node(forest, wmd->object_from);
- DagNode *toNode = dag_get_node(forest, wmd->object_to);
-
- dag_add_relation(forest, fromNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Warp Modifier1");
- dag_add_relation(forest, toNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Warp Modifier2");
- }
-
- if ((wmd->texmapping == MOD_DISP_MAP_OBJECT) && wmd->map_object) {
- DagNode *curNode = dag_get_node(forest, wmd->map_object);
- dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Warp Modifier3");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -387,7 +366,6 @@ ModifierTypeInfo modifierType_Warp = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c
index 683649ed1c0..291913675c3 100644
--- a/source/blender/modifiers/intern/MOD_wave.c
+++ b/source/blender/modifiers/intern/MOD_wave.c
@@ -131,29 +131,6 @@ static void foreachTexLink(ModifierData *md, Object *ob,
walk(userData, ob, md, "texture");
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
-{
- WaveModifierData *wmd = (WaveModifierData *) md;
-
- if (wmd->objectcenter) {
- DagNode *curNode = dag_get_node(forest, wmd->objectcenter);
-
- dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA,
- "Wave Modifier");
- }
-
- if (wmd->map_object) {
- DagNode *curNode = dag_get_node(forest, wmd->map_object);
-
- dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA,
- "Wave Modifer");
- }
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -397,7 +374,6 @@ ModifierTypeInfo modifierType_Wave = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ NULL,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c
index 93567aed2c4..585b223d436 100644
--- a/source/blender/modifiers/intern/MOD_weightvgedit.c
+++ b/source/blender/modifiers/intern/MOD_weightvgedit.c
@@ -143,26 +143,6 @@ static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void
walk(userData, ob, md, "mask_texture");
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob), DagNode *obNode)
-{
- WeightVGEditModifierData *wmd = (WeightVGEditModifierData *) md;
- DagNode *curNode;
-
- if (wmd->mask_tex_map_obj && wmd->mask_tex_mapping == MOD_DISP_MAP_OBJECT) {
- curNode = dag_get_node(forest, wmd->mask_tex_map_obj);
-
- dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
- "WeightVGEdit Modifier");
- }
-
- if (wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL)
- dag_add_relation(forest, obNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
- "WeightVGEdit Modifier");
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -307,7 +287,6 @@ ModifierTypeInfo modifierType_WeightVGEdit = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c
index 170fbbed7f1..a6adf72e4eb 100644
--- a/source/blender/modifiers/intern/MOD_weightvgmix.c
+++ b/source/blender/modifiers/intern/MOD_weightvgmix.c
@@ -192,26 +192,6 @@ static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void
walk(userData, ob, md, "mask_texture");
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob), DagNode *obNode)
-{
- WeightVGMixModifierData *wmd = (WeightVGMixModifierData *) md;
- DagNode *curNode;
-
- if (wmd->mask_tex_map_obj && wmd->mask_tex_mapping == MOD_DISP_MAP_OBJECT) {
- curNode = dag_get_node(forest, wmd->mask_tex_map_obj);
-
- dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
- "WeightVGMix Modifier");
- }
-
- if (wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL)
- dag_add_relation(forest, obNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
- "WeightVGMix Modifier");
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -439,7 +419,6 @@ ModifierTypeInfo modifierType_WeightVGMix = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index af59f11ba15..b26cbc3a7d3 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -343,32 +343,6 @@ static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void
walk(userData, ob, md, "mask_texture");
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob), DagNode *obNode)
-{
- WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *) md;
- DagNode *curNode;
-
- if (wmd->proximity_ob_target) {
- curNode = dag_get_node(forest, wmd->proximity_ob_target);
- dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
- "WeightVGProximity Modifier");
- }
-
- if (wmd->mask_tex_map_obj && wmd->mask_tex_mapping == MOD_DISP_MAP_OBJECT) {
- curNode = dag_get_node(forest, wmd->mask_tex_map_obj);
-
- dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
- "WeightVGProximity Modifier");
- }
-
- if (wmd->mask_tex_mapping == MOD_DISP_MAP_GLOBAL)
- dag_add_relation(forest, obNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
- "WeightVGProximity Modifier");
-}
-
static void updateDepsgraph(ModifierData *md,
struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
@@ -617,7 +591,6 @@ ModifierTypeInfo modifierType_WeightVGProximity = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ freeData,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ updateDepgraph,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_wireframe.c b/source/blender/modifiers/intern/MOD_wireframe.c
index adadd4834d4..0c295f91012 100644
--- a/source/blender/modifiers/intern/MOD_wireframe.c
+++ b/source/blender/modifiers/intern/MOD_wireframe.c
@@ -132,7 +132,6 @@ ModifierTypeInfo modifierType_Wireframe = {
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
- /* updateDepgraph */ NULL,
/* updateDepsgraph */ NULL,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ dependsOnNormals,
diff --git a/source/blender/nodes/composite/nodes/node_composite_outputFile.c b/source/blender/nodes/composite/nodes/node_composite_outputFile.c
index 7d1087435c2..6a96f1b30d8 100644
--- a/source/blender/nodes/composite/nodes/node_composite_outputFile.c
+++ b/source/blender/nodes/composite/nodes/node_composite_outputFile.c
@@ -32,7 +32,7 @@
#include <string.h>
#include "BLI_utildefines.h"
-#include "BLI_path_util.h"
+#include "BLI_string_utils.h"
#include "BKE_context.h"
diff --git a/source/blender/nodes/shader/nodes/node_shader_light_path.c b/source/blender/nodes/shader/nodes/node_shader_light_path.c
index b1001cd3937..052f2a66ec8 100644
--- a/source/blender/nodes/shader/nodes/node_shader_light_path.c
+++ b/source/blender/nodes/shader/nodes/node_shader_light_path.c
@@ -39,6 +39,8 @@ static bNodeSocketTemplate sh_node_light_path_out[] = {
{ SOCK_FLOAT, 0, N_("Is Transmission Ray"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_("Ray Length"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_("Ray Depth"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 0, N_("Diffuse Depth"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 0, N_("Glossy Depth"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_("Transparent Depth"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 0, N_("Transmission Depth"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{ -1, 0, "" }
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index 7021477a702..f535aa5aa71 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -97,9 +97,10 @@ typedef struct RenderPass {
} RenderPass;
enum {
- RENDER_PASS_DEBUG_BVH_TRAVERSAL_STEPS = 0,
+ RENDER_PASS_DEBUG_BVH_TRAVERSED_NODES = 0,
RENDER_PASS_DEBUG_BVH_TRAVERSED_INSTANCES = 1,
RENDER_PASS_DEBUG_RAY_BOUNCES = 2,
+ RENDER_PASS_DEBUG_BVH_INTERSECTIONS = 3,
};
/* a renderlayer is a full image, but with all passes and samples */
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 86961cdd169..263ea3d4ef2 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -5569,12 +5569,17 @@ static void calculate_speedvectors(Render *re, ObjectInstanceRen *obi, float *ve
/* interpolate speed vectors from strand surface */
face= mesh->face[*index];
- co1= mesh->co[face[0]];
- co2= mesh->co[face[1]];
- co3= mesh->co[face[2]];
- co4= (face[3])? mesh->co[face[3]]: NULL;
+ co1 = mesh->co[face[0]];
+ co2 = mesh->co[face[1]];
+ co3 = mesh->co[face[2]];
- interp_weights_face_v3(w, co1, co2, co3, co4, strand->vert->co);
+ if (face[3]) {
+ co4 = mesh->co[face[3]];
+ interp_weights_quad_v3(w, co1, co2, co3, co4, strand->vert->co);
+ }
+ else {
+ interp_weights_tri_v3(w, co1, co2, co3, strand->vert->co);
+ }
zero_v4(speed);
madd_v4_v4fl(speed, winspeed[face[0]], w[0]);
diff --git a/source/blender/render/intern/source/occlusion.c b/source/blender/render/intern/source/occlusion.c
index ddcd2e84520..cd93898d846 100644
--- a/source/blender/render/intern/source/occlusion.c
+++ b/source/blender/render/intern/source/occlusion.c
@@ -1190,9 +1190,14 @@ static void sample_occ_surface(ShadeInput *shi)
co1 = mesh->co[face[0]];
co2 = mesh->co[face[1]];
co3 = mesh->co[face[2]];
- co4 = (face[3]) ? mesh->co[face[3]] : NULL;
- interp_weights_face_v3(w, co1, co2, co3, co4, strand->vert->co);
+ if (face[3]) {
+ co4 = mesh->co[face[3]];
+ interp_weights_quad_v3(w, co1, co2, co3, co4, strand->vert->co);
+ }
+ else {
+ interp_weights_tri_v3(w, co1, co2, co3, strand->vert->co);
+ }
zero_v3(shi->ao);
zero_v3(shi->env);
diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c
index 2be6238eeec..f276c01e86a 100644
--- a/source/blender/render/intern/source/render_result.c
+++ b/source/blender/render/intern/source/render_result.c
@@ -550,10 +550,12 @@ RenderPass *gp_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int pas
const char *RE_debug_pass_name_get(int debug_type)
{
switch (debug_type) {
- case RENDER_PASS_DEBUG_BVH_TRAVERSAL_STEPS:
- return "BVH Traversal Steps";
+ case RENDER_PASS_DEBUG_BVH_TRAVERSED_NODES:
+ return "BVH Traversed Nodes";
case RENDER_PASS_DEBUG_BVH_TRAVERSED_INSTANCES:
return "BVH Traversed Instances";
+ case RENDER_PASS_DEBUG_BVH_INTERSECTIONS:
+ return "BVH Primitive Intersections";
case RENDER_PASS_DEBUG_RAY_BOUNCES:
return "Ray Bounces";
}
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 7c68a0ce438..a8abc3bb54f 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -1850,7 +1850,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
BLENDER_VERSION / 100, BLENDER_VERSION % 100);
uiItemStringO(col, IFACE_("Release Log"), ICON_URL, "WM_OT_url_open", "url", url);
uiItemStringO(col, IFACE_("Manual"), ICON_URL, "WM_OT_url_open", "url",
- "http://www.blender.org/manual");
+ "https://docs.blender.org/manual/en/dev/");
uiItemStringO(col, IFACE_("Blender Website"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org");
if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "release")) {
BLI_snprintf(url, sizeof(url), "http://www.blender.org/documentation/blender_python_api_%d_%d"
@@ -4603,4 +4603,3 @@ EnumPropertyItem *RNA_mask_local_itemf(bContext *C, PointerRNA *ptr, PropertyRNA
{
return rna_id_itemf(C, ptr, r_free, C ? (ID *)CTX_data_main(C)->mask.first : NULL, true);
}
-
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator.c
index 824141d1c40..7fdbb0d6324 100644
--- a/source/blender/windowmanager/manipulators/intern/wm_manipulator.c
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator.c
@@ -31,8 +31,8 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BLI_path_util.h"
#include "BLI_string.h"
+#include "BLI_string_utils.h"
#include "ED_screen.h"
#include "ED_view3d.h"
diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c
index 06119b35e37..3b6cd1c9561 100644
--- a/source/creator/creator_args.c
+++ b/source/creator/creator_args.c
@@ -55,8 +55,6 @@
#include "BKE_sound.h"
#include "BKE_image.h"
-#include "DEG_depsgraph.h"
-
#ifdef WITH_FFMPEG
#include "IMB_imbuf.h"
#endif
@@ -438,7 +436,7 @@ static void arg_py_context_restore(
* see: `doc/manpage/blender.1.py`
* - Parsed and extracted for the manual,
* which converts our ad-hoc formatting to reStructuredText.
- * see: http://www.blender.org/manual/advanced/command_line.html
+ * see: https://docs.blender.org/manual/en/dev/advanced/command_line.html
*
* \{ */
@@ -587,7 +585,6 @@ static int arg_handle_print_help(int UNUSED(argc), const char **UNUSED(argv), vo
printf("\n");
printf("Experimental Features:\n");
- BLI_argsPrintArgDoc(ba, "--enable-new-depsgraph");
BLI_argsPrintArgDoc(ba, "--enable-new-basic-shader-glsl");
/* Other options _must_ be last (anything not handled will show here) */
@@ -1185,16 +1182,6 @@ static int arg_handle_threads_set(int argc, const char **argv, void *UNUSED(data
}
}
-static const char arg_handle_depsgraph_use_new_doc[] =
-"\n\tUse new dependency graph"
-;
-static int arg_handle_depsgraph_use_new(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
-{
- printf("Using new dependency graph.\n");
- DEG_depsgraph_switch_to_new();
- return 0;
-}
-
static const char arg_handle_basic_shader_use_legacy_doc[] =
"\n\tUse legacy (non-GLSL) basic shader"
;
@@ -1840,7 +1827,6 @@ void main_args_setup(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
BLI_argsAdd(ba, 1, NULL, "--debug-gpumem",
CB_EX(arg_handle_debug_mode_generic_set, gpumem), (void *)G_DEBUG_GPU_MEM);
- BLI_argsAdd(ba, 1, NULL, "--enable-new-depsgraph", CB(arg_handle_depsgraph_use_new), NULL);
BLI_argsAdd(ba, 1, NULL, "--enable-legacy-basic-shader", CB(arg_handle_basic_shader_use_legacy), NULL);
BLI_argsAdd(ba, 1, NULL, "--verbose", CB(arg_handle_verbosity_set), NULL);
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index 4751e60996d..6add30f1131 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -1740,7 +1740,7 @@ static void blenderSceneSetBackground(Scene *blenderscene)
for (SETLOOPER(blenderscene, it, base)) {
base->object->lay = base->lay;
- base->object->flag = base->flag;
+ BKE_scene_base_flag_sync_from_base(base);
}
}
diff --git a/source/tools b/source/tools
-Subproject 896c5f78952adb2d091d28c65086d46992dabda
+Subproject 6bbb68073bfa11e94bb0b3623db38f847037add