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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Tönne <lukas.toenne@gmail.com>2018-01-03 13:24:05 +0300
committerLukas Tönne <lukas.toenne@gmail.com>2018-01-03 13:24:05 +0300
commit36fac1e27ccc143a56bcf9ce35c236d5762e79fc (patch)
tree8def2e87a2c0f3905fde99af557b7a640dad9457 /source/blender
parent2a7dfcd927c78d675bcde3d3ca9d417e0eae6704 (diff)
parent060fdb49d64857ff1cbf9937420ed70b10b17086 (diff)
Merge branch 'blender2.8' into hair_guides
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/alembic/intern/abc_customdata.cc6
-rw-r--r--source/blender/blenkernel/BKE_font.h2
-rw-r--r--source/blender/blenkernel/BKE_freestyle.h2
-rw-r--r--source/blender/blenkernel/BKE_layer.h1
-rw-r--r--source/blender/blenkernel/BKE_object.h9
-rw-r--r--source/blender/blenkernel/BKE_paint.h2
-rw-r--r--source/blender/blenkernel/BKE_tracking.h40
-rw-r--r--source/blender/blenkernel/intern/collection.c96
-rw-r--r--source/blender/blenkernel/intern/context.c22
-rw-r--r--source/blender/blenkernel/intern/curve.c25
-rw-r--r--source/blender/blenkernel/intern/font.c13
-rw-r--r--source/blender/blenkernel/intern/freestyle.c10
-rw-r--r--source/blender/blenkernel/intern/group.c5
-rw-r--r--source/blender/blenkernel/intern/layer.c9
-rw-r--r--source/blender/blenkernel/intern/mesh.c18
-rw-r--r--source/blender/blenkernel/intern/object.c28
-rw-r--r--source/blender/blenkernel/intern/object_dupli.c2
-rw-r--r--source/blender/blenkernel/intern/paint.c7
-rw-r--r--source/blender/blenkernel/intern/particle.c2
-rw-r--r--source/blender/blenkernel/intern/scene.c2
-rw-r--r--source/blender/blenkernel/intern/tracking.c152
-rw-r--r--source/blender/blenlib/BLI_math_rotation.h5
-rw-r--r--source/blender/blenlib/intern/math_bits_inline.c4
-rw-r--r--source/blender/blenlib/intern/math_rotation.c66
-rw-r--r--source/blender/blenloader/intern/versioning_280.c44
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c20
-rw-r--r--source/blender/depsgraph/CMakeLists.txt9
-rw-r--r--source/blender/depsgraph/DEG_depsgraph.h6
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_debug.h9
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_query.h13
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder.cc1
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_cycle.cc59
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc4
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc1
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_transitive.cc16
-rw-r--r--source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc (renamed from source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc)37
-rw-r--r--source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc157
-rw-r--r--source/blender/depsgraph/intern/depsgraph.cc21
-rw-r--r--source/blender/depsgraph/intern/depsgraph.h2
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build.cc1
-rw-r--r--source/blender/depsgraph/intern/depsgraph_debug.cc3
-rw-r--r--source/blender/depsgraph/intern/depsgraph_eval.cc4
-rw-r--r--source/blender/depsgraph/intern/depsgraph_intern.h9
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query.cc1
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query_foreach.cc1
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query_iter.cc19
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc458
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval.cc132
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc1
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_flush.cc18
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_stats.cc70
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_stats.h40
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node.cc244
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node.h109
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_component.cc43
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_component.h61
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_id.cc217
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_id.h81
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_operation.cc2
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_operation.h3
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_time.cc46
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_time.h52
-rw-r--r--source/blender/draw/DRW_engine.h1
-rw-r--r--source/blender/draw/engines/clay/clay_engine.c71
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c15
-rw-r--r--source/blender/draw/intern/DRW_render.h4
-rw-r--r--source/blender/draw/intern/draw_cache_impl_curve.c5
-rw-r--r--source/blender/draw/intern/draw_cache_impl_displist.c100
-rw-r--r--source/blender/draw/intern/draw_cache_impl_metaball.c3
-rw-r--r--source/blender/draw/intern/draw_manager.c50
-rw-r--r--source/blender/draw/modes/object_mode.c13
-rw-r--r--source/blender/editors/include/UI_interface.h8
-rw-r--r--source/blender/editors/interface/interface_handlers.c11
-rw-r--r--source/blender/editors/interface/interface_intern.h3
-rw-r--r--source/blender/editors/interface/interface_region_tooltip.c254
-rw-r--r--source/blender/editors/interface/interface_templates.c60
-rw-r--r--source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c7
-rw-r--r--source/blender/editors/mesh/editmesh_add.c111
-rw-r--r--source/blender/editors/object/object_add.c1
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c10
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c11
-rw-r--r--source/blender/editors/space_clip/clip_intern.h2
-rw-r--r--source/blender/editors/space_clip/clip_utils.c58
-rw-r--r--source/blender/editors/space_clip/tracking_ops.c9
-rw-r--r--source/blender/editors/space_info/space_info.c20
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c108
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c10
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h3
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c6
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c49
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c9
-rw-r--r--source/blender/editors/space_view3d/drawobject.c7
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_navigate.c22
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c18
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c4
-rw-r--r--source/blender/editors/transform/transform_manipulator.c2
-rw-r--r--source/blender/makesdna/DNA_ID.h20
-rw-r--r--source/blender/makesdna/DNA_object_types.h8
-rw-r--r--source/blender/makesrna/intern/rna_ID.c1
-rw-r--r--source/blender/makesrna/intern/rna_context.c6
-rw-r--r--source/blender/makesrna/intern/rna_depsgraph.c29
-rw-r--r--source/blender/makesrna/intern/rna_layer.c9
-rw-r--r--source/blender/makesrna/intern/rna_object.c16
-rw-r--r--source/blender/makesrna/intern/rna_particle.c5
-rw-r--r--source/blender/makesrna/intern/rna_rna.c2
-rw-r--r--source/blender/makesrna/intern/rna_tracking.c147
-rw-r--r--source/blender/makesrna/intern/rna_wm.c4
-rw-r--r--source/blender/modifiers/intern/MOD_surfacedeform.c4
-rw-r--r--source/blender/render/intern/source/convertblender.c3
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c19
-rw-r--r--source/blender/windowmanager/manipulators/WM_manipulator_api.h9
-rw-r--r--source/blender/windowmanager/manipulators/WM_manipulator_types.h2
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulator.c2
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c192
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h3
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c55
118 files changed, 2776 insertions, 1371 deletions
diff --git a/source/blender/alembic/intern/abc_customdata.cc b/source/blender/alembic/intern/abc_customdata.cc
index d6e7a80d174..8b526616053 100644
--- a/source/blender/alembic/intern/abc_customdata.cc
+++ b/source/blender/alembic/intern/abc_customdata.cc
@@ -235,17 +235,19 @@ static void read_uvs(const CDStreamConfig &config, void *data,
MPoly *mpolys = config.mpoly;
MLoopUV *mloopuvs = static_cast<MLoopUV *>(data);
- unsigned int uv_index, loop_index;
+ unsigned int uv_index, loop_index, rev_loop_index;
for (int i = 0; i < config.totpoly; ++i) {
MPoly &poly = mpolys[i];
+ unsigned int rev_loop_offset = poly.loopstart + poly.totloop - 1;
for (int f = 0; f < poly.totloop; ++f) {
loop_index = poly.loopstart + f;
+ rev_loop_index = rev_loop_offset - f;
uv_index = (*indices)[loop_index];
const Imath::V2f &uv = (*uvs)[uv_index];
- MLoopUV &loopuv = mloopuvs[loop_index];
+ MLoopUV &loopuv = mloopuvs[rev_loop_index];
loopuv.uv[0] = uv[0];
loopuv.uv[1] = uv[1];
}
diff --git a/source/blender/blenkernel/BKE_font.h b/source/blender/blenkernel/BKE_font.h
index 60ad061bf77..e5eea4423c9 100644
--- a/source/blender/blenkernel/BKE_font.h
+++ b/source/blender/blenkernel/BKE_font.h
@@ -86,7 +86,7 @@ struct VFont *BKE_vfont_load_exists(struct Main *bmain, const char *filepath);
void BKE_vfont_make_local(struct Main *bmain, struct VFont *vfont, const bool lib_local);
-bool BKE_vfont_to_curve_ex(struct Main *bmain, struct Object *ob, int mode,
+bool BKE_vfont_to_curve_ex(struct Main *bmain, struct Object *ob, struct Curve *cu, int mode,
struct ListBase *r_nubase,
const wchar_t **r_text, int *r_text_len, bool *r_text_free,
struct CharTrans **r_chartransdata);
diff --git a/source/blender/blenkernel/BKE_freestyle.h b/source/blender/blenkernel/BKE_freestyle.h
index 1045fde0039..f7368683d93 100644
--- a/source/blender/blenkernel/BKE_freestyle.h
+++ b/source/blender/blenkernel/BKE_freestyle.h
@@ -49,7 +49,7 @@ typedef struct FreestyleModuleSettings FreestyleModuleSettings;
/* FreestyleConfig */
void BKE_freestyle_config_init(FreestyleConfig *config);
-void BKE_freestyle_config_free(FreestyleConfig *config);
+void BKE_freestyle_config_free(FreestyleConfig *config, const bool do_id_user);
void BKE_freestyle_config_copy(FreestyleConfig *new_config, FreestyleConfig *config, const int flag);
/* FreestyleConfig.modules */
diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h
index 6a762c9b711..77f760a7843 100644
--- a/source/blender/blenkernel/BKE_layer.h
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -66,6 +66,7 @@ struct ViewLayer *BKE_view_layer_group_add(struct Group *group);
struct ViewLayer *BKE_view_layer_context_active_PLACEHOLDER(const struct Scene *scene);
void BKE_view_layer_free(struct ViewLayer *view_layer);
+void BKE_view_layer_free_ex(struct ViewLayer *view_layer, const bool do_id_user);
void BKE_view_layer_selected_objects_tag(struct ViewLayer *view_layer, const int tag);
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 2b183906f57..d98c52aa91a 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -82,7 +82,14 @@ bool BKE_object_exists_check(struct Object *obtest);
bool BKE_object_is_in_editmode(struct Object *ob);
bool BKE_object_is_in_editmode_vgroup(struct Object *ob);
bool BKE_object_is_in_wpaint_select_vert(struct Object *ob);
-bool BKE_object_is_visible(struct Object *ob);
+
+typedef enum eObjectVisibilityCheck {
+ OB_VISIBILITY_CHECK_FOR_VIEWPORT,
+ OB_VISIBILITY_CHECK_FOR_RENDER,
+ OB_VISIBILITY_CHECK_UNKNOWN_RENDER_MODE,
+} eObjectVisibilityCheck;
+
+bool BKE_object_is_visible(struct Object *ob, const eObjectVisibilityCheck mode);
void BKE_object_init(struct Object *ob);
struct Object *BKE_object_add_only_object(
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 31f4695201c..b8fde8bd68e 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -157,7 +157,7 @@ float paint_grid_paint_mask(const struct GridPaintMask *gpm, unsigned level,
unsigned x, unsigned y);
/* stroke related */
-void paint_calculate_rake_rotation(struct UnifiedPaintSettings *ups, struct Brush *brush, const float mouse_pos[2]);
+bool paint_calculate_rake_rotation(struct UnifiedPaintSettings *ups, struct Brush *brush, const float mouse_pos[2]);
void paint_update_brush_rake_rotation(struct UnifiedPaintSettings *ups, struct Brush *brush, float rotation);
void BKE_paint_stroke_get_average(struct Scene *scene, struct Object *ob, float stroke[3]);
diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h
index b4ca1b79238..5da87de1cc9 100644
--- a/source/blender/blenkernel/BKE_tracking.h
+++ b/source/blender/blenkernel/BKE_tracking.h
@@ -289,6 +289,46 @@ void BKE_tracking_stabilization_data_to_mat4(int width, int height, float aspect
void BKE_tracking_dopesheet_tag_update(struct MovieTracking *tracking);
void BKE_tracking_dopesheet_update(struct MovieTracking *tracking);
+/* **** Query/search **** */
+
+struct MovieTrackingObject *BKE_tracking_find_object_for_track(
+ const struct MovieTracking *tracking,
+ const struct MovieTrackingTrack *track);
+struct ListBase *BKE_tracking_find_tracks_list_for_track(
+ struct MovieTracking *tracking,
+ const struct MovieTrackingTrack *track);
+
+struct MovieTrackingObject *BKE_tracking_find_object_for_plane_track(
+ const struct MovieTracking *tracking,
+ const struct MovieTrackingPlaneTrack *plane_track);
+struct ListBase *BKE_tracking_find_tracks_list_for_plane_track(
+ struct MovieTracking *tracking,
+ const struct MovieTrackingPlaneTrack *plane_track);
+
+
+void BKE_tracking_get_rna_path_for_track(
+ const struct MovieTracking *tracking,
+ const struct MovieTrackingTrack *track,
+ char *rna_path,
+ size_t rna_path_len);
+void BKE_tracking_get_rna_path_prefix_for_track(
+ const struct MovieTracking *tracking,
+ const struct MovieTrackingTrack *track,
+ char *rna_path,
+ size_t rna_path_len);
+void BKE_tracking_get_rna_path_for_plane_track(
+ const struct MovieTracking *tracking,
+ const struct MovieTrackingPlaneTrack *plane_track,
+ char *rna_path,
+ size_t rna_path_len);
+void BKE_tracking_get_rna_path_prefix_for_plane_track(
+ const struct MovieTracking *tracking,
+ const struct MovieTrackingPlaneTrack *plane_track,
+ char *rna_path,
+ size_t rna_path_len);
+
+/* **** Utility macros **** */
+
#define TRACK_SELECTED(track) ((track)->flag & SELECT || (track)->pat_flag & SELECT || (track)->search_flag & SELECT)
#define TRACK_AREA_SELECTED(track, area) ((area) == TRACK_AREA_POINT ? (track)->flag & SELECT : \
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index 8d69563f5ff..e2b10de575c 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -50,6 +50,7 @@
#include "MEM_guardedalloc.h"
/* Prototypes. */
+static SceneCollection *find_collection_parent(const struct SceneCollection *sc_child, struct SceneCollection *sc_parent);
static bool is_collection_in_tree(const struct SceneCollection *sc_reference, struct SceneCollection *sc_parent);
static SceneCollection *collection_master_from_id(const ID *owner_id)
@@ -69,24 +70,35 @@ static SceneCollection *collection_master_from_id(const ID *owner_id)
* Add a collection to a collection ListBase and syncronize all render layers
* The ListBase is NULL when the collection is to be added to the master collection
*/
-SceneCollection *BKE_collection_add(ID *owner_id, SceneCollection *sc_parent, const int type, const char *name)
+SceneCollection *BKE_collection_add(ID *owner_id, SceneCollection *sc_parent, const int type, const char *name_custom)
{
SceneCollection *sc_master = collection_master_from_id(owner_id);
SceneCollection *sc = MEM_callocN(sizeof(SceneCollection), "New Collection");
sc->type = type;
-
- if (!name) {
- name = DATA_("New Collection");
- }
+ const char *name = name_custom;
if (!sc_parent) {
sc_parent = sc_master;
}
- BKE_collection_rename((Scene *)owner_id, sc, name);
+ if (!name) {
+ if (sc_parent == sc_master) {
+ name = BLI_sprintfN("Collection %d", BLI_listbase_count(&sc_master->scene_collections) + 1);
+ }
+ else {
+ name = BLI_sprintfN("%s %d", sc_parent->name, BLI_listbase_count(&sc_parent->scene_collections) + 1);
+ }
+ }
+
BLI_addtail(&sc_parent->scene_collections, sc);
+ BKE_collection_rename((Scene *)owner_id, sc, name);
BKE_layer_sync_new_scene_collection(owner_id, sc_parent, sc);
+
+ if (name != name_custom) {
+ MEM_freeN((char *)name);
+ }
+
return sc;
}
@@ -164,6 +176,8 @@ static void layer_collection_remove(ViewLayer *view_layer, ListBase *lb, const S
/**
* Remove a collection from the scene, and syncronize all render layers
+ *
+ * If an object is in any other collection, link the object to the master collection.
*/
bool BKE_collection_remove(ID *owner_id, SceneCollection *sc)
{
@@ -174,11 +188,50 @@ bool BKE_collection_remove(ID *owner_id, SceneCollection *sc)
return false;
}
+ /* We need to do bottom up removal, otherwise we get a crash when we remove a collection that
+ * has one of its nested collections linked to a view layer. */
+ SceneCollection *scene_collection_nested = sc->scene_collections.first;
+ while (scene_collection_nested != NULL) {
+ SceneCollection *scene_collection_next = scene_collection_nested->next;
+ BKE_collection_remove(owner_id, scene_collection_nested);
+ scene_collection_nested = scene_collection_next;
+ }
+
/* Unlink from the respective collection tree. */
if (!collection_remlink(sc_master, sc)) {
BLI_assert(false);
}
+ /* If an object is no longer in any collection, we add it to the master collection. */
+ ListBase collection_objects;
+ BLI_duplicatelist(&collection_objects, &sc->objects);
+
+ FOREACH_SCENE_COLLECTION(owner_id, scene_collection_iter)
+ {
+ if (scene_collection_iter == sc) {
+ continue;
+ }
+
+ LinkData *link_next, *link = collection_objects.first;
+ while (link) {
+ link_next = link->next;
+
+ if (BLI_findptr(&scene_collection_iter->objects, link->data, offsetof(LinkData, data))) {
+ BLI_remlink(&collection_objects, link);
+ MEM_freeN(link);
+ }
+
+ link = link_next;
+ }
+ }
+ FOREACH_SCENE_COLLECTION_END
+
+ for (LinkData *link = collection_objects.first; link; link = link->next) {
+ BKE_collection_object_add(owner_id, sc_master, link->data);
+ }
+
+ BLI_freelistN(&collection_objects);
+
/* Clear the collection items. */
collection_free(sc, true);
@@ -243,38 +296,11 @@ SceneCollection *BKE_collection_master(const ID *owner_id)
return master_collection_from_id(owner_id);
}
-struct UniqueNameCheckData {
- ListBase *lb;
- SceneCollection *lookup_sc;
-};
-
-static bool collection_unique_name_check(void *arg, const char *name)
-{
- struct UniqueNameCheckData *data = arg;
-
- for (SceneCollection *sc = data->lb->first; sc; sc = sc->next) {
- struct UniqueNameCheckData child_data = {.lb = &sc->scene_collections, .lookup_sc = data->lookup_sc};
-
- if (sc != data->lookup_sc) {
- if (STREQ(sc->name, name)) {
- return true;
- }
- }
- if (collection_unique_name_check(&child_data, name)) {
- return true;
- }
- }
-
- return false;
-}
-
static void collection_rename(const ID *owner_id, SceneCollection *sc, const char *name)
{
- SceneCollection *sc_master = collection_master_from_id(owner_id);
- struct UniqueNameCheckData data = {.lb = &sc_master->scene_collections, .lookup_sc = sc};
-
+ SceneCollection *sc_parent = find_collection_parent(sc, collection_master_from_id(owner_id));
BLI_strncpy(sc->name, name, sizeof(sc->name));
- BLI_uniquename_cb(collection_unique_name_check, &data, DATA_("Collection"), '.', sc->name, sizeof(sc->name));
+ BLI_uniquename(&sc_parent->scene_collections, sc, DATA_("Collection"), '.', offsetof(SceneCollection, name), sizeof(sc->name));
}
void BKE_collection_rename(const Scene *scene, SceneCollection *sc, const char *name)
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 3c326a77f2b..b9a8ea67a0a 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -968,11 +968,11 @@ RenderEngineType *CTX_data_engine_type(const bContext *C)
LayerCollection *CTX_data_layer_collection(const bContext *C)
{
ViewLayer *view_layer = CTX_data_view_layer(C);
- LayerCollection *lc;
+ LayerCollection *layer_collection;
- if (ctx_data_pointer_verify(C, "layer_collection", (void *)&lc)) {
- if (BKE_view_layer_has_collection(view_layer, lc->scene_collection)) {
- return lc;
+ if (ctx_data_pointer_verify(C, "layer_collection", (void *)&layer_collection)) {
+ if (BKE_view_layer_has_collection(view_layer, layer_collection->scene_collection)) {
+ return layer_collection;
}
}
@@ -982,16 +982,14 @@ LayerCollection *CTX_data_layer_collection(const bContext *C)
SceneCollection *CTX_data_scene_collection(const bContext *C)
{
- SceneCollection *sc;
- if (ctx_data_pointer_verify(C, "scene_collection", (void *)&sc)) {
- if (BKE_view_layer_has_collection(CTX_data_view_layer(C), sc)) {
- return sc;
- }
+ SceneCollection *scene_collection;
+ if (ctx_data_pointer_verify(C, "scene_collection", (void *)&scene_collection)) {
+ return scene_collection;
}
- LayerCollection *lc = CTX_data_layer_collection(C);
- if (lc) {
- return lc->scene_collection;
+ LayerCollection *layer_collection = CTX_data_layer_collection(C);
+ if (layer_collection) {
+ return layer_collection->scene_collection;
}
/* fallback */
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index ba9ccf94303..5a284761814 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -4938,12 +4938,27 @@ void BKE_curve_nurb_vert_active_validate(Curve *cu)
bool BKE_curve_minmax(Curve *cu, bool use_radius, float min[3], float max[3])
{
ListBase *nurb_lb = BKE_curve_nurbs_get(cu);
- Nurb *nu;
-
- for (nu = nurb_lb->first; nu; nu = nu->next)
+ ListBase temp_nurb_lb = {NULL, NULL};
+ const bool is_font = (BLI_listbase_is_empty(nurb_lb)) && (cu->len != 0);
+ /* For font curves we generate temp list of splines.
+ *
+ * This is likely to be fine, this function is not supposed to be called
+ * often, and it's the only way to get meaningful bounds for fonts.
+ */
+ if (is_font) {
+ nurb_lb = &temp_nurb_lb;
+ BKE_vfont_to_curve_ex(G.main, NULL, cu, FO_EDIT, nurb_lb,
+ NULL, NULL, NULL, NULL);
+ use_radius = false;
+ }
+ /* Do bounding box based on splines. */
+ for (Nurb *nu = nurb_lb->first; nu; nu = nu->next) {
BKE_nurb_minmax(nu, use_radius, min, max);
-
- return (BLI_listbase_is_empty(nurb_lb) == false);
+ }
+ const bool result = (BLI_listbase_is_empty(nurb_lb) == false);
+ /* Cleanup if needed. */
+ BKE_nurbList_free(&temp_nurb_lb);
+ return result;
}
bool BKE_curve_center_median(Curve *cu, float cent[3])
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
index d6b28cfaf70..ef479d77915 100644
--- a/source/blender/blenkernel/intern/font.c
+++ b/source/blender/blenkernel/intern/font.c
@@ -635,11 +635,10 @@ struct TempLineInfo {
int wspace_nr; /* number of whitespaces of line */
};
-bool BKE_vfont_to_curve_ex(Main *bmain, Object *ob, int mode, ListBase *r_nubase,
+bool BKE_vfont_to_curve_ex(Main *bmain, Object *ob, Curve *cu, int mode, ListBase *r_nubase,
const wchar_t **r_text, int *r_text_len, bool *r_text_free,
struct CharTrans **r_chartransdata)
{
- Curve *cu = ob->data;
EditFont *ef = cu->editfont;
EditFontSelBox *selboxes = NULL;
VFont *vfont, *oldvfont;
@@ -670,7 +669,7 @@ bool BKE_vfont_to_curve_ex(Main *bmain, Object *ob, int mode, ListBase *r_nubase
/* remark: do calculations including the trailing '\0' of a string
* because the cursor can be at that location */
- BLI_assert(ob->type == OB_FONT);
+ BLI_assert(ob == NULL || ob->type == OB_FONT);
/* Set font data */
vfont = cu->vfont;
@@ -708,7 +707,7 @@ bool BKE_vfont_to_curve_ex(Main *bmain, Object *ob, int mode, ListBase *r_nubase
if (cu->tb == NULL)
cu->tb = MEM_callocN(MAXTEXTBOX * sizeof(TextBox), "TextBox compat");
- if (ef) {
+ if (ef != NULL && ob != NULL) {
if (ef->selboxes)
MEM_freeN(ef->selboxes);
@@ -1258,7 +1257,7 @@ makebreak:
cha = towupper(cha);
}
- if (info->mat_nr > (ob->totcol)) {
+ if (ob == NULL || info->mat_nr > (ob->totcol)) {
/* printf("Error: Illegal material index (%d) in text object, setting to 0\n", info->mat_nr); */
info->mat_nr = 0;
}
@@ -1334,7 +1333,7 @@ bool BKE_vfont_to_curve_nubase(Main *bmain, Object *ob, int mode, ListBase *r_nu
{
BLI_assert(ob->type == OB_FONT);
- return BKE_vfont_to_curve_ex(bmain, ob, mode, r_nubase,
+ return BKE_vfont_to_curve_ex(bmain, ob, ob->data, mode, r_nubase,
NULL, NULL, NULL, NULL);
}
@@ -1342,7 +1341,7 @@ bool BKE_vfont_to_curve(Main *bmain, Object *ob, int mode)
{
Curve *cu = ob->data;
- return BKE_vfont_to_curve_ex(bmain, ob, mode, &cu->nurb, NULL, NULL, NULL, NULL);
+ return BKE_vfont_to_curve_ex(bmain, ob, ob->data, mode, &cu->nurb, NULL, NULL, NULL, NULL);
}
diff --git a/source/blender/blenkernel/intern/freestyle.c b/source/blender/blenkernel/intern/freestyle.c
index 686fe3bda93..b656d2cf7c0 100644
--- a/source/blender/blenkernel/intern/freestyle.c
+++ b/source/blender/blenkernel/intern/freestyle.c
@@ -61,17 +61,21 @@ void BKE_freestyle_config_init(FreestyleConfig *config)
BLI_listbase_clear(&config->linesets);
}
-void BKE_freestyle_config_free(FreestyleConfig *config)
+void BKE_freestyle_config_free(FreestyleConfig *config, const bool do_id_user)
{
FreestyleLineSet *lineset;
for (lineset = (FreestyleLineSet *)config->linesets.first; lineset; lineset = lineset->next) {
if (lineset->group) {
- id_us_min(&lineset->group->id);
+ if (do_id_user) {
+ id_us_min(&lineset->group->id);
+ }
lineset->group = NULL;
}
if (lineset->linestyle) {
- id_us_min(&lineset->linestyle->id);
+ if (do_id_user) {
+ id_us_min(&lineset->linestyle->id);
+ }
lineset->linestyle = NULL;
}
}
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
index 5b55433c1b9..8295fafba56 100644
--- a/source/blender/blenkernel/intern/group.c
+++ b/source/blender/blenkernel/intern/group.c
@@ -88,10 +88,7 @@ void BKE_group_init(Group *group)
BKE_collection_unlink(group->view_layer, group->view_layer->layer_collections.first);
/* Create and link a new default collection. */
- SceneCollection *defaut_collection = BKE_collection_add(&group->id,
- NULL,
- COLLECTION_TYPE_GROUP_INTERNAL,
- "Default Collection");
+ SceneCollection *defaut_collection = BKE_collection_add(&group->id, NULL, COLLECTION_TYPE_GROUP_INTERNAL, NULL);
BKE_collection_link(group->view_layer, defaut_collection);
}
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index 2e6cd769db8..288dcb34439 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -163,10 +163,15 @@ ViewLayer *BKE_view_layer_group_add(Group *group)
return view_layer;
}
+void BKE_view_layer_free(ViewLayer *view_layer)
+{
+ BKE_view_layer_free_ex(view_layer, true);
+}
+
/**
* Free (or release) any data used by this ViewLayer.
*/
-void BKE_view_layer_free(ViewLayer *view_layer)
+void BKE_view_layer_free_ex(ViewLayer *view_layer, const bool do_id_user)
{
view_layer->basact = NULL;
@@ -205,7 +210,7 @@ void BKE_view_layer_free(ViewLayer *view_layer)
MEM_SAFE_FREE(view_layer->stats);
- BKE_freestyle_config_free(&view_layer->freestyle_config);
+ BKE_freestyle_config_free(&view_layer->freestyle_config, do_id_user);
if (view_layer->id_properties) {
IDP_FreeProperty(view_layer->id_properties);
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 8f41f0611d4..24ed97ccfc1 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -1436,6 +1436,17 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use
me->totcol = cu->totcol;
me->mat = cu->mat;
+ /* Copy evaluated texture space from curve to mesh.
+ *
+ * Note that we disable auto texture space feature since that will cause
+ * texture space to evaluate differently for curve and mesh, since curve
+ * uses CV to calculate bounding box, and mesh uses what is coming from
+ * tessellated curve.
+ */
+ me->texflag = cu->texflag & ~CU_AUTOSPACE;
+ copy_v3_v3(me->loc, cu->loc);
+ copy_v3_v3(me->size, cu->size);
+ copy_v3_v3(me->rot, cu->rot);
BKE_mesh_texspace_calc(me);
cu->mat = NULL;
@@ -2460,6 +2471,11 @@ Mesh *BKE_mesh_new_from_object(
/* copies the data */
copycu = tmpobj->data = BKE_curve_copy(bmain, (Curve *) ob->data);
+ /* make sure texture space is calculated for a copy of curve,
+ * it will be used for the final result.
+ */
+ BKE_curve_texspace_calc(copycu);
+
/* temporarily set edit so we get updates from edit mode, but
* also because for text datablocks copying it while in edit
* mode gives invalid data structures */
@@ -2490,8 +2506,6 @@ Mesh *BKE_mesh_new_from_object(
return NULL;
}
- BKE_mesh_texspace_copy_from_object(tmpmesh, ob);
-
BKE_libblock_free_us(bmain, tmpobj);
/* XXX The curve to mesh conversion is convoluted... But essentially, BKE_mesh_from_nurbs_displist()
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index ab09ccf5654..ddc73a4427a 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -566,11 +566,32 @@ bool BKE_object_is_in_wpaint_select_vert(Object *ob)
/**
* Return if the object is visible, as evaluated by depsgraph
- * Keep in sync with rna_object.c (object.is_visible).
*/
-bool BKE_object_is_visible(Object *ob)
+bool BKE_object_is_visible(Object *ob, const eObjectVisibilityCheck mode)
{
- return (ob->base_flag & BASE_VISIBLED) != 0;
+ if ((ob->base_flag & BASE_VISIBLED) == 0) {
+ return false;
+ }
+
+ if (mode == OB_VISIBILITY_CHECK_UNKNOWN_RENDER_MODE) {
+ return true;
+ }
+
+ if (((ob->transflag & OB_DUPLI) == 0) &&
+ (ob->particlesystem.first == NULL))
+ {
+ return true;
+ }
+
+ switch (mode) {
+ case OB_VISIBILITY_CHECK_FOR_VIEWPORT:
+ return ((ob->duplicator_visibility_flag & OB_DUPLI_FLAG_VIEWPORT) != 0);
+ case OB_VISIBILITY_CHECK_FOR_RENDER:
+ return ((ob->duplicator_visibility_flag & OB_DUPLI_FLAG_RENDER) != 0);
+ default:
+ BLI_assert(!"Object visible test mode not supported.");
+ return false;
+ }
}
bool BKE_object_exists_check(Object *obtest)
@@ -700,6 +721,7 @@ void BKE_object_init(Object *ob)
ob->col_group = 0x01;
ob->col_mask = 0xffff;
ob->preview = NULL;
+ ob->duplicator_visibility_flag = OB_DUPLI_FLAG_VIEWPORT | OB_DUPLI_FLAG_RENDER;
/* NT fluid sim defaults */
ob->fluidsimSettings = NULL;
diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c
index 9b25a1db6ff..13589866e48 100644
--- a/source/blender/blenkernel/intern/object_dupli.c
+++ b/source/blender/blenkernel/intern/object_dupli.c
@@ -613,7 +613,7 @@ static void make_duplis_font(const DupliContext *ctx)
/* in par the family name is stored, use this to find the other objects */
- BKE_vfont_to_curve_ex(G.main, par, FO_DUPLI, NULL,
+ BKE_vfont_to_curve_ex(G.main, par, par->data, FO_DUPLI, NULL,
&text, &text_len, &text_free, &chartransdata);
if (text == NULL || chartransdata == NULL) {
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index c88642a8164..11702236066 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -641,8 +641,9 @@ void paint_update_brush_rake_rotation(UnifiedPaintSettings *ups, Brush *brush, f
ups->brush_rotation_sec = 0.0f;
}
-void paint_calculate_rake_rotation(UnifiedPaintSettings *ups, Brush *brush, const float mouse_pos[2])
+bool paint_calculate_rake_rotation(UnifiedPaintSettings *ups, Brush *brush, const float mouse_pos[2])
{
+ bool ok = false;
if ((brush->mtex.brush_angle_mode & MTEX_ANGLE_RAKE) || (brush->mask_mtex.brush_angle_mode & MTEX_ANGLE_RAKE)) {
const float r = RAKE_THRESHHOLD;
float rotation;
@@ -658,16 +659,20 @@ void paint_calculate_rake_rotation(UnifiedPaintSettings *ups, Brush *brush, cons
ups->last_rake_angle = rotation;
paint_update_brush_rake_rotation(ups, brush, rotation);
+ ok = true;
}
/* make sure we reset here to the last rotation to avoid accumulating
* values in case a random rotation is also added */
else {
paint_update_brush_rake_rotation(ups, brush, ups->last_rake_angle);
+ ok = false;
}
}
else {
ups->brush_rotation = ups->brush_rotation_sec = 0.0f;
+ ok = true;
}
+ return ok;
}
void BKE_sculptsession_free_deformMats(SculptSession *ss)
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 9bdf0acb1c3..b14c752fec3 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -3284,7 +3284,7 @@ static void default_particle_settings(ParticleSettings *part)
part->clength = 1.0f;
part->clength_thres = 0.0f;
- part->draw = PART_DRAW_EMITTER;
+ part->draw = 0;
part->draw_line[0] = 0.5;
part->path_start = 0.0f;
part->path_end = 1.0f;
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 22c3da09f13..a462e5b215c 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -540,7 +540,7 @@ void BKE_scene_free_ex(Scene *sce, const bool do_id_user)
view_layer_next = view_layer->next;
BLI_remlink(&sce->view_layers, view_layer);
- BKE_view_layer_free(view_layer);
+ BKE_view_layer_free_ex(view_layer, do_id_user);
}
/* Master Collection */
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index 07e071df04a..ebd4c04e8ce 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -2905,3 +2905,155 @@ void BKE_tracking_dopesheet_update(MovieTracking *tracking)
dopesheet->ok = true;
}
+
+/* NOTE: Returns NULL if the track comes from camera object, */
+MovieTrackingObject *BKE_tracking_find_object_for_track(
+ const MovieTracking *tracking,
+ const MovieTrackingTrack *track)
+{
+ const ListBase *tracksbase = &tracking->tracks;
+ if (BLI_findindex(tracksbase, track) != -1) {
+ return NULL;
+ }
+ MovieTrackingObject *object = tracking->objects.first;
+ while (object != NULL) {
+ if (BLI_findindex(&object->tracks, track) != -1) {
+ return object;
+ }
+ object = object->next;
+ }
+ return NULL;
+}
+
+ListBase *BKE_tracking_find_tracks_list_for_track(
+ MovieTracking *tracking,
+ const MovieTrackingTrack *track)
+{
+ MovieTrackingObject *object = BKE_tracking_find_object_for_track(tracking,
+ track);
+ if (object != NULL) {
+ return &object->tracks;
+ }
+ return &tracking->tracks;
+}
+
+/* NOTE: Returns NULL if the track comes from camera object, */
+MovieTrackingObject *BKE_tracking_find_object_for_plane_track(
+ const MovieTracking *tracking,
+ const MovieTrackingPlaneTrack *plane_track)
+{
+ const ListBase *plane_tracks_base = &tracking->plane_tracks;
+ if (BLI_findindex(plane_tracks_base, plane_track) != -1) {
+ return NULL;
+ }
+ MovieTrackingObject *object = tracking->objects.first;
+ while (object != NULL) {
+ if (BLI_findindex(&object->plane_tracks, plane_track) != -1) {
+ return object;
+ }
+ object = object->next;
+ }
+ return NULL;
+}
+
+ListBase *BKE_tracking_find_tracks_list_for_plane_track(
+ MovieTracking *tracking,
+ const MovieTrackingPlaneTrack *plane_track)
+{
+ MovieTrackingObject *object =
+ BKE_tracking_find_object_for_plane_track(tracking, plane_track);
+ if (object != NULL) {
+ return &object->plane_tracks;
+ }
+ return &tracking->plane_tracks;
+}
+
+void BKE_tracking_get_rna_path_for_track(
+ const struct MovieTracking *tracking,
+ const struct MovieTrackingTrack *track,
+ char *rna_path,
+ size_t rna_path_len)
+{
+ MovieTrackingObject *object =
+ BKE_tracking_find_object_for_track(tracking, track);
+ char track_name_esc[MAX_NAME * 2];
+ BLI_strescape(track_name_esc, track->name, sizeof(track_name_esc));
+ if (object == NULL) {
+ BLI_snprintf(rna_path, rna_path_len,
+ "tracking.tracks[\"%s\"]",
+ track_name_esc);
+ }
+ else {
+ char object_name_esc[MAX_NAME * 2];
+ BLI_strescape(object_name_esc, object->name, sizeof(object_name_esc));
+ BLI_snprintf(rna_path, rna_path_len,
+ "tracking.objects[\"%s\"].tracks[\"%s\"]",
+ object_name_esc,
+ track_name_esc);
+ }
+}
+
+void BKE_tracking_get_rna_path_prefix_for_track(
+ const struct MovieTracking *tracking,
+ const struct MovieTrackingTrack *track,
+ char *rna_path,
+ size_t rna_path_len)
+{
+ MovieTrackingObject *object =
+ BKE_tracking_find_object_for_track(tracking, track);
+ if (object == NULL) {
+ BLI_snprintf(rna_path, rna_path_len, "tracking.tracks");
+ }
+ else {
+ char object_name_esc[MAX_NAME * 2];
+ BLI_strescape(object_name_esc, object->name, sizeof(object_name_esc));
+ BLI_snprintf(rna_path, rna_path_len,
+ "tracking.objects[\"%s\"]",
+ object_name_esc);
+ }
+}
+
+void BKE_tracking_get_rna_path_for_plane_track(
+ const struct MovieTracking *tracking,
+ const struct MovieTrackingPlaneTrack *plane_track,
+ char *rna_path,
+ size_t rna_path_len)
+{
+ MovieTrackingObject *object =
+ BKE_tracking_find_object_for_plane_track(tracking, plane_track);
+ char track_name_esc[MAX_NAME * 2];
+ BLI_strescape(track_name_esc, plane_track->name, sizeof(track_name_esc));
+ if (object == NULL) {
+ BLI_snprintf(rna_path, rna_path_len,
+ "tracking.plane_tracks[\"%s\"]",
+ track_name_esc);
+ }
+ else {
+ char object_name_esc[MAX_NAME * 2];
+ BLI_strescape(object_name_esc, object->name, sizeof(object_name_esc));
+ BLI_snprintf(rna_path, rna_path_len,
+ "tracking.objects[\"%s\"].plane_tracks[\"%s\"]",
+ object_name_esc,
+ track_name_esc);
+ }
+}
+
+void BKE_tracking_get_rna_path_prefix_for_plane_track(
+ const struct MovieTracking *tracking,
+ const struct MovieTrackingPlaneTrack *plane_track,
+ char *rna_path,
+ size_t rna_path_len)
+{
+ MovieTrackingObject *object =
+ BKE_tracking_find_object_for_plane_track(tracking, plane_track);
+ if (object == NULL) {
+ BLI_snprintf(rna_path, rna_path_len, "tracking.plane_tracks");
+ }
+ else {
+ char object_name_esc[MAX_NAME * 2];
+ BLI_strescape(object_name_esc, object->name, sizeof(object_name_esc));
+ BLI_snprintf(rna_path, rna_path_len,
+ "tracking.objects[\"%s\"].plane_tracks",
+ object_name_esc);
+ }
+}
diff --git a/source/blender/blenlib/BLI_math_rotation.h b/source/blender/blenlib/BLI_math_rotation.h
index e059327a490..1f206e5e234 100644
--- a/source/blender/blenlib/BLI_math_rotation.h
+++ b/source/blender/blenlib/BLI_math_rotation.h
@@ -97,6 +97,11 @@ float angle_normalized_qtqt(const float q1[4], const float q2[4]);
float angle_qt(const float q[4]);
float angle_qtqt(const float q1[4], const float q2[4]);
+float angle_signed_normalized_qt(const float q[4]);
+float angle_signed_normalized_qtqt(const float q1[4], const float q2[4]);
+float angle_signed_qt(const float q[4]);
+float angle_signed_qtqt(const float q1[4], const float q2[4]);
+
/* TODO: don't what this is, but it's not the same as mat3_to_quat */
void mat3_to_quat_is_ok(float q[4], float mat[3][3]);
diff --git a/source/blender/blenlib/intern/math_bits_inline.c b/source/blender/blenlib/intern/math_bits_inline.c
index d96cf969dae..37fdcd7878a 100644
--- a/source/blender/blenlib/intern/math_bits_inline.c
+++ b/source/blender/blenlib/intern/math_bits_inline.c
@@ -25,6 +25,10 @@
#ifndef __MATH_BITS_INLINE_C__
#define __MATH_BITS_INLINE_C__
+#ifdef _MSC_VER
+# include <intrin.h>
+#endif
+
#include "BLI_math_bits.h"
MINLINE int bitscan_forward_i(int a)
diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c
index 23bd5e60e22..29e7cf32ddc 100644
--- a/source/blender/blenlib/intern/math_rotation.c
+++ b/source/blender/blenlib/intern/math_rotation.c
@@ -511,6 +511,14 @@ void rotation_between_quats_to_quat(float q[4], const float q1[4], const float q
}
+/* -------------------------------------------------------------------- */
+/** \name Quaternion Angle
+ *
+ * Unlike the angle between vectors, this does NOT return the shortest angle.
+ * See signed functions below for this.
+ *
+ * \{ */
+
float angle_normalized_qt(const float q[4])
{
BLI_ASSERT_UNIT_QUAT(q);
@@ -548,6 +556,64 @@ float angle_qtqt(const float q1[4], const float q2[4])
return angle_normalized_qtqt(quat1, quat2);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Quaternion Angle (Signed)
+ *
+ * Angles with quaternion calculation can exceed 180d,
+ * Having signed versions of these functions allows 'fabsf(angle_signed_qtqt(...))'
+ * to give us the shortest angle between quaternions.
+ * With higher precision than subtracting pi afterwards.
+ *
+ * \{ */
+
+float angle_signed_normalized_qt(const float q[4])
+{
+ BLI_ASSERT_UNIT_QUAT(q);
+ if (q[0] >= 0.0f) {
+ return 2.0f * saacos(q[0]);
+ }
+ else {
+ return -2.0f * saacos(-q[0]);
+ }
+}
+
+float angle_signed_normalized_qtqt(const float q1[4], const float q2[4])
+{
+ if (dot_qtqt(q1, q2) >= 0.0f) {
+ return angle_normalized_qtqt(q1, q2);
+ }
+ else {
+ float q2_copy[4];
+ negate_v4_v4(q2_copy, q2);
+ return -angle_normalized_qtqt(q1, q2_copy);
+ }
+}
+
+float angle_signed_qt(const float q[4])
+{
+ float tquat[4];
+
+ normalize_qt_qt(tquat, q);
+
+ return angle_signed_normalized_qt(tquat);
+}
+
+float angle_signed_qtqt(const float q1[4], const float q2[4])
+{
+ if (dot_qtqt(q1, q2) >= 0.0f) {
+ return angle_qtqt(q1, q2);
+ }
+ else {
+ float q2_copy[4];
+ negate_v4_v4(q2_copy, q2);
+ return -angle_qtqt(q1, q2_copy);
+ }
+}
+
+/** \} */
+
void vec_to_quat(float q[4], const float vec[3], short axis, const short upflag)
{
const float eps = 1e-4f;
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 944ddf1763d..31d3b48aee0 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -45,6 +45,7 @@
#include "DNA_lightprobe_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_view3d_types.h"
@@ -351,7 +352,7 @@ void do_versions_after_linking_280(Main *main)
view_layer->pass_xor = srl->pass_xor;
view_layer->pass_alpha_threshold = srl->pass_alpha_threshold;
- BKE_freestyle_config_free(&view_layer->freestyle_config);
+ BKE_freestyle_config_free(&view_layer->freestyle_config, true);
view_layer->freestyle_config = srl->freestyleConfig;
view_layer->id_properties = srl->prop;
@@ -424,7 +425,7 @@ void do_versions_after_linking_280(Main *main)
IDP_FreeProperty(srl->prop);
MEM_freeN(srl->prop);
}
- BKE_freestyle_config_free(&srl->freestyleConfig);
+ BKE_freestyle_config_free(&srl->freestyleConfig, true);
}
}
BLI_freelistN(&scene->r.layers);
@@ -481,11 +482,6 @@ void do_versions_after_linking_280(Main *main)
base->lay = base->object->lay;
}
- /* Fallback name if only one layer was found in the original file */
- if (BLI_listbase_is_single(&sc_master->scene_collections)) {
- BKE_collection_rename(scene, sc_master->scene_collections.first, "Default Collection");
- }
-
/* remove bases once and for all */
for (Base *base = scene->base.first; base; base = base->next) {
id_us_min(&base->object->id);
@@ -544,7 +540,7 @@ void do_versions_after_linking_280(Main *main)
IDP_FreeProperty(srl->prop);
MEM_freeN(srl->prop);
}
- BKE_freestyle_config_free(&srl->freestyleConfig);
+ BKE_freestyle_config_free(&srl->freestyleConfig, true);
}
BLI_freelistN(&scene->r.layers);
}
@@ -602,6 +598,38 @@ void do_versions_after_linking_280(Main *main)
}
}
}
+
+ {
+ for (Object *object = main->object.first; object; object = object->id.next) {
+#ifndef VERSION_280_SUBVERSION_4
+ /* If any object already has an initialized value for
+ * duplicator_visibility_flag it means we've already doversioned it.
+ * TODO(all) remove the VERSION_280_SUBVERSION_4 code once the subversion was bumped. */
+ if (object->duplicator_visibility_flag != 0) {
+ break;
+ }
+#endif
+ if (object->particlesystem.first) {
+ object->duplicator_visibility_flag = OB_DUPLI_FLAG_VIEWPORT;
+ for (ParticleSystem *psys = object->particlesystem.first; psys; psys=psys->next) {
+ if (psys->part->draw & PART_DRAW_EMITTER) {
+ object->duplicator_visibility_flag |= OB_DUPLI_FLAG_RENDER;
+#ifndef VERSION_280_SUBVERSION_4
+ psys->part->draw &= ~PART_DRAW_EMITTER;
+#else
+ break;
+#endif
+ }
+ }
+ }
+ else if (object->transflag & OB_DUPLI){
+ object->duplicator_visibility_flag = OB_DUPLI_FLAG_VIEWPORT;
+ }
+ else {
+ object->duplicator_visibility_flag = OB_DUPLI_FLAG_VIEWPORT | OB_DUPLI_FLAG_RENDER;
+ }
+ }
+ }
}
static void do_version_layer_collections_idproperties(ListBase *lb)
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 2c6213dacce..d00d0d508c7 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -718,14 +718,18 @@ static void slide_dist(EdgeHalf *e, BMVert *v, float d, float slideco[3])
/* Is co not on the edge e? if not, return the closer end of e in ret_closer_v */
static bool is_outside_edge(EdgeHalf *e, const float co[3], BMVert **ret_closer_v)
{
- float d_squared;
-
- d_squared = dist_squared_to_line_segment_v3(co, e->e->v1->co, e->e->v2->co);
- if (d_squared > BEVEL_EPSILON_BIG * BEVEL_EPSILON_BIG) {
- if (len_squared_v3v3(co, e->e->v1->co) > len_squared_v3v3(co, e->e->v2->co))
- *ret_closer_v = e->e->v2;
- else
- *ret_closer_v = e->e->v1;
+ float h[3], u[3], lambda, lenu, *l1 = e->e->v1->co;
+
+ sub_v3_v3v3(u, e->e->v2->co, l1);
+ sub_v3_v3v3(h, co, l1);
+ lenu = normalize_v3(u);
+ lambda = dot_v3v3(u, h);
+ if (lambda <= -BEVEL_EPSILON_BIG * lenu) {
+ *ret_closer_v = e->e->v1;
+ return true;
+ }
+ else if (lambda >= (1.0f + BEVEL_EPSILON_BIG) * lenu) {
+ *ret_closer_v = e->e->v2;
return true;
}
else {
diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt
index 9495321a0ff..c42d06bd0a2 100644
--- a/source/blender/depsgraph/CMakeLists.txt
+++ b/source/blender/depsgraph/CMakeLists.txt
@@ -53,13 +53,17 @@ set(SRC
intern/builder/deg_builder_relations_rig.cc
intern/builder/deg_builder_relations_view_layer.cc
intern/builder/deg_builder_transitive.cc
- intern/debug/deg_debug_graphviz.cc
+ intern/debug/deg_debug_relations_graphviz.cc
+ intern/debug/deg_debug_stats_gnuplot.cc
intern/eval/deg_eval.cc
intern/eval/deg_eval_copy_on_write.cc
intern/eval/deg_eval_flush.cc
+ intern/eval/deg_eval_stats.cc
intern/nodes/deg_node.cc
intern/nodes/deg_node_component.cc
+ intern/nodes/deg_node_id.cc
intern/nodes/deg_node_operation.cc
+ intern/nodes/deg_node_time.cc
intern/depsgraph.cc
intern/depsgraph_build.cc
intern/depsgraph_debug.cc
@@ -85,9 +89,12 @@ set(SRC
intern/eval/deg_eval.h
intern/eval/deg_eval_copy_on_write.h
intern/eval/deg_eval_flush.h
+ intern/eval/deg_eval_stats.h
intern/nodes/deg_node.h
intern/nodes/deg_node_component.h
+ intern/nodes/deg_node_id.h
intern/nodes/deg_node_operation.h
+ intern/nodes/deg_node_time.h
intern/depsgraph.h
intern/depsgraph_intern.h
intern/depsgraph_types.h
diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h
index aaa6142fa21..4f45768cbea 100644
--- a/source/blender/depsgraph/DEG_depsgraph.h
+++ b/source/blender/depsgraph/DEG_depsgraph.h
@@ -140,10 +140,10 @@ void DEG_graph_on_visible_update(struct Main *bmain, Depsgraph *depsgraph);
void DEG_on_visible_update(struct Main *bmain, const bool do_time);
/* Tag given ID for an update in all the dependency graphs. */
-enum {
+typedef enum eDepsgraph_Tag {
/* Object transformation changed, corresponds to OB_RECALC_OB. */
DEG_TAG_TRANSFORM = (1 << 0),
- /* Object geoemtry changed, corresponds to OB_RECALC_DATA. */
+ /* Object geometry changed, corresponds to OB_RECALC_DATA. */
DEG_TAG_GEOMETRY = (1 << 1),
/* Time changed and animation is to be re-evaluated, OB_RECALC_TIME. */
DEG_TAG_TIME = (1 << 2),
@@ -168,7 +168,7 @@ enum {
DEG_TAG_BASE_FLAGS_UPDATE = (1 << 11),
/* Only inform editors about the change. Don't modify datablock itself. */
DEG_TAG_EDITORS_UPDATE = (1 << 12),
-};
+} eDepsgraph_Tag;
void DEG_id_tag_update(struct ID *id, int flag);
void DEG_id_tag_update_ex(struct Main *bmain, struct ID *id, int flag);
diff --git a/source/blender/depsgraph/DEG_depsgraph_debug.h b/source/blender/depsgraph/DEG_depsgraph_debug.h
index bd03874436b..363749dab26 100644
--- a/source/blender/depsgraph/DEG_depsgraph_debug.h
+++ b/source/blender/depsgraph/DEG_depsgraph_debug.h
@@ -53,7 +53,14 @@ void DEG_stats_simple(const struct Depsgraph *graph,
/* ************************************************ */
/* Diagram-Based Graph Debugging */
-void DEG_debug_graphviz(const struct Depsgraph *graph, FILE *stream, const char *label, bool show_eval);
+void DEG_debug_relations_graphviz(const struct Depsgraph *graph,
+ FILE *stream,
+ const char *label);
+
+void DEG_debug_stats_gnuplot(const struct Depsgraph *graph,
+ FILE *stream,
+ const char *label,
+ const char *output_filename);
/* ************************************************ */
diff --git a/source/blender/depsgraph/DEG_depsgraph_query.h b/source/blender/depsgraph/DEG_depsgraph_query.h
index c782a91f76e..83fb100436c 100644
--- a/source/blender/depsgraph/DEG_depsgraph_query.h
+++ b/source/blender/depsgraph/DEG_depsgraph_query.h
@@ -77,12 +77,18 @@ enum {
DEG_ITER_OBJECT_FLAG_DUPLI = (1 << 4),
};
+typedef enum eDepsObjectIteratorMode {
+ DEG_ITER_OBJECT_MODE_VIEWPORT = 0,
+ DEG_ITER_OBJECT_MODE_RENDER = 1,
+} eDepsObjectIteratorMode;
+
typedef struct DEGObjectIterData {
struct Depsgraph *graph;
struct Scene *scene;
struct EvaluationContext eval_ctx;
int flag;
+ eDepsObjectIteratorMode mode;
/* **** Iteration over dupli-list. *** */
@@ -115,10 +121,11 @@ void DEG_iterator_objects_end(struct BLI_Iterator *iter);
* Although they are available they have no overrides (collection_properties)
* and will crash if you try to access it.
*/
-#define DEG_OBJECT_ITER(graph_, instance_, flag_) \
+#define DEG_OBJECT_ITER(graph_, instance_, mode_, flag_) \
{ \
DEGObjectIterData data_ = { \
.graph = (graph_), \
+ .mode = (mode_), \
.flag = (flag_), \
}; \
\
@@ -134,8 +141,8 @@ void DEG_iterator_objects_end(struct BLI_Iterator *iter);
/**
* Depsgraph objects iterator for draw manager and final render
*/
-#define DEG_OBJECT_ITER_FOR_RENDER_ENGINE(graph_, instance_) \
- DEG_OBJECT_ITER(graph_, instance_, \
+#define DEG_OBJECT_ITER_FOR_RENDER_ENGINE(graph_, instance_, mode_) \
+ DEG_OBJECT_ITER(graph_, instance_, mode_, \
DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | \
DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | \
DEG_ITER_OBJECT_FLAG_VISIBLE | \
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc
index 1e906d454ac..2fcad233044 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder.cc
@@ -36,6 +36,7 @@
#include "intern/depsgraph.h"
#include "intern/depsgraph_types.h"
#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_id.h"
#include "util/deg_util_foreach.h"
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
index 3eed0697b5e..e30b9b44490 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
@@ -46,17 +46,38 @@
namespace DEG {
-void deg_graph_detect_cycles(Depsgraph *graph)
+typedef enum eCyclicCheckVisitedState {
+ /* Not is not visited at all during traversal. */
+ NODE_NOT_VISITED = 0,
+ /* Node has been visited during traversal and not in current stack. */
+ NODE_VISITED = 1,
+ /* Node has been visited during traversal and is in current stack. */
+ NODE_IN_STACK = 2,
+} eCyclicCheckVisitedState;
+
+BLI_INLINE void set_node_visited_state(DepsNode *node,
+ eCyclicCheckVisitedState state)
{
- enum {
- /* Not is not visited at all during traversal. */
- NODE_NOT_VISITED = 0,
- /* Node has been visited during traversal and not in current stack. */
- NODE_VISITED = 1,
- /* Node has been visited during traversal and is in current stack. */
- NODE_IN_STACK = 2,
- };
+ node->done = (node->done & ~0x3) | (int)state;
+}
+
+BLI_INLINE eCyclicCheckVisitedState get_node_visited_state(DepsNode *node)
+{
+ return (eCyclicCheckVisitedState)(node->done & 0x3);
+}
+
+BLI_INLINE void set_node_num_visited_children(DepsNode *node, int num_children)
+{
+ node->done = (node->done & 0x3) | (num_children << 2);
+}
+
+BLI_INLINE int get_node_num_visited_children(DepsNode *node)
+{
+ return node->done >> 2;
+}
+void deg_graph_detect_cycles(Depsgraph *graph)
+{
struct StackEntry {
OperationDepsNode *node;
StackEntry *from;
@@ -73,29 +94,31 @@ void deg_graph_detect_cycles(Depsgraph *graph)
has_inlinks = true;
}
}
+ node->done = 0;
if (has_inlinks == false) {
StackEntry entry;
entry.node = node;
entry.from = NULL;
entry.via_relation = NULL;
BLI_stack_push(traversal_stack, &entry);
- node->tag = NODE_IN_STACK;
+ set_node_visited_state(node, NODE_IN_STACK);
}
else {
- node->tag = NODE_NOT_VISITED;
+ set_node_visited_state(node, NODE_NOT_VISITED);
}
- node->done = 0;
}
while (!BLI_stack_is_empty(traversal_stack)) {
StackEntry *entry = (StackEntry *)BLI_stack_peek(traversal_stack);
OperationDepsNode *node = entry->node;
bool all_child_traversed = true;
- for (int i = node->done; i < node->outlinks.size(); ++i) {
+ const int num_visited = get_node_num_visited_children(node);
+ for (int i = num_visited; i < node->outlinks.size(); ++i) {
DepsRelation *rel = node->outlinks[i];
if (rel->to->type == DEG_NODE_TYPE_OPERATION) {
OperationDepsNode *to = (OperationDepsNode *)rel->to;
- if (to->tag == NODE_IN_STACK) {
+ eCyclicCheckVisitedState to_state = get_node_visited_state(to);
+ if (to_state == NODE_IN_STACK) {
printf("Dependency cycle detected:\n");
printf(" '%s' depends on '%s' through '%s'\n",
to->full_identifier().c_str(),
@@ -114,21 +137,21 @@ void deg_graph_detect_cycles(Depsgraph *graph)
/* TODO(sergey): So called russian roulette cycle solver. */
rel->flag |= DEPSREL_FLAG_CYCLIC;
}
- else if (to->tag == NODE_NOT_VISITED) {
+ else if (to_state == NODE_NOT_VISITED) {
StackEntry new_entry;
new_entry.node = to;
new_entry.from = entry;
new_entry.via_relation = rel;
BLI_stack_push(traversal_stack, &new_entry);
- to->tag = NODE_IN_STACK;
+ set_node_visited_state(node, NODE_IN_STACK);
all_child_traversed = false;
- node->done = i;
+ set_node_num_visited_children(node, i);
break;
}
}
}
if (all_child_traversed) {
- node->tag = NODE_VISITED;
+ set_node_visited_state(node, NODE_VISITED);
BLI_stack_discard(traversal_stack);
}
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 68440bb4ff1..95f710616c5 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -108,9 +108,11 @@ extern "C" {
#include "intern/eval/deg_eval_copy_on_write.h"
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_id.h"
#include "intern/nodes/deg_node_operation.h"
#include "intern/depsgraph_types.h"
#include "intern/depsgraph_intern.h"
+
#include "util/deg_util_foreach.h"
namespace DEG {
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index dd41d6df7db..57fca7365d1 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -104,7 +104,9 @@ extern "C" {
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_id.h"
#include "intern/nodes/deg_node_operation.h"
+#include "intern/nodes/deg_node_time.h"
#include "intern/depsgraph_intern.h"
#include "intern/depsgraph_types.h"
@@ -1453,7 +1455,7 @@ void DepsgraphRelationBuilder::build_particles(Object *object)
if (part->dup_ob->type == OB_MBALL) {
ComponentKey dup_geometry_key(&part->dup_ob->id,
DEG_NODE_TYPE_GEOMETRY);
- add_relation(psys_key,
+ add_relation(obdata_ubereval_key,
dup_geometry_key,
"Particle MBall Visualization");
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
index 29cff0cb28d..9b3e46df69a 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
@@ -59,6 +59,7 @@ extern "C" {
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_id.h"
#include "intern/nodes/deg_node_operation.h"
#include "intern/depsgraph_intern.h"
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc b/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc
index b12af21fc8d..7731b76c6b9 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc
@@ -37,6 +37,7 @@
#include "intern/nodes/deg_node_operation.h"
#include "intern/depsgraph.h"
+#include "intern/depsgraph_intern.h"
#include "util/deg_util_foreach.h"
@@ -79,13 +80,13 @@ static void deg_graph_tag_paths_recursive(DepsNode *node)
void deg_graph_transitive_reduction(Depsgraph *graph)
{
+ int num_removed_relations = 0;
foreach (OperationDepsNode *target, graph->operations) {
/* Clear tags. */
foreach (OperationDepsNode *node, graph->operations) {
node->done = 0;
}
-
- /* mark nodes from which we can reach the target
+ /* Mark nodes from which we can reach the target
* start with children, so the target node and direct children are not
* flagged.
*/
@@ -93,27 +94,30 @@ void deg_graph_transitive_reduction(Depsgraph *graph)
foreach (DepsRelation *rel, target->inlinks) {
deg_graph_tag_paths_recursive(rel->from);
}
-
/* Remove redundant paths to the target. */
for (DepsNode::Relations::const_iterator it_rel = target->inlinks.begin();
it_rel != target->inlinks.end();
)
{
DepsRelation *rel = *it_rel;
- /* Increment in advance, so we can safely remove the relation. */
- ++it_rel;
-
if (rel->from->type == DEG_NODE_TYPE_TIMESOURCE) {
/* HACK: time source nodes don't get "done" flag set/cleared. */
/* TODO: there will be other types in future, so iterators above
* need modifying.
*/
+ ++it_rel;
}
else if (rel->from->done & OP_REACHABLE) {
+ rel->unlink();
OBJECT_GUARDED_DELETE(rel, DepsRelation);
+ ++num_removed_relations;
+ }
+ else {
+ ++it_rel;
}
}
}
+ DEG_DEBUG_PRINTF("Removed %d relations\n", num_removed_relations);
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
index bd3d74b307b..827bb4d10ad 100644
--- a/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc
+++ b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
@@ -24,7 +24,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/depsgraph/intern/debug/deg_debug_graphviz.cc
+/** \file blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
* \ingroup depsgraph
*
* Implementation of tools for debugging the depsgraph
@@ -41,6 +41,9 @@ extern "C" {
#include "DEG_depsgraph_debug.h"
#include "intern/depsgraph_intern.h"
+#include "intern/nodes/deg_node_id.h"
+#include "intern/nodes/deg_node_time.h"
+
#include "util/deg_util_foreach.h"
/* ****************** */
@@ -115,7 +118,7 @@ static int deg_debug_node_color_index(const DepsNode *node)
break;
}
/* Do others based on class. */
- switch (node->tclass) {
+ switch (node->get_class()) {
case DEG_NODE_CLASS_OPERATION:
return 4;
case DEG_NODE_CLASS_COMPONENT:
@@ -139,7 +142,6 @@ static int deg_debug_node_color_index(const DepsNode *node)
struct DebugContext {
FILE *file;
bool show_tags;
- bool show_eval_priority;
};
static void deg_debug_fprintf(const DebugContext &ctx, const char *fmt, ...) ATTR_PRINTF_FORMAT(2, 3);
@@ -202,7 +204,7 @@ static void deg_debug_graphviz_node_color(const DebugContext &ctx,
const char *color_update = "dodgerblue3";
const char *color = color_default;
if (ctx.show_tags) {
- if (node->tclass == DEG_NODE_CLASS_OPERATION) {
+ if (node->get_class() == DEG_NODE_CLASS_OPERATION) {
OperationDepsNode *op_node = (OperationDepsNode *)node;
if (op_node->flag & DEPSOP_FLAG_DIRECTLY_MODIFIED) {
color = color_modified;
@@ -223,7 +225,7 @@ static void deg_debug_graphviz_node_penwidth(const DebugContext &ctx,
float penwidth_update = 4.0f;
float penwidth = penwidth_default;
if (ctx.show_tags) {
- if (node->tclass == DEG_NODE_CLASS_OPERATION) {
+ if (node->get_class() == DEG_NODE_CLASS_OPERATION) {
OperationDepsNode *op_node = (OperationDepsNode *)node;
if (op_node->flag & DEPSOP_FLAG_DIRECTLY_MODIFIED) {
penwidth = penwidth_modified;
@@ -261,14 +263,14 @@ static void deg_debug_graphviz_node_style(const DebugContext &ctx, const DepsNod
{
const char *base_style = "filled"; /* default style */
if (ctx.show_tags) {
- if (node->tclass == DEG_NODE_CLASS_OPERATION) {
+ if (node->get_class() == DEG_NODE_CLASS_OPERATION) {
OperationDepsNode *op_node = (OperationDepsNode *)node;
if (op_node->flag & (DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE)) {
base_style = "striped";
}
}
}
- switch (node->tclass) {
+ switch (node->get_class()) {
case DEG_NODE_CLASS_GENERIC:
deg_debug_fprintf(ctx, "\"%s\"", base_style);
break;
@@ -286,22 +288,11 @@ static void deg_debug_graphviz_node_single(const DebugContext &ctx,
{
const char *shape = "box";
string name = node->identifier();
- float priority = -1.0f;
- if (ctx.show_eval_priority && node->tclass == DEG_NODE_CLASS_OPERATION) {
- priority = ((OperationDepsNode *)node)->eval_priority;
- }
deg_debug_fprintf(ctx, "// %s\n", name.c_str());
deg_debug_fprintf(ctx, "\"node_%p\"", node);
deg_debug_fprintf(ctx, "[");
// deg_debug_fprintf(ctx, "label=<<B>%s</B>>", name);
- if (priority >= 0.0f) {
- deg_debug_fprintf(ctx, "label=<%s<BR/>(<I>%.2f</I>)>",
- name.c_str(),
- priority);
- }
- else {
- deg_debug_fprintf(ctx, "label=<%s>", name.c_str());
- }
+ deg_debug_fprintf(ctx, "label=<%s>", name.c_str());
deg_debug_fprintf(ctx, ",fontname=\"%s\"", deg_debug_graphviz_fontname);
deg_debug_fprintf(ctx, ",fontsize=%f", deg_debug_graphviz_node_label_size);
deg_debug_fprintf(ctx, ",shape=%s", shape);
@@ -436,7 +427,7 @@ static bool deg_debug_graphviz_is_cluster(const DepsNode *node)
static bool deg_debug_graphviz_is_owner(const DepsNode *node,
const DepsNode *other)
{
- switch (node->tclass) {
+ switch (node->get_class()) {
case DEG_NODE_CLASS_COMPONENT:
{
ComponentDepsNode *comp_node = (ComponentDepsNode *)node;
@@ -526,7 +517,9 @@ static void deg_debug_graphviz_graph_relations(const DebugContext &ctx,
} // namespace DEG
-void DEG_debug_graphviz(const Depsgraph *graph, FILE *f, const char *label, bool show_eval)
+void DEG_debug_relations_graphviz(const Depsgraph *graph,
+ FILE *f,
+ const char *label)
{
if (!graph) {
return;
@@ -536,8 +529,6 @@ void DEG_debug_graphviz(const Depsgraph *graph, FILE *f, const char *label, bool
DEG::DebugContext ctx;
ctx.file = f;
- ctx.show_tags = show_eval;
- ctx.show_eval_priority = show_eval;
DEG::deg_debug_fprintf(ctx, "digraph depgraph {" NL);
DEG::deg_debug_fprintf(ctx, "rankdir=LR;" NL);
diff --git a/source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc b/source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc
new file mode 100644
index 00000000000..35888f8d5e3
--- /dev/null
+++ b/source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc
@@ -0,0 +1,157 @@
+/*
+ * ***** 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Sergey Sharybin
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc
+ * \ingroup depsgraph
+ */
+
+#include "DEG_depsgraph_debug.h"
+
+#include <algorithm>
+#include <cstdarg>
+
+#include "BLI_compiler_attrs.h"
+#include "BLI_math_base.h"
+
+#include "intern/depsgraph.h"
+#include "intern/nodes/deg_node_id.h"
+
+#include "util/deg_util_foreach.h"
+
+extern "C" {
+#include "DNA_ID.h"
+} /* extern "C" */
+
+#define NL "\r\n"
+
+namespace DEG {
+namespace {
+
+struct DebugContext {
+ FILE *file;
+ const Depsgraph *graph;
+ const char *label;
+ const char *output_filename;
+};
+
+struct StatsEntry {
+ const IDDepsNode *id_node;
+ double time;
+};
+
+/* TODO(sergey): De-duplicate with graphviz relation debugger. */
+static void deg_debug_fprintf(const DebugContext &ctx,
+ const char *fmt,
+ ...) ATTR_PRINTF_FORMAT(2, 3);
+static void deg_debug_fprintf(const DebugContext &ctx, const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(ctx.file, fmt, args);
+ va_end(args);
+}
+
+BLI_INLINE double get_node_time(const DebugContext& /*ctx*/,
+ const DepsNode *node)
+{
+ // TODO(sergey): Figure out a nice way to define which exact time
+ // we want to show.
+ return node->stats.current_time;
+}
+
+bool stat_entry_comparator(const StatsEntry& a, const StatsEntry& b)
+{
+ return a.time < b.time;
+}
+
+void write_stats_data(const DebugContext& ctx)
+{
+ // Fill in array of all stats which are to be displayed.
+ vector<StatsEntry> stats;
+ stats.reserve(ctx.graph->id_nodes.size());
+ foreach (const IDDepsNode *id_node, ctx.graph->id_nodes) {
+ const double time = get_node_time(ctx, id_node);
+ if (time == 0.0) {
+ continue;
+ }
+ StatsEntry entry;
+ entry.id_node = id_node;
+ entry.time = time;
+ stats.push_back(entry);
+ }
+ // Sort the data.
+ std::sort(stats.begin(), stats.end(), stat_entry_comparator);
+ // We limit number of entries, otherwise things become unreadable.
+ stats.resize(min_ii(stats.size(), 32));
+ // Print data to the file stream.
+ deg_debug_fprintf(ctx, "$data << EOD" NL);
+ foreach (const StatsEntry& entry, stats) {
+ deg_debug_fprintf(ctx, "\"%s\",%f" NL,
+ entry.id_node->id_orig->name + 2,
+ entry.time);
+ }
+ deg_debug_fprintf(ctx, "EOD" NL);
+}
+
+void deg_debug_stats_gnuplot(const DebugContext& ctx)
+{
+ // Data itself.
+ write_stats_data(ctx);
+ // Optional label.
+ if (ctx.label && ctx.label[0]) {
+ deg_debug_fprintf(ctx, "set title \"%s\"" NL, ctx.label);
+ }
+ // Rest of the commands.
+ // TODO(sergey): Need to decide on the resolution somehow.
+ deg_debug_fprintf(ctx, "set terminal pngcairo size 1920,1080" NL);
+ deg_debug_fprintf(ctx, "set output \"%s\"" NL, ctx.output_filename);
+ deg_debug_fprintf(ctx, "set grid" NL);
+ deg_debug_fprintf(ctx, "set datafile separator ','" NL);
+ deg_debug_fprintf(ctx, "set style fill solid" NL);
+ deg_debug_fprintf(ctx, "plot \"$data\" using " \
+ "($2*0.5):0:($2*0.5):(0.2):yticlabels(1) "
+ "with boxxyerrorbars t '' lt rgb \"#406090\"" NL);
+
+}
+
+} // namespace
+} // namespace DEG
+
+void DEG_debug_stats_gnuplot(const Depsgraph *depsgraph,
+ FILE *f,
+ const char *label,
+ const char *output_filename)
+{
+ if (depsgraph == NULL) {
+ return;
+ }
+ DEG::DebugContext ctx;
+ ctx.file = f;
+ ctx.graph = (DEG::Depsgraph *)depsgraph;
+ ctx.label = label;
+ ctx.output_filename = output_filename;
+ DEG::deg_debug_stats_gnuplot(ctx);
+}
diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc
index 995157f5c9a..45013bb1bcd 100644
--- a/source/blender/depsgraph/intern/depsgraph.cc
+++ b/source/blender/depsgraph/intern/depsgraph.cc
@@ -49,6 +49,7 @@ extern "C" {
#include "RNA_access.h"
}
+#include <algorithm>
#include <cstring>
#include "DEG_depsgraph.h"
@@ -57,7 +58,9 @@ extern "C" {
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_id.h"
#include "intern/nodes/deg_node_operation.h"
+#include "intern/nodes/deg_node_time.h"
#include "intern/depsgraph_intern.h"
#include "util/deg_util_foreach.h"
@@ -79,6 +82,14 @@ namespace DEG {
static DEG_EditorUpdateIDCb deg_editor_update_id_cb = NULL;
static DEG_EditorUpdateSceneCb deg_editor_update_scene_cb = NULL;
+/* TODO(sergey): Find a better place for this. */
+template <typename T>
+static void remove_from_vector(vector<T> *vector, const T& value)
+{
+ vector->erase(std::remove(vector->begin(), vector->end(), value),
+ vector->end());
+}
+
Depsgraph::Depsgraph()
: time_source(NULL),
need_update(true),
@@ -431,7 +442,15 @@ DepsRelation::DepsRelation(DepsNode *from,
DepsRelation::~DepsRelation()
{
/* Sanity check. */
- BLI_assert(this->from && this->to);
+ BLI_assert(from != NULL && to != NULL);
+}
+
+void DepsRelation::unlink()
+{
+ /* Sanity check. */
+ BLI_assert(from != NULL && to != NULL);
+ remove_from_vector(&from->outlinks, this);
+ remove_from_vector(&to->inlinks, this);
}
/* Low level tagging -------------------------------------- */
diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h
index 8a34be0c7a2..f18b93c9807 100644
--- a/source/blender/depsgraph/intern/depsgraph.h
+++ b/source/blender/depsgraph/intern/depsgraph.h
@@ -87,6 +87,8 @@ struct DepsRelation {
const char *description);
~DepsRelation();
+
+ void unlink();
};
/* ********* */
diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc
index 57153279acb..5b07630240d 100644
--- a/source/blender/depsgraph/intern/depsgraph_build.cc
+++ b/source/blender/depsgraph/intern/depsgraph_build.cc
@@ -68,6 +68,7 @@ extern "C" {
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_id.h"
#include "intern/nodes/deg_node_operation.h"
#include "intern/depsgraph_types.h"
diff --git a/source/blender/depsgraph/intern/depsgraph_debug.cc b/source/blender/depsgraph/intern/depsgraph_debug.cc
index 42c1cf861eb..e8d166532ad 100644
--- a/source/blender/depsgraph/intern/depsgraph_debug.cc
+++ b/source/blender/depsgraph/intern/depsgraph_debug.cc
@@ -42,6 +42,9 @@ extern "C" {
#include "DEG_depsgraph_build.h"
#include "intern/depsgraph_intern.h"
+#include "intern/nodes/deg_node_id.h"
+#include "intern/nodes/deg_node_time.h"
+
#include "util/deg_util_foreach.h"
bool DEG_debug_compare(const struct Depsgraph *graph1,
diff --git a/source/blender/depsgraph/intern/depsgraph_eval.cc b/source/blender/depsgraph/intern/depsgraph_eval.cc
index 2ed403c463a..ad1a850a807 100644
--- a/source/blender/depsgraph/intern/depsgraph_eval.cc
+++ b/source/blender/depsgraph/intern/depsgraph_eval.cc
@@ -48,12 +48,10 @@ extern "C" {
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_operation.h"
+#include "intern/nodes/deg_node_time.h"
#include "intern/depsgraph.h"
-/* Unfinished and unused, and takes quite some pre-processing time. */
-#undef USE_EVAL_PRIORITY
-
/* ****************** */
/* Evaluation Context */
diff --git a/source/blender/depsgraph/intern/depsgraph_intern.h b/source/blender/depsgraph/intern/depsgraph_intern.h
index 4484d4ed94f..df5e51a3910 100644
--- a/source/blender/depsgraph/intern/depsgraph_intern.h
+++ b/source/blender/depsgraph/intern/depsgraph_intern.h
@@ -60,8 +60,8 @@ namespace DEG {
/* Typeinfo Struct (nti) */
struct DepsNodeFactory {
virtual eDepsNode_Type type() const = 0;
- virtual eDepsNode_Class tclass() const = 0;
virtual const char *tname() const = 0;
+ virtual int id_recalc_tag() const = 0;
virtual DepsNode *create_node(const ID *id,
const char *subdata,
@@ -71,8 +71,8 @@ struct DepsNodeFactory {
template <class NodeType>
struct DepsNodeFactoryImpl : public DepsNodeFactory {
eDepsNode_Type type() const { return NodeType::typeinfo.type; }
- eDepsNode_Class tclass() const { return NodeType::typeinfo.tclass; }
const char *tname() const { return NodeType::typeinfo.tname; }
+ int id_recalc_tag() const { return NodeType::typeinfo.id_recalc_tag; }
DepsNode *create_node(const ID *id, const char *subdata, const char *name) const
{
@@ -80,7 +80,6 @@ struct DepsNodeFactoryImpl : public DepsNodeFactory {
/* populate base node settings */
node->type = type();
- node->tclass = tclass();
if (name[0] != '\0') {
/* set name if provided ... */
@@ -113,10 +112,6 @@ void deg_editors_id_update(const DEGEditorUpdateContext *update_ctx,
void deg_editors_scene_update(const DEGEditorUpdateContext *update_ctx,
bool updated);
-/* Tagging helpers ------------------------------------------------------ */
-
-void lib_id_recalc_tag(struct Main *bmain, struct ID *id);
-
#define DEG_DEBUG_PRINTF(...) \
do { \
if (G.debug & G_DEBUG_DEPSGRAPH) { \
diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc
index 6892bdaa178..98bf335f89e 100644
--- a/source/blender/depsgraph/intern/depsgraph_query.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query.cc
@@ -46,6 +46,7 @@ extern "C" {
#include "DEG_depsgraph_query.h"
#include "intern/depsgraph_intern.h"
+#include "intern/nodes/deg_node_id.h"
bool DEG_id_type_tagged(Main *bmain, short id_type)
{
diff --git a/source/blender/depsgraph/intern/depsgraph_query_foreach.cc b/source/blender/depsgraph/intern/depsgraph_query_foreach.cc
index b1353f528bc..e6692cf49b3 100644
--- a/source/blender/depsgraph/intern/depsgraph_query_foreach.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query_foreach.cc
@@ -50,6 +50,7 @@ extern "C" {
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_id.h"
#include "intern/nodes/deg_node_operation.h"
#include "util/deg_util_foreach.h"
diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
index a7f37575ff6..42d512d473c 100644
--- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
@@ -50,6 +50,8 @@ extern "C" {
#include "intern/depsgraph_intern.h"
#include "util/deg_util_foreach.h"
+#include "intern/nodes/deg_node_id.h"
+
#ifndef NDEBUG
# include "intern/eval/deg_eval_copy_on_write.h"
#endif
@@ -82,6 +84,7 @@ static bool deg_objects_dupli_iterator_next(BLI_Iterator *iter)
Object *dupli_parent = data->dupli_parent;
Object *temp_dupli_object = &data->temp_dupli_object;
*temp_dupli_object = *dob->ob;
+ temp_dupli_object->transflag &= ~OB_DUPLI;
temp_dupli_object->select_color = dupli_parent->select_color;
temp_dupli_object->base_flag = dupli_parent->base_flag | BASE_FROMDUPLI;
@@ -137,7 +140,7 @@ static void DEG_iterator_objects_step(BLI_Iterator *iter, DEG::IDDepsNode *id_no
Object *object = (Object *)id_node->id_cow;
BLI_assert(DEG::deg_validate_copy_on_write_datablock(&object->id));
- if ((BKE_object_is_visible(object) == false) &&
+ if ((BKE_object_is_visible(object, OB_VISIBILITY_CHECK_UNKNOWN_RENDER_MODE) == false) &&
((data->flag & DEG_ITER_OBJECT_FLAG_VISIBLE) != 0))
{
return;
@@ -147,6 +150,14 @@ static void DEG_iterator_objects_step(BLI_Iterator *iter, DEG::IDDepsNode *id_no
data->dupli_parent = object;
data->dupli_list = object_duplilist(&data->eval_ctx, data->scene, object);
data->dupli_object_next = (DupliObject *)data->dupli_list->first;
+
+ const eObjectVisibilityCheck mode = (data->mode == DEG_ITER_OBJECT_MODE_RENDER) ?
+ OB_VISIBILITY_CHECK_FOR_RENDER :
+ OB_VISIBILITY_CHECK_FOR_VIEWPORT;
+
+ if (BKE_object_is_visible(object, mode) == false) {
+ return;
+ }
}
iter->current = object;
@@ -165,7 +176,10 @@ void DEG_iterator_objects_begin(BLI_Iterator *iter, DEGObjectIterData *data)
}
/* TODO(sergey): What evaluation type we want here? */
- DEG_evaluation_context_init(&data->eval_ctx, DAG_EVAL_RENDER);
+ /* TODO(dfelinto): Get rid of evaluation context here, it's only used to do
+ * direct dupli-objects update in group.c. Which is terribly bad, and all
+ * objects are expected to be evaluated already. */
+ DEG_evaluation_context_init(&data->eval_ctx, DAG_EVAL_VIEWPORT);
data->eval_ctx.view_layer = DEG_get_evaluated_view_layer(depsgraph);
iter->data = data;
@@ -191,6 +205,7 @@ void DEG_iterator_objects_next(BLI_Iterator *iter)
Depsgraph *depsgraph = data->graph;
DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
do {
+ iter->skip = false;
if (data->dupli_list) {
if (deg_objects_dupli_iterator_next(iter)) {
return;
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index dc8a4aecc46..9082c885c64 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -35,8 +35,9 @@
#include <queue>
#include "BLI_utildefines.h"
-#include "BLI_task.h"
#include "BLI_listbase.h"
+#include "BLI_math_bits.h"
+#include "BLI_task.h"
extern "C" {
#include "DNA_object_types.h"
@@ -63,105 +64,29 @@ extern "C" {
#include "intern/eval/deg_eval_flush.h"
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_id.h"
#include "intern/nodes/deg_node_operation.h"
#include "intern/depsgraph_intern.h"
#include "util/deg_util_foreach.h"
-/* Define this in order to have more strict sanitization of what tagging flags
- * are used for ID databnlocks. Ideally, we would always want this, but there
- * are cases in generic modules (like IR remapping) where we don't want to spent
- * lots of time trying to guess which components are to be updated.
- */
-// #define STRICT_COMPONENT_TAGGING
-
/* *********************** */
/* Update Tagging/Flushing */
namespace DEG {
-/* Data-Based Tagging ------------------------------- */
-
-void lib_id_recalc_tag(Main *bmain, ID *id)
-{
- id->recalc |= ID_RECALC;
- DEG_id_type_tag(bmain, GS(id->name));
-}
-
namespace {
void deg_graph_id_tag_update(Main *bmain, Depsgraph *graph, ID *id, int flag);
-void lib_id_recalc_tag_flag(Main *bmain, ID *id, int flag)
+void depsgraph_geometry_tag_to_component(const ID *id,
+ eDepsNode_Type *component_type)
{
- /* This bit of code ensures legacy object->recalc flags are still filled in
- * the same way as it was expected with the old dependency graph.
- *
- * This is because some areas like motion paths and likely some other
- * physics baking process are doing manual scene update on all the frames,
- * trying to minimize number of updates.
- *
- * But this flag will also let us to re-construct entry nodes for update
- * after relations update and after layer visibility changes.
- */
- if (flag) {
- if (flag & OB_RECALC_OB) {
- lib_id_recalc_tag(bmain, id);
- }
- if (flag & (OB_RECALC_DATA)) {
- if (GS(id->name) == ID_OB) {
- Object *object = (Object *)id;
- ID *object_data = (ID *)object->data;
- if (object_data != NULL) {
- lib_id_recalc_tag(bmain, object_data);
- }
- }
- else {
- // BLI_assert(!"Tagging non-object as object data update");
- lib_id_recalc_tag(bmain, id);
- }
- }
- if (flag & PSYS_RECALC) {
- lib_id_recalc_tag(bmain, id);
- }
- }
- else {
- lib_id_recalc_tag(bmain, id);
- }
-}
-
-/* Special tagging */
-void id_tag_update_special_zero_flag(Depsgraph *graph, IDDepsNode *id_node)
-{
- /* NOTE: Full ID node update for now, need to minimize that in the future. */
- id_node->tag_update(graph);
-}
-
-/* Tag corresponding to OB_RECALC_OB. */
-void id_tag_update_object_transform(Depsgraph *graph, IDDepsNode *id_node)
-{
- ComponentDepsNode *transform_comp =
- id_node->find_component(DEG_NODE_TYPE_TRANSFORM);
- if (transform_comp == NULL) {
-#ifdef STRICT_COMPONENT_TAGGING
- DEG_ERROR_PRINTF("ERROR: Unable to find transform component for %s\n",
- id_node->id_orig->name);
- BLI_assert(!"This is not supposed to happen!");
-#endif
- return;
- }
- transform_comp->tag_update(graph);
-}
-
-/* Tag corresponding to OB_RECALC_DATA. */
-void id_tag_update_object_data(Depsgraph *graph, IDDepsNode *id_node)
-{
- const ID_Type id_type = GS(id_node->id_orig->name);
- ComponentDepsNode *data_comp = NULL;
+ const ID_Type id_type = GS(id->name);
switch (id_type) {
case ID_OB:
{
- const Object *object = (Object *)id_node->id_orig;
+ const Object *object = (Object *)id;
switch (object->type) {
case OB_MESH:
case OB_CURVE:
@@ -169,127 +94,34 @@ void id_tag_update_object_data(Depsgraph *graph, IDDepsNode *id_node)
case OB_FONT:
case OB_MBALL:
case OB_GROOM:
- data_comp = id_node->find_component(DEG_NODE_TYPE_GEOMETRY);
+ *component_type = DEG_NODE_TYPE_GEOMETRY;
break;
case OB_ARMATURE:
- data_comp = id_node->find_component(DEG_NODE_TYPE_EVAL_POSE);
+ *component_type = DEG_NODE_TYPE_EVAL_POSE;
break;
- /* TODO(sergey): More cases here? */
+ /* TODO(sergey): More cases here? */
}
break;
}
case ID_ME:
- data_comp = id_node->find_component(DEG_NODE_TYPE_GEOMETRY);
+ *component_type = DEG_NODE_TYPE_GEOMETRY;
break;
case ID_PA:
return;
case ID_LP:
- data_comp = id_node->find_component(DEG_NODE_TYPE_PARAMETERS);
+ *component_type = DEG_NODE_TYPE_PARAMETERS;
break;
default:
break;
}
- if (data_comp == NULL) {
-#ifdef STRICT_COMPONENT_TAGGING
- DEG_ERROR_PRINTF("ERROR: Unable to find data component for %s\n",
- id_node->id_orig->name);
- BLI_assert(!"This is not supposed to happen!");
-#endif
- return;
- }
- data_comp->tag_update(graph);
- /* Special legacy compatibility code, tag data ID for update when object
- * is tagged for data update.
- */
- if (id_type == ID_OB) {
- Object *object = (Object *)id_node->id_orig;
- ID *data_id = (ID *)object->data;
- if (data_id != NULL) {
- IDDepsNode *data_id_node = graph->find_id_node(data_id);
- // BLI_assert(data_id_node != NULL);
- /* TODO(sergey): Do we want more granular tags here? */
- /* TODO(sergey): Hrm, during some operations it's possible to have
- * object node existing but not it's data. For example, when making
- * objects local. This is valid situation, but how can we distinguish
- * that from someone trying to do stupid things with dependency
- * graph?
- */
- if (data_id_node != NULL) {
- data_id_node->tag_update(graph);
- }
- }
- }
-}
-
-/* Tag corresponding to OB_RECALC_TIME. */
-void id_tag_update_object_time(Depsgraph *graph, IDDepsNode *id_node)
-{
- ComponentDepsNode *animation_comp =
- id_node->find_component(DEG_NODE_TYPE_ANIMATION);
- if (animation_comp == NULL) {
- /* It's not necessarily we've got animation component in cases when
- * we are tagging for time updates.
- */
- return;
- }
- animation_comp->tag_update(graph);
- /* TODO(sergey): More components to tag here? */
-}
-
-void id_tag_update_particle(Depsgraph *graph, IDDepsNode *id_node, int tag)
-{
- ComponentDepsNode *particle_comp =
- id_node->find_component(DEG_NODE_TYPE_PARAMETERS);
- ParticleSettings *particle_settings = (ParticleSettings *)id_node->id_orig;
- particle_settings->recalc |= (tag & PSYS_RECALC);
- if (particle_comp == NULL) {
-#ifdef STRICT_COMPONENT_TAGGING
- DEG_ERROR_PRINTF("ERROR: Unable to find particle component for %s\n",
- id_node->id_orig->name);
- BLI_assert(!"This is not supposed to happen!");
-#endif
- return;
- }
- particle_comp->tag_update(graph);
}
-void id_tag_update_shading(Depsgraph *graph, IDDepsNode *id_node)
+void depsgraph_select_tag_to_component_opcode(
+ const ID *id,
+ eDepsNode_Type *component_type,
+ eDepsOperation_Code *operation_code)
{
- ComponentDepsNode *shading_comp;
- if (GS(id_node->id_orig->name) == ID_NT) {
- shading_comp = id_node->find_component(DEG_NODE_TYPE_SHADING_PARAMETERS);
- }
- else {
- shading_comp = id_node->find_component(DEG_NODE_TYPE_SHADING);
- }
- if (shading_comp == NULL) {
-#ifdef STRICT_COMPONENT_TAGGING
- DEG_ERROR_PRINTF("ERROR: Unable to find shading component for %s\n",
- id_node->id_orig->name);
- BLI_assert(!"This is not supposed to happen!");
-#endif
- return;
- }
- shading_comp->tag_update(graph);
-}
-
-/* Tag corresponding to DEG_TAG_COPY_ON_WRITE. */
-void id_tag_update_copy_on_write(Depsgraph *graph, IDDepsNode *id_node)
-{
- if (!DEG_depsgraph_use_copy_on_write()) {
- return;
- }
- ComponentDepsNode *cow_comp =
- id_node->find_component(DEG_NODE_TYPE_COPY_ON_WRITE);
- OperationDepsNode *cow_node = cow_comp->get_entry_operation();
- cow_node->tag_update(graph);
-}
-
-void id_tag_update_select_update(Depsgraph *graph, IDDepsNode *id_node)
-{
- ComponentDepsNode *component;
- OperationDepsNode *node = NULL;
- const ID_Type id_type = GS(id_node->id_orig->name);
+ const ID_Type id_type = GS(id->name);
if (id_type == ID_SCE) {
/* We need to flush base flags to all objects in a scene since we
* don't know which ones changed. However, we don't want to update
@@ -300,62 +132,107 @@ void id_tag_update_select_update(Depsgraph *graph, IDDepsNode *id_node)
* does nothing and which is only used to cascade flush down the
* road.
*/
- component = id_node->find_component(DEG_NODE_TYPE_LAYER_COLLECTIONS);
- BLI_assert(component != NULL);
- if (component != NULL) {
- node = component->find_operation(DEG_OPCODE_VIEW_LAYER_DONE);
- }
+ *component_type = DEG_NODE_TYPE_LAYER_COLLECTIONS;
+ *operation_code = DEG_OPCODE_VIEW_LAYER_DONE;
}
else if (id_type == ID_OB) {
- component = id_node->find_component(DEG_NODE_TYPE_LAYER_COLLECTIONS);
- /* NOTE: This component might be missing for indirectly linked
- * objects.
- */
- if (component != NULL) {
- node = component->find_operation(DEG_OPCODE_OBJECT_BASE_FLAGS);
- }
+ *component_type = DEG_NODE_TYPE_LAYER_COLLECTIONS;
+ *operation_code = DEG_OPCODE_OBJECT_BASE_FLAGS;
}
else {
- component = id_node->find_component(DEG_NODE_TYPE_BATCH_CACHE);
- BLI_assert(component != NULL);
- if (component != NULL) {
- node = component->find_operation(DEG_OPCODE_GEOMETRY_SELECT_UPDATE,
- "", -1);
- }
- }
- if (node != NULL) {
- node->tag_update(graph);
+ *component_type = DEG_NODE_TYPE_BATCH_CACHE;
+ *operation_code = DEG_OPCODE_GEOMETRY_SELECT_UPDATE;
}
}
-void id_tag_update_base_flags(Depsgraph *graph, IDDepsNode *id_node)
+void depsgraph_base_flags_tag_to_component_opcode(
+ const ID *id,
+ eDepsNode_Type *component_type,
+ eDepsOperation_Code *operation_code)
{
- ComponentDepsNode *component;
- OperationDepsNode *node = NULL;
- const ID_Type id_type = GS(id_node->id_orig->name);
+ const ID_Type id_type = GS(id->name);
if (id_type == ID_SCE) {
- component = id_node->find_component(DEG_NODE_TYPE_LAYER_COLLECTIONS);
- if (component == NULL) {
- return;
- }
- node = component->find_operation(DEG_OPCODE_VIEW_LAYER_INIT);
+ *component_type = DEG_NODE_TYPE_LAYER_COLLECTIONS;
+ *operation_code = DEG_OPCODE_VIEW_LAYER_INIT;
}
else if (id_type == ID_OB) {
- component = id_node->find_component(DEG_NODE_TYPE_LAYER_COLLECTIONS);
- if (component == NULL) {
- return;
- }
- node = component->find_operation(DEG_OPCODE_OBJECT_BASE_FLAGS);
- if (node == NULL) {
- return;
- }
+ *component_type = DEG_NODE_TYPE_LAYER_COLLECTIONS;
+ *operation_code = DEG_OPCODE_OBJECT_BASE_FLAGS;
}
- if (node != NULL) {
- node->tag_update(graph);
+}
+
+void depsgraph_tag_to_component_opcode(const ID *id,
+ eDepsgraph_Tag tag,
+ eDepsNode_Type *component_type,
+ eDepsOperation_Code *operation_code)
+{
+ const ID_Type id_type = GS(id->name);
+ *component_type = DEG_NODE_TYPE_UNDEFINED;
+ *operation_code = DEG_OPCODE_OPERATION;
+ /* Special case for now, in the future we should get rid of this. */
+ if (tag == 0) {
+ *component_type = DEG_NODE_TYPE_ID_REF;
+ *operation_code = DEG_OPCODE_OPERATION;
+ return;
+ }
+ switch (tag) {
+ case DEG_TAG_TRANSFORM:
+ *component_type = DEG_NODE_TYPE_TRANSFORM;
+ break;
+ case DEG_TAG_GEOMETRY:
+ depsgraph_geometry_tag_to_component(id, component_type);
+ break;
+ case DEG_TAG_TIME:
+ *component_type = DEG_NODE_TYPE_ANIMATION;
+ break;
+ case DEG_TAG_PSYS_REDO:
+ case DEG_TAG_PSYS_RESET:
+ case DEG_TAG_PSYS_TYPE:
+ case DEG_TAG_PSYS_CHILD:
+ case DEG_TAG_PSYS_PHYS:
+ *component_type = DEG_NODE_TYPE_EVAL_PARTICLES;
+ break;
+ case DEG_TAG_COPY_ON_WRITE:
+ *component_type = DEG_NODE_TYPE_COPY_ON_WRITE;
+ break;
+ case DEG_TAG_SHADING_UPDATE:
+ if (id_type == ID_NT) {
+ *component_type = DEG_NODE_TYPE_SHADING_PARAMETERS;
+ }
+ else {
+ *component_type = DEG_NODE_TYPE_SHADING;
+ }
+ break;
+ case DEG_TAG_SELECT_UPDATE:
+ depsgraph_select_tag_to_component_opcode(id,
+ component_type,
+ operation_code);
+ break;
+ case DEG_TAG_BASE_FLAGS_UPDATE:
+ depsgraph_base_flags_tag_to_component_opcode(id,
+ component_type,
+ operation_code);
+ case DEG_TAG_EDITORS_UPDATE:
+ /* There is no such node in depsgraph, this tag is to be handled
+ * separately.
+ */
+ break;
+ case DEG_TAG_PSYS_ALL:
+ BLI_assert(!"Should not happen");
+ break;
}
}
-void id_tag_update_editors_update(Main *bmain, Depsgraph *graph, ID *id)
+void id_tag_update_ntree_special(Main *bmain, Depsgraph *graph, ID *id, int flag)
+{
+ bNodeTree *ntree = ntreeFromID(id);
+ if (ntree == NULL) {
+ return;
+ }
+ deg_graph_id_tag_update(bmain, graph, &ntree->id, flag);
+}
+
+void depsgraph_update_editors_tag(Main *bmain, Depsgraph *graph, ID *id)
{
/* NOTE: We handle this immediately, without delaying anything, to be
* sure we don't cause threading issues with OpenGL.
@@ -368,77 +245,93 @@ void id_tag_update_editors_update(Main *bmain, Depsgraph *graph, ID *id)
deg_editors_id_update(&update_ctx, id);
}
-void id_tag_update_ntree_special(Main *bmain, Depsgraph *graph, ID *id, int flag)
+void deg_graph_id_tag_update_single_flag(Main *bmain,
+ Depsgraph *graph,
+ ID *id,
+ IDDepsNode *id_node,
+ eDepsgraph_Tag tag)
{
- bNodeTree *ntree = ntreeFromID(id);
- if (ntree == NULL) {
+ if (tag == DEG_TAG_EDITORS_UPDATE) {
+ if (graph != NULL) {
+ depsgraph_update_editors_tag(bmain, graph, id);
+ }
return;
}
- IDDepsNode *id_node = graph->find_id_node(&ntree->id);
- if (id_node != NULL) {
- deg_graph_id_tag_update(bmain, graph, id_node->id_orig, flag);
- }
-}
-
-void deg_graph_id_tag_update(Main *bmain, Depsgraph *graph, ID *id, int flag)
-{
- Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
- IDDepsNode *id_node = deg_graph->find_id_node(id);
- /* Make sure legacy flags are all nicely update. */
- lib_id_recalc_tag_flag(bmain, id, flag);
- if (id_node == NULL) {
- /* Shouldn't happen, but better be sure here. */
+ /* Get description of what is to be tagged. */
+ eDepsNode_Type component_type;
+ eDepsOperation_Code operation_code;
+ depsgraph_tag_to_component_opcode(id,
+ tag,
+ &component_type,
+ &operation_code);
+ /* Check whether we've got something to tag. */
+ if (component_type == DEG_NODE_TYPE_UNDEFINED) {
+ /* Given ID does not support tag. */
+ /* TODO(sergey): Shall we raise some panic here? */
return;
}
- /* Tag components based on flags. */
- if (flag == 0) {
- id_tag_update_special_zero_flag(graph, id_node);
- id_tag_update_ntree_special(bmain, graph, id, flag);
+ /* Tag ID recalc flag. */
+ DepsNodeFactory *factory = deg_type_get_factory(component_type);
+ BLI_assert(factory != NULL);
+ id->recalc |= factory->id_recalc_tag();
+ /* Some sanity checks before moving forward. */
+ if (id_node == NULL) {
+ /* Happens when object is tagged for update and not yet in the
+ * dependency graph (but will be after relations update).
+ */
return;
}
- if (flag & OB_RECALC_OB) {
- id_tag_update_object_transform(graph, id_node);
+ /* Tag corresponding dependency graph operation for update. */
+ if (component_type == DEG_NODE_TYPE_ID_REF) {
+ id_node->tag_update(graph);
}
- if (flag & OB_RECALC_DATA) {
- id_tag_update_object_data(graph, id_node);
- if (DEG_depsgraph_use_copy_on_write()) {
- if (flag & DEG_TAG_COPY_ON_WRITE) {
- const ID_Type id_type = GS(id_node->id_orig->name);
- if (id_type == ID_OB) {
- Object *object = (Object *)id_node->id_orig;
- ID *ob_data = (ID *)object->data;
- DEG_id_tag_update_ex(bmain, ob_data, flag);
+ else {
+ ComponentDepsNode *component_node =
+ id_node->find_component(component_type);
+ if (component_node != NULL) {
+ if (operation_code == DEG_OPCODE_OPERATION) {
+ component_node->tag_update(graph);
+ }
+ else {
+ OperationDepsNode *operation_node =
+ component_node->find_operation(operation_code);
+ if (operation_node != NULL) {
+ operation_node->tag_update(graph);
}
}
}
}
- if (flag & OB_RECALC_TIME) {
- id_tag_update_object_time(graph, id_node);
- }
- if (flag & PSYS_RECALC) {
- id_tag_update_particle(graph, id_node, flag);
- }
- if (flag & DEG_TAG_SHADING_UPDATE) {
- id_tag_update_shading(graph, id_node);
- }
- if (flag & DEG_TAG_COPY_ON_WRITE) {
- id_tag_update_copy_on_write(graph, id_node);
- }
- if (flag & DEG_TAG_SELECT_UPDATE) {
- id_tag_update_select_update(graph, id_node);
- }
- if (flag & DEG_TAG_BASE_FLAGS_UPDATE) {
- id_tag_update_base_flags(graph, id_node);
- }
- if (flag & DEG_TAG_EDITORS_UPDATE) {
- id_tag_update_editors_update(bmain, graph, id);
+}
+
+void deg_graph_id_tag_update(Main *bmain, Depsgraph *graph, ID *id, int flag)
+{
+ IDDepsNode *id_node = (graph != NULL) ? graph->find_id_node(id)
+ : NULL;
+ DEG_id_type_tag(bmain, GS(id->name));
+ if (flag == 0) {
+ /* TODO(sergey): Which recalc flags to set here? */
+ id->recalc |= ID_RECALC_ALL;
+ if (id_node != NULL) {
+ id_node->tag_update(graph);
+ }
}
+ int current_flag = flag;
+ while (current_flag != 0) {
+ eDepsgraph_Tag tag =
+ (eDepsgraph_Tag)(1 << bitscan_forward_clear_i(&current_flag));
+ deg_graph_id_tag_update_single_flag(bmain,
+ graph,
+ id,
+ id_node,
+ tag);
+ }
+ /* Special case for nested node tree datablocks. */
id_tag_update_ntree_special(bmain, graph, id, flag);
}
void deg_id_tag_update(Main *bmain, ID *id, int flag)
{
- lib_id_recalc_tag_flag(bmain, id, flag);
+ deg_graph_id_tag_update(bmain, NULL, id, flag);
LINKLIST_FOREACH(Scene *, scene, &bmain->scene) {
LINKLIST_FOREACH(ViewLayer *, view_layer, &scene->view_layers) {
Depsgraph *depsgraph =
@@ -470,7 +363,10 @@ void deg_graph_on_visible_update(Main *bmain, Depsgraph *graph)
deg_graph_id_tag_update(bmain, graph, id_node->id_orig, flag);
}
/* Make sure collection properties are up to date. */
- for (Scene *scene_iter = graph->scene; scene_iter != NULL; scene_iter = scene_iter->set) {
+ for (Scene *scene_iter = graph->scene;
+ scene_iter != NULL;
+ scene_iter = scene_iter->set)
+ {
IDDepsNode *scene_id_node = graph->find_id_node(&scene_iter->id);
BLI_assert(scene_id_node != NULL);
scene_id_node->tag_update(graph);
@@ -481,6 +377,8 @@ void deg_graph_on_visible_update(Main *bmain, Depsgraph *graph)
} // namespace DEG
+/* Data-Based Tagging */
+
/* Tag given ID for an update in all the dependency graphs. */
void DEG_id_tag_update(ID *id, int flag)
{
diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc
index 5aebd6814a0..ee58a3b02a5 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval.cc
@@ -46,20 +46,16 @@
#include "atomic_ops.h"
#include "intern/eval/deg_eval_flush.h"
+#include "intern/eval/deg_eval_stats.h"
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_id.h"
#include "intern/nodes/deg_node_operation.h"
+#include "intern/nodes/deg_node_time.h"
#include "intern/depsgraph.h"
#include "intern/depsgraph_intern.h"
-#include "util/deg_util_foreach.h"
-
-/* Unfinished and unused, and takes quite some pre-processing time. */
-#undef USE_EVAL_PRIORITY
-/* Use integrated debugger to keep track how much each of the nodes was
- * evaluating.
- */
-#undef USE_DEBUGGER
+#include "util/deg_util_foreach.h"
namespace DEG {
@@ -75,52 +71,28 @@ static void schedule_children(TaskPool *pool,
struct DepsgraphEvalState {
EvaluationContext *eval_ctx;
Depsgraph *graph;
+ bool do_stats;
};
static void deg_task_run_func(TaskPool *pool,
void *taskdata,
int thread_id)
{
- DepsgraphEvalState *state =
- reinterpret_cast<DepsgraphEvalState *>(BLI_task_pool_userdata(pool));
- OperationDepsNode *node = reinterpret_cast<OperationDepsNode *>(taskdata);
-
+ void *userdata_v = BLI_task_pool_userdata(pool);
+ DepsgraphEvalState *state = (DepsgraphEvalState *)userdata_v;
+ OperationDepsNode *node = (OperationDepsNode *)taskdata;
+ /* Sanity checks. */
BLI_assert(!node->is_noop() && "NOOP nodes should not actually be scheduled");
-
- /* Should only be the case for NOOPs, which never get to this point. */
- BLI_assert(node->evaluate);
-
- /* Get context. */
- /* TODO: Who initialises this? "Init" operations aren't able to
- * initialise it!!!
- */
- /* TODO(sergey): We don't use component contexts at this moment. */
- /* ComponentDepsNode *comp = node->owner; */
- BLI_assert(node->owner != NULL);
-
- /* Since we're not leaving the thread for until the graph branches it is
- * possible to have NO-OP on the way. for which evaluate() will be NULL.
- * but that's all fine, we'll just scheduler it's children.
- */
- if (node->evaluate) {
- /* Take note of current time. */
-#ifdef USE_DEBUGGER
- double start_time = PIL_check_seconds_timer();
- DepsgraphDebug::task_started(state->graph, node);
-#endif
-
- /* Perform operation. */
+ /* Perform operation. */
+ if (state->do_stats) {
+ const double start_time = PIL_check_seconds_timer();
node->evaluate(state->eval_ctx);
-
- /* Note how long this took. */
-#ifdef USE_DEBUGGER
- double end_time = PIL_check_seconds_timer();
- DepsgraphDebug::task_completed(state->graph,
- node,
- end_time - start_time);
-#endif
+ node->stats.current_time += PIL_check_seconds_timer() - start_time;
}
-
+ else {
+ node->evaluate(state->eval_ctx);
+ }
+ /* Schedule children. */
BLI_task_pool_delayed_push_begin(pool, thread_id);
schedule_children(pool, state->graph, node, thread_id);
BLI_task_pool_delayed_push_end(pool, thread_id);
@@ -167,32 +139,18 @@ static void calculate_pending_parents(Depsgraph *graph)
do_threads);
}
-#ifdef USE_EVAL_PRIORITY
-static void calculate_eval_priority(OperationDepsNode *node)
+static void initialize_execution(DepsgraphEvalState *state, Depsgraph *graph)
{
- if (node->done) {
- return;
- }
- node->done = 1;
-
- if (node->flag & DEPSOP_FLAG_NEEDS_UPDATE) {
- /* XXX standard cost of a node, could be estimated somewhat later on */
- const float cost = 1.0f;
- /* NOOP nodes have no cost */
- node->eval_priority = node->is_noop() ? cost : 0.0f;
-
- foreach (DepsRelation *rel, node->outlinks) {
- OperationDepsNode *to = (OperationDepsNode *)rel->to;
- BLI_assert(to->type == DEG_NODE_TYPE_OPERATION);
- calculate_eval_priority(to);
- node->eval_priority += to->eval_priority;
+ const bool do_stats = state->do_stats;
+ calculate_pending_parents(graph);
+ /* Clear tags and other things which needs to be clear. */
+ foreach (OperationDepsNode *node, graph->operations) {
+ node->done = 0;
+ if (do_stats) {
+ node->stats.reset_current();
}
}
- else {
- node->eval_priority = 0.0f;
- }
}
-#endif
/* Schedule a node if it needs evaluation.
* dec_parents: Decrement pending parents count, true when child nodes are
@@ -267,28 +225,23 @@ static void schedule_children(TaskPool *pool,
void deg_evaluate_on_refresh(EvaluationContext *eval_ctx,
Depsgraph *graph)
{
- /* Generate base evaluation context, upon which all the others are derived. */
- // TODO: this needs both main and scene access...
-
/* Nothing to update, early out. */
if (BLI_gset_size(graph->entry_tags) == 0) {
return;
}
-
/* Set time for the current graph evaluation context. */
TimeSourceDepsNode *time_src = graph->find_time_source();
eval_ctx->depsgraph = (::Depsgraph *)graph;
eval_ctx->view_layer = DEG_get_evaluated_view_layer((::Depsgraph *)graph);
eval_ctx->ctime = time_src->cfra;
-
- /* XXX could use a separate pool for each eval context */
+ /* Set up evaluation context for depsgraph itself. */
DepsgraphEvalState state;
state.eval_ctx = eval_ctx;
state.graph = graph;
-
+ state.do_stats = (G.debug_value != 0);
+ /* Set up task scheduler and pull for threaded evaluation. */
TaskScheduler *task_scheduler;
bool need_free_scheduler;
-
if (G.debug & G_DEBUG_DEPSGRAPH_NO_THREADS) {
task_scheduler = BLI_task_scheduler_create(1);
need_free_scheduler = true;
@@ -297,31 +250,22 @@ void deg_evaluate_on_refresh(EvaluationContext *eval_ctx,
task_scheduler = BLI_task_scheduler_get();
need_free_scheduler = false;
}
-
TaskPool *task_pool = BLI_task_pool_create_suspended(task_scheduler, &state);
-
- calculate_pending_parents(graph);
-
- /* Clear tags. */
- foreach (OperationDepsNode *node, graph->operations) {
- node->done = 0;
- }
-
- /* Calculate priority for operation nodes. */
-#ifdef USE_EVAL_PRIORITY
- foreach (OperationDepsNode *node, graph->operations) {
- calculate_eval_priority(node);
- }
-#endif
-
+ /* Prepare all nodes for evaluation. */
+ initialize_execution(&state, graph);
+ /* Do actual evaluation now. */
schedule_graph(task_pool, graph);
-
BLI_task_pool_work_and_wait(task_pool);
BLI_task_pool_free(task_pool);
-
+ /* Finalize statistics gathering. This is because we only gather single
+ * operation timing here, without aggregating anything to avoid any extra
+ * synchronization.
+ */
+ if (state.do_stats) {
+ deg_eval_stats_aggregate(graph);
+ }
/* Clear any uncleared tags - just in case. */
deg_graph_clear_tags(graph);
-
if (need_free_scheduler) {
BLI_task_scheduler_free(task_scheduler);
}
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
index 00406cc8342..abd17616584 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
@@ -80,6 +80,7 @@ extern "C" {
#include "intern/depsgraph.h"
#include "intern/builder/deg_builder_nodes.h"
#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_id.h"
namespace DEG {
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
index a839a8beac6..af1d09ad54a 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
@@ -47,6 +47,7 @@ extern "C" {
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_id.h"
#include "intern/nodes/deg_node_operation.h"
#include "intern/depsgraph_intern.h"
@@ -190,6 +191,7 @@ BLI_INLINE OperationDepsNode *flush_schedule_children(
return result;
}
+/* NOTE: It will also accumulate flags from changed components. */
BLI_INLINE void flush_editors_id_update(Main *bmain,
Depsgraph *graph,
const DEGEditorUpdateContext *update_ctx)
@@ -198,6 +200,7 @@ BLI_INLINE void flush_editors_id_update(Main *bmain,
if (id_node->done != ID_STATE_MODIFIED) {
continue;
}
+ DEG_id_type_tag(bmain, GS(id_node->id_orig->name));
/* TODO(sergey): Do we need to pass original or evaluated ID here? */
ID *id_orig = id_node->id_orig;
ID *id_cow = id_node->id_cow;
@@ -206,10 +209,23 @@ BLI_INLINE void flush_editors_id_update(Main *bmain,
* data.
*/
id_cow->recalc |= (id_orig->recalc & ID_RECALC_ALL);
+ /* Gather recalc flags from all changed components. */
+ GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, id_node->components)
+ {
+ if (comp_node->done != COMPONENT_STATE_DONE) {
+ continue;
+ }
+ DepsNodeFactory *factory = deg_type_get_factory(comp_node->type);
+ BLI_assert(factory != NULL);
+ id_cow->recalc |= factory->id_recalc_tag();
+ }
+ GHASH_FOREACH_END();
+ DEG_DEBUG_PRINTF("Accumulated recalc bits for %s: %u\n",
+ id_orig->name, (unsigned int)id_cow->recalc);
+ /* Inform editors. */
if (deg_copy_on_write_is_expanded(id_cow)) {
deg_editors_id_update(update_ctx, id_cow);
}
- lib_id_recalc_tag(bmain, id_orig);
}
}
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_stats.cc b/source/blender/depsgraph/intern/eval/deg_eval_stats.cc
new file mode 100644
index 00000000000..52ce744cc0a
--- /dev/null
+++ b/source/blender/depsgraph/intern/eval/deg_eval_stats.cc
@@ -0,0 +1,70 @@
+/*
+ * ***** 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Sergey Sharybin
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/eval/deg_eval_stats.cc
+ * \ingroup depsgraph
+ */
+
+#include "intern/eval/deg_eval_stats.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+
+#include "intern/depsgraph.h"
+
+#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_id.h"
+#include "intern/nodes/deg_node_operation.h"
+
+#include "util/deg_util_foreach.h"
+
+namespace DEG {
+
+void deg_eval_stats_aggregate(Depsgraph *graph)
+{
+ /* Reset current evaluation stats for ID and component nodes.
+ * Those are not filled in by the evaluation engine.
+ */
+ foreach (DepsNode *node, graph->id_nodes) {
+ IDDepsNode *id_node = (IDDepsNode *)node;
+ GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, id_node->components)
+ {
+ comp_node->stats.reset_current();
+ }
+ GHASH_FOREACH_END();
+ id_node->stats.reset_current();
+ }
+ /* Now accumulate operation timings to components and IDs. */
+ foreach (OperationDepsNode *op_node, graph->operations) {
+ ComponentDepsNode *comp_node = op_node->owner;
+ IDDepsNode *id_node = comp_node->owner;
+ id_node->stats.current_time += op_node->stats.current_time;
+ comp_node->stats.current_time += op_node->stats.current_time;
+ }
+}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_stats.h b/source/blender/depsgraph/intern/eval/deg_eval_stats.h
new file mode 100644
index 00000000000..8a7272ac89c
--- /dev/null
+++ b/source/blender/depsgraph/intern/eval/deg_eval_stats.h
@@ -0,0 +1,40 @@
+/*
+ * ***** 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 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Sergey Sharybin
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/eval/deg_eval_stats.h
+ * \ingroup depsgraph
+ */
+
+#pragma once
+
+namespace DEG {
+
+struct Depsgraph;
+
+/* Aggregate operation timings to overall component and ID nodes timing. */
+void deg_eval_stats_aggregate(Depsgraph *graph);
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/nodes/deg_node.cc b/source/blender/depsgraph/intern/nodes/deg_node.cc
index 3f70f8e1281..fdcfc129073 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node.cc
+++ b/source/blender/depsgraph/intern/nodes/deg_node.cc
@@ -31,48 +31,57 @@
#include "intern/nodes/deg_node.h"
#include <stdio.h>
-#include <cstring> /* required for STREQ later on. */
#include "BLI_utildefines.h"
-#include "BLI_ghash.h"
-
-extern "C" {
-#include "DNA_ID.h"
-#include "DNA_anim_types.h"
-#include "DNA_object_types.h"
-
-#include "BKE_animsys.h"
-#include "BKE_library.h"
-}
-
-#include "DEG_depsgraph.h"
#include "intern/eval/deg_eval_copy_on_write.h"
#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_id.h"
#include "intern/nodes/deg_node_operation.h"
+#include "intern/nodes/deg_node_time.h"
#include "intern/depsgraph_intern.h"
+
#include "util/deg_util_foreach.h"
#include "util/deg_util_function.h"
namespace DEG {
-/* *************** */
-/* Node Management */
+/*******************************************************************************
+ * Type information.
+ */
-/* Add ------------------------------------------------ */
+DepsNode::TypeInfo::TypeInfo(eDepsNode_Type type,
+ const char *tname,
+ int id_recalc_tag)
+ : type(type),
+ tname(tname),
+ id_recalc_tag(id_recalc_tag)
+{
+}
-DepsNode::TypeInfo::TypeInfo(eDepsNode_Type type, const char *tname)
+/*******************************************************************************
+ * Evaluation statistics.
+ */
+
+DepsNode::Stats::Stats()
{
- this->type = type;
- if (type == DEG_NODE_TYPE_OPERATION)
- this->tclass = DEG_NODE_CLASS_OPERATION;
- else if (type < DEG_NODE_TYPE_PARAMETERS)
- this->tclass = DEG_NODE_CLASS_GENERIC;
- else
- this->tclass = DEG_NODE_CLASS_COMPONENT;
- this->tname = tname;
+ reset();
}
+void DepsNode::Stats::reset()
+{
+ current_time = 0.0;
+}
+
+void DepsNode::Stats::reset_current()
+{
+ current_time = 0.0;
+}
+
+/*******************************************************************************
+ * Node itself.
+ */
+
DepsNode::DepsNode()
{
name = "";
@@ -100,185 +109,24 @@ string DepsNode::identifier() const
return string(typebuf) + " : " + name;
}
-/* ************* */
-/* Generic Nodes */
-
-/* Time Source Node ============================================== */
-
-void TimeSourceDepsNode::tag_update(Depsgraph *graph)
-{
- foreach (DepsRelation *rel, outlinks) {
- DepsNode *node = rel->to;
- node->tag_update(graph);
- }
-}
-
-/* Time Source Node ======================================= */
-
-DEG_DEPSNODE_DEFINE(TimeSourceDepsNode, DEG_NODE_TYPE_TIMESOURCE, "Time Source");
-static DepsNodeFactoryImpl<TimeSourceDepsNode> DNTI_TIMESOURCE;
-
-/* ID Node ================================================ */
-
-IDDepsNode::ComponentIDKey::ComponentIDKey(eDepsNode_Type type,
- const char *name)
- : type(type), name(name)
-{
-}
-
-bool IDDepsNode::ComponentIDKey::operator== (const ComponentIDKey &other) const
-{
- return type == other.type &&
- STREQ(name, other.name);
-}
-
-static unsigned int id_deps_node_hash_key(const void *key_v)
-{
- const IDDepsNode::ComponentIDKey *key =
- reinterpret_cast<const IDDepsNode::ComponentIDKey *>(key_v);
- return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(key->type),
- BLI_ghashutil_strhash_p(key->name));
-}
-
-static bool id_deps_node_hash_key_cmp(const void *a, const void *b)
-{
- const IDDepsNode::ComponentIDKey *key_a =
- reinterpret_cast<const IDDepsNode::ComponentIDKey *>(a);
- const IDDepsNode::ComponentIDKey *key_b =
- reinterpret_cast<const IDDepsNode::ComponentIDKey *>(b);
- return !(*key_a == *key_b);
-}
-
-static void id_deps_node_hash_key_free(void *key_v)
-{
- typedef IDDepsNode::ComponentIDKey ComponentIDKey;
- ComponentIDKey *key = reinterpret_cast<ComponentIDKey *>(key_v);
- OBJECT_GUARDED_DELETE(key, ComponentIDKey);
-}
-
-static void id_deps_node_hash_value_free(void *value_v)
-{
- ComponentDepsNode *comp_node = reinterpret_cast<ComponentDepsNode *>(value_v);
- OBJECT_GUARDED_DELETE(comp_node, ComponentDepsNode);
-}
-
-/* Initialize 'id' node - from pointer data given. */
-void IDDepsNode::init(const ID *id, const char *UNUSED(subdata))
-{
- BLI_assert(id != NULL);
- /* Store ID-pointer. */
- id_orig = (ID *)id;
- eval_flags = 0;
- linked_state = DEG_ID_LINKED_INDIRECTLY;
-
- components = BLI_ghash_new(id_deps_node_hash_key,
- id_deps_node_hash_key_cmp,
- "Depsgraph id components hash");
-}
-
-void IDDepsNode::init_copy_on_write(ID *id_cow_hint)
-{
- /* Early output for non-copy-on-write case: we keep CoW pointer same as
- * an original one.
- */
- if (!DEG_depsgraph_use_copy_on_write()) {
- UNUSED_VARS(id_cow_hint);
- id_cow = id_orig;
- return;
+eDepsNode_Class DepsNode::get_class() const {
+ if (type == DEG_NODE_TYPE_OPERATION) {
+ return DEG_NODE_CLASS_OPERATION;
}
- /* Create pointer as early as possible, so we can use it for function
- * bindings. Rest of data we'll be copying to the new datablock when
- * it is actually needed.
- */
- if (id_cow_hint != NULL) {
- // BLI_assert(deg_copy_on_write_is_needed(id_orig));
- if (deg_copy_on_write_is_needed(id_orig)) {
- id_cow = id_cow_hint;
- }
- else {
- id_cow = id_orig;
- }
- }
- else if (deg_copy_on_write_is_needed(id_orig)) {
- id_cow = (ID *)BKE_libblock_alloc_notest(GS(id_orig->name));
- DEG_COW_PRINT("Create shallow copy for %s: id_orig=%p id_cow=%p\n",
- id_orig->name, id_orig, id_cow);
- deg_tag_copy_on_write_id(id_cow, id_orig);
+ else if (type < DEG_NODE_TYPE_PARAMETERS) {
+ return DEG_NODE_CLASS_GENERIC;
}
else {
- id_cow = id_orig;
- }
-}
-
-/* Free 'id' node. */
-IDDepsNode::~IDDepsNode()
-{
- destroy();
-}
-
-void IDDepsNode::destroy()
-{
- if (id_orig == NULL) {
- return;
- }
-
- BLI_ghash_free(components,
- id_deps_node_hash_key_free,
- id_deps_node_hash_value_free);
-
- /* Free memory used by this CoW ID. */
- if (id_cow != id_orig && id_cow != NULL) {
- deg_free_copy_on_write_datablock(id_cow);
- MEM_freeN(id_cow);
- DEG_COW_PRINT("Destroy CoW for %s: id_orig=%p id_cow=%p\n",
- id_orig->name, id_orig, id_cow);
- }
-
- /* Tag that the node is freed. */
- id_orig = NULL;
-}
-
-ComponentDepsNode *IDDepsNode::find_component(eDepsNode_Type type,
- const char *name) const
-{
- ComponentIDKey key(type, name);
- return reinterpret_cast<ComponentDepsNode *>(BLI_ghash_lookup(components, &key));
-}
-
-ComponentDepsNode *IDDepsNode::add_component(eDepsNode_Type type,
- const char *name)
-{
- ComponentDepsNode *comp_node = find_component(type, name);
- if (!comp_node) {
- DepsNodeFactory *factory = deg_type_get_factory(type);
- comp_node = (ComponentDepsNode *)factory->create_node(this->id_orig, "", name);
-
- /* Register. */
- ComponentIDKey *key = OBJECT_GUARDED_NEW(ComponentIDKey, type, name);
- BLI_ghash_insert(components, key, comp_node);
- comp_node->owner = this;
+ return DEG_NODE_CLASS_COMPONENT;
}
- return comp_node;
}
-void IDDepsNode::tag_update(Depsgraph *graph)
-{
- GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, components)
- {
- comp_node->tag_update(graph);
- }
- GHASH_FOREACH_END();
-}
-
-void IDDepsNode::finalize_build(Depsgraph *graph)
-{
- /* Finalize build of all components. */
- GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, components)
- {
- comp_node->finalize_build(graph);
- }
- GHASH_FOREACH_END();
-}
+/*******************************************************************************
+ * Generic nodes definition.
+ */
+\
+DEG_DEPSNODE_DEFINE(TimeSourceDepsNode, DEG_NODE_TYPE_TIMESOURCE, "Time Source");
+static DepsNodeFactoryImpl<TimeSourceDepsNode> DNTI_TIMESOURCE;
DEG_DEPSNODE_DEFINE(IDDepsNode, DEG_NODE_TYPE_ID_REF, "ID Node");
static DepsNodeFactoryImpl<IDDepsNode> DNTI_ID_REF;
diff --git a/source/blender/depsgraph/intern/nodes/deg_node.h b/source/blender/depsgraph/intern/nodes/deg_node.h
index fd3ed694c9c..603a6be7ceb 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node.h
+++ b/source/blender/depsgraph/intern/nodes/deg_node.h
@@ -51,22 +51,24 @@ struct OperationDepsNode;
struct DepsNode {
/* Helper class for static typeinfo in subclasses. */
struct TypeInfo {
- TypeInfo(eDepsNode_Type type, const char *tname);
-
+ TypeInfo(eDepsNode_Type type, const char *tname, int id_recalc_tag = 0);
eDepsNode_Type type;
- eDepsNode_Class tclass;
const char *tname;
+ int id_recalc_tag;
+ };
+ struct Stats {
+ Stats();
+ /* Reset all the counters. Including all stats needed for average
+ * evaluation time calculation.
+ */
+ void reset();
+ /* Reset counters needed for the current graph evaluation, does not
+ * touch averaging accumulators.
+ */
+ void reset_current();
+ /* Time spend on this node during current graph evaluation. */
+ double current_time;
};
-
- /* Identifier - mainly for debugging purposes. */
- const char *name;
-
- /* Structural type of node. */
- eDepsNode_Type type;
-
- /* Type of data/behaviour represented by node... */
- eDepsNode_Class tclass;
-
/* Relationships between nodes
* The reason why all depsgraph nodes are descended from this type (apart
* from basic serialization benefits - from the typeinfo) is that we can have
@@ -74,23 +76,18 @@ struct DepsNode {
*/
typedef vector<DepsRelation *> Relations;
- /* Nodes which this one depends on. */
- Relations inlinks;
-
- /* Nodes which depend on this one. */
- Relations outlinks;
-
- /* Generic tags for traversal algorithms. */
- int done;
- int tag;
+ const char *name; /* Identifier - mainly for debugging purposes. */
+ eDepsNode_Type type; /* Structural type of node. */
+ Relations inlinks; /* Nodes which this one depends on. */
+ Relations outlinks; /* Nodes which depend on this one. */
+ int done; /* Generic tags for traversal algorithms. */
+ Stats stats; /* Evaluation statistics. */
/* Methods. */
-
DepsNode();
virtual ~DepsNode();
virtual string identifier() const;
- string full_identifier() const;
virtual void init(const ID * /*id*/,
const char * /*subdata*/) {}
@@ -99,6 +96,8 @@ struct DepsNode {
virtual OperationDepsNode *get_entry_operation() { return NULL; }
virtual OperationDepsNode *get_exit_operation() { return NULL; }
+
+ virtual eDepsNode_Class get_class() const;
};
/* Macros for common static typeinfo. */
@@ -107,68 +106,6 @@ struct DepsNode {
#define DEG_DEPSNODE_DEFINE(NodeType, type_, tname_) \
const DepsNode::TypeInfo NodeType::typeinfo = DepsNode::TypeInfo(type_, tname_)
-/* Generic Nodes ======================= */
-
-struct ComponentDepsNode;
-struct IDDepsNode;
-
-/* Time Source Node. */
-struct TimeSourceDepsNode : public DepsNode {
- /* New "current time". */
- float cfra;
-
- /* time-offset relative to the "official" time source that this one has. */
- float offset;
-
- // TODO: evaluate() operation needed
-
- void tag_update(Depsgraph *graph);
-
- DEG_DEPSNODE_DECLARE;
-};
-
-/* ID-Block Reference */
-struct IDDepsNode : public DepsNode {
- struct ComponentIDKey {
- ComponentIDKey(eDepsNode_Type type, const char *name = "");
- bool operator==(const ComponentIDKey &other) const;
-
- eDepsNode_Type type;
- const char *name;
- };
-
- void init(const ID *id, const char *subdata);
- void init_copy_on_write(ID *id_cow_hint = NULL);
- ~IDDepsNode();
- void destroy();
-
- ComponentDepsNode *find_component(eDepsNode_Type type,
- const char *name = "") const;
- ComponentDepsNode *add_component(eDepsNode_Type type,
- const char *name = "");
-
- void tag_update(Depsgraph *graph);
-
- void finalize_build(Depsgraph *graph);
-
- /* ID Block referenced. */
- ID *id_orig;
- ID *id_cow;
-
- /* Hash to make it faster to look up components. */
- GHash *components;
-
- /* Additional flags needed for scene evaluation.
- * TODO(sergey): Only needed for until really granular updates
- * of all the entities.
- */
- int eval_flags;
-
- eDepsNode_LinkedState_Type linked_state;
-
- DEG_DEPSNODE_DECLARE;
-};
-
void deg_register_base_depsnodes();
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/nodes/deg_node_component.cc b/source/blender/depsgraph/intern/nodes/deg_node_component.cc
index f4530ecebdb..1f56edd1f87 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node_component.cc
+++ b/source/blender/depsgraph/intern/nodes/deg_node_component.cc
@@ -42,6 +42,7 @@ extern "C" {
#include "BKE_action.h"
} /* extern "C" */
+#include "intern/nodes/deg_node_id.h"
#include "intern/nodes/deg_node_operation.h"
#include "intern/depsgraph_intern.h"
#include "util/deg_util_foreach.h"
@@ -355,30 +356,6 @@ void ComponentDepsNode::finalize_build(Depsgraph * /*graph*/)
operations_map = NULL;
}
-/* Register all components. =============================== */
-
-#define DEG_COMPONENT_DEFINE(name, NAME) \
- DEG_DEPSNODE_DEFINE(name ## ComponentDepsNode, \
- DEG_NODE_TYPE_ ## NAME, \
- #name " Component"); \
-static DepsNodeFactoryImpl<name ## ComponentDepsNode> DNTI_ ## NAME
-
-
-DEG_COMPONENT_DEFINE(Animation, ANIMATION);
-DEG_COMPONENT_DEFINE(BatchCache, BATCH_CACHE);
-DEG_COMPONENT_DEFINE(Cache, CACHE);
-DEG_COMPONENT_DEFINE(CopyOnWrite, COPY_ON_WRITE);
-DEG_COMPONENT_DEFINE(Geometry, GEOMETRY);
-DEG_COMPONENT_DEFINE(LayerCollections, LAYER_COLLECTIONS);
-DEG_COMPONENT_DEFINE(Parameters, PARAMETERS);
-DEG_COMPONENT_DEFINE(Particles, EVAL_PARTICLES);
-DEG_COMPONENT_DEFINE(Proxy, PROXY);
-DEG_COMPONENT_DEFINE(Pose, EVAL_POSE);
-DEG_COMPONENT_DEFINE(Sequencer, SEQUENCER);
-DEG_COMPONENT_DEFINE(Shading, SHADING);
-DEG_COMPONENT_DEFINE(ShadingParameters, SHADING_PARAMETERS);
-DEG_COMPONENT_DEFINE(Transform, TRANSFORM);
-
/* Bone Component ========================================= */
/* Initialize 'bone component' node - from pointer data given */
@@ -398,7 +375,23 @@ void BoneComponentDepsNode::init(const ID *id, const char *subdata)
this->pchan = BKE_pose_channel_find_name(object->pose, subdata);
}
-DEG_COMPONENT_DEFINE(Bone, BONE);
+/* Register all components. =============================== */
+
+DEG_COMPONENT_NODE_DEFINE(Animation, ANIMATION, ID_RECALC_ANIMATION);
+DEG_COMPONENT_NODE_DEFINE(BatchCache, BATCH_CACHE, ID_RECALC_DRAW_CACHE);
+DEG_COMPONENT_NODE_DEFINE(Bone, BONE, ID_RECALC_GEOMETRY);
+DEG_COMPONENT_NODE_DEFINE(Cache, CACHE, ID_RECALC);
+DEG_COMPONENT_NODE_DEFINE(CopyOnWrite, COPY_ON_WRITE, ID_RECALC);
+DEG_COMPONENT_NODE_DEFINE(Geometry, GEOMETRY, ID_RECALC_GEOMETRY);
+DEG_COMPONENT_NODE_DEFINE(LayerCollections, LAYER_COLLECTIONS, ID_RECALC_COLLECTIONS);
+DEG_COMPONENT_NODE_DEFINE(Parameters, PARAMETERS, ID_RECALC);
+DEG_COMPONENT_NODE_DEFINE(Particles, EVAL_PARTICLES, ID_RECALC_GEOMETRY);
+DEG_COMPONENT_NODE_DEFINE(Proxy, PROXY, ID_RECALC_GEOMETRY);
+DEG_COMPONENT_NODE_DEFINE(Pose, EVAL_POSE, ID_RECALC_GEOMETRY);
+DEG_COMPONENT_NODE_DEFINE(Sequencer, SEQUENCER, ID_RECALC);
+DEG_COMPONENT_NODE_DEFINE(Shading, SHADING, ID_RECALC_DRAW);
+DEG_COMPONENT_NODE_DEFINE(ShadingParameters, SHADING_PARAMETERS, ID_RECALC_DRAW);
+DEG_COMPONENT_NODE_DEFINE(Transform, TRANSFORM, ID_RECALC_TRANSFORM);
/* Node Types Register =================================== */
diff --git a/source/blender/depsgraph/intern/nodes/deg_node_component.h b/source/blender/depsgraph/intern/nodes/deg_node_component.h
index ba4f8551fea..b8009cc0a7f 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node_component.h
+++ b/source/blender/depsgraph/intern/nodes/deg_node_component.h
@@ -46,6 +46,7 @@ namespace DEG {
struct Depsgraph;
struct OperationDepsNode;
struct BoneComponentDepsNode;
+struct IDDepsNode;
/* ID Component - Base type for all components */
struct ComponentDepsNode : public DepsNode {
@@ -123,19 +124,6 @@ struct ComponentDepsNode : public DepsNode {
void tag_update(Depsgraph *graph);
- /* Evaluation Context Management .................. */
-
- /* Initialize component's evaluation context used for the specified
- * purpose.
- */
- virtual bool eval_context_init(EvaluationContext * /*eval_ctx*/) { return false; }
- /* Free data in component's evaluation context which is used for
- * the specified purpose
- *
- * NOTE: this does not free the actual context in question
- */
- virtual void eval_context_free(EvaluationContext * /*eval_ctx*/) {}
-
OperationDepsNode *get_entry_operation();
OperationDepsNode *get_exit_operation();
@@ -164,25 +152,38 @@ struct ComponentDepsNode : public DepsNode {
/* ---------------------------------------- */
-#define DEG_COMPONENT_DECLARE_GENERIC(name) \
+#define DEG_COMPONENT_NODE_DEFINE_TYPEINFO(NodeType, type_, tname_, id_recalc_tag) \
+ const DepsNode::TypeInfo NodeType::typeinfo = \
+ DepsNode::TypeInfo(type_, tname_, id_recalc_tag)
+
+#define DEG_COMPONENT_NODE_DECLARE DEG_DEPSNODE_DECLARE
+
+#define DEG_COMPONENT_NODE_DEFINE(name, NAME, id_recalc_tag) \
+ DEG_COMPONENT_NODE_DEFINE_TYPEINFO(name ## ComponentDepsNode, \
+ DEG_NODE_TYPE_ ## NAME, \
+ #name " Component", \
+ id_recalc_tag) ; \
+ static DepsNodeFactoryImpl<name ## ComponentDepsNode> DNTI_ ## NAME
+
+#define DEG_COMPONENT_NODE_DECLARE_GENERIC(name) \
struct name ## ComponentDepsNode : public ComponentDepsNode { \
- DEG_DEPSNODE_DECLARE; \
+ DEG_COMPONENT_NODE_DECLARE; \
}
-DEG_COMPONENT_DECLARE_GENERIC(Animation);
-DEG_COMPONENT_DECLARE_GENERIC(BatchCache);
-DEG_COMPONENT_DECLARE_GENERIC(Cache);
-DEG_COMPONENT_DECLARE_GENERIC(CopyOnWrite);
-DEG_COMPONENT_DECLARE_GENERIC(Geometry);
-DEG_COMPONENT_DECLARE_GENERIC(LayerCollections);
-DEG_COMPONENT_DECLARE_GENERIC(Parameters);
-DEG_COMPONENT_DECLARE_GENERIC(Particles);
-DEG_COMPONENT_DECLARE_GENERIC(Proxy);
-DEG_COMPONENT_DECLARE_GENERIC(Pose);
-DEG_COMPONENT_DECLARE_GENERIC(Sequencer);
-DEG_COMPONENT_DECLARE_GENERIC(Shading);
-DEG_COMPONENT_DECLARE_GENERIC(ShadingParameters);
-DEG_COMPONENT_DECLARE_GENERIC(Transform);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(Animation);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(BatchCache);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(Cache);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(CopyOnWrite);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(Geometry);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(LayerCollections);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(Parameters);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(Particles);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(Proxy);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(Pose);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(Sequencer);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(Shading);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(ShadingParameters);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(Transform);
/* Bone Component */
struct BoneComponentDepsNode : public ComponentDepsNode {
@@ -190,7 +191,7 @@ struct BoneComponentDepsNode : public ComponentDepsNode {
struct bPoseChannel *pchan; /* the bone that this component represents */
- DEG_DEPSNODE_DECLARE;
+ DEG_COMPONENT_NODE_DECLARE;
};
void deg_register_component_depsnodes();
diff --git a/source/blender/depsgraph/intern/nodes/deg_node_id.cc b/source/blender/depsgraph/intern/nodes/deg_node_id.cc
new file mode 100644
index 00000000000..edc5c0114f9
--- /dev/null
+++ b/source/blender/depsgraph/intern/nodes/deg_node_id.cc
@@ -0,0 +1,217 @@
+/*
+ * ***** 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) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/nodes/deg_node_id.cc
+ * \ingroup depsgraph
+ */
+
+#include "intern/nodes/deg_node_id.h"
+
+#include <stdio.h>
+#include <cstring> /* required for STREQ later on. */
+
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+
+extern "C" {
+#include "DNA_ID.h"
+#include "DNA_anim_types.h"
+
+#include "BKE_animsys.h"
+#include "BKE_library.h"
+}
+
+#include "DEG_depsgraph.h"
+
+#include "intern/eval/deg_eval_copy_on_write.h"
+#include "intern/nodes/deg_node_time.h"
+#include "intern/depsgraph_intern.h"
+
+#include "util/deg_util_foreach.h"
+
+namespace DEG {
+
+IDDepsNode::ComponentIDKey::ComponentIDKey(eDepsNode_Type type,
+ const char *name)
+ : type(type), name(name)
+{
+}
+
+bool IDDepsNode::ComponentIDKey::operator== (const ComponentIDKey &other) const
+{
+ return type == other.type &&
+ STREQ(name, other.name);
+}
+
+static unsigned int id_deps_node_hash_key(const void *key_v)
+{
+ const IDDepsNode::ComponentIDKey *key =
+ reinterpret_cast<const IDDepsNode::ComponentIDKey *>(key_v);
+ return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(key->type),
+ BLI_ghashutil_strhash_p(key->name));
+}
+
+static bool id_deps_node_hash_key_cmp(const void *a, const void *b)
+{
+ const IDDepsNode::ComponentIDKey *key_a =
+ reinterpret_cast<const IDDepsNode::ComponentIDKey *>(a);
+ const IDDepsNode::ComponentIDKey *key_b =
+ reinterpret_cast<const IDDepsNode::ComponentIDKey *>(b);
+ return !(*key_a == *key_b);
+}
+
+static void id_deps_node_hash_key_free(void *key_v)
+{
+ typedef IDDepsNode::ComponentIDKey ComponentIDKey;
+ ComponentIDKey *key = reinterpret_cast<ComponentIDKey *>(key_v);
+ OBJECT_GUARDED_DELETE(key, ComponentIDKey);
+}
+
+static void id_deps_node_hash_value_free(void *value_v)
+{
+ ComponentDepsNode *comp_node = reinterpret_cast<ComponentDepsNode *>(value_v);
+ OBJECT_GUARDED_DELETE(comp_node, ComponentDepsNode);
+}
+
+/* Initialize 'id' node - from pointer data given. */
+void IDDepsNode::init(const ID *id, const char *UNUSED(subdata))
+{
+ BLI_assert(id != NULL);
+ /* Store ID-pointer. */
+ id_orig = (ID *)id;
+ eval_flags = 0;
+ linked_state = DEG_ID_LINKED_INDIRECTLY;
+
+ components = BLI_ghash_new(id_deps_node_hash_key,
+ id_deps_node_hash_key_cmp,
+ "Depsgraph id components hash");
+}
+
+void IDDepsNode::init_copy_on_write(ID *id_cow_hint)
+{
+ /* Early output for non-copy-on-write case: we keep CoW pointer same as
+ * an original one.
+ */
+ if (!DEG_depsgraph_use_copy_on_write()) {
+ UNUSED_VARS(id_cow_hint);
+ id_cow = id_orig;
+ return;
+ }
+ /* Create pointer as early as possible, so we can use it for function
+ * bindings. Rest of data we'll be copying to the new datablock when
+ * it is actually needed.
+ */
+ if (id_cow_hint != NULL) {
+ // BLI_assert(deg_copy_on_write_is_needed(id_orig));
+ if (deg_copy_on_write_is_needed(id_orig)) {
+ id_cow = id_cow_hint;
+ }
+ else {
+ id_cow = id_orig;
+ }
+ }
+ else if (deg_copy_on_write_is_needed(id_orig)) {
+ id_cow = (ID *)BKE_libblock_alloc_notest(GS(id_orig->name));
+ DEG_COW_PRINT("Create shallow copy for %s: id_orig=%p id_cow=%p\n",
+ id_orig->name, id_orig, id_cow);
+ deg_tag_copy_on_write_id(id_cow, id_orig);
+ }
+ else {
+ id_cow = id_orig;
+ }
+}
+
+/* Free 'id' node. */
+IDDepsNode::~IDDepsNode()
+{
+ destroy();
+}
+
+void IDDepsNode::destroy()
+{
+ if (id_orig == NULL) {
+ return;
+ }
+
+ BLI_ghash_free(components,
+ id_deps_node_hash_key_free,
+ id_deps_node_hash_value_free);
+
+ /* Free memory used by this CoW ID. */
+ if (id_cow != id_orig && id_cow != NULL) {
+ deg_free_copy_on_write_datablock(id_cow);
+ MEM_freeN(id_cow);
+ DEG_COW_PRINT("Destroy CoW for %s: id_orig=%p id_cow=%p\n",
+ id_orig->name, id_orig, id_cow);
+ }
+
+ /* Tag that the node is freed. */
+ id_orig = NULL;
+}
+
+ComponentDepsNode *IDDepsNode::find_component(eDepsNode_Type type,
+ const char *name) const
+{
+ ComponentIDKey key(type, name);
+ return reinterpret_cast<ComponentDepsNode *>(BLI_ghash_lookup(components, &key));
+}
+
+ComponentDepsNode *IDDepsNode::add_component(eDepsNode_Type type,
+ const char *name)
+{
+ ComponentDepsNode *comp_node = find_component(type, name);
+ if (!comp_node) {
+ DepsNodeFactory *factory = deg_type_get_factory(type);
+ comp_node = (ComponentDepsNode *)factory->create_node(this->id_orig, "", name);
+
+ /* Register. */
+ ComponentIDKey *key = OBJECT_GUARDED_NEW(ComponentIDKey, type, name);
+ BLI_ghash_insert(components, key, comp_node);
+ comp_node->owner = this;
+ }
+ return comp_node;
+}
+
+void IDDepsNode::tag_update(Depsgraph *graph)
+{
+ GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, components)
+ {
+ comp_node->tag_update(graph);
+ }
+ GHASH_FOREACH_END();
+}
+
+void IDDepsNode::finalize_build(Depsgraph *graph)
+{
+ /* Finalize build of all components. */
+ GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, components)
+ {
+ comp_node->finalize_build(graph);
+ }
+ GHASH_FOREACH_END();
+}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/nodes/deg_node_id.h b/source/blender/depsgraph/intern/nodes/deg_node_id.h
new file mode 100644
index 00000000000..505a1129192
--- /dev/null
+++ b/source/blender/depsgraph/intern/nodes/deg_node_id.h
@@ -0,0 +1,81 @@
+/*
+ * ***** 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) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file depsgraph/intern/nodes/deg_node_id.h
+ * \ingroup depsgraph
+ */
+
+#pragma once
+
+#include "intern/nodes/deg_node.h"
+
+namespace DEG {
+
+struct ComponentDepsNode;
+
+/* ID-Block Reference */
+struct IDDepsNode : public DepsNode {
+ struct ComponentIDKey {
+ ComponentIDKey(eDepsNode_Type type, const char *name = "");
+ bool operator==(const ComponentIDKey &other) const;
+
+ eDepsNode_Type type;
+ const char *name;
+ };
+
+ void init(const ID *id, const char *subdata);
+ void init_copy_on_write(ID *id_cow_hint = NULL);
+ ~IDDepsNode();
+ void destroy();
+
+ ComponentDepsNode *find_component(eDepsNode_Type type,
+ const char *name = "") const;
+ ComponentDepsNode *add_component(eDepsNode_Type type,
+ const char *name = "");
+
+ void tag_update(Depsgraph *graph);
+
+ void finalize_build(Depsgraph *graph);
+
+ /* ID Block referenced. */
+ ID *id_orig;
+ ID *id_cow;
+
+ /* Hash to make it faster to look up components. */
+ GHash *components;
+
+ /* Additional flags needed for scene evaluation.
+ * TODO(sergey): Only needed for until really granular updates
+ * of all the entities.
+ */
+ int eval_flags;
+
+ eDepsNode_LinkedState_Type linked_state;
+
+ DEG_DEPSNODE_DECLARE;
+};
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/nodes/deg_node_operation.cc b/source/blender/depsgraph/intern/nodes/deg_node_operation.cc
index 7467264f612..cbc0fbb4241 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node_operation.cc
+++ b/source/blender/depsgraph/intern/nodes/deg_node_operation.cc
@@ -37,6 +37,7 @@
#include "intern/depsgraph.h"
#include "intern/depsgraph_intern.h"
+#include "intern/nodes/deg_node_id.h"
namespace DEG {
@@ -44,7 +45,6 @@ namespace DEG {
/* Inner Nodes */
OperationDepsNode::OperationDepsNode() :
- eval_priority(0.0f),
flag(0),
customdata_mask(0)
{
diff --git a/source/blender/depsgraph/intern/nodes/deg_node_operation.h b/source/blender/depsgraph/intern/nodes/deg_node_operation.h
index d8203540fc5..c172f73be5f 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node_operation.h
+++ b/source/blender/depsgraph/intern/nodes/deg_node_operation.h
@@ -38,6 +38,8 @@ struct Depsgraph;
namespace DEG {
+struct ComponentDepsNode;
+
/* Flags for Depsgraph Nodes */
typedef enum eDepsOperation_Flag {
/* node needs to be updated */
@@ -74,7 +76,6 @@ struct OperationDepsNode : public DepsNode {
/* How many inlinks are we still waiting on before we can be evaluated. */
uint32_t num_links_pending;
- float eval_priority;
bool scheduled;
/* Identifier for the operation being performed. */
diff --git a/source/blender/depsgraph/intern/nodes/deg_node_time.cc b/source/blender/depsgraph/intern/nodes/deg_node_time.cc
new file mode 100644
index 00000000000..230488b2328
--- /dev/null
+++ b/source/blender/depsgraph/intern/nodes/deg_node_time.cc
@@ -0,0 +1,46 @@
+/*
+ * ***** 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) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/nodes/deg_node_time.cc
+ * \ingroup depsgraph
+ */
+
+#include "intern/nodes/deg_node_time.h"
+
+#include "intern/depsgraph_intern.h"
+#include "util/deg_util_foreach.h"
+
+namespace DEG {
+
+void TimeSourceDepsNode::tag_update(Depsgraph *graph)
+{
+ foreach (DepsRelation *rel, outlinks) {
+ DepsNode *node = rel->to;
+ node->tag_update(graph);
+ }
+}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/nodes/deg_node_time.h b/source/blender/depsgraph/intern/nodes/deg_node_time.h
new file mode 100644
index 00000000000..93f3edef9cf
--- /dev/null
+++ b/source/blender/depsgraph/intern/nodes/deg_node_time.h
@@ -0,0 +1,52 @@
+/*
+ * ***** 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) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file depsgraph/intern/nodes/deg_node_time.h
+ * \ingroup depsgraph
+ */
+
+#pragma once
+
+#include "intern/nodes/deg_node.h"
+
+namespace DEG {
+
+/* Time Source Node. */
+struct TimeSourceDepsNode : public DepsNode {
+ /* New "current time". */
+ float cfra;
+
+ /* time-offset relative to the "official" time source that this one has. */
+ float offset;
+
+ // TODO: evaluate() operation needed
+
+ void tag_update(Depsgraph *graph);
+
+ DEG_DEPSNODE_DECLARE;
+};
+
+} // namespace DEG
diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h
index ba0f8681f10..7efd9639874 100644
--- a/source/blender/draw/DRW_engine.h
+++ b/source/blender/draw/DRW_engine.h
@@ -95,6 +95,7 @@ void DRW_draw_render_loop_offscreen(
struct Depsgraph *graph,
struct RenderEngineType *engine_type,
struct ARegion *ar, struct View3D *v3d,
+ const bool draw_background,
struct GPUOffScreen *ofs);
void DRW_draw_select_loop(
struct Depsgraph *graph,
diff --git a/source/blender/draw/engines/clay/clay_engine.c b/source/blender/draw/engines/clay/clay_engine.c
index 01f89ae6b1c..9f9ebd692b9 100644
--- a/source/blender/draw/engines/clay/clay_engine.c
+++ b/source/blender/draw/engines/clay/clay_engine.c
@@ -746,12 +746,45 @@ static void clay_cache_init(void *vedata)
}
}
+static void clay_cache_populate_particles(void *vedata, Object *ob)
+{
+ CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
+ CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+
+
+ Scene *scene = draw_ctx->scene;
+ Object *obedit = scene->obedit;
+
+ if (ob != obedit) {
+ for (ParticleSystem *psys = ob->particlesystem.first; psys; psys = psys->next) {
+ if (psys_check_enabled(ob, psys, false)) {
+ ParticleSettings *part = psys->part;
+ int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as;
+
+ if (draw_as == PART_DRAW_PATH && !psys->pathcache && !psys->childcache) {
+ draw_as = PART_DRAW_DOT;
+ }
+
+ static float mat[4][4];
+ unit_m4(mat);
+
+ if (draw_as == PART_DRAW_PATH) {
+ struct Gwn_Batch *geom = DRW_cache_particles_get_hair(psys, NULL);
+ DRWShadingGroup *hair_shgrp = CLAY_hair_shgrp_get(vedata, ob, stl, psl);
+ DRW_shgroup_call_add(hair_shgrp, geom, mat);
+ }
+ }
+ }
+ }
+}
+
static void clay_cache_populate(void *vedata, Object *ob)
{
CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
- DRWShadingGroup *clay_shgrp, *hair_shgrp;
+ DRWShadingGroup *clay_shgrp;
if (!DRW_object_is_renderable(ob))
return;
@@ -764,6 +797,15 @@ static void clay_cache_populate(void *vedata, Object *ob)
}
}
+ /* Handle particles first in case the emitter itself shouldn't be rendered. */
+ if (ob->type == OB_MESH) {
+ clay_cache_populate_particles(vedata, ob);
+ }
+
+ if (DRW_check_object_visible_within_active_context(ob) == false) {
+ return;
+ }
+
struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob);
if (geom) {
IDProperty *ces_mode_ob = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_OBJECT, "");
@@ -797,33 +839,6 @@ static void clay_cache_populate(void *vedata, Object *ob)
DRW_shgroup_call_add(clay_shgrp, geom, ob->obmat);
}
}
-
- if (ob->type == OB_MESH) {
- Scene *scene = draw_ctx->scene;
- Object *obedit = scene->obedit;
-
- if (ob != obedit) {
- for (ParticleSystem *psys = ob->particlesystem.first; psys; psys = psys->next) {
- if (psys_check_enabled(ob, psys, false)) {
- ParticleSettings *part = psys->part;
- int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as;
-
- if (draw_as == PART_DRAW_PATH && !psys->pathcache && !psys->childcache) {
- draw_as = PART_DRAW_DOT;
- }
-
- static float mat[4][4];
- unit_m4(mat);
-
- if (draw_as == PART_DRAW_PATH) {
- geom = DRW_cache_particles_get_hair(psys, NULL);
- hair_shgrp = CLAY_hair_shgrp_get(vedata, ob, stl, psl);
- DRW_shgroup_call_add(hair_shgrp, geom, mat);
- }
- }
- }
- }
- }
}
static void clay_cache_finish(void *vedata)
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index f24381e1fb4..31ce5d4174d 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -56,7 +56,7 @@ static void eevee_engine_init(void *ved)
/* Alloc transient pointers */
stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
}
- stl->g_data->background_alpha = 1.0f;
+ stl->g_data->background_alpha = DRW_state_draw_background() ? 1.0f : 0.0f;
stl->g_data->valid_double_buffer = (txl->color_double_buffer != NULL);
DRWFboTexture tex = {&txl->color, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
@@ -113,6 +113,10 @@ static void eevee_cache_populate(void *vedata, Object *ob)
}
}
+ if (DRW_check_object_visible_within_active_context(ob) == false) {
+ return;
+ }
+
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) {
EEVEE_materials_cache_populate(vedata, sldata, ob);
@@ -283,6 +287,13 @@ static void eevee_view_update(void *vedata)
static void eevee_id_update(void *UNUSED(vedata), ID *id)
{
+ /* This is a bit mask of components which update is to be ignored. */
+ const int ignore_updates = ID_RECALC_COLLECTIONS;
+ /* Check whether we have to do anything here. */
+ if ((id->recalc & ~ignore_updates) == 0) {
+ return;
+ }
+ /* Handle updates based on ID type. */
const ID_Type id_type = GS(id->name);
if (id_type == ID_OB) {
Object *object = (Object *)id;
@@ -407,8 +418,8 @@ DrawEngineType draw_engine_eevee_type = {
&eevee_cache_init,
&eevee_cache_populate,
&eevee_cache_finish,
+ NULL,
&eevee_draw_scene,
- NULL, //&EEVEE_draw_scene
&eevee_view_update,
&eevee_id_update,
};
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 0753dbc7a1a..505371d8e3b 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -396,6 +396,7 @@ void DRW_lamp_engine_data_free(struct LampEngineData *led);
/* Settings */
bool DRW_object_is_renderable(struct Object *ob);
+bool DRW_check_object_visible_within_active_context(struct Object *ob);
bool DRW_object_is_flat_normal(const struct Object *ob);
int DRW_object_is_mode_shade(const struct Object *ob);
@@ -431,6 +432,9 @@ bool DRW_state_is_image_render(void);
bool DRW_state_is_scene_render(void);
bool DRW_state_show_text(void);
bool DRW_state_draw_support(void);
+bool DRW_state_draw_background(void);
+
+enum eDepsObjectIteratorMode DRW_iterator_mode_get(void);
struct DRWTextStore *DRW_state_text_cache_get(void);
diff --git a/source/blender/draw/intern/draw_cache_impl_curve.c b/source/blender/draw/intern/draw_cache_impl_curve.c
index 6d98195495f..a6dc52f66c9 100644
--- a/source/blender/draw/intern/draw_cache_impl_curve.c
+++ b/source/blender/draw/intern/draw_cache_impl_curve.c
@@ -126,7 +126,8 @@ static int curve_render_normal_len_get(const ListBase *lb, const CurveCache *ob_
nr -= skip;
}
#else
- normal_len += max_ii((nr + max_ii(skip - 1, 0)) / (skip + 1), 0);
+ /* Same as loop above */
+ normal_len += (nr / (skip + 1)) + ((nr % (skip + 1)) != 0);
#endif
}
return normal_len;
@@ -1043,7 +1044,7 @@ Gwn_Batch **DRW_curve_batch_cache_get_surface_shaded(
for (int i = 0; i < gpumat_array_len; ++i) {
cache->surface.shaded_triangles[i] = GWN_batch_create_ex(
- GWN_PRIM_TRIS, cache->surface.verts, el[i], el[i] ? GWN_BATCH_OWNS_INDEX : 0);
+ GWN_PRIM_TRIS, cache->surface.verts, el[i], GWN_BATCH_OWNS_INDEX);
/* TODO: Add vertbuff for UV */
}
diff --git a/source/blender/draw/intern/draw_cache_impl_displist.c b/source/blender/draw/intern/draw_cache_impl_displist.c
index b055a023e79..fd095c0ce4f 100644
--- a/source/blender/draw/intern/draw_cache_impl_displist.c
+++ b/source/blender/draw/intern/draw_cache_impl_displist.c
@@ -128,32 +128,28 @@ Gwn_VertBuf *DRW_displist_vertbuf_calc_pos_with_normals(ListBase *lb)
attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
}
- const int vert_len = curve_render_surface_vert_len_get(lb);
Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format);
- {
- const int vbo_len_capacity = vert_len;
- int vbo_len_used = 0;
- GWN_vertbuf_data_alloc(vbo, vbo_len_capacity);
-
- BKE_displist_normals_add(lb);
-
- for (const DispList *dl = lb->first; dl; dl = dl->next) {
- const bool ndata_is_single = dl->type == DL_INDEX3;
- if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
- const float *fp_co = dl->verts;
- const float *fp_no = dl->nors;
- const int vbo_end = vbo_len_used + dl_vert_len(dl);
- while (vbo_len_used < vbo_end) {
- GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, fp_co);
- if (fp_no) {
- GWN_vertbuf_attr_set(vbo, attr_id.nor, vbo_len_used, fp_no);
- if (ndata_is_single == false) {
- fp_no += 3;
- }
+ GWN_vertbuf_data_alloc(vbo, curve_render_surface_vert_len_get(lb));
+
+ BKE_displist_normals_add(lb);
+
+ int vbo_len_used = 0;
+ for (const DispList *dl = lb->first; dl; dl = dl->next) {
+ const bool ndata_is_single = dl->type == DL_INDEX3;
+ if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
+ const float *fp_co = dl->verts;
+ const float *fp_no = dl->nors;
+ const int vbo_end = vbo_len_used + dl_vert_len(dl);
+ while (vbo_len_used < vbo_end) {
+ GWN_vertbuf_attr_set(vbo, attr_id.pos, vbo_len_used, fp_co);
+ if (fp_no) {
+ GWN_vertbuf_attr_set(vbo, attr_id.nor, vbo_len_used, fp_no);
+ if (ndata_is_single == false) {
+ fp_no += 3;
}
- fp_co += 3;
- vbo_len_used += 1;
}
+ fp_co += 3;
+ vbo_len_used += 1;
}
}
}
@@ -164,52 +160,44 @@ Gwn_VertBuf *DRW_displist_vertbuf_calc_pos_with_normals(ListBase *lb)
Gwn_IndexBuf *DRW_displist_indexbuf_calc_triangles_in_order(ListBase *lb)
{
const int tri_len = curve_render_surface_tri_len_get(lb);
- if (tri_len == 0) {
- return NULL;
- }
-
const int vert_len = curve_render_surface_vert_len_get(lb);
- {
- Gwn_IndexBufBuilder elb;
- GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tri_len, vert_len);
-
- int ofs = 0;
- for (const DispList *dl = lb->first; dl; dl = dl->next) {
- displist_indexbufbuilder_set(&elb, dl, ofs);
- ofs += dl_vert_len(dl);
- }
+ Gwn_IndexBufBuilder elb;
+ GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tri_len, vert_len);
- return GWN_indexbuf_build(&elb);
+ int ofs = 0;
+ for (const DispList *dl = lb->first; dl; dl = dl->next) {
+ displist_indexbufbuilder_set(&elb, dl, ofs);
+ ofs += dl_vert_len(dl);
}
+
+ return GWN_indexbuf_build(&elb);
}
Gwn_IndexBuf **DRW_displist_indexbuf_calc_triangles_in_order_split_by_material(ListBase *lb, uint gpumat_array_len)
{
Gwn_IndexBuf **shaded_triangles_in_order = MEM_callocN(sizeof(*shaded_triangles_in_order) * gpumat_array_len, __func__);
- const int tri_len = curve_render_surface_tri_len_get(lb);
+ Gwn_IndexBufBuilder *elb = BLI_array_alloca(elb, gpumat_array_len);
- if (tri_len != 0) {
- const int vert_len = curve_render_surface_vert_len_get(lb);
- int i;
- Gwn_IndexBufBuilder *elb = BLI_array_alloca(elb, gpumat_array_len);
+ const int tri_len = curve_render_surface_tri_len_get(lb);
+ const int vert_len = curve_render_surface_vert_len_get(lb);
+ int i;
- /* Init each index buffer builder */
- for (i = 0; i < gpumat_array_len; i++) {
- GWN_indexbuf_init(&elb[i], GWN_PRIM_TRIS, tri_len, vert_len);
- }
+ /* Init each index buffer builder */
+ for (i = 0; i < gpumat_array_len; i++) {
+ GWN_indexbuf_init(&elb[i], GWN_PRIM_TRIS, tri_len, vert_len);
+ }
- /* calc each index buffer builder */
- int ofs = 0;
- for (const DispList *dl = lb->first; dl; dl = dl->next) {
- displist_indexbufbuilder_set(&elb[dl->col], dl, ofs);
- ofs += dl_vert_len(dl);
- }
+ /* calc each index buffer builder */
+ int ofs = 0;
+ for (const DispList *dl = lb->first; dl; dl = dl->next) {
+ displist_indexbufbuilder_set(&elb[dl->col], dl, ofs);
+ ofs += dl_vert_len(dl);
+ }
- /* build each indexbuf */
- for (i = 0; i < gpumat_array_len; i++) {
- shaded_triangles_in_order[i] = GWN_indexbuf_build(&elb[i]);
- }
+ /* build each indexbuf */
+ for (i = 0; i < gpumat_array_len; i++) {
+ shaded_triangles_in_order[i] = GWN_indexbuf_build(&elb[i]);
}
return shaded_triangles_in_order;
diff --git a/source/blender/draw/intern/draw_cache_impl_metaball.c b/source/blender/draw/intern/draw_cache_impl_metaball.c
index 9a9bbbd2c0c..f01e7b929f8 100644
--- a/source/blender/draw/intern/draw_cache_impl_metaball.c
+++ b/source/blender/draw/intern/draw_cache_impl_metaball.c
@@ -133,10 +133,9 @@ Gwn_Batch *DRW_metaball_batch_cache_get_triangles_with_normals(Object *ob)
if (cache->batch == NULL) {
ListBase *lb = &ob->curve_cache->disp;
- Gwn_VertBuf *verts = DRW_displist_vertbuf_calc_pos_with_normals(lb);
cache->batch = GWN_batch_create_ex(
GWN_PRIM_TRIS,
- verts,
+ DRW_displist_vertbuf_calc_pos_with_normals(lb),
DRW_displist_indexbuf_calc_triangles_in_order(lb),
GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX);
}
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 421d8f9088f..20eb4dd534d 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -354,6 +354,7 @@ static struct DRWGlobalState {
unsigned int is_depth : 1;
unsigned int is_image_render : 1;
unsigned int is_scene_render : 1;
+ unsigned int draw_background : 1;
} options;
/* Current rendering context */
@@ -2214,7 +2215,7 @@ bool DRW_object_is_renderable(Object *ob)
Scene *scene = DST.draw_ctx.scene;
Object *obedit = scene->obedit;
- BLI_assert(BKE_object_is_visible(ob));
+ BLI_assert(BKE_object_is_visible(ob, OB_VISIBILITY_CHECK_UNKNOWN_RENDER_MODE));
if (ob->type == OB_MESH) {
if (ob == obedit) {
@@ -2233,6 +2234,18 @@ bool DRW_object_is_renderable(Object *ob)
return true;
}
+/**
+ * Return whether this object is visible depending if
+ * we are rendering or drawing in the viewport.
+ */
+bool DRW_check_object_visible_within_active_context(Object *ob)
+{
+ const eObjectVisibilityCheck mode = DRW_state_is_scene_render() ?
+ OB_VISIBILITY_CHECK_FOR_RENDER :
+ OB_VISIBILITY_CHECK_FOR_VIEWPORT;
+ return BKE_object_is_visible(ob, mode);
+}
+
bool DRW_object_is_flat_normal(const Object *ob)
{
if (ob->type == OB_MESH) {
@@ -2244,7 +2257,6 @@ bool DRW_object_is_flat_normal(const Object *ob)
return true;
}
-
/**
* Return true if the object has its own draw mode.
* Caller must check this is active */
@@ -3405,7 +3417,7 @@ void DRW_draw_render_loop_ex(
PROFILE_START(stime);
drw_engines_cache_init();
- DEG_OBJECT_ITER_FOR_RENDER_ENGINE(graph, ob)
+ DEG_OBJECT_ITER_FOR_RENDER_ENGINE(graph, ob, DRW_iterator_mode_get())
{
drw_engines_cache_populate(ob);
}
@@ -3419,7 +3431,10 @@ void DRW_draw_render_loop_ex(
/* Start Drawing */
DRW_state_reset();
- drw_engines_draw_background();
+
+ if (DRW_state_draw_background()) {
+ drw_engines_draw_background();
+ }
/* WIP, single image drawn over the camera view (replace) */
bool do_bg_image = false;
@@ -3506,7 +3521,7 @@ void DRW_draw_render_loop(
void DRW_draw_render_loop_offscreen(
struct Depsgraph *graph, RenderEngineType *engine_type,
- ARegion *ar, View3D *v3d, GPUOffScreen *ofs)
+ ARegion *ar, View3D *v3d, const bool draw_background, GPUOffScreen *ofs)
{
RegionView3D *rv3d = ar->regiondata;
@@ -3520,6 +3535,7 @@ void DRW_draw_render_loop_offscreen(
/* Reset before using it. */
memset(&DST, 0x0, sizeof(DST));
DST.options.is_image_render = true;
+ DST.options.draw_background = draw_background;
DRW_draw_render_loop_ex(graph, engine_type, ar, v3d, NULL);
/* restore */
@@ -3618,7 +3634,7 @@ void DRW_draw_select_loop(
drw_engines_cache_populate(scene->obedit);
}
else {
- DEG_OBJECT_ITER(graph, ob,
+ DEG_OBJECT_ITER(graph, ob, DRW_iterator_mode_get(),
DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
DEG_ITER_OBJECT_FLAG_VISIBLE |
DEG_ITER_OBJECT_FLAG_DUPLI)
@@ -3713,7 +3729,7 @@ void DRW_draw_depth_loop(
if (cache_is_dirty) {
drw_engines_cache_init();
- DEG_OBJECT_ITER_FOR_RENDER_ENGINE(graph, ob)
+ DEG_OBJECT_ITER_FOR_RENDER_ENGINE(graph, ob, DRW_iterator_mode_get())
{
drw_engines_cache_populate(ob);
}
@@ -3799,6 +3815,15 @@ bool DRW_state_is_scene_render(void)
}
/**
+ * Gives you the iterator mode to use for depsgraph.
+ */
+eDepsObjectIteratorMode DRW_iterator_mode_get(void)
+{
+ return DRW_state_is_scene_render() ? DEG_ITER_OBJECT_MODE_RENDER :
+ DEG_ITER_OBJECT_MODE_VIEWPORT;
+}
+
+/**
* Should text draw in this mode?
*/
bool DRW_state_show_text(void)
@@ -3820,6 +3845,17 @@ bool DRW_state_draw_support(void)
((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0);
}
+/**
+ * Whether we should render the background
+ */
+bool DRW_state_draw_background(void)
+{
+ if (DRW_state_is_image_render() == false) {
+ return true;
+ }
+ return DST.options.draw_background;
+}
+
/** \} */
diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c
index e2263ef35f7..cd81ac59350 100644
--- a/source/blender/draw/modes/object_mode.c
+++ b/source/blender/draw/modes/object_mode.c
@@ -1675,7 +1675,7 @@ static void DRW_shgroup_lightprobe(OBJECT_StorageList *stl, OBJECT_PassList *psl
static void DRW_shgroup_relationship_lines(OBJECT_StorageList *stl, Object *ob)
{
- if (ob->parent && BKE_object_is_visible(ob->parent)) {
+ if (ob->parent && DRW_check_object_visible_within_active_context(ob->parent)) {
DRW_shgroup_call_dynamic_add(stl->g_data->relationship_lines, ob->obmat[3]);
DRW_shgroup_call_dynamic_add(stl->g_data->relationship_lines, ob->parent->obmat[3]);
}
@@ -1790,6 +1790,15 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
View3D *v3d = draw_ctx->v3d;
int theme_id = TH_UNDEFINED;
+ /* Handle particles first in case the emitter itself shouldn't be rendered. */
+ if (ob->type == OB_MESH) {
+ OBJECT_cache_populate_particles(ob, psl);
+ }
+
+ if (DRW_check_object_visible_within_active_context(ob) == false) {
+ return;
+ }
+
//CollectionEngineSettings *ces_mode_ob = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_OBJECT, "");
//bool do_wire = BKE_collection_engine_property_value_get_bool(ces_mode_ob, "show_wire");
@@ -1827,8 +1836,6 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
}
}
}
-
- OBJECT_cache_populate_particles(ob, psl);
break;
}
case OB_SURF:
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 4fc72200c04..c94a890b357 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -73,6 +73,7 @@ struct bNodeSocket;
struct wmDropBox;
struct wmDrag;
struct wmEvent;
+struct wmManipulator;
struct wmMsgBus;
typedef struct uiBut uiBut;
@@ -1135,6 +1136,13 @@ void UI_butstore_register(uiButStore *bs_handle, uiBut **but_p);
bool UI_butstore_register_update(uiBlock *block, uiBut *but_dst, const uiBut *but_src);
void UI_butstore_unregister(uiButStore *bs_handle, uiBut **but_p);
+/* ui_interface_region_tooltip.c */
+struct ARegion *UI_tooltip_create_from_button(struct bContext *C, struct ARegion *butregion, uiBut *but);
+struct ARegion *UI_tooltip_create_from_manipulator(struct bContext *C, struct wmManipulator *mpr);
+void UI_tooltip_free(struct bContext *C, struct ARegion *ar);
+
+/* How long before a tool-tip shows. */
+#define UI_TOOLTIP_DELAY 0.5
/* Float precision helpers */
#define UI_PRECISION_FLOAT_MAX 6
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index f28a398a46a..5218a9b8216 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -130,7 +130,6 @@ static bool ui_mouse_motion_keynav_test(struct uiKeyNavLock *keynav, const wmEve
/***************** structs and defines ****************/
-#define BUTTON_TOOLTIP_DELAY 0.500
#define BUTTON_FLASH_DELAY 0.020
#define MENU_SCROLL_INTERVAL 0.1
#define PIE_MENU_INTERVAL 0.01
@@ -7697,8 +7696,8 @@ void UI_but_tooltip_refresh(bContext *C, uiBut *but)
data = but->active;
if (data && data->tooltip) {
- ui_tooltip_free(C, data->tooltip);
- data->tooltip = ui_tooltip_create(C, data->region, but);
+ UI_tooltip_free(C, data->tooltip);
+ data->tooltip = UI_tooltip_create_from_button(C, data->region, but);
}
}
@@ -7715,7 +7714,7 @@ void UI_but_tooltip_timer_remove(bContext *C, uiBut *but)
data->tooltiptimer = NULL;
}
if (data->tooltip) {
- ui_tooltip_free(C, data->tooltip);
+ UI_tooltip_free(C, data->tooltip);
data->tooltip = NULL;
}
@@ -7741,7 +7740,7 @@ static void button_tooltip_timer_reset(bContext *C, uiBut *but)
if ((U.flag & USER_TOOLTIPS) || (data->tooltip_force)) {
if (!but->block->tooltipdisabled) {
if (!wm->drags.first) {
- data->tooltiptimer = WM_event_add_timer(data->wm, data->window, TIMER, BUTTON_TOOLTIP_DELAY);
+ data->tooltiptimer = WM_event_add_timer(data->wm, data->window, TIMER, UI_TOOLTIP_DELAY);
}
}
}
@@ -8443,7 +8442,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
data->tooltiptimer = NULL;
if (!data->tooltip)
- data->tooltip = ui_tooltip_create(C, data->region, but);
+ data->tooltip = UI_tooltip_create_from_button(C, data->region, but);
}
/* handle menu auto open timer */
else if (event->customdata == data->autoopentimer) {
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index ba62def7458..8d7f9d47ab5 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -590,8 +590,7 @@ struct uiPopupBlockHandle {
/* interface_region_*.c */
/* interface_region_tooltip.c */
-struct ARegion *ui_tooltip_create(struct bContext *C, struct ARegion *butregion, uiBut *but);
-void ui_tooltip_free(struct bContext *C, struct ARegion *ar);
+/* exposed as public API in UI_interface.h */
/* interface_region_color_picker.c */
void ui_rgb_to_color_picker_compat_v(const float rgb[3], float r_cp[3]);
diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c
index f71b71fce43..9a818efebee 100644
--- a/source/blender/editors/interface/interface_region_tooltip.c
+++ b/source/blender/editors/interface/interface_region_tooltip.c
@@ -29,6 +29,14 @@
* ToolTip Region and Construction
*/
+/* TODO(campbell):
+ * We may want to have a higher level API that initializes a timer,
+ * checks for mouse motion and clears the tool-tip afterwards.
+ * We never want multiple tool-tips at once so this could be handled on the window / window-manager level.
+ *
+ * For now it's not a priority, so leave as-is.
+ */
+
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
@@ -97,7 +105,6 @@ typedef struct uiTooltipField {
} uiTooltipField;
-#define MAX_TOOLTIP_LINES 8
typedef struct uiTooltipData {
rcti bbox;
uiTooltipField *fields;
@@ -314,8 +321,6 @@ static uiTooltipData *ui_tooltip_data_from_keymap(bContext *C, wmKeyMap *keymap)
/* create tooltip data */
uiTooltipData *data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");
- BLI_assert(data->fields_len < MAX_TOOLTIP_LINES);
-
for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) {
wmOperatorType *ot = WM_operatortype_find(kmi->idname, true);
if (ot != NULL) {
@@ -609,8 +614,6 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
if (rna_prop.strinfo)
MEM_freeN(rna_prop.strinfo);
- BLI_assert(data->fields_len < MAX_TOOLTIP_LINES);
-
if (data->fields_len == 0) {
MEM_freeN(data);
return NULL;
@@ -620,13 +623,116 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
}
}
-/** \} */
+static uiTooltipData *ui_tooltip_data_from_manipulator(bContext *C, wmManipulator *mpr)
+{
+ uiTooltipData *data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData");
-/* -------------------------------------------------------------------- */
-/** \name ToolTip Public API
- * \{ */
+ /* TODO(campbell): a way for manipulators to have their own descriptions (low priority). */
+
+ /* Operator Actions */
+ {
+ bool use_drag = mpr->drag_part != -1 && mpr->highlight_part != mpr->drag_part;
+
+ const struct {
+ int part;
+ const char *prefix;
+ } mpop_actions[] = {
+ {
+ .part = mpr->highlight_part,
+ .prefix = use_drag ? TIP_("Click") : NULL,
+ }, {
+ .part = use_drag ? mpr->drag_part : -1,
+ .prefix = use_drag ? TIP_("Drag") : NULL,
+ },
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(mpop_actions); i++) {
+ wmManipulatorOpElem *mpop = (mpop_actions[i].part != -1) ? WM_manipulator_operator_get(mpr, mpop_actions[i].part) : NULL;
+ if (mpop != NULL) {
+ /* Description */
+ const char *info = RNA_struct_ui_description(mpop->type->srna);
+ if (!(info && info[0])) {
+ info = RNA_struct_ui_name(mpop->type->srna);
+ }
-ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
+ if (info && info[0]) {
+ char *text = NULL;
+ if (mpop_actions[i].prefix != NULL) {
+ text = BLI_sprintfN("%s: %s", mpop_actions[i].prefix, info);
+ }
+ else {
+ text = BLI_strdup(info);
+ }
+
+ if (text != NULL) {
+ uiTooltipField *field = text_field_add(
+ data, &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_HEADER,
+ .color_id = UI_TIP_LC_VALUE,
+ .is_pad = true,
+ });
+ field->text = text;
+ }
+ }
+
+ /* Shortcut */
+ {
+ bool found = false;
+ IDProperty *prop = mpop->ptr.data;
+ char buf[128];
+ if (WM_key_event_operator_string(
+ C, mpop->type->idname, WM_OP_INVOKE_DEFAULT, prop, true,
+ buf, ARRAY_SIZE(buf)))
+ {
+ found = true;
+ }
+ uiTooltipField *field = text_field_add(
+ data, &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_VALUE,
+ .is_pad = true,
+ });
+ field->text = BLI_sprintfN(TIP_("Shortcut: %s"), found ? buf : "None");
+ }
+ }
+ }
+ }
+
+ /* Property Actions */
+ if (mpr->type->target_property_defs_len) {
+ wmManipulatorProperty *mpr_prop_array = WM_manipulator_target_property_array(mpr);
+ for (int i = 0; i < mpr->type->target_property_defs_len; i++) {
+ /* TODO(campbell): function callback descriptions. */
+ wmManipulatorProperty *mpr_prop = &mpr_prop_array[i];
+ if (mpr_prop->prop != NULL) {
+ const char *info = RNA_property_ui_description(mpr_prop->prop);
+ if (info && info[0]) {
+ uiTooltipField *field = text_field_add(
+ data, &(uiTooltipFormat){
+ .style = UI_TIP_STYLE_NORMAL,
+ .color_id = UI_TIP_LC_VALUE,
+ .is_pad = true,
+ });
+ field->text = BLI_strdup(info);
+ }
+ }
+ }
+ }
+
+ if (data->fields_len == 0) {
+ MEM_freeN(data);
+ return NULL;
+ }
+ else {
+ return data;
+ }
+}
+
+
+static ARegion *ui_tooltip_create_with_data(
+ bContext *C, uiTooltipData *data,
+ const float init_position[2],
+ const float aspect)
{
const float pad_px = UI_TIP_PADDING;
wmWindow *win = CTX_wm_window(C);
@@ -634,43 +740,12 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
uiStyle *style = UI_style_get();
static ARegionType type;
ARegion *ar;
-/* IDProperty *prop;*/
- /* aspect values that shrink text are likely unreadable */
- const float aspect = min_ff(1.0f, but->block->aspect);
int fonth, fontw;
- int ofsx, ofsy, h, i;
+ int h, i;
rctf rect_fl;
rcti rect_i;
int font_flag = 0;
- if (but->drawflag & UI_BUT_NO_TOOLTIP) {
- return NULL;
- }
- uiTooltipData *data = NULL;
-
- /* custom tips for pre-defined operators */
- if (but->optype) {
- if (STREQ(but->optype->idname, "WM_OT_tool_set")) {
- char keymap[64] = "";
- RNA_string_get(but->opptr, "keymap", keymap);
- if (keymap[0]) {
- ScrArea *sa = CTX_wm_area(C);
- wmKeyMap *km = WM_keymap_find_all(C, keymap, sa->spacetype, RGN_TYPE_WINDOW);
- if (km != NULL) {
- data = ui_tooltip_data_from_keymap(C, km);
- }
- }
- }
- }
- /* toolsystem exception */
-
- if (data == NULL) {
- data = ui_tooltip_data_from_button(C, but);
- }
- if (data == NULL) {
- return NULL;
- }
-
/* create area region */
ar = ui_region_temp_add(CTX_wm_screen(C));
@@ -748,31 +823,12 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
data->lineh = h;
/* compute position */
- ofsx = 0; //(but->block->panel) ? but->block->panel->ofsx : 0;
- ofsy = 0; //(but->block->panel) ? but->block->panel->ofsy : 0;
- rect_fl.xmin = BLI_rctf_cent_x(&but->rect) + ofsx - TIP_BORDER_X;
+ rect_fl.xmin = init_position[0] - TIP_BORDER_X;
rect_fl.xmax = rect_fl.xmin + fontw + pad_px;
- rect_fl.ymax = but->rect.ymin + ofsy - TIP_BORDER_Y;
+ rect_fl.ymax = init_position[1] - TIP_BORDER_Y;
rect_fl.ymin = rect_fl.ymax - fonth - TIP_BORDER_Y;
- /* since the text has beens caled already, the size of tooltips is defined now */
- /* here we try to figure out the right location */
- if (butregion) {
- float mx, my;
- float ofsx_fl = rect_fl.xmin, ofsy_fl = rect_fl.ymax;
- ui_block_to_window_fl(butregion, but->block, &ofsx_fl, &ofsy_fl);
-
-#if 1
- /* use X mouse location */
- mx = (win->eventstate->x + (TIP_BORDER_X * 2)) - BLI_rctf_cent_x(&but->rect);
-#else
- mx = ofsx_fl - rect_fl.xmin;
-#endif
- my = ofsy_fl - rect_fl.ymax;
-
- BLI_rctf_translate(&rect_fl, mx, my);
- }
BLI_rcti_rctf_copy(&rect_i, &rect_fl);
#undef TIP_BORDER_X
@@ -827,7 +883,77 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
return ar;
}
-void ui_tooltip_free(bContext *C, ARegion *ar)
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name ToolTip Public API
+ * \{ */
+
+
+ARegion *UI_tooltip_create_from_button(bContext *C, ARegion *butregion, uiBut *but)
+{
+ wmWindow *win = CTX_wm_window(C);
+ /* aspect values that shrink text are likely unreadable */
+ const float aspect = min_ff(1.0f, but->block->aspect);
+ float init_position[2];
+
+ if (but->drawflag & UI_BUT_NO_TOOLTIP) {
+ return NULL;
+ }
+ uiTooltipData *data = NULL;
+
+ /* custom tips for pre-defined operators */
+ if (but->optype) {
+ if (STREQ(but->optype->idname, "WM_OT_tool_set")) {
+ char keymap[64] = "";
+ RNA_string_get(but->opptr, "keymap", keymap);
+ if (keymap[0]) {
+ ScrArea *sa = CTX_wm_area(C);
+ wmKeyMap *km = WM_keymap_find_all(C, keymap, sa->spacetype, RGN_TYPE_WINDOW);
+ if (km != NULL) {
+ data = ui_tooltip_data_from_keymap(C, km);
+ }
+ }
+ }
+ }
+ /* toolsystem exception */
+
+ if (data == NULL) {
+ data = ui_tooltip_data_from_button(C, but);
+ }
+ if (data == NULL) {
+ return NULL;
+ }
+
+ init_position[0] = BLI_rctf_cent_x(&but->rect);
+ init_position[1] = but->rect.ymin;
+
+ if (butregion) {
+ ui_block_to_window_fl(butregion, but->block, &init_position[0], &init_position[1]);
+ init_position[0] = win->eventstate->x;
+ }
+
+ return ui_tooltip_create_with_data(C, data, init_position, aspect);
+}
+
+ARegion *UI_tooltip_create_from_manipulator(bContext *C, wmManipulator *mpr)
+{
+ wmWindow *win = CTX_wm_window(C);
+ const float aspect = 1.0f;
+ float init_position[2];
+
+ uiTooltipData *data = ui_tooltip_data_from_manipulator(C, mpr);
+ if (data == NULL) {
+ return NULL;
+ }
+
+ init_position[0] = win->eventstate->x;
+ init_position[1] = win->eventstate->y;
+
+ return ui_tooltip_create_with_data(C, data, init_position, aspect);
+}
+
+void UI_tooltip_free(bContext *C, ARegion *ar)
{
ui_region_temp_remove(C, CTX_wm_screen(C), ar);
}
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 5a2200fbe49..7d378a11a23 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -383,28 +383,34 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
case UI_ID_LOCAL:
if (id) {
Main *bmain = CTX_data_main(C);
- if (id_make_local(bmain, id, false, false)) {
- BKE_main_id_clear_newpoins(bmain);
+ if (CTX_wm_window(C)->eventstate->shift) {
+ ID *override_id = BKE_override_static_create_from(bmain, id);
+ if (override_id != NULL) {
+ BKE_main_id_clear_newpoins(bmain);
- /* reassign to get get proper updates/notifiers */
- idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
- RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr);
- RNA_property_update(C, &template_ui->ptr, template_ui->prop);
+ /* Assign new pointer, takes care of updates/notifiers */
+ RNA_id_pointer_create(override_id, &idptr);
+ }
+ }
+ else {
+ if (id_make_local(bmain, id, false, false)) {
+ BKE_main_id_clear_newpoins(bmain);
+
+ /* reassign to get get proper updates/notifiers */
+ idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
+ }
}
+ RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr);
+ RNA_property_update(C, &template_ui->ptr, template_ui->prop);
}
break;
case UI_ID_OVERRIDE:
- if (id) {
- Main *bmain = CTX_data_main(C);
- ID *override_id = BKE_override_static_create_from(bmain, id);
- if (override_id != NULL) {
- BKE_main_id_clear_newpoins(bmain);
-
- /* Assign new pointer, takes care of updates/notifiers */
- RNA_id_pointer_create(override_id, &idptr);
- RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr);
- RNA_property_update(C, &template_ui->ptr, template_ui->prop);
- }
+ if (id && id->override_static) {
+ BKE_override_static_free(&id->override_static);
+ /* reassign to get get proper updates/notifiers */
+ idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
+ RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr);
+ RNA_property_update(C, &template_ui->ptr, template_ui->prop);
}
break;
case UI_ID_ALONE:
@@ -542,25 +548,23 @@ static void template_ID(
const bool disabled = (!id_make_local(CTX_data_main(C), id, true /* test */, false) ||
(idfrom && idfrom->lib));
but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y,
- NULL, 0, 0, 0, 0, TIP_("Direct linked library data-block, click to make local"));
- if (disabled) {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
- else {
- UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), SET_INT_IN_POINTER(UI_ID_LOCAL));
- }
-
- but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_LIBRARY_DATA_OVERRIDE, 0, 0, UI_UNIT_X, UI_UNIT_Y,
NULL, 0, 0, 0, 0,
- TIP_("Direct linked library data-block, click to create static override"));
+ TIP_("Direct linked library data-block, click to make local, "
+ "Shift + Click to create a static override"));
if (disabled) {
UI_but_flag_enable(but, UI_BUT_DISABLED);
}
else {
- UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), SET_INT_IN_POINTER(UI_ID_OVERRIDE));
+ UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), SET_INT_IN_POINTER(UI_ID_LOCAL));
}
}
}
+ else if (ID_IS_STATIC_OVERRIDE(id)) {
+ but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_LIBRARY_DATA_OVERRIDE, 0, 0, UI_UNIT_X, UI_UNIT_Y,
+ NULL, 0, 0, 0, 0,
+ TIP_("Static override of linked library data-block, click to make fully local"));
+ UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), SET_INT_IN_POINTER(UI_ID_OVERRIDE));
+ }
if (id->us > 1) {
char numstr[32];
diff --git a/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c
index 32c1dbae0a6..cad97a9ef03 100644
--- a/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c
+++ b/source/blender/editors/manipulator_library/manipulator_types/button2d_manipulator.c
@@ -114,8 +114,8 @@ static void button3d_draw_intern(
int icon = RNA_enum_get(mpr->ptr, "icon");
if (icon != ICON_NONE) {
UI_icon_draw(
- mpr->matrix_basis[3][0] - (ICON_DEFAULT_WIDTH / 2.0) * U.pixelsize,
- mpr->matrix_basis[3][1] - (ICON_DEFAULT_HEIGHT / 2.0) * U.pixelsize,
+ mpr->matrix_basis[3][0] - (ICON_DEFAULT_WIDTH / 2.0) * U.ui_scale,
+ mpr->matrix_basis[3][1] - (ICON_DEFAULT_HEIGHT / 2.0) * U.ui_scale,
icon);
}
}
@@ -153,9 +153,8 @@ static int manipulator_button_test_select(
else {
copy_v2_v2(point_local, (float [2]){UNPACK2(event->mval)});
sub_v2_v2(point_local, mpr->matrix_basis[3]);
- mul_v2_fl(point_local, 1.0f / mpr->scale_basis);
+ mul_v2_fl(point_local, 1.0f / (mpr->scale_basis * U.ui_scale));
}
-
/* The 'mpr->scale_final' is already applied when projecting. */
if (len_squared_v2(point_local) < 1.0f) {
return 0;
diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c
index 77772cfc8cc..a21fc2fffde 100644
--- a/source/blender/editors/mesh/editmesh_add.c
+++ b/source/blender/editors/mesh/editmesh_add.c
@@ -60,30 +60,35 @@
/* ********* add primitive operators ************* */
+typedef struct MakePrimitiveData {
+ float mat[4][4];
+ bool was_editmode;
+} MakePrimitiveData;
+
static Object *make_prim_init(bContext *C, const char *idname,
- float *dia, float mat[4][4],
- bool *was_editmode, const float loc[3], const float rot[3], const unsigned int layer)
+ const float loc[3], const float rot[3], const unsigned int layer,
+ MakePrimitiveData *r_creation_data)
{
Object *obedit = CTX_data_edit_object(C);
- *was_editmode = false;
+ r_creation_data->was_editmode = false;
if (obedit == NULL || obedit->type != OB_MESH) {
obedit = ED_object_add_type(C, OB_MESH, idname, loc, rot, false, layer);
/* create editmode */
ED_object_editmode_enter(C, EM_DO_UNDO | EM_IGNORE_LAYER); /* rare cases the active layer is messed up */
- *was_editmode = true;
+ r_creation_data->was_editmode = true;
}
- *dia = ED_object_new_primitive_matrix(C, obedit, loc, rot, mat);
+ ED_object_new_primitive_matrix(C, obedit, loc, rot, r_creation_data->mat);
return obedit;
}
-static void make_prim_finish(bContext *C, Object *obedit, bool was_editmode, int enter_editmode)
+static void make_prim_finish(bContext *C, Object *obedit, const MakePrimitiveData *creation_data, int enter_editmode)
{
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- const bool exit_editmode = ((was_editmode == true) && (enter_editmode == false));
+ const bool exit_editmode = ((creation_data->was_editmode == true) && (enter_editmode == false));
/* Primitive has all verts selected, use vert select flush
* to push this up to edges & faces. */
@@ -101,17 +106,17 @@ static void make_prim_finish(bContext *C, Object *obedit, bool was_editmode, int
static int add_primitive_plane_exec(bContext *C, wmOperator *op)
{
+ MakePrimitiveData creation_data;
Object *obedit;
BMEditMesh *em;
- float loc[3], rot[3], mat[4][4], dia;
+ float loc[3], rot[3];
bool enter_editmode;
- bool was_editmode;
unsigned int layer;
const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Plane"), &dia, mat, &was_editmode, loc, rot, layer);
+ obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Plane"), loc, rot, layer, &creation_data);
em = BKE_editmesh_from_object(obedit);
if (calc_uvs) {
@@ -121,12 +126,12 @@ static int add_primitive_plane_exec(bContext *C, wmOperator *op)
if (!EDBM_op_call_and_selectf(
em, op, "verts.out", false,
"create_grid x_segments=%i y_segments=%i size=%f matrix=%m4 calc_uvs=%b",
- 1, 1, RNA_float_get(op->ptr, "radius"), mat, calc_uvs))
+ 1, 1, RNA_float_get(op->ptr, "radius"), creation_data.mat, calc_uvs))
{
return OPERATOR_CANCELLED;
}
- make_prim_finish(C, obedit, was_editmode, enter_editmode);
+ make_prim_finish(C, obedit, &creation_data, enter_editmode);
return OPERATOR_FINISHED;
}
@@ -152,17 +157,17 @@ void MESH_OT_primitive_plane_add(wmOperatorType *ot)
static int add_primitive_cube_exec(bContext *C, wmOperator *op)
{
+ MakePrimitiveData creation_data;
Object *obedit;
BMEditMesh *em;
- float loc[3], rot[3], mat[4][4], dia;
+ float loc[3], rot[3];
bool enter_editmode;
- bool was_editmode;
unsigned int layer;
const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Cube"), &dia, mat, &was_editmode, loc, rot, layer);
+ obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Cube"), loc, rot, layer, &creation_data);
em = BKE_editmesh_from_object(obedit);
if (calc_uvs) {
@@ -172,13 +177,13 @@ static int add_primitive_cube_exec(bContext *C, wmOperator *op)
if (!EDBM_op_call_and_selectf(
em, op, "verts.out", false,
"create_cube matrix=%m4 size=%f calc_uvs=%b",
- mat, RNA_float_get(op->ptr, "radius") * 2.0f, calc_uvs))
+ creation_data.mat, RNA_float_get(op->ptr, "radius") * 2.0f, calc_uvs))
{
return OPERATOR_CANCELLED;
}
/* BMESH_TODO make plane side this: M_SQRT2 - plane (diameter of 1.41 makes it unit size) */
- make_prim_finish(C, obedit, was_editmode, enter_editmode);
+ make_prim_finish(C, obedit, &creation_data, enter_editmode);
return OPERATOR_FINISHED;
}
@@ -210,13 +215,13 @@ static const EnumPropertyItem fill_type_items[] = {
static int add_primitive_circle_exec(bContext *C, wmOperator *op)
{
+ MakePrimitiveData creation_data;
Object *obedit;
BMEditMesh *em;
- float loc[3], rot[3], mat[4][4], dia;
+ float loc[3], rot[3];
bool enter_editmode;
int cap_end, cap_tri;
unsigned int layer;
- bool was_editmode;
const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
cap_end = RNA_enum_get(op->ptr, "fill_type");
@@ -224,7 +229,7 @@ static int add_primitive_circle_exec(bContext *C, wmOperator *op)
WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Circle"), &dia, mat, &was_editmode, loc, rot, layer);
+ obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Circle"), loc, rot, layer, &creation_data);
em = BKE_editmesh_from_object(obedit);
if (calc_uvs) {
@@ -235,12 +240,12 @@ static int add_primitive_circle_exec(bContext *C, wmOperator *op)
em, op, "verts.out", false,
"create_circle segments=%i radius=%f cap_ends=%b cap_tris=%b matrix=%m4 calc_uvs=%b",
RNA_int_get(op->ptr, "vertices"), RNA_float_get(op->ptr, "radius"),
- cap_end, cap_tri, mat, calc_uvs))
+ cap_end, cap_tri, creation_data.mat, calc_uvs))
{
return OPERATOR_CANCELLED;
}
- make_prim_finish(C, obedit, was_editmode, enter_editmode);
+ make_prim_finish(C, obedit, &creation_data, enter_editmode);
return OPERATOR_FINISHED;
}
@@ -270,12 +275,12 @@ void MESH_OT_primitive_circle_add(wmOperatorType *ot)
static int add_primitive_cylinder_exec(bContext *C, wmOperator *op)
{
+ MakePrimitiveData creation_data;
Object *obedit;
BMEditMesh *em;
- float loc[3], rot[3], mat[4][4], dia;
+ float loc[3], rot[3];
bool enter_editmode;
unsigned int layer;
- bool was_editmode;
const int end_fill_type = RNA_enum_get(op->ptr, "end_fill_type");
const bool cap_end = (end_fill_type != 0);
const bool cap_tri = (end_fill_type == 2);
@@ -283,7 +288,7 @@ static int add_primitive_cylinder_exec(bContext *C, wmOperator *op)
WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Cylinder"), &dia, mat, &was_editmode, loc, rot, layer);
+ obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Cylinder"), loc, rot, layer, &creation_data);
em = BKE_editmesh_from_object(obedit);
if (calc_uvs) {
@@ -297,12 +302,12 @@ static int add_primitive_cylinder_exec(bContext *C, wmOperator *op)
RNA_float_get(op->ptr, "radius"),
RNA_float_get(op->ptr, "radius"),
cap_end, cap_tri,
- RNA_float_get(op->ptr, "depth"), mat, calc_uvs))
+ RNA_float_get(op->ptr, "depth"), creation_data.mat, calc_uvs))
{
return OPERATOR_CANCELLED;
}
- make_prim_finish(C, obedit, was_editmode, enter_editmode);
+ make_prim_finish(C, obedit, &creation_data, enter_editmode);
return OPERATOR_FINISHED;
}
@@ -333,12 +338,12 @@ void MESH_OT_primitive_cylinder_add(wmOperatorType *ot)
static int add_primitive_cone_exec(bContext *C, wmOperator *op)
{
+ MakePrimitiveData creation_data;
Object *obedit;
BMEditMesh *em;
- float loc[3], rot[3], mat[4][4], dia;
+ float loc[3], rot[3];
bool enter_editmode;
unsigned int layer;
- bool was_editmode;
const int end_fill_type = RNA_enum_get(op->ptr, "end_fill_type");
const bool cap_end = (end_fill_type != 0);
const bool cap_tri = (end_fill_type == 2);
@@ -346,7 +351,7 @@ static int add_primitive_cone_exec(bContext *C, wmOperator *op)
WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Cone"), &dia, mat, &was_editmode, loc, rot, layer);
+ obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Cone"), loc, rot, layer, &creation_data);
em = BKE_editmesh_from_object(obedit);
if (calc_uvs) {
@@ -357,12 +362,13 @@ static int add_primitive_cone_exec(bContext *C, wmOperator *op)
em, op, "verts.out", false,
"create_cone segments=%i diameter1=%f diameter2=%f cap_ends=%b cap_tris=%b depth=%f matrix=%m4 calc_uvs=%b",
RNA_int_get(op->ptr, "vertices"), RNA_float_get(op->ptr, "radius1"),
- RNA_float_get(op->ptr, "radius2"), cap_end, cap_tri, RNA_float_get(op->ptr, "depth"), mat, calc_uvs))
+ RNA_float_get(op->ptr, "radius2"), cap_end, cap_tri, RNA_float_get(op->ptr, "depth"),
+ creation_data.mat, calc_uvs))
{
return OPERATOR_CANCELLED;
}
- make_prim_finish(C, obedit, was_editmode, enter_editmode);
+ make_prim_finish(C, obedit, &creation_data, enter_editmode);
return OPERATOR_FINISHED;
}
@@ -394,17 +400,17 @@ void MESH_OT_primitive_cone_add(wmOperatorType *ot)
static int add_primitive_grid_exec(bContext *C, wmOperator *op)
{
+ MakePrimitiveData creation_data;
Object *obedit;
BMEditMesh *em;
- float loc[3], rot[3], mat[4][4], dia;
+ float loc[3], rot[3];
bool enter_editmode;
- bool was_editmode;
unsigned int layer;
const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Grid"), &dia, mat, &was_editmode, loc, rot, layer);
+ obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Grid"), loc, rot, layer, &creation_data);
em = BKE_editmesh_from_object(obedit);
if (calc_uvs) {
@@ -416,12 +422,12 @@ static int add_primitive_grid_exec(bContext *C, wmOperator *op)
"create_grid x_segments=%i y_segments=%i size=%f matrix=%m4 calc_uvs=%b",
RNA_int_get(op->ptr, "x_subdivisions"),
RNA_int_get(op->ptr, "y_subdivisions"),
- RNA_float_get(op->ptr, "radius"), mat, calc_uvs))
+ RNA_float_get(op->ptr, "radius"), creation_data.mat, calc_uvs))
{
return OPERATOR_CANCELLED;
}
- make_prim_finish(C, obedit, was_editmode, enter_editmode);
+ make_prim_finish(C, obedit, &creation_data, enter_editmode);
return OPERATOR_FINISHED;
}
@@ -453,22 +459,21 @@ void MESH_OT_primitive_grid_add(wmOperatorType *ot)
static int add_primitive_monkey_exec(bContext *C, wmOperator *op)
{
+ MakePrimitiveData creation_data;
Object *obedit;
BMEditMesh *em;
- float mat[4][4];
float loc[3], rot[3];
float dia;
bool enter_editmode;
unsigned int layer;
- bool was_editmode;
const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, 'Y', loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Suzanne"), &dia, mat, &was_editmode, loc, rot, layer);
+ obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Suzanne"), loc, rot, layer, &creation_data);
dia = RNA_float_get(op->ptr, "radius");
- mul_mat3_m4_fl(mat, dia);
+ mul_mat3_m4_fl(creation_data.mat, dia);
em = BKE_editmesh_from_object(obedit);
@@ -478,12 +483,12 @@ static int add_primitive_monkey_exec(bContext *C, wmOperator *op)
if (!EDBM_op_call_and_selectf(
em, op, "verts.out", false,
- "create_monkey matrix=%m4 calc_uvs=%b", mat, calc_uvs))
+ "create_monkey matrix=%m4 calc_uvs=%b", creation_data.mat, calc_uvs))
{
return OPERATOR_CANCELLED;
}
- make_prim_finish(C, obedit, was_editmode, enter_editmode);
+ make_prim_finish(C, obedit, &creation_data, enter_editmode);
return OPERATOR_FINISHED;
}
@@ -510,17 +515,17 @@ void MESH_OT_primitive_monkey_add(wmOperatorType *ot)
static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op)
{
+ MakePrimitiveData creation_data;
Object *obedit;
BMEditMesh *em;
- float loc[3], rot[3], mat[4][4], dia;
+ float loc[3], rot[3];
bool enter_editmode;
- bool was_editmode;
unsigned int layer;
const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Sphere"), &dia, mat, &was_editmode, loc, rot, layer);
+ obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Sphere"), loc, rot, layer, &creation_data);
em = BKE_editmesh_from_object(obedit);
if (calc_uvs) {
@@ -531,12 +536,12 @@ static int add_primitive_uvsphere_exec(bContext *C, wmOperator *op)
em, op, "verts.out", false,
"create_uvsphere u_segments=%i v_segments=%i diameter=%f matrix=%m4 calc_uvs=%b",
RNA_int_get(op->ptr, "segments"), RNA_int_get(op->ptr, "ring_count"),
- RNA_float_get(op->ptr, "size"), mat, calc_uvs))
+ RNA_float_get(op->ptr, "size"), creation_data.mat, calc_uvs))
{
return OPERATOR_CANCELLED;
}
- make_prim_finish(C, obedit, was_editmode, enter_editmode);
+ make_prim_finish(C, obedit, &creation_data, enter_editmode);
return OPERATOR_FINISHED;
}
@@ -566,17 +571,17 @@ void MESH_OT_primitive_uv_sphere_add(wmOperatorType *ot)
static int add_primitive_icosphere_exec(bContext *C, wmOperator *op)
{
+ MakePrimitiveData creation_data;
Object *obedit;
BMEditMesh *em;
- float loc[3], rot[3], mat[4][4], dia;
+ float loc[3], rot[3];
bool enter_editmode;
- bool was_editmode;
unsigned int layer;
const bool calc_uvs = RNA_boolean_get(op->ptr, "calc_uvs");
WM_operator_view3d_unit_defaults(C, op);
ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, &enter_editmode, &layer, NULL);
- obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Icosphere"), &dia, mat, &was_editmode, loc, rot, layer);
+ obedit = make_prim_init(C, CTX_DATA_(BLT_I18NCONTEXT_ID_MESH, "Icosphere"), loc, rot, layer, &creation_data);
em = BKE_editmesh_from_object(obedit);
if (calc_uvs) {
@@ -587,12 +592,12 @@ static int add_primitive_icosphere_exec(bContext *C, wmOperator *op)
em, op, "verts.out", false,
"create_icosphere subdivisions=%i diameter=%f matrix=%m4 calc_uvs=%b",
RNA_int_get(op->ptr, "subdivisions"),
- RNA_float_get(op->ptr, "size"), mat, calc_uvs))
+ RNA_float_get(op->ptr, "size"), creation_data.mat, calc_uvs))
{
return OPERATOR_CANCELLED;
}
- make_prim_finish(C, obedit, was_editmode, enter_editmode);
+ make_prim_finish(C, obedit, &creation_data, enter_editmode);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 3eb26fa52b8..af131e270ef 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1137,6 +1137,7 @@ static int group_instance_add_exec(bContext *C, wmOperator *op)
/* works without this except if you try render right after, see: 22027 */
DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&group->id, 0);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index dacaea6a96e..9dd51b289f4 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -233,6 +233,9 @@ static bool paint_brush_update(bContext *C,
UnifiedPaintSettings *ups = stroke->ups;
bool location_sampled = false;
bool location_success = false;
+ /* Use to perform all operations except applying the stroke,
+ * needed for operations that require cursor motion (rake). */
+ bool is_dry_run = false;
bool do_random = false;
bool do_random_mask = false;
/* XXX: Use pressure value from first brush step for brushes which don't
@@ -371,7 +374,10 @@ static bool paint_brush_update(bContext *C,
}
/* curve strokes do their own rake calculation */
else if (!(brush->flag & BRUSH_CURVE)) {
- paint_calculate_rake_rotation(ups, brush, mouse_init);
+ if (!paint_calculate_rake_rotation(ups, brush, mouse_init)) {
+ /* Not enough motion to define an angle. */
+ is_dry_run = true;
+ }
}
}
@@ -402,7 +408,7 @@ static bool paint_brush_update(bContext *C,
}
}
- return location_success;
+ return location_success && (is_dry_run == false);
}
static bool paint_stroke_use_jitter(ePaintMode mode, Brush *brush, bool invert)
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index 878feb81e8a..179780bf517 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -226,11 +226,12 @@ static void buttons_header_region_draw(const bContext *C, ARegion *ar)
}
static void buttons_header_region_message_subscribe(
- const struct bContext *UNUSED(C),
- struct WorkSpace *UNUSED(workspace), struct Scene *UNUSED(scene),
- struct bScreen *UNUSED(screen), struct ScrArea *UNUSED(sa), struct ARegion *ar,
+ const bContext *UNUSED(C),
+ WorkSpace *UNUSED(workspace), Scene *UNUSED(scene),
+ bScreen *UNUSED(screen), ScrArea *sa, ARegion *ar,
struct wmMsgBus *mbus)
{
+ SpaceButs *sbuts = sa->spacedata.first;
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
.owner = ar,
.user_data = ar,
@@ -240,6 +241,10 @@ static void buttons_header_region_message_subscribe(
/* Don't check for SpaceButs.mainb here, we may toggle between view-layers
* where one has no active object, so that available contexts changes. */
WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_region_tag_redraw);
+
+ if (!ELEM(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_SCENE, BCONTEXT_WORLD)) {
+ WM_msg_subscribe_rna_anon_prop(mbus, ViewLayer, name, &msg_sub_value_region_tag_redraw);
+ }
}
/* draw a certain button set only if properties area is currently
diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h
index ffc7a41f0aa..b0d00744558 100644
--- a/source/blender/editors/space_clip/clip_intern.h
+++ b/source/blender/editors/space_clip/clip_intern.h
@@ -139,6 +139,8 @@ void clip_graph_tracking_iterate(struct SpaceClip *sc, bool selected_only, bool
void clip_delete_track(struct bContext *C, struct MovieClip *clip, struct MovieTrackingTrack *track);
void clip_delete_marker(struct bContext *C, struct MovieClip *clip, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker);
+void clip_delete_plane_track(struct bContext *C, struct MovieClip *clip, struct MovieTrackingPlaneTrack *plane_track);
+
void clip_view_center_to_point(SpaceClip *sc, float x, float y);
void clip_draw_cfra(struct SpaceClip *sc, struct ARegion *ar, struct Scene *scene);
diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c
index 40661937bae..7f9d9bf577c 100644
--- a/source/blender/editors/space_clip/clip_utils.c
+++ b/source/blender/editors/space_clip/clip_utils.c
@@ -184,37 +184,37 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track)
MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking);
ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
bool has_bundle = false;
- char track_name_escaped[MAX_NAME], prefix[MAX_NAME * 2];
- const bool used_for_stabilization = (track->flag & (TRACK_USE_2D_STAB | TRACK_USE_2D_STAB_ROT));
-
- if (track == act_track)
+ const bool used_for_stabilization =
+ (track->flag & (TRACK_USE_2D_STAB | TRACK_USE_2D_STAB_ROT)) != 0;
+ if (track == act_track) {
tracking->act_track = NULL;
-
- /* handle reconstruction display in 3d viewport */
- if (track->flag & TRACK_HAS_BUNDLE)
+ }
+ /* Handle reconstruction display in 3d viewport. */
+ if (track->flag & TRACK_HAS_BUNDLE) {
has_bundle = true;
-
+ }
/* Make sure no plane will use freed track */
BKE_tracking_plane_tracks_remove_point_track(tracking, track);
-
/* Delete f-curves associated with the track (such as weight, i.e.) */
- BLI_strescape(track_name_escaped, track->name, sizeof(track_name_escaped));
- BLI_snprintf(prefix, sizeof(prefix), "tracks[\"%s\"]", track_name_escaped);
- BKE_animdata_fix_paths_remove(&clip->id, prefix);
-
+ /* Escaped object name, escaped track name, rest of the path. */
+ char rna_path[MAX_NAME * 4 + 64];
+ BKE_tracking_get_rna_path_for_track(tracking,
+ track,
+ rna_path, sizeof(rna_path));
+ BKE_animdata_fix_paths_remove(&clip->id, rna_path);
+ /* Delete track itself. */
BKE_tracking_track_free(track);
BLI_freelinkN(tracksbase, track);
-
+ /* Send notifiers. */
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
-
if (used_for_stabilization) {
WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
}
-
+ /* Inform dependency graph. */
DEG_id_tag_update(&clip->id, 0);
-
- if (has_bundle)
+ if (has_bundle) {
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ }
}
void clip_delete_marker(bContext *C, MovieClip *clip, MovieTrackingTrack *track,
@@ -230,6 +230,28 @@ void clip_delete_marker(bContext *C, MovieClip *clip, MovieTrackingTrack *track,
}
}
+void clip_delete_plane_track(bContext *C,
+ MovieClip *clip,
+ MovieTrackingPlaneTrack *plane_track)
+{
+ MovieTracking *tracking = &clip->tracking;
+ ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
+ /* Delete f-curves associated with the track (such as weight, i.e.) */
+ /* Escaped object name, escaped track name, rest of the path. */
+ char rna_path[MAX_NAME * 4 + 64];
+ BKE_tracking_get_rna_path_for_plane_track(tracking,
+ plane_track,
+ rna_path, sizeof(rna_path));
+ BKE_animdata_fix_paths_remove(&clip->id, rna_path);
+ /* Delete the plane track itself. */
+ BKE_tracking_plane_track_free(plane_track);
+ BLI_freelinkN(plane_tracks_base, plane_track);
+ /* TODO(sergey): Any notifiers to be sent here? */
+ (void) C;
+ /* Inform dependency graph. */
+ DEG_id_tag_update(&clip->id, 0);
+}
+
void clip_view_center_to_point(SpaceClip *sc, float x, float y)
{
int width, height;
diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c
index 2439ac06d9c..4dd96a838e0 100644
--- a/source/blender/editors/space_clip/tracking_ops.c
+++ b/source/blender/editors/space_clip/tracking_ops.c
@@ -227,7 +227,6 @@ static int delete_track_exec(bContext *C, wmOperator *UNUSED(op))
MovieClip *clip = ED_space_clip_get_clip(sc);
MovieTracking *tracking = &clip->tracking;
bool changed = false;
-
/* Delete selected plane tracks. */
ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
for (MovieTrackingPlaneTrack *plane_track = plane_tracks_base->first,
@@ -236,14 +235,11 @@ static int delete_track_exec(bContext *C, wmOperator *UNUSED(op))
plane_track = next_plane_track)
{
next_plane_track = plane_track->next;
-
if (PLANE_TRACK_VIEW_SELECTED(plane_track)) {
- BKE_tracking_plane_track_free(plane_track);
- BLI_freelinkN(plane_tracks_base, plane_track);
+ clip_delete_plane_track(C, clip, plane_track);
changed = true;
}
}
-
/* Remove selected point tracks (they'll also be removed from planes which
* uses them).
*/
@@ -258,14 +254,11 @@ static int delete_track_exec(bContext *C, wmOperator *UNUSED(op))
changed = true;
}
}
-
/* Nothing selected now, unlock view so it can be scrolled nice again. */
sc->flag &= ~SC_LOCK_SELECTION;
-
if (changed) {
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
}
-
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c
index 4f042364c63..b13152883c3 100644
--- a/source/blender/editors/space_info/space_info.c
+++ b/source/blender/editors/space_info/space_info.c
@@ -50,6 +50,9 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_message.h"
+
+#include "RNA_access.h"
#include "UI_resources.h"
#include "UI_interface.h"
@@ -284,6 +287,22 @@ static void info_header_listener(
}
+static void info_header_region_message_subscribe(
+ const bContext *UNUSED(C),
+ WorkSpace *UNUSED(workspace), Scene *UNUSED(scene),
+ bScreen *UNUSED(screen), ScrArea *UNUSED(sa), ARegion *ar,
+ struct wmMsgBus *mbus)
+{
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+
+ WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_region_tag_redraw);
+ WM_msg_subscribe_rna_anon_prop(mbus, ViewLayer, name, &msg_sub_value_region_tag_redraw);
+}
+
static void recent_files_menu_draw(const bContext *UNUSED(C), Menu *menu)
{
struct RecentFile *recent;
@@ -347,6 +366,7 @@ void ED_spacetype_info(void)
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
art->listener = info_header_listener;
+ art->message_subscribe = info_header_region_message_subscribe;
art->init = info_header_region_init;
art->draw = info_header_region_draw;
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index 0a51b1a0d69..7689131bad4 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -51,6 +51,9 @@
#include "outliner_intern.h" /* own include */
+/* Prototypes. */
+static int collection_delete_exec(struct bContext *C, struct wmOperator *op);
+
/* -------------------------------------------------------------------- */
static LayerCollection *outliner_collection_active(bContext *C)
@@ -86,6 +89,19 @@ static CollectionOverride *outliner_override_active(bContext *UNUSED(C))
#endif
/* -------------------------------------------------------------------- */
+/* Poll functions. */
+
+static int collections_editor_poll(bContext *C)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ if ((sa) && (sa->spacetype == SPACE_OUTLINER)) {
+ SpaceOops *so = CTX_wm_space_outliner(C);
+ return (so->outlinevis == SO_COLLECTIONS);
+ }
+ return 0;
+}
+
+/* -------------------------------------------------------------------- */
/* collection manager operators */
/**
@@ -306,12 +322,14 @@ void OUTLINER_OT_collection_unlink(wmOperatorType *ot)
static int collection_new_exec(bContext *C, wmOperator *UNUSED(op))
{
+ SpaceOops *soops = CTX_wm_space_outliner(C);
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
SceneCollection *scene_collection = BKE_collection_add(&scene->id, NULL, COLLECTION_TYPE_NONE, NULL);
BKE_collection_link(view_layer, scene_collection);
+ outliner_cleanup_tree(soops);
DEG_relations_tag_update(bmain);
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
return OPERATOR_FINISHED;
@@ -332,6 +350,96 @@ void OUTLINER_OT_collection_new(wmOperatorType *ot)
}
/**********************************************************************************/
+/* Add new nested collection. */
+
+struct CollectionNewData
+{
+ bool error;
+ SceneCollection *scene_collection;
+};
+
+static TreeTraversalAction collection_find_selected_to_add(TreeElement *te, void *customdata)
+{
+ struct CollectionNewData *data = customdata;
+ SceneCollection *scene_collection = outliner_scene_collection_from_tree_element(te);
+
+ if (!scene_collection) {
+ return TRAVERSE_SKIP_CHILDS;
+ }
+
+ if (data->scene_collection != NULL) {
+ data->error = true;
+ return TRAVERSE_BREAK;
+ }
+
+ data->scene_collection = scene_collection;
+ return TRAVERSE_CONTINUE;
+}
+
+static int collection_nested_new_exec(bContext *C, wmOperator *op)
+{
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+
+ struct CollectionNewData data = {
+ .error = false,
+ .scene_collection = NULL,
+ };
+
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_selected_to_add, &data);
+
+ if (data.error) {
+ BKE_report(op->reports, RPT_ERROR, "More than one collection is selected");
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_collection_add(
+ &scene->id,
+ data.scene_collection,
+ COLLECTION_TYPE_NONE,
+ NULL);
+
+ outliner_cleanup_tree(soops);
+ DEG_relations_tag_update(bmain);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_collection_nested_new(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "New Nested Collection";
+ ot->idname = "OUTLINER_OT_collection_nested_new";
+ ot->description = "Add a new collection inside selected collection";
+
+ /* api callbacks */
+ ot->exec = collection_nested_new_exec;
+ ot->poll = collections_editor_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/**********************************************************************************/
+/* Delete selected collection. */
+
+void OUTLINER_OT_collection_delete_selected(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Delete Selected Collections";
+ ot->idname = "OUTLINER_OT_collection_delete_selected";
+ ot->description = "Delete all the selected collections";
+
+ /* api callbacks */
+ ot->exec = collection_delete_exec;
+ ot->poll = collections_editor_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/**********************************************************************************/
/**
* Returns true is selected element is a collection
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index af9d1fa3107..32f7ef39c19 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -1416,8 +1416,11 @@ static void outliner_draw_tree_element(
te->flag |= TE_ACTIVE; // for lookup in display hierarchies
}
+ if ((soops->outlinevis == SO_COLLECTIONS) && te->parent == NULL) {
+ /* Master collection can't expand/collapse. */
+ }
+ else if (te->subtree.first || (tselem->type == 0 && te->idcode == ID_SCE) || (te->flag & TE_LAZY_CLOSED)) {
/* open/close icon, only when sublevels, except for scene */
- if (te->subtree.first || (tselem->type == 0 && te->idcode == ID_SCE) || (te->flag & TE_LAZY_CLOSED)) {
int icon_x;
if (tselem->type == 0 && ELEM(te->idcode, ID_OB, ID_SCE))
icon_x = startx;
@@ -1458,6 +1461,11 @@ static void outliner_draw_tree_element(
}
offsx += UI_UNIT_X + 2 * ufac;
}
+ else if (tselem->type == 0 && ID_IS_STATIC_OVERRIDE(tselem->id)) {
+ UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_OVERRIDE,
+ alpha_fac);
+ offsx += UI_UNIT_X + 2 * ufac;
+ }
glDisable(GL_BLEND);
/* name */
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index 20dfa43ce8e..e81a7668bbc 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -340,6 +340,9 @@ void OUTLINER_OT_collection_objects_remove(struct wmOperatorType *ot);
void OUTLINER_OT_collection_objects_select(struct wmOperatorType *ot);
void OUTLINER_OT_collection_objects_deselect(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_nested_new(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_delete_selected(struct wmOperatorType *ot);
+
/* outliner_utils.c ---------------------------------------------- */
TreeElement *outliner_find_item_at_y(const SpaceOops *soops, const ListBase *tree, float view_co_y);
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index 856dd022c14..98e8aca0e1f 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -335,6 +335,9 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_collection_objects_remove);
WM_operatortype_append(OUTLINER_OT_collection_objects_select);
WM_operatortype_append(OUTLINER_OT_collection_objects_deselect);
+
+ WM_operatortype_append(OUTLINER_OT_collection_nested_new);
+ WM_operatortype_append(OUTLINER_OT_collection_delete_selected);
}
static wmKeyMap *outliner_item_drag_drop_modal_keymap(wmKeyConfig *keyconf)
@@ -432,6 +435,9 @@ void outliner_keymap(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "OUTLINER_OT_drivers_add_selected", DKEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "OUTLINER_OT_drivers_delete_selected", DKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_verify_item(keymap, "OUTLINER_OT_collection_nested_new", CKEY, KM_PRESS, 0, 0);
+ WM_keymap_verify_item(keymap, "OUTLINER_OT_collection_delete_selected", XKEY, KM_PRESS, 0, 0);
+
outliner_item_drag_drop_modal_keymap(keyconf);
}
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 2fe860508d5..23190a6fa80 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -1483,35 +1483,46 @@ static bool outliner_scene_collections_reorder_poll(
return true;
}
-static void outliner_add_scene_collection_objects(
+BLI_INLINE void outliner_add_scene_collection_init(TreeElement *te, SceneCollection *collection)
+{
+ te->name = collection->name;
+ te->directdata = collection;
+ te->reinsert = outliner_scene_collections_reorder;
+ te->reinsert_poll = outliner_scene_collections_reorder_poll;
+}
+
+BLI_INLINE void outliner_add_scene_collection_objects(
SpaceOops *soops, ListBase *tree, SceneCollection *collection, TreeElement *parent)
{
for (LinkData *link = collection->objects.first; link; link = link->next) {
outliner_add_element(soops, tree, link->data, parent, 0, 0);
}
- outliner_make_hierarchy(tree);
}
-static void outliner_add_scene_collections_recursive(
- SpaceOops *soops, ListBase *tree, ListBase *scene_collections, TreeElement *parent_ten)
+static TreeElement *outliner_add_scene_collection_recursive(
+ SpaceOops *soops, ListBase *tree, SceneCollection *scene_collection, TreeElement *parent_ten)
{
- for (SceneCollection *collection = scene_collections->first; collection; collection = collection->next) {
- TreeElement *ten = outliner_add_element(soops, tree, collection, parent_ten, TSE_SCENE_COLLECTION, 0);
-
- ten->name = collection->name;
- ten->directdata = collection;
- ten->reinsert = outliner_scene_collections_reorder;
- ten->reinsert_poll = outliner_scene_collections_reorder_poll;
+ TreeElement *ten = outliner_add_element(soops, tree, scene_collection, parent_ten, TSE_SCENE_COLLECTION, 0);
+ outliner_add_scene_collection_init(ten, scene_collection);
+ outliner_add_scene_collection_objects(soops, &ten->subtree, scene_collection, ten);
- outliner_add_scene_collections_recursive(soops, &ten->subtree, &collection->scene_collections, ten);
- outliner_add_scene_collection_objects(soops, &ten->subtree, collection, ten);
+ for (SceneCollection *scene_collection_nested = scene_collection->scene_collections.first;
+ scene_collection_nested != NULL;
+ scene_collection_nested = scene_collection_nested->next)
+ {
+ outliner_add_scene_collection_recursive(soops, &ten->subtree, scene_collection_nested, ten);
}
+
+ outliner_make_hierarchy(&ten->subtree);
+ return ten;
}
+
static void outliner_add_collections_master(SpaceOops *soops, Scene *scene)
{
- SceneCollection *master = BKE_collection_master(&scene->id);
- outliner_add_scene_collections_recursive(soops, &soops->tree, &master->scene_collections, NULL);
- outliner_add_scene_collection_objects(soops, &soops->tree, master, NULL);
+ SceneCollection *master_collection = BKE_collection_master(&scene->id);
+ TreeElement *ten = outliner_add_scene_collection_recursive(soops, &soops->tree, master_collection, NULL);
+ /* Master Collection should always be expanded. */
+ TREESTORE(ten)->flag &= ~TSE_CLOSED;
}
/* ======================================================= */
@@ -1967,8 +1978,10 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa
outliner_add_collections_master(soops, scene);
}
else {
- ten = outliner_add_element(soops, &soops->tree, OBACT(view_layer), NULL, 0, 0);
- ten->directdata = BASACT(view_layer);
+ if (BASACT(view_layer)) {
+ ten = outliner_add_element(soops, &soops->tree, OBACT(view_layer), NULL, 0, 0);
+ ten->directdata = BASACT(view_layer);
+ }
}
if ((soops->flag & SO_SKIP_SORT_ALPHA) == 0) {
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 8f6eb064b0d..cb0c5bd3717 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -2190,23 +2190,24 @@ static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op))
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq;
MetaStack *ms;
- bool nothingSelected = true;
+ bool nothing_selected = true;
seq = BKE_sequencer_active_get(scene);
if (seq && seq->flag & SELECT) { /* avoid a loop since this is likely to be selected */
- nothingSelected = false;
+ nothing_selected = false;
}
else {
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
if (seq->flag & SELECT) {
- nothingSelected = false;
+ nothing_selected = false;
break;
}
}
}
- if (nothingSelected)
+ if (nothing_selected) {
return OPERATOR_FINISHED;
+ }
/* for effects and modifiers, try to find a replacement input */
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index c1e45f8280f..58002880c5e 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -7405,7 +7405,7 @@ static void draw_editnurb(
}
#else
/* Same as loop above */
- count += 4 * max_ii((nr + max_ii(skip - 1, 0)) / (skip + 1), 0);
+ count += 4 * ((nr / (skip + 1)) + ((nr % (skip + 1)) != 0));
#endif
}
@@ -9217,7 +9217,10 @@ afterdraw:
/* help lines and so */
if (ob != scene->obedit && ob->parent) {
- if (BKE_object_is_visible(ob->parent)) {
+ const eObjectVisibilityCheck mode = eval_ctx->mode != DAG_EVAL_VIEWPORT ?
+ OB_VISIBILITY_CHECK_FOR_RENDER :
+ OB_VISIBILITY_CHECK_FOR_VIEWPORT;
+ if (BKE_object_is_visible(ob->parent, mode)) {
setlinestyle(3);
immBegin(GWN_PRIM_LINES, 2);
immVertex3fv(pos, ob->obmat[3]);
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 6ea2ff10af2..4a00329bd09 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -2060,7 +2060,7 @@ void ED_view3d_draw_offscreen(
/* XXX, should take depsgraph as arg */
Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, false);
BLI_assert(depsgraph != NULL);
- DRW_draw_render_loop_offscreen(depsgraph, eval_ctx->engine_type, ar, v3d, ofs);
+ DRW_draw_render_loop_offscreen(depsgraph, eval_ctx->engine_type, ar, v3d, do_sky, ofs);
}
/* restore size */
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_navigate.c b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
index b7a62c3e60f..bacb14336a9 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
@@ -127,9 +127,9 @@ static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmManipulatorG
const struct NavigateManipulatorInfo *info = &g_navigate_params[i];
navgroup->mpr_array[i] = WM_manipulator_new(info->manipulator, mgroup, NULL);
wmManipulator *mpr = navgroup->mpr_array[i];
- mpr->flag |= WM_MANIPULATOR_GRAB_CURSOR;
- copy_v3_fl(mpr->color, 1.0f);
- mpr->color[3] = 0.4f;
+ mpr->flag |= WM_MANIPULATOR_GRAB_CURSOR | WM_MANIPULATOR_DRAW_MODAL;
+ mpr->color[3] = 0.2f;
+ mpr->color_hi[3] = 0.4f;
/* may be overwritten later */
mpr->scale_basis = (MANIPULATOR_SIZE * MANIPULATOR_MINI_FAC) / 2;
@@ -159,10 +159,13 @@ static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmManipulatorG
RV3D_VIEW_TOP,
};
- for (int part_index = 0; part_index < 6; part_index+= 1) {
- PointerRNA *ptr = WM_manipulator_operator_set(mpr, mapping[part_index], ot_viewnumpad, NULL);
- RNA_enum_set(ptr, "type", RV3D_VIEW_FRONT + part_index);
+ for (int part_index = 0; part_index < 6; part_index += 1) {
+ PointerRNA *ptr = WM_manipulator_operator_set(mpr, part_index + 1, ot_viewnumpad, NULL);
+ RNA_enum_set(ptr, "type", mapping[part_index]);
}
+
+ /* When dragging an axis, use this instead. */
+ mpr->drag_part = 0;
}
mgroup->customdata = navgroup;
@@ -188,8 +191,8 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmManipulatorGr
navgroup->region_size[1] = ar->winy;
const float icon_size = MANIPULATOR_SIZE;
- const float icon_offset = (icon_size / 2.0) * MANIPULATOR_OFFSET_FAC * U.pixelsize;
- const float icon_offset_mini = icon_size * MANIPULATOR_MINI_OFFSET_FAC * U.pixelsize;
+ const float icon_offset = (icon_size / 2.0) * MANIPULATOR_OFFSET_FAC * U.ui_scale;
+ const float icon_offset_mini = icon_size * MANIPULATOR_MINI_OFFSET_FAC * U.ui_scale;
const float co[2] = {ar->winx - icon_offset, ar->winy - icon_offset};
wmManipulator *mpr;
@@ -220,7 +223,8 @@ void VIEW3D_WGT_navigate(wmManipulatorGroupType *wgt)
wgt->idname = "VIEW3D_WGT_navigate";
wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT |
- WM_MANIPULATORGROUPTYPE_SCALE);
+ WM_MANIPULATORGROUPTYPE_SCALE |
+ WM_MANIPULATORGROUPTYPE_DRAW_MODAL_ALL);
wgt->poll = WIDGETGROUP_navigate_poll;
wgt->setup = WIDGETGROUP_navigate_setup;
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c b/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c
index b520f239ef5..424b5dae402 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c
@@ -43,7 +43,6 @@
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
-#include "GPU_select.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -54,8 +53,6 @@
#include "WM_types.h"
#include "ED_screen.h"
-#include "ED_view3d.h"
-#include "ED_manipulator_library.h"
#include "view3d_intern.h"
@@ -96,8 +93,9 @@ static void axis_geom_draw(
};
qsort(&axis_order, ARRAY_SIZE(axis_order), sizeof(axis_order[0]), BLI_sortutil_cmp_float);
- const float scale_axis = 0.33f;
+ const float scale_axis = 0.25f;
static const float axis_highlight[4] = {1, 1, 1, 1};
+ static const float axis_nop[4] = {1, 1, 1, 0};
static const float axis_black[4] = {0, 0, 0, 1};
static float axis_color[3][4];
gpuPushMatrix();
@@ -138,7 +136,8 @@ static void axis_geom_draw(
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
glLineWidth(1.0f);
- immUniformColor4fv(axis_highlight);
+ /* Just draw depth values. */
+ immUniformColor4fv(axis_nop);
imm_draw_cube_fill_3d(pos_id, center, size);
immUniformColor4fv(axis_black);
madd_v3_v3fl(
@@ -224,7 +223,7 @@ static void axis3d_draw_intern(
static void manipulator_axis_draw(const bContext *C, wmManipulator *mpr)
{
const bool is_modal = mpr->state & WM_MANIPULATOR_STATE_MODAL;
- const bool is_highlight = (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0 && (mpr->highlight_part == 0);
+ const bool is_highlight = (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0;
(void)is_modal;
@@ -238,16 +237,17 @@ static int manipulator_axis_test_select(
{
float point_local[2] = {UNPACK2(event->mval)};
sub_v2_v2(point_local, mpr->matrix_basis[3]);
- mul_v2_fl(point_local, 1.0f / mpr->scale_basis);
+ mul_v2_fl(point_local, 1.0f / (mpr->scale_basis * U.ui_scale));
const float len_sq = len_squared_v2(point_local);
- if (len_sq > SQUARE(1.0 + HANDLE_SIZE)) {
+ if (len_sq > 1.0) {
return -1;
}
int part_best = -1;
int part_index = 1;
- float i_best_len_sq = SQUARE(HANDLE_SIZE);
+ /* Use 'SQUARE(HANDLE_SIZE)' if we want to be able to _not_ focus on one of the axis. */
+ float i_best_len_sq = FLT_MAX;
for (int i = 0; i < 3; i++) {
for (int is_pos = 0; is_pos < 2; is_pos++) {
float co[2] = {
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 882f0ec0bc0..880707f3b4b 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -273,7 +273,7 @@ void ED_view3d_smooth_view_ex(
* this means small rotations wont lag */
if (sview->quat && !sview->ofs && !sview->dist) {
/* scale the time allowed by the rotation */
- sms.time_allowed *= (double)angle_normalized_qtqt(sms.dst.quat, sms.src.quat) / M_PI; /* 180deg == 1.0 */
+ sms.time_allowed *= (double)fabsf(angle_signed_normalized_qtqt(sms.dst.quat, sms.src.quat)) / M_PI; /* 180deg == 1.0 */
}
/* ensure it shows correct */
@@ -1069,7 +1069,7 @@ char ED_view3d_quat_to_axis_view(const float quat[4], const float epsilon)
char view;
for (view = RV3D_VIEW_FRONT; view <= RV3D_VIEW_BOTTOM; view++) {
- if (angle_qtqt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT]) < epsilon) {
+ if (fabsf(angle_signed_qtqt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT])) < epsilon) {
return view;
}
}
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index 90428dc5ddd..0643687c29a 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -1155,6 +1155,8 @@ static void manipulator_xform_message_subscribe(
else {
BLI_assert(0);
}
+
+ WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_mpr_tag_refresh);
}
/** \} */
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index 946c2302d47..69e377faa97 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -375,6 +375,12 @@ typedef enum ID_Type {
#define ID_IS_LINKED(_id) (((ID *)(_id))->lib != NULL)
+#define ID_IS_STATIC_OVERRIDE(_id) (((ID *)(_id))->override_static != NULL && \
+ ((ID *)(_id))->override_static->reference != NULL)
+
+#define ID_IS_STATIC_OVERRIDE_TEMPLATE(_id) (((ID *)(_id))->override_static != NULL && \
+ ((ID *)(_id))->override_static->reference == NULL)
+
#ifdef GS
# undef GS
#endif
@@ -453,10 +459,18 @@ enum {
enum {
/* RESET_AFTER_USE, used by update code (depsgraph). */
+ ID_RECALC_NONE = 0,
+ /* Generic recalc flag, when nothing else matches. */
ID_RECALC = 1 << 0,
- ID_RECALC_DATA = 1 << 1,
- ID_RECALC_SKIP_ANIM_TAG = 1 << 2,
- ID_RECALC_ALL = (ID_RECALC | ID_RECALC_DATA),
+ /* Per-component update flags. */
+ ID_RECALC_ANIMATION = 1 << 1,
+ ID_RECALC_DRAW = 1 << 2,
+ ID_RECALC_DRAW_CACHE = 1 << 3,
+ ID_RECALC_GEOMETRY = 1 << 4,
+ ID_RECALC_TRANSFORM = 1 << 5,
+ ID_RECALC_COLLECTIONS = 1 << 6,
+ /* Special flag to check if SOMETHING was changed. */
+ ID_RECALC_ALL = (~(int)0),
};
/* To filter ID types (filter_id) */
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index a876cacbcc8..6cf6dc06d5e 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -208,7 +208,7 @@ typedef struct Object {
/* did last modifier stack generation need mapping support? */
char lastNeedMapping; /* bool */
- char pad;
+ char duplicator_visibility_flag;
/* dupli-frame settings */
int dupon, dupoff, dupsta, dupend;
@@ -709,6 +709,12 @@ enum {
OB_LOCK_ROT4D = 1 << 10,
};
+/* ob->duplicator_visibility_flag */
+enum {
+ OB_DUPLI_FLAG_VIEWPORT = 1 << 0,
+ OB_DUPLI_FLAG_RENDER = 1 << 1,
+};
+
/* ob->mode */
typedef enum eObjectMode {
OB_MODE_OBJECT = 0,
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 7c78d42a530..1e6023bd278 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -1043,7 +1043,6 @@ static void rna_def_ID(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Is Updated", "Data-block is tagged for recalculation");
prop = RNA_def_property(srna, "is_updated_data", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "recalc", ID_RECALC_DATA);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_boolean_funcs(prop, "rna_ID_is_updated_data_get", NULL);
RNA_def_property_ui_text(prop, "Is Updated Data", "Data-block data is tagged for recalculation");
diff --git a/source/blender/makesrna/intern/rna_context.c b/source/blender/makesrna/intern/rna_context.c
index 3df114282fd..bcd805b0f3a 100644
--- a/source/blender/makesrna/intern/rna_context.c
+++ b/source/blender/makesrna/intern/rna_context.c
@@ -132,7 +132,11 @@ static PointerRNA rna_Context_scene_get(PointerRNA *ptr)
static PointerRNA rna_Context_view_layer_get(PointerRNA *ptr)
{
bContext *C = (bContext *)ptr->data;
- return rna_pointer_inherit_refine(ptr, &RNA_ViewLayer, CTX_data_view_layer(C));
+ Scene *scene = CTX_data_scene(C);
+ PointerRNA scene_ptr;
+
+ RNA_id_pointer_create(&scene->id, &scene_ptr);
+ return rna_pointer_inherit_refine(&scene_ptr, &RNA_ViewLayer, CTX_data_view_layer(C));
}
static PointerRNA rna_Context_view_render_get(PointerRNA *ptr)
diff --git a/source/blender/makesrna/intern/rna_depsgraph.c b/source/blender/makesrna/intern/rna_depsgraph.c
index ffa75dd75cb..706fb23ab56 100644
--- a/source/blender/makesrna/intern/rna_depsgraph.c
+++ b/source/blender/makesrna/intern/rna_depsgraph.c
@@ -120,13 +120,26 @@ static int rna_DepsgraphIter_is_instance_get(PointerRNA *ptr)
/* **************** Depsgraph **************** */
-static void rna_Depsgraph_debug_graphviz(Depsgraph *graph, const char *filename)
+static void rna_Depsgraph_debug_relations_graphviz(Depsgraph *graph,
+ const char *filename)
{
FILE *f = fopen(filename, "w");
if (f == NULL) {
return;
}
- DEG_debug_graphviz(graph, f, "Depsgraph", false);
+ DEG_debug_relations_graphviz(graph, f, "Depsgraph");
+ fclose(f);
+}
+
+static void rna_Depsgraph_debug_stats_gnuplot(Depsgraph *graph,
+ const char *filename,
+ const char *output_filename)
+{
+ FILE *f = fopen(filename, "w");
+ if (f == NULL) {
+ return;
+ }
+ DEG_debug_stats_gnuplot(graph, f, "Timing Statistics", output_filename);
fclose(f);
}
@@ -155,6 +168,7 @@ static void rna_Depsgraph_objects_begin(CollectionPropertyIterator *iter, Pointe
data->flag = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
DEG_ITER_OBJECT_FLAG_VISIBLE |
DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET;
+ data->mode = DEG_ITER_OBJECT_MODE_RENDER;
((BLI_Iterator *)iter->internal.custom)->valid = true;
DEG_iterator_objects_begin(iter->internal.custom, data);
@@ -195,6 +209,7 @@ static void rna_Depsgraph_duplis_begin(CollectionPropertyIterator *iter, Pointer
DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET |
DEG_ITER_OBJECT_FLAG_VISIBLE |
DEG_ITER_OBJECT_FLAG_DUPLI;
+ data->mode = DEG_ITER_OBJECT_MODE_RENDER;
((BLI_Iterator *)iter->internal.custom)->valid = true;
DEG_iterator_objects_begin(iter->internal.custom, data);
@@ -297,10 +312,18 @@ static void rna_def_depsgraph(BlenderRNA *brna)
srna = RNA_def_struct(brna, "Depsgraph", NULL);
RNA_def_struct_ui_text(srna, "Dependency Graph", "");
- func = RNA_def_function(srna, "debug_graphviz", "rna_Depsgraph_debug_graphviz");
+ func = RNA_def_function(srna, "debug_relations_graphviz", "rna_Depsgraph_debug_relations_graphviz");
+ parm = RNA_def_string_file_path(func, "filename", NULL, FILE_MAX, "File Name",
+ "File in which to store graphviz debug output");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+
+ func = RNA_def_function(srna, "debug_stats_gnuplot", "rna_Depsgraph_debug_stats_gnuplot");
parm = RNA_def_string_file_path(func, "filename", NULL, FILE_MAX, "File Name",
"File in which to store graphviz debug output");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_string_file_path(func, "output_filename", NULL, FILE_MAX, "Output File Name",
+ "File name where gnuplot script will save the result");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
func = RNA_def_function(srna, "debug_tag_update", "rna_Depsgraph_debug_tag_update");
diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c
index 00b08957fdd..bcf8f36d7ce 100644
--- a/source/blender/makesrna/intern/rna_layer.c
+++ b/source/blender/makesrna/intern/rna_layer.c
@@ -870,7 +870,7 @@ static void rna_LayerObjects_selected_begin(CollectionPropertyIterator *iter, Po
static void rna_ViewLayer_update_tagged(ViewLayer *UNUSED(view_layer), bContext *C)
{
Depsgraph *graph = CTX_data_depsgraph(C);
- DEG_OBJECT_ITER(graph, ob,
+ DEG_OBJECT_ITER(graph, ob, DEG_ITER_OBJECT_MODE_VIEWPORT,
DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET |
DEG_ITER_OBJECT_FLAG_LINKED_INDIRECTLY |
@@ -991,15 +991,14 @@ static void rna_def_scene_collections(BlenderRNA *brna, PropertyRNA *cprop)
func = RNA_def_function(srna, "new", "rna_SceneCollection_new");
RNA_def_function_ui_description(func, "Add a collection to scene");
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
- parm = RNA_def_string(func, "name", "SceneCollection", 0, "", "New name for the collection (not unique)");
- RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_string(func, "name", NULL, 0, "", "New name for the collection (not unique)");
parm = RNA_def_pointer(func, "result", "SceneCollection", "", "Newly created collection");
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "remove", "rna_SceneCollection_remove");
- RNA_def_function_ui_description(func, "Remove a collection layer");
+ RNA_def_function_ui_description(func, "Remove a collection and move its objects to the master collection");
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func, "layer", "SceneCollection", "", "Collection to remove");
+ parm = RNA_def_pointer(func, "collection", "SceneCollection", "", "Collection to remove");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
}
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index c9dcc787617..9ba341fde03 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -233,7 +233,13 @@ static void rna_Object_hide_update(Main *bmain, Scene *UNUSED(scene), PointerRNA
static int rna_Object_is_visible_get(PointerRNA *ptr)
{
Object *ob = ptr->id.data;
- return BKE_object_is_visible(ob);
+ /* The duplicators final visibility is not evaluated by depsgraph, so it's
+ * in ob->base_flag & VISIBLED. Instead we need to take into account whether
+ * we are rendering or not, and the ob->duplicator_visibility_flag.
+ * However for this assessor we don't know if we are rendering, so we just
+ * ignore the duplicator visibility
+ */
+ return BKE_object_is_visible(ob, OB_VISIBILITY_CHECK_UNKNOWN_RENDER_MODE);
}
static void rna_Object_collection_properties_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
@@ -2800,6 +2806,14 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, 1);
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_hide_update");
+ prop = RNA_def_property(srna, "show_duplicator_for_render", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "duplicator_visibility_flag", OB_DUPLI_FLAG_RENDER);
+ RNA_def_property_ui_text(prop, "Render Duplicator", "Make duplicator visible when rendering");
+
+ prop = RNA_def_property(srna, "show_duplicator_for_viewport", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "duplicator_visibility_flag", OB_DUPLI_FLAG_VIEWPORT);
+ RNA_def_property_ui_text(prop, "Show Duplicator", "Make duplicator visible in the viewport");
+
prop = RNA_def_property(srna, "is_visible", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_Object_is_visible_get", NULL);
RNA_def_property_ui_text(prop, "Visible", "Visible to camera rays, set only on objects evaluated by depsgraph");
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index 67eaa22fbe4..12e56b8e926 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -2292,11 +2292,6 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Size", "Show particle size");
RNA_def_property_update(prop, 0, "rna_Particle_redo");
- prop = RNA_def_property(srna, "use_render_emitter", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_EMITTER);
- RNA_def_property_ui_text(prop, "Emitter", "Render emitter Object also");
- RNA_def_property_update(prop, 0, "rna_Particle_redo");
-
prop = RNA_def_property(srna, "show_health", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_HEALTH);
RNA_def_property_ui_text(prop, "Health", "Draw boid health");
diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c
index da4eea41223..38149734bc2 100644
--- a/source/blender/makesrna/intern/rna_rna.c
+++ b/source/blender/makesrna/intern/rna_rna.c
@@ -337,7 +337,7 @@ static void rna_Struct_property_tags_begin(CollectionPropertyIterator *iter, Poi
/* here ptr->data should always be the same as iter->parent.type */
StructRNA *srna = (StructRNA *)ptr->data;
const EnumPropertyItem *tag_defines = RNA_struct_property_tag_defines(srna);
- unsigned int tag_count = RNA_enum_items_count(tag_defines);
+ unsigned int tag_count = tag_defines ? RNA_enum_items_count(tag_defines) : 0;
rna_iterator_array_begin(iter, (void *)tag_defines, sizeof(EnumPropertyItem), tag_count, 0, NULL);
}
diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c
index d23017429c1..ccc118edfb6 100644
--- a/source/blender/makesrna/intern/rna_tracking.c
+++ b/source/blender/makesrna/intern/rna_tracking.c
@@ -48,6 +48,9 @@
#ifdef RNA_RUNTIME
+#include "DNA_anim_types.h"
+
+#include "BKE_animsys.h"
#include "BKE_node.h"
#include "DEG_depsgraph.h"
@@ -56,71 +59,6 @@
#include "WM_api.h"
-static MovieTrackingObject *tracking_object_from_track(MovieClip *clip,
- MovieTrackingTrack *track)
-{
- MovieTracking *tracking = &clip->tracking;
- ListBase *tracksbase = &tracking->tracks;
- /* TODO: it's a bit difficult to find list track came from knowing just
- * movie clip ID and MovieTracking structure, so keep this naive
- * search for a while */
- if (BLI_findindex(tracksbase, track) == -1) {
- MovieTrackingObject *object = tracking->objects.first;
- while (object) {
- if (BLI_findindex(&object->tracks, track) != -1) {
- return object;
- }
- object = object->next;
- }
- }
- return NULL;
-}
-
-static ListBase *tracking_tracksbase_from_track(MovieClip *clip,
- MovieTrackingTrack *track)
-{
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *object = tracking_object_from_track(clip, track);
- if (object != NULL) {
- return &object->tracks;
- }
- return &tracking->tracks;
-}
-
-static MovieTrackingObject *tracking_object_from_plane_track(
- MovieClip *clip,
- MovieTrackingPlaneTrack *plane_track)
-{
- MovieTracking *tracking = &clip->tracking;
- ListBase *plane_tracks_base = &tracking->plane_tracks;
- /* TODO: it's a bit difficult to find list track came from knowing just
- * movie clip ID and MovieTracking structure, so keep this naive
- * search for a while */
- if (BLI_findindex(plane_tracks_base, plane_track) == -1) {
- MovieTrackingObject *object = tracking->objects.first;
- while (object) {
- if (BLI_findindex(&object->plane_tracks, plane_track) != -1) {
- return object;
- }
- object = object->next;
- }
- }
- return NULL;
-}
-
-static ListBase *tracking_tracksbase_from_plane_track(
- MovieClip *clip,
- MovieTrackingPlaneTrack *plane_track)
-{
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *object = tracking_object_from_plane_track(clip,
- plane_track);
- if (object != NULL) {
- return &object->plane_tracks;
- }
- return &tracking->plane_tracks;
-}
-
static char *rna_tracking_path(PointerRNA *UNUSED(ptr))
{
return BLI_sprintfN("tracking");
@@ -150,19 +88,12 @@ static char *rna_trackingTrack_path(PointerRNA *ptr)
{
MovieClip *clip = (MovieClip *)ptr->id.data;
MovieTrackingTrack *track = (MovieTrackingTrack *)ptr->data;
- MovieTrackingObject *object = tracking_object_from_track(clip, track);
- char track_name_esc[sizeof(track->name) * 2];
- BLI_strescape(track_name_esc, track->name, sizeof(track_name_esc));
- if (object == NULL) {
- return BLI_sprintfN("tracking.tracks[\"%s\"]", track_name_esc);
- }
- else {
- char object_name_esc[sizeof(object->name) * 2];
- BLI_strescape(object_name_esc, object->name, sizeof(object_name_esc));
- return BLI_sprintfN("tracking.objects[\"%s\"].tracks[\"%s\"]",
- object_name_esc,
- track_name_esc);
- }
+ /* Escaped object name, escaped track name, rest of the path. */
+ char rna_path[MAX_NAME * 4 + 64];
+ BKE_tracking_get_rna_path_for_track(&clip->tracking,
+ track,
+ rna_path, sizeof(rna_path));
+ return BLI_strdup(rna_path);
}
static void rna_trackingTracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
@@ -256,9 +187,26 @@ static void rna_trackingTrack_name_set(PointerRNA *ptr, const char *value)
{
MovieClip *clip = (MovieClip *)ptr->id.data;
MovieTrackingTrack *track = (MovieTrackingTrack *)ptr->data;
- ListBase *tracksbase = tracking_tracksbase_from_track(clip, track);
+ ListBase *tracksbase =
+ BKE_tracking_find_tracks_list_for_track(&clip->tracking, track);
+ /* Store old name, for the animation fix later. */
+ char old_name[sizeof(track->name)];
+ BLI_strncpy(old_name, track->name, sizeof(track->name));
+ /* Update the name, */
BLI_strncpy(track->name, value, sizeof(track->name));
BKE_tracking_track_unique_name(tracksbase, track);
+ /* Fix animation paths. */
+ AnimData *adt = BKE_animdata_from_id(&clip->id);
+ if (adt != NULL) {
+ char rna_path[MAX_NAME * 2 + 64];
+ BKE_tracking_get_rna_path_prefix_for_track(&clip->tracking,
+ track,
+ rna_path, sizeof(rna_path));
+ BKE_animdata_fix_paths_rename(&clip->id, adt, NULL,
+ rna_path,
+ old_name, track->name,
+ 0, 0, 1);
+ }
}
static int rna_trackingTrack_select_get(PointerRNA *ptr)
@@ -327,28 +275,40 @@ static char *rna_trackingPlaneTrack_path(PointerRNA *ptr)
{
MovieClip *clip = (MovieClip *)ptr->id.data;
MovieTrackingPlaneTrack *plane_track = (MovieTrackingPlaneTrack *)ptr->data;
- char track_name_esc[sizeof(plane_track->name) * 2];
- MovieTrackingObject *object = tracking_object_from_plane_track(clip, plane_track);
- BLI_strescape(track_name_esc, plane_track->name, sizeof(track_name_esc));
- if (object == NULL) {
- return BLI_sprintfN("tracking.plane_tracks[\"%s\"]", track_name_esc);
- }
- else {
- char object_name_esc[sizeof(object->name) * 2];
- BLI_strescape(object_name_esc, object->name, sizeof(object_name_esc));
- return BLI_sprintfN("tracking.objects[\"%s\"].plane_tracks[\"%s\"]",
- object_name_esc,
- track_name_esc);
- }
+ /* Escaped object name, escaped track name, rest of the path. */
+ char rna_path[MAX_NAME * 4 + 64];
+ BKE_tracking_get_rna_path_for_plane_track(&clip->tracking,
+ plane_track,
+ rna_path, sizeof(rna_path));
+ return BLI_strdup(rna_path);
}
static void rna_trackingPlaneTrack_name_set(PointerRNA *ptr, const char *value)
{
MovieClip *clip = (MovieClip *)ptr->id.data;
MovieTrackingPlaneTrack *plane_track = (MovieTrackingPlaneTrack *)ptr->data;
- ListBase *plane_tracks_base = tracking_tracksbase_from_plane_track(clip, plane_track);
+ ListBase *plane_tracks_base =
+ BKE_tracking_find_tracks_list_for_plane_track(&clip->tracking,
+ plane_track);
+ /* Store old name, for the animation fix later. */
+ char old_name[sizeof(plane_track->name)];
+ BLI_strncpy(old_name, plane_track->name, sizeof(plane_track->name));
+ /* Update the name, */
BLI_strncpy(plane_track->name, value, sizeof(plane_track->name));
BKE_tracking_plane_track_unique_name(plane_tracks_base, plane_track);
+ /* Fix animation paths. */
+ AnimData *adt = BKE_animdata_from_id(&clip->id);
+ if (adt != NULL) {
+ char rna_path[MAX_NAME * 2 + 64];
+ BKE_tracking_get_rna_path_prefix_for_plane_track(&clip->tracking,
+ plane_track,
+ rna_path,
+ sizeof(rna_path));
+ BKE_animdata_fix_paths_rename(&clip->id, adt, NULL,
+ rna_path,
+ old_name, plane_track->name,
+ 0, 0, 1);
+ }
}
static char *rna_trackingCamera_path(PointerRNA *UNUSED(ptr))
@@ -1651,6 +1611,7 @@ static void rna_def_trackingPlaneTrack(BlenderRNA *brna)
/* auto keyframing */
prop = RNA_def_property(srna, "use_auto_keying", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PLANE_TRACK_AUTOKEY);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Auto Keyframe", "Automatic keyframe insertion when moving plane corners");
RNA_def_property_ui_icon(prop, ICON_REC, 0);
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index d25888e0f93..36f07db727b 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -763,8 +763,10 @@ static PointerRNA rna_Window_view_layer_get(PointerRNA *ptr)
Scene *scene = WM_window_get_active_scene(win);
WorkSpace *workspace = WM_window_get_active_workspace(win);
ViewLayer *view_layer = BKE_workspace_view_layer_get(workspace, scene);
+ PointerRNA scene_ptr;
- return rna_pointer_inherit_refine(ptr, &RNA_ViewLayer, view_layer);
+ RNA_id_pointer_create(&scene->id, &scene_ptr);
+ return rna_pointer_inherit_refine(&scene_ptr, &RNA_ViewLayer, view_layer);
}
static void rna_Window_view_layer_set(PointerRNA *ptr, PointerRNA value)
diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c
index b623293ed5c..2919f169d00 100644
--- a/source/blender/modifiers/intern/MOD_surfacedeform.c
+++ b/source/blender/modifiers/intern/MOD_surfacedeform.c
@@ -314,11 +314,13 @@ BLI_INLINE int isPolyValid(const float coords[][2], const unsigned int nr)
copy_v2_v2(prev_co, coords[nr - 1]);
sub_v2_v2v2(prev_vec, prev_co, coords[nr - 2]);
+ normalize_v2(prev_vec);
for (int i = 0; i < nr; i++) {
sub_v2_v2v2(curr_vec, coords[i], prev_co);
- if (len_squared_v2(curr_vec) < FLT_EPSILON) {
+ const float curr_len = normalize_v2(curr_vec);
+ if (curr_len < FLT_EPSILON) {
return MOD_SDEF_BIND_RESULT_OVERLAP_ERR;
}
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 74de3fcded6..fc60c70c2c4 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -4668,9 +4668,8 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject *
/* the emitter has to be processed first (render levels of modifiers) */
/* so here we only check if the emitter should be rendered */
if (ob->particlesystem.first) {
- show_emitter= 0;
+ show_emitter = (ob->duplicator_visibility_flag & OB_DUPLI_FLAG_RENDER) != 0;
for (psys=ob->particlesystem.first; psys; psys=psys->next) {
- show_emitter += psys->part->draw & PART_DRAW_EMITTER;
if (!(re->r.scemode & R_VIEWPORT_PREVIEW)) {
psys_has_renderdata |= (psys->renderdata != NULL);
psys_render_set(ob, psys, re->viewmat, re->winmat, re->winx, re->winy, timeoffset);
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index b1ec1c009df..d50788063e2 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -2251,13 +2251,32 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
wm_manipulatormap_handler_context(C, handler);
wm_region_mouse_co(C, event);
+ if (event->type == MOUSEMOVE) {
+ WM_manipulatormap_tooltip_clear(C, mmap);
+ }
+
/* handle manipulator highlighting */
if (event->type == MOUSEMOVE && !wm_manipulatormap_modal_get(mmap)) {
int part;
mpr = wm_manipulatormap_highlight_find(mmap, C, event, &part);
wm_manipulatormap_highlight_set(mmap, C, mpr, part);
+ if (mpr != NULL) {
+ WM_manipulatormap_tooltip_timer_init(C, mmap);
+ }
}
/* handle user configurable manipulator-map keymap */
+ else if ((event->type == TIMER) &&
+ (event->customdata == WM_manipulatormap_tooltip_timer_get(mmap)))
+ {
+ if (mpr) {
+ if (mpr->state & WM_MANIPULATOR_STATE_MODAL) {
+ WM_manipulatormap_tooltip_clear(C, mmap);
+ }
+ else {
+ WM_manipulatormap_tooltip_create(C, mmap);
+ }
+ }
+ }
else {
/* Either we operate on a single highlighted item
* or groups attached to the selected manipulators.
diff --git a/source/blender/windowmanager/manipulators/WM_manipulator_api.h b/source/blender/windowmanager/manipulators/WM_manipulator_api.h
index 9214bccb6a0..7a31f4e6f1f 100644
--- a/source/blender/windowmanager/manipulators/WM_manipulator_api.h
+++ b/source/blender/windowmanager/manipulators/WM_manipulator_api.h
@@ -259,6 +259,15 @@ bool WM_manipulatormap_minmax(
const struct wmManipulatorMap *mmap, bool use_hidden, bool use_select,
float r_min[3], float r_max[3]);
+void WM_manipulatormap_tooltip_create(
+ struct bContext *C, struct wmManipulatorMap *mmap);
+void WM_manipulatormap_tooltip_clear(
+ struct bContext *C, struct wmManipulatorMap *mmap);
+void WM_manipulatormap_tooltip_timer_init(
+ struct bContext *C, struct wmManipulatorMap *mmap);
+const void *WM_manipulatormap_tooltip_timer_get(
+ struct wmManipulatorMap *mmap);
+
/* -------------------------------------------------------------------- */
/* wmManipulatorMapType */
diff --git a/source/blender/windowmanager/manipulators/WM_manipulator_types.h b/source/blender/windowmanager/manipulators/WM_manipulator_types.h
index e8b81e1a78c..f2c0a8e93d9 100644
--- a/source/blender/windowmanager/manipulators/WM_manipulator_types.h
+++ b/source/blender/windowmanager/manipulators/WM_manipulator_types.h
@@ -182,6 +182,8 @@ struct wmManipulator {
/* Optional ID for highlighting different parts of this manipulator.
* -1 when unset, otherwise a valid index. (Used as index to 'op_data'). */
int highlight_part;
+ /* For single click button manipulators, use a different part as a fallback, -1 when unused. */
+ int drag_part;
/* Transformation of the manipulator in 2d or 3d space.
* - Matrix axis are expected to be unit length (scale is applied after).
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator.c
index 7ca1f8fd5f2..5190a4932b4 100644
--- a/source/blender/windowmanager/manipulators/intern/wm_manipulator.c
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator.c
@@ -98,6 +98,8 @@ static wmManipulator *wm_manipulator_create(
unit_m4(mpr->matrix_basis);
unit_m4(mpr->matrix_offset);
+ mpr->drag_part = -1;
+
return mpr;
}
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c
index ebb5d835455..c4220aa3a5d 100644
--- a/source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator_group.c
@@ -39,6 +39,7 @@
#include "BLI_listbase.h"
#include "BLI_string.h"
+#include "BLI_math.h"
#include "BKE_context.h"
#include "BKE_main.h"
@@ -61,6 +62,10 @@
# include "BPY_extern.h"
#endif
+/* Allow manipulator part's to be single click only,
+ * dragging falls back to activating their 'drag_part' action. */
+#define USE_DRAG_DETECT
+
/* -------------------------------------------------------------------- */
/** \name wmManipulatorGroup
*
@@ -307,15 +312,71 @@ typedef struct ManipulatorTweakData {
int init_event; /* initial event type */
int flag; /* tweak flags */
+
+#ifdef USE_DRAG_DETECT
+ /* True until the mouse is moved (only use when the operator has no modal).
+ * this allows some manipulators to be click-only. */
+ enum {
+ /* Don't detect dragging. */
+ DRAG_NOP = 0,
+ /* Detect dragging (wait until a drag or click is detected). */
+ DRAG_DETECT,
+ /* Drag has started, idle until there is no active modal operator.
+ * This is needed because finishing the modal operator also exits
+ * the modal manipulator state (un-grabbs the cursor).
+ * Ideally this workaround could be removed later. */
+ DRAG_IDLE,
+ } drag_state;
+#endif
+
} ManipulatorTweakData;
-static void manipulator_tweak_finish(bContext *C, wmOperator *op, const bool cancel)
+static bool manipulator_tweak_start(
+ bContext *C, wmManipulatorMap *mmap, wmManipulator *mpr, const wmEvent *event)
+{
+ /* activate highlighted manipulator */
+ wm_manipulatormap_modal_set(mmap, C, mpr, event, true);
+
+ return (mpr->state & WM_MANIPULATOR_STATE_MODAL);
+}
+
+static bool manipulator_tweak_start_and_finish(
+ bContext *C, wmManipulatorMap *mmap, wmManipulator *mpr, const wmEvent *event, bool *r_is_modal)
+{
+ wmManipulatorOpElem *mpop = WM_manipulator_operator_get(mpr, mpr->highlight_part);
+ if (r_is_modal) {
+ *r_is_modal = false;
+ }
+ if (mpop && mpop->type) {
+ /* XXX temporary workaround for modal manipulator operator
+ * conflicting with modal operator attached to manipulator */
+ if (mpop->type->modal) {
+ /* activate highlighted manipulator */
+ wm_manipulatormap_modal_set(mmap, C, mpr, event, true);
+ if (r_is_modal) {
+ *r_is_modal = true;
+ }
+ }
+ else {
+ /* Allow for 'button' manipulators, single click to run an action. */
+ WM_operator_name_call_ptr(C, mpop->type, WM_OP_INVOKE_DEFAULT, &mpop->ptr);
+ }
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+static void manipulator_tweak_finish(bContext *C, wmOperator *op, const bool cancel, bool clear_modal)
{
ManipulatorTweakData *mtweak = op->customdata;
if (mtweak->mpr_modal->type->exit) {
mtweak->mpr_modal->type->exit(C, mtweak->mpr_modal, cancel);
}
- wm_manipulatormap_modal_set(mtweak->mmap, C, mtweak->mpr_modal, NULL, false);
+ if (clear_modal) {
+ wm_manipulatormap_modal_set(mtweak->mmap, C, mtweak->mpr_modal, NULL, false);
+ }
MEM_freeN(mtweak);
}
@@ -323,27 +384,68 @@ static int manipulator_tweak_modal(bContext *C, wmOperator *op, const wmEvent *e
{
ManipulatorTweakData *mtweak = op->customdata;
wmManipulator *mpr = mtweak->mpr_modal;
+ int retval = OPERATOR_PASS_THROUGH;
+ bool clear_modal = true;
if (mpr == NULL) {
BLI_assert(0);
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
}
- if (event->type == mtweak->init_event && event->val == KM_RELEASE) {
- manipulator_tweak_finish(C, op, false);
- return OPERATOR_FINISHED;
- }
+#ifdef USE_DRAG_DETECT
+ wmManipulatorMap *mmap = mtweak->mmap;
+ if (mtweak->drag_state == DRAG_DETECT) {
+ if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
+ if (len_manhattan_v2v2_int(&event->x, mmap->mmap_context.event_xy) > 2) {
+ mtweak->drag_state = DRAG_IDLE;
+ mpr->highlight_part = mpr->drag_part;
+ }
+ }
+ else if (event->type == mtweak->init_event && event->val == KM_RELEASE) {
+ mtweak->drag_state = DRAG_NOP;
+ retval = OPERATOR_FINISHED;
+ }
+ if (mtweak->drag_state != DRAG_DETECT) {
+ /* Follow logic in 'manipulator_tweak_invoke' */
+ bool is_modal = false;
+ if (manipulator_tweak_start_and_finish(C, mmap, mpr, event, &is_modal)) {
+ if (is_modal) {
+ clear_modal = false;
+ }
+ }
+ else {
+ if (!manipulator_tweak_start(C, mmap, mpr, event)) {
+ retval = OPERATOR_FINISHED;
+ }
+ }
+ }
+ }
+ if (mtweak->drag_state == DRAG_IDLE) {
+ if (mmap->mmap_context.modal != NULL) {
+ return OPERATOR_PASS_THROUGH;
+ }
+ else {
+ manipulator_tweak_finish(C, op, false, false);
+ return OPERATOR_FINISHED;
+ }
+ }
+#endif /* USE_DRAG_DETECT */
- if (event->type == EVT_MODAL_MAP) {
+ if (retval == OPERATOR_FINISHED) {
+ /* pass */
+ }
+ else if (event->type == mtweak->init_event && event->val == KM_RELEASE) {
+ retval = OPERATOR_FINISHED;
+ }
+ else if (event->type == EVT_MODAL_MAP) {
switch (event->val) {
case TWEAK_MODAL_CANCEL:
- manipulator_tweak_finish(C, op, true);
- return OPERATOR_CANCELLED;
+ retval = OPERATOR_CANCELLED;
+ break;
case TWEAK_MODAL_CONFIRM:
- manipulator_tweak_finish(C, op, false);
- return OPERATOR_FINISHED;
-
+ retval = OPERATOR_FINISHED;
+ break;
case TWEAK_MODAL_PRECISION_ON:
mtweak->flag |= WM_MANIPULATOR_TWEAK_PRECISE;
break;
@@ -360,20 +462,28 @@ static int manipulator_tweak_modal(bContext *C, wmOperator *op, const wmEvent *e
}
}
+ if (retval != OPERATOR_PASS_THROUGH) {
+ manipulator_tweak_finish(C, op, retval != OPERATOR_FINISHED, clear_modal);
+ return retval;
+ }
+
/* handle manipulator */
wmManipulatorFnModal modal_fn = mpr->custom_modal ? mpr->custom_modal : mpr->type->modal;
- int retval = modal_fn(C, mpr, event, mtweak->flag);
+ if (modal_fn) {
+ int modal_retval = modal_fn(C, mpr, event, mtweak->flag);
- if ((retval & OPERATOR_RUNNING_MODAL) == 0) {
- manipulator_tweak_finish(C, op, (retval & OPERATOR_CANCELLED) != 0);
- return OPERATOR_FINISHED;
- }
+ if ((modal_retval & OPERATOR_RUNNING_MODAL) == 0) {
+ manipulator_tweak_finish(C, op, (modal_retval & OPERATOR_CANCELLED) != 0, true);
+ return OPERATOR_FINISHED;
+ }
- /* Ugly hack to send manipulator events */
- ((wmEvent *)event)->type = EVT_MANIPULATOR_UPDATE;
+ /* Ugly hack to send manipulator events */
+ ((wmEvent *)event)->type = EVT_MANIPULATOR_UPDATE;
+ }
/* always return PASS_THROUGH so modal handlers
* with manipulators attached can update */
+ BLI_assert(retval == OPERATOR_PASS_THROUGH);
return OPERATOR_PASS_THROUGH;
}
@@ -383,36 +493,44 @@ static int manipulator_tweak_invoke(bContext *C, wmOperator *op, const wmEvent *
wmManipulatorMap *mmap = ar->manipulator_map;
wmManipulator *mpr = mmap->mmap_context.highlight;
+ /* Needed for single click actions which don't enter modal state. */
+ WM_manipulatormap_tooltip_clear(C, mmap);
+
if (!mpr) {
/* wm_handlers_do_intern shouldn't let this happen */
BLI_assert(0);
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
}
- wmManipulatorOpElem *mpop = WM_manipulator_operator_get(mpr, mpr->highlight_part);
+ bool use_drag_fallback = false;
- /* Allow for 'button' manipulators, single click to run an action. */
- if (mpop && mpop->type) {
- if (mpop->type->modal == NULL) {
- WM_operator_name_call_ptr(C, mpop->type, WM_OP_INVOKE_DEFAULT, &mpop->ptr);
+#ifdef USE_DRAG_DETECT
+ use_drag_fallback = !ELEM(mpr->drag_part, -1, mpr->highlight_part);
+#endif
+
+ if (use_drag_fallback == false) {
+ if (manipulator_tweak_start_and_finish(C, mmap, mpr, event, NULL)) {
return OPERATOR_FINISHED;
}
}
- /* activate highlighted manipulator */
- wm_manipulatormap_modal_set(mmap, C, mpr, event, true);
-
- /* XXX temporary workaround for modal manipulator operator
- * conflicting with modal operator attached to manipulator */
- if (mpop && mpop->type) {
- if (mpop->type->modal) {
- return OPERATOR_FINISHED;
+ bool use_drag_detect = false;
+#ifdef USE_DRAG_DETECT
+ if (use_drag_fallback) {
+ wmManipulatorOpElem *mpop = WM_manipulator_operator_get(mpr, mpr->highlight_part);
+ if (mpop && mpop->type) {
+ if (mpop->type->modal == NULL) {
+ use_drag_detect = true;
+ }
}
}
+#endif
- /* Couldn't start the manipulator. */
- if ((mpr->state & WM_MANIPULATOR_STATE_MODAL) == 0) {
- return OPERATOR_PASS_THROUGH;
+ if (use_drag_detect == false) {
+ if (!manipulator_tweak_start(C, mmap, mpr, event)) {
+ /* failed to start */
+ return OPERATOR_PASS_THROUGH;
+ }
}
ManipulatorTweakData *mtweak = MEM_mallocN(sizeof(ManipulatorTweakData), __func__);
@@ -422,6 +540,10 @@ static int manipulator_tweak_invoke(bContext *C, wmOperator *op, const wmEvent *
mtweak->mmap = mmap;
mtweak->flag = 0;
+#ifdef USE_DRAG_DETECT
+ mtweak->drag_state = use_drag_detect ? DRAG_DETECT : DRAG_NOP;
+#endif
+
op->customdata = mtweak;
WM_event_add_modal_handler(C, op);
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h b/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h
index 419ac7d5521..fc814adaef1 100644
--- a/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h
@@ -115,6 +115,9 @@ struct wmManipulatorMap {
/* cursor location at point of entering modal (see: WM_MANIPULATOR_GRAB_CURSOR) */
int event_xy[2];
short event_grabcursor;
+
+ struct ARegion *tooltip;
+ struct wmTimer *tooltip_timer;
} mmap_context;
};
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c b/source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c
index ba3b405e612..ab7b4688d49 100644
--- a/source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator_map.c
@@ -51,6 +51,9 @@
#include "WM_types.h"
#include "wm_event_system.h"
+/* for tool-tips */
+#include "UI_interface.h"
+
#include "DEG_depsgraph.h"
/* own includes */
@@ -888,6 +891,8 @@ void wm_manipulatormap_modal_set(
BLI_assert(mmap->mmap_context.modal == NULL);
wmWindow *win = CTX_wm_window(C);
+ WM_manipulatormap_tooltip_clear(C, mmap);
+
/* For now only grab cursor for 3D manipulators. */
int retval = OPERATOR_RUNNING_MODAL;
@@ -953,6 +958,8 @@ void wm_manipulatormap_modal_set(
ED_region_tag_redraw(CTX_wm_region(C));
WM_event_add_mousemove(C);
}
+
+ mmap->mmap_context.event_xy[0] = INT_MAX;
}
}
@@ -995,6 +1002,54 @@ void WM_manipulatormap_message_subscribe(
/* -------------------------------------------------------------------- */
+/** \name Tooltip Handling
+ *
+ * \{ */
+
+
+void WM_manipulatormap_tooltip_create(
+ bContext *C, wmManipulatorMap *mmap)
+{
+ WM_manipulatormap_tooltip_clear(C, mmap);
+ if (mmap->mmap_context.highlight) {
+ mmap->mmap_context.tooltip = UI_tooltip_create_from_manipulator(C, mmap->mmap_context.highlight);
+ }
+}
+
+void WM_manipulatormap_tooltip_clear(
+ bContext *C, wmManipulatorMap *mmap)
+{
+ if (mmap->mmap_context.tooltip_timer != NULL) {
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
+ WM_event_remove_timer(wm, win, mmap->mmap_context.tooltip_timer);
+ mmap->mmap_context.tooltip_timer = NULL;
+ }
+ if (mmap->mmap_context.tooltip != NULL) {
+ UI_tooltip_free(C, mmap->mmap_context.tooltip);
+ mmap->mmap_context.tooltip = NULL;
+ }
+}
+
+void WM_manipulatormap_tooltip_timer_init(
+ bContext *C, wmManipulatorMap *mmap)
+{
+ if (mmap->mmap_context.tooltip_timer == NULL) {
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
+ /* TODO: BUTTON_TOOLTIP_DELAY */
+ mmap->mmap_context.tooltip_timer = WM_event_add_timer(wm, win, TIMER, UI_TOOLTIP_DELAY);
+ }
+}
+
+const void *WM_manipulatormap_tooltip_timer_get(wmManipulatorMap *mmap)
+{
+ return mmap->mmap_context.tooltip_timer;
+}
+
+/** \} */ /* wmManipulatorMapType */
+
+/* -------------------------------------------------------------------- */
/** \name wmManipulatorMapType
*
* \{ */