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:
authorJulian Eisel <eiseljulian@gmail.com>2017-12-06 19:42:39 +0300
committerJulian Eisel <eiseljulian@gmail.com>2017-12-06 19:42:39 +0300
commit9d956c65a64ea6f8b1dec1a1fe11f7c67d7a0709 (patch)
treea17fa5fff8f22ea969fca67166f3842adf78f205 /source/blender/editors
parent8f46733e77752edbd958628efd432b38dc1457f2 (diff)
parent46f518e92790a04885f4e047bb59b11019d73aa3 (diff)
Merge branch 'blender2.8' into topbar
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/armature/armature_select.c14
-rw-r--r--source/blender/editors/armature/editarmature_sketch.c2
-rw-r--r--source/blender/editors/curve/editcurve.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_convert.c2
-rw-r--r--source/blender/editors/include/ED_mesh.h1
-rw-r--r--source/blender/editors/include/ED_object.h2
-rw-r--r--source/blender/editors/include/ED_render.h11
-rw-r--r--source/blender/editors/include/ED_screen.h19
-rw-r--r--source/blender/editors/include/ED_transform_snap_object_context.h4
-rw-r--r--source/blender/editors/include/ED_view3d.h2
-rw-r--r--source/blender/editors/include/UI_interface.h5
-rw-r--r--source/blender/editors/interface/interface.c53
-rw-r--r--source/blender/editors/interface/interface_handlers.c59
-rw-r--r--source/blender/editors/interface/interface_intern.h1
-rw-r--r--source/blender/editors/interface/interface_ops.c212
-rw-r--r--source/blender/editors/interface/interface_templates.c18
-rw-r--r--source/blender/editors/interface/interface_widgets.c14
-rw-r--r--source/blender/editors/mesh/editmesh_bevel.c4
-rw-r--r--source/blender/editors/mesh/editmesh_inset.c28
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c3
-rw-r--r--source/blender/editors/mesh/editmesh_polybuild.c8
-rw-r--r--source/blender/editors/mesh/editmesh_select.c16
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c2
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c19
-rw-r--r--source/blender/editors/object/object_add.c13
-rw-r--r--source/blender/editors/object/object_edit.c8
-rw-r--r--source/blender/editors/object/object_intern.h1
-rw-r--r--source/blender/editors/object/object_ops.c1
-rw-r--r--source/blender/editors/object/object_relations.c86
-rw-r--r--source/blender/editors/object/object_select.c3
-rw-r--r--source/blender/editors/render/render_internal.c2
-rw-r--r--source/blender/editors/render/render_update.c127
-rw-r--r--source/blender/editors/scene/scene_edit.c17
-rw-r--r--source/blender/editors/screen/area.c81
-rw-r--r--source/blender/editors/screen/screen_context.c2
-rw-r--r--source/blender/editors/screen/screen_edit.c4
-rw-r--r--source/blender/editors/screen/workspace_edit.c37
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c22
-rw-r--r--source/blender/editors/space_buttons/buttons_intern.h1
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c1
-rw-r--r--source/blender/editors/space_file/file_ops.c16
-rw-r--r--source/blender/editors/space_file/space_file.c29
-rw-r--r--source/blender/editors/space_info/info_stats.c49
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c48
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c40
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c8
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h5
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c17
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c41
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c85
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c86
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c3
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c31
-rw-r--r--source/blender/editors/space_time/space_time.c45
-rw-r--r--source/blender/editors/space_view3d/drawobject.c14
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c71
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c12
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_camera.c51
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_ruler.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c7
-rw-r--r--source/blender/editors/space_view3d/view3d_ruler.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c6
-rw-r--r--source/blender/editors/transform/transform.h2
-rw-r--r--source/blender/editors/transform/transform_conversions.c169
-rw-r--r--source/blender/editors/transform/transform_generics.c4
-rw-r--r--source/blender/editors/transform/transform_manipulator.c64
-rw-r--r--source/blender/editors/transform/transform_snap.c9
-rw-r--r--source/blender/editors/transform/transform_snap_object.c19
-rw-r--r--source/blender/editors/util/numinput.c14
-rw-r--r--source/blender/editors/util/undo.c4
72 files changed, 1429 insertions, 435 deletions
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index e32324d25f9..b87942fed84 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -807,6 +807,7 @@ enum {
SIMEDBONE_PREFIX,
SIMEDBONE_SUFFIX,
SIMEDBONE_LAYER,
+ SIMEDBONE_GROUP,
SIMEDBONE_SHAPE,
};
@@ -819,6 +820,7 @@ static const EnumPropertyItem prop_similar_types[] = {
{SIMEDBONE_PREFIX, "PREFIX", 0, "Prefix", ""},
{SIMEDBONE_SUFFIX, "SUFFIX", 0, "Suffix", ""},
{SIMEDBONE_LAYER, "LAYER", 0, "Layer", ""},
+ {SIMEDBONE_GROUP, "GROUP", 0, "Group", ""},
{SIMEDBONE_SHAPE, "SHAPE", 0, "Shape", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -1009,6 +1011,9 @@ static int armature_select_similar_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+#define STRUCT_SIZE_AND_OFFSET(_struct, _member) \
+ sizeof(((_struct *)NULL)->_member), offsetof(_struct, _member)
+
switch (type) {
case SIMEDBONE_CHILDREN:
select_similar_children(arm, ebone_act);
@@ -1034,13 +1039,20 @@ static int armature_select_similar_exec(bContext *C, wmOperator *op)
case SIMEDBONE_LAYER:
select_similar_layer(arm, ebone_act);
break;
+ case SIMEDBONE_GROUP:
+ select_similar_data_pchan(
+ arm, obedit, ebone_act,
+ STRUCT_SIZE_AND_OFFSET(bPoseChannel, agrp_index));
+ break;
case SIMEDBONE_SHAPE:
select_similar_data_pchan(
arm, obedit, ebone_act,
- sizeof(void *), offsetof(bPoseChannel, custom));
+ STRUCT_SIZE_AND_OFFSET(bPoseChannel, custom));
break;
}
+#undef STRUCT_SIZE_AND_OFFSET
+
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c
index a240d6b190f..4dd8e4bd6fa 100644
--- a/source/blender/editors/armature/editarmature_sketch.c
+++ b/source/blender/editors/armature/editarmature_sketch.c
@@ -998,7 +998,7 @@ static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, S
* the ideal would be to call this function only at the beginning of the snap operation,
* or at the beginning of the operator itself */
struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C), CTX_data_scene(C), CTX_data_view_layer(C), CTX_data_engine(C), 0,
+ CTX_data_main(C), CTX_data_scene(C), CTX_data_view_layer(C), CTX_data_engine_type(C), 0,
CTX_wm_region(C), CTX_wm_view3d(C));
float mvalf[2] = {UNPACK2(dd->mval)};
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index e8c784f15d5..79b63f36b76 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -5020,7 +5020,7 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const float mval[2] = {UNPACK2(event->mval)};
struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C), vc.scene, vc.view_layer, vc.engine, 0,
+ CTX_data_main(C), vc.scene, vc.view_layer, vc.engine_type, 0,
vc.ar, vc.v3d);
ED_transform_snap_object_project_view3d_mixed(
diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c
index 92daa802601..f3b12b9bc85 100644
--- a/source/blender/editors/gpencil/gpencil_convert.c
+++ b/source/blender/editors/gpencil/gpencil_convert.c
@@ -1156,7 +1156,7 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG
*/
ob = BKE_object_add_only_object(bmain, OB_CURVE, gpl->info);
cu = ob->data = BKE_curve_add(bmain, gpl->info, OB_CURVE);
- BKE_collection_object_add(scene, sc, ob);
+ BKE_collection_object_add(&scene->id, sc, ob);
base_new = BKE_view_layer_base_find(view_layer, ob);
cu->flag |= CU_3D;
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 1c8cf0665b3..1fd7756df77 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -76,7 +76,6 @@ struct BMFace *EDBM_verts_mirror_get_face(struct BMEditMesh *em, struct BMFace *
void EDBM_verts_mirror_cache_clear(struct BMEditMesh *em, struct BMVert *v);
void EDBM_verts_mirror_cache_end(struct BMEditMesh *em);
-void EDBM_mesh_ensure_valid_dm_hack(struct Scene *scene, struct BMEditMesh *em);
void EDBM_mesh_normals_update(struct BMEditMesh *em);
void EDBM_mesh_clear(struct BMEditMesh *em);
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 066c4e5a692..8d2ff327c51 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -82,7 +82,7 @@ typedef enum eParentType {
PAR_VERTEX_TRI,
} eParentType;
-typedef enum eObjectSelect_Mode{
+typedef enum eObjectSelect_Mode {
BA_DESELECT = 0,
BA_SELECT = 1,
BA_INVERT = 2,
diff --git a/source/blender/editors/include/ED_render.h b/source/blender/editors/include/ED_render.h
index 707d7c6c693..b7317d75cd4 100644
--- a/source/blender/editors/include/ED_render.h
+++ b/source/blender/editors/include/ED_render.h
@@ -31,6 +31,7 @@
#include "DNA_vec_types.h"
struct bContext;
+struct DEGEditorUpdateContext;
struct ID;
struct Main;
struct MTex;
@@ -43,13 +44,15 @@ struct wmWindowManager;
void ED_operatortypes_render(void);
-/* render_shading.c */
+/* render_update.c */
-void ED_render_id_flush_update(struct Main *bmain, struct ID *id);
void ED_render_engine_changed(struct Main *bmain);
void ED_render_engine_area_exit(struct Main *bmain, struct ScrArea *sa);
-void ED_render_scene_update(struct Main *bmain, struct Scene *scene, int updated);
-void ED_render_scene_update_pre(struct Main *bmain, struct Scene *scene, bool time);
+
+/* Callbacks handling data update events coming from depsgraph. */
+
+void ED_render_id_flush_update(const struct DEGEditorUpdateContext *update_ctx, struct ID *id);
+void ED_render_scene_update(const struct DEGEditorUpdateContext *update_ctx, int updated);
void ED_viewport_render_kill_jobs(struct wmWindowManager *wm, struct Main *bmain, bool free_database);
struct Scene *ED_render_job_get_scene(const struct bContext *C);
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index 6cb20c818fd..d931109b941 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -55,6 +55,9 @@ struct ARegion;
struct uiBlock;
struct rcti;
struct Main;
+struct wmMsgBus;
+struct wmMsgSubscribeKey;
+struct wmMsgSubscribeValue;
/* regions */
void ED_region_do_listen(
@@ -86,6 +89,18 @@ void ED_region_grid_draw(struct ARegion *ar, float zoomx, float zoomy);
float ED_region_blend_factor(struct ARegion *ar);
void ED_region_visible_rect(struct ARegion *ar, struct rcti *rect);
+/* message_bus callbacks */
+void ED_region_do_msg_notify_tag_redraw(
+ struct bContext *C, struct wmMsgSubscribeKey *msg_key, struct wmMsgSubscribeValue *msg_val);
+void ED_area_do_msg_notify_tag_refresh(
+ struct bContext *C, struct wmMsgSubscribeKey *msg_key, struct wmMsgSubscribeValue *msg_val);
+
+/* message bus */
+void ED_region_message_subscribe(
+ struct bContext *C,
+ struct WorkSpace *workspace, struct Scene *scene,
+ struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar,
+ struct wmMsgBus *mbus);
/* spaces */
void ED_spacetypes_keymap(struct wmKeyConfig *keyconf);
@@ -153,6 +168,7 @@ void ED_screen_preview_render(const struct bScreen *screen, int size_x, int s
struct WorkSpace *ED_workspace_add(
struct Main *bmain,
const char *name,
+ Scene *scene,
ViewLayer *act_render_layer,
struct ViewRender *view_render) ATTR_NONNULL();
bool ED_workspace_change(
@@ -169,7 +185,8 @@ bool ED_workspace_delete(
void ED_workspace_scene_data_sync(
struct WorkSpaceInstanceHook *hook, Scene *scene) ATTR_NONNULL();
void ED_workspace_view_layer_unset(
- const struct Main *bmain, const ViewLayer *layer_unset, ViewLayer *layer_new) ATTR_NONNULL(1, 2);
+ const struct Main *bmain, struct Scene *scene,
+ const ViewLayer *layer_unset, ViewLayer *layer_new) ATTR_NONNULL(1, 2);
struct WorkSpaceLayout *ED_workspace_layout_add(
struct WorkSpace *workspace,
struct wmWindow *win,
diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h
index 49e85600819..8761f2c5361 100644
--- a/source/blender/editors/include/ED_transform_snap_object_context.h
+++ b/source/blender/editors/include/ED_transform_snap_object_context.h
@@ -76,9 +76,9 @@ struct SnapObjectParams {
typedef struct SnapObjectContext SnapObjectContext;
SnapObjectContext *ED_transform_snap_object_context_create(
- struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, struct RenderEngineType *engine, int flag);
+ struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, struct RenderEngineType *engine_type, int flag);
SnapObjectContext *ED_transform_snap_object_context_create_view3d(
- struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, struct RenderEngineType *engine, int flag,
+ struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, struct RenderEngineType *engine_type, int flag,
/* extra args for view3d */
const struct ARegion *ar, const struct View3D *v3d);
void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index feb3686db9f..69061bdcd26 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -78,7 +78,7 @@ typedef struct ViewContext {
struct Depsgraph *depsgraph;
struct Scene *scene;
struct ViewLayer *view_layer;
- struct RenderEngineType *engine;
+ struct RenderEngineType *engine_type;
struct Object *obact;
struct Object *obedit;
struct ARegion *ar;
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 51a98c47718..9a816f21fb8 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 wmMsgBus;
typedef struct uiBut uiBut;
typedef struct uiBlock uiBlock;
@@ -183,6 +184,8 @@ enum {
UI_BUT_UPDATE_DELAY = (1 << 28), /* don't run updates while dragging (needed in rare cases). */
UI_BUT_TEXTEDIT_UPDATE = (1 << 29), /* when widget is in textedit mode, update value on each char stroke */
UI_BUT_VALUE_CLEAR = (1 << 30), /* show 'x' icon to clear/unlink value of text or search button */
+
+ UI_BUT_OVERRIDEN = (1 << 31), /* RNA property of the button is overriden from linked reference data. */
};
#define UI_PANEL_WIDTH 340
@@ -901,6 +904,8 @@ uiLayout *UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int s
void UI_block_layout_set_current(uiBlock *block, uiLayout *layout);
void UI_block_layout_resolve(uiBlock *block, int *x, int *y);
+void UI_region_message_subscribe(struct ARegion *ar, struct wmMsgBus *mbus);
+
uiBlock *uiLayoutGetBlock(uiLayout *layout);
void uiLayoutSetFunc(uiLayout *layout, uiMenuHandleFunc handlefunc, void *argv);
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 09007681455..a5ef2943387 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -41,6 +41,7 @@
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
+#include "DNA_workspace_types.h"
#include "BLI_math.h"
#include "BLI_listbase.h"
@@ -69,11 +70,14 @@
#include "WM_api.h"
#include "WM_types.h"
#include "wm_subwindow.h"
+#include "WM_message.h"
#include "RNA_access.h"
#include "BPY_extern.h"
+#include "ED_screen.h"
+
#include "IMB_colormanagement.h"
#include "interface_intern.h"
@@ -1216,6 +1220,20 @@ static void ui_menu_block_set_keymaps(const bContext *C, uiBlock *block)
}
}
+void ui_but_override_flag(uiBut *but)
+{
+ bool is_overridden;
+
+ RNA_property_override_status(&but->rnapoin, but->rnaprop, but->rnaindex, NULL, &is_overridden, NULL, NULL);
+
+ if (is_overridden) {
+ but->flag |= UI_BUT_OVERRIDEN;
+ }
+ else {
+ but->flag &= ~UI_BUT_OVERRIDEN;
+ }
+}
+
void UI_block_update_from_old(const bContext *C, uiBlock *block)
{
uiBut *but_old;
@@ -1280,6 +1298,7 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x
}
ui_but_anim_flag(but, (scene) ? scene->r.cfra : 0.0f);
+ ui_but_override_flag(but);
}
@@ -1438,6 +1457,40 @@ void UI_block_draw(const bContext *C, uiBlock *block)
ui_draw_links(block);
}
+static void ui_block_message_subscribe(ARegion *ar, struct wmMsgBus *mbus, uiBlock *block)
+{
+ uiBut *but_prev = NULL;
+ /* possibly we should keep the region this block is contained in? */
+ for (uiBut *but = block->buttons.first; but; but = but->next) {
+ if (but->rnapoin.type && but->rnaprop) {
+ /* quick check to avoid adding buttons representing a vector, multiple times. */
+ if ((but_prev &&
+ (but_prev->rnaprop == but->rnaprop) &&
+ (but_prev->rnapoin.type == but->rnapoin.type) &&
+ (but_prev->rnapoin.data == but->rnapoin.data) &&
+ (but_prev->rnapoin.id.data == but->rnapoin.id.data)) == false)
+ {
+ /* TODO: could make this into utility function. */
+ WM_msg_subscribe_rna(
+ mbus, &but->rnapoin, but->rnaprop,
+ &(const wmMsgSubscribeValue){
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ }, __func__);
+ but_prev = but;
+ }
+ }
+ }
+}
+
+void UI_region_message_subscribe(ARegion *ar, struct wmMsgBus *mbus)
+{
+ for (uiBlock *block = ar->uiblocks.first; block; block = block->next) {
+ ui_block_message_subscribe(ar, mbus, block);
+ }
+}
+
/* ************* EVENTS ************* */
/**
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 908fa19e3b1..53505fc39a4 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -6800,6 +6800,8 @@ static bool ui_but_menu(bContext *C, uiBut *but)
MenuType *mt = WM_menutype_find("WM_MT_button_context", true);
bool is_array, is_array_component;
uiStringInfo label = {BUT_GET_LABEL, NULL};
+ wmOperatorType *ot;
+ PointerRNA op_ptr;
/* if ((but->rnapoin.data && but->rnaprop) == 0 && but->optype == NULL)*/
/* return 0;*/
@@ -6826,11 +6828,11 @@ static bool ui_but_menu(bContext *C, uiBut *but)
const PropertySubType subtype = RNA_property_subtype(prop);
bool is_anim = RNA_property_animateable(ptr, prop);
bool is_editable = RNA_property_editable(ptr, prop);
+ bool is_overridable;
/*bool is_idprop = RNA_property_is_idprop(prop);*/ /* XXX does not work as expected, not strictly needed */
bool is_set = RNA_property_is_set(ptr, prop);
- /* Set the (button_pointer, button_prop) and pointer data for Python access to the hovered ui element. */
- uiLayoutSetContextFromBut(layout, but);
+ RNA_property_override_status(ptr, prop, -1, &is_overridable, NULL, NULL, NULL);
/* second slower test, saved people finding keyframe items in menus when its not possible */
if (is_anim)
@@ -6959,11 +6961,57 @@ static bool ui_but_menu(bContext *C, uiBut *but)
ICON_NONE, "ANIM_OT_keyingset_button_remove");
}
}
-
+
+ if (is_overridable) {
+ /* Override Operators */
+ uiItemS(layout);
+
+ if (but->flag & UI_BUT_OVERRIDEN) {
+ if (is_array_component) {
+ ot = WM_operatortype_find("UI_OT_override_type_set_button", false);
+ uiItemFullO_ptr(layout, ot, "Overrides Type", ICON_NONE,
+ NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_boolean_set(&op_ptr, "all", true);
+ uiItemFullO_ptr(layout, ot, "Single Override Type", ICON_NONE,
+ NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_boolean_set(&op_ptr, "all", false);
+
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Overrides"),
+ ICON_X, "UI_OT_override_remove_button", "all", true);
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Single Override"),
+ ICON_X, "UI_OT_override_remove_button", "all", false);
+ }
+ else {
+ uiItemFullO(layout, "UI_OT_override_type_set_button", "Override Type", ICON_NONE,
+ NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_boolean_set(&op_ptr, "all", false);
+
+ uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Override"),
+ ICON_X, "UI_OT_override_remove_button", "all", true);
+ }
+ }
+ else {
+ if (is_array_component) {
+ ot = WM_operatortype_find("UI_OT_override_type_set_button", false);
+ uiItemFullO_ptr(layout, ot, "Define Overrides", ICON_NONE,
+ NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_boolean_set(&op_ptr, "all", true);
+ uiItemFullO_ptr(layout, ot, "Define Single Override", ICON_NONE,
+ NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_boolean_set(&op_ptr, "all", false);
+ }
+ else {
+ uiItemFullO(layout, "UI_OT_override_type_set_button", "Define Override", ICON_NONE,
+ NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr);
+ RNA_boolean_set(&op_ptr, "all", false);
+ }
+ }
+ }
+
uiItemS(layout);
-
+
/* Property Operators */
-
+
/* Copy Property Value
* Paste Property Value */
@@ -8241,6 +8289,7 @@ void UI_context_update_anim_flag(const bContext *C)
for (block = ar->uiblocks.first; block; block = block->next) {
for (but = block->buttons.first; but; but = but->next) {
ui_but_anim_flag(but, (scene) ? scene->r.cfra : 0.0f);
+ ui_but_override_flag(but);
ED_region_tag_redraw(ar);
if (but->active) {
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 424063953a7..6f450093d30 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -514,6 +514,7 @@ extern bool ui_but_supports_cycling(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
extern int ui_but_is_pushed_ex(uiBut *but, double *value) ATTR_WARN_UNUSED_RESULT;
extern int ui_but_is_pushed(uiBut *but) ATTR_WARN_UNUSED_RESULT;
+void ui_but_override_flag(uiBut *but);
extern void ui_block_bounds_calc(uiBlock *block);
extern void ui_block_translate(uiBlock *block, int x, int y);
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 5913f1c48f5..bbcd10270d5 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -46,6 +46,7 @@
#include "BKE_layer.h"
#include "BKE_screen.h"
#include "BKE_global.h"
+#include "BKE_library_override.h"
#include "BKE_node.h"
#include "BKE_text.h" /* for UI_OT_reports_to_text */
#include "BKE_report.h"
@@ -452,6 +453,215 @@ static void UI_OT_unuse_property_button(wmOperatorType *ot)
ot->flag = OPTYPE_UNDO;
}
+
+
+
+
+/* Note that we use different values for UI/UX than 'real' override operations, user does not care
+ * whether it's added or removed for the differential operation e.g. */
+enum {
+ UIOverride_Type_NOOP = 0,
+ UIOverride_Type_Replace = 1,
+ UIOverride_Type_Difference = 2, /* Add/subtract */
+ UIOverride_Type_Factor = 3, /* Multiply */
+ /* TODO: should/can we expose insert/remove ones for collections? Doubt it... */
+};
+
+static EnumPropertyItem override_type_items[] = {
+ {UIOverride_Type_NOOP, "NOOP", 0, "NoOp",
+ "'No-Operation', place holder preventing automatic override to ever affect the property"},
+ {UIOverride_Type_Replace, "REPLACE", 0, "Replace", "Completely replace value from linked data by local one"},
+ {UIOverride_Type_Difference, "DIFFERENCE", 0, "Difference", "Store difference to linked data value"},
+ {UIOverride_Type_Factor, "FACTOR", 0, "Factor", "Store factor to linked data value (useful e.g. for scale)"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+
+static int override_type_set_button_poll(bContext *C)
+{
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+ bool is_overridable;
+
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+ RNA_property_override_status(&ptr, prop, index, &is_overridable, NULL, NULL, NULL);
+
+ return (ptr.data && prop && is_overridable);
+}
+
+static int override_type_set_button_exec(bContext *C, wmOperator *op)
+{
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+ bool created;
+ const bool all = RNA_boolean_get(op->ptr, "all");
+ const int op_type = RNA_enum_get(op->ptr, "type");
+
+ short operation;
+
+ switch (op_type) {
+ case UIOverride_Type_NOOP:
+ operation = IDOVERRIDESTATIC_OP_NOOP;
+ break;
+ case UIOverride_Type_Replace:
+ operation = IDOVERRIDESTATIC_OP_REPLACE;
+ break;
+ case UIOverride_Type_Difference:
+ operation = IDOVERRIDESTATIC_OP_ADD; /* override code will automatically switch to subtract if needed. */
+ break;
+ case UIOverride_Type_Factor:
+ operation = IDOVERRIDESTATIC_OP_MULTIPLY;
+ break;
+ default:
+ operation = IDOVERRIDESTATIC_OP_REPLACE;
+ BLI_assert(0);
+ break;
+ }
+
+ /* try to reset the nominated setting to its default value */
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+ BLI_assert(ptr.id.data != NULL);
+
+ if (all) {
+ index = -1;
+ }
+
+ IDOverrideStaticPropertyOperation *opop = RNA_property_override_property_operation_get(
+ &ptr, prop, operation, index, true, NULL, &created);
+ if (!created) {
+ opop->operation = operation;
+ }
+
+ return operator_button_property_finish(C, &ptr, prop);
+}
+
+static int override_type_set_button_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ return WM_menu_invoke_ex(C, op, WM_OP_INVOKE_DEFAULT);
+}
+
+static void UI_OT_override_type_set_button(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Define Override Type";
+ ot->idname = "UI_OT_override_type_set_button";
+ ot->description = "Create an override operation, or set the type of an existing one";
+
+ /* callbacks */
+ ot->poll = override_type_set_button_poll;
+ ot->exec = override_type_set_button_exec;
+ ot->invoke = override_type_set_button_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array");
+ ot->prop = RNA_def_enum(ot->srna, "type", override_type_items, UIOverride_Type_Replace,
+ "Type", "Type of override operation");
+ /* TODO: add itemf callback, not all aoptions are available for all data types... */
+}
+
+
+static int override_remove_button_poll(bContext *C)
+{
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+ bool is_overridden;
+
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+ RNA_property_override_status(&ptr, prop, index, NULL, &is_overridden, NULL, NULL);
+
+ return (ptr.data && ptr.id.data && prop && is_overridden);
+}
+
+static int override_remove_button_exec(bContext *C, wmOperator *op)
+{
+ PointerRNA ptr, id_refptr, src;
+ PropertyRNA *prop;
+ int index;
+ const bool all = RNA_boolean_get(op->ptr, "all");
+
+ /* try to reset the nominated setting to its default value */
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+ ID *id = ptr.id.data;
+ IDOverrideStaticProperty *oprop = RNA_property_override_property_find(&ptr, prop);
+ BLI_assert(oprop != NULL);
+ BLI_assert(id != NULL && id->override_static != NULL);
+
+ const bool is_template = (id->override_static->reference == NULL);
+
+ /* We need source (i.e. linked data) to restore values of deleted overrides...
+ * If this is an override template, we obviously do not need to restore anything. */
+ if (!is_template) {
+ RNA_id_pointer_create(id->override_static->reference, &id_refptr);
+ if (!RNA_path_resolve(&id_refptr, oprop->rna_path, &src, NULL)) {
+ BLI_assert(0 && "Failed to create matching source (linked data) RNA pointer");
+ }
+ }
+
+ if (!all && index != -1) {
+ bool is_strict_find;
+ /* Remove override operation for given item, add singular operations for the other items as needed. */
+ IDOverrideStaticPropertyOperation *opop = BKE_override_static_property_operation_find(
+ oprop, NULL, NULL, index, index, false, &is_strict_find);
+ BLI_assert(opop != NULL);
+ if (!is_strict_find) {
+ /* No specific override operation, we have to get generic one,
+ * and create item-specific override operations for all but given index, before removing generic one. */
+ for (int idx = RNA_property_array_length(&ptr, prop); idx--; ) {
+ if (idx != index) {
+ BKE_override_static_property_operation_get(oprop, opop->operation, NULL, NULL, idx, idx, true, NULL, NULL);
+ }
+ }
+ }
+ BKE_override_static_property_operation_delete(oprop, opop);
+ if (!is_template) {
+ RNA_property_copy(&ptr, &src, prop, index);
+ }
+ if (BLI_listbase_is_empty(&oprop->operations)) {
+ BKE_override_static_property_delete(id->override_static, oprop);
+ }
+ }
+ else {
+ /* Just remove whole generic override operation of this property. */
+ BKE_override_static_property_delete(id->override_static, oprop);
+ if (!is_template) {
+ RNA_property_copy(&ptr, &src, prop, -1);
+ }
+ }
+
+ return operator_button_property_finish(C, &ptr, prop);
+}
+
+static void UI_OT_override_remove_button(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Override";
+ ot->idname = "UI_OT_override_remove_button";
+ ot->description = "Remove an override operation";
+
+ /* callbacks */
+ ot->poll = override_remove_button_poll;
+ ot->exec = override_remove_button_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array");
+}
+
+
+
+
/* Copy To Selected Operator ------------------------ */
bool UI_context_copy_to_selected_list(
@@ -1243,6 +1453,8 @@ void ED_operatortypes_ui(void)
WM_operatortype_append(UI_OT_unset_property_button);
WM_operatortype_append(UI_OT_use_property_button);
WM_operatortype_append(UI_OT_unuse_property_button);
+ WM_operatortype_append(UI_OT_override_type_set_button);
+ WM_operatortype_append(UI_OT_override_remove_button);
WM_operatortype_append(UI_OT_copy_to_selected_button);
WM_operatortype_append(UI_OT_reports_to_textblock); /* XXX: temp? */
WM_operatortype_append(UI_OT_drop_color);
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index c7e1a60b05c..78874076b92 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -1075,8 +1075,10 @@ void uiTemplateSearch(
const char *newop, const char *unlinkop)
{
TemplateSearch *template_search = template_search_setup(ptr, propname, searchptr, searchpropname);
- template_search_buttons(C, layout, template_search, newop, unlinkop);
- MEM_freeN(template_search);
+ if (template_search != NULL) {
+ template_search_buttons(C, layout, template_search, newop, unlinkop);
+ MEM_freeN(template_search);
+ }
}
void uiTemplateSearchPreview(
@@ -1088,13 +1090,15 @@ void uiTemplateSearchPreview(
{
TemplateSearch *template_search = template_search_setup(ptr, propname, searchptr, searchpropname);
- template_search->use_previews = true;
- template_search->preview_rows = rows;
- template_search->preview_cols = cols;
+ if (template_search != NULL) {
+ template_search->use_previews = true;
+ template_search->preview_rows = rows;
+ template_search->preview_cols = cols;
- template_search_buttons(C, layout, template_search, newop, unlinkop);
+ template_search_buttons(C, layout, template_search, newop, unlinkop);
- MEM_freeN(template_search);
+ MEM_freeN(template_search);
+ }
}
/********************* RNA Path Builder Template ********************/
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 375f4f95697..8c894c7852e 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -1710,6 +1710,8 @@ static struct uiWidgetStateColors wcol_state_colors = {
{215, 211, 75, 255},
{180, 0, 255, 255},
{153, 0, 230, 255},
+ {74, 137, 137, 255},
+ {49, 112, 112, 255},
0.5f, 0.0f
};
@@ -2062,6 +2064,8 @@ static void widget_state(uiWidgetType *wt, int state)
widget_state_blend(wt->wcol.inner, wcol_state->inner_anim_sel, wcol_state->blend);
else if (state & UI_BUT_DRIVEN)
widget_state_blend(wt->wcol.inner, wcol_state->inner_driven_sel, wcol_state->blend);
+ else if (state & UI_BUT_OVERRIDEN)
+ widget_state_blend(wt->wcol.inner, wcol_state->inner_overridden_sel, wcol_state->blend);
copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
@@ -2075,6 +2079,8 @@ static void widget_state(uiWidgetType *wt, int state)
widget_state_blend(wt->wcol.inner, wcol_state->inner_anim, wcol_state->blend);
else if (state & UI_BUT_DRIVEN)
widget_state_blend(wt->wcol.inner, wcol_state->inner_driven, wcol_state->blend);
+ else if (state & UI_BUT_OVERRIDEN)
+ widget_state_blend(wt->wcol.inner, wcol_state->inner_overridden, wcol_state->blend);
if (state & UI_ACTIVE) { /* mouse over? */
wt->wcol.inner[0] = wt->wcol.inner[0] >= 240 ? 255 : wt->wcol.inner[0] + 15;
@@ -2120,7 +2126,9 @@ static void widget_state_numslider(uiWidgetType *wt, int state)
widget_state_blend(wt->wcol.item, wcol_state->inner_anim_sel, blend);
else if (state & UI_BUT_DRIVEN)
widget_state_blend(wt->wcol.item, wcol_state->inner_driven_sel, blend);
-
+ else if (state & UI_BUT_OVERRIDEN)
+ widget_state_blend(wt->wcol.item, wcol_state->inner_overridden_sel, blend);
+
if (state & UI_SELECT)
SWAP(short, wt->wcol.shadetop, wt->wcol.shadedown);
}
@@ -2131,6 +2139,8 @@ static void widget_state_numslider(uiWidgetType *wt, int state)
widget_state_blend(wt->wcol.item, wcol_state->inner_anim, blend);
else if (state & UI_BUT_DRIVEN)
widget_state_blend(wt->wcol.item, wcol_state->inner_driven, blend);
+ else if (state & UI_BUT_OVERRIDEN)
+ widget_state_blend(wt->wcol.item, wcol_state->inner_overridden, blend);
}
}
@@ -3157,7 +3167,7 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
ui_but_v3_get(but, col);
- if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_REDALERT)) {
+ if (state & (UI_BUT_ANIMATED | UI_BUT_ANIMATED_KEY | UI_BUT_DRIVEN | UI_BUT_OVERRIDEN | UI_BUT_REDALERT)) {
/* draw based on state - color for keyed etc */
widgetbase_draw(&wtb, wcol);
diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c
index e541df8ffa3..d4d7d92d5ad 100644
--- a/source/blender/editors/mesh/editmesh_bevel.c
+++ b/source/blender/editors/mesh/editmesh_bevel.c
@@ -58,8 +58,7 @@
#define MVAL_PIXEL_MARGIN 5.0f
-/* until implement profile = 0 case, need to clamp somewhat above zero */
-#define PROFILE_HARD_MIN 0.15f
+#define PROFILE_HARD_MIN 0.0f
#define SEGMENTS_HARD_MAX 1000
@@ -623,6 +622,7 @@ void MESH_OT_bevel(wmOperatorType *ot)
RNA_def_enum(ot->srna, "offset_type", offset_type_items, 0, "Amount Type", "What distance Amount measures");
prop = RNA_def_float(ot->srna, "offset", 0.0f, -1e6f, 1e6f, "Amount", "", 0.0f, 1.0f);
RNA_def_property_float_array_funcs_runtime(prop, NULL, NULL, mesh_ot_bevel_offset_range_func);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
RNA_def_int(ot->srna, "segments", 1, 1, SEGMENTS_HARD_MAX, "Segments", "Segments for curved edge", 1, 8);
RNA_def_float(ot->srna, "profile", 0.5f, PROFILE_HARD_MIN, 1.0f, "Profile",
"Controls profile shape (0.5 = round)", PROFILE_HARD_MIN, 1.0f);
diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c
index 3e0747f055f..afe52ec69f4 100644
--- a/source/blender/editors/mesh/editmesh_inset.c
+++ b/source/blender/editors/mesh/editmesh_inset.c
@@ -80,8 +80,10 @@ static void edbm_inset_update_header(wmOperator *op, bContext *C)
{
InsetData *opdata = op->customdata;
- const char *str = IFACE_("Confirm: Enter/LClick, Cancel: (Esc/RClick), Thickness: %s, "
- "Depth (Ctrl to tweak): %s (%s), Outset (O): (%s), Boundary (B): (%s), Individual (I): (%s)");
+ const char *str = IFACE_(
+ "Confirm: Enter/LClick, Cancel: (Esc/RClick), Thickness: %s, "
+ "Depth (Ctrl to tweak): %s (%s), Outset (O): (%s), Boundary (B): (%s), Individual (I): (%s)"
+ );
char msg[UI_MAX_DRAW_STR];
ScrArea *sa = CTX_wm_area(C);
@@ -141,7 +143,8 @@ static bool edbm_inset_init(bContext *C, wmOperator *op, const bool is_modal)
ARegion *ar = CTX_wm_region(C);
opdata->mesh_backup = EDBM_redo_state_store(em);
- opdata->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL);
+ opdata->draw_handle_pixel = ED_region_draw_cb_activate(
+ ar->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL);
G.moving = G_TRANSFORM_EDIT;
if (v3d) {
opdata->twtype = v3d->twtype;
@@ -506,16 +509,27 @@ void MESH_OT_inset(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR | OPTYPE_BLOCKING;
/* properties */
- RNA_def_boolean(ot->srna, "use_boundary", true, "Boundary", "Inset face boundaries");
- RNA_def_boolean(ot->srna, "use_even_offset", true, "Offset Even", "Scale the offset to give more even thickness");
- RNA_def_boolean(ot->srna, "use_relative_offset", false, "Offset Relative", "Scale the offset by surrounding geometry");
- RNA_def_boolean(ot->srna, "use_edge_rail", false, "Edge Rail", "Inset the region along existing edges");
+ RNA_def_boolean(
+ ot->srna, "use_boundary",
+ true, "Boundary", "Inset face boundaries");
+ RNA_def_boolean(
+ ot->srna, "use_even_offset",
+ true, "Offset Even", "Scale the offset to give more even thickness");
+ RNA_def_boolean(
+ ot->srna, "use_relative_offset",
+ false, "Offset Relative", "Scale the offset by surrounding geometry");
+ RNA_def_boolean(
+ ot->srna, "use_edge_rail",
+ false, "Edge Rail", "Inset the region along existing edges");
prop = RNA_def_float_distance(ot->srna, "thickness", 0.01f, 0.0f, 1e12f, "Thickness", "", 0.0f, 10.0f);
/* use 1 rather then 10 for max else dragging the button moves too far */
RNA_def_property_ui_range(prop, 0.0, 1.0, 0.01, 4);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
prop = RNA_def_float_distance(ot->srna, "depth", 0.0f, -1e12f, 1e12f, "Depth", "", -10.0f, 10.0f);
RNA_def_property_ui_range(prop, -10.0f, 10.0f, 0.01, 4);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
RNA_def_boolean(ot->srna, "use_outset", false, "Outset", "Outset rather than inset");
RNA_def_boolean(ot->srna, "use_select_inset", false, "Select Outer", "Select the new inset faces");
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index 876d63ef64a..3ab56f2ebcb 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -534,9 +534,6 @@ static int ringsel_init(bContext *C, wmOperator *op, bool do_cut)
lcd->num.unit_type[0] = B_UNIT_NONE;
lcd->num.unit_type[1] = B_UNIT_NONE;
- /* XXX, temp, workaround for [# ] */
- EDBM_mesh_ensure_valid_dm_hack(scene, lcd->em);
-
em_setup_viewcontext(C, &lcd->vc);
ED_region_tag_redraw(lcd->ar);
diff --git a/source/blender/editors/mesh/editmesh_polybuild.c b/source/blender/editors/mesh/editmesh_polybuild.c
index bfabd64396f..f398f087da9 100644
--- a/source/blender/editors/mesh/editmesh_polybuild.c
+++ b/source/blender/editors/mesh/editmesh_polybuild.c
@@ -132,7 +132,7 @@ static int edbm_polybuild_face_at_cursor_invoke(
BMEdge *e_iter = v_act->e;
do {
if ((BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == false) &&
- (allow_wire ? BM_edge_is_wire(e_iter) : BM_edge_is_boundary(e_iter)))
+ (allow_wire ? BM_edge_is_wire(e_iter) : BM_edge_is_boundary(e_iter)))
{
if (i == 2) {
e_pair[0] = e_pair[1] = NULL;
@@ -489,9 +489,9 @@ static int edbm_polybuild_hover_invoke(
/* pass */
}
else if (vc.win->tweak ||
- (vc.win->eventstate->check_click &&
- vc.win->eventstate->prevval == KM_PRESS &&
- ISMOUSE(vc.win->eventstate->prevtype)))
+ (vc.win->eventstate->check_click &&
+ vc.win->eventstate->prevval == KM_PRESS &&
+ ISMOUSE(vc.win->eventstate->prevtype)))
{
return OPERATOR_PASS_THROUGH;
}
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 0a0a8ff2de3..3e0afd3095e 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -640,9 +640,17 @@ BMEdge *EDBM_edge_find_nearest_ex(
unsigned int index;
BMEdge *eed;
+ /* Make sure that the edges also are considered to find nearest.
+ * TODO: cleanup: add `selectmode` as a parameter */
+ const short ts_selectmode = vc->scene->toolsettings->selectmode;
+ vc->scene->toolsettings->selectmode |= SCE_SELECT_EDGE;
+
/* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */
ED_view3d_backbuf_validate(eval_ctx, vc);
+ /* restore `selectmode` */
+ vc->scene->toolsettings->selectmode = ts_selectmode;
+
index = ED_view3d_backbuf_sample_rect(eval_ctx, vc, vc->mval, dist_px, bm_solidoffs, bm_wireoffs, &dist_test);
eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL;
@@ -1583,9 +1591,17 @@ static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool de
mvalf[1] = (float)(vc.mval[1] = mval[1]);
em = vc.em;
+ /* Make sure that the edges are also considered for selection.
+ * TODO: cleanup: add `selectmode` as a parameter */
+ const short ts_selectmode = vc.scene->toolsettings->selectmode;
+ vc.scene->toolsettings->selectmode |= SCE_SELECT_EDGE;
+
/* no afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad */
ED_view3d_backbuf_validate(&eval_ctx, &vc);
+ /* restore `selectmode` */
+ vc.scene->toolsettings->selectmode = ts_selectmode;
+
eed = EDBM_edge_find_nearest_ex(&eval_ctx, &vc, &dist, NULL, true, true, NULL);
if (eed == NULL) {
return false;
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 74bd4e978e7..75a13a916e6 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -311,7 +311,7 @@ void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em)
ED_view3d_init_mats_rv3d(obedit, ar->regiondata);
struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C), CTX_data_scene(C), CTX_data_view_layer(C), CTX_data_engine(C), 0,
+ CTX_data_main(C), CTX_data_scene(C), CTX_data_view_layer(C), CTX_data_engine_type(C), 0,
ar, CTX_wm_view3d(C));
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index 230f46abad1..27fe93b049a 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -53,7 +53,7 @@
#include "DEG_depsgraph.h"
-#include "BKE_object.h" /* XXX. only for EDBM_mesh_ensure_valid_dm_hack() which will be removed */
+#include "BKE_object.h" /* XXX. only for EDBM_mesh_load(). */
#include "WM_api.h"
#include "WM_types.h"
@@ -108,21 +108,6 @@ void EDBM_redo_state_free(BMBackup *backup, BMEditMesh *em, int recalctess)
BKE_editmesh_tessface_calc(em);
}
-/* hack to workaround multiple operators being called within the same event loop without an update
- * see: [#31811] */
-void EDBM_mesh_ensure_valid_dm_hack(Scene *scene, BMEditMesh *em)
-{
- if ((((ID *)em->ob->data)->tag & LIB_TAG_ID_RECALC) ||
- (em->ob->recalc & OB_RECALC_DATA))
- {
- /* since we may not have done selection flushing */
- if ((em->ob->recalc & OB_RECALC_DATA) == 0) {
- DEG_id_tag_update(&em->ob->id, OB_RECALC_DATA);
- }
- BKE_object_handle_update(G.main->eval_ctx, scene, em->ob);
- }
-}
-
void EDBM_mesh_normals_update(BMEditMesh *em)
{
BM_mesh_normals_update(em->bm);
@@ -413,6 +398,7 @@ void EDBM_mesh_load(Object *ob)
* of freed data on scene update, especially in cases when there are dependency
* cycles.
*/
+ /*
for (Object *other_object = G.main->object.first;
other_object != NULL;
other_object = other_object->id.next)
@@ -421,6 +407,7 @@ void EDBM_mesh_load(Object *ob)
BKE_object_free_derived_caches(other_object);
}
}
+ */
}
/**
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 77b30951dee..e8807432328 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -449,10 +449,13 @@ Object *ED_object_add_type(
ob->gameflag &= ~(OB_SENSOR | OB_RIGID_BODY | OB_SOFT_BODY | OB_COLLISION | OB_CHARACTER | OB_OCCLUDER | OB_DYNAMIC | OB_NAVMESH); /* copied from rna_object.c */
}
+ /* TODO(sergey): This is weird to manually tag objects for update, better to
+ * use DEG_id_tag_update here perhaps.
+ */
DEG_id_type_tag(bmain, ID_OB);
DEG_relations_tag_update(bmain);
- if (ob->data) {
- ED_render_id_flush_update(bmain, ob->data);
+ if (ob->data != NULL) {
+ DEG_id_tag_update_ex(bmain, (ID *)ob->data, DEG_TAG_EDITORS_UPDATE);
}
if (enter_editmode)
@@ -1218,7 +1221,7 @@ void ED_object_base_free_and_unlink(Main *bmain, Scene *scene, Object *ob)
DEG_id_tag_update_ex(bmain, &ob->id, DEG_TAG_BASE_FLAGS_UPDATE);
object_delete_check_glsl_update(ob);
- BKE_collections_object_remove(bmain, scene, ob, true);
+ BKE_collections_object_remove(bmain, &scene->id, ob, true);
}
static int object_delete_exec(bContext *C, wmOperator *op)
@@ -2340,8 +2343,8 @@ Base *ED_object_add_duplicate(Main *bmain, Scene *scene, ViewLayer *view_layer,
/* DAG_relations_tag_update(bmain); */ /* caller must do */
- if (ob->data) {
- ED_render_id_flush_update(bmain, ob->data);
+ if (ob->data != NULL) {
+ DEG_id_tag_update_ex(bmain, (ID *)ob->data, DEG_TAG_EDITORS_UPDATE);
}
BKE_main_id_clear_newpoins(bmain);
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 804d0ed1f0d..5697c48d381 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -1516,15 +1516,13 @@ bool ED_object_mode_compat_set(bContext *C, Object *ob, int mode, ReportList *re
{
bool ok;
if (!ELEM(ob->mode, mode, OB_MODE_OBJECT)) {
- WorkSpace *workspace = CTX_wm_workspace(C);
const char *opstring = object_mode_op_string(ob->mode);
WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL);
#ifdef USE_WORKSPACE_MODE
- BKE_workspace_object_mode_set(workspace, ob->mode);
-#else
- UNUSED_VARS(workspace);
+ BKE_workspace_object_mode_set(CTX_wm_workspace(C), CTX_data_scene(C), ob->mode);
#endif
+
ok = ELEM(ob->mode, mode, OB_MODE_OBJECT);
if (!ok) {
wmOperatorType *ot = WM_operatortype_find(opstring, false);
@@ -1648,7 +1646,7 @@ void ED_object_toggle_modes(bContext *C, int mode)
#ifdef USE_WORKSPACE_MODE
Object *ob = CTX_data_active_object(C);
if (ob) {
- BKE_workspace_object_mode_set(workspace, ob->mode);
+ BKE_workspace_object_mode_set(workspace, CTX_data_scene(C), ob->mode);
}
#endif
}
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index 3e655fa04a4..c38a7d58904 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -68,6 +68,7 @@ void OBJECT_OT_track_clear(struct wmOperatorType *ot);
void OBJECT_OT_slow_parent_set(struct wmOperatorType *ot);
void OBJECT_OT_slow_parent_clear(struct wmOperatorType *ot);
void OBJECT_OT_make_local(struct wmOperatorType *ot);
+void OBJECT_OT_make_override(struct wmOperatorType *ot);
void OBJECT_OT_make_single_user(struct wmOperatorType *ot);
void OBJECT_OT_make_links_scene(struct wmOperatorType *ot);
void OBJECT_OT_make_links_data(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index c87df877d5c..ceea3b9c0ac 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -84,6 +84,7 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_slow_parent_set);
WM_operatortype_append(OBJECT_OT_slow_parent_clear);
WM_operatortype_append(OBJECT_OT_make_local);
+ WM_operatortype_append(OBJECT_OT_make_override);
WM_operatortype_append(OBJECT_OT_make_single_user);
WM_operatortype_append(OBJECT_OT_make_links_scene);
WM_operatortype_append(OBJECT_OT_make_links_data);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 9854b61813b..436364ec6c3 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -77,8 +77,10 @@
#include "BKE_lattice.h"
#include "BKE_layer.h"
#include "BKE_library.h"
+#include "BKE_library_override.h"
#include "BKE_library_query.h"
#include "BKE_library_remap.h"
+#include "BKE_lightprobe.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mball.h"
@@ -340,17 +342,15 @@ static int make_proxy_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Object *ob, *gob = ED_object_active_context(C);
- GroupObject *go;
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
if (gob->dup_group != NULL) {
- go = BLI_findlink(&gob->dup_group->gobject, RNA_enum_get(op->ptr, "object"));
- ob = go->ob;
+ Base *base = BLI_findlink(&gob->dup_group->view_layer->object_bases, RNA_enum_get(op->ptr, "object"));
+ ob = base->object;
}
else {
ob = gob;
- gob = NULL;
}
if (ob) {
@@ -395,17 +395,18 @@ static const EnumPropertyItem *proxy_group_object_itemf(bContext *C, PointerRNA
int totitem = 0;
int i = 0;
Object *ob = ED_object_active_context(C);
- GroupObject *go;
if (!ob || !ob->dup_group)
return DummyRNA_DEFAULT_items;
/* find the object to affect */
- for (go = ob->dup_group->gobject.first; go; go = go->next) {
- item_tmp.identifier = item_tmp.name = go->ob->id.name + 2;
+ FOREACH_GROUP_OBJECT(ob->dup_group, object)
+ {
+ item_tmp.identifier = item_tmp.name = object->id.name + 2;
item_tmp.value = i++;
RNA_enum_item_add(&item, &totitem, &item_tmp);
}
+ FOREACH_GROUP_OBJECT_END
RNA_enum_item_end(&item, &totitem);
*r_free = true;
@@ -1366,10 +1367,10 @@ static int make_links_scene_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- SceneCollection *sc_to = BKE_collection_master(scene_to);
+ SceneCollection *sc_to = BKE_collection_master(&scene_to->id);
CTX_DATA_BEGIN (C, Base *, base, selected_bases)
{
- BKE_collection_object_add(scene_to, sc_to, base->object);
+ BKE_collection_object_add(&scene_to->id, sc_to, base->object);
}
CTX_DATA_END;
@@ -1689,12 +1690,11 @@ static void single_object_users_scene_collection(Main *bmain, Scene *scene, Scen
static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_groups)
{
Group *group, *groupn;
- GroupObject *go;
clear_sca_new_poins(); /* BGE logic */
/* duplicate all the objects of the scene */
- SceneCollection *msc = BKE_collection_master(scene);
+ SceneCollection *msc = BKE_collection_master(&scene->id);
single_object_users_scene_collection(bmain, scene, msc, flag, copy_groups);
/* loop over ViewLayers and assign the pointers accordingly */
@@ -1706,22 +1706,26 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
/* duplicate groups that consist entirely of duplicated objects */
for (group = bmain->group.first; group; group = group->id.next) {
- if (copy_groups && group->gobject.first) {
+ if (copy_groups && group->view_layer->object_bases.first) {
bool all_duplicated = true;
- for (go = group->gobject.first; go; go = go->next) {
- if (!(go->ob && (go->ob->id.newid))) {
+ FOREACH_GROUP_OBJECT(group, object)
+ {
+ if (object->id.newid == NULL) {
all_duplicated = false;
break;
}
}
+ FOREACH_GROUP_OBJECT_END
if (all_duplicated) {
groupn = ID_NEW_SET(group, BKE_group_copy(bmain, group));
- for (go = groupn->gobject.first; go; go = go->next) {
- go->ob = (Object *)go->ob->id.newid;
+ FOREACH_GROUP_BASE(groupn, base)
+ {
+ base->object = (Object *)base->object->id.newid;
}
+ FOREACH_GROUP_BASE_END
}
}
}
@@ -1840,9 +1844,15 @@ static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer
case OB_SPEAKER:
ob->data = ID_NEW_SET(ob->data, BKE_speaker_copy(bmain, ob->data));
break;
+ case OB_LIGHTPROBE:
+ ob->data = ID_NEW_SET(ob->data, BKE_lightprobe_copy(bmain, ob->data));
+ break;
default:
- if (G.debug & G_DEBUG)
- printf("ERROR %s: can't copy %s\n", __func__, id->name);
+ printf("ERROR %s: can't copy %s\n", __func__, id->name);
+ BLI_assert(!"This should never happen.");
+
+ /* We need to end the FOREACH_OBJECT_FLAG iterator to prevent memory leak. */
+ BKE_scene_objects_iterator_end(&iter_macro);
return;
}
@@ -2143,7 +2153,7 @@ static bool make_local_all__instance_indirect_unused(Main *bmain, Scene *scene,
id_us_plus(&ob->id);
- BKE_collection_object_add(scene, sc, ob);
+ BKE_collection_object_add(&scene->id, sc, ob);
base = BKE_view_layer_base_find(view_layer, ob);
base->flag |= BASE_SELECTED;
BKE_scene_object_base_flag_sync_from_base(base);
@@ -2325,6 +2335,44 @@ void OBJECT_OT_make_local(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
}
+static int make_override_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Main *bmain = CTX_data_main(C);
+ Object *locobj, *refobj = CTX_data_active_object(C);
+
+ locobj = (Object *)BKE_override_static_create_from(bmain, &refobj->id);
+ UNUSED_VARS(locobj);
+
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static int make_override_poll(bContext *C)
+{
+ Object *obact = CTX_data_active_object(C);
+
+ /* Object must be directly linked to be overridable. */
+ return (ED_operator_objectmode(C) && obact && obact->id.lib != NULL && obact->id.tag & LIB_TAG_EXTERN);
+}
+
+void OBJECT_OT_make_override(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Make Override";
+ ot->description = "Make local override of this library linked data-block";
+ ot->idname = "OBJECT_OT_make_override";
+
+ /* api callbacks */
+ ot->exec = make_override_exec;
+ ot->poll = make_override_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+}
+
enum {
MAKE_SINGLE_USER_ALL = 1,
MAKE_SINGLE_USER_SELECTED = 2,
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index 47e63cb43e5..552380cebdb 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -123,8 +123,7 @@ void ED_object_base_activate(bContext *C, Base *base)
if (base) {
#ifdef USE_WORKSPACE_MODE
- WorkSpace *workspace = CTX_wm_workspace(C);
- BKE_workspace_object_mode_set(workspace, base->object->mode);
+ BKE_workspace_object_mode_set(CTX_wm_workspace(C), CTX_data_scene(C), base->object->mode);
#endif
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, view_layer);
}
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 2c659d2b985..4e75ca3e6f1 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -832,7 +832,7 @@ static void clean_viewport_memory(Main *bmain, Scene *scene)
}
}
- for (SETLOOPER_SET_ONLY(scene, sce_iter, base)) {
+ for (SETLOOPER_SET_ONLY(scene, sce_iter, base)) {
clean_viewport_memory_base(base);
}
}
diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c
index 8956ef79958..a391b13a000 100644
--- a/source/blender/editors/render/render_update.c
+++ b/source/blender/editors/render/render_update.c
@@ -70,6 +70,8 @@
#include "ED_render.h"
#include "ED_view3d.h"
+#include "DEG_depsgraph.h"
+
#include "WM_api.h"
#include "render_intern.h" // own include
@@ -78,10 +80,13 @@ extern Material defmaterial;
/***************************** Render Engines ********************************/
-void ED_render_scene_update(Main *bmain, Scene *scene, int updated)
+void ED_render_scene_update(const DEGEditorUpdateContext *update_ctx, int updated)
{
/* viewport rendering update on data changes, happens after depsgraph
* updates if there was any change. context is set to the 3d view */
+ Main *bmain = update_ctx->bmain;
+ Scene *scene = update_ctx->scene;
+ ViewLayer *view_layer = update_ctx->view_layer;
bContext *C;
wmWindowManager *wm;
wmWindow *win;
@@ -123,15 +128,11 @@ void ED_render_scene_update(Main *bmain, Scene *scene, int updated)
continue;
for (ar = sa->regionbase.first; ar; ar = ar->next) {
- RegionView3D *rv3d;
- RenderEngine *engine;
-
- if (ar->regiontype != RGN_TYPE_WINDOW)
+ if (ar->regiontype != RGN_TYPE_WINDOW) {
continue;
-
- rv3d = ar->regiondata;
- engine = rv3d->render_engine;
-
+ }
+ RegionView3D *rv3d = ar->regiondata;
+ RenderEngine *engine = rv3d->render_engine;
/* call update if the scene changed, or if the render engine
* tagged itself for update (e.g. because it was busy at the
* time of the last update) */
@@ -145,13 +146,20 @@ void ED_render_scene_update(Main *bmain, Scene *scene, int updated)
engine->type->view_update(engine, C);
}
- else if ((RE_engines_find(view_render->engine_id)->flag & RE_USE_LEGACY_PIPELINE) == 0) {
- if (updated) {
- CTX_wm_screen_set(C, sc);
- CTX_wm_area_set(C, sa);
- CTX_wm_region_set(C, ar);
-
- DRW_notify_view_update(C);
+ else {
+ RenderEngineType *engine_type = RE_engines_find(view_render->engine_id);
+ if ((engine_type->flag & RE_USE_LEGACY_PIPELINE) == 0) {
+ if (updated) {
+ DRW_notify_view_update(
+ (&(DRWUpdateContext){
+ .bmain = bmain,
+ .scene = scene,
+ .view_layer = view_layer,
+ .ar = ar,
+ .v3d = (View3D *)sa->spacedata.first,
+ .engine_type = engine_type
+ }));
+ }
}
}
}
@@ -163,23 +171,6 @@ void ED_render_scene_update(Main *bmain, Scene *scene, int updated)
recursive_check = false;
}
-void ED_render_scene_update_pre(Main *bmain, Scene *scene, bool time)
-{
- /* Blender internal might access to the data which is gonna to be freed
- * by the scene update functions. This applies for example to simulation
- * data like smoke and fire.
- */
- if (time && !BKE_scene_use_new_shading_nodes(scene)) {
- bScreen *sc;
- ScrArea *sa;
- for (sc = bmain->screen.first; sc; sc = sc->id.next) {
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- ED_render_engine_area_exit(bmain, sa);
- }
- }
- }
-}
-
void ED_render_engine_area_exit(Main *bmain, ScrArea *sa)
{
/* clear all render engines in this area */
@@ -199,18 +190,21 @@ void ED_render_engine_area_exit(Main *bmain, ScrArea *sa)
void ED_render_engine_changed(Main *bmain)
{
/* on changing the render engine type, clear all running render engines */
- bScreen *sc;
- ScrArea *sa;
- Scene *scene;
-
- for (sc = bmain->screen.first; sc; sc = sc->id.next)
- for (sa = sc->areabase.first; sa; sa = sa->next)
+ for (bScreen *sc = bmain->screen.first; sc; sc = sc->id.next) {
+ for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
ED_render_engine_area_exit(bmain, sa);
-
+ }
+ }
RE_FreePersistentData();
-
- for (scene = bmain->scene.first; scene; scene = scene->id.next) {
- ED_render_id_flush_update(bmain, &scene->id);
+ /* Inform all render engines and draw managers. */
+ DEGEditorUpdateContext update_ctx = {NULL};
+ update_ctx.bmain = bmain;
+ for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+ update_ctx.scene = scene;
+ LINKLIST_FOREACH(ViewLayer *, view_layer, &scene->view_layers) {
+ update_ctx.view_layer = view_layer;
+ ED_render_id_flush_update(&update_ctx, &scene->id);
+ }
if (scene->nodetree) {
ntreeCompositUpdateRLayers(scene->nodetree);
}
@@ -536,14 +530,18 @@ static void scene_changed(Main *bmain, Scene *scene)
}
}
-void ED_render_id_flush_update(Main *bmain, ID *id)
+void ED_render_id_flush_update(const DEGEditorUpdateContext *update_ctx, ID *id)
{
/* this can be called from render or baking thread when a python script makes
* changes, in that case we don't want to do any editor updates, and making
* GPU changes is not possible because OpenGL only works in the main thread */
- if (!BLI_thread_is_main())
+ if (!BLI_thread_is_main()) {
return;
-
+ }
+ Main *bmain = update_ctx->bmain;
+ Scene *scene = update_ctx->scene;
+ ViewLayer *view_layer = update_ctx->view_layer;
+ /* Internal ID update handlers. */
switch (GS(id->name)) {
case ID_MA:
material_changed(bmain, (Material *)id);
@@ -569,7 +567,42 @@ void ED_render_id_flush_update(Main *bmain, ID *id)
render_engine_flag_changed(bmain, RE_ENGINE_UPDATE_OTHER);
break;
}
-
+ /* Inform all draw managers about changes.
+ *
+ * TODO(sergey): This code is run for every updated ID, via flushing
+ * mechanism. How can we avoid iterating over the whole interface for
+ * every of those IDs? One of the ideas would be to call draw manager's
+ * ID update which is not bound to any of contexts.
+ */
+ {
+ wmWindowManager *wm = bmain->wm.first;
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ bScreen *sc = WM_window_get_active_screen(win);
+ WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
+ ViewRender *view_render = BKE_viewrender_get(win->scene, workspace);
+ for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
+ if (sa->spacetype != SPACE_VIEW3D) {
+ continue;
+ }
+ for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype != RGN_TYPE_WINDOW) {
+ continue;
+ }
+ RenderEngineType *engine_type = RE_engines_find(view_render->engine_id);
+ DRW_notify_id_update(
+ (&(DRWUpdateContext){
+ .bmain = bmain,
+ .scene = scene,
+ .view_layer = view_layer,
+ .ar = ar,
+ .v3d = (View3D *)sa->spacedata.first,
+ .engine_type = engine_type
+ }),
+ id);
+ }
+ }
+ }
+ }
}
diff --git a/source/blender/editors/scene/scene_edit.c b/source/blender/editors/scene/scene_edit.c
index c7f04a0e2f9..812f9a736bf 100644
--- a/source/blender/editors/scene/scene_edit.c
+++ b/source/blender/editors/scene/scene_edit.c
@@ -118,16 +118,20 @@ void ED_scene_exit(bContext *C)
ED_object_editmode_exit(C, EM_FREEDATA | EM_DO_UNDO);
}
+static ViewLayer *scene_change_get_new_view_layer(const WorkSpace *workspace, const Scene *scene_new)
+{
+ ViewLayer *layer_new = BKE_workspace_view_layer_get(workspace, scene_new);
+ return layer_new ? layer_new : BKE_view_layer_from_scene_get(scene_new);
+}
+
void ED_scene_changed_update(Main *bmain, bContext *C, Scene *scene_new, const bScreen *active_screen)
{
- /* XXX Just using active scene render-layer for workspace when switching,
- * but workspace should remember the last one set. Could store render-layer
- * per window-workspace combination (using WorkSpaceDataRelation) */
- ViewLayer *layer_new = BLI_findlink(&scene_new->view_layers, scene_new->active_view_layer);
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ ViewLayer *layer_new = scene_change_get_new_view_layer(workspace, scene_new);
Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene_new, layer_new, true);
CTX_data_scene_set(C, scene_new);
- BKE_workspace_view_layer_set(CTX_wm_workspace(C), layer_new);
+ BKE_workspace_view_layer_set(workspace, layer_new, scene_new);
BKE_scene_set_background(bmain, scene_new);
DEG_graph_relations_update(depsgraph, bmain, scene_new, layer_new);
DEG_on_visible_update(bmain, false);
@@ -186,7 +190,8 @@ bool ED_scene_view_layer_delete(
BLI_assert(BLI_listbase_is_empty(&scene->view_layers) == false);
scene->active_view_layer = 0;
- ED_workspace_view_layer_unset(bmain, layer, scene->view_layers.first);
+ ED_workspace_view_layer_unset(bmain, scene, layer, scene->view_layers.first);
+ BKE_workspace_view_layer_remove_references(bmain, layer);
view_layer_remove_unset_nodetrees(bmain, scene, layer);
BKE_view_layer_free(layer);
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index e5ed2ff1d67..dbeac782e10 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -51,6 +51,7 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_message.h"
#include "wm_subwindow.h"
#include "ED_screen.h"
@@ -511,6 +512,33 @@ void ED_region_set(const bContext *C, ARegion *ar)
ED_region_pixelspace(ar);
}
+/* Follow wmMsgNotifyFn spec */
+void ED_region_do_msg_notify_tag_redraw(
+ bContext *UNUSED(C), wmMsgSubscribeKey *UNUSED(msg_key), wmMsgSubscribeValue *msg_val)
+{
+ ARegion *ar = msg_val->owner;
+ ED_region_tag_redraw(ar);
+
+ /* This avoids _many_ situations where header/properties control display settings.
+ * the common case is space properties in the header */
+ if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_UI)) {
+ while (ar && ar->prev) {
+ ar = ar->prev;
+ }
+ for (; ar; ar = ar->next) {
+ if (ELEM(ar->regiontype, RGN_TYPE_WINDOW, RGN_TYPE_CHANNELS)) {
+ ED_region_tag_redraw(ar);
+ }
+ }
+ }
+}
+/* Follow wmMsgNotifyFn spec */
+void ED_area_do_msg_notify_tag_refresh(
+ bContext *UNUSED(C), wmMsgSubscribeKey *UNUSED(msg_key), wmMsgSubscribeValue *msg_val)
+{
+ ScrArea *sa = msg_val->user_data;
+ ED_area_tag_refresh(sa);
+}
/* only exported for WM */
void ED_region_do_draw(bContext *C, ARegion *ar)
@@ -589,6 +617,37 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
region_draw_emboss(ar, &ar->winrct);
}
}
+
+ /* We may want to detach message-subscriptions from drawing. */
+ {
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ bScreen *screen = WM_window_get_active_screen(win);
+ Scene *scene = CTX_data_scene(C);
+ struct wmMsgBus *mbus = wm->message_bus;
+ WM_msgbus_clear_by_owner(mbus, ar);
+
+ /* Cheat, always subscribe to this space type properties.
+ *
+ * This covers most cases and avoids copy-paste similar code for each space type.
+ */
+ if (ELEM(ar->regiontype, RGN_TYPE_WINDOW, RGN_TYPE_CHANNELS, RGN_TYPE_UI, RGN_TYPE_TOOLS)) {
+ SpaceLink *sl = sa->spacedata.first;
+
+ PointerRNA ptr;
+ RNA_pointer_create(&screen->id, &RNA_Space, sl, &ptr);
+
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+ /* All properties for this space type. */
+ WM_msg_subscribe_rna(mbus, &ptr, NULL, &msg_sub_value_region_tag_redraw, __func__);
+ }
+
+ ED_region_message_subscribe(C, workspace, scene, screen, sa, ar, mbus);
+ }
}
/* **********************************
@@ -2695,3 +2754,25 @@ void ED_region_cache_draw_cached_segments(const ARegion *ar, const int num_segme
immUnbindProgram();
}
}
+
+/**
+ * Generate subscriptions for this region.
+ */
+void ED_region_message_subscribe(
+ bContext *C,
+ struct WorkSpace *workspace, struct Scene *scene,
+ struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar,
+ struct wmMsgBus *mbus)
+{
+ if (ar->manipulator_map != NULL) {
+ WM_manipulatormap_message_subscribe(C, ar->manipulator_map, ar, mbus);
+ }
+
+ if (BLI_listbase_is_empty(&ar->uiblocks)) {
+ UI_region_message_subscribe(ar, mbus);
+ }
+
+ if (ar->type->message_subscribe != NULL) {
+ ar->type->message_subscribe(C, workspace, scene, screen, sa, ar, mbus);
+ }
+}
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
index d84f256bc32..4c62253bef6 100644
--- a/source/blender/editors/screen/screen_context.c
+++ b/source/blender/editors/screen/screen_context.c
@@ -91,7 +91,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
ViewLayer *view_layer = BKE_view_layer_from_workspace_get(scene, workspace);
Object *obedit = scene->obedit;
- Object *obact = view_layer->basact ? view_layer->basact->object : NULL;
+ Object *obact = (view_layer && view_layer->basact) ? view_layer->basact->object : NULL;
if (CTX_data_dir(member)) {
CTX_data_dir_set(result, screen_context_dir);
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index c1ea219ad04..4b5ce2f4b81 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -66,6 +66,8 @@
#include "UI_interface.h"
+#include "WM_message.h"
+
/* XXX actually should be not here... solve later */
#include "wm_subwindow.h"
@@ -897,6 +899,8 @@ void ED_region_exit(bContext *C, ARegion *ar)
ar->regiontimer = NULL;
}
+ WM_msgbus_clear_by_owner(wm->message_bus, ar);
+
CTX_wm_region_set(C, prevar);
}
diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c
index fb113816144..da9cb69b528 100644
--- a/source/blender/editors/screen/workspace_edit.c
+++ b/source/blender/editors/screen/workspace_edit.c
@@ -71,15 +71,16 @@
* \{ */
WorkSpace *ED_workspace_add(
- Main *bmain, const char *name, ViewLayer *act_view_layer, ViewRender *view_render)
+ Main *bmain, const char *name, Scene *scene,
+ ViewLayer *act_view_layer, ViewRender *view_render)
{
WorkSpace *workspace = BKE_workspace_add(bmain, name);
- BKE_workspace_view_layer_set(workspace, act_view_layer);
+ BKE_workspace_view_layer_set(workspace, act_view_layer, scene);
BKE_viewrender_copy(&workspace->view_render, view_render);
#ifdef USE_WORKSPACE_MODE
- BKE_workspace_object_mode_set(workspace, OB_MODE_OBJECT);
+ BKE_workspace_object_mode_set(workspace, scene, OB_MODE_OBJECT);
#endif
return workspace;
@@ -94,8 +95,9 @@ static void workspace_change_update_mode(
const WorkSpace *workspace_old, const WorkSpace *workspace_new,
bContext *C, Object *ob_act, ReportList *reports)
{
- eObjectMode mode_old = BKE_workspace_object_mode_get(workspace_old);
- eObjectMode mode_new = BKE_workspace_object_mode_get(workspace_new);
+ const Scene *scene = CTX_data_scene(C);
+ eObjectMode mode_old = BKE_workspace_object_mode_get(workspace_old, scene);
+ eObjectMode mode_new = BKE_workspace_object_mode_get(workspace_new, scene);
if (mode_old != mode_new) {
ED_object_mode_compat_set(C, ob_act, mode_new, reports);
@@ -105,10 +107,11 @@ static void workspace_change_update_mode(
#endif
static void workspace_change_update_view_layer(
- WorkSpace *workspace_new, const WorkSpace *workspace_old)
+ WorkSpace *workspace_new, const WorkSpace *workspace_old,
+ Scene *scene)
{
- if (!BKE_workspace_view_layer_get(workspace_new)) {
- BKE_workspace_view_layer_set(workspace_new, BKE_workspace_view_layer_get(workspace_old));
+ if (!BKE_workspace_view_layer_get(workspace_new, scene)) {
+ BKE_workspace_view_layer_set(workspace_new, BKE_workspace_view_layer_get(workspace_old, scene), scene);
}
}
@@ -117,7 +120,7 @@ static void workspace_change_update(
bContext *C, wmWindowManager *wm)
{
/* needs to be done before changing mode! (to ensure right context) */
- workspace_change_update_view_layer(workspace_new, workspace_old);
+ workspace_change_update_view_layer(workspace_new, workspace_old, CTX_data_scene(C));
#ifdef USE_WORKSPACE_MODE
workspace_change_update_mode(workspace_old, workspace_new, C, CTX_data_active_object(C), &wm->reports);
#else
@@ -199,7 +202,7 @@ bool ED_workspace_change(
screen_changed_update(C, win, screen_new);
workspace_change_update(workspace_new, workspace_old, C, wm);
- BLI_assert(BKE_workspace_view_layer_get(workspace_new) != NULL);
+ BLI_assert(BKE_workspace_view_layer_get(workspace_new, CTX_data_scene(C)) != NULL);
BLI_assert(CTX_wm_workspace(C) == workspace_new);
WM_toolsystem_unlink(C, workspace_old);
@@ -220,15 +223,16 @@ WorkSpace *ED_workspace_duplicate(
{
WorkSpaceLayout *layout_active_old = BKE_workspace_active_layout_get(win->workspace_hook);
ListBase *layouts_old = BKE_workspace_layouts_get(workspace_old);
+ Scene *scene = WM_window_get_active_scene(win);
WorkSpace *workspace_new = ED_workspace_add(
- bmain, workspace_old->id.name + 2,
- BKE_workspace_view_layer_get(workspace_old),
+ bmain, workspace_old->id.name + 2, scene,
+ BKE_workspace_view_layer_get(workspace_old, scene),
&workspace_old->view_render);
ListBase *transform_orientations_old = BKE_workspace_transform_orientations_get(workspace_old);
ListBase *transform_orientations_new = BKE_workspace_transform_orientations_get(workspace_new);
#ifdef USE_WORKSPACE_MODE
- BKE_workspace_object_mode_set(workspace_new, BKE_workspace_object_mode_get(workspace_old));
+ BKE_workspace_object_mode_set(workspace_new, scene, BKE_workspace_object_mode_get(workspace_old, scene));
#endif
BLI_duplicatelist(transform_orientations_new, transform_orientations_old);
@@ -279,11 +283,12 @@ void ED_workspace_scene_data_sync(
}
void ED_workspace_view_layer_unset(
- const Main *bmain, const ViewLayer *layer_unset, ViewLayer *layer_new)
+ const Main *bmain, Scene *scene,
+ const ViewLayer *layer_unset, ViewLayer *layer_new)
{
for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
- if (BKE_workspace_view_layer_get(workspace) == layer_unset) {
- BKE_workspace_view_layer_set(workspace, layer_new);
+ if (BKE_workspace_view_layer_get(workspace, scene) == layer_unset) {
+ BKE_workspace_view_layer_set(workspace, layer_new, scene);
}
}
}
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index 183d715a93e..8866c6b6c40 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -39,6 +39,7 @@
#include "BLT_translation.h"
#include "DNA_armature_types.h"
+#include "DNA_group_types.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
#include "DNA_node_types.h"
@@ -177,7 +178,7 @@ static int buttons_context_path_workspace(ButsContextPath *path)
return RNA_struct_is_a(ptr->type, &RNA_WorkSpace);
}
-static int buttons_context_path_collection(ButsContextPath *path)
+static int buttons_context_path_collection(ButsContextPath *path, eSpaceButtons_Collection_Context collection_context)
{
PointerRNA *ptr = &path->ptr[path->len - 1];
@@ -187,10 +188,21 @@ static int buttons_context_path_collection(ButsContextPath *path)
}
ViewLayer *view_layer = ptr->data;
- LayerCollection *sc = BKE_layer_collection_get_active(view_layer);
- if (sc) {
- RNA_pointer_create(NULL, &RNA_LayerCollection, sc, &path->ptr[path->len]);
+ if (collection_context == SB_COLLECTION_CTX_GROUP) {
+ Object *ob = OBACT(view_layer);
+ if (ob && ob->dup_group) {
+ view_layer = ob->dup_group->view_layer;
+
+ /* Replace the view layer by the group in the context path. */
+ RNA_pointer_create(NULL, &RNA_Group, ob->dup_group, &path->ptr[path->len - 1]);
+ }
+ }
+
+ LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
+
+ if (layer_collection) {
+ RNA_pointer_create(NULL, &RNA_LayerCollection, layer_collection, &path->ptr[path->len]);
path->len++;
return 1;
}
@@ -650,7 +662,7 @@ static int buttons_context_path(const bContext *C, ButsContextPath *path, int ma
found = buttons_context_path_workspace(path);
break;
case BCONTEXT_COLLECTION:
- found = buttons_context_path_collection(path);
+ found = buttons_context_path_collection(path, sbuts->collection_context);
break;
case BCONTEXT_OBJECT:
case BCONTEXT_PHYSICS:
diff --git a/source/blender/editors/space_buttons/buttons_intern.h b/source/blender/editors/space_buttons/buttons_intern.h
index 7fc35a6b1e7..e6d19caad47 100644
--- a/source/blender/editors/space_buttons/buttons_intern.h
+++ b/source/blender/editors/space_buttons/buttons_intern.h
@@ -65,6 +65,7 @@ typedef struct ButsContextPath {
int len;
int flag;
int tex_ctx;
+ int collection_ctx;
} ButsContextPath;
typedef struct ButsTextureUser {
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index 74b20360a53..d2f407bfa8c 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -44,6 +44,7 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_message.h"
#include "RNA_access.h"
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index cca33cdd1a7..217ce8f1d9a 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -151,15 +151,25 @@ static FileSelection file_selection_get(bContext *C, const rcti *rect, bool fill
/* if desired, fill the selection up from the last selected file to the current one */
if (fill && (sel.last >= 0) && (sel.last < numfiles) ) {
- int f = sel.last;
- while (f >= 0) {
+ int f;
+ /* Try to find a smaller-index selected item. */
+ for (f = sel.last; f >= 0; f--) {
if (filelist_entry_select_index_get(sfile->files, f, CHECK_ALL) )
break;
- f--;
}
if (f >= 0) {
sel.first = f + 1;
}
+ /* If none found, try to find a higher-index selected item. */
+ else {
+ for (f = sel.first; f < numfiles; f++) {
+ if (filelist_entry_select_index_get(sfile->files, f, CHECK_ALL) )
+ break;
+ }
+ if (f < numfiles) {
+ sel.last = f - 1;
+ }
+ }
}
return sel;
}
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index 780c2ec5a47..3f26604c23a 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -49,6 +49,7 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_message.h"
#include "ED_space_api.h"
#include "ED_screen.h"
@@ -354,6 +355,33 @@ static void file_main_region_listener(
}
}
+static void file_main_region_message_subscribe(
+ const struct bContext *UNUSED(C),
+ struct WorkSpace *UNUSED(workspace), struct Scene *UNUSED(scene),
+ struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar,
+ struct wmMsgBus *mbus)
+{
+ SpaceFile *sfile = sa->spacedata.first;
+ FileSelectParams *params = ED_fileselect_get_params(sfile);
+ /* This is a bit odd that a region owns the subscriber for an area,
+ * keep for now since all subscribers for WM are regions.
+ * May be worth re-visiting later. */
+ wmMsgSubscribeValue msg_sub_value_area_tag_refresh = {
+ .owner = ar,
+ .user_data = sa,
+ .notify = ED_area_do_msg_notify_tag_refresh,
+ };
+
+ /* FileSelectParams */
+ {
+ PointerRNA ptr;
+ RNA_pointer_create(&screen->id, &RNA_FileSelectParams, params, &ptr);
+
+ /* All properties for this space type. */
+ WM_msg_subscribe_rna(mbus, &ptr, NULL, &msg_sub_value_area_tag_refresh, __func__);
+ }
+}
+
static void file_main_region_draw(const bContext *C, ARegion *ar)
{
/* draw entirely, view changes should be handled here */
@@ -731,6 +759,7 @@ void ED_spacetype_file(void)
art->init = file_main_region_init;
art->draw = file_main_region_draw;
art->listener = file_main_region_listener;
+ art->message_subscribe = file_main_region_message_subscribe;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
BLI_addhead(&st->regiontypes, art);
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index 53709e4cea7..3cf833756ef 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -270,6 +270,39 @@ static void stats_object_sculpt_dynamic_topology(Object *ob, SceneStats *stats)
stats->tottri = ob->sculpt->bm->totface;
}
+static void stats_dupli_object_group_count(SceneCollection *scene_collection, int *count)
+{
+ for (LinkData *link = scene_collection->objects.first; link; link = link->next) {
+ (*count)++;
+ }
+
+ SceneCollection *scene_collection_nested;
+ for (scene_collection_nested = scene_collection->scene_collections.first;
+ scene_collection_nested;
+ scene_collection_nested = scene_collection_nested->next)
+ {
+ stats_dupli_object_group_count(scene_collection_nested, count);
+ }
+}
+
+static void stats_dupli_object_group_doit(SceneCollection *scene_collection, SceneStats *stats, ParticleSystem *psys,
+ const int totgroup, int *cur)
+{
+ for (LinkData *link = scene_collection->objects.first; link; link = link->next) {
+ int tot = count_particles_mod(psys, totgroup, *cur);
+ stats_object(link->data, 0, tot, stats);
+ (*cur)++;
+ }
+
+ SceneCollection *scene_collection_nested;
+ for (scene_collection_nested = scene_collection->scene_collections.first;
+ scene_collection_nested;
+ scene_collection_nested = scene_collection_nested->next)
+ {
+ stats_dupli_object_group_doit(scene_collection_nested, stats, psys, totgroup, cur);
+ }
+}
+
static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
{
if (base->flag & BASE_SELECTED) stats->totobjsel++;
@@ -287,17 +320,11 @@ static void stats_dupli_object(Base *base, Object *ob, SceneStats *stats)
stats_object(part->dup_ob, 0, tot, stats);
}
else if (part->draw_as == PART_DRAW_GR && part->dup_group) {
- GroupObject *go;
- int tot, totgroup = 0, cur = 0;
-
- for (go = part->dup_group->gobject.first; go; go = go->next)
- totgroup++;
-
- for (go = part->dup_group->gobject.first; go; go = go->next) {
- tot = count_particles_mod(psys, totgroup, cur);
- stats_object(go->ob, 0, tot, stats);
- cur++;
- }
+ int totgroup = 0, cur = 0;
+
+ SceneCollection *scene_collection = part->dup_group->collection;
+ stats_dupli_object_group_count(scene_collection, &totgroup);
+ stats_dupli_object_group_doit(scene_collection, stats, psys, totgroup, &cur);
}
}
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index adf7e1dc5d3..d5c833a7b5f 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -36,6 +36,8 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
+#include "DNA_group_types.h"
+
#include "ED_screen.h"
#include "WM_api.h"
@@ -110,7 +112,7 @@ static int collection_link_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- SceneCollection *sc_master = BKE_collection_master(scene);
+ SceneCollection *sc_master = BKE_collection_master(&scene->id);
SceneCollection *sc;
int scene_collection_index = RNA_enum_get(op->ptr, "scene_collection");
@@ -136,7 +138,9 @@ static int collection_link_exec(bContext *C, wmOperator *op)
static int collection_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (BKE_collection_master(CTX_data_scene(C))->scene_collections.first == NULL) {
+ Scene *scene = CTX_data_scene(C);
+ SceneCollection *master_collection = BKE_collection_master(&scene->id);
+ if (master_collection->scene_collections.first == NULL) {
RNA_enum_set(op->ptr, "scene_collection", 0);
return collection_link_exec(C, op);
}
@@ -169,7 +173,7 @@ static const EnumPropertyItem *collection_scene_collection_itemf(
int value = 0, totitem = 0;
Scene *scene = CTX_data_scene(C);
- SceneCollection *sc = BKE_collection_master(scene);
+ SceneCollection *sc = BKE_collection_master(&scene->id);
collection_scene_collection_itemf_recursive(&tmp, &item, &totitem, &value, sc);
RNA_enum_item_end(&item, &totitem);
@@ -257,15 +261,18 @@ void OUTLINER_OT_collection_unlink(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/**********************************************************************************/
+/* Add new collection. */
+
static int collection_new_exec(bContext *C, wmOperator *UNUSED(op))
{
+ 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);
- SceneCollection *sc = BKE_collection_add(scene, NULL, NULL);
- BKE_collection_link(view_layer, sc);
-
- DEG_relations_tag_update(CTX_data_main(C));
+ DEG_relations_tag_update(bmain);
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
return OPERATOR_FINISHED;
}
@@ -275,7 +282,7 @@ void OUTLINER_OT_collection_new(wmOperatorType *ot)
/* identifiers */
ot->name = "New Collection";
ot->idname = "OUTLINER_OT_collection_new";
- ot->description = "Add a new collection to the scene, and link it to the active layer";
+ ot->description = "Add a new collection to the scene";
/* api callbacks */
ot->exec = collection_new_exec;
@@ -284,6 +291,8 @@ void OUTLINER_OT_collection_new(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/**********************************************************************************/
+
/**
* Returns true is selected element is a collection
*/
@@ -325,9 +334,10 @@ void OUTLINER_OT_collection_override_new(wmOperatorType *ot)
struct CollectionDeleteData {
Scene *scene;
SpaceOops *soops;
+ GSet *collections_to_delete;
};
-static TreeTraversalAction collection_delete_cb(TreeElement *te, void *customdata)
+static TreeTraversalAction collection_find_data_to_delete(TreeElement *te, void *customdata)
{
struct CollectionDeleteData *data = customdata;
SceneCollection *scene_collection = outliner_scene_collection_from_tree_element(te);
@@ -336,12 +346,12 @@ static TreeTraversalAction collection_delete_cb(TreeElement *te, void *customdat
return TRAVERSE_SKIP_CHILDS;
}
- if (scene_collection == BKE_collection_master(data->scene)) {
+ if (scene_collection == BKE_collection_master(&data->scene->id)) {
/* skip - showing warning/error message might be missleading
* when deleting multiple collections, so just do nothing */
}
else {
- BKE_collection_remove(data->scene, scene_collection);
+ BLI_gset_add(data->collections_to_delete, scene_collection);
}
return TRAVERSE_CONTINUE;
@@ -353,8 +363,22 @@ static int collection_delete_exec(bContext *C, wmOperator *UNUSED(op))
SpaceOops *soops = CTX_wm_space_outliner(C);
struct CollectionDeleteData data = {.scene = scene, .soops = soops};
+ data.collections_to_delete = BLI_gset_ptr_new(__func__);
+
TODO_LAYER_OVERRIDE; /* handle overrides */
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_delete_cb, &data);
+
+ /* We first walk over and find the SceneCollections we actually want to delete (ignoring duplicates). */
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_data_to_delete, &data);
+
+ /* Effectively delete the collections. */
+ GSetIterator collections_to_delete_iter;
+ GSET_ITER(collections_to_delete_iter, data.collections_to_delete) {
+
+ SceneCollection *sc = BLI_gsetIterator_getKey(&collections_to_delete_iter);
+ BKE_collection_remove(&data.scene->id, sc);
+ }
+
+ BLI_gset_free(data.collections_to_delete, NULL);
DEG_relations_tag_update(CTX_data_main(C));
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 8b4ed61f148..670fc4e6627 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -250,9 +250,16 @@ static void restrictbutton_gp_layer_flag_cb(bContext *C, void *UNUSED(poin), voi
static void enablebutton_collection_flag_cb(bContext *C, void *poin, void *poin2)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = poin;
+ Scene *scene = CTX_data_scene(C);
+ ID *id = poin;
LayerCollection *layer_collection = poin2;
- ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, layer_collection);
+ ViewLayer *view_layer = BKE_view_layer_find_from_collection(id, layer_collection);
+
+ /* TODO: This breaks when you see the collections of a group. (dfelinto) */
+ if (view_layer == NULL) {
+ WM_reportf(RPT_INFO, "Enable/disable of group collections disabled for now");
+ return;
+ }
/* We need to toggle the flag since this is called after the flag is already set. */
layer_collection->flag ^= COLLECTION_DISABLED;
@@ -273,11 +280,16 @@ static void enablebutton_collection_flag_cb(bContext *C, void *poin, void *poin2
static void restrictbutton_collection_flag_cb(bContext *C, void *poin, void *UNUSED(poin2))
{
- Scene *scene = poin;
+ ID *id = (ID *)poin;
+
/* hide and deselect bases that are directly influenced by this LayerCollection */
/* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(&scene->id, 0);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ DEG_id_tag_update(id, 0);
+
+ if (GS(id->name) == ID_SCE) {
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, id);
+ }
+
WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, NULL);
}
@@ -595,22 +607,24 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
(int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_ENABLEX), te->ys, UI_UNIT_X,
UI_UNIT_Y, &collection->flag, 0, 0, 0, 0,
TIP_("Enable/Disable collection from depsgraph"));
- UI_but_func_set(bt, enablebutton_collection_flag_cb, scene, collection);
+ UI_but_func_set(bt, enablebutton_collection_flag_cb, tselem->id, collection);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE_N, COLLECTION_VISIBLE, 0, ICON_RESTRICT_VIEW_OFF,
(int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
UI_UNIT_Y, &collection->flag, 0, 0, 0, 0,
TIP_("Restrict/Allow 3D View visibility of objects in the collection"));
- UI_but_func_set(bt, restrictbutton_collection_flag_cb, scene, collection);
+ UI_but_func_set(bt, restrictbutton_collection_flag_cb, tselem->id, collection);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE_N, COLLECTION_SELECTABLE, 0, ICON_RESTRICT_SELECT_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &collection->flag, 0, 0, 0, 0,
- TIP_("Restrict/Allow 3D View selection of objects in the collection"));
- UI_but_func_set(bt, restrictbutton_collection_flag_cb, scene, collection);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ if (collection->scene_collection->type == COLLECTION_TYPE_NONE) {
+ bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE_N, COLLECTION_SELECTABLE, 0, ICON_RESTRICT_SELECT_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &collection->flag, 0, 0, 0, 0,
+ TIP_("Restrict/Allow 3D View selection of objects in the collection"));
+ UI_but_func_set(bt, restrictbutton_collection_flag_cb, scene, collection);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
UI_block_emboss_set(block, UI_EMBOSS);
}
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 4858b6cb120..8cd76179f23 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -274,7 +274,7 @@ static void do_item_rename(const Scene *scene, ARegion *ar, TreeElement *te, Tre
BKE_report(reports, RPT_WARNING, "Cannot edit sequence name");
}
else if (ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) {
- SceneCollection *master = BKE_collection_master(scene);
+ SceneCollection *master = BKE_collection_master(&scene->id);
if ((tselem->type == TSE_SCENE_COLLECTION && te->directdata == master) ||
(((LayerCollection *)te->directdata)->scene_collection == master))
@@ -1940,7 +1940,7 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
BLI_assert(scene);
RNA_string_get(op->ptr, "child", childname);
ob = (Object *)BKE_libblock_find_name(ID_OB, childname);
- BKE_collection_object_add(scene, sc, ob);
+ BKE_collection_object_add(&scene->id, sc, ob);
DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
@@ -2166,13 +2166,13 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
SceneCollection *sc;
if (scene != CTX_data_scene(C)) {
/* when linking to an inactive scene link to the master collection */
- sc = BKE_collection_master(scene);
+ sc = BKE_collection_master(&scene->id);
}
else {
sc = CTX_data_scene_collection(C);
}
- BKE_collection_object_add(scene, sc, ob);
+ BKE_collection_object_add(&scene->id, sc, ob);
for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
Base *base = BKE_view_layer_base_find(view_layer, ob);
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index 23e1b766891..f69eb9af1bf 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -67,9 +67,8 @@ typedef enum TreeTraversalAction {
/**
* Callback type for reinserting elements at a different position, used to allow user customizable element order.
- * Passing scene right now, may be better to allow some custom data.
*/
-typedef void (*TreeElementReinsertFunc)(struct Main *bmain, const struct Scene *scene,
+typedef void (*TreeElementReinsertFunc)(struct Main *bmain,
struct TreeElement *insert_element,
struct TreeElement *insert_handle, TreeElementInsertType action);
/**
@@ -77,7 +76,7 @@ typedef void (*TreeElementReinsertFunc)(struct Main *bmain, const struct Scene *
* if reinserting insert_element before/after/into insert_handle would be allowed.
* It's allowed to change the reinsert info here for non const pointers.
*/
-typedef bool (*TreeElementReinsertPollFunc)(const struct Scene *scene, const struct TreeElement *insert_element,
+typedef bool (*TreeElementReinsertPollFunc)(const struct TreeElement *insert_element,
struct TreeElement **io_insert_handle, TreeElementInsertType *io_action);
typedef TreeTraversalAction (*TreeTraversalFunc)(struct TreeElement *te, void *customdata);
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index aa6a5dba6a7..856dd022c14 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -58,7 +58,7 @@ static int outliner_item_drag_drop_poll(bContext *C)
SpaceOops *soops = CTX_wm_space_outliner(C);
return ED_operator_outliner_active(C) &&
/* Only collection display modes supported for now. Others need more design work */
- ELEM(soops->outlinevis, SO_ACT_LAYER, SO_COLLECTIONS);
+ ELEM(soops->outlinevis, SO_ACT_LAYER, SO_COLLECTIONS, SO_GROUPS);
}
static TreeElement *outliner_item_drag_element_find(SpaceOops *soops, ARegion *ar, const wmEvent *event)
@@ -138,7 +138,7 @@ static void outliner_item_drag_get_insert_data(
}
static void outliner_item_drag_handle(
- const Scene *scene, SpaceOops *soops, ARegion *ar, const wmEvent *event, TreeElement *te_dragged)
+ SpaceOops *soops, ARegion *ar, const wmEvent *event, TreeElement *te_dragged)
{
TreeElement *te_insert_handle;
TreeElementInsertType insert_type;
@@ -156,7 +156,7 @@ static void outliner_item_drag_handle(
/* nothing will happen anyway, no need to do poll check */
}
else if (!te_dragged->reinsert_poll ||
- !te_dragged->reinsert_poll(scene, te_dragged, &te_insert_handle, &insert_type))
+ !te_dragged->reinsert_poll(te_dragged, &te_insert_handle, &insert_type))
{
te_insert_handle = NULL;
}
@@ -164,7 +164,7 @@ static void outliner_item_drag_handle(
te_dragged->drag_data->insert_handle = te_insert_handle;
}
-static bool outliner_item_drag_drop_apply(Main *bmain, const Scene *scene, TreeElement *dragged_te)
+static bool outliner_item_drag_drop_apply(Main *bmain, TreeElement *dragged_te)
{
TreeElement *insert_handle = dragged_te->drag_data->insert_handle;
TreeElementInsertType insert_type = dragged_te->drag_data->insert_type;
@@ -173,12 +173,12 @@ static bool outliner_item_drag_drop_apply(Main *bmain, const Scene *scene, TreeE
/* No need to do anything */
}
else if (dragged_te->reinsert) {
- BLI_assert(!dragged_te->reinsert_poll || dragged_te->reinsert_poll(scene, dragged_te, &insert_handle,
+ BLI_assert(!dragged_te->reinsert_poll || dragged_te->reinsert_poll(dragged_te, &insert_handle,
&insert_type));
/* call of assert above should not have changed insert_handle and insert_type at this point */
BLI_assert(dragged_te->drag_data->insert_handle == insert_handle &&
dragged_te->drag_data->insert_type == insert_type);
- dragged_te->reinsert(bmain, scene, dragged_te, insert_handle, insert_type);
+ dragged_te->reinsert(bmain, dragged_te, insert_handle, insert_type);
return true;
}
@@ -188,7 +188,6 @@ static bool outliner_item_drag_drop_apply(Main *bmain, const Scene *scene, TreeE
static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
ARegion *ar = CTX_wm_region(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
TreeElement *te_dragged = op->customdata;
@@ -199,7 +198,7 @@ static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEv
switch (event->type) {
case EVT_MODAL_MAP:
if (event->val == OUTLINER_ITEM_DRAG_CONFIRM) {
- if (outliner_item_drag_drop_apply(bmain, scene, te_dragged)) {
+ if (outliner_item_drag_drop_apply(bmain, te_dragged)) {
skip_rebuild = false;
}
retval = OPERATOR_FINISHED;
@@ -215,7 +214,7 @@ static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEv
redraw = true;
break;
case MOUSEMOVE:
- outliner_item_drag_handle(scene, soops, ar, event, te_dragged);
+ outliner_item_drag_handle(soops, ar, event, te_dragged);
redraw = true;
break;
}
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 5215efaa05c..08b5f337936 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -44,6 +44,7 @@
#include "BLI_listbase.h"
#include "BKE_context.h"
+#include "BKE_group.h"
#include "BKE_object.h"
#include "BKE_layer.h"
#include "BKE_scene.h"
@@ -780,12 +781,23 @@ static eOLDrawState tree_element_active_collection(
/* don't allow selecting a scene collection, it can have multiple layer collection
* instances (which one would the user want to be selected then?) */
else if (tselem->type == TSE_LAYER_COLLECTION) {
- ViewLayer *view_layer = CTX_data_view_layer(C);
- LayerCollection *lc = te->directdata;
- const int collection_index = BKE_layer_collection_findindex(view_layer, lc);
+ LayerCollection *layer_collection = te->directdata;
+
+ switch (layer_collection->scene_collection->type) {
+ case COLLECTION_TYPE_NONE:
+ case COLLECTION_TYPE_GROUP_INTERNAL:
+ {
+ ViewLayer *view_layer = BKE_view_layer_find_from_collection(tselem->id, layer_collection);
+ const int collection_index = BKE_layer_collection_findindex(view_layer, layer_collection);
- BLI_assert(collection_index >= 0);
- view_layer->active_collection = collection_index;
+ if (collection_index > -1) {
+ view_layer->active_collection = collection_index;
+ }
+ break;
+ }
+ default:
+ BLI_assert(!"Collection type not fully implemented");
+ }
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
}
@@ -906,26 +918,30 @@ static void do_outliner_item_activate_tree_element(
}
else if (te->idcode == ID_GR) {
Group *gr = (Group *)tselem->id;
- GroupObject *gob;
if (extend) {
int sel = BA_SELECT;
- for (gob = gr->gobject.first; gob; gob = gob->next) {
- if (gob->ob->flag & SELECT) {
+ FOREACH_GROUP_BASE(gr, base)
+ {
+ if (base->flag & BASE_SELECTED) {
sel = BA_DESELECT;
break;
}
}
+ FOREACH_GROUP_BASE_END
- for (gob = gr->gobject.first; gob; gob = gob->next) {
- ED_object_base_select(BKE_view_layer_base_find(view_layer, gob->ob), sel);
+ FOREACH_GROUP_OBJECT(gr, object)
+ {
+ ED_object_base_select(BKE_view_layer_base_find(view_layer, object), sel);
}
+ FOREACH_GROUP_OBJECT_END
}
else {
BKE_view_layer_base_deselect_all(view_layer);
- for (gob = gr->gobject.first; gob; gob = gob->next) {
- Base *base = BKE_view_layer_base_find(view_layer, gob->ob);
+ FOREACH_GROUP_OBJECT(gr, object)
+ {
+ Base *base = BKE_view_layer_base_find(view_layer, object);
/* Object may not be in this scene */
if (base != NULL) {
if ((base->flag & BASE_SELECTED) == 0) {
@@ -933,6 +949,7 @@ static void do_outliner_item_activate_tree_element(
}
}
}
+ FOREACH_GROUP_OBJECT_END
}
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 63e1a527138..99fd539293f 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -525,20 +525,21 @@ static void group_linkobs2scene_cb(
ViewLayer *view_layer = CTX_data_view_layer(C);
SceneCollection *sc = CTX_data_scene_collection(C);
Group *group = (Group *)tselem->id;
- GroupObject *gob;
Base *base;
- for (gob = group->gobject.first; gob; gob = gob->next) {
- base = BKE_view_layer_base_find(view_layer, gob->ob);
+ FOREACH_GROUP_OBJECT(group, object)
+ {
+ base = BKE_view_layer_base_find(view_layer, object);
if (!base) {
/* link to scene */
- BKE_collection_object_add(scene, sc, gob->ob);
- base = BKE_view_layer_base_find(view_layer, gob->ob);
- id_us_plus(&gob->ob->id);
+ BKE_collection_object_add(&scene->id, sc, object);
+ base = BKE_view_layer_base_find(view_layer, object);
+ id_us_plus(&object->id);
}
base->flag |= BASE_SELECTED;
}
+ FOREACH_GROUP_OBJECT_END
}
static void group_instance_cb(
@@ -663,6 +664,7 @@ typedef enum eOutliner_PropCollectionOps {
OL_COLLECTION_OP_COLLECTION_NEW,
OL_COLLECTION_OP_COLLECTION_DEL,
OL_COLLECTION_OP_COLLECTION_UNLINK,
+ OL_COLLECTION_OP_GROUP_CREATE,
} eOutliner_PropCollectionOps;
static void pchan_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *UNUSED(arg))
@@ -820,12 +822,13 @@ static void collection_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tsel
bContext *C = (bContext *)Carg;
Scene *scene = CTX_data_scene(C);
LayerCollection *lc = te->directdata;
+ ID *id = te->store_elem->id;
SceneCollection *sc = lc->scene_collection;
if (event == OL_COLLECTION_OP_OBJECTS_ADD) {
CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
{
- BKE_collection_object_add(scene, sc, ob);
+ BKE_collection_object_add(id, sc, ob);
}
CTX_DATA_END;
@@ -836,7 +839,7 @@ static void collection_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tsel
CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
{
- BKE_collection_object_remove(bmain, scene, sc, ob, true);
+ BKE_collection_object_remove(bmain, id, sc, ob, true);
}
CTX_DATA_END;
@@ -844,7 +847,13 @@ static void collection_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tsel
te->store_elem->flag &= ~TSE_SELECTED;
}
else if (event == OL_COLLECTION_OP_COLLECTION_NEW) {
- BKE_collection_add(scene, sc, NULL);
+ if (GS(id->name) == ID_GR) {
+ BKE_collection_add(id, sc, COLLECTION_TYPE_GROUP_INTERNAL, NULL);
+ }
+ else {
+ BLI_assert(GS(id->name) == ID_SCE);
+ BKE_collection_add(id, sc, COLLECTION_TYPE_NONE, NULL);
+ }
WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
}
else if (event == OL_COLLECTION_OP_COLLECTION_UNLINK) {
@@ -861,7 +870,7 @@ static void collection_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tsel
}
}
else if (event == OL_COLLECTION_OP_COLLECTION_DEL) {
- if (BKE_collection_remove(scene, sc)) {
+ if (BKE_collection_remove(id, sc)) {
DEG_relations_tag_update(CTX_data_main(C));
WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
}
@@ -870,6 +879,17 @@ static void collection_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tsel
TODO_LAYER_OPERATORS; /* this shouldn't be in the menu in those cases */
}
}
+ else if (event == OL_COLLECTION_OP_GROUP_CREATE) {
+ Main *bmain = CTX_data_main(C);
+ BKE_collection_group_create(bmain, scene, lc);
+ DEG_relations_tag_update(bmain);
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DEG_id_tag_update(&scene->id, 0);
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+ }
+ else {
+ BLI_assert(!"Collection operation not fully implemented!");
+ }
}
static void outliner_do_data_operation(SpaceOops *soops, int type, int event, ListBase *lb,
@@ -1794,15 +1814,39 @@ void OUTLINER_OT_modifier_operation(wmOperatorType *ot)
/* ******************** */
-static EnumPropertyItem prop_collection_op_types[] = {
- {OL_COLLECTION_OP_OBJECTS_ADD, "OBJECTS_ADD", ICON_ZOOMIN, "Add Selected", "Add selected objects to collection"},
- {OL_COLLECTION_OP_OBJECTS_REMOVE, "OBJECTS_REMOVE", ICON_X, "Remove Selected", "Remove selected objects from collection"},
- {OL_COLLECTION_OP_COLLECTION_NEW, "COLLECTION_NEW", ICON_NEW, "New Collection", "Add a new nested collection"},
- {OL_COLLECTION_OP_COLLECTION_UNLINK, "COLLECTION_UNLINK", ICON_UNLINKED, "Unlink", "Unlink collection"},
- {OL_COLLECTION_OP_COLLECTION_DEL, "COLLECTION_DEL", ICON_X, "Delete Collection", "Delete the collection"},
- {0, NULL, 0, NULL, NULL}
+static EnumPropertyItem prop_collection_op_none_types[] = {
+ {OL_COLLECTION_OP_OBJECTS_ADD, "OBJECTS_ADD", ICON_ZOOMIN, "Add Selected", "Add selected objects to collection"},
+ {OL_COLLECTION_OP_OBJECTS_REMOVE, "OBJECTS_REMOVE", ICON_X, "Remove Selected", "Remove selected objects from collection"},
+ {OL_COLLECTION_OP_COLLECTION_NEW, "COLLECTION_NEW", ICON_NEW, "New Collection", "Add a new nested collection"},
+ {OL_COLLECTION_OP_COLLECTION_UNLINK, "COLLECTION_UNLINK", ICON_UNLINKED, "Unlink", "Unlink collection"},
+ {OL_COLLECTION_OP_COLLECTION_DEL, "COLLECTION_DEL", ICON_X, "Delete Collection", "Delete the collection"},
+ {OL_COLLECTION_OP_GROUP_CREATE, "GROUP_CREATE", ICON_GROUP, "Create Group", "Turn the collection into a group collection"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static EnumPropertyItem prop_collection_op_group_internal_types[] = {
+ {OL_COLLECTION_OP_OBJECTS_ADD, "OBJECTS_ADD", ICON_ZOOMIN, "Add Selected", "Add selected objects to collection"},
+ {OL_COLLECTION_OP_OBJECTS_REMOVE, "OBJECTS_REMOVE", ICON_X, "Remove Selected", "Remove selected objects from collection"},
+ {OL_COLLECTION_OP_COLLECTION_NEW, "COLLECTION_NEW", ICON_NEW, "New Collection", "Add a new nested collection"},
+ {OL_COLLECTION_OP_COLLECTION_DEL, "COLLECTION_DEL", ICON_X, "Delete Collection", "Delete the collection"},
+ {0, NULL, 0, NULL, NULL}
};
+static const EnumPropertyItem *outliner_collection_operation_type_itemf(
+ bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ *r_free = false;
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+
+ switch (soops->outlinevis) {
+ case SO_GROUPS:
+ return prop_collection_op_group_internal_types;
+ case SO_ACT_LAYER:
+ return prop_collection_op_none_types;
+ }
+ return NULL;
+}
+
static int outliner_collection_operation_exec(bContext *C, wmOperator *op)
{
SpaceOops *soops = CTX_wm_space_outliner(C);
@@ -1823,6 +1867,8 @@ static int outliner_collection_operation_exec(bContext *C, wmOperator *op)
void OUTLINER_OT_collection_operation(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Outliner Collection Operation";
ot->idname = "OUTLINER_OT_collection_operation";
@@ -1835,7 +1881,10 @@ void OUTLINER_OT_collection_operation(wmOperatorType *ot)
ot->flag = 0;
- ot->prop = RNA_def_enum(ot->srna, "type", prop_collection_op_types, 0, "Collection Operation", "");
+ prop = RNA_def_enum(ot->srna, "type", DummyRNA_NULL_items, 0, "Collection Operation", "");
+ RNA_def_enum_funcs(prop, outliner_collection_operation_type_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
/* ******************** */
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 1ab715d0246..a9c9ab74970 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -88,6 +88,8 @@
#endif
/* prototypes */
+static void outliner_add_layer_collections_recursive(
+ SpaceOops *soops, ListBase *tree, ID *id, ListBase *layer_collections, TreeElement *parent_ten);
static void outliner_make_hierarchy(ListBase *lb);
/* ********************************************************* */
@@ -386,13 +388,14 @@ static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *s
}
static void outliner_object_reorder(
- Main *UNUSED(bmain), const Scene *scene,
+ Main *UNUSED(bmain),
TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action)
{
TreeStoreElem *tselem_insert = TREESTORE(insert_element);
Object *ob = (Object *)tselem_insert->id;
SceneCollection *sc = outliner_scene_collection_from_tree_element(insert_handle);
SceneCollection *sc_ob_parent = NULL;
+ ID *id = insert_handle->store_elem->id;
BLI_assert(action == TE_INSERT_INTO);
UNUSED_VARS_NDEBUG(action);
@@ -407,13 +410,13 @@ static void outliner_object_reorder(
}
}
else {
- sc_ob_parent = BKE_collection_master(scene);
+ sc_ob_parent = BKE_collection_master(id);
}
- BKE_collection_object_move(scene, sc, sc_ob_parent, ob);
+ BKE_collection_object_move(id, sc, sc_ob_parent, ob);
}
static bool outliner_object_reorder_poll(
- const Scene *UNUSED(scene), const TreeElement *insert_element,
+ const TreeElement *insert_element,
TreeElement **io_insert_handle, TreeElementInsertType *io_action)
{
TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle);
@@ -861,7 +864,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
}
/* exceptions */
- if (ELEM(type, TSE_ID_BASE, TSE_LAYER_COLLECTION)) {
+ if (type == TSE_ID_BASE) {
/* pass */
}
else if (id == NULL) {
@@ -1199,6 +1202,11 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
te->flag |= TE_LAZY_CLOSED;
}
+ if ((type != TSE_LAYER_COLLECTION) && GS(id->name) == ID_GR) {
+ Group *group = (Group *)id;
+ outliner_add_layer_collections_recursive(soops, &te->subtree, id, &group->view_layer->layer_collections, NULL);
+ }
+
return te;
}
@@ -1349,20 +1357,21 @@ static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops)
}
static void outliner_layer_collections_reorder(
- Main *bmain, const Scene *scene,
+ Main *bmain,
TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action)
{
LayerCollection *lc_insert = insert_element->directdata;
LayerCollection *lc_handle = insert_handle->directdata;
+ ID *id = insert_element->store_elem->id;
if (action == TE_INSERT_BEFORE) {
- BKE_layer_collection_move_above(scene, lc_handle, lc_insert);
+ BKE_layer_collection_move_above(id, lc_handle, lc_insert);
}
else if (action == TE_INSERT_AFTER) {
- BKE_layer_collection_move_below(scene, lc_handle, lc_insert);
+ BKE_layer_collection_move_below(id, lc_handle, lc_insert);
}
else if (action == TE_INSERT_INTO) {
- BKE_layer_collection_move_into(scene, lc_handle, lc_insert);
+ BKE_layer_collection_move_into(id, lc_handle, lc_insert);
}
else {
BLI_assert(0);
@@ -1371,25 +1380,30 @@ static void outliner_layer_collections_reorder(
DEG_relations_tag_update(bmain);
}
static bool outliner_layer_collections_reorder_poll(
- const Scene *UNUSED(scene), const TreeElement *UNUSED(insert_element),
+ const TreeElement *insert_element,
TreeElement **io_insert_handle, TreeElementInsertType *UNUSED(io_action))
{
const TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle);
+
+ if (tselem_handle->id != insert_element->store_elem->id) {
+ return false;
+ }
+
return ELEM(tselem_handle->type, TSE_LAYER_COLLECTION);
}
static void outliner_add_layer_collections_recursive(
- SpaceOops *soops, ListBase *tree, ListBase *layer_collections, TreeElement *parent_ten)
+ SpaceOops *soops, ListBase *tree, ID *id, ListBase *layer_collections, TreeElement *parent_ten)
{
for (LayerCollection *collection = layer_collections->first; collection; collection = collection->next) {
- TreeElement *ten = outliner_add_element(soops, tree, collection, parent_ten, TSE_LAYER_COLLECTION, 0);
+ TreeElement *ten = outliner_add_element(soops, tree, id, parent_ten, TSE_LAYER_COLLECTION, 0);
ten->name = collection->scene_collection->name;
ten->directdata = collection;
ten->reinsert = outliner_layer_collections_reorder;
ten->reinsert_poll = outliner_layer_collections_reorder_poll;
- outliner_add_layer_collections_recursive(soops, &ten->subtree, &collection->layer_collections, ten);
+ outliner_add_layer_collections_recursive(soops, &ten->subtree, id, &collection->layer_collections, ten);
for (LinkData *link = collection->object_bases.first; link; link = link->next) {
Base *base = (Base *)link->data;
TreeElement *te_object = outliner_add_element(soops, &ten->subtree, base->object, ten, 0, 0);
@@ -1398,27 +1412,29 @@ static void outliner_add_layer_collections_recursive(
outliner_make_hierarchy(&ten->subtree);
}
}
-static void outliner_add_collections_act_layer(SpaceOops *soops, ViewLayer *layer)
+static void outliner_add_collections_act_layer(SpaceOops *soops, Scene *scene, ViewLayer *layer)
{
- outliner_add_layer_collections_recursive(soops, &soops->tree, &layer->layer_collections, NULL);
+ outliner_add_layer_collections_recursive(soops, &soops->tree, &scene->id, &layer->layer_collections, NULL);
}
static void outliner_scene_collections_reorder(
- Main *bmain, const Scene *scene,
+ Main *bmain,
TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action)
{
SceneCollection *sc_insert = insert_element->directdata;
SceneCollection *sc_handle = insert_handle->directdata;
+ ID *id = insert_handle->store_elem->id;
+ BLI_assert(id == insert_element->store_elem->id);
- BLI_assert((action == TE_INSERT_INTO) || (sc_handle != BKE_collection_master(scene)));
+ BLI_assert((action == TE_INSERT_INTO) || (sc_handle != BKE_collection_master(id)));
if (action == TE_INSERT_BEFORE) {
- BKE_collection_move_above(scene, sc_handle, sc_insert);
+ BKE_collection_move_above(id, sc_handle, sc_insert);
}
else if (action == TE_INSERT_AFTER) {
- BKE_collection_move_below(scene, sc_handle, sc_insert);
+ BKE_collection_move_below(id, sc_handle, sc_insert);
}
else if (action == TE_INSERT_INTO) {
- BKE_collection_move_into(scene, sc_handle, sc_insert);
+ BKE_collection_move_into(id, sc_handle, sc_insert);
}
else {
BLI_assert(0);
@@ -1427,17 +1443,23 @@ static void outliner_scene_collections_reorder(
DEG_relations_tag_update(bmain);
}
static bool outliner_scene_collections_reorder_poll(
- const Scene *scene, const TreeElement *UNUSED(insert_element),
+ const TreeElement *insert_element,
TreeElement **io_insert_handle, TreeElementInsertType *io_action)
{
const TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle);
- SceneCollection *sc_master = BKE_collection_master(scene);
- SceneCollection *sc_handle = (*io_insert_handle)->directdata;
+ ID *id = tselem_handle->id;
+
+ if (id != insert_element->store_elem->id) {
+ return false;
+ }
if (!ELEM(tselem_handle->type, TSE_SCENE_COLLECTION)) {
return false;
}
+ SceneCollection *sc_master = BKE_collection_master(id);
+ SceneCollection *sc_handle = (*io_insert_handle)->directdata;
+
if (sc_handle == sc_master) {
/* exception: Can't insert before/after master selection, has to be one of its childs */
TreeElement *te_master = *io_insert_handle;
@@ -1478,7 +1500,7 @@ static void outliner_add_scene_collections_recursive(
}
static void outliner_add_collections_master(SpaceOops *soops, Scene *scene)
{
- SceneCollection *master = BKE_collection_master(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);
}
@@ -1851,19 +1873,9 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa
}
else if (soops->outlinevis == SO_GROUPS) {
Group *group;
- GroupObject *go;
-
for (group = mainvar->group.first; group; group = group->id.next) {
- if (group->gobject.first) {
- te = outliner_add_element(soops, &soops->tree, group, NULL, 0, 0);
-
- for (go = group->gobject.first; go; go = go->next) {
- outliner_add_element(soops, &te->subtree, go->ob, te, 0, 0);
- }
- outliner_make_hierarchy(&te->subtree);
- /* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */
- for (go = group->gobject.first; go; go = go->next) go->ob->id.newid = NULL;
- }
+ te = outliner_add_element(soops, &soops->tree, group, NULL, 0, 0);
+ outliner_make_hierarchy(&te->subtree);
}
}
else if (soops->outlinevis == SO_SAME_TYPE) {
@@ -1940,7 +1952,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa
outliner_add_orphaned_datablocks(mainvar, soops);
}
else if (soops->outlinevis == SO_ACT_LAYER) {
- outliner_add_collections_act_layer(soops, view_layer);
+ outliner_add_collections_act_layer(soops, scene, view_layer);
}
else if (soops->outlinevis == SO_COLLECTIONS) {
outliner_add_collections_master(soops, scene);
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index ffaa259ab6f..1bc1a227a03 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -125,7 +125,8 @@ static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *e
*/
if (!scene) {
return 1;
- } else {
+ }
+ else {
for (ViewLayer *view_layer = scene->view_layers.first;
view_layer;
view_layer = view_layer->next)
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 399e76e71b8..04dbab0b853 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -157,6 +157,7 @@ void color3ubv_from_seq(Scene *curscene, Sequence *seq, unsigned char col[3])
case SEQ_TYPE_MULTICAM:
case SEQ_TYPE_ADJUSTMENT:
case SEQ_TYPE_GAUSSIAN_BLUR:
+ case SEQ_TYPE_COLORMIX:
UI_GetThemeColor3ubv(TH_SEQ_EFFECT, col);
/* slightly offset hue to distinguish different effects */
@@ -171,6 +172,7 @@ void color3ubv_from_seq(Scene *curscene, Sequence *seq, unsigned char col[3])
else if (seq->type == SEQ_TYPE_MULTICAM) rgb_byte_set_hue_float_offset(col, 0.32);
else if (seq->type == SEQ_TYPE_ADJUSTMENT) rgb_byte_set_hue_float_offset(col, 0.40);
else if (seq->type == SEQ_TYPE_GAUSSIAN_BLUR) rgb_byte_set_hue_float_offset(col, 0.42);
+ else if (seq->type == SEQ_TYPE_COLORMIX) rgb_byte_set_hue_float_offset(col, 0.46);
break;
case SEQ_TYPE_COLOR:
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index a8a5bc6e96b..8f6eb064b0d 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -95,6 +95,7 @@ EnumPropertyItem sequencer_prop_effect_types[] = {
{SEQ_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
{SEQ_TYPE_GAUSSIAN_BLUR, "GAUSSIAN_BLUR", 0, "Gaussian Blur", ""},
{SEQ_TYPE_TEXT, "TEXT", 0, "Text", ""},
+ {SEQ_TYPE_COLORMIX, "COLORMIX", 0, "Color Mix", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -694,7 +695,7 @@ static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, int cutframe)
BKE_sequence_calc(scene, seq);
}
- if ((seq->startstill) && (cutframe < seq->start)) {
+ if ((seq->startstill) && (cutframe <= seq->start)) {
/* don't do funny things with METAs ... */
if (seq->type == SEQ_TYPE_META) {
skip_dup = true;
@@ -708,13 +709,15 @@ static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, int cutframe)
}
}
/* normal strip */
- else if ((cutframe >= seq->start) && (cutframe <= (seq->start + seq->len))) {
+ else if ((cutframe >= seq->start) && (cutframe < (seq->start + seq->len))) {
seq->endofs = 0;
seq->endstill = 0;
seq->anim_endofs += (seq->start + seq->len) - cutframe;
}
/* strips with extended stillframes after */
- else if (((seq->start + seq->len) < cutframe) && (seq->endstill)) {
+ else if (((seq->start + seq->len) == cutframe) ||
+ (((seq->start + seq->len) < cutframe) && (seq->endstill)))
+ {
seq->endstill -= seq->enddisp - cutframe;
/* don't do funny things with METAs ... */
if (seq->type == SEQ_TYPE_META) {
@@ -743,7 +746,7 @@ static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, int cutframe)
}
/* normal strip */
- else if ((cutframe >= seqn->start) && (cutframe <= (seqn->start + seqn->len))) {
+ else if ((cutframe >= seqn->start) && (cutframe < (seqn->start + seqn->len))) {
seqn->start = cutframe;
seqn->startstill = 0;
seqn->startofs = 0;
@@ -754,7 +757,9 @@ static Sequence *cut_seq_hard(Scene *scene, Sequence *seq, int cutframe)
}
/* strips with extended stillframes after */
- else if (((seqn->start + seqn->len) < cutframe) && (seqn->endstill)) {
+ else if (((seqn->start + seqn->len) == cutframe) ||
+ (((seqn->start + seqn->len) < cutframe) && (seqn->endstill)))
+ {
seqn->start = cutframe;
seqn->startofs = 0;
seqn->anim_startofs += ts.len - 1;
@@ -790,7 +795,7 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe)
/* First Strip! */
/* strips with extended stillfames before */
- if ((seq->startstill) && (cutframe < seq->start)) {
+ if ((seq->startstill) && (cutframe <= seq->start)) {
/* don't do funny things with METAs ... */
if (seq->type == SEQ_TYPE_META) {
skip_dup = true;
@@ -804,11 +809,13 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe)
}
}
/* normal strip */
- else if ((cutframe >= seq->start) && (cutframe <= (seq->start + seq->len))) {
+ else if ((cutframe >= seq->start) && (cutframe < (seq->start + seq->len))) {
seq->endofs = (seq->start + seq->len) - cutframe;
}
/* strips with extended stillframes after */
- else if (((seq->start + seq->len) < cutframe) && (seq->endstill)) {
+ else if (((seq->start + seq->len) == cutframe) ||
+ (((seq->start + seq->len) < cutframe) && (seq->endstill)))
+ {
seq->endstill -= seq->enddisp - cutframe;
/* don't do funny things with METAs ... */
if (seq->type == SEQ_TYPE_META) {
@@ -834,9 +841,9 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe)
seqn->endofs = ts.endofs;
seqn->endstill = ts.endstill;
}
-
+
/* normal strip */
- else if ((cutframe >= seqn->start) && (cutframe <= (seqn->start + seqn->len))) {
+ if ((cutframe >= seqn->start) && (cutframe < (seqn->start + seqn->len))) {
seqn->startstill = 0;
seqn->startofs = cutframe - ts.start;
seqn->endofs = ts.endofs;
@@ -844,7 +851,9 @@ static Sequence *cut_seq_soft(Scene *scene, Sequence *seq, int cutframe)
}
/* strips with extended stillframes after */
- else if (((seqn->start + seqn->len) < cutframe) && (seqn->endstill)) {
+ else if (((seqn->start + seqn->len) == cutframe) ||
+ (((seqn->start + seqn->len) < cutframe) && (seqn->endstill)))
+ {
seqn->start = cutframe - ts.len + 1;
seqn->startofs = ts.len - 1;
seqn->endstill = ts.enddisp - cutframe - 1;
diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c
index 99ac0d9024c..283dbf3b4e2 100644
--- a/source/blender/editors/space_time/space_time.c
+++ b/source/blender/editors/space_time/space_time.c
@@ -58,6 +58,9 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_message.h"
+
+#include "RNA_access.h"
#include "BIF_gl.h"
@@ -649,6 +652,47 @@ static void time_main_region_listener(
}
}
+static void time_main_region_message_subscribe(
+ const struct bContext *UNUSED(C),
+ struct WorkSpace *UNUSED(workspace), struct Scene *scene,
+ struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar,
+ struct wmMsgBus *mbus)
+{
+ PointerRNA ptr;
+ RNA_pointer_create(&screen->id, &RNA_SpaceTimeline, sa->spacedata.first, &ptr);
+
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+
+ /* Timeline depends on scene properties. */
+ {
+ bool use_preview = (scene->r.flag & SCER_PRV_RANGE);
+ extern PropertyRNA rna_Scene_frame_start;
+ extern PropertyRNA rna_Scene_frame_end;
+ extern PropertyRNA rna_Scene_frame_preview_start;
+ extern PropertyRNA rna_Scene_frame_preview_end;
+ extern PropertyRNA rna_Scene_use_preview_range;
+ extern PropertyRNA rna_Scene_frame_current;
+ const PropertyRNA *props[] = {
+ use_preview ? &rna_Scene_frame_preview_start : &rna_Scene_frame_start,
+ use_preview ? &rna_Scene_frame_preview_end : &rna_Scene_frame_end,
+ &rna_Scene_use_preview_range,
+ &rna_Scene_frame_current,
+ };
+
+ PointerRNA idptr;
+ RNA_id_pointer_create(&scene->id, &idptr);
+
+ for (int i = 0; i < ARRAY_SIZE(props); i++) {
+ WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_region_tag_redraw, __func__);
+ }
+ }
+}
+
+
/* ************************ header time area region *********************** */
/* add handlers, stuff you only do once or on area/region changes */
@@ -797,6 +841,7 @@ void ED_spacetype_time(void)
art->init = time_main_region_init;
art->draw = time_main_region_draw;
art->listener = time_main_region_listener;
+ art->message_subscribe = time_main_region_message_subscribe;
art->keymap = time_keymap;
art->lock = 1; /* Due to pointcache, see T4960. */
BLI_addhead(&st->regiontypes, art);
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 3e7e617bd0e..08ef9cc21cb 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -9458,6 +9458,8 @@ static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *dm, int offset)
#else
static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *UNUSED(dm), int offset)
{
+ glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
+
Mesh *me = em->ob->data;
Gwn_Batch *batch = DRW_mesh_batch_cache_get_verts_with_select_id(me, offset);
GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32);
@@ -9497,7 +9499,7 @@ static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *dm, int offset)
immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR_U32);
- glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
+ glLineWidth(1.0f);
immBeginAtMost(GWN_PRIM_LINES, imm_len);
dm->foreachMappedEdge(dm, bbs_mesh_wire__mapFunc, &data);
@@ -9508,7 +9510,7 @@ static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *dm, int offset)
#else
static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *UNUSED(dm), int offset)
{
- glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
+ glLineWidth(1.0f);
Mesh *me = em->ob->data;
Gwn_Batch *batch = DRW_mesh_batch_cache_get_edges_with_select_id(me, offset);
@@ -9772,9 +9774,11 @@ void draw_object_backbufsel(
ED_view3d_polygon_offset(rv3d, 1.0);
- /* we draw edges always, for loop (select) tools */
- bbs_mesh_wire(em, dm, bm_solidoffs);
- bm_wireoffs = bm_solidoffs + em->bm->totedge;
+ /* we draw edges if edge select mode */
+ if (ts->selectmode & SCE_SELECT_EDGE) {
+ bbs_mesh_wire(em, dm, bm_solidoffs);
+ bm_wireoffs = bm_solidoffs + em->bm->totedge;
+ }
/* we draw verts if vert select mode. */
if (ts->selectmode & SCE_SELECT_VERTEX) {
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index f138b014d03..7cf1573de43 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -67,6 +67,7 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_message.h"
#include "RE_engine.h"
#include "RE_pipeline.h"
@@ -1038,6 +1039,75 @@ static void view3d_main_region_listener(
}
}
+static void view3d_main_region_message_subscribe(
+ const struct bContext *UNUSED(C),
+ struct WorkSpace *workspace, struct Scene *scene,
+ struct bScreen *UNUSED(screen), struct ScrArea *UNUSED(sa), struct ARegion *ar,
+ struct wmMsgBus *mbus)
+{
+ /* Developer note: there are many properties that impact 3D view drawing,
+ * so instead of subscribing to individual properties, just subscribe to types
+ * accepting some redundant redraws.
+ *
+ * For other space types we might try avoid this, keep the 3D view as an exceptional case! */
+ ViewRender *view_render = BKE_viewrender_get(scene, workspace);
+ wmMsgParams_RNA msg_key_params = {0};
+
+ /* Only subscribe to types. */
+ StructRNA *type_array[] = {
+ /* These object have properties that impact drawing. */
+ &RNA_AreaLamp,
+ &RNA_Camera,
+ &RNA_Lamp,
+ &RNA_Speaker,
+ &RNA_SunLamp,
+
+ /* General types the 3D view depends on. */
+ &RNA_Object,
+ &RNA_UnitSettings, /* grid-floor */
+
+ &RNA_ViewRenderSettings,
+ &RNA_World,
+ };
+
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
+ msg_key_params.ptr.type = type_array[i];
+ WM_msg_subscribe_rna_params(
+ mbus,
+ &msg_key_params,
+ &msg_sub_value_region_tag_redraw,
+ __func__);
+ }
+
+ /* Subscribe to a handful of other properties. */
+ RegionView3D *rv3d = ar->regiondata;
+
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_x, &msg_sub_value_region_tag_redraw);
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_y, &msg_sub_value_region_tag_redraw);
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_x, &msg_sub_value_region_tag_redraw);
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_y, &msg_sub_value_region_tag_redraw);
+ if (rv3d->persp == RV3D_CAMOB) {
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, use_border, &msg_sub_value_region_tag_redraw);
+ }
+
+ /* Each engine could be responsible for its own engine data types.
+ * For now this is simplest. */
+ if (STREQ(view_render->engine_id, RE_engine_id_BLENDER_EEVEE)) {
+ extern StructRNA RNA_ViewLayerEngineSettingsEevee;
+ WM_msg_subscribe_rna_anon_type(mbus, ViewLayerEngineSettingsEevee, &msg_sub_value_region_tag_redraw);
+ }
+ else if (STREQ(view_render->engine_id, RE_engine_id_BLENDER_CLAY)) {
+ extern StructRNA RNA_ViewLayerEngineSettingsClay;
+ WM_msg_subscribe_rna_anon_type(mbus, ViewLayerEngineSettingsClay, &msg_sub_value_region_tag_redraw);
+ }
+}
+
/* concept is to retrieve cursor type context-less */
static void view3d_main_region_cursor(wmWindow *win, ScrArea *UNUSED(sa), ARegion *UNUSED(ar))
{
@@ -1379,6 +1449,7 @@ void ED_spacetype_view3d(void)
art->free = view3d_main_region_free;
art->duplicate = view3d_main_region_duplicate;
art->listener = view3d_main_region_listener;
+ art->message_subscribe = view3d_main_region_message_subscribe;
art->cursor = view3d_main_region_cursor;
art->lock = 1; /* can become flag, see BKE_spacedata_draw_locks */
BLI_addhead(&st->regiontypes, art);
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 8024a733f40..6ea2ff10af2 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -90,6 +90,8 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "RNA_access.h"
+
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -1931,8 +1933,8 @@ static void view3d_stereo3d_setup_offscreen(
void ED_view3d_draw_offscreen_init(const EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, View3D *v3d)
{
- RenderEngineType *type = eval_ctx->engine;
- if (type->flag & RE_USE_LEGACY_PIPELINE) {
+ RenderEngineType *engine_type = eval_ctx->engine_type;
+ if (engine_type->flag & RE_USE_LEGACY_PIPELINE) {
/* shadow buffers, before we setup matrices */
if (draw_glsl_material(scene, view_layer, NULL, v3d, v3d->drawtype)) {
VP_deprecated_gpu_update_lamps_shadows_world(eval_ctx, scene, v3d);
@@ -2014,8 +2016,8 @@ void ED_view3d_draw_offscreen(
view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, winmat, NULL);
/* main drawing call */
- RenderEngineType *type = eval_ctx->engine;
- if (type->flag & RE_USE_LEGACY_PIPELINE) {
+ RenderEngineType *engine_type = eval_ctx->engine_type;
+ if (engine_type->flag & RE_USE_LEGACY_PIPELINE) {
/* framebuffer fx needed, we need to draw offscreen first */
if (v3d->fx_settings.fx_flag && fx) {
@@ -2058,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, ar, v3d, ofs);
+ DRW_draw_render_loop_offscreen(depsgraph, eval_ctx->engine_type, ar, v3d, ofs);
}
/* restore size */
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_camera.c b/source/blender/editors/space_view3d/view3d_manipulator_camera.c
index a4d408eedc6..d020571930a 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_camera.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_camera.c
@@ -45,6 +45,7 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_message.h"
#include "view3d_intern.h" /* own include */
@@ -217,6 +218,55 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmManipulatorGroup *mg
}
+static void WIDGETGROUP_camera_message_subscribe(
+ const bContext *C, wmManipulatorGroup *mgroup, struct wmMsgBus *mbus)
+{
+ ARegion *ar = CTX_wm_region(C);
+ Object *ob = CTX_data_active_object(C);
+ Camera *ca = ob->data;
+
+ wmMsgSubscribeValue msg_sub_value_mpr_tag_refresh = {
+ .owner = ar,
+ .user_data = mgroup->parent_mmap,
+ .notify = WM_manipulator_do_msg_notify_tag_refresh,
+ };
+
+ {
+ extern PropertyRNA rna_Camera_dof_distance;
+ extern PropertyRNA rna_Camera_draw_size;
+ extern PropertyRNA rna_Camera_ortho_scale;
+ extern PropertyRNA rna_Camera_sensor_fit;
+ extern PropertyRNA rna_Camera_sensor_width;
+ extern PropertyRNA rna_Camera_shift_x;
+ extern PropertyRNA rna_Camera_shift_y;
+ extern PropertyRNA rna_Camera_type;
+ const PropertyRNA *props[] = {
+ &rna_Camera_dof_distance,
+ &rna_Camera_draw_size,
+ &rna_Camera_ortho_scale,
+ &rna_Camera_sensor_fit,
+ &rna_Camera_sensor_width,
+ &rna_Camera_shift_x,
+ &rna_Camera_shift_y,
+ &rna_Camera_type,
+ };
+
+ PointerRNA idptr;
+ RNA_id_pointer_create(&ca->id, &idptr);
+
+ for (int i = 0; i < ARRAY_SIZE(props); i++) {
+ WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_mpr_tag_refresh, __func__);
+ }
+ }
+
+ /* Subscribe to render settings */
+ {
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_x, &msg_sub_value_mpr_tag_refresh);
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, resolution_y, &msg_sub_value_mpr_tag_refresh);
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_x, &msg_sub_value_mpr_tag_refresh);
+ WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, pixel_aspect_y, &msg_sub_value_mpr_tag_refresh);
+ }
+}
void VIEW3D_WGT_camera(wmManipulatorGroupType *wgt)
{
@@ -230,6 +280,7 @@ void VIEW3D_WGT_camera(wmManipulatorGroupType *wgt)
wgt->poll = WIDGETGROUP_camera_poll;
wgt->setup = WIDGETGROUP_camera_setup;
wgt->refresh = WIDGETGROUP_camera_refresh;
+ wgt->message_subscribe = WIDGETGROUP_camera_message_subscribe;
}
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c
index 0495d1d696c..230b4f44c16 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c
@@ -272,7 +272,7 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state)
}
else if (state == RULER_STATE_DRAG) {
ruler_info->snap_context = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C), CTX_data_scene(C), CTX_data_view_layer(C), CTX_data_engine(C), 0,
+ CTX_data_main(C), CTX_data_scene(C), CTX_data_view_layer(C), CTX_data_engine_type(C), 0,
ruler_info->ar, CTX_wm_view3d(C));
}
else {
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index 568343f8ec8..79fa9e14dc1 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -46,6 +46,7 @@
#include "BKE_appdir.h"
#include "BKE_blender_copybuffer.h"
#include "BKE_context.h"
+#include "BKE_group.h"
#include "BKE_main.h"
#include "BKE_report.h"
@@ -81,14 +82,16 @@ static int view3d_copybuffer_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
for (Group *group = bmain->group.first; group; group = group->id.next) {
- for (GroupObject *go = group->gobject.first; go; go = go->next) {
- if (go->ob && (go->ob->id.tag & LIB_TAG_DOIT)) {
+ FOREACH_GROUP_OBJECT(group, object)
+ {
+ if (object && (object->id.tag & LIB_TAG_DOIT)) {
BKE_copybuffer_tag_ID(&group->id);
/* don't expand out to all other objects */
group->id.tag &= ~LIB_TAG_NEED_EXPAND;
break;
}
}
+ FOREACH_GROUP_OBJECT_END
}
BLI_make_file_string("/", str, BKE_tempdir_base(), "copybuffer.blend");
diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c
index 5d213962ae9..093425fc3bc 100644
--- a/source/blender/editors/space_view3d/view3d_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_ruler.c
@@ -282,7 +282,7 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state)
}
else if (state == RULER_STATE_DRAG) {
ruler_info->snap_context = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C), CTX_data_scene(C), CTX_data_view_layer(C), CTX_data_engine(C), 0,
+ CTX_data_main(C), CTX_data_scene(C), CTX_data_view_layer(C), CTX_data_engine_type(C), 0,
ruler_info->ar, CTX_wm_view3d(C));
}
else {
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 4658ca566d2..28e15b3bfee 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -113,7 +113,7 @@ void view3d_set_viewcontext(bContext *C, ViewContext *vc)
vc->depsgraph = CTX_data_depsgraph(C);
vc->scene = CTX_data_scene(C);
vc->view_layer = CTX_data_view_layer(C);
- vc->engine = CTX_data_engine(C);
+ vc->engine_type = CTX_data_engine_type(C);
vc->v3d = CTX_wm_view3d(C);
vc->win = CTX_wm_window(C);
vc->rv3d = CTX_wm_region_view3d(C);
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index 2901588b040..76da1faf530 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -251,7 +251,7 @@ typedef struct WalkInfo {
ARegion *ar;
Scene *scene;
ViewLayer *view_layer;
- RenderEngineType *engine;
+ RenderEngineType *engine_type;
wmTimer *timer; /* needed for redraws */
@@ -515,7 +515,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
walk->ar = CTX_wm_region(C);
walk->scene = CTX_data_scene(C);
walk->view_layer = CTX_data_view_layer(C);
- walk->engine = CTX_data_engine(C);
+ walk->engine_type = CTX_data_engine_type(C);
#ifdef NDOF_WALK_DEBUG
puts("\n-- walk begin --");
@@ -604,7 +604,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
walk->rv3d->rflag |= RV3D_NAVIGATING;
walk->snap_context = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C), walk->scene, walk->view_layer, walk->engine, 0,
+ CTX_data_main(C), walk->scene, walk->view_layer, walk->engine_type, 0,
walk->ar, walk->v3d);
walk->v3d_camera_control = ED_view3d_cameracontrol_acquire(
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index b6a9ba1079a..d9bfcd0c289 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -470,7 +470,7 @@ typedef struct TransInfo {
struct ARegion *ar;
struct Scene *scene;
struct ViewLayer *view_layer;
- struct RenderEngineType *engine;
+ struct RenderEngineType *engine_type;
struct ToolSettings *settings;
struct wmTimer *animtimer;
struct wmKeyMap *keymap; /* so we can do lookups for header text */
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 89c43187bd4..730ca70547b 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -119,6 +119,7 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
#include "transform.h"
#include "bmesh.h"
@@ -1890,7 +1891,6 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
{
TransData *td = NULL;
TransDataExtension *tx;
- Base *base = CTX_data_active_base(C);
Object *ob = CTX_data_active_object(C);
ParticleEditSettings *pset = PE_settings(t->scene);
PTCacheEdit *edit = PE_get_current(t->scene, t->view_layer, ob);
@@ -1910,8 +1910,6 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
if (psys)
psmd = psys_get_modifier(ob, psys);
- base->flag |= BA_HAS_RECALC_DATA;
-
for (i = 0, point = edit->points; i < edit->totpoint; i++, point++) {
point->flag &= ~PEP_TRANSFORM;
transformparticle = 0;
@@ -2485,7 +2483,7 @@ static void createTransEditVerts(TransInfo *t)
int *island_vert_map = NULL;
DEG_evaluation_context_init_from_scene(&eval_ctx,
- t->scene, t->view_layer, t->engine,
+ t->scene, t->view_layer, t->engine_type,
DAG_EVAL_VIEWPORT);
/* Even for translation this is needed because of island-orientation, see: T51651. */
@@ -5531,6 +5529,37 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
}
}
+static void trans_object_base_deps_flag_prepare(ViewLayer *view_layer)
+{
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ base->object->id.tag &= ~LIB_TAG_DOIT;
+ }
+}
+
+static void set_trans_object_base_deps_flag_cb(ID *id, void *UNUSED(user_data))
+{
+ /* Here we only handle object IDs. */
+ if (GS(id->name) != ID_OB) {
+ return;
+ }
+ id->tag |= LIB_TAG_DOIT;
+}
+
+static void flush_trans_object_base_deps_flag(Depsgraph *depsgraph, Object *object)
+{
+ object->id.tag |= LIB_TAG_DOIT;
+ DEG_foreach_dependent_ID(depsgraph, &object->id,
+ set_trans_object_base_deps_flag_cb, NULL);
+}
+
+static void trans_object_base_deps_flag_finish(ViewLayer *view_layer)
+{
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (base->object->id.tag & LIB_TAG_DOIT) {
+ base->flag_legacy |= BA_SNAP_FIX_DEPS_FIASCO;
+ }
+ }
+}
/* sets flags in Bases to define whether they take part in transform */
/* it deselects Bases, so we have to call the clear function always after */
@@ -5541,47 +5570,30 @@ static void set_trans_object_base_flags(TransInfo *t)
ViewLayer *view_layer = t->view_layer;
Scene *scene = t->scene;
Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
-
- /*
- * if Base selected and has parent selected:
- * base->flag_legacy = BA_WAS_SEL
+ /* NOTE: if Base selected and has parent selected:
+ * base->flag_legacy = BA_WAS_SEL
*/
- Base *base;
-
- /* don't do it if we're not actually going to recalculate anything */
- if (t->mode == TFM_DUMMY)
+ /* Don't do it if we're not actually going to recalculate anything. */
+ if (t->mode == TFM_DUMMY) {
return;
-
- /* makes sure base flags and object flags are identical */
+ }
+ /* Makes sure base flags and object flags are identical. */
BKE_scene_base_flag_to_objects(t->view_layer);
-
/* Make sure depsgraph is here. */
DEG_graph_relations_update(depsgraph, bmain, scene, view_layer);
-
- /* handle pending update events, otherwise they got copied below */
- EvaluationContext eval_ctx;
- DEG_evaluation_context_init_from_scene(&eval_ctx,
- t->scene, t->view_layer, t->engine,
- DAG_EVAL_VIEWPORT);
- for (base = view_layer->object_bases.first; base; base = base->next) {
- if (base->object->recalc & OB_RECALC_ALL) {
- /* TODO(sergey): Ideally, it's not needed. */
- BKE_object_handle_update(&eval_ctx, t->scene, base->object);
- }
- }
-
- for (base = view_layer->object_bases.first; base; base = base->next) {
+ /* Clear all flags we need. It will be used to detect dependencies. */
+ trans_object_base_deps_flag_prepare(view_layer);
+ /* Traverse all bases and set all possible flags. */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
base->flag_legacy &= ~BA_WAS_SEL;
-
if (TESTBASELIB_BGMODE(base)) {
Object *ob = base->object;
Object *parsel = ob->parent;
-
- /* if parent selected, deselect */
- while (parsel) {
+ /* If parent selected, deselect. */
+ while (parsel != NULL) {
if (parsel->base_flag & BASE_SELECTED) {
Base *parbase = BKE_view_layer_base_find(view_layer, parsel);
- if (parbase) { /* in rare cases this can fail */
+ if (parbase != NULL) { /* in rare cases this can fail */
if (TESTBASELIB_BGMODE(parbase)) {
break;
}
@@ -5589,9 +5601,8 @@ static void set_trans_object_base_flags(TransInfo *t)
}
parsel = parsel->parent;
}
-
- if (parsel) {
- /* rotation around local centers are allowed to propagate */
+ if (parsel != NULL) {
+ /* Rotation around local centers are allowed to propagate. */
if ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
(t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL))
{
@@ -5602,21 +5613,13 @@ static void set_trans_object_base_flags(TransInfo *t)
base->flag_legacy |= BA_WAS_SEL;
}
}
- DEG_id_tag_update(&ob->id, OB_RECALC_OB);
+ flush_trans_object_base_deps_flag(depsgraph, ob);
}
}
-
- /* all recalc flags get flushed to all layers, so a layer flip later on works fine */
- DEG_graph_flush_update(bmain, depsgraph);
-
- /* and we store them temporal in base (only used for transform code) */
- /* this because after doing updates, the object->recalc is cleared */
- for (base = view_layer->object_bases.first; base; base = base->next) {
- if (base->object->recalc & OB_RECALC_OB)
- base->flag_legacy |= BA_HAS_RECALC_OB;
- if (base->object->recalc & OB_RECALC_DATA)
- base->flag_legacy |= BA_HAS_RECALC_DATA;
- }
+ /* Store temporary bits in base indicating that base is being modified
+ * (directly or indirectly) by transforming objects.
+ */
+ trans_object_base_deps_flag_finish(view_layer);
}
static bool mark_children(Object *ob)
@@ -5637,32 +5640,28 @@ static bool mark_children(Object *ob)
static int count_proportional_objects(TransInfo *t)
{
int total = 0;
- /* TODO(sergey): Get rid of global, use explicit main. */
- Main *bmain = G.main;
ViewLayer *view_layer = t->view_layer;
Scene *scene = t->scene;
Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
- Base *base;
-
- /* rotations around local centers are allowed to propagate, so we take all objects */
+ /* Clear all flags we need. It will be used to detect dependencies. */
+ trans_object_base_deps_flag_prepare(view_layer);
+ /* Rotations around local centers are allowed to propagate, so we take all objects. */
if (!((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
(t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL)))
{
- /* mark all parents */
- for (base = view_layer->object_bases.first; base; base = base->next) {
+ /* Mark all parents. */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
if (TESTBASELIB_BGMODE(base)) {
Object *parent = base->object->parent;
-
/* flag all parents */
- while (parent) {
+ while (parent != NULL) {
parent->flag |= BA_TRANSFORM_PARENT;
parent = parent->parent;
}
}
}
-
- /* mark all children */
- for (base = view_layer->object_bases.first; base; base = base->next) {
+ /* Mark all children. */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
/* all base not already selected or marked that is editable */
if ((base->object->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 &&
(base->flag & BASE_SELECTED) == 0 &&
@@ -5672,36 +5671,24 @@ static int count_proportional_objects(TransInfo *t)
}
}
}
-
- for (base = view_layer->object_bases.first; base; base = base->next) {
+ /* Flush changed flags to all dependencies. */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
Object *ob = base->object;
-
- /* if base is not selected, not a parent of selection or not a child of selection and it is editable */
+ /* If base is not selected, not a parent of selection or not a child of
+ * selection and it is editable.
+ */
if ((ob->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 &&
(base->flag & BASE_SELECTED) == 0 &&
(BASE_EDITABLE_BGMODE(base)))
{
-
- DEG_id_tag_update(&ob->id, OB_RECALC_OB);
-
+ flush_trans_object_base_deps_flag(depsgraph, ob);
total += 1;
}
}
-
-
- /* all recalc flags get flushed to all layers, so a layer flip later on works fine */
- DEG_graph_relations_update(depsgraph, bmain, scene, view_layer);
- DEG_graph_flush_update(bmain, depsgraph);
-
- /* and we store them temporal in base (only used for transform code) */
- /* this because after doing updates, the object->recalc is cleared */
- for (base = view_layer->object_bases.first; base; base = base->next) {
- if (base->object->recalc & OB_RECALC_OB)
- base->flag_legacy |= BA_HAS_RECALC_OB;
- if (base->object->recalc & OB_RECALC_DATA)
- base->flag_legacy |= BA_HAS_RECALC_DATA;
- }
-
+ /* Store temporary bits in base indicating that base is being modified
+ * (directly or indirectly) by transforming objects.
+ */
+ trans_object_base_deps_flag_finish(view_layer);
return total;
}
@@ -5715,7 +5702,7 @@ static void clear_trans_object_base_flags(TransInfo *t)
base->flag |= BASE_SELECTED;
}
- base->flag_legacy &= ~(BA_WAS_SEL | BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA | BA_TEMP_TAG | BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT);
+ base->flag_legacy &= ~(BA_WAS_SEL | BA_SNAP_FIX_DEPS_FIASCO | BA_TEMP_TAG | BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT);
}
}
@@ -6489,12 +6476,16 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
else if (arm->flag & ARM_DELAYDEFORM) {
- /* old optimize trick... this enforces to bypass the depgraph */
+ /* TODO(sergey): Armature is already updated by recalcData(), so we
+ * might save some time by skipping re-evaluating it. But this isn't
+ * possible yet within new dependency graph, and also other contexts
+ * might need to update their CoW copies.
+ */
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
- ob->recalc = 0; // is set on OK position already by recalcData()
}
- else
+ else {
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ }
}
else if (t->options & CTX_PAINT_CURVE) {
@@ -8291,7 +8282,7 @@ void createTransData(bContext *C, TransInfo *t)
RegionView3D *rv3d = t->ar->regiondata;
if ((rv3d->persp == RV3D_CAMOB) && v3d->camera) {
/* we could have a flag to easily check an object is being transformed */
- if (v3d->camera->recalc) {
+ if (v3d->camera->id.tag & LIB_TAG_DOIT) {
t->flag |= T_CAMERA;
}
}
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index f6ec93d8ff9..10a7677f42b 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -1123,12 +1123,12 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
Object *obedit = CTX_data_edit_object(C);
Object *ob = CTX_data_active_object(C);
bGPdata *gpd = CTX_data_gpencil_data(C);
- RenderEngineType *engine = CTX_data_engine(C);
+ RenderEngineType *engine_type = CTX_data_engine_type(C);
PropertyRNA *prop;
t->scene = sce;
t->view_layer = view_layer;
- t->engine = engine;
+ t->engine_type = engine_type;
t->sa = sa;
t->ar = ar;
t->obedit = obedit;
diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c
index ee722397f91..0e0c2f3ae25 100644
--- a/source/blender/editors/transform/transform_manipulator.c
+++ b/source/blender/editors/transform/transform_manipulator.c
@@ -65,6 +65,7 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_message.h"
#include "ED_armature.h"
#include "ED_curve.h"
@@ -1115,6 +1116,47 @@ static void manipulator_line_range(const View3D *v3d, const short axis_type, flo
*r_len -= *r_start;
}
+static void manipulator_xform_message_subscribe(
+ wmManipulatorGroup *mgroup, struct wmMsgBus *mbus,
+ bScreen *screen, ScrArea *sa, ARegion *ar, const void *type_fn)
+{
+ /* Subscribe to view properties */
+ wmMsgSubscribeValue msg_sub_value_mpr_tag_refresh = {
+ .owner = ar,
+ .user_data = mgroup->parent_mmap,
+ .notify = WM_manipulator_do_msg_notify_tag_refresh,
+ };
+
+ PointerRNA space_ptr;
+ RNA_pointer_create(&screen->id, &RNA_SpaceView3D, sa->spacedata.first, &space_ptr);
+
+ {
+ extern PropertyRNA rna_SpaceView3D_transform_orientation;
+ const PropertyRNA *props[] = {
+ &rna_SpaceView3D_transform_orientation,
+ };
+ for (int i = 0; i < ARRAY_SIZE(props); i++) {
+ WM_msg_subscribe_rna(mbus, &space_ptr, props[i], &msg_sub_value_mpr_tag_refresh, __func__);
+ }
+ }
+
+ if (type_fn == TRANSFORM_WGT_manipulator) {
+ extern PropertyRNA rna_SpaceView3D_pivot_point;
+ const PropertyRNA *props[] = {
+ &rna_SpaceView3D_pivot_point
+ };
+ for (int i = 0; i < ARRAY_SIZE(props); i++) {
+ WM_msg_subscribe_rna(mbus, &space_ptr, props[i], &msg_sub_value_mpr_tag_refresh, __func__);
+ }
+ }
+ else if (type_fn == VIEW3D_WGT_xform_cage) {
+ /* pass */
+ }
+ else {
+ BLI_assert(0);
+ }
+}
+
/** \} */
@@ -1383,6 +1425,15 @@ static void WIDGETGROUP_manipulator_refresh(const bContext *C, wmManipulatorGrou
MAN_ITER_AXES_END;
}
+static void WIDGETGROUP_manipulator_message_subscribe(
+ const bContext *C, wmManipulatorGroup *mgroup, struct wmMsgBus *mbus)
+{
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ manipulator_xform_message_subscribe(mgroup, mbus, screen, sa, ar, TRANSFORM_WGT_manipulator);
+}
+
static void WIDGETGROUP_manipulator_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup)
{
ManipulatorGroup *man = mgroup->customdata;
@@ -1464,6 +1515,7 @@ void TRANSFORM_WGT_manipulator(wmManipulatorGroupType *wgt)
wgt->poll = WIDGETGROUP_manipulator_poll;
wgt->setup = WIDGETGROUP_manipulator_setup;
wgt->refresh = WIDGETGROUP_manipulator_refresh;
+ wgt->message_subscribe = WIDGETGROUP_manipulator_message_subscribe;
wgt->draw_prepare = WIDGETGROUP_manipulator_draw_prepare;
}
@@ -1500,7 +1552,7 @@ static void WIDGETGROUP_xform_cage_setup(const bContext *UNUSED(C), wmManipulato
ED_MANIPULATOR_CAGE2D_XFORM_FLAG_TRANSLATE);
mpr->color[0] = 1;
- mpr->color_hi[0]=1;
+ mpr->color_hi[0] =1;
mgroup->customdata = xmgroup;
@@ -1585,6 +1637,15 @@ static void WIDGETGROUP_xform_cage_refresh(const bContext *C, wmManipulatorGroup
}
}
+static void WIDGETGROUP_xform_cage_message_subscribe(
+ const bContext *C, wmManipulatorGroup *mgroup, struct wmMsgBus *mbus)
+{
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ manipulator_xform_message_subscribe(mgroup, mbus, screen, sa, ar, VIEW3D_WGT_xform_cage);
+}
+
static void WIDGETGROUP_xform_cage_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup)
{
struct XFormCageWidgetGroup *xmgroup = mgroup->customdata;
@@ -1613,6 +1674,7 @@ void VIEW3D_WGT_xform_cage(wmManipulatorGroupType *wgt)
wgt->poll = WIDGETGROUP_xform_cage_poll;
wgt->setup = WIDGETGROUP_xform_cage_setup;
wgt->refresh = WIDGETGROUP_xform_cage_refresh;
+ wgt->message_subscribe = WIDGETGROUP_xform_cage_message_subscribe;
wgt->draw_prepare = WIDGETGROUP_xform_cage_draw_prepare;
}
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 6b3167a0392..30aad46843d 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -300,9 +300,7 @@ void applyProject(TransInfo *t)
mul_m4_v3(ob->obmat, iloc);
}
else if (t->flag & T_OBJECT) {
- /* TODO(sergey): Ideally force update is not needed here. */
- td->ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
- BKE_object_handle_update(G.main->eval_ctx, t->scene, td->ob);
+ BKE_object_eval_transform_all(G.main->eval_ctx, t->scene, td->ob);
copy_v3_v3(iloc, td->ob->obmat[3]);
}
@@ -391,8 +389,7 @@ void applyGridAbsolute(TransInfo *t)
mul_m4_v3(obmat, iloc);
}
else if (t->flag & T_OBJECT) {
- td->ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
- BKE_object_handle_update(G.main->eval_ctx, t->scene, td->ob);
+ BKE_object_eval_transform_all(G.main->eval_ctx, t->scene, td->ob);
copy_v3_v3(iloc, td->ob->obmat[3]);
}
@@ -585,7 +582,7 @@ static void initSnappingMode(TransInfo *t)
if (t->spacetype == SPACE_VIEW3D) {
if (t->tsnap.object_context == NULL) {
t->tsnap.object_context = ED_transform_snap_object_context_create_view3d(
- G.main, t->scene, t->view_layer, t->engine, 0,
+ G.main, t->scene, t->view_layer, t->engine_type, 0,
t->ar, t->view);
ED_transform_snap_object_context_set_editmesh_callbacks(
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index 61705ba2868..ce8de2ef4d3 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -161,17 +161,8 @@ static void iter_snap_objects(
void *data)
{
Base *base_act = sctx->eval_ctx.view_layer->basact;
- /* Need an exception for particle edit because the base is flagged with BA_HAS_RECALC_DATA
- * which makes the loop skip it, even the derived mesh will never change
- *
- * To solve that problem, we do it first as an exception.
- * */
- if (base_act && base_act->object && base_act->object->mode & OB_MODE_PARTICLE_EDIT) {
- sob_callback(sctx, false, base_act->object, base_act->object->obmat, data);
- }
-
for (Base *base = sctx->eval_ctx.view_layer->object_bases.first; base != NULL; base = base->next) {
- if ((BASE_VISIBLE(base)) && (base->flag_legacy & (BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA)) == 0 &&
+ if ((BASE_VISIBLE(base)) && (base->flag_legacy & BA_SNAP_FIX_DEPS_FIASCO) == 0 &&
!((snap_select == SNAP_NOT_SELECTED && ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL))) ||
(snap_select == SNAP_NOT_ACTIVE && base == base_act)))
{
@@ -2096,7 +2087,7 @@ static bool snapObjectsRay(
* \{ */
SnapObjectContext *ED_transform_snap_object_context_create(
- Main *bmain, Scene *scene, ViewLayer *view_layer, RenderEngineType *engine, int flag)
+ Main *bmain, Scene *scene, ViewLayer *view_layer, RenderEngineType *engine_type, int flag)
{
SnapObjectContext *sctx = MEM_callocN(sizeof(*sctx), __func__);
@@ -2105,7 +2096,7 @@ SnapObjectContext *ED_transform_snap_object_context_create(
sctx->bmain = bmain;
sctx->scene = scene;
- DEG_evaluation_context_init_from_scene(&sctx->eval_ctx, scene, view_layer, engine, DAG_EVAL_VIEWPORT);
+ DEG_evaluation_context_init_from_scene(&sctx->eval_ctx, scene, view_layer, engine_type, DAG_EVAL_VIEWPORT);
sctx->cache.object_map = BLI_ghash_ptr_new(__func__);
sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
@@ -2114,11 +2105,11 @@ SnapObjectContext *ED_transform_snap_object_context_create(
}
SnapObjectContext *ED_transform_snap_object_context_create_view3d(
- Main *bmain, Scene *scene, ViewLayer *view_layer, RenderEngineType *engine, int flag,
+ Main *bmain, Scene *scene, ViewLayer *view_layer, RenderEngineType *engine_type, int flag,
/* extra args for view3d */
const ARegion *ar, const View3D *v3d)
{
- SnapObjectContext *sctx = ED_transform_snap_object_context_create(bmain, scene, view_layer, engine, flag);
+ SnapObjectContext *sctx = ED_transform_snap_object_context_create(bmain, scene, view_layer, engine_type, flag);
sctx->use_v3d = true;
sctx->v3d_data.ar = ar;
diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c
index 61142fdc887..0f3240946fd 100644
--- a/source/blender/editors/util/numinput.c
+++ b/source/blender/editors/util/numinput.c
@@ -488,8 +488,9 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
const float fac = (float)BKE_scene_unit_scale(&sce->unit, n->unit_type[idx], 1.0);
/* Make radian default unit when needed. */
- if (n->unit_use_radians && n->unit_type[idx] == B_UNIT_ROTATION)
+ if (n->unit_use_radians && n->unit_type[idx] == B_UNIT_ROTATION) {
default_unit = "r";
+ }
BLI_strncpy(str_unit_convert, n->str, sizeof(str_unit_convert));
@@ -513,7 +514,16 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
n->val[idx] = -n->val[idx];
}
if (n->val_flag[idx] & NUM_INVERSE) {
- n->val[idx] = 1.0f / n->val[idx];
+ val = n->val[idx];
+ /* If we invert on radians when user is in degrees, you get unexpected results... See T53463. */
+ if (!n->unit_use_radians && n->unit_type[idx] == B_UNIT_ROTATION) {
+ val = RAD2DEG(val);
+ }
+ val = 1.0 / val;
+ if (!n->unit_use_radians && n->unit_type[idx] == B_UNIT_ROTATION) {
+ val = DEG2RAD(val);
+ }
+ n->val[idx] = (float)val;
}
if (UNLIKELY(!isfinite(n->val[idx]))) {
diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c
index c24e4994f7f..dbf1cf46c61 100644
--- a/source/blender/editors/util/undo.c
+++ b/source/blender/editors/util/undo.c
@@ -45,6 +45,7 @@
#include "BKE_blender_undo.h"
#include "BKE_context.h"
#include "BKE_global.h"
+#include "BKE_library_override.h"
#include "BKE_main.h"
#include "BKE_screen.h"
@@ -82,6 +83,9 @@ void ED_undo_push(bContext *C, const char *str)
if (G.debug & G_DEBUG)
printf("%s: %s\n", __func__, str);
+ /* Always do it for now, this might need to be refined... */
+ BKE_main_override_static_operations_create(CTX_data_main(C));
+
if (obedit) {
if (U.undosteps == 0) return;