diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2017-01-25 14:28:52 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2017-01-25 14:28:52 +0300 |
commit | 72ff78a9515255c1b687ad3fd63d169ef5c27355 (patch) | |
tree | 56ae2d118761dcc7080a8282e35715d8b83852d3 /source | |
parent | c5ed9434791ec01a65756cd182e15f8744b7e6f3 (diff) | |
parent | 95e9790704c61cb26171f4c7c84673eacd5ac3bd (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')
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 |