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:
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/animation/anim_markers.c3
-rw-r--r--source/blender/editors/animation/anim_ops.c6
-rw-r--r--source/blender/editors/animation/drivers.c1
-rw-r--r--source/blender/editors/animation/keyframing.c2
-rw-r--r--source/blender/editors/armature/armature_relations.c5
-rw-r--r--source/blender/editors/armature/armature_select.c13
-rw-r--r--source/blender/editors/armature/pose_utils.c1
-rw-r--r--source/blender/editors/curve/editcurve.c9
-rw-r--r--source/blender/editors/curve/editcurve_select.c16
-rw-r--r--source/blender/editors/curve/editfont.c9
-rw-r--r--source/blender/editors/datafiles/CMakeLists.txt26
-rw-r--r--source/blender/editors/gpencil/gpencil_brush.c20
-rw-r--r--source/blender/editors/gpencil/gpencil_convert.c1
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c15
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h3
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c46
-rw-r--r--source/blender/editors/gpencil/gpencil_undo.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c6
-rw-r--r--source/blender/editors/include/ED_manipulator_library.h11
-rw-r--r--source/blender/editors/include/ED_mesh.h2
-rw-r--r--source/blender/editors/include/ED_object.h8
-rw-r--r--source/blender/editors/include/ED_screen.h38
-rw-r--r--source/blender/editors/include/ED_undo.h8
-rw-r--r--source/blender/editors/include/ED_view3d.h9
-rw-r--r--source/blender/editors/include/UI_icons.h14
-rw-r--r--source/blender/editors/include/UI_interface.h8
-rw-r--r--source/blender/editors/interface/CMakeLists.txt1
-rw-r--r--source/blender/editors/interface/interface.c36
-rw-r--r--source/blender/editors/interface/interface_anim.c59
-rw-r--r--source/blender/editors/interface/interface_handlers.c126
-rw-r--r--source/blender/editors/interface/interface_icons.c132
-rw-r--r--source/blender/editors/interface/interface_intern.h12
-rw-r--r--source/blender/editors/interface/interface_layout.c234
-rw-r--r--source/blender/editors/interface/interface_ops.c1
-rw-r--r--source/blender/editors/interface/interface_panel.c17
-rw-r--r--source/blender/editors/interface/interface_region_color_picker.c2
-rw-r--r--source/blender/editors/interface/interface_region_hud.c338
-rw-r--r--source/blender/editors/interface/interface_region_popover.c12
-rw-r--r--source/blender/editors/interface/interface_region_popup.c8
-rw-r--r--source/blender/editors/interface/interface_region_search.c12
-rw-r--r--source/blender/editors/interface/interface_region_tooltip.c2
-rw-r--r--source/blender/editors/interface/interface_templates.c43
-rw-r--r--source/blender/editors/interface/interface_widgets.c114
-rw-r--r--source/blender/editors/interface/resources.c1
-rw-r--r--source/blender/editors/interface/view2d_ops.c2
-rw-r--r--source/blender/editors/io/io_alembic.c6
-rw-r--r--source/blender/editors/io/io_cache.c2
-rw-r--r--source/blender/editors/io/io_collada.c8
-rw-r--r--source/blender/editors/lattice/editlattice_select.c8
-rw-r--r--source/blender/editors/manipulator_library/manipulator_types/arrow3d_manipulator.c49
-rw-r--r--source/blender/editors/manipulator_library/manipulator_types/dial3d_manipulator.c6
-rw-r--r--source/blender/editors/mesh/editface.c3
-rw-r--r--source/blender/editors/mesh/editmesh_intersect.c28
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c6
-rw-r--r--source/blender/editors/mesh/editmesh_select.c26
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c19
-rw-r--r--source/blender/editors/mesh/editmesh_undo.c4
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c11
-rw-r--r--source/blender/editors/mesh/mesh_data.c3
-rw-r--r--source/blender/editors/mesh/meshtools.c7
-rw-r--r--source/blender/editors/metaball/mball_edit.c10
-rw-r--r--source/blender/editors/object/object_add.c20
-rw-r--r--source/blender/editors/object/object_data_transfer.c23
-rw-r--r--source/blender/editors/object/object_edit.c229
-rw-r--r--source/blender/editors/object/object_hook.c4
-rw-r--r--source/blender/editors/object/object_intern.h3
-rw-r--r--source/blender/editors/object/object_modifier.c14
-rw-r--r--source/blender/editors/object/object_ops.c21
-rw-r--r--source/blender/editors/object/object_relations.c20
-rw-r--r--source/blender/editors/object/object_select.c32
-rw-r--r--source/blender/editors/object/object_shapekey.c3
-rw-r--r--source/blender/editors/object/object_vgroup.c2
-rw-r--r--source/blender/editors/physics/dynamicpaint_ops.c2
-rw-r--r--source/blender/editors/physics/particle_edit.c848
-rw-r--r--source/blender/editors/physics/particle_edit_undo.c2
-rw-r--r--source/blender/editors/physics/particle_object.c6
-rw-r--r--source/blender/editors/physics/physics_fluid.c2
-rw-r--r--source/blender/editors/physics/physics_pointcache.c4
-rw-r--r--source/blender/editors/physics/rigidbody_object.c7
-rw-r--r--source/blender/editors/render/render_internal.c12
-rw-r--r--source/blender/editors/render/render_preview.c48
-rw-r--r--source/blender/editors/render/render_shading.c1
-rw-r--r--source/blender/editors/screen/area.c172
-rw-r--r--source/blender/editors/screen/screen_edit.c10
-rw-r--r--source/blender/editors/screen/screen_intern.h3
-rw-r--r--source/blender/editors/screen/screen_ops.c172
-rw-r--r--source/blender/editors/screen/screendump.c2
-rw-r--r--source/blender/editors/screen/workspace_layout_edit.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c358
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c18
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c25
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c52
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c18
-rw-r--r--source/blender/editors/sound/sound_ops.c6
-rw-r--r--source/blender/editors/space_action/action_buttons.c2
-rw-r--r--source/blender/editors/space_action/action_draw.c2
-rw-r--r--source/blender/editors/space_action/space_action.c4
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c25
-rw-r--r--source/blender/editors/space_clip/clip_buttons.c2
-rw-r--r--source/blender/editors/space_clip/clip_intern.h2
-rw-r--r--source/blender/editors/space_clip/clip_toolbar.c4
-rw-r--r--source/blender/editors/space_clip/space_clip.c4
-rw-r--r--source/blender/editors/space_file/filelist.c29
-rw-r--r--source/blender/editors/space_file/filesel.c4
-rw-r--r--source/blender/editors/space_file/space_file.c2
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c4
-rw-r--r--source/blender/editors/space_graph/space_graph.c6
-rw-r--r--source/blender/editors/space_image/image_buttons.c24
-rw-r--r--source/blender/editors/space_image/image_edit.c13
-rw-r--r--source/blender/editors/space_image/image_intern.h3
-rw-r--r--source/blender/editors/space_image/image_ops.c96
-rw-r--r--source/blender/editors/space_image/space_image.c14
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c2
-rw-r--r--source/blender/editors/space_nla/nla_edit.c8
-rw-r--r--source/blender/editors/space_nla/space_nla.c6
-rw-r--r--source/blender/editors/space_node/drawnode.c10
-rw-r--r--source/blender/editors/space_node/node_buttons.c2
-rw-r--r--source/blender/editors/space_node/node_edit.c11
-rw-r--r--source/blender/editors/space_node/node_group.c17
-rw-r--r--source/blender/editors/space_node/space_node.c4
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c5
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c431
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c52
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h14
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c7
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c53
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c22
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c8
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c4
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c2
-rw-r--r--source/blender/editors/space_text/space_text.c2
-rw-r--r--source/blender/editors/space_text/text_header.c2
-rw-r--r--source/blender/editors/space_text/text_ops.c16
-rw-r--r--source/blender/editors/space_topbar/space_topbar.c58
-rw-r--r--source/blender/editors/space_userpref/space_userpref.c4
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c25
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c17
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_camera.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_forcefield.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_lamp.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_navigate.c75
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_ruler.c3
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_ruler.c3
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c125
-rw-r--r--source/blender/editors/space_view3d/view3d_toolbar.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c31
-rw-r--r--source/blender/editors/transform/transform.h4
-rw-r--r--source/blender/editors/transform/transform_conversions.c7
-rw-r--r--source/blender/editors/transform/transform_generics.c14
-rw-r--r--source/blender/editors/transform/transform_input.c7
-rw-r--r--source/blender/editors/transform/transform_manipulator_3d.c91
-rw-r--r--source/blender/editors/transform/transform_ops.c17
-rw-r--r--source/blender/editors/undo/ed_undo.c59
-rw-r--r--source/blender/editors/util/CMakeLists.txt1
-rw-r--r--source/blender/editors/util/ed_util.c4
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c18
158 files changed, 3625 insertions, 1644 deletions
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index 624c6e9f5de..e957e84857a 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -76,6 +76,8 @@
#include "ED_transform.h"
#include "ED_types.h"
+#include "DEG_depsgraph.h"
+
/* ************* Marker API **************** */
/* helper function for getting the list of markers to work on */
@@ -1196,6 +1198,7 @@ static int ed_marker_select(bContext *C, const wmEvent *event, bool extend, bool
}
}
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
#else
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c
index 23563e7f15f..4402ca78976 100644
--- a/source/blender/editors/animation/anim_ops.c
+++ b/source/blender/editors/animation/anim_ops.c
@@ -268,7 +268,7 @@ static void ANIM_OT_change_frame(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR | OPTYPE_UNDO_GROUPED;
- ot->undo_group = "FRAME_CHANGE";
+ ot->undo_group = "Frame Change";
/* rna */
ot->prop = RNA_def_float(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
@@ -332,7 +332,7 @@ static void ANIM_OT_start_frame_set(wmOperatorType *ot)
/* identifiers */
ot->name = "Set Start Frame";
ot->idname = "ANIM_OT_start_frame_set";
- ot->description = "Set the start frame";
+ ot->description = "Set the current frame as the preview or scene start frame";
/* api callbacks */
ot->exec = anim_set_sfra_exec;
@@ -376,7 +376,7 @@ static void ANIM_OT_end_frame_set(wmOperatorType *ot)
/* identifiers */
ot->name = "Set End Frame";
ot->idname = "ANIM_OT_end_frame_set";
- ot->description = "Set the end frame";
+ ot->description = "Set the current frame as the preview or scene end frame";
/* api callbacks */
ot->exec = anim_set_efra_exec;
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index 294cff43c56..f303be0dd76 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -449,6 +449,7 @@ int ANIM_add_driver(ReportList *reports, ID *id, const char rna_path[], int arra
else fval = RNA_property_float_get_index(&ptr, prop, array_index);
BLI_snprintf(expression, maxlen, "%s%.3f", dvar_prefix, fval);
+ BLI_str_rstrip_float_zero(expression, '\0');
}
else if (flag & CREATEDRIVER_WITH_DEFAULT_DVAR) {
BLI_strncpy(expression, "var", maxlen);
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 1913eb944d9..fe5714aba2e 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -954,7 +954,7 @@ bool insert_keyframe_direct(Depsgraph *depsgraph, ReportList *reports, PointerRN
if (RNA_path_resolved_create(&ptr, prop, fcu->array_index, &anim_rna)) {
/* for making it easier to add corrective drivers... */
- cfra = evaluate_driver(&anim_rna, fcu->driver, cfra);
+ cfra = evaluate_driver(&anim_rna, fcu->driver, fcu->driver, cfra);
}
else {
cfra = 0.0f;
diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c
index 9282148e857..cc149d3e42f 100644
--- a/source/blender/editors/armature/armature_relations.c
+++ b/source/blender/editors/armature/armature_relations.c
@@ -377,7 +377,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
}
else {
/* merge in data - we'll fix the drivers manually */
- BKE_animdata_merge_copy(&ob->id, &base->object->id, ADT_MERGECOPY_KEEP_DST, false);
+ BKE_animdata_merge_copy(bmain, &ob->id, &base->object->id, ADT_MERGECOPY_KEEP_DST, false);
}
}
@@ -388,7 +388,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
}
else {
/* merge in data - we'll fix the drivers manually */
- BKE_animdata_merge_copy(&arm->id, &curarm->id, ADT_MERGECOPY_KEEP_DST, false);
+ BKE_animdata_merge_copy(bmain, &arm->id, &curarm->id, ADT_MERGECOPY_KEEP_DST, false);
}
}
@@ -403,6 +403,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
ED_armature_from_edit(bmain, arm);
ED_armature_edit_free(arm);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index 95acc8ab6ba..e295e1fd35a 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -254,7 +254,9 @@ void *get_nearest_bone(
rect.xmin = rect.xmax = xy[0];
rect.ymin = rect.ymax = xy[1];
- hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST);
+ hits = view3d_opengl_select(
+ &vc, buffer, MAXPICKBUF, &rect,
+ VIEW3D_SELECT_PICK_NEAREST, VIEW3D_SELECT_FILTER_NOP);
*r_base = NULL;
@@ -446,9 +448,11 @@ static EditBone *get_nearest_editbonepoint(
{
const int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL);
+ const eV3DSelectObjectFilter select_filter = VIEW3D_SELECT_FILTER_NOP;
+
rcti rect;
BLI_rcti_init_pt_radius(&rect, vc->mval, 12);
- const int hits12 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode);
+ const int hits12 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter);
if (hits12 == 1) {
hits = selectbuffer_ret_hits_12(buffer, hits12);
goto cache_end;
@@ -458,7 +462,9 @@ static EditBone *get_nearest_editbonepoint(
offs = 4 * hits12;
BLI_rcti_init_pt_radius(&rect, vc->mval, 5);
- const int hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode);
+ const int hits5 = view3d_opengl_select(
+ vc, buffer + offs, MAXPICKBUF - offs, &rect,
+ select_mode, select_filter);
if (hits5 == 1) {
hits = selectbuffer_ret_hits_5(buffer, hits12, hits5);
@@ -717,6 +723,7 @@ bool ED_armature_edit_select_pick(bContext *C, const int mval[2], bool extend, b
if (vc.view_layer->basact != basact) {
vc.view_layer->basact = basact;
+ DEG_id_tag_update(&vc.scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, vc.scene);
}
}
diff --git a/source/blender/editors/armature/pose_utils.c b/source/blender/editors/armature/pose_utils.c
index b64c8528010..e280284a9ce 100644
--- a/source/blender/editors/armature/pose_utils.c
+++ b/source/blender/editors/armature/pose_utils.c
@@ -40,6 +40,7 @@
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_idprop.h"
+#include "BKE_main.h"
#include "BKE_context.h"
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 616017dac0a..aa50916f5e0 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -2896,7 +2896,7 @@ static int hide_exec(bContext *C, wmOperator *op)
}
}
- DEG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
BKE_curve_nurb_vert_active_validate(obedit->data);
@@ -2959,7 +2959,7 @@ static int reveal_exec(bContext *C, wmOperator *op)
}
}
- DEG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -4413,6 +4413,7 @@ bool ED_curve_editnurb_select_pick(bContext *C, const int mval[2], bool extend,
BKE_curve_nurb_active_set(cu, nu);
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return true;
@@ -5300,6 +5301,7 @@ static int duplicate_exec(bContext *C, wmOperator *op)
if (BLI_listbase_is_empty(&newnurb) == false) {
BLI_movelisttolist(object_editcurve_get(obedit), &newnurb);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
else {
@@ -5803,7 +5805,7 @@ void CURVE_OT_delete(wmOperatorType *ot)
/* properties */
prop = RNA_def_enum(ot->srna, "type", curve_delete_type_items, 0, "Type", "Which elements to delete");
RNA_def_enum_funcs(prop, rna_curve_delete_type_itemf);
-
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
ot->prop = prop;
}
@@ -6148,6 +6150,7 @@ int join_curve_exec(bContext *C, wmOperator *op)
DEG_relations_tag_update(bmain); // because we removed object(s), call before editmode!
DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c
index 58fb6d50575..0fae39776a9 100644
--- a/source/blender/editors/curve/editcurve_select.c
+++ b/source/blender/editors/curve/editcurve_select.c
@@ -55,10 +55,10 @@
#include "curve_intern.h"
-
#include "RNA_access.h"
#include "RNA_define.h"
+#include "DEG_depsgraph.h"
/* returns 1 in case (de)selection was successful */
bool select_beztriple(BezTriple *bezt, bool selstatus, short flag, eVisible_Types hidden)
@@ -404,6 +404,7 @@ static int de_select_first_exec(bContext *C, wmOperator *UNUSED(op))
Object *obedit = CTX_data_edit_object(C);
selectend_nurb(obedit, FIRST, true, DESELECT);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
BKE_curve_nurb_vert_active_validate(obedit->data);
@@ -430,6 +431,7 @@ static int de_select_last_exec(bContext *C, wmOperator *UNUSED(op))
Object *obedit = CTX_data_edit_object(C);
selectend_nurb(obedit, LAST, true, DESELECT);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
BKE_curve_nurb_vert_active_validate(obedit->data);
@@ -488,6 +490,7 @@ static int de_select_all_exec(bContext *C, wmOperator *op)
break;
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
BKE_curve_nurb_vert_active_validate(cu);
}
@@ -540,6 +543,7 @@ static int select_linked_exec(bContext *C, wmOperator *UNUSED(op))
}
if (changed) {
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
}
@@ -608,6 +612,7 @@ static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent
}
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
if (!select) {
BKE_curve_nurb_vert_active_validate(obedit->data);
@@ -670,6 +675,7 @@ static int select_row_exec(bContext *C, wmOperator *UNUSED(op))
}
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -698,6 +704,7 @@ static int select_next_exec(bContext *C, wmOperator *UNUSED(op))
ListBase *editnurb = object_editcurve_get(obedit);
select_adjacent_cp(editnurb, 1, 0, SELECT);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -726,6 +733,7 @@ static int select_previous_exec(bContext *C, wmOperator *UNUSED(op))
ListBase *editnurb = object_editcurve_get(obedit);
select_adjacent_cp(editnurb, -1, 0, SELECT);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -814,6 +822,7 @@ static int select_more_exec(bContext *C, wmOperator *UNUSED(op))
select_adjacent_cp(editnurb, -1, 0, SELECT);
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -1001,6 +1010,7 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op))
}
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
BKE_curve_nurb_vert_active_validate(obedit->data);
@@ -1087,6 +1097,7 @@ static int curve_select_random_exec(bContext *C, wmOperator *op)
curve_select_random(editnurb, randfac, seed_iter, select);
BKE_curve_nurb_vert_active_validate(obedit->data);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
@@ -1197,6 +1208,7 @@ static int select_nth_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -1503,6 +1515,7 @@ static int curve_select_similar_exec(bContext *C, wmOperator *op)
}
if (changed) {
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
}
@@ -1744,6 +1757,7 @@ static int edcu_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE
BKE_curve_nurb_vert_active_set(cu, nu_dst, vert_dst_p);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index 7cdfafdad43..75efdec3dd2 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -246,7 +246,6 @@ static int insert_into_textbuf(Object *obedit, uintptr_t c)
static void text_update_edited(bContext *C, Object *obedit, int mode)
{
- struct Main *bmain = CTX_data_main(C);
Curve *cu = obedit->data;
EditFont *ef = cu->editfont;
@@ -259,7 +258,7 @@ static void text_update_edited(bContext *C, Object *obedit, int mode)
}
else {
/* depsgraph runs above, but since we're not tagging for update, call direct */
- BKE_vfont_to_curve(bmain, obedit, mode);
+ BKE_vfont_to_curve(obedit, mode);
}
cu->curinfo = ef->textbufinfo[ef->pos ? ef->pos - 1 : 0];
@@ -982,16 +981,14 @@ static int move_cursor(bContext *C, int type, const bool select)
/* apply virtical cursor motion to position immediately
* otherwise the selection will lag behind */
if (FO_CURS_IS_MOTION(cursmove)) {
- struct Main *bmain = CTX_data_main(C);
- BKE_vfont_to_curve(bmain, obedit, cursmove);
+ BKE_vfont_to_curve(obedit, cursmove);
cursmove = FO_CURS;
}
if (select == 0) {
if (ef->selstart) {
- struct Main *bmain = CTX_data_main(C);
ef->selstart = ef->selend = 0;
- BKE_vfont_to_curve(bmain, obedit, FO_SELCHANGE);
+ BKE_vfont_to_curve(obedit, FO_SELCHANGE);
}
}
diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt
index 23b328aa8e0..98b57fcbd71 100644
--- a/source/blender/editors/datafiles/CMakeLists.txt
+++ b/source/blender/editors/datafiles/CMakeLists.txt
@@ -681,32 +681,6 @@ if(WITH_BLENDER)
data_to_c_simple(../../../../release/datafiles/brushicons/twist.png SRC)
data_to_c_simple(../../../../release/datafiles/brushicons/vertexdraw.png SRC)
- # matcap
- data_to_c_simple(../../../../release/datafiles/matcaps/mc01.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc02.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc03.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc04.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc05.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc06.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc07.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc08.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc09.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc10.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc11.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc12.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc13.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc14.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc15.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc16.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc17.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc18.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc19.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc20.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc21.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc22.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc23.jpg SRC)
- data_to_c_simple(../../../../release/datafiles/matcaps/mc24.jpg SRC)
-
endif()
data_to_c_simple(../../../../release/datafiles/startup.blend SRC)
diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_brush.c
index c2e532be0b3..f9284d71db3 100644
--- a/source/blender/editors/gpencil/gpencil_brush.c
+++ b/source/blender/editors/gpencil/gpencil_brush.c
@@ -44,6 +44,8 @@
#include "BLI_rand.h"
#include "BLI_utildefines.h"
+#include "PIL_time.h"
+
#include "BLT_translation.h"
#include "DNA_scene_types.h"
@@ -138,6 +140,8 @@ typedef struct tGP_BrushEditData {
/* Timer for in-place accumulation of brush effect */
wmTimer *timer;
bool timerTick; /* is this event from a timer */
+
+ RNG *rng;
} tGP_BrushEditData;
@@ -658,7 +662,7 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in
* as well as the strength of the brush
*/
const float inf = gp_brush_influence_calc(gso, radius, co) / 2.0f;
- const float fac = BLI_frand() * inf;
+ const float fac = BLI_rng_get_float(gso->rng) * inf;
/* need one flag enabled by default */
if ((gso->settings->flag & (GP_BRUSHEDIT_FLAG_APPLY_POSITION |
GP_BRUSHEDIT_FLAG_APPLY_STRENGTH |
@@ -685,7 +689,7 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in
svec[1] = mvec[0];
/* scale the displacement by the random displacement, and apply */
- if (BLI_frand() > 0.5f) {
+ if (BLI_rng_get_float(gso->rng) > 0.5f) {
mul_v2_fl(svec, -fac);
}
else {
@@ -724,7 +728,7 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in
}
/* apply random to strength */
if (gso->settings->flag & GP_BRUSHEDIT_FLAG_APPLY_STRENGTH) {
- if (BLI_frand() > 0.5f) {
+ if (BLI_rng_get_float(gso->rng) > 0.5f) {
pt->strength += fac;
}
else {
@@ -735,7 +739,7 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in
}
/* apply random to thickness (use pressure) */
if (gso->settings->flag & GP_BRUSHEDIT_FLAG_APPLY_THICKNESS) {
- if (BLI_frand() > 0.5f) {
+ if (BLI_rng_get_float(gso->rng) > 0.5f) {
pt->pressure += fac;
}
else {
@@ -1061,6 +1065,10 @@ static bool gpsculpt_brush_init(bContext *C, wmOperator *op)
gso->brush_type = gso->settings->brushtype;
+ /* Random generator, only init once. */
+ uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
+ rng_seed ^= GET_UINT_FROM_POINTER(gso);
+ gso->rng = BLI_rng_new(rng_seed);
gso->is_painting = false;
gso->first = true;
@@ -1163,6 +1171,10 @@ static void gpsculpt_brush_exit(bContext *C, wmOperator *op)
WM_event_remove_timer(CTX_wm_manager(C), win, gso->timer);
}
+ if (gso->rng != NULL) {
+ BLI_rng_free(gso->rng);
+ }
+
/* disable cursor and headerprints */
ED_area_headerprint(CTX_wm_area(C), NULL);
WM_cursor_modal_restore(win);
diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c
index dfaa1420d68..d2301337c0e 100644
--- a/source/blender/editors/gpencil/gpencil_convert.c
+++ b/source/blender/editors/gpencil/gpencil_convert.c
@@ -1374,6 +1374,7 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op)
}
/* notifiers */
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index 2e8e48b2f15..9f437f28f0f 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -52,14 +52,15 @@
#include "DNA_view3d_types.h"
#include "DNA_gpencil_types.h"
+#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_gpencil.h"
#include "BKE_library.h"
+#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
-#include "BKE_colortools.h"
#include "UI_interface.h"
#include "UI_resources.h"
@@ -83,6 +84,7 @@
/* add new datablock - wrapper around API */
static int gp_data_add_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
ToolSettings *ts = CTX_data_tool_settings(C);
@@ -95,7 +97,7 @@ static int gp_data_add_exec(bContext *C, wmOperator *op)
bGPdata *gpd = (*gpd_ptr);
id_us_min(&gpd->id);
- *gpd_ptr = BKE_gpencil_data_addnew(DATA_("GPencil"));
+ *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil"));
/* if not exist brushes, create a new set */
if (ts) {
@@ -183,6 +185,7 @@ void GPENCIL_OT_data_unlink(wmOperatorType *ot)
/* add new layer - wrapper around API */
static int gp_layer_add_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
ToolSettings *ts = CTX_data_tool_settings(C);
@@ -192,7 +195,7 @@ static int gp_layer_add_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
if (*gpd_ptr == NULL)
- *gpd_ptr = BKE_gpencil_data_addnew(DATA_("GPencil"));
+ *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil"));
/* if not exist brushes, create a new set */
if (ts) {
@@ -1376,6 +1379,7 @@ void GPENCIL_OT_brush_select(wmOperatorType *ot)
/* add new palette - wrapper around API */
static int gp_palette_add_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
/* if there's no existing Grease-Pencil data there, add some */
@@ -1384,7 +1388,7 @@ static int gp_palette_add_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
if (*gpd_ptr == NULL)
- *gpd_ptr = BKE_gpencil_data_addnew(DATA_("GPencil"));
+ *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil"));
/* add new palette now */
BKE_gpencil_palette_addnew(*gpd_ptr, DATA_("GP_Palette"), true);
@@ -1588,6 +1592,7 @@ void GPENCIL_OT_palette_lock_layer(wmOperatorType *ot)
/* add new palette - wrapper around API */
static int gp_palettecolor_add_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL);
/* if there's no existing Grease-Pencil data there, add some */
@@ -1596,7 +1601,7 @@ static int gp_palettecolor_add_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
if (*gpd_ptr == NULL)
- *gpd_ptr = BKE_gpencil_data_addnew(DATA_("GPencil"));
+ *gpd_ptr = BKE_gpencil_data_addnew(bmain, DATA_("GPencil"));
/* verify palette */
bGPDpalette *palette = BKE_gpencil_palette_getactive(*gpd_ptr);
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index 33af6cab915..67b88efa285 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -41,6 +41,7 @@ struct bGPDstroke;
struct bGPDspoint;
struct GHash;
+struct RNG;
struct ARegion;
struct View2D;
@@ -117,7 +118,7 @@ bool gp_smooth_stroke(bGPDstroke *gps, int i, float inf, bool affect_pressure);
bool gp_smooth_stroke_strength(bGPDstroke *gps, int i, float inf);
bool gp_smooth_stroke_thickness(bGPDstroke *gps, int i, float inf);
void gp_subdivide_stroke(bGPDstroke *gps, const int new_totpoints);
-void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush);
+void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush, struct RNG *rng);
/* Layers Enums -------------------------------------- */
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 437d5cef6f8..c8f1901d075 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -169,6 +169,8 @@ typedef struct tGPsdata {
short straight[2]; /* 1: line horizontal, 2: line vertical, other: not defined, second element position */
int lock_axis; /* lock drawing to one axis */
+ RNG *rng;
+
short keymodifier; /* key used for invoking the operator */
} tGPsdata;
@@ -408,7 +410,8 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3]
}
/* apply jitter to stroke */
-static void gp_brush_jitter(bGPdata *gpd, bGPDbrush *brush, tGPspoint *pt, const int mval[2], int r_mval[2])
+static void gp_brush_jitter(
+ bGPdata *gpd, bGPDbrush *brush, tGPspoint *pt, const int mval[2], int r_mval[2], RNG *rng)
{
float pressure = pt->pressure;
float tmp_pressure = pt->pressure;
@@ -417,7 +420,7 @@ static void gp_brush_jitter(bGPdata *gpd, bGPDbrush *brush, tGPspoint *pt, const
tmp_pressure = curvef * brush->draw_sensitivity;
}
const float exfactor = (brush->draw_jitter + 2.0f) * (brush->draw_jitter + 2.0f); /* exponential value */
- const float fac = BLI_frand() * exfactor * tmp_pressure;
+ const float fac = BLI_rng_get_float(rng) * exfactor * tmp_pressure;
/* Jitter is applied perpendicular to the mouse movement vector (2D space) */
float mvec[2], svec[2];
/* mouse movement in ints -> floats */
@@ -434,7 +437,7 @@ static void gp_brush_jitter(bGPdata *gpd, bGPDbrush *brush, tGPspoint *pt, const
svec[0] = -mvec[1];
svec[1] = mvec[0];
/* scale the displacement by the random, and apply */
- if (BLI_frand() > 0.5f) {
+ if (BLI_rng_get_float(rng) > 0.5f) {
mul_v2_fl(svec, -fac);
}
else {
@@ -550,7 +553,7 @@ static short gp_stroke_addpoint(
/* Apply jitter to position */
if (brush->draw_jitter > 0.0f) {
int r_mval[2];
- gp_brush_jitter(gpd, brush, pt, mval, r_mval);
+ gp_brush_jitter(gpd, brush, pt, mval, r_mval, p->rng);
copy_v2_v2_int(&pt->x, r_mval);
}
else {
@@ -560,11 +563,11 @@ static short gp_stroke_addpoint(
if ((brush->draw_random_press > 0.0f) && (brush->flag & GP_BRUSH_USE_RANDOM_PRESSURE)) {
float curvef = curvemapping_evaluateF(brush->cur_sensitivity, 0, pressure);
float tmp_pressure = curvef * brush->draw_sensitivity;
- if (BLI_frand() > 0.5f) {
- pt->pressure -= tmp_pressure * brush->draw_random_press * BLI_frand();
+ if (BLI_rng_get_float(p->rng) > 0.5f) {
+ pt->pressure -= tmp_pressure * brush->draw_random_press * BLI_rng_get_float(p->rng);
}
else {
- pt->pressure += tmp_pressure * brush->draw_random_press * BLI_frand();
+ pt->pressure += tmp_pressure * brush->draw_random_press * BLI_rng_get_float(p->rng);
}
CLAMP(pt->pressure, GPENCIL_STRENGTH_MIN, 1.0f);
}
@@ -588,11 +591,11 @@ static short gp_stroke_addpoint(
/* apply randomness to color strength */
if ((brush->draw_random_press > 0.0f) && (brush->flag & GP_BRUSH_USE_RANDOM_STRENGTH)) {
- if (BLI_frand() > 0.5f) {
- pt->strength -= pt->strength * brush->draw_random_press * BLI_frand();
+ if (BLI_rng_get_float(p->rng) > 0.5f) {
+ pt->strength -= pt->strength * brush->draw_random_press * BLI_rng_get_float(p->rng);
}
else {
- pt->strength += pt->strength * brush->draw_random_press * BLI_frand();
+ pt->strength += pt->strength * brush->draw_random_press * BLI_rng_get_float(p->rng);
}
CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f);
}
@@ -978,7 +981,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
}
/* apply randomness to stroke */
if (brush->draw_random_sub > 0.0f) {
- gp_randomize_stroke(gps, brush);
+ gp_randomize_stroke(gps, brush, p->rng);
}
/* smooth stroke after subdiv - only if there's something to do
@@ -1387,6 +1390,7 @@ static void gp_init_palette(tGPsdata *p)
/* (re)init new painting data */
static bool gp_session_initdata(bContext *C, tGPsdata *p)
{
+ Main *bmain = CTX_data_main(C);
bGPdata **gpd_ptr = NULL;
ScrArea *curarea = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
@@ -1537,7 +1541,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p)
else {
/* if no existing GPencil block exists, add one */
if (*gpd_ptr == NULL)
- *gpd_ptr = BKE_gpencil_data_addnew("GPencil");
+ *gpd_ptr = BKE_gpencil_data_addnew(bmain, "GPencil");
p->gpd = *gpd_ptr;
}
@@ -1582,6 +1586,11 @@ static tGPsdata *gp_session_initpaint(bContext *C)
*/
p->radius = U.gp_eraser;
+ /* Random generator, only init once. */
+ uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
+ rng_seed ^= GET_UINT_FROM_POINTER(p);
+ p->rng = BLI_rng_new(rng_seed);
+
/* return context data for running paint operator */
return p;
}
@@ -1608,6 +1617,15 @@ static void gp_session_cleanup(tGPsdata *p)
p->inittime = 0.0;
}
+static void gp_session_free(tGPsdata *p)
+{
+ if (p->rng != NULL) {
+ BLI_rng_free(p->rng);
+ }
+ MEM_freeN(p);
+}
+
+
/* init new stroke */
static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Depsgraph *depsgraph)
{
@@ -1948,9 +1966,7 @@ static void gpencil_draw_exit(bContext *C, wmOperator *op)
/* cleanup */
gp_paint_cleanup(p);
gp_session_cleanup(p);
-
- /* finally, free the temp data */
- MEM_freeN(p);
+ gp_session_free(p);
}
op->customdata = NULL;
diff --git a/source/blender/editors/gpencil/gpencil_undo.c b/source/blender/editors/gpencil/gpencil_undo.c
index 5e2be7c41f0..d35df8bc380 100644
--- a/source/blender/editors/gpencil/gpencil_undo.c
+++ b/source/blender/editors/gpencil/gpencil_undo.c
@@ -179,7 +179,7 @@ void gpencil_undo_push(bGPdata *gpd)
/* create new undo node */
undo_node = MEM_callocN(sizeof(bGPundonode), "gpencil undo node");
- undo_node->gpd = BKE_gpencil_data_duplicate(G.main, gpd, true);
+ undo_node->gpd = BKE_gpencil_data_duplicate(NULL, gpd, true);
cur_node = undo_node;
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index f6d72d9e575..4ee3bdd587e 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -965,7 +965,7 @@ void gp_subdivide_stroke(bGPDstroke *gps, const int new_totpoints)
* \param gps Stroke data
* \param brush Brush data
*/
-void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush)
+void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush, RNG *rng)
{
bGPDspoint *pt1, *pt2, *pt3;
float v1[3];
@@ -998,10 +998,10 @@ void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush)
for (int i = 1; i < gps->totpoints - 1; ++i) {
bGPDspoint *pt = &gps->points[i];
/* get vector with shift (apply a division because random is too sensitive */
- const float fac = BLI_frand() * (brush->draw_random_sub / 10.0f);
+ const float fac = BLI_rng_get_float(rng) * (brush->draw_random_sub / 10.0f);
float svec[3];
copy_v3_v3(svec, ortho);
- if (BLI_frand() > 0.5f) {
+ if (BLI_rng_get_float(rng) > 0.5f) {
mul_v3_fl(svec, -fac);
}
else {
diff --git a/source/blender/editors/include/ED_manipulator_library.h b/source/blender/editors/include/ED_manipulator_library.h
index b67af4274a6..fca0f5c8806 100644
--- a/source/blender/editors/include/ED_manipulator_library.h
+++ b/source/blender/editors/include/ED_manipulator_library.h
@@ -73,11 +73,18 @@ enum {
ED_MANIPULATOR_ARROW_STYLE_CONE = 3,
};
+/* transform */
enum {
/* inverted offset during interaction - if set it also sets constrained below */
- ED_MANIPULATOR_ARROW_STYLE_INVERTED = (1 << 3),
+ ED_MANIPULATOR_ARROW_XFORM_FLAG_INVERTED = (1 << 3),
/* clamp arrow interaction to property width */
- ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED = (1 << 4),
+ ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED = (1 << 4),
+};
+
+/* draw_options */
+enum {
+ /* Show arrow stem. */
+ ED_MANIPULATOR_ARROW_DRAW_FLAG_STEM = (1 << 0),
};
void ED_manipulator_arrow3d_set_ui_range(struct wmManipulator *mpr, const float min, const float max);
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 0d323258a19..a9c9e8c0fbd 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -83,7 +83,7 @@ void EDBM_mesh_clear(struct BMEditMesh *em);
void EDBM_selectmode_to_scene(struct bContext *C);
void EDBM_mesh_make(struct Object *ob, const int select_mode, const bool add_key_index);
void EDBM_mesh_free(struct BMEditMesh *em);
-void EDBM_mesh_load(struct Object *ob);
+void EDBM_mesh_load(struct Main *bmain, struct Object *ob);
struct DerivedMesh *EDBM_mesh_deform_dm_get(struct BMEditMesh *em);
/* flushes based on the current select mode. if in vertex select mode,
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index f1311233f23..29f7edaebf0 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -40,6 +40,7 @@ struct Base;
struct EnumPropertyItem;
struct ID;
struct Main;
+struct Menu;
struct ModifierData;
struct Object;
struct ReportList;
@@ -58,12 +59,14 @@ struct PointerRNA;
struct PropertyRNA;
struct EnumPropertyItem;
struct Depsgraph;
+struct uiLayout;
#include "DNA_object_enums.h"
/* object_edit.c */
struct Object *ED_object_context(struct bContext *C); /* context.object */
struct Object *ED_object_active_context(struct bContext *C); /* context.object or context.active_object */
+void ED_hide_collections_menu_draw(const struct bContext *C, struct uiLayout *layout);
/* object_ops.c */
void ED_operatortypes_object(void);
@@ -245,7 +248,7 @@ int ED_object_modifier_convert(
struct ReportList *reports, struct Main *bmain, struct Scene *scene,
struct ViewLayer *view_layer, struct Object *ob, struct ModifierData *md);
int ED_object_modifier_apply(
- struct ReportList *reports, struct Depsgraph *depsgraph, struct Scene *scene,
+ struct Main *bmain, struct ReportList *reports, struct Depsgraph *depsgraph, struct Scene *scene,
struct Object *ob, struct ModifierData *md, int mode);
int ED_object_modifier_copy(struct ReportList *reports, struct Object *ob, struct ModifierData *md);
@@ -277,7 +280,4 @@ void ED_object_facemap_face_remove(struct Object *ob, struct bFaceMap *fmap, int
}
#endif
-/* Don't allow switching object-modes when selecting objects. */
-#define USE_OBJECT_MODE_STRICT
-
#endif /* __ED_OBJECT_H__ */
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index a741f12c112..204c5fa5956 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -69,22 +69,33 @@ void ED_region_do_layout(struct bContext *C, struct ARegion *ar);
void ED_region_do_draw(struct bContext *C, struct ARegion *ar);
void ED_region_exit(struct bContext *C, struct ARegion *ar);
void ED_region_pixelspace(struct ARegion *ar);
-void ED_region_update_rect(struct bContext *C, struct ARegion *ar);
-void ED_region_init(struct bContext *C, struct ARegion *ar);
+void ED_region_update_rect(struct ARegion *ar);
+void ED_region_init(struct ARegion *ar);
void ED_region_tag_redraw(struct ARegion *ar);
void ED_region_tag_redraw_partial(struct ARegion *ar, const struct rcti *rct);
void ED_region_tag_redraw_overlay(struct ARegion *ar);
void ED_region_tag_redraw_no_rebuild(struct ARegion *ar);
void ED_region_tag_refresh_ui(struct ARegion *ar);
-void ED_region_panels_init(struct wmWindowManager *wm, struct ARegion *ar);
-void ED_region_panels(
- const struct bContext *C, struct ARegion *ar,
- const char *contexts[], int contextnr,
- const bool vertical);
-void ED_region_header_init(struct ARegion *ar);
-void ED_region_header(const struct bContext *C, struct ARegion *ar);
-void ED_region_header_layout(const struct bContext *C, struct ARegion *ar);
-void ED_region_header_draw(const struct bContext *C, struct ARegion *ar);
+
+void ED_region_panels_init(struct wmWindowManager *wm, struct ARegion *ar);
+void ED_region_panels_ex(
+ const struct bContext *C, struct ARegion *ar,
+ const char *contexts[], int contextnr, const bool vertical);
+void ED_region_panels(
+ const struct bContext *C, struct ARegion *ar);
+void ED_region_panels_layout_ex(
+ const struct bContext *C, struct ARegion *ar,
+ const char *contexts[], int contextnr, const bool vertical);
+void ED_region_panels_layout(
+ const struct bContext *C, struct ARegion *ar);
+void ED_region_panels_draw(
+ const struct bContext *C, struct ARegion *ar);
+
+void ED_region_header_init(struct ARegion *ar);
+void ED_region_header(const struct bContext *C, struct ARegion *ar);
+void ED_region_header_layout(const struct bContext *C, struct ARegion *ar);
+void ED_region_header_draw(const struct bContext *C, struct ARegion *ar);
+
void ED_region_cursor_set(struct wmWindow *win, struct ScrArea *sa, struct ARegion *ar);
void ED_region_toggle_hidden(struct bContext *C, struct ARegion *ar);
void ED_region_visibility_change_update(struct bContext *C, struct ARegion *ar);
@@ -308,6 +319,11 @@ void ED_region_cache_draw_background(const struct ARegion *ar);
void ED_region_cache_draw_curfra_label(const int framenr, const float x, const float y);
void ED_region_cache_draw_cached_segments(const struct ARegion *ar, const int num_segments, const int *points, const int sfra, const int efra);
+/* interface_region_hud.c */
+struct ARegionType *ED_area_type_hud(int space_type);
+void ED_area_type_hud_clear(struct wmWindowManager *wm, ScrArea *sa_keep);
+void ED_area_type_hud_ensure(struct bContext *C, struct ScrArea *sa);
+
/* default keymaps, bitflags */
#define ED_KEYMAP_UI 1
#define ED_KEYMAP_VIEW2D 2
diff --git a/source/blender/editors/include/ED_undo.h b/source/blender/editors/include/ED_undo.h
index 5103ac97361..37744e7eb0f 100644
--- a/source/blender/editors/include/ED_undo.h
+++ b/source/blender/editors/include/ED_undo.h
@@ -52,14 +52,6 @@ int ED_undo_operator_repeat(struct bContext *C, struct wmOperator *op);
void ED_undo_operator_repeat_cb(struct bContext *C, void *arg_op, void *arg_unused);
void ED_undo_operator_repeat_cb_evt(struct bContext *C, void *arg_op, int arg_unused);
-/* Context sanity helpers for operator repeat. */
-typedef struct OperatorRepeatContextHandle OperatorRepeatContextHandle;
-
-const OperatorRepeatContextHandle *ED_operator_repeat_prepare_context(
- struct bContext *C, struct wmOperator *op) ATTR_WARN_UNUSED_RESULT;
-void ED_operator_repeat_reset_context(
- struct bContext *C, const OperatorRepeatContextHandle *context_info);
-
bool ED_undo_is_valid(const struct bContext *C, const char *undoname);
struct UndoStack *ED_undo_stack_get(void);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 24e5b3e2662..343bffa0082 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -351,12 +351,19 @@ typedef enum {
VIEW3D_SELECT_PICK_NEAREST = 2,
} eV3DSelectMode;
+typedef enum {
+ /* Don't exclude anything. */
+ VIEW3D_SELECT_FILTER_NOP = 0,
+ /* Don't select objects outside the current mode. */
+ VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK = 1,
+} eV3DSelectObjectFilter;
+
void view3d_opengl_select_cache_begin(void);
void view3d_opengl_select_cache_end(void);
int view3d_opengl_select(
struct ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const struct rcti *input,
- eV3DSelectMode select_mode);
+ eV3DSelectMode select_mode, eV3DSelectObjectFilter select_filter);
/* view3d_select.c */
float ED_view3d_select_dist_px(void);
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 3bc1255d23f..03c99bb7f0d 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -113,9 +113,7 @@ DEF_ICON(FILE_TICK)
DEF_ICON(QUIT)
DEF_ICON(URL)
DEF_ICON(RECOVER_LAST)
-#ifndef DEF_ICON_BLANK_SKIP
- DEF_ICON(BLANK038)
-#endif
+DEF_ICON(PRESET)
DEF_ICON(FULLSCREEN_ENTER)
DEF_ICON(FULLSCREEN_EXIT)
DEF_ICON(BLANK1) // Not actually blank - this is used all over the place
@@ -294,8 +292,10 @@ DEF_ICON(RNA_ADD)
DEF_ICON(BLANK112)
DEF_ICON(BLANK113)
DEF_ICON(BLANK114)
- DEF_ICON(BLANK115)
- DEF_ICON(BLANK116)
+#endif
+DEF_ICON(RESTRICT_VIEW_OFF)
+DEF_ICON(RESTRICT_VIEW_ON)
+#ifndef DEF_ICON_BLANK_SKIP
DEF_ICON(BLANK116b)
#endif
@@ -321,8 +321,8 @@ DEF_ICON(OUTLINER_OB_LIGHTPROBE)
#endif
DEF_ICON(RESTRICT_COLOR_OFF)
DEF_ICON(RESTRICT_COLOR_ON)
-DEF_ICON(RESTRICT_VIEW_OFF)
-DEF_ICON(RESTRICT_VIEW_ON)
+DEF_ICON(HIDE_OFF)
+DEF_ICON(HIDE_ON)
DEF_ICON(RESTRICT_SELECT_OFF)
DEF_ICON(RESTRICT_SELECT_ON)
DEF_ICON(RESTRICT_RENDER_OFF)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index c82a320268f..0b4817c8049 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -830,6 +830,7 @@ struct Panel *UI_panel_begin(struct ScrArea *sa, struct ARegion *ar, struct List
void UI_panel_end(uiBlock *block, int width, int height);
void UI_panels_scale(struct ARegion *ar, float new_width);
void UI_panel_label_offset(struct uiBlock *block, int *x, int *y);
+int UI_panel_size_y(const struct Panel *pa);
bool UI_panel_category_is_visible(struct ARegion *ar);
void UI_panel_category_add(struct ARegion *ar, const char *name);
@@ -905,7 +906,7 @@ void UI_exit(void);
#define UI_ITEM_O_DEPRESS (1 << 9)
#define UI_ITEM_R_COMPACT (1 << 10)
-#define UI_HEADER_OFFSET_START ((void)0, 0.4f * UI_UNIT_X)
+#define UI_HEADER_OFFSET ((void)0, 0.2f * UI_UNIT_X)
/* uiLayoutOperatorButs flags */
enum {
@@ -963,6 +964,7 @@ void uiLayoutSetScaleX(uiLayout *layout, float scale);
void uiLayoutSetScaleY(uiLayout *layout, float scale);
void uiLayoutSetEmboss(uiLayout *layout, char emboss);
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep);
+void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep);
int uiLayoutGetOperatorContext(uiLayout *layout);
bool uiLayoutGetActive(uiLayout *layout);
@@ -975,6 +977,7 @@ float uiLayoutGetScaleX(uiLayout *layout);
float uiLayoutGetScaleY(uiLayout *layout);
int uiLayoutGetEmboss(uiLayout *layout);
bool uiLayoutGetPropSep(uiLayout *layout);
+bool uiLayoutGetPropDecorate(uiLayout *layout);
/* layout specifiers */
uiLayout *uiLayoutRow(uiLayout *layout, int align);
@@ -1030,6 +1033,7 @@ uiLayout *uiTemplateConstraint(uiLayout *layout, struct PointerRNA *ptr);
void uiTemplatePreview(uiLayout *layout, struct bContext *C, struct ID *id, int show_buttons, struct ID *parent,
struct MTex *slot, const char *preview_id);
void uiTemplateColorRamp(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int expand);
+void uiTemplateIcon(uiLayout *layout, int icon_value, float icon_scale);
void uiTemplateIconView(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int show_labels, float icon_scale);
void uiTemplateHistogram(uiLayout *layout, struct PointerRNA *ptr, const char *propname);
void uiTemplateWaveform(uiLayout *layout, struct PointerRNA *ptr, const char *propname);
@@ -1255,5 +1259,7 @@ void UI_widgetbase_draw_cache_end(void);
#define USE_UI_POPOVER_ONCE
bool UI_but_is_tool(const uiBut *but);
+#define UI_but_is_decorator(but) \
+ ((but)->func == ui_but_anim_decorate_cb)
#endif /* __UI_INTERFACE_H__ */
diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt
index 49fe6bfb2dc..07ba3b90e11 100644
--- a/source/blender/editors/interface/CMakeLists.txt
+++ b/source/blender/editors/interface/CMakeLists.txt
@@ -58,6 +58,7 @@ set(SRC
interface_panel.c
interface_regions.c
interface_region_color_picker.c
+ interface_region_hud.c
interface_region_menu_pie.c
interface_region_menu_popup.c
interface_region_popover.c
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 811bd4457d8..8c37054098b 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -243,19 +243,44 @@ static void ui_update_flexible_spacing(const ARegion *region, uiBlock *block)
rcti rect;
ui_but_to_pixelrect(&rect, region, block, block->buttons.last);
- const float buttons_width = (float)rect.xmax + UI_HEADER_OFFSET_START;
+ const float buttons_width = (float)rect.xmax + UI_HEADER_OFFSET;
const float region_width = (float)region->sizex * U.dpi_fac;
if (region_width <= buttons_width) {
return;
}
- const float spacing = ((region_width - buttons_width) / (float)sepr_flex_len);
- float offset = 0;
+ /* We could get rid of this loop if we agree on a max number of spacer */
+ int *spacers_pos = alloca(sizeof(*spacers_pos) * (size_t)sepr_flex_len);
+ int i = 0;
+ for (uiBut *but = block->buttons.first; but; but = but->next) {
+ if (but->type == UI_BTYPE_SEPR_SPACER) {
+ ui_but_to_pixelrect(&rect, region, block, but);
+ spacers_pos[i] = rect.xmax + UI_HEADER_OFFSET;
+ i++;
+ }
+ }
+
+ const float segment_width = region_width / (float)sepr_flex_len;
+ float offset = 0, remaining_space = region_width - buttons_width;
+ i = 0;
for (uiBut *but = block->buttons.first; but; but = but->next) {
BLI_rctf_translate(&but->rect, offset, 0);
if (but->type == UI_BTYPE_SEPR_SPACER) {
- offset += spacing;
+ /* How much the next block overlap with the current segment */
+ int overlap = (
+ (i == sepr_flex_len - 1) ?
+ buttons_width - spacers_pos[i] :
+ (spacers_pos[i + 1] - spacers_pos[i]) / 2);
+ int segment_end = segment_width * (i + 1);
+ int spacer_end = segment_end - overlap;
+ int spacer_sta = spacers_pos[i] + offset;
+ if (spacer_end > spacer_sta) {
+ float step = min_ff(remaining_space, spacer_end - spacer_sta);
+ remaining_space -= step;
+ offset += step;
+ }
+ i++;
}
}
ui_block_bounds_calc(block);
@@ -1247,6 +1272,9 @@ 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);
+ if (UI_but_is_decorator(but)) {
+ ui_but_anim_decorate_update_from_flag(but);
+ }
}
diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c
index fc0ad7e5dce..cda70d405ad 100644
--- a/source/blender/editors/interface/interface_anim.c
+++ b/source/blender/editors/interface/interface_anim.c
@@ -103,6 +103,30 @@ void ui_but_anim_flag(uiBut *but, float cfra)
}
}
+void ui_but_anim_decorate_update_from_flag(uiBut *but)
+{
+ BLI_assert(UI_but_is_decorator(but) && but->prev);
+ int flag = but->prev->flag;
+ if (flag & UI_BUT_DRIVEN) {
+ but->icon = ICON_AUTO;
+ }
+ else if (flag & UI_BUT_ANIMATED_KEY) {
+ but->icon = ICON_SPACE2;
+ }
+ else if (flag & UI_BUT_ANIMATED) {
+ but->icon = ICON_SPACE3;
+ }
+ else if (flag & UI_BUT_OVERRIDEN) {
+ but->icon = ICON_LIBRARY_DATA_OVERRIDE;
+ }
+ else {
+ but->icon = ICON_DOT;
+ }
+
+ const int flag_copy = (UI_BUT_DISABLED | UI_BUT_INACTIVE);
+ but->flag = (but->flag & ~flag_copy) | (flag & flag_copy);
+}
+
/**
* \a str can be NULL to only perform check if \a but has an expression at all.
* \return if button has an expression.
@@ -299,3 +323,38 @@ void ui_but_anim_paste_driver(bContext *C)
/* this operator calls UI_context_active_but_prop_get */
WM_operator_name_call(C, "ANIM_OT_paste_driver_button", WM_OP_INVOKE_DEFAULT, NULL);
}
+
+void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy))
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ uiBut *but = arg_but;
+ but = but->prev;
+
+ /* FIXME(campbell), swapping active pointer is weak. */
+ SWAP(struct uiHandleButtonData *, but->active, but->next->active);
+ wm->op_undo_depth++;
+
+ if (but->flag & UI_BUT_DRIVEN) {
+ /* pass */
+ /* TODO: report? */
+ }
+ else if (but->flag & UI_BUT_ANIMATED_KEY) {
+ PointerRNA props_ptr;
+ wmOperatorType *ot = WM_operatortype_find("ANIM_OT_keyframe_delete_button", false);
+ WM_operator_properties_create_ptr(&props_ptr, ot);
+ RNA_boolean_set(&props_ptr, "all", but->rnaindex == -1);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
+ WM_operator_properties_free(&props_ptr);
+ }
+ else {
+ PointerRNA props_ptr;
+ wmOperatorType *ot = WM_operatortype_find("ANIM_OT_keyframe_insert_button", false);
+ WM_operator_properties_create_ptr(&props_ptr, ot);
+ RNA_boolean_set(&props_ptr, "all", but->rnaindex == -1);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
+ WM_operator_properties_free(&props_ptr);
+ }
+
+ SWAP(struct uiHandleButtonData *, but->active, but->next->active);
+ wm->op_undo_depth--;
+}
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 02844f5e861..63bf29a26ea 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -58,6 +58,7 @@
#include "PIL_time.h"
+#include "BKE_addon.h"
#include "BKE_colorband.h"
#include "BKE_blender_undo.h"
#include "BKE_brush.h"
@@ -1267,6 +1268,34 @@ static void ui_multibut_states_apply(bContext *C, uiHandleButtonData *data, uiBl
#ifdef USE_DRAG_TOGGLE
+/* Helpers that wrap boolean functions, to support different kinds of buttons. */
+
+static bool ui_drag_toggle_but_is_supported(const uiBut *but)
+{
+ if (ui_but_is_bool(but)) {
+ return true;
+ }
+ else if (UI_but_is_decorator(but)) {
+ return ELEM(but->icon, ICON_SPACE2, ICON_SPACE3, ICON_DOT, ICON_LIBRARY_DATA_OVERRIDE);
+ }
+ else {
+ return false;
+ }
+}
+
+static bool ui_drag_toggle_but_is_pushed(uiBut *but)
+{
+ if (ui_but_is_bool(but)) {
+ return ui_but_is_pushed(but);
+ }
+ else if (UI_but_is_decorator(but)) {
+ return (but->icon == ICON_SPACE2);
+ }
+ else {
+ return false;
+ }
+}
+
typedef struct uiDragToggleHandle {
/* init */
bool is_init;
@@ -1304,10 +1333,9 @@ static bool ui_drag_toggle_set_xy_xy(
if (BLI_rctf_isect_segment(&but->rect, xy_a_block, xy_b_block)) {
/* execute the button */
- if (ui_but_is_bool(but) && but->type == but_type_start) {
+ if (ui_drag_toggle_but_is_supported(but) && but->type == but_type_start) {
/* is it pressed? */
- bool is_set_but = ui_but_is_pushed(but);
- BLI_assert(ui_but_is_bool(but) == true);
+ bool is_set_but = ui_drag_toggle_but_is_pushed(but);
if (is_set_but != is_set) {
UI_but_execute(C, but);
if (do_check) {
@@ -1437,7 +1465,7 @@ static int ui_handler_region_drag_toggle(bContext *C, const wmEvent *event, void
static bool ui_but_is_drag_toggle(const uiBut *but)
{
- return ((ui_but_is_bool(but) == true) &&
+ return ((ui_drag_toggle_but_is_supported(but) == true) &&
/* menu check is importnt so the button dragged over isn't removed instantly */
(ui_block_is_menu(but->block) == false));
}
@@ -1745,7 +1773,7 @@ static bool ui_but_drag_init(
button_activate_state(C, but, BUTTON_STATE_EXIT);
data->cancel = true;
#ifdef USE_DRAG_TOGGLE
- if (ui_but_is_bool(but)) {
+ if (ui_drag_toggle_but_is_supported(but)) {
uiDragToggleHandle *drag_info = MEM_callocN(sizeof(*drag_info), __func__);
ARegion *ar_prev;
@@ -1753,7 +1781,7 @@ static bool ui_but_drag_init(
* typically 'button_activate_exit()' handles this */
ui_apply_but_autokey(C, but);
- drag_info->is_set = ui_but_is_pushed(but);
+ drag_info->is_set = ui_drag_toggle_but_is_pushed(but);
drag_info->but_cent_start[0] = BLI_rctf_cent_x(&but->rect);
drag_info->but_cent_start[1] = BLI_rctf_cent_y(&but->rect);
drag_info->but_type_start = but->type;
@@ -3585,10 +3613,50 @@ static uiBut *ui_but_list_row_text_activate(
/* ***************** events for different button types *************** */
+#ifdef USE_DRAG_TOGGLE
+/* Shared by any button that supports drag-toggle. */
+static bool ui_do_but_ANY_drag_toggle(
+ bContext *C, uiBut *but,
+ uiHandleButtonData *data, const wmEvent *event,
+ int *r_retval)
+{
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ if (event->type == LEFTMOUSE && event->val == KM_PRESS && ui_but_is_drag_toggle(but)) {
+#if 0 /* UNUSED */
+ data->togdual = event->ctrl;
+ data->togonly = !event->shift;
+#endif
+ ui_apply_but(C, but->block, but, data, true);
+ button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
+ data->dragstartx = event->x;
+ data->dragstarty = event->y;
+ *r_retval = WM_UI_HANDLER_BREAK;
+ return true;
+ }
+ }
+ else if (data->state == BUTTON_STATE_WAIT_DRAG) {
+ /* note: the 'BUTTON_STATE_WAIT_DRAG' part of 'ui_do_but_EXIT' could be refactored into its own function */
+ data->applied = false;
+ *r_retval = ui_do_but_EXIT(C, but, data, event);
+ return true;
+ }
+ return false;
+}
+#endif /* USE_DRAG_TOGGLE */
+
static int ui_do_but_BUT(
bContext *C, uiBut *but,
uiHandleButtonData *data, const wmEvent *event)
{
+#ifdef USE_DRAG_TOGGLE
+ {
+ int retval;
+ if (ui_do_but_ANY_drag_toggle(C, but, data, event, &retval)) {
+ return retval;
+ }
+ }
+#endif
+
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
button_activate_state(C, but, BUTTON_STATE_WAIT_RELEASE);
@@ -3836,25 +3904,14 @@ static int ui_do_but_TOG(
uiHandleButtonData *data, const wmEvent *event)
{
#ifdef USE_DRAG_TOGGLE
- if (data->state == BUTTON_STATE_HIGHLIGHT) {
- if (event->type == LEFTMOUSE && event->val == KM_PRESS && ui_but_is_drag_toggle(but)) {
-#if 0 /* UNUSED */
- data->togdual = event->ctrl;
- data->togonly = !event->shift;
-#endif
- ui_apply_but(C, but->block, but, data, true);
- button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG);
- data->dragstartx = event->x;
- data->dragstarty = event->y;
- return WM_UI_HANDLER_BREAK;
+ {
+ int retval;
+ if (ui_do_but_ANY_drag_toggle(C, but, data, event, &retval)) {
+ return retval;
}
}
- else if (data->state == BUTTON_STATE_WAIT_DRAG) {
- /* note: the 'BUTTON_STATE_WAIT_DRAG' part of 'ui_do_but_EXIT' could be refactored into its own function */
- data->applied = false;
- return ui_do_but_EXIT(C, but, data, event);
- }
#endif
+
if (data->state == BUTTON_STATE_HIGHLIGHT) {
if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) {
#if 0 /* UNUSED */
@@ -4277,10 +4334,14 @@ static int ui_do_but_NUM(
retval = WM_UI_HANDLER_BREAK; /* allow accumulating values, otherwise scrolling gets preference */
else if (type == WHEELDOWNMOUSE && event->ctrl) {
mx = but->rect.xmin;
+ but->drawflag &= ~UI_BUT_ACTIVE_RIGHT;
+ but->drawflag |= UI_BUT_ACTIVE_LEFT;
click = 1;
}
else if (type == WHEELUPMOUSE && event->ctrl) {
mx = but->rect.xmax;
+ but->drawflag &= ~UI_BUT_ACTIVE_LEFT;
+ but->drawflag |= UI_BUT_ACTIVE_RIGHT;
click = 1;
}
else if (event->val == KM_PRESS) {
@@ -5086,12 +5147,12 @@ static int ui_do_but_COLOR(
rgb_to_hsv_compat_v(col, hsv);
if (event->type == WHEELDOWNMOUSE)
- hsv[2] = CLAMPIS(hsv[2] - 0.05f, 0.0f, 1.0f);
+ hsv[2] = clamp_f(hsv[2] - 0.05f, 0.0f, 1.0f);
else if (event->type == WHEELUPMOUSE)
- hsv[2] = CLAMPIS(hsv[2] + 0.05f, 0.0f, 1.0f);
+ hsv[2] = clamp_f(hsv[2] + 0.05f, 0.0f, 1.0f);
else {
float fac = 0.005 * (event->y - event->prevy);
- hsv[2] = CLAMPIS(hsv[2] + fac, 0.0f, 1.0f);
+ hsv[2] = clamp_f(hsv[2] + fac, 0.0f, 1.0f);
}
hsv_to_rgb_v(hsv, data->vec);
@@ -5810,12 +5871,12 @@ static int ui_do_but_HSVCIRCLE(
}
/* XXX hardcoded keymap check.... */
else if (event->type == WHEELDOWNMOUSE) {
- hsv[2] = CLAMPIS(hsv[2] - 0.05f, 0.0f, 1.0f);
+ hsv[2] = clamp_f(hsv[2] - 0.05f, 0.0f, 1.0f);
ui_but_hsv_set(but); /* converts to rgb */
ui_numedit_apply(C, block, but, data);
}
else if (event->type == WHEELUPMOUSE) {
- hsv[2] = CLAMPIS(hsv[2] + 0.05f, 0.0f, 1.0f);
+ hsv[2] = clamp_f(hsv[2] + 0.05f, 0.0f, 1.0f);
ui_but_hsv_set(but); /* converts to rgb */
ui_numedit_apply(C, block, but, data);
}
@@ -7010,7 +7071,10 @@ static bool ui_but_menu(bContext *C, uiBut *but)
if (ui_block_is_menu(but->block) == false) {
uiItemFullO(layout, "UI_OT_editsource", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL);
}
- uiItemFullO(layout, "UI_OT_edittranslation_init", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL);
+
+ if (BKE_addon_find(&U.addons, "ui_translate")) {
+ uiItemFullO(layout, "UI_OT_edittranslation_init", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL);
+ }
mt = WM_menutype_find("WM_MT_button_context", true);
if (mt) {
@@ -8167,6 +8231,10 @@ void UI_context_update_anim_flag(const bContext *C)
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);
+ if (UI_but_is_decorator(but)) {
+ ui_but_anim_decorate_update_from_flag(but);
+ }
+
ED_region_tag_redraw(ar);
if (but->active) {
@@ -9136,7 +9204,7 @@ static int ui_handle_menu_event(
add_v2_v2v2_int(menu->popup_create_vars.event_xy, menu->popup_create_vars.event_xy, mdiff);
- ui_popup_translate(C, ar, mdiff);
+ ui_popup_translate(ar, mdiff);
}
return retval;
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index c2ada1e3733..64fca05c082 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -77,6 +77,9 @@
#include "UI_interface.h"
#include "UI_interface_icons.h"
+#include "WM_api.h"
+#include "WM_types.h"
+
#include "interface_intern.h"
#ifndef WITH_HEADLESS
@@ -451,49 +454,6 @@ static void icon_verify_datatoc(IconImage *iimg)
}
}
-static void init_matcap_icons(void)
-{
- /* dynamic allocation now, tucking datatoc pointers in DrawInfo */
-#define INIT_MATCAP_ICON(icon_id, name) \
- { \
- unsigned char *rect = (unsigned char *)datatoc_ ##name## _jpg; \
- int size = datatoc_ ##name## _jpg_size; \
- DrawInfo *di; \
- \
- di = def_internal_icon(NULL, icon_id, 0, 0, 96, ICON_TYPE_BUFFER); \
- di->data.buffer.image->datatoc_rect = rect; \
- di->data.buffer.image->datatoc_size = size; \
- } (void)0
-
- INIT_MATCAP_ICON(ICON_MATCAP_01, mc01);
- INIT_MATCAP_ICON(ICON_MATCAP_02, mc02);
- INIT_MATCAP_ICON(ICON_MATCAP_03, mc03);
- INIT_MATCAP_ICON(ICON_MATCAP_04, mc04);
- INIT_MATCAP_ICON(ICON_MATCAP_05, mc05);
- INIT_MATCAP_ICON(ICON_MATCAP_06, mc06);
- INIT_MATCAP_ICON(ICON_MATCAP_07, mc07);
- INIT_MATCAP_ICON(ICON_MATCAP_08, mc08);
- INIT_MATCAP_ICON(ICON_MATCAP_09, mc09);
- INIT_MATCAP_ICON(ICON_MATCAP_10, mc10);
- INIT_MATCAP_ICON(ICON_MATCAP_11, mc11);
- INIT_MATCAP_ICON(ICON_MATCAP_12, mc12);
- INIT_MATCAP_ICON(ICON_MATCAP_13, mc13);
- INIT_MATCAP_ICON(ICON_MATCAP_14, mc14);
- INIT_MATCAP_ICON(ICON_MATCAP_15, mc15);
- INIT_MATCAP_ICON(ICON_MATCAP_16, mc16);
- INIT_MATCAP_ICON(ICON_MATCAP_17, mc17);
- INIT_MATCAP_ICON(ICON_MATCAP_18, mc18);
- INIT_MATCAP_ICON(ICON_MATCAP_19, mc19);
- INIT_MATCAP_ICON(ICON_MATCAP_20, mc20);
- INIT_MATCAP_ICON(ICON_MATCAP_21, mc21);
- INIT_MATCAP_ICON(ICON_MATCAP_22, mc22);
- INIT_MATCAP_ICON(ICON_MATCAP_23, mc23);
- INIT_MATCAP_ICON(ICON_MATCAP_24, mc24);
-
-#undef INIT_MATCAP_ICON
-
-}
-
static void init_internal_icons(void)
{
// bTheme *btheme = UI_GetTheme();
@@ -645,7 +605,7 @@ static void init_iconfile_list(struct ListBase *list)
if ((dir[i].type & S_IFREG)) {
const char *filename = dir[i].relname;
- if (BLI_testextensie(filename, ".png")) {
+ if (BLI_path_extension_check(filename, ".png")) {
/* loading all icons on file start is overkill & slows startup
* its possible they change size after blender load anyway. */
#if 0
@@ -777,14 +737,7 @@ static DrawInfo *icon_create_drawinfo(Icon *icon)
di->type = ICON_TYPE_GEOM;
}
else if (icon_data_type == ICON_DATA_STUDIOLIGHT) {
- const int STUDIOLIGHT_SIZE = 96;
- StudioLight *sl = icon->obj;
di->type = ICON_TYPE_BUFFER;
- IconImage *img = MEM_mallocN(sizeof(IconImage), __func__);
- img->w = STUDIOLIGHT_SIZE;
- img->h = STUDIOLIGHT_SIZE;
- img->rect = BKE_studiolight_preview(sl, STUDIOLIGHT_SIZE, icon->id_type);
- di->data.buffer.image = img;
}
else {
BLI_assert(0);
@@ -850,7 +803,6 @@ void UI_icons_init(int first_dyn_id)
init_iconfile_list(&iconfilelist);
init_internal_icons();
init_brush_icons();
- init_matcap_icons();
#endif
}
@@ -890,6 +842,41 @@ static void icon_create_rect(struct PreviewImage *prv_img, enum eIconSizes size)
static void ui_id_preview_image_render_size(
const bContext *C, Scene *scene, ID *id, PreviewImage *pi, int size, const bool use_job);
+static void ui_studiolight_icon_job_exec(void *customdata, short *UNUSED(stop), short *UNUSED(do_update), float *UNUSED(progress))
+{
+ Icon **tmp = (Icon **)customdata;
+ Icon *icon = *tmp;
+ DrawInfo *di = icon_ensure_drawinfo(icon);
+ StudioLight *sl = icon->obj;
+ BKE_studiolight_preview(di->data.buffer.image->rect, sl, icon->id_type);
+}
+
+static void ui_studiolight_kill_icon_preview_job(wmWindowManager *wm, int icon_id)
+{
+ Icon *icon = BKE_icon_get(icon_id);
+ WM_jobs_kill_type(wm, icon, WM_JOB_TYPE_STUDIOLIGHT);
+ icon->obj = NULL;
+}
+
+static void ui_studiolight_free_function(StudioLight * sl, void* data)
+{
+ wmWindowManager *wm = data;
+
+ // get icons_id, get icons and kill wm jobs
+ if (sl->icon_id_radiance) {
+ ui_studiolight_kill_icon_preview_job(wm, sl->icon_id_radiance);
+ }
+ if (sl->icon_id_irradiance) {
+ ui_studiolight_kill_icon_preview_job(wm, sl->icon_id_irradiance);
+ }
+ if (sl->icon_id_matcap) {
+ ui_studiolight_kill_icon_preview_job(wm, sl->icon_id_matcap);
+ }
+ if (sl->icon_id_matcap_flipped) {
+ ui_studiolight_kill_icon_preview_job(wm, sl->icon_id_matcap_flipped);
+ }
+}
+
void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool big)
{
Icon *icon = BKE_icon_get(icon_id);
@@ -916,6 +903,33 @@ void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool bi
}
break;
}
+ case ICON_TYPE_BUFFER:
+ {
+ if (icon->obj_type == ICON_DATA_STUDIOLIGHT) {
+ if (di->data.buffer.image == NULL) {
+ wmWindowManager *wm = CTX_wm_manager(C);
+ StudioLight *sl = icon->obj;
+ BKE_studiolight_set_free_function(sl, &ui_studiolight_free_function, wm);
+ IconImage *img = MEM_mallocN(sizeof(IconImage), __func__);
+
+ img->w = STUDIOLIGHT_ICON_SIZE;
+ img->h = STUDIOLIGHT_ICON_SIZE;
+ size_t size = STUDIOLIGHT_ICON_SIZE * STUDIOLIGHT_ICON_SIZE * sizeof(uint);
+ img->rect = MEM_mallocN(size, __func__);
+ memset(img->rect, 0, size);
+ di->data.buffer.image = img;
+
+ wmJob *wm_job = WM_jobs_get(wm, CTX_wm_window(C), icon, "StudioLight Icon", 0, WM_JOB_TYPE_STUDIOLIGHT);
+ Icon** tmp = MEM_callocN(sizeof(Icon*), __func__);
+ *tmp = icon;
+ WM_jobs_customdata_set(wm_job, tmp, MEM_freeN);
+ WM_jobs_timer(wm_job, 0.01, 0, NC_WINDOW);
+ WM_jobs_callbacks(wm_job, ui_studiolight_icon_job_exec, NULL, NULL, NULL);
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
+ }
+ }
+ break;
+ }
}
}
}
@@ -1479,7 +1493,7 @@ int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, const bool big
id = RNA_pointer_get(ptr, "texture").data;
}
else if (RNA_struct_is_a(ptr->type, &RNA_DynamicPaintSurface)) {
- DynamicPaintSurface *surface = (DynamicPaintSurface *)ptr->data;
+ DynamicPaintSurface *surface = ptr->data;
if (surface->format == MOD_DPAINT_SURFACE_F_PTEX)
return ICON_TEXTURE_SHADED;
@@ -1488,6 +1502,18 @@ int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, const bool big
else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ)
return ICON_FILE_IMAGE;
}
+ else if (RNA_struct_is_a(ptr->type, &RNA_StudioLight)) {
+ StudioLight *sl = ptr->data;
+ switch (sl->flag & STUDIOLIGHT_FLAG_ORIENTATIONS) {
+ case STUDIOLIGHT_ORIENTATION_CAMERA:
+ return sl->icon_id_irradiance;
+ case STUDIOLIGHT_ORIENTATION_WORLD:
+ default:
+ return sl->icon_id_radiance;
+ case STUDIOLIGHT_ORIENTATION_VIEWNORMAL:
+ return sl->icon_id_matcap;
+ }
+ }
/* get icon from ID */
if (id) {
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index b5bf9be737b..6f029b81e92 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -652,7 +652,7 @@ void ui_pie_menu_level_create(
const EnumPropertyItem *items, int totitem, int context, int flag);
/* interface_region_popup.c */
-void ui_popup_translate(struct bContext *C, struct ARegion *ar, const int mdiff[2]);
+void ui_popup_translate(struct ARegion *ar, const int mdiff[2]);
void ui_popup_block_free(struct bContext *C, uiPopupBlockHandle *handle);
void ui_popup_block_scrolltest(struct uiBlock *block);
@@ -757,8 +757,13 @@ void ui_draw_menu_back(struct uiStyle *style, uiBlock *block, rcti *rect);
void ui_draw_popover_back(ARegion *ar, struct uiStyle *style, uiBlock *block, rcti *rect);
void ui_draw_pie_center(uiBlock *block);
uiWidgetColors *ui_tooltip_get_theme(void);
+
+void ui_draw_widget_back_color(
+ uiWidgetTypeEnum type, bool use_shadow, const rcti *rect,
+ const float color[4]);
+void ui_draw_widget_back(
+ uiWidgetTypeEnum type, bool use_shadow, const rcti *rect);
void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock *block, rcti *rect);
-void ui_draw_search_back(struct uiStyle *style, uiBlock *block, rcti *rect);
extern void ui_draw_but(const struct bContext *C, ARegion *ar, struct uiStyle *style, uiBut *but, rcti *rect);
/* theme color init */
@@ -810,6 +815,9 @@ bool ui_but_anim_expression_set(uiBut *but, const char *str);
bool ui_but_anim_expression_create(uiBut *but, const char *str);
void ui_but_anim_autokey(struct bContext *C, uiBut *but, struct Scene *scene, float cfra);
+void ui_but_anim_decorate_cb(struct bContext *C, void *arg_but, void *arg_dummy);
+void ui_but_anim_decorate_update_from_flag(uiBut *but);
+
/* interface_eyedropper.c */
struct wmKeyMap *eyedropper_modal_keymap(struct wmKeyConfig *keyconf);
struct wmKeyMap *eyedropper_colorband_modal_keymap(struct wmKeyConfig *keyconf);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 9888c6d65cc..3784ab635be 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -50,6 +50,7 @@
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_screen.h"
+#include "BKE_animsys.h"
#include "RNA_access.h"
@@ -63,6 +64,10 @@
#include "interface_intern.h"
+/* Show an icon button after each RNA button to use to quickly set keyframes,
+ * this is a way to display animation/driven/override status, see T54951. */
+#define UI_PROP_DECORATE
+
/************************ Structs and Defines *************************/
#define UI_OPERATOR_ERROR_RET(_ot, _opname, return_statement) \
@@ -132,6 +137,9 @@ enum {
UI_ITEM_BOX_ITEM = 1 << 2, /* The item is "inside" a box item */
UI_ITEM_PROP_SEP = 1 << 3,
+ /* Show an icon button next to each property (to set keyframes, show status).
+ * Enabled by default, depends on 'UI_ITEM_PROP_SEP'. */
+ UI_ITEM_PROP_DECORATE = 1 << 4,
};
typedef struct uiButtonItem {
@@ -1477,6 +1485,19 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
bool is_array;
const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0);
+#ifdef UI_PROP_DECORATE
+ struct {
+ bool use_prop_decorate;
+ int len;
+ uiLayout *layout;
+ uiBut *but;
+ } ui_decorate = {
+ .use_prop_decorate = (
+ ((layout->item.flag & UI_ITEM_PROP_DECORATE) != 0) &&
+ (use_prop_sep && ptr->id.data && id_can_have_animdata(ptr->id.data))),
+ };
+#endif /* UI_PROP_DECORATE */
+
UI_block_layout_set_current(block, layout);
/* retrieve info */
@@ -1558,14 +1579,25 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
/* Split the label / property. */
if (use_prop_sep) {
+ uiLayout *layout_row = NULL;
+#ifdef UI_PROP_DECORATE
+ if (ui_decorate.use_prop_decorate) {
+ layout_row = uiLayoutRow(layout, true);
+ layout_row->space = 0;
+ ui_decorate.len = max_ii(1, len);
+ }
+#endif /* UI_PROP_DECORATE */
+
if (name[0] == '\0') {
/* Ensure we get a column when text is not set. */
- layout = uiLayoutColumn(layout, true);
+ layout = uiLayoutColumn(layout_row ? layout_row : layout, true);
layout->space = 0;
}
else {
const PropertySubType subtype = RNA_property_subtype(prop);
- uiLayout *layout_split = uiLayoutSplit(layout, UI_ITEM_PROP_SEP_DIVIDE, true);
+ uiLayout *layout_split = uiLayoutSplit(
+ layout_row ? layout_row : layout,
+ UI_ITEM_PROP_SEP_DIVIDE, true);
layout_split->space = 0;
uiLayout *layout_sub = uiLayoutColumn(layout_split, true);
layout_sub->space = 0;
@@ -1605,8 +1637,22 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
/* Watch out! We can only write into the new column now. */
layout = uiLayoutColumn(layout_split, true);
layout->space = 0;
- name = "";
+ if ((type == PROP_ENUM) && (flag & UI_ITEM_R_EXPAND)) {
+ /* pass (expanded enums each have their own name) */
+ }
+ else {
+ name = "";
+ }
}
+
+#ifdef UI_PROP_DECORATE
+ if (ui_decorate.use_prop_decorate) {
+ ui_decorate.layout = uiLayoutColumn(layout_row, true);
+ ui_decorate.layout->space = 0;
+ UI_block_layout_set_current(block, layout);
+ ui_decorate.but = block->buttons.last;
+ }
+#endif /* UI_PROP_DECORATE */
}
/* End split. */
@@ -1655,6 +1701,40 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index
UI_but_flag_enable(but, UI_BUT_LIST_ITEM);
}
+#ifdef UI_PROP_DECORATE
+ if (ui_decorate.use_prop_decorate) {
+ const bool is_anim = RNA_property_animateable(ptr, prop);
+ uiBut *but_decorate = ui_decorate.but ? ui_decorate.but->next : block->buttons.first;
+ uiLayout *layout_col = uiLayoutColumn(ui_decorate.layout, false);
+ layout_col->space = 0;
+ layout_col->emboss = UI_EMBOSS_NONE;
+ int i;
+ for (i = 0; i < ui_decorate.len && but_decorate; i++) {
+ /* The icons are set in 'ui_but_anim_flag' */
+ if (is_anim) {
+ but = uiDefIconBut(
+ block, UI_BTYPE_BUT, 0, ICON_DOT, 0, 0, UI_UNIT_X, UI_UNIT_Y,
+ NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Animate property"));
+ UI_but_func_set(but, ui_but_anim_decorate_cb, but, NULL);
+ but->flag |= UI_BUT_UNDO | UI_BUT_DRAG_LOCK;
+ }
+ else {
+ /* We may show other information here in future, for now use empty space. */
+ but = uiDefIconBut(
+ block, UI_BTYPE_BUT, 0, ICON_BLANK1, 0, 0, UI_UNIT_X, UI_UNIT_Y,
+ NULL, 0.0, 0.0, 0.0, 0.0, "");
+ but->flag |= UI_BUT_DISABLED;
+ }
+ /* Order the decorator after the button we decorate, this is used so we can always
+ * do a quick lookup. */
+ BLI_remlink(&block->buttons, but);
+ BLI_insertlinkafter(&block->buttons, but_decorate, but);
+ but_decorate = but->next;
+ }
+ BLI_assert(ELEM(i, 1, ui_decorate.len));
+ }
+#endif /* UI_PROP_DECORATE */
+
if (no_bg) {
layout->emboss = prev_emboss;
}
@@ -1811,7 +1891,8 @@ static void search_id_collection(StructRNA *ptype, PointerRNA *ptr, PropertyRNA
StructRNA *srna;
/* look for collection property in Main */
- RNA_main_pointer_create(G.main, ptr);
+ /* Note: using global Main is OK-ish here, UI shall not access other Mains anyay... */
+ RNA_main_pointer_create(G_MAIN, ptr);
*prop = NULL;
@@ -1985,12 +2066,15 @@ static uiBut *ui_item_menu(
h = UI_UNIT_Y;
if (layout->root->type == UI_LAYOUT_HEADER) { /* ugly .. */
- if (force_menu) {
- w += UI_UNIT_Y;
+ if (icon == ICON_NONE && force_menu) {
+ /* pass */
+ }
+ else if (force_menu) {
+ w += UI_UNIT_X;
}
else {
if (name[0]) {
- w -= UI_UNIT_Y / 2;
+ w -= UI_UNIT_X / 2;
}
}
}
@@ -3014,10 +3098,16 @@ static void ui_litem_grid_flow_compute(
const float wfac = (float)(parameters->litem_w - (parameters->tot_columns - 1) * parameters->space_x) / tot_w;
for (int col = 0; col < parameters->tot_columns; col++) {
- results->cos_x_array[col] = col ? results->cos_x_array[col - 1] + results->widths_array[col - 1] + parameters->space_x : parameters->litem_x;
+ results->cos_x_array[col] = (
+ col ?
+ results->cos_x_array[col - 1] + results->widths_array[col - 1] + parameters->space_x :
+ parameters->litem_x
+ );
if (parameters->even_columns) {
- /* (< remaining width > - < space between remaining columns >) / < remaining columns > */
- results->widths_array[col] = ((parameters->litem_w - (results->cos_x_array[col] - parameters->litem_x)) - (parameters->tot_columns - col - 1) * parameters->space_x) / (parameters->tot_columns - col);
+ /* (< remaining width > - < space between remaining columns >) / < remaining columns > */
+ results->widths_array[col] = (
+ ((parameters->litem_w - (results->cos_x_array[col] - parameters->litem_x)) -
+ (parameters->tot_columns - col - 1) * parameters->space_x) / (parameters->tot_columns - col));
}
else if (col == parameters->tot_columns - 1) {
/* Last column copes width rounding errors... */
@@ -3036,7 +3126,10 @@ static void ui_litem_grid_flow_compute(
else {
results->heights_array[row] = max_h[row];
}
- results->cos_y_array[row] = row ? results->cos_y_array[row - 1] - parameters->space_y - results->heights_array[row] : parameters->litem_y - results->heights_array[row];
+ results->cos_y_array[row] = (
+ row ?
+ results->cos_y_array[row - 1] - parameters->space_y - results->heights_array[row] :
+ parameters->litem_y - results->heights_array[row]);
}
}
@@ -3068,22 +3161,22 @@ static void ui_litem_estimate_grid_flow(uiLayout *litem)
int max_h;
ui_litem_grid_flow_compute(
- &litem->items,
- &((UILayoutGridFlowInput) {
- .row_major = gflow->row_major,
- .even_columns = gflow->even_columns,
- .even_rows = gflow->even_rows,
- .litem_w = litem->w,
- .litem_x = litem->x,
- .litem_y = litem->y,
- .space_x = space_x,
- .space_y = space_y,
- }),
- &((UILayoutGridFlowOutput) {
- .tot_items = &gflow->tot_items,
- .global_avg_w = &avg_w,
- .global_max_h = &max_h,
- }));
+ &litem->items,
+ &((UILayoutGridFlowInput) {
+ .row_major = gflow->row_major,
+ .even_columns = gflow->even_columns,
+ .even_rows = gflow->even_rows,
+ .litem_w = litem->w,
+ .litem_x = litem->x,
+ .litem_y = litem->y,
+ .space_x = space_x,
+ .space_y = space_y,
+ }),
+ &((UILayoutGridFlowOutput) {
+ .tot_items = &gflow->tot_items,
+ .global_avg_w = &avg_w,
+ .global_max_h = &max_h,
+ }));
if (gflow->tot_items == 0) {
litem->w = litem->h = 0;
@@ -3153,23 +3246,23 @@ static void ui_litem_estimate_grid_flow(uiLayout *litem)
int tot_w, tot_h;
ui_litem_grid_flow_compute(
- &litem->items,
- &((UILayoutGridFlowInput) {
- .row_major = gflow->row_major,
- .even_columns = gflow->even_columns,
- .even_rows = gflow->even_rows,
- .litem_w = litem->w,
- .litem_x = litem->x,
- .litem_y = litem->y,
- .space_x = space_x,
- .space_y = space_y,
- .tot_columns = gflow->tot_columns,
- .tot_rows = gflow->tot_rows,
- }),
- &((UILayoutGridFlowOutput) {
- .tot_w = &tot_w,
- .tot_h = &tot_h,
- }));
+ &litem->items,
+ &((UILayoutGridFlowInput) {
+ .row_major = gflow->row_major,
+ .even_columns = gflow->even_columns,
+ .even_rows = gflow->even_rows,
+ .litem_w = litem->w,
+ .litem_x = litem->x,
+ .litem_y = litem->y,
+ .space_x = space_x,
+ .space_y = space_y,
+ .tot_columns = gflow->tot_columns,
+ .tot_rows = gflow->tot_rows,
+ }),
+ &((UILayoutGridFlowOutput) {
+ .tot_w = &tot_w,
+ .tot_h = &tot_h,
+ }));
litem->w = tot_w;
litem->h = tot_h;
@@ -3201,25 +3294,25 @@ static void ui_litem_layout_grid_flow(uiLayout *litem)
/* This time we directly compute coordinates and sizes of all cells. */
ui_litem_grid_flow_compute(
- &litem->items,
- &((UILayoutGridFlowInput) {
- .row_major = gflow->row_major,
- .even_columns = gflow->even_columns,
- .even_rows = gflow->even_rows,
- .litem_w = litem->w,
- .litem_x = litem->x,
- .litem_y = litem->y,
- .space_x = space_x,
- .space_y = space_y,
- .tot_columns = gflow->tot_columns,
- .tot_rows = gflow->tot_rows,
- }),
- &((UILayoutGridFlowOutput) {
- .cos_x_array = cos_x,
- .cos_y_array = cos_y,
- .widths_array = widths,
- .heights_array = heights,
- }));
+ &litem->items,
+ &((UILayoutGridFlowInput) {
+ .row_major = gflow->row_major,
+ .even_columns = gflow->even_columns,
+ .even_rows = gflow->even_rows,
+ .litem_w = litem->w,
+ .litem_x = litem->x,
+ .litem_y = litem->y,
+ .space_x = space_x,
+ .space_y = space_y,
+ .tot_columns = gflow->tot_columns,
+ .tot_rows = gflow->tot_rows,
+ }),
+ &((UILayoutGridFlowOutput) {
+ .cos_x_array = cos_x,
+ .cos_y_array = cos_y,
+ .widths_array = widths,
+ .heights_array = heights,
+ }));
for (item = litem->items.first, i = 0; item; item = item->next, i++) {
const int col = gflow->row_major ? i % gflow->tot_columns : i / gflow->tot_rows;
@@ -3422,7 +3515,7 @@ static void ui_litem_init_from_parent(uiLayout *litem, uiLayout *layout, int ali
litem->redalert = layout->redalert;
litem->w = layout->w;
litem->emboss = layout->emboss;
- litem->item.flag = (layout->item.flag & UI_ITEM_PROP_SEP);
+ litem->item.flag = (layout->item.flag & (UI_ITEM_PROP_SEP | UI_ITEM_PROP_DECORATE));
BLI_addtail(&layout->items, litem);
}
@@ -3687,6 +3780,16 @@ void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
SET_FLAG_FROM_TEST(layout->item.flag, is_sep, UI_ITEM_PROP_SEP);
}
+bool uiLayoutGetPropDecorate(uiLayout *layout)
+{
+ return (layout->item.flag & UI_ITEM_PROP_DECORATE) != 0;
+}
+
+void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
+{
+ SET_FLAG_FROM_TEST(layout->item.flag, is_sep, UI_ITEM_PROP_DECORATE);
+}
+
bool uiLayoutGetActive(uiLayout *layout)
{
return layout->active;
@@ -3989,6 +4092,9 @@ uiLayout *UI_block_layout(uiBlock *block, int dir, int type, int x, int y, int s
layout = MEM_callocN(sizeof(uiLayout), "uiLayout");
layout->item.type = ITEM_LAYOUT_ROOT;
+ /* Only used when 'UI_ITEM_PROP_SEP' is set. */
+ layout->item.flag = UI_ITEM_PROP_DECORATE;
+
layout->x = x;
layout->y = y;
layout->root = root;
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 6fcede58737..aad48d13277 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -1004,6 +1004,7 @@ static int editsource_exec(bContext *C, wmOperator *op)
ui_editsource_active_but_set(but);
/* redraw and get active button python info */
+ ED_region_do_layout(C, ar);
ED_region_do_draw(C, ar);
ar->do_draw = false;
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index dbdf2a0863c..e383ae42f8c 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -110,7 +110,7 @@ typedef struct uiHandlePanelData {
int startsizex, startsizey;
} uiHandlePanelData;
-static int get_panel_real_size_y(Panel *pa);
+static int get_panel_real_size_y(const Panel *pa);
static void panel_activate_state(const bContext *C, Panel *pa, uiHandlePanelState state);
/*********************** space specific code ************************/
@@ -855,7 +855,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
/************************** panel alignment *************************/
-static int get_panel_header(Panel *pa)
+static int get_panel_header(const Panel *pa)
{
if (pa->type && (pa->type->flag & PNL_NO_HEADER))
return 0;
@@ -863,7 +863,7 @@ static int get_panel_header(Panel *pa)
return PNL_HEADER;
}
-static int get_panel_size_y(Panel *pa)
+static int get_panel_size_y(const Panel *pa)
{
if (pa->type && (pa->type->flag & PNL_NO_HEADER))
return pa->sizey;
@@ -871,7 +871,7 @@ static int get_panel_size_y(Panel *pa)
return PNL_HEADER + pa->sizey;
}
-static int get_panel_real_size_y(Panel *pa)
+static int get_panel_real_size_y(const Panel *pa)
{
int sizey = (pa->flag & PNL_CLOSED) ? 0 : pa->sizey;
@@ -881,6 +881,11 @@ static int get_panel_real_size_y(Panel *pa)
return PNL_HEADER + sizey;
}
+int UI_panel_size_y(const Panel *pa)
+{
+ return get_panel_real_size_y(pa);
+}
+
/* this function is needed because uiBlock and Panel itself don't
* change sizey or location when closed */
static int get_panel_real_ofsy(Panel *pa)
@@ -1596,6 +1601,10 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
ED_region_tag_redraw(ar);
}
else if (show_drag && BLI_rctf_isect_x(&rect_drag, mx)) {
+ /* XXX, for now don't allow dragging in floating windows yet. */
+ if (ar->alignment == RGN_ALIGN_FLOAT) {
+ return;
+ }
panel_activate_state(C, block->panel, PANEL_STATE_DRAG);
}
else if (show_pin && BLI_rctf_isect_x(&rect_pin, mx)) {
diff --git a/source/blender/editors/interface/interface_region_color_picker.c b/source/blender/editors/interface/interface_region_color_picker.c
index 4309e913d9e..00462b456ea 100644
--- a/source/blender/editors/interface/interface_region_color_picker.c
+++ b/source/blender/editors/interface/interface_region_color_picker.c
@@ -585,7 +585,7 @@ static int ui_colorpicker_small_wheel_cb(const bContext *UNUSED(C), uiBlock *blo
ui_rgb_to_color_picker_compat_v(rgb, hsv);
- hsv[2] = CLAMPIS(hsv[2] + add, 0.0f, 1.0f);
+ hsv[2] = clamp_f(hsv[2] + add, 0.0f, 1.0f);
ui_color_picker_to_rgb_v(hsv, rgb);
if (use_display_colorspace)
diff --git a/source/blender/editors/interface/interface_region_hud.c b/source/blender/editors/interface/interface_region_hud.c
new file mode 100644
index 00000000000..1a49010ad9d
--- /dev/null
+++ b/source/blender/editors/interface/interface_region_hud.c
@@ -0,0 +1,338 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/interface/interface_region_hud.c
+ * \ingroup edinterface
+ *
+ * Floating Persistent Region
+ */
+
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_userdef_types.h"
+
+#include "BLI_string.h"
+#include "BLI_rect.h"
+#include "BLI_listbase.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_screen.h"
+#include "BKE_main.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+
+#include "BIF_gl.h"
+
+#include "UI_interface.h"
+#include "UI_view2d.h"
+
+#include "BLT_translation.h"
+
+#include "ED_screen.h"
+#include "ED_undo.h"
+
+#include "interface_intern.h"
+
+
+/* -------------------------------------------------------------------- */
+/** \name Utilities
+ * \{ */
+
+static bool last_redo_poll(const bContext *C)
+{
+ wmOperator *op = WM_operator_last_redo(C);
+ if (op == NULL) {
+ return false;
+ }
+ bool success = false;
+ if (WM_operator_repeat_check(C, op) &&
+ WM_operator_check_ui_empty(op->type) == false)
+ {
+ success = WM_operator_poll((bContext *)C, op->type);
+ }
+ return success;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Redo Panel
+ * \{ */
+
+static int hud_panel_operator_redo_poll(const bContext *C, PanelType *UNUSED(pt))
+{
+ return last_redo_poll(C);
+}
+
+static void hud_panel_operator_redo_draw_header(const bContext *C, Panel *pa)
+{
+ wmOperator *op = WM_operator_last_redo(C);
+ BLI_strncpy(pa->drawname, RNA_struct_ui_name(op->type->srna), sizeof(pa->drawname));
+}
+
+static void hud_panel_operator_redo_draw(const bContext *C, Panel *pa)
+{
+ wmOperator *op = WM_operator_last_redo(C);
+ if (op == NULL) {
+ return;
+ }
+ if (!WM_operator_check_ui_enabled(C, op->type->name)) {
+ uiLayoutSetEnabled(pa->layout, false);
+ }
+ uiLayout *col = uiLayoutColumn(pa->layout, false);
+ uiTemplateOperatorRedoProperties(col, C);
+}
+
+static void hud_panels_register(ARegionType *art, int space_type, int region_type)
+{
+ PanelType *pt;
+
+ pt = MEM_callocN(sizeof(PanelType), __func__);
+ strcpy(pt->idname, "OPERATOR_PT_redo");
+ strcpy(pt->label, N_("Redo"));
+ strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->draw_header = hud_panel_operator_redo_draw_header;
+ pt->draw = hud_panel_operator_redo_draw;
+ pt->poll = hud_panel_operator_redo_poll;
+ pt->space_type = space_type;
+ pt->region_type = region_type;
+ BLI_addtail(&art->paneltypes, pt);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Callbacks for Floating Region
+ * \{ */
+
+struct HudRegionData {
+ short regionid;
+};
+
+static void hud_region_init(wmWindowManager *wm, ARegion *ar)
+{
+ ED_region_panels_init(wm, ar);
+ UI_region_handlers_add(&ar->handlers);
+ ar->flag |= RGN_FLAG_TEMP_REGIONDATA;
+}
+
+static void hud_region_free(ARegion *ar)
+{
+ MEM_SAFE_FREE(ar->regiondata);
+}
+
+static void hud_region_layout(const bContext *C, ARegion *ar)
+{
+ bool ok = false;
+
+ {
+ struct HudRegionData *hrd = ar->regiondata;
+ if (hrd != NULL) {
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar_op = (hrd->regionid != -1) ? BKE_area_find_region_type(sa, hrd->regionid) : NULL;
+ ARegion *ar_prev = CTX_wm_region(C);
+ CTX_wm_region_set((bContext *)C, ar_op);
+ ok = last_redo_poll(C);
+ CTX_wm_region_set((bContext *)C, ar_prev);
+ }
+ }
+
+ if (!ok) {
+ ED_region_tag_redraw(ar);
+ ar->flag |= RGN_FLAG_HIDDEN;
+ return;
+ }
+
+ int size_y = ar->sizey;
+
+ ED_region_panels_layout(C, ar);
+
+ if (ar->panels.first && (ar->sizey != size_y)) {
+ View2D *v2d = &ar->v2d;
+ ar->winx = ar->sizex;
+ ar->winy = ar->sizey;
+
+ ar->winrct.xmax = (ar->winrct.xmin + ar->winx) - 1;
+ ar->winrct.ymax = (ar->winrct.ymin + ar->winy) - 1;
+
+ UI_view2d_region_reinit(v2d, V2D_COMMONVIEW_PANELS_UI, ar->winx, ar->winy);
+ }
+
+ /* restore view matrix */
+ UI_view2d_view_restore(C);
+}
+
+static void hud_region_draw(const bContext *C, ARegion *ar)
+{
+ UI_view2d_view_ortho(&ar->v2d);
+ wmOrtho2_region_pixelspace(ar);
+ glClearColor(0, 0, 0, 0.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ if ((ar->flag & RGN_FLAG_HIDDEN) == 0) {
+ float color[4];
+ UI_GetThemeColor4fv(TH_BUTBACK, color);
+ if ((U.uiflag2 & USER_REGION_OVERLAP) == 0) {
+ color[3] = 1.0f;
+ }
+ ui_draw_widget_back_color(UI_WTYPE_BOX, false, &(rcti){.xmax = ar->winx, .ymax = ar->winy}, color);
+ ED_region_panels_draw(C, ar);
+ }
+}
+
+ARegionType *ED_area_type_hud(int space_type)
+{
+ ARegionType *art = MEM_callocN(sizeof(ARegionType), __func__);
+ art->regionid = RGN_TYPE_HUD;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
+ art->layout = hud_region_layout;
+ art->draw = hud_region_draw;
+ art->init = hud_region_init;
+ art->free = hud_region_free;
+
+ hud_panels_register(art, space_type, art->regionid);
+
+ art->lock = 1; /* can become flag, see BKE_spacedata_draw_locks */
+ return art;
+}
+
+static ARegion *hud_region_add(ScrArea *sa)
+{
+ ARegion *ar = MEM_callocN(sizeof(ARegion), "area region");
+ ARegion *ar_win = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+ if (ar_win) {
+ BLI_insertlinkbefore(&sa->regionbase, ar_win, ar);
+ }
+ else {
+ BLI_addtail(&sa->regionbase, ar);
+ }
+ ar->regiontype = RGN_TYPE_HUD;
+ ar->alignment = RGN_ALIGN_FLOAT;
+ ar->overlap = true;
+ ar->flag |= RGN_FLAG_DYNAMIC_SIZE;
+
+ return ar;
+}
+
+void ED_area_type_hud_clear(wmWindowManager *wm, ScrArea *sa_keep)
+{
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ bScreen *screen = WM_window_get_active_screen(win);
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ if (sa != sa_keep) {
+ for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype == RGN_TYPE_HUD) {
+ if ((ar->flag & RGN_FLAG_HIDDEN) == 0) {
+ ar->flag |= RGN_FLAG_HIDDEN;
+ ED_region_tag_redraw(ar);
+ ED_area_tag_redraw(sa);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void ED_area_type_hud_ensure(bContext *C, ScrArea *sa)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ ED_area_type_hud_clear(wm, sa);
+
+ ARegionType *art = BKE_regiontype_from_id(sa->type, RGN_TYPE_HUD);
+ if (art == NULL) {
+ return;
+ }
+
+ bool init = false;
+ ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_HUD);
+ if (!last_redo_poll(C)) {
+ if (ar) {
+ ED_region_tag_redraw(ar);
+ ar->flag |= RGN_FLAG_HIDDEN;
+ }
+ return;
+ }
+
+ if (ar == NULL) {
+ init = true;
+ ar = hud_region_add(sa);
+ ar->type = art;
+ }
+
+ ED_region_init(ar);
+ ED_region_tag_redraw(ar);
+
+ /* Reset zoom level (not well supported). */
+ ar->v2d.cur = ar->v2d.tot = (rctf){.xmax = ar->winx, .ymax = ar->winy};
+ ar->v2d.minzoom = 1.0f;
+ ar->v2d.maxzoom = 1.0f;
+
+ /* Let 'ED_area_update_region_sizes' do the work of placing the region.
+ * Otherwise we could set the 'ar->winrct' & 'ar->winx/winy' here. */
+ if (init) {
+ sa->flag |= AREA_FLAG_REGION_SIZE_UPDATE;
+ }
+ else {
+ if (ar->flag & RGN_FLAG_HIDDEN) {
+ sa->flag |= AREA_FLAG_REGION_SIZE_UPDATE;
+ }
+ ar->flag &= ~RGN_FLAG_HIDDEN;
+ }
+
+ {
+ ARegion *ar_op = CTX_wm_region(C);
+ BLI_assert((ar_op == NULL) || (ar_op->regiontype != RGN_TYPE_HUD));
+ struct HudRegionData *hrd = ar->regiondata;
+ if (hrd == NULL) {
+ hrd = MEM_callocN(sizeof(*hrd), __func__);
+ ar->regiondata = hrd;
+ }
+ if (ar_op) {
+ hrd->regionid = ar_op->regiontype;
+ }
+ else {
+ hrd->regionid = -1;
+ }
+ }
+
+ /* XXX, should be handled in more general way. */
+ ar->visible = !((ar->flag & RGN_FLAG_HIDDEN) || (ar->flag & RGN_FLAG_TOO_SMALL));
+
+ /* We shouldn't need to do this every time :S */
+ /* XXX, this is evil! - it also makes the menu show on first draw. :( */
+ ARegion *ar_prev = CTX_wm_region(C);
+ CTX_wm_region_set((bContext *)C, ar);
+ hud_region_layout(C, ar);
+ CTX_wm_region_set((bContext *)C, ar_prev);
+}
+
+/** \} */
diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c
index e769d367b45..fb14ca745c6 100644
--- a/source/blender/editors/interface/interface_region_popover.c
+++ b/source/blender/editors/interface/interface_region_popover.c
@@ -168,11 +168,17 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v
block->my = handle->prev_my;
}
- /* Prefer popover from header to be positioned into the editor. */
if (!slideout) {
ScrArea *sa = CTX_wm_area(C);
- if (sa && ED_area_header_alignment(sa) == RGN_ALIGN_BOTTOM) {
- ARegion *ar = CTX_wm_region(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ if (ar && ar->panels.first) {
+ /* For regions with panels, prefer to open to top so we can
+ * see the values of the buttons below changing. */
+ UI_block_direction_set(block, UI_DIR_UP | UI_DIR_CENTER_X);
+ }
+ else if (sa && ED_area_header_alignment(sa) == RGN_ALIGN_BOTTOM) {
+ /* Prefer popover from header to be positioned into the editor. */
if (ar && ar->regiontype == RGN_TYPE_HEADER) {
UI_block_direction_set(block, UI_DIR_UP | UI_DIR_CENTER_X);
}
diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c
index 654dc5e4d30..0ac4d4d28ec 100644
--- a/source/blender/editors/interface/interface_region_popup.c
+++ b/source/blender/editors/interface/interface_region_popup.c
@@ -63,13 +63,13 @@
/**
* Translate any popup regions (so we can drag them).
*/
-void ui_popup_translate(bContext *C, ARegion *ar, const int mdiff[2])
+void ui_popup_translate(ARegion *ar, const int mdiff[2])
{
uiBlock *block;
BLI_rcti_translate(&ar->winrct, UNPACK2(mdiff));
- ED_region_update_rect(C, ar);
+ ED_region_update_rect(ar);
ED_region_tag_redraw(ar);
@@ -625,7 +625,7 @@ uiBlock *ui_popup_block_refresh(
ui_popup_block_scrolltest(block);
/* adds subwindow */
- ED_region_init(C, ar);
+ ED_region_init(ar);
/* get winmat now that we actually have the subwindow */
wmGetProjectionMatrix(block->winmat, &ar->winrct);
@@ -633,7 +633,7 @@ uiBlock *ui_popup_block_refresh(
/* notify change and redraw */
ED_region_tag_redraw(ar);
- ED_region_update_rect(C, ar);
+ ED_region_update_rect(ar);
#ifdef DEBUG
window->eventstate = event_back;
diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.c
index f14f9af8785..e0dc149be17 100644
--- a/source/blender/editors/interface/interface_region_search.c
+++ b/source/blender/editors/interface/interface_region_search.c
@@ -404,8 +404,9 @@ static void ui_searchbox_region_draw_cb(const bContext *C, ARegion *ar)
/* pixel space */
wmOrtho2_region_pixelspace(ar);
- if (data->noback == false)
- ui_draw_search_back(NULL, NULL, &data->bbox); /* style not used yet */
+ if (data->noback == false) {
+ ui_draw_widget_back(UI_WTYPE_BOX, true, &data->bbox);
+ }
/* draw text */
if (data->items.totitem) {
@@ -625,7 +626,7 @@ ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiBut *but
}
/* adds subwindow */
- ED_region_init(C, ar);
+ ED_region_init(ar);
/* notify change and redraw */
ED_region_tag_redraw(ar);
@@ -681,8 +682,9 @@ static void ui_searchbox_region_draw_cb__operator(const bContext *UNUSED(C), ARe
/* pixel space */
wmOrtho2_region_pixelspace(ar);
- if (data->noback == false)
- ui_draw_search_back(NULL, NULL, &data->bbox); /* style not used yet */
+ if (data->noback == false) {
+ ui_draw_widget_back(UI_WTYPE_BOX, true, &data->bbox);
+ }
/* draw text */
if (data->items.totitem) {
diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c
index aa8fe173638..ed83a715c7e 100644
--- a/source/blender/editors/interface/interface_region_tooltip.c
+++ b/source/blender/editors/interface/interface_region_tooltip.c
@@ -867,7 +867,7 @@ static ARegion *ui_tooltip_create_with_data(
}
/* adds subwindow */
- ED_region_init(C, ar);
+ ED_region_init(ar);
/* notify change and redraw */
ED_region_tag_redraw(ar);
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 9978726fa74..59cb2229905 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -500,6 +500,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ED_object_single_user(bmain, scene, (struct Object *)id);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
DEG_relations_tag_update(bmain);
}
@@ -1578,12 +1579,16 @@ void uiTemplateOperatorRedoProperties(uiLayout *layout, const bContext *C)
#endif
if (WM_operator_repeat_check(C, op)) {
+ int layout_flags = 0;
+ if (block->panel == NULL) {
+ layout_flags = UI_TEMPLATE_OP_PROPS_SHOW_TITLE;
+ }
#if 0
bool has_advanced = false;
#endif
UI_block_func_set(block, ED_undo_operator_repeat_cb, op, NULL);
- template_operator_redo_property_buts_draw(C, op, layout, UI_TEMPLATE_OP_PROPS_COMPACT, NULL /* &has_advanced */ );
+ template_operator_redo_property_buts_draw(C, op, layout, layout_flags, NULL /* &has_advanced */ );
UI_block_func_set(block, NULL, NULL, NULL); /* may want to reset to old state instead of NULLing all */
#if 0
@@ -1743,7 +1748,7 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
/* enabled */
UI_block_emboss_set(block, UI_EMBOSS_NONE);
uiItemR(row, &ptr, "mute", 0, "",
- (con->flag & CONSTRAINT_OFF) ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF);
+ (con->flag & CONSTRAINT_OFF) ? ICON_HIDE_ON : ICON_HIDE_OFF);
UI_block_emboss_set(block, UI_EMBOSS);
uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
@@ -2180,6 +2185,19 @@ void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, const char *propname
MEM_freeN(cb);
}
+/********************* Icon Template ************************/
+/**
+ * \param icon_scale: Scale of the icon, 1x == button height.
+ */
+void uiTemplateIcon(uiLayout *layout, int icon_value, float icon_scale)
+{
+ uiBlock *block;
+ uiBut *but;
+
+ block = uiLayoutAbsoluteBlock(layout);
+ but = uiDefIconBut(block, UI_BTYPE_LABEL, 0, ICON_X, 0, 0, UI_UNIT_X * icon_scale, UI_UNIT_Y * icon_scale, NULL, 0.0, 0.0, 0.0, 0.0, "");
+ ui_def_but_icon(but, icon_value, UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
+}
/********************* Icon viewer Template ************************/
typedef struct IconViewMenuArgs {
@@ -2266,13 +2284,20 @@ void uiTemplateIconView(uiLayout *layout, PointerRNA *ptr, const char *propname,
value = RNA_property_enum_get(ptr, prop);
RNA_enum_icon_from_value(items, value, &icon);
- cb_args = MEM_callocN(sizeof(IconViewMenuArgs), __func__);
- cb_args->ptr = *ptr;
- cb_args->prop = prop;
- cb_args->show_labels = show_labels;
- cb_args->icon_scale = icon_scale;
- but = uiDefBlockButN(block, ui_icon_view_menu_cb, cb_args, "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, "");
+ if (RNA_property_editable(ptr, prop)) {
+ cb_args = MEM_callocN(sizeof(IconViewMenuArgs), __func__);
+ cb_args->ptr = *ptr;
+ cb_args->prop = prop;
+ cb_args->show_labels = show_labels;
+ cb_args->icon_scale = icon_scale;
+
+ but = uiDefBlockButN(block, ui_icon_view_menu_cb, cb_args, "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, "");
+ }
+ else {
+ but = uiDefIconBut(block, UI_BTYPE_LABEL, 0, ICON_X, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, NULL, 0.0, 0.0, 0.0, 0.0, "");
+ }
+
ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
@@ -3945,6 +3970,8 @@ eAutoPropButsReturn uiTemplateOperatorPropertyButs(
RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
+ uiLayoutSetPropSep(layout, true);
+
/* main draw call */
return_info = uiDefAutoButsRNA(layout, &ptr, check_prop, label_align, (flag & UI_TEMPLATE_OP_PROPS_COMPACT));
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index ac8d900f560..3b7ccb68fd4 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -230,16 +230,16 @@ static const uint g_shape_preset_hold_action_face[2][3] = {{2, 0, 1}, {3, 5, 4}}
static const int tria_ofs[ROUNDBOX_TRIA_MAX] = {
[ROUNDBOX_TRIA_NONE] = 0,
[ROUNDBOX_TRIA_ARROWS] = 0,
- [ROUNDBOX_TRIA_SCROLL] = 6,
- [ROUNDBOX_TRIA_MENU] = 22,
- [ROUNDBOX_TRIA_CHECK] = 28,
- [ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 34,
+ [ROUNDBOX_TRIA_SCROLL] = 12,
+ [ROUNDBOX_TRIA_MENU] = 28,
+ [ROUNDBOX_TRIA_CHECK] = 34,
+ [ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 40,
};
static const int tria_vcount[ROUNDBOX_TRIA_MAX] = {
[ROUNDBOX_TRIA_NONE] = 0,
- [ROUNDBOX_TRIA_ARROWS] = 3,
+ [ROUNDBOX_TRIA_ARROWS] = 6,
[ROUNDBOX_TRIA_SCROLL] = 16,
- [ROUNDBOX_TRIA_MENU] = 3,
+ [ROUNDBOX_TRIA_MENU] = 6,
[ROUNDBOX_TRIA_CHECK] = 6,
[ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 3,
};
@@ -296,8 +296,8 @@ static uint32_t set_tria_vertex(
int tria_type, int tria_v, int tria_id, int jit_v)
{
uint32_t *data = GWN_vertbuf_raw_step(vflag_step);
- if (ELEM(tria_type, ROUNDBOX_TRIA_ARROWS, ROUNDBOX_TRIA_MENU)) {
- tria_v += tria_id * 3;
+ if (ELEM(tria_type, ROUNDBOX_TRIA_ARROWS)) {
+ tria_v += tria_id * tria_vcount[ROUNDBOX_TRIA_ARROWS];
}
*data = tria_ofs[tria_type] + tria_v;
*data |= jit_v << 6;
@@ -308,7 +308,7 @@ static uint32_t set_tria_vertex(
static void roundbox_batch_add_tria(Gwn_VertBufRaw *vflag_step, int tria, uint32_t last_data)
{
- const int tria_num = ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW) ? 1 : 2;
+ const int tria_num = ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW, ROUNDBOX_TRIA_MENU) ? 1 : 2;
/* for each tria */
for (int t = 0; t < tria_num; ++t) {
for (int j = 0; j < WIDGET_AA_JITTER; j++) {
@@ -335,7 +335,7 @@ Gwn_Batch *ui_batch_roundbox_widget_get(int tria)
vcount += ((WIDGET_CURVE_RESOLU * 2) * 2) * WIDGET_AA_JITTER; /* emboss */
if (tria) {
vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria1 */
- if (!ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW)) {
+ if (!ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW, ROUNDBOX_TRIA_MENU)) {
vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria2 */
}
}
@@ -2657,18 +2657,22 @@ static void widget_state_pie_menu_item(uiWidgetType *wt, int state)
copy_v4_v4_char(wt->wcol.inner, wt->wcol.item);
wt->wcol.inner[3] = 64;
}
- /* regular disabled */
- else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
- widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f);
- }
- /* regular active */
- else if (state & UI_SELECT) {
- copy_v4_v4_char(wt->wcol.outline, wt->wcol.inner_sel);
- copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
- }
- else if (state & UI_ACTIVE) {
- copy_v4_v4_char(wt->wcol.inner, wt->wcol.item);
- copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
+ else {
+ /* regular active */
+ if (state & (UI_SELECT | UI_ACTIVE)) {
+ copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
+ }
+ else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
+ /* regular disabled */
+ widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f);
+ }
+
+ if (state & UI_SELECT) {
+ copy_v4_v4_char(wt->wcol.outline, wt->wcol.inner_sel);
+ }
+ else if (state & UI_ACTIVE) {
+ copy_v4_v4_char(wt->wcol.inner, wt->wcol.item);
+ }
}
}
@@ -2685,14 +2689,19 @@ static void widget_state_menu_item(uiWidgetType *wt, int state)
copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
wt->wcol.inner[3] = 64;
}
- /* regular disabled */
- else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
- widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f);
- }
- /* regular active */
- else if (state & UI_ACTIVE) {
- copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
- copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
+ else {
+ /* regular active */
+ if (state & UI_ACTIVE) {
+ copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel);
+ }
+ else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
+ /* regular disabled */
+ widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f);
+ }
+
+ if (state & UI_ACTIVE) {
+ copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel);
+ }
}
}
@@ -2825,7 +2834,7 @@ void ui_hsvcircle_pos_from_vals(uiBut *but, const rcti *rect, float *hsv, float
else
radius_t = hsv[1];
- radius = CLAMPIS(radius_t, 0.0f, 1.0f) * radius;
+ radius = clamp_f(radius_t, 0.0f, 1.0f) * radius;
*xpos = centx + cosf(-ang) * radius;
*ypos = centy + sinf(-ang) * radius;
}
@@ -4916,30 +4925,41 @@ uiWidgetColors *ui_tooltip_get_theme(void)
return wt->wcol_theme;
}
-void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock *UNUSED(block), rcti *rect)
+/**
+ * Generic drawing for background.
+ */
+void ui_draw_widget_back_color(
+ uiWidgetTypeEnum type, bool use_shadow, const rcti *rect,
+ const float color[4])
{
- uiWidgetType *wt = widget_type(UI_WTYPE_TOOLTIP);
+ uiWidgetType *wt = widget_type(type);
+
+ if (use_shadow) {
+ glEnable(GL_BLEND);
+ widget_softshadow(rect, UI_CNR_ALL, 0.25f * U.widget_unit);
+ glDisable(GL_BLEND);
+ }
+
+ rcti rect_copy = *rect;
wt->state(wt, 0);
- /* wt->draw ends up using same function to draw the tooltip as menu_back */
- wt->draw(&wt->wcol, rect, 0, 0);
+ if (color) {
+ rgba_float_to_uchar((unsigned char *)wt->wcol.inner, color);
+ }
+ wt->draw(&wt->wcol, &rect_copy, 0, UI_CNR_ALL);
}
-
-void ui_draw_search_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
+void ui_draw_widget_back(uiWidgetTypeEnum type, bool use_shadow, const rcti *rect)
{
- uiWidgetType *wt = widget_type(UI_WTYPE_BOX);
-
- glEnable(GL_BLEND);
- widget_softshadow(rect, UI_CNR_ALL, 0.25f * U.widget_unit);
- glDisable(GL_BLEND);
+ ui_draw_widget_back_color(type, use_shadow, rect, NULL);
+}
+void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock *UNUSED(block), rcti *rect)
+{
+ uiWidgetType *wt = widget_type(UI_WTYPE_TOOLTIP);
wt->state(wt, 0);
- if (block)
- wt->draw(&wt->wcol, rect, block->flag, UI_CNR_ALL);
- else
- wt->draw(&wt->wcol, rect, 0, UI_CNR_ALL);
+ /* wt->draw ends up using same function to draw the tooltip as menu_back */
+ wt->draw(&wt->wcol, rect, 0, 0);
}
-
/* helper call to draw a menu item without button */
/* state: UI_ACTIVE or 0 */
void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state, bool use_sep)
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 2a61be21589..8bd41b874f5 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -3031,6 +3031,7 @@ void init_userdef_do_versions(Main *bmain)
rgba_char_args_set(ts->panelcolors.sub_back, 0, 0, 0, 25);
}
}
+ U.gpu_viewport_antialias = USER_AA_FXAA;
}
/**
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index fbc8fe790c9..b9e6d43aa87 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -1123,7 +1123,7 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, const wmEvent *event
/* some view2d's (graph) don't have min/max zoom, or extreme ones */
if (v2d->maxzoom > 0.0f)
- zoomfac = CLAMPIS(0.001f * v2d->maxzoom, 0.001f, 0.01f);
+ zoomfac = clamp_f(0.001f * v2d->maxzoom, 0.001f, 0.01f);
/* x-axis transform */
fac = zoomfac * (event->x - vzd->lastx);
diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c
index 4440b99f211..91fc1e9fe6a 100644
--- a/source/blender/editors/io/io_alembic.c
+++ b/source/blender/editors/io/io_alembic.c
@@ -86,7 +86,7 @@ static int wm_alembic_export_invoke(bContext *C, wmOperator *op, const wmEvent *
BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath));
}
- BLI_replace_extension(filepath, sizeof(filepath), ".abc");
+ BLI_path_extension_replace(filepath, sizeof(filepath), ".abc");
RNA_string_set(op->ptr, "filepath", filepath);
}
@@ -284,8 +284,8 @@ static bool wm_alembic_export_check(bContext *UNUSED(C), wmOperator *op)
char filepath[FILE_MAX];
RNA_string_get(op->ptr, "filepath", filepath);
- if (!BLI_testextensie(filepath, ".abc")) {
- BLI_ensure_extension(filepath, FILE_MAX, ".abc");
+ if (!BLI_path_extension_check(filepath, ".abc")) {
+ BLI_path_extension_ensure(filepath, FILE_MAX, ".abc");
RNA_string_set(op->ptr, "filepath", filepath);
return true;
}
diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c
index b13eaced843..221142a6cf8 100644
--- a/source/blender/editors/io/io_cache.c
+++ b/source/blender/editors/io/io_cache.c
@@ -61,7 +61,7 @@ static int cachefile_open_invoke(bContext *C, wmOperator *op, const wmEvent *eve
Main *bmain = CTX_data_main(C);
BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath));
- BLI_replace_extension(filepath, sizeof(filepath), ".abc");
+ BLI_path_extension_replace(filepath, sizeof(filepath), ".abc");
RNA_string_set(op->ptr, "filepath", filepath);
}
diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c
index aca380c3123..8f05495bb7f 100644
--- a/source/blender/editors/io/io_collada.c
+++ b/source/blender/editors/io/io_collada.c
@@ -72,7 +72,7 @@ static int wm_collada_export_invoke(bContext *C, wmOperator *op, const wmEvent *
else
BLI_strncpy(filepath, blendfile_path, sizeof(filepath));
- BLI_replace_extension(filepath, sizeof(filepath), ".dae");
+ BLI_path_extension_replace(filepath, sizeof(filepath), ".dae");
RNA_string_set(op->ptr, "filepath", filepath);
}
@@ -119,7 +119,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
}
RNA_string_get(op->ptr, "filepath", filepath);
- BLI_ensure_extension(filepath, sizeof(filepath), ".dae");
+ BLI_path_extension_ensure(filepath, sizeof(filepath), ".dae");
/* Avoid File write exceptions in Collada */
@@ -337,8 +337,8 @@ static bool wm_collada_export_check(bContext *UNUSED(C), wmOperator *op)
char filepath[FILE_MAX];
RNA_string_get(op->ptr, "filepath", filepath);
- if (!BLI_testextensie(filepath, ".dae")) {
- BLI_ensure_extension(filepath, FILE_MAX, ".dae");
+ if (!BLI_path_extension_check(filepath, ".dae")) {
+ BLI_path_extension_ensure(filepath, FILE_MAX, ".dae");
RNA_string_set(op->ptr, "filepath", filepath);
return true;
}
diff --git a/source/blender/editors/lattice/editlattice_select.c b/source/blender/editors/lattice/editlattice_select.c
index 2ba1dde243b..6f1c864130d 100644
--- a/source/blender/editors/lattice/editlattice_select.c
+++ b/source/blender/editors/lattice/editlattice_select.c
@@ -59,6 +59,8 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "DEG_depsgraph.h"
+
#include "lattice_intern.h"
/* -------------------------------------------------------------------- */
@@ -118,6 +120,7 @@ static int lattice_select_random_exec(bContext *C, wmOperator *op)
BLI_rng_free(rng);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
@@ -209,6 +212,7 @@ static int lattice_select_mirror_exec(bContext *C, wmOperator *op)
}
/* TODO, only notify changes */
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
MEM_freeN(objects);
@@ -295,6 +299,7 @@ static int lattice_select_more_less(bContext *C, const bool select)
MEM_freeN(selpoints);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
}
@@ -411,6 +416,7 @@ static int lattice_select_all_exec(bContext *C, wmOperator *op)
}
break;
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
MEM_freeN(objects);
@@ -470,6 +476,7 @@ static int lattice_select_ungrouped_exec(bContext *C, wmOperator *op)
}
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -568,6 +575,7 @@ bool ED_lattice_select_pick(bContext *C, const int mval[2], bool extend, bool de
lt->actbp = LT_ACTBP_NONE;
}
+ DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
return true;
diff --git a/source/blender/editors/manipulator_library/manipulator_types/arrow3d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/arrow3d_manipulator.c
index 409a2c3ca83..8516b9d8244 100644
--- a/source/blender/editors/manipulator_library/manipulator_types/arrow3d_manipulator.c
+++ b/source/blender/editors/manipulator_library/manipulator_types/arrow3d_manipulator.c
@@ -92,6 +92,7 @@ static void arrow_draw_geom(const ArrowManipulator3D *arrow, const bool select,
uint pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
bool unbind_shader = true;
const int draw_style = RNA_enum_get(arrow->manipulator.ptr, "draw_style");
+ const int draw_options = RNA_enum_get(arrow->manipulator.ptr, "draw_options");
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
@@ -131,9 +132,13 @@ static void arrow_draw_geom(const ArrowManipulator3D *arrow, const bool select,
{0.0f, 0.0f, arrow_length},
};
- glLineWidth(arrow->manipulator.line_width);
- wm_manipulator_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GWN_PRIM_LINE_STRIP);
-
+ if (draw_options & ED_MANIPULATOR_ARROW_DRAW_FLAG_STEM) {
+ glLineWidth(arrow->manipulator.line_width);
+ wm_manipulator_vec_draw(color, vec, ARRAY_SIZE(vec), pos, GWN_PRIM_LINE_STRIP);
+ }
+ else {
+ immUniformColor4fv(color);
+ }
/* *** draw arrow head *** */
@@ -303,9 +308,9 @@ static int manipulator_arrow_modal(
/* set the property for the operator and call its modal function */
if (WM_manipulator_target_property_is_valid(mpr_prop)) {
- const int draw_options = RNA_enum_get(arrow->manipulator.ptr, "draw_options");
- const bool constrained = (draw_options & ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED) != 0;
- const bool inverted = (draw_options & ED_MANIPULATOR_ARROW_STYLE_INVERTED) != 0;
+ const int transform_flag = RNA_enum_get(arrow->manipulator.ptr, "transform");
+ const bool constrained = (transform_flag & ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED) != 0;
+ const bool inverted = (transform_flag & ED_MANIPULATOR_ARROW_XFORM_FLAG_INVERTED) != 0;
const bool use_precision = (tweak_flag & WM_MANIPULATOR_TWEAK_PRECISE) != 0;
float value = manipulator_value_from_offset(data, inter, ofs_new, constrained, inverted, use_precision);
@@ -363,9 +368,9 @@ static int manipulator_arrow_invoke(
static void manipulator_arrow_property_update(wmManipulator *mpr, wmManipulatorProperty *mpr_prop)
{
ArrowManipulator3D *arrow = (ArrowManipulator3D *)mpr;
- const int draw_options = RNA_enum_get(arrow->manipulator.ptr, "draw_options");
- const bool constrained = (draw_options & ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED) != 0;
- const bool inverted = (draw_options & ED_MANIPULATOR_ARROW_STYLE_INVERTED) != 0;
+ const int transform_flag = RNA_enum_get(arrow->manipulator.ptr, "transform");
+ const bool constrained = (transform_flag & ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED) != 0;
+ const bool inverted = (transform_flag & ED_MANIPULATOR_ARROW_XFORM_FLAG_INVERTED) != 0;
manipulator_property_data_update(mpr, &arrow->data, mpr_prop, constrained, inverted);
}
@@ -448,21 +453,35 @@ static void MANIPULATOR_WT_arrow_3d(wmManipulatorType *wt)
wt->struct_size = sizeof(ArrowManipulator3D);
/* rna */
- static EnumPropertyItem rna_enum_draw_style[] = {
+ static EnumPropertyItem rna_enum_draw_style_items[] = {
{ED_MANIPULATOR_ARROW_STYLE_NORMAL, "NORMAL", 0, "Normal", ""},
{ED_MANIPULATOR_ARROW_STYLE_CROSS, "CROSS", 0, "Cross", ""},
{ED_MANIPULATOR_ARROW_STYLE_BOX, "BOX", 0, "Box", ""},
{ED_MANIPULATOR_ARROW_STYLE_CONE, "CONE", 0, "Cone", ""},
{0, NULL, 0, NULL, NULL}
};
- static EnumPropertyItem rna_enum_draw_options[] = {
- {ED_MANIPULATOR_ARROW_STYLE_INVERTED, "INVERT", 0, "Inverted", ""},
- {ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED, "CONSTRAIN", 0, "Constrained", ""},
+ static EnumPropertyItem rna_enum_draw_options_items[] = {
+ {ED_MANIPULATOR_ARROW_DRAW_FLAG_STEM, "STEM", 0, "Stem", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+ static EnumPropertyItem rna_enum_transform_items[] = {
+ {ED_MANIPULATOR_ARROW_XFORM_FLAG_INVERTED, "INVERT", 0, "Inverted", ""},
+ {ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED, "CONSTRAIN", 0, "Constrained", ""},
{0, NULL, 0, NULL, NULL}
};
- RNA_def_enum(wt->srna, "draw_style", rna_enum_draw_style, ED_MANIPULATOR_ARROW_STYLE_NORMAL, "Draw Style", "");
- RNA_def_enum_flag(wt->srna, "draw_options", rna_enum_draw_options, 0, "Draw Options", "");
+ RNA_def_enum(
+ wt->srna, "draw_style", rna_enum_draw_style_items,
+ ED_MANIPULATOR_ARROW_STYLE_NORMAL,
+ "Draw Style", "");
+ RNA_def_enum_flag(
+ wt->srna, "draw_options", rna_enum_draw_options_items,
+ ED_MANIPULATOR_ARROW_DRAW_FLAG_STEM,
+ "Draw Options", "");
+ RNA_def_enum_flag(
+ wt->srna, "transform", rna_enum_transform_items,
+ 0,
+ "Transform", "");
RNA_def_float(wt->srna, "length", 1.0f, 0.0f, FLT_MAX, "Arrow Line Length", "", 0.0f, FLT_MAX);
RNA_def_float_vector(wt->srna, "aspect", 2, NULL, 0, FLT_MAX, "Aspect", "Cone/box style only", 0.0f, FLT_MAX);
diff --git a/source/blender/editors/manipulator_library/manipulator_types/dial3d_manipulator.c b/source/blender/editors/manipulator_library/manipulator_types/dial3d_manipulator.c
index a3034597f56..643a379cbb0 100644
--- a/source/blender/editors/manipulator_library/manipulator_types/dial3d_manipulator.c
+++ b/source/blender/editors/manipulator_library/manipulator_types/dial3d_manipulator.c
@@ -94,6 +94,9 @@ typedef struct DialInteraction {
#define DIAL_WIDTH 1.0f
#define DIAL_RESOLUTION 48
+/* Could make option, negative to clip more (don't show when view aligned). */
+#define DIAL_CLIP_BIAS 0.02
+
/**
* We can't use this for the #wmManipulatorType.matrix_basis_get callback, it conflicts with depth picking.
*/
@@ -347,6 +350,7 @@ static void manipulator_dial_draw_select(const bContext *C, wmManipulator *mpr,
copy_v3_v3(clip_plane, rv3d->viewinv[2]);
clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], mpr->matrix_basis[3]);
+ clip_plane[3] += DIAL_CLIP_BIAS * mpr->scale_final;
glEnable(GL_CLIP_DISTANCE0);
}
@@ -373,7 +377,7 @@ static void manipulator_dial_draw(const bContext *C, wmManipulator *mpr)
copy_v3_v3(clip_plane, rv3d->viewinv[2]);
clip_plane[3] = -dot_v3v3(rv3d->viewinv[2], mpr->matrix_basis[3]);
- clip_plane[3] -= 0.02f * mpr->scale_final;
+ clip_plane[3] += DIAL_CLIP_BIAS * mpr->scale_final;
glEnable(GL_CLIP_DISTANCE0);
}
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index 7e31b6a3774..cf4d8ebf05d 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -52,6 +52,8 @@
#include "GPU_draw.h"
+#include "DEG_depsgraph.h"
+
/* own include */
/* copy the face flags, most importantly selection from the mesh to the final derived mesh,
@@ -382,6 +384,7 @@ bool paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], b
/* image window redraw */
paintface_flush_flags(ob, SELECT);
+ DEG_id_tag_update(ob->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views
return true;
diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c
index ad76f0c66f1..9af700aa6bf 100644
--- a/source/blender/editors/mesh/editmesh_intersect.c
+++ b/source/blender/editors/mesh/editmesh_intersect.c
@@ -197,18 +197,18 @@ static int edbm_intersect_exec(bContext *C, wmOperator *op)
}
has_isect = BM_mesh_intersect(
- em->bm,
- em->looptris, em->tottri,
- test_fn, NULL,
- use_self, use_separate_all, true, true, true,
- -1,
- eps);
+ em->bm,
+ em->looptris, em->tottri,
+ test_fn, NULL,
+ use_self, use_separate_all, true, true, true, true,
+ -1,
+ eps);
if (use_separate_cut) {
/* detach selected/un-selected faces */
BM_mesh_separate_faces(
- em->bm,
- BM_elem_cb_check_hflag_enabled_simple(const BMFace *, BM_ELEM_SELECT));
+ em->bm,
+ BM_elem_cb_check_hflag_enabled_simple(const BMFace *, BM_ELEM_SELECT));
}
if (has_isect) {
@@ -300,12 +300,12 @@ static int edbm_intersect_boolean_exec(bContext *C, wmOperator *op)
}
has_isect = BM_mesh_intersect(
- em->bm,
- em->looptris, em->tottri,
- test_fn, NULL,
- false, false, true, true, true,
- boolean_operation,
- eps);
+ em->bm,
+ em->looptris, em->tottri,
+ test_fn, NULL,
+ false, false, true, true, false, true,
+ boolean_operation,
+ eps);
if (has_isect) {
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index 3e787b2055a..7dac9a09b97 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -400,6 +400,7 @@ static void edgering_select(RingSelOpData *lcd)
Object *ob_iter = lcd->objects[ob_index];
BMEditMesh *em = BKE_editmesh_from_object(ob_iter);
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ DEG_id_tag_update(ob_iter->data, DEG_TAG_SELECT_UPDATE);
WM_main_add_notifier(NC_GEOM | ND_SELECT, ob_iter->data);
}
}
@@ -496,6 +497,7 @@ static void ringsel_finish(bContext *C, wmOperator *op)
BM_select_history_store(em->bm, lcd->eed);
EDBM_selectmode_flush(lcd->em);
+ DEG_id_tag_update(lcd->ob->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, lcd->ob->data);
}
}
@@ -868,7 +870,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (cuts != lcd->cuts) {
/* allow zero so you can backspace and type in a value
* otherwise 1 as minimum would make more sense */
- lcd->cuts = CLAMPIS(cuts, 0, SUBD_CUTS_MAX);
+ lcd->cuts = clamp_i(cuts, 0, SUBD_CUTS_MAX);
RNA_int_set(op->ptr, "number_cuts", (int)lcd->cuts);
ringsel_find_edge(lcd, (int)lcd->cuts);
show_cuts = true;
@@ -876,7 +878,7 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
if (smoothness != lcd->smoothness) {
- lcd->smoothness = CLAMPIS(smoothness, -SUBD_SMOOTH_MAX, SUBD_SMOOTH_MAX);
+ lcd->smoothness = clamp_f(smoothness, -SUBD_SMOOTH_MAX, SUBD_SMOOTH_MAX);
RNA_float_set(op->ptr, "smoothness", lcd->smoothness);
show_cuts = true;
ED_region_tag_redraw(lcd->ar);
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 634c65485e9..99a95c27b7b 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -1414,6 +1414,7 @@ static int edbm_select_similar_region_exec(bContext *C, wmOperator *op)
MEM_freeN(group_index);
if (changed) {
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
else {
@@ -1621,6 +1622,7 @@ static int edbm_loop_multiselect_exec(bContext *C, wmOperator *op)
MEM_freeN(edarray);
// if (EM_texFaceCheck())
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
MEM_freeN(objects);
@@ -1824,6 +1826,7 @@ static bool mouse_mesh_loop(bContext *C, const int mval[2], bool extend, bool de
}
}
+ DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
return true;
@@ -1930,6 +1933,7 @@ static int edbm_select_all_exec(bContext *C, wmOperator *op)
EDBM_selectmode_flush(em);
break;
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
@@ -1975,6 +1979,7 @@ static int edbm_faces_select_interior_exec(bContext *C, wmOperator *UNUSED(op))
continue;
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
MEM_freeN(objects);
@@ -2032,6 +2037,7 @@ bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect
Object *ob_iter = objects[ob_index];
EDBM_flag_disable_all(BKE_editmesh_from_object(ob_iter), BM_ELEM_SELECT);
if (basact->object != ob_iter) {
+ DEG_id_tag_update(ob_iter->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data);
}
}
@@ -2150,8 +2156,10 @@ bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect
* switch UV layers, vgroups for eg. */
if (vc.view_layer->basact != basact) {
vc.view_layer->basact = basact;
+ DEG_id_tag_update(&vc.scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, vc.scene);
}
+ DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
return true;
@@ -2482,7 +2490,7 @@ bool EDBM_selectmode_toggle(
Object *ob_iter = objects[ob_index];
BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
EDBM_selectmode_set(em_iter);
- DEG_id_tag_update(ob_iter->data, DEG_TAG_COPY_ON_WRITE);
+ DEG_id_tag_update(ob_iter->data, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data);
}
WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL);
@@ -2932,6 +2940,7 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op)
select_linked_delimit_end(em);
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
@@ -3143,6 +3152,7 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE
* index selections isn't very common. */
RNA_int_set(op->ptr, "index", index);
+ DEG_id_tag_update(basact->object->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, basact->object->data);
return OPERATOR_FINISHED;
@@ -3172,6 +3182,7 @@ static int edbm_select_linked_pick_exec(bContext *C, wmOperator *op)
edbm_select_linked_pick_ex(em, ele, sel, delimit);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -3260,6 +3271,7 @@ static int edbm_select_face_by_sides_exec(bContext *C, wmOperator *op)
EDBM_selectmode_flush(em);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
@@ -3357,6 +3369,7 @@ static int edbm_select_loose_exec(bContext *C, wmOperator *op)
EDBM_selectmode_flush(em);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
@@ -3420,6 +3433,8 @@ static int edbm_select_mirror_exec(bContext *C, wmOperator *op)
if (tot_mirr_iter) {
EDBM_selectmode_flush(em);
+
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
@@ -3480,6 +3495,7 @@ static int edbm_select_more_exec(bContext *C, wmOperator *op)
}
EDBM_select_more(em, use_face_step);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
@@ -3530,6 +3546,7 @@ static int edbm_select_less_exec(bContext *C, wmOperator *op)
}
EDBM_select_less(em, use_face_step);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
@@ -3855,6 +3872,7 @@ static int edbm_select_sharp_edges_exec(bContext *C, wmOperator *op)
else {
EDBM_selectmode_flush(em);
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
MEM_freeN(objects);
@@ -3953,6 +3971,7 @@ static int edbm_select_linked_flat_faces_exec(bContext *C, wmOperator *op)
BLI_LINKSTACK_FREE(stack);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
MEM_freeN(objects);
@@ -4049,6 +4068,7 @@ static int edbm_select_non_manifold_exec(bContext *C, wmOperator *op)
}
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
EDBM_selectmode_flush(em);
@@ -4152,6 +4172,7 @@ static int edbm_select_random_exec(bContext *C, wmOperator *op)
EDBM_deselect_flush(em);
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
@@ -4246,6 +4267,7 @@ static int edbm_select_ungrouped_exec(bContext *C, wmOperator *op)
if (changed) {
EDBM_selectmode_flush(em);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
}
@@ -4418,6 +4440,7 @@ static int edbm_region_to_loop_exec(bContext *C, wmOperator *UNUSED(op))
EDBM_selectmode_to_scene(C);
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
MEM_freeN(objects);
@@ -4625,6 +4648,7 @@ static int edbm_loop_to_region_exec(bContext *C, wmOperator *op)
EDBM_selectmode_flush(em);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
MEM_freeN(objects);
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index bbeb80fa8af..15840f8f9d6 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -104,13 +104,13 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op)
const float fractal = RNA_float_get(op->ptr, "fractal") / 2.5f;
const float along_normal = RNA_float_get(op->ptr, "fractal_along_normal");
- if (RNA_boolean_get(op->ptr, "quadtri") &&
+ if (RNA_boolean_get(op->ptr, "ngon") &&
RNA_enum_get(op->ptr, "quadcorner") == SUBD_CORNER_STRAIGHT_CUT)
{
RNA_enum_set(op->ptr, "quadcorner", SUBD_CORNER_INNERVERT);
}
const int quad_corner_type = RNA_enum_get(op->ptr, "quadcorner");
- const bool use_quad_tri = RNA_boolean_get(op->ptr, "quadtri");
+ const bool use_quad_tri = !RNA_boolean_get(op->ptr, "ngon");
const int seed = RNA_int_get(op->ptr, "seed");
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -176,7 +176,7 @@ void MESH_OT_subdivide(wmOperatorType *ot)
WM_operatortype_props_advanced_begin(ot);
- RNA_def_boolean(ot->srna, "quadtri", 0, "Quad/Tri Mode", "Tries to prevent ngons");
+ RNA_def_boolean(ot->srna, "ngon", true, "Create N-Gons", "When disabled, newly created faces are limited to 3-4 sided faces");
RNA_def_enum(ot->srna, "quadcorner", prop_mesh_cornervert_types, SUBD_CORNER_STRAIGHT_CUT,
"Quad Corner Type", "How to subdivide quad corners (anything other than Straight Cut will prevent ngons)");
@@ -518,6 +518,7 @@ void MESH_OT_delete(wmOperatorType *ot)
/* props */
ot->prop = RNA_def_enum(ot->srna, "type", prop_mesh_delete_types, MESH_DELETE_VERT,
"Type", "Method used for deleting mesh data");
+ RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
/** \} */
@@ -1036,7 +1037,7 @@ void MESH_OT_mark_seam(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
prop = RNA_def_boolean(ot->srna, "clear", 0, "Clear", "");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
WM_operatortype_props_advanced_begin(ot);
}
@@ -1109,7 +1110,7 @@ void MESH_OT_mark_sharp(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
prop = RNA_def_boolean(ot->srna, "clear", false, "Clear", "");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_boolean(ot->srna, "use_verts", false, "Vertices",
"Consider vertices instead of edges to select which edges to (un)tag as sharp");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
@@ -3647,7 +3648,7 @@ static Base *mesh_separate_tagged(Main *bmain, Scene *scene, ViewLayer *view_lay
BM_mesh_normals_update(bm_new);
- BM_mesh_bm_to_me(bm_new, base_new->object->data, (&(struct BMeshToMeshParams){0}));
+ BM_mesh_bm_to_me(bmain, bm_new, base_new->object->data, (&(struct BMeshToMeshParams){0}));
BM_mesh_free(bm_new);
((Mesh *)base_new->object->data)->edit_btmesh = NULL;
@@ -3960,7 +3961,7 @@ static int edbm_separate_exec(bContext *C, wmOperator *op)
if (retval_iter) {
BM_mesh_bm_to_me(
- bm_old, me,
+ bmain, bm_old, me,
(&(struct BMeshToMeshParams){
.calc_object_remap = true,
}));
@@ -6835,7 +6836,7 @@ void MESH_OT_mark_freestyle_edge(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
prop = RNA_def_boolean(ot->srna, "clear", false, "Clear", "");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
/** \} */
@@ -6918,7 +6919,7 @@ void MESH_OT_mark_freestyle_face(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
prop = RNA_def_boolean(ot->srna, "clear", false, "Clear", "");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
/** \} */
diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c
index 6fb7a713ce0..33864cd1e95 100644
--- a/source/blender/editors/mesh/editmesh_undo.c
+++ b/source/blender/editors/mesh/editmesh_undo.c
@@ -511,8 +511,8 @@ static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key)
/* BM_mesh_validate(em->bm); */ /* for troubleshooting */
BM_mesh_bm_to_me(
- em->bm, &um->me, (&(struct BMeshToMeshParams){
- /* Undo code should not be manipulating 'G.main->object' hooks/vertex-parent. */
+ NULL, em->bm, &um->me, (&(struct BMeshToMeshParams){
+ /* Undo code should not be manipulating 'G_MAIN->object' hooks/vertex-parent. */
.calc_object_remap = false,
.cd_mask_extra = CD_MASK_SHAPE_KEYINDEX,
}));
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index 16c1a2c45ec..9524d1b0791 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -43,6 +43,7 @@
#include "BKE_DerivedMesh.h"
#include "BKE_context.h"
+#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_report.h"
@@ -172,6 +173,10 @@ bool EDBM_op_finish(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const bool
BKE_editmesh_tessface_calc(em);
}
+ if (em->ob) {
+ DEG_id_tag_update(&((Mesh *)em->ob->data)->id, DEG_TAG_COPY_ON_WRITE);
+ }
+
return false;
}
else {
@@ -326,7 +331,7 @@ void EDBM_mesh_make(Object *ob, const int select_mode, const bool add_key_index)
* \warning This can invalidate the #DerivedMesh cache of other objects (for linked duplicates).
* Most callers should run #DEG_id_tag_update on \a ob->data, see: T46738, T46913
*/
-void EDBM_mesh_load(Object *ob)
+void EDBM_mesh_load(Main *bmain, Object *ob)
{
Mesh *me = ob->data;
BMesh *bm = me->edit_btmesh->bm;
@@ -338,7 +343,7 @@ void EDBM_mesh_load(Object *ob)
}
BM_mesh_bm_to_me(
- bm, me, (&(struct BMeshToMeshParams){
+ bmain, bm, me, (&(struct BMeshToMeshParams){
.calc_object_remap = true,
}));
@@ -358,7 +363,7 @@ void EDBM_mesh_load(Object *ob)
* cycles.
*/
#if 0
- for (Object *other_object = G.main->object.first;
+ for (Object *other_object = bmain->object.first;
other_object != NULL;
other_object = other_object->id.next)
{
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index d2410c7d97b..46b84f328cc 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -538,6 +538,7 @@ void MESH_OT_uv_texture_add(wmOperatorType *ot)
static int drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
Base *base;
@@ -578,7 +579,7 @@ static int drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *e
return OPERATOR_CANCELLED;
if (exitmode) {
- EDBM_mesh_load(obedit);
+ EDBM_mesh_load(bmain, obedit);
EDBM_mesh_free(me->edit_btmesh);
MEM_freeN(me->edit_btmesh);
me->edit_btmesh = NULL;
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index 41e1ca13b79..6c8de1a481e 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -373,7 +373,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
}
else if (haskey) {
/* add a new key-block and add to the mesh */
- key = me->key = BKE_key_add((ID *)me);
+ key = me->key = BKE_key_add(bmain, (ID *)me);
key->type = KEY_RELATIVE;
}
@@ -593,6 +593,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
return OPERATOR_FINISHED;
@@ -605,6 +606,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
int join_mesh_shapes_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
Depsgraph *depsgraph = CTX_data_depsgraph(C);
@@ -639,7 +641,7 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op)
}
if (key == NULL) {
- key = me->key = BKE_key_add((ID *)me);
+ key = me->key = BKE_key_add(bmain, (ID *)me);
key->type = KEY_RELATIVE;
/* first key added, so it was the basis. initialize it with the existing mesh */
@@ -670,6 +672,7 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c
index 65bf258f334..1ae122a3801 100644
--- a/source/blender/editors/metaball/mball_edit.c
+++ b/source/blender/editors/metaball/mball_edit.c
@@ -154,6 +154,7 @@ static int mball_select_all_exec(bContext *C, wmOperator *op)
break;
}
+ DEG_id_tag_update(&mb->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
return OPERATOR_FINISHED;
@@ -335,6 +336,7 @@ static int mball_select_similar_exec(bContext *C, wmOperator *op)
}
if (changed) {
+ DEG_id_tag_update(&mb->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
}
@@ -403,6 +405,7 @@ static int select_random_metaelems_exec(bContext *C, wmOperator *op)
BLI_rng_free(rng);
+ DEG_id_tag_update(&mb->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
}
MEM_freeN(objects);
@@ -614,7 +617,9 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese
BLI_rcti_init_pt_radius(&rect, mval, 12);
- hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST);
+ hits = view3d_opengl_select(
+ &vc, buffer, MAXPICKBUF, &rect,
+ VIEW3D_SELECT_PICK_NEAREST, VIEW3D_SELECT_FILTER_NOP);
/* does startelem exist? */
ml = mb->editelems->first;
@@ -670,6 +675,7 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese
mb->lastelem = ml_act;
+ DEG_id_tag_update(&mb->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, mb);
return true;
@@ -678,5 +684,3 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese
return false;
}
-
-
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 9ce7f556448..dd358b95722 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -931,6 +931,7 @@ static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEv
/* if empty under cursor, then set object */
if (base && base->object->type == OB_EMPTY) {
ob = base->object;
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
}
else {
@@ -1098,6 +1099,7 @@ static int collection_instance_add_exec(bContext *C, wmOperator *op)
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&collection->id, 0);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
return OPERATOR_FINISHED;
@@ -1294,6 +1296,7 @@ static int object_delete_exec(bContext *C, wmOperator *op)
DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
}
@@ -1846,7 +1849,7 @@ static int convert_exec(bContext *C, wmOperator *op)
* datablock, but for until we've got granular update
* lets take care by selves.
*/
- BKE_vfont_to_curve(bmain, newob, FO_EDIT);
+ BKE_vfont_to_curve(newob, FO_EDIT);
newob->type = OB_CURVE;
cu->type = OB_CURVE;
@@ -2018,6 +2021,7 @@ static int convert_exec(bContext *C, wmOperator *op)
}
DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, scene);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
@@ -2098,7 +2102,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer
/* duplicates using userflags */
if (dupflag & USER_DUP_ACT) {
- BKE_animdata_copy_id_action(&obn->id, true);
+ BKE_animdata_copy_id_action(bmain, &obn->id, true);
}
if (dupflag & USER_DUP_MAT) {
@@ -2112,7 +2116,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer
id_us_min(id);
if (dupflag & USER_DUP_ACT) {
- BKE_animdata_copy_id_action(&obn->mat[a]->id, true);
+ BKE_animdata_copy_id_action(bmain, &obn->mat[a]->id, true);
}
}
}
@@ -2128,7 +2132,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer
}
if (dupflag & USER_DUP_ACT) {
- BKE_animdata_copy_id_action(&psys->part->id, true);
+ BKE_animdata_copy_id_action(bmain, &psys->part->id, true);
}
id_us_min(id);
@@ -2256,9 +2260,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer
}
if (dupflag & USER_DUP_ACT) {
- BKE_animdata_copy_id_action((ID *)obn->data, true);
+ BKE_animdata_copy_id_action(bmain, (ID *)obn->data, true);
if (key) {
- BKE_animdata_copy_id_action((ID *)key, true);
+ BKE_animdata_copy_id_action(bmain, (ID *)key, true);
}
}
@@ -2353,8 +2357,7 @@ static int duplicate_exec(bContext *C, wmOperator *op)
BKE_main_id_clear_newpoins(bmain);
DEG_relations_tag_update(bmain);
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(&scene->id, 0);
+ DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
@@ -2436,6 +2439,7 @@ static int add_named_exec(bContext *C, wmOperator *op)
/* TODO(sergey): Only update relations for the current scene. */
DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c
index db81c51cc90..788f0826848 100644
--- a/source/blender/editors/object/object_data_transfer.c
+++ b/source/blender/editors/object/object_data_transfer.c
@@ -40,7 +40,6 @@
#include "BKE_context.h"
#include "BKE_data_transfer.h"
-#include "BKE_DerivedMesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_mesh_remap.h"
#include "BKE_mesh_runtime.h"
@@ -137,20 +136,17 @@ static const EnumPropertyItem *dt_layers_select_src_itemf(
Scene *scene = CTX_data_scene(C);
if (ob_src) {
- DerivedMesh *dm_src;
- CustomData *ldata;
+ Mesh *me_eval;
int num_data, i;
- /* XXX Is this OK? */
- dm_src = mesh_get_derived_final(depsgraph, scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPUV);
- ldata = dm_src->getLoopDataLayout(dm_src);
- num_data = CustomData_number_of_layers(ldata, CD_MLOOPUV);
+ me_eval = mesh_get_eval_final(depsgraph, scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPUV);
+ num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPUV);
RNA_enum_item_add_separator(&item, &totitem);
for (i = 0; i < num_data; i++) {
tmp_item.value = i;
- tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(ldata, CD_MLOOPUV, i);
+ tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(&me_eval->ldata, CD_MLOOPUV, i);
RNA_enum_item_add(&item, &totitem, &tmp_item);
}
}
@@ -160,20 +156,17 @@ static const EnumPropertyItem *dt_layers_select_src_itemf(
Scene *scene = CTX_data_scene(C);
if (ob_src) {
- DerivedMesh *dm_src;
- CustomData *ldata;
+ Mesh *me_eval;
int num_data, i;
- /* XXX Is this OK? */
- dm_src = mesh_get_derived_final(depsgraph, scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPCOL);
- ldata = dm_src->getLoopDataLayout(dm_src);
- num_data = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
+ me_eval = mesh_get_eval_final(depsgraph, scene, ob_src, CD_MASK_BAREMESH | CD_MLOOPCOL);
+ num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPCOL);
RNA_enum_item_add_separator(&item, &totitem);
for (i = 0; i < num_data; i++) {
tmp_item.value = i;
- tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(ldata, CD_MLOOPCOL, i);
+ tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(&me_eval->ldata, CD_MLOOPCOL, i);
RNA_enum_item_add(&item, &totitem, &tmp_item);
}
}
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index b7f59285186..f050297ee2f 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -146,6 +146,228 @@ Object *ED_object_active_context(bContext *C)
return ob;
}
+/* ********************** object hiding *************************** */
+
+static int object_hide_poll(bContext *C)
+{
+ if (CTX_wm_space_outliner(C) != NULL) {
+ return ED_outliner_collections_editor_poll(C);
+ }
+ else {
+ return ED_operator_view3d_active(C);
+ }
+}
+
+static int object_hide_view_clear_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const bool select = RNA_boolean_get(op->ptr, "select");
+ bool changed = false;
+
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (base->flag & BASE_HIDE) {
+ base->flag &= ~BASE_HIDE;
+ changed = true;
+
+ if (select) {
+ ED_object_base_select(base, BA_SELECT);
+ }
+ }
+ }
+
+ if (!changed) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_layer_collection_sync(scene, view_layer);
+ DEG_id_tag_update(&scene->id, DEG_TAG_BASE_FLAGS_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_hide_view_clear(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Show Hidden Objects";
+ ot->description = "Reveal temporarily hidden objects";
+ ot->idname = "OBJECT_OT_hide_view_clear";
+
+ /* api callbacks */
+ ot->exec = object_hide_view_clear_exec;
+ ot->poll = object_hide_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ PropertyRNA *prop = RNA_def_boolean(ot->srna, "select", false, "Select", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+}
+
+static int object_hide_view_set_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const bool unselected = RNA_boolean_get(op->ptr, "unselected");
+ bool changed = false;
+
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (!(base->flag & BASE_VISIBLED)) {
+ continue;
+ }
+
+ if (!unselected) {
+ if (base->flag & BASE_SELECTED) {
+ ED_object_base_select(base, BA_DESELECT);
+ base->flag |= BASE_HIDE;
+ changed = true;
+ }
+ }
+ else {
+ if (!(base->flag & BASE_SELECTED)) {
+ ED_object_base_select(base, BA_DESELECT);
+ base->flag |= BASE_HIDE;
+ changed = true;
+ }
+ }
+ }
+
+ if (!changed) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_layer_collection_sync(scene, view_layer);
+ DEG_id_tag_update(&scene->id, DEG_TAG_BASE_FLAGS_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_hide_view_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Hide Objects";
+ ot->description = "Temporarily hide objects from the viewport";
+ ot->idname = "OBJECT_OT_hide_view_set";
+
+ /* api callbacks */
+ ot->exec = object_hide_view_set_exec;
+ ot->poll = object_hide_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ PropertyRNA *prop;
+ prop = RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected objects");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+}
+
+static int object_hide_collection_exec(bContext *C, wmOperator *op)
+{
+ int index = RNA_int_get(op->ptr, "collection_index");
+ bool extend = (CTX_wm_window(C)->eventstate->shift != 0);
+
+ if (CTX_wm_window(C)->eventstate->alt != 0) {
+ index += 10;
+ }
+
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ LayerCollection *lc = BKE_layer_collection_from_index(view_layer, index);
+
+ if (!lc) {
+ return OPERATOR_CANCELLED;
+ }
+
+ BKE_layer_collection_set_visible(scene, view_layer, lc, extend);
+
+ DEG_id_tag_update(&scene->id, DEG_TAG_BASE_FLAGS_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+#define COLLECTION_INVALID_INDEX -1
+
+void ED_hide_collections_menu_draw(const bContext *C, uiLayout *layout)
+{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ LayerCollection *lc_scene = view_layer->layer_collections.first;
+
+ uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN);
+
+ for (LayerCollection *lc = lc_scene->layer_collections.first; lc; lc = lc->next) {
+ int index = BKE_layer_collection_findindex(view_layer, lc);
+ uiLayout *row = uiLayoutRow(layout, false);
+
+ if (lc->collection->flag & COLLECTION_RESTRICT_VIEW) {
+ continue;
+ }
+
+ if ((view_layer->runtime_flag & VIEW_LAYER_HAS_HIDE) &&
+ !(lc->runtime_flag & LAYER_COLLECTION_HAS_VISIBLE_OBJECTS)) {
+ uiLayoutSetActive(row, false);
+ }
+
+ int icon = ICON_NONE;
+ if (BKE_layer_collection_has_selected_objects(view_layer, lc)) {
+ icon = ICON_LAYER_ACTIVE;
+ }
+ else if (lc->runtime_flag & LAYER_COLLECTION_HAS_OBJECTS) {
+ icon = ICON_LAYER_USED;
+ }
+
+ uiItemIntO(row,
+ lc->collection->id.name + 2,
+ icon,
+ "OBJECT_OT_hide_collection",
+ "collection_index",
+ index);
+ }
+}
+
+static int object_hide_collection_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ /* Immediately execute if collection index was specified. */
+ int index = RNA_int_get(op->ptr, "collection_index");
+ if (index != COLLECTION_INVALID_INDEX) {
+ return object_hide_collection_exec(C, op);
+ }
+
+ /* Open popup menu. */
+ const char *title = CTX_IFACE_(op->type->translation_context, op->type->name);
+ uiPopupMenu *pup = UI_popup_menu_begin(C, title, ICON_GROUP);
+ uiLayout *layout = UI_popup_menu_layout(pup);
+
+ ED_hide_collections_menu_draw(C, layout);
+
+ UI_popup_menu_end(C, pup);
+
+ return OPERATOR_INTERFACE;
+}
+
+void OBJECT_OT_hide_collection(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Hide Objects By Collection";
+ ot->description = "Show only objects in collection (Shift to extend)";
+ ot->idname = "OBJECT_OT_hide_collection";
+
+ /* api callbacks */
+ ot->exec = object_hide_collection_exec;
+ ot->invoke = object_hide_collection_invoke;
+ ot->poll = ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* Properties. */
+ PropertyRNA *prop;
+ prop = RNA_def_int(ot->srna, "collection_index", COLLECTION_INVALID_INDEX, COLLECTION_INVALID_INDEX, INT_MAX,
+ "Collection Index", "Index of the collection to change visibility", 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+}
/* ******************* toggle editmode operator ***************** */
@@ -191,7 +413,7 @@ static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool f
return false;
}
- EDBM_mesh_load(obedit);
+ EDBM_mesh_load(bmain, obedit);
if (freedata) {
EDBM_mesh_free(me->edit_btmesh);
@@ -1548,8 +1770,6 @@ bool ED_object_editmode_calc_active_center(Object *obedit, const bool select_onl
return false;
}
-#define COLLECTION_INVALID_INDEX -1
-
static int move_to_collection_poll(bContext *C)
{
if (CTX_wm_space_outliner(C) != NULL) {
@@ -1631,7 +1851,7 @@ static int move_to_collection_exec(bContext *C, wmOperator *op)
collection->id.name + 2);
DEG_relations_tag_update(CTX_data_main(C));
- DEG_id_tag_update(&scene->id, 0);
+ DEG_id_tag_update(&scene->id, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
@@ -1870,4 +2090,3 @@ void OBJECT_OT_link_to_collection(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-#undef COLLECTION_INVALID_INDEX
diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c
index 31e8685e323..6a3cb9aa097 100644
--- a/source/blender/editors/object/object_hook.c
+++ b/source/blender/editors/object/object_hook.c
@@ -318,7 +318,7 @@ static bool object_hook_index_array(Main *bmain, Scene *scene, Object *obedit,
BMEditMesh *em;
- EDBM_mesh_load(obedit);
+ EDBM_mesh_load(bmain, obedit);
EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true);
DEG_id_tag_update(obedit->data, 0);
@@ -619,6 +619,7 @@ static int object_add_hook_newob_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
if (add_hook_object(C, bmain, scene, view_layer, obedit, NULL, OBJECT_ADDHOOK_NEWOB, op->reports)) {
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obedit);
return OPERATOR_FINISHED;
@@ -889,6 +890,7 @@ static int object_hook_select_exec(bContext *C, wmOperator *op)
/* select functionality */
object_hook_select(ob, hmd);
+ DEG_id_tag_update(ob->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index 18251a25b73..f7179912f52 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -76,6 +76,9 @@ void OBJECT_OT_drop_named_material(struct wmOperatorType *ot);
void OBJECT_OT_unlink_data(struct wmOperatorType *ot);
/* object_edit.c */
+void OBJECT_OT_hide_view_set(struct wmOperatorType *ot);
+void OBJECT_OT_hide_view_clear(struct wmOperatorType *ot);
+void OBJECT_OT_hide_collection(struct wmOperatorType *ot);
void OBJECT_OT_mode_set(struct wmOperatorType *ot);
void OBJECT_OT_mode_set_or_submode(struct wmOperatorType *ot);
void OBJECT_OT_editmode_toggle(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 1b9af3725ca..425a0acff17 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -119,7 +119,7 @@ ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *sc
/* don't need to worry about the new modifier's name, since that is set to the number
* of particle systems which shouldn't have too many duplicates
*/
- new_md = object_add_particle_system(scene, ob, name);
+ new_md = object_add_particle_system(bmain, scene, ob, name);
}
else {
/* get new modifier data to add */
@@ -524,7 +524,8 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene *
return 1;
}
-static int modifier_apply_shape(ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md)
+static int modifier_apply_shape(
+ Main *bmain, ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md)
{
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
@@ -564,7 +565,7 @@ static int modifier_apply_shape(ReportList *reports, Depsgraph *depsgraph, Scene
}
if (key == NULL) {
- key = me->key = BKE_key_add((ID *)me);
+ key = me->key = BKE_key_add(bmain, (ID *)me);
key->type = KEY_RELATIVE;
/* if that was the first key block added, then it was the basis.
* Initialize it with the mesh, and add another for the modifier */
@@ -673,7 +674,7 @@ static int modifier_apply_obdata(ReportList *reports, Depsgraph *depsgraph, Scen
}
int ED_object_modifier_apply(
- ReportList *reports, Depsgraph *depsgraph,
+ Main *bmain, ReportList *reports, Depsgraph *depsgraph,
Scene *scene, Object *ob, ModifierData *md, int mode)
{
int prev_mode;
@@ -702,7 +703,7 @@ int ED_object_modifier_apply(
md->mode |= eModifierMode_Realtime;
if (mode == MODIFIER_APPLY_SHAPE) {
- if (!modifier_apply_shape(reports, depsgraph, scene, ob, md)) {
+ if (!modifier_apply_shape(bmain, reports, depsgraph, scene, ob, md)) {
md->mode = prev_mode;
return 0;
}
@@ -1017,13 +1018,14 @@ void OBJECT_OT_modifier_move_down(wmOperatorType *ot)
static int modifier_apply_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
Depsgraph *depsgraph = CTX_data_depsgraph(C);
Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_active_context(C);
ModifierData *md = edit_modifier_property_get(op, ob, 0);
int apply_as = RNA_enum_get(op->ptr, "apply_as");
- if (!md || !ED_object_modifier_apply(op->reports, depsgraph, scene, ob, md, apply_as)) {
+ if (!md || !ED_object_modifier_apply(bmain, op->reports, depsgraph, scene, ob, md, apply_as)) {
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index af572824068..89dd54b6f64 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -247,6 +247,10 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_data_transfer);
WM_operatortype_append(OBJECT_OT_datalayout_transfer);
WM_operatortype_append(OBJECT_OT_surfacedeform_bind);
+
+ WM_operatortype_append(OBJECT_OT_hide_view_clear);
+ WM_operatortype_append(OBJECT_OT_hide_view_set);
+ WM_operatortype_append(OBJECT_OT_hide_collection);
}
void ED_operatormacros_object(void)
@@ -289,11 +293,11 @@ void ED_keymap_object(wmKeyConfig *keyconf)
keymap = WM_keymap_find(keyconf, "Object Non-modal", 0, 0);
/* modes */
- kmi = WM_keymap_add_item(keymap, "OBJECT_OT_mode_set", TABKEY, KM_RELEASE, 0, 0);
+ kmi = WM_keymap_add_item(keymap, "OBJECT_OT_mode_set", TABKEY, KM_CLICK, 0, 0);
RNA_enum_set(kmi->ptr, "mode", OB_MODE_EDIT);
RNA_boolean_set(kmi->ptr, "toggle", true);
- kmi = WM_keymap_add_menu_pie(keymap, "VIEW3D_PIE_object_mode", TABKEY, KM_CLICK_DRAG, 0, 0);
+ kmi = WM_keymap_add_menu_pie(keymap, "VIEW3D_MT_object_mode_pie", TABKEY, KM_CLICK_DRAG, 0, 0);
WM_keymap_add_item(keymap, "OBJECT_OT_origin_set", CKEY, KM_PRESS, KM_ALT | KM_SHIFT | KM_CTRL, 0);
@@ -404,6 +408,19 @@ void ED_keymap_object(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "OBJECT_OT_move_to_collection", MKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "OBJECT_OT_link_to_collection", MKEY, KM_PRESS, KM_SHIFT, 0);
+
+ kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_clear", HKEY, KM_PRESS, KM_ALT, 0);
+ kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "unselected", false);
+ kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "unselected", true);
+ kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_collection", HKEY, KM_PRESS, KM_CTRL, 0);
+
+ /* Collection switching. */
+ for (int i = 0; i < 10; i++) {
+ kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_collection", ZEROKEY + i, KM_PRESS, KM_ANY, 0);
+ RNA_int_set(kmi->ptr, "collection_index", (i == 0) ? 10 : i);
+ }
}
void ED_keymap_proportional_cycle(struct wmKeyConfig *UNUSED(keyconf), struct wmKeyMap *keymap)
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 4f441826bfd..a114b2cc6d5 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -145,7 +145,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
Mesh *me = obedit->data;
BMEditMesh *em;
- EDBM_mesh_load(obedit);
+ EDBM_mesh_load(bmain, obedit);
EDBM_mesh_make(obedit, scene->toolsettings->selectmode, true);
DEG_id_tag_update(obedit->data, 0);
@@ -1786,7 +1786,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer
/* Needed to remap texcomesh below. */
me = ob->data = ID_NEW_SET(ob->data, BKE_mesh_copy(bmain, ob->data));
if (me->key) /* We do not need to set me->key->id.newid here... */
- BKE_animdata_copy_id_action((ID *)me->key, false);
+ BKE_animdata_copy_id_action(bmain, (ID *)me->key, false);
break;
case OB_MBALL:
ob->data = ID_NEW_SET(ob->data, BKE_mball_copy(bmain, ob->data));
@@ -1798,12 +1798,12 @@ static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer
ID_NEW_REMAP(cu->bevobj);
ID_NEW_REMAP(cu->taperobj);
if (cu->key) /* We do not need to set cu->key->id.newid here... */
- BKE_animdata_copy_id_action((ID *)cu->key, false);
+ BKE_animdata_copy_id_action(bmain, (ID *)cu->key, false);
break;
case OB_LATTICE:
ob->data = lat = ID_NEW_SET(ob->data, BKE_lattice_copy(bmain, ob->data));
if (lat->key) /* We do not need to set lat->key->id.newid here... */
- BKE_animdata_copy_id_action((ID *)lat->key, false);
+ BKE_animdata_copy_id_action(bmain, (ID *)lat->key, false);
break;
case OB_ARMATURE:
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
@@ -1830,7 +1830,7 @@ static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer
* AnimData structure, which is not what we want.
* (sergey)
*/
- BKE_animdata_copy_id_action((ID *)ob->data, false);
+ BKE_animdata_copy_id_action(bmain, (ID *)ob->data, false);
id_us_min(id);
}
@@ -1845,13 +1845,13 @@ static void single_obdata_users(Main *bmain, Scene *scene, ViewLayer *view_layer
}
}
-static void single_object_action_users(Scene *scene, ViewLayer *view_layer, const int flag)
+static void single_object_action_users(Main *bmain, Scene *scene, ViewLayer *view_layer, const int flag)
{
FOREACH_OBJECT_FLAG_BEGIN(scene, view_layer, flag, ob)
{
if (!ID_IS_LINKED(ob)) {
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
- BKE_animdata_copy_id_action(&ob->id, false);
+ BKE_animdata_copy_id_action(bmain, &ob->id, false);
}
}
FOREACH_OBJECT_FLAG_END;
@@ -1872,7 +1872,7 @@ static void single_mat_users(Main *bmain, Scene *scene, ViewLayer *view_layer, c
if (ma->id.us > 1) {
man = BKE_material_copy(bmain, ma);
- BKE_animdata_copy_id_action(&man->id, false);
+ BKE_animdata_copy_id_action(bmain, &man->id, false);
man->id.us = 0;
assign_material(bmain, ob, man, a, BKE_MAT_ASSIGN_USERPREF);
@@ -1916,7 +1916,7 @@ void ED_object_single_users(Main *bmain, Scene *scene, const bool full, const bo
if (full) {
single_obdata_users(bmain, scene, NULL, 0);
- single_object_action_users(scene, NULL, 0);
+ single_object_action_users(bmain, scene, NULL, 0);
single_mat_users_expand(bmain);
}
@@ -2457,7 +2457,7 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
}
if (RNA_boolean_get(op->ptr, "animation")) {
- single_object_action_users(scene, view_layer, flag);
+ single_object_action_users(bmain, scene, view_layer, flag);
}
BKE_main_id_clear_newpoins(bmain);
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index bac1ba0e37d..ce29125ac79 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -129,6 +129,7 @@ void ED_object_base_activate(bContext *C, Base *base)
else {
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, NULL);
}
+ DEG_id_tag_update(&CTX_data_scene(C)->id, DEG_TAG_SELECT_UPDATE);
}
/********************** Selection Operators **********************/
@@ -172,7 +173,9 @@ static int object_select_by_type_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
return OPERATOR_FINISHED;
}
@@ -365,7 +368,9 @@ void ED_object_select_linked_by_id(bContext *C, ID *id)
}
if (changed) {
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
}
@@ -439,6 +444,7 @@ static int object_select_linked_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
if (changed) {
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
return OPERATOR_FINISHED;
}
@@ -809,6 +815,7 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op)
}
if (changed) {
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
return OPERATOR_FINISHED;
}
@@ -878,7 +885,9 @@ static int object_select_all_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
return OPERATOR_FINISHED;
}
@@ -930,7 +939,9 @@ static int object_select_same_collection_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
return OPERATOR_FINISHED;
}
@@ -986,6 +997,7 @@ static int object_select_mirror_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
/* undo? */
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
return OPERATOR_FINISHED;
@@ -1073,7 +1085,9 @@ static int object_select_more_exec(bContext *C, wmOperator *UNUSED(op))
bool changed = object_select_more_less(C, true);
if (changed) {
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
return OPERATOR_FINISHED;
}
else {
@@ -1101,7 +1115,9 @@ static int object_select_less_exec(bContext *C, wmOperator *UNUSED(op))
bool changed = object_select_more_less(C, false);
if (changed) {
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
return OPERATOR_FINISHED;
}
else {
@@ -1147,7 +1163,9 @@ static int object_select_random_exec(bContext *C, wmOperator *op)
BLI_rng_free(rng);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c
index 03fe6e9de65..4f985293ec3 100644
--- a/source/blender/editors/object/object_shapekey.c
+++ b/source/blender/editors/object/object_shapekey.c
@@ -78,8 +78,9 @@
static void ED_object_shape_key_add(bContext *C, Object *ob, const bool from_mix)
{
+ Main *bmain = CTX_data_main(C);
KeyBlock *kb;
- if ((kb = BKE_object_shapekey_insert(ob, NULL, from_mix))) {
+ if ((kb = BKE_object_shapekey_insert(bmain, ob, NULL, from_mix))) {
Key *key = BKE_key_from_object(ob);
/* for absolute shape keys, new keys may not be added last */
ob->shapenr = BLI_findindex(&key->block, kb) + 1;
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 84786024160..a6f688c49fb 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -2820,6 +2820,7 @@ static int vertex_group_select_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
vgroup_select_verts(ob, 1);
+ DEG_id_tag_update(ob->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
return OPERATOR_FINISHED;
@@ -2845,6 +2846,7 @@ static int vertex_group_deselect_exec(bContext *C, wmOperator *UNUSED(op))
Object *ob = ED_object_context(C);
vgroup_select_verts(ob, 0);
+ DEG_id_tag_update(ob->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c
index f45ee050ef9..7f74dd4666a 100644
--- a/source/blender/editors/physics/dynamicpaint_ops.c
+++ b/source/blender/editors/physics/dynamicpaint_ops.c
@@ -316,7 +316,7 @@ static void dpaint_bake_endjob(void *customdata)
G.is_rendering = false;
BKE_spacedata_draw_locks(false);
- WM_set_locked_interface(G.main->wm.first, false);
+ WM_set_locked_interface(G_MAIN->wm.first, false);
/* Bake was successful:
* Report for ended bake and how long it took */
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 359e9365ea7..08eaaa7284f 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -49,6 +49,7 @@
#include "BLI_string.h"
#include "BLI_kdtree.h"
#include "BLI_rand.h"
+#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "BKE_context.h"
@@ -56,6 +57,7 @@
#include "BKE_global.h"
#include "BKE_object.h"
#include "BKE_library.h"
+#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
@@ -91,6 +93,8 @@
#include "DEG_depsgraph_query.h"
+#include "PIL_time_utildefines.h"
+
#include "physics_intern.h"
#include "particle_edit_utildefines.h"
@@ -117,7 +121,7 @@ int PE_hair_poll(bContext *C)
if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT)) {
return 0;
}
- edit= PE_get_current(scene, ob);
+ edit = PE_get_current(scene, ob);
return (edit && edit->psys);
}
@@ -213,6 +217,31 @@ PTCacheEdit *PE_get_current_from_psys(ParticleSystem *psys)
return NULL;
}
+/* NOTE: Similar to creation of edit, but only updates pointers in the
+ * existing struct.
+ */
+static void pe_update_hair_particle_edit_pointers(PTCacheEdit *edit)
+{
+ ParticleSystem *psys = edit->psys;
+ ParticleData *pa = psys->particles;
+ for (int p = 0; p < edit->totpoint; p++) {
+ PTCacheEditPoint *point = &edit->points[p];
+ HairKey *hair_key = pa->hair;
+ for (int k = 0; k < point->totkey; k++) {
+ PTCacheEditKey *key = &point->keys[k];
+ key->co = hair_key->co;
+ key->time = &hair_key->time;
+ key->flag = hair_key->editflag;
+ if (!(psys->flag & PSYS_GLOBAL_HAIR)) {
+ key->flag |= PEK_USE_WCO;
+ hair_key->editflag |= PEK_USE_WCO;
+ }
+ hair_key++;
+ }
+ pa++;
+ }
+}
+
/* always gets at least the first particlesystem even if PSYS_CURRENT flag is not set
*
* note: this function runs on poll, therefor it can runs many times a second
@@ -298,8 +327,16 @@ static PTCacheEdit *pe_get_current(
}
}
- if (edit)
+ if (edit) {
edit->pid = *pid;
+ if (edit->flags & PT_CACHE_EDIT_UPDATE_PARTICLE_FROM_EVAL) {
+ if (edit->psys != NULL) {
+ psys_copy_particles(edit->psys, edit->psys_eval);
+ pe_update_hair_particle_edit_pointers(edit);
+ }
+ edit->flags &= ~PT_CACHE_EDIT_UPDATE_PARTICLE_FROM_EVAL;
+ }
+ }
BLI_freelistN(&pidlist);
@@ -364,6 +401,7 @@ typedef struct PEData {
ViewContext vc;
const bContext *context;
+ Main *bmain;
Scene *scene;
ViewLayer *view_layer;
Object *ob;
@@ -372,6 +410,8 @@ typedef struct PEData {
BVHTreeFromMesh shape_bvh;
Depsgraph *depsgraph;
+ RNG *rng;
+
const int *mval;
rcti *rect;
float rad;
@@ -400,6 +440,7 @@ static void PE_set_data(bContext *C, PEData *data)
{
memset(data, 0, sizeof(*data));
+ data->bmain = CTX_data_main(C);
data->scene = CTX_data_scene(C);
data->view_layer = CTX_data_view_layer(C);
data->ob = CTX_data_active_object(C);
@@ -445,6 +486,22 @@ static void PE_free_shape_tree(PEData *data)
free_bvhtree_from_mesh(&data->shape_bvh);
}
+static void PE_create_random_generator(PEData *data)
+{
+ uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
+ rng_seed ^= GET_UINT_FROM_POINTER(data->ob);
+ rng_seed ^= GET_UINT_FROM_POINTER(data->edit);
+ data->rng = BLI_rng_new(rng_seed);
+}
+
+static void PE_free_random_generator(PEData *data)
+{
+ if (data->rng != NULL) {
+ BLI_rng_free(data->rng);
+ data->rng = NULL;
+ }
+}
+
/*************************** selection utilities *******************************/
static bool key_test_depth(PEData *data, const float co[3], const int screen_co[2])
@@ -642,61 +699,87 @@ static void foreach_mouse_hit_point(PEData *data, ForPointFunc func, int selecte
}
}
-static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected)
+typedef struct KeyIterData {
+ PEData *data;
+ PTCacheEdit *edit;
+ int selected;
+ ForKeyMatFunc func;
+} KeyIterData;
+
+static void foreach_mouse_hit_key_iter(
+ void *__restrict iter_data_v,
+ const int iter,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
{
+ KeyIterData *iter_data = (KeyIterData *)iter_data_v;
+ PEData *data = iter_data->data;
PTCacheEdit *edit = data->edit;
+ PTCacheEditPoint *point = &edit->points[iter];
+ if (point->flag & PEP_HIDE) {
+ return;
+ }
ParticleSystem *psys = edit->psys;
- ParticleSystemModifierData *psmd = NULL;
- ParticleEditSettings *pset= PE_settings(data->scene);
- POINT_P; KEY_K;
+ ParticleSystemModifierData *psmd_eval = iter_data->edit->psmd_eval;
+ ParticleEditSettings *pset = PE_settings(data->scene);
+ const int selected = iter_data->selected;
float mat[4][4], imat[4][4];
-
unit_m4(mat);
unit_m4(imat);
-
- if (edit->psys)
- psmd= psys_get_modifier(data->ob, edit->psys);
-
- /* all is selected in path mode */
- if (pset->selectmode==SCE_SELECT_PATH)
- selected= 0;
-
- LOOP_VISIBLE_POINTS {
- if (pset->selectmode==SCE_SELECT_END) {
- if (point->totkey) {
- /* only do end keys */
- key= point->keys + point->totkey-1;
-
- if (selected==0 || key->flag & PEK_SELECT) {
- if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) {
- if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) {
- psys_mat_hair_to_global(data->ob, psmd->mesh_final, psys->part->from, psys->particles + p, mat);
- invert_m4_m4(imat, mat);
- }
-
- func(data, mat, imat, p, point->totkey-1, key);
+ if (pset->selectmode==SCE_SELECT_END) {
+ if (point->totkey) {
+ /* only do end keys */
+ PTCacheEditKey *key = point->keys + point->totkey-1;
+
+ if (selected==0 || key->flag & PEK_SELECT) {
+ if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) {
+ if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) {
+ psys_mat_hair_to_global(data->ob, psmd_eval->mesh_final, psys->part->from, psys->particles + iter, mat);
+ invert_m4_m4(imat, mat);
}
+ iter_data->func(data, mat, imat, iter, point->totkey-1, key);
}
}
}
- else {
- /* do all keys */
- LOOP_VISIBLE_KEYS {
- if (selected==0 || key->flag & PEK_SELECT) {
- if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) {
- if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) {
- psys_mat_hair_to_global(data->ob, psmd->mesh_final, psys->part->from, psys->particles + p, mat);
- invert_m4_m4(imat, mat);
- }
-
- func(data, mat, imat, p, k, key);
+ }
+ else {
+ /* do all keys */
+ PTCacheEditKey *key;
+ int k;
+ LOOP_VISIBLE_KEYS {
+ if (selected==0 || key->flag & PEK_SELECT) {
+ if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) {
+ if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) {
+ psys_mat_hair_to_global(data->ob, psmd_eval->mesh_final, psys->part->from, psys->particles + iter, mat);
+ invert_m4_m4(imat, mat);
}
+ iter_data->func(data, mat, imat, iter, k, key);
}
}
}
}
}
+static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected)
+{
+ PTCacheEdit *edit = data->edit;
+ ParticleEditSettings *pset = PE_settings(data->scene);
+ /* all is selected in path mode */
+ if (pset->selectmode == SCE_SELECT_PATH) {
+ selected = 0;
+ }
+
+ KeyIterData iter_data;
+ iter_data.data = data;
+ iter_data.edit = edit;
+ iter_data.selected = selected;
+ iter_data.func = func;
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC;
+ BLI_task_parallel_range(0, edit->totpoint, &iter_data, foreach_mouse_hit_key_iter, &settings);
+}
+
static void foreach_selected_point(PEData *data, ForPointFunc func)
{
PTCacheEdit *edit = data->edit;
@@ -760,7 +843,7 @@ static int count_selected_keys(Scene *scene, PTCacheEdit *edit)
static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
{
PTCacheEdit *edit;
- ParticleSystemModifierData *psmd;
+ ParticleSystemModifierData *psmd_eval;
KDTree *tree;
KDTreeNearest nearest;
HairKey *key;
@@ -769,10 +852,10 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
int index, totpart;
edit= psys->edit;
- psmd= psys_get_modifier(ob, psys);
+ psmd_eval = edit->psmd_eval;
totpart= psys->totpart;
- if (!psmd->mesh_final)
+ if (!psmd_eval->mesh_final)
return;
tree= BLI_kdtree_new(totpart);
@@ -780,7 +863,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
/* insert particles into kd tree */
LOOP_PARTICLES {
key = pa->hair;
- psys_mat_hair_to_orco(ob, psmd->mesh_final, psys->part->from, pa, mat);
+ psys_mat_hair_to_orco(ob, psmd_eval->mesh_final, psys->part->from, pa, mat);
copy_v3_v3(co, key->co);
mul_m4_v3(mat, co);
BLI_kdtree_insert(tree, p, co);
@@ -794,7 +877,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
LOOP_PARTICLES {
key = pa->hair;
- psys_mat_hair_to_orco(ob, psmd->mesh_final, psys->part->from, pa, mat);
+ psys_mat_hair_to_orco(ob, psmd_eval->mesh_final, psys->part->from, pa, mat);
copy_v3_v3(co, key->co);
mul_m4_v3(mat, co);
co[0] = -co[0];
@@ -900,16 +983,16 @@ static void PE_mirror_particle(Object *ob, Mesh *mesh, ParticleSystem *psys, Par
static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
{
PTCacheEdit *edit;
- ParticleSystemModifierData *psmd;
+ ParticleSystemModifierData *psmd_eval;
POINT_P;
if (!psys)
return;
edit= psys->edit;
- psmd= psys_get_modifier(ob, psys);
+ psmd_eval= edit->psmd_eval;
- if (!psmd->mesh_final)
+ if (!psmd_eval->mesh_final)
return;
if (!edit->mirror_cache)
@@ -922,7 +1005,7 @@ static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
* to avoid doing mirror twice */
LOOP_POINTS {
if (point->flag & PEP_EDIT_RECALC) {
- PE_mirror_particle(ob, psmd->mesh_final, psys, psys->particles + p, NULL);
+ PE_mirror_particle(ob, psmd_eval->mesh_final, psys, psys->particles + p, NULL);
if (edit->mirror_cache[p] != -1)
edit->points[edit->mirror_cache[p]].flag &= ~PEP_EDIT_RECALC;
@@ -939,110 +1022,152 @@ static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
/************************************************/
/* Edit Calculation */
/************************************************/
-/* tries to stop edited particles from going through the emitter's surface */
-static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit)
-{
- ParticleEditSettings *pset= PE_settings(scene);
+
+typedef struct DeflectEmitterIter {
+ Object *object;
ParticleSystem *psys;
- ParticleSystemModifierData *psmd;
- POINT_P; KEY_K;
+ PTCacheEdit *edit;
+ float dist;
+ float emitterdist;
+} DeflectEmitterIter;
+
+static void deflect_emitter_iter(
+ void *__restrict iter_data_v,
+ const int iter,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
+ {
+ DeflectEmitterIter *iter_data = (DeflectEmitterIter *)iter_data_v;
+ PTCacheEdit *edit = iter_data->edit;
+ PTCacheEditPoint *point = &edit->points[iter];
+ if ((point->flag & PEP_EDIT_RECALC) == 0) {
+ return;
+ }
+ Object *object = iter_data->object;
+ ParticleSystem *psys = iter_data->psys;
+ ParticleSystemModifierData *psmd_eval = iter_data->edit->psmd_eval;
+ PTCacheEditKey *key;
+ int k;
+ float hairimat[4][4], hairmat[4][4];
int index;
float *vec, *nor, dvec[3], dot, dist_1st=0.0f;
- float hairimat[4][4], hairmat[4][4];
- const float dist = ED_view3d_select_dist_px() * 0.01f;
-
- if (edit==NULL || edit->psys==NULL || (pset->flag & PE_DEFLECT_EMITTER)==0 || (edit->psys->flag & PSYS_GLOBAL_HAIR))
- return;
-
- psys = edit->psys;
- psmd = psys_get_modifier(ob, psys);
-
- if (!psmd->mesh_final)
- return;
+ const float dist = iter_data->dist;
+ const float emitterdist = iter_data->emitterdist;
+ psys_mat_hair_to_object(object,
+ psmd_eval->mesh_final,
+ psys->part->from,
+ psys->particles + iter,
+ hairmat);
- LOOP_EDITED_POINTS {
- psys_mat_hair_to_object(ob, psmd->mesh_final, psys->part->from, psys->particles + p, hairmat);
+ LOOP_KEYS {
+ mul_m4_v3(hairmat, key->co);
+ }
- LOOP_KEYS {
- mul_m4_v3(hairmat, key->co);
+ LOOP_KEYS {
+ if (k == 0) {
+ dist_1st = len_v3v3((key + 1)->co, key->co);
+ dist_1st *= dist * emitterdist;
}
+ else {
+ index = BLI_kdtree_find_nearest(edit->emitter_field, key->co, NULL);
- LOOP_KEYS {
- if (k==0) {
- dist_1st = len_v3v3((key+1)->co, key->co);
- dist_1st *= dist * pset->emitterdist;
- }
- else {
- index= BLI_kdtree_find_nearest(edit->emitter_field, key->co, NULL);
-
- vec=edit->emitter_cosnos +index*6;
- nor=vec+3;
+ vec = edit->emitter_cosnos + index * 6;
+ nor = vec + 3;
- sub_v3_v3v3(dvec, key->co, vec);
+ sub_v3_v3v3(dvec, key->co, vec);
- dot=dot_v3v3(dvec, nor);
- copy_v3_v3(dvec, nor);
+ dot = dot_v3v3(dvec, nor);
+ copy_v3_v3(dvec, nor);
- if (dot>0.0f) {
- if (dot<dist_1st) {
- normalize_v3(dvec);
- mul_v3_fl(dvec, dist_1st-dot);
- add_v3_v3(key->co, dvec);
- }
- }
- else {
+ if (dot > 0.0f) {
+ if (dot < dist_1st) {
normalize_v3(dvec);
- mul_v3_fl(dvec, dist_1st-dot);
+ mul_v3_fl(dvec, dist_1st - dot);
add_v3_v3(key->co, dvec);
}
- if (k==1)
- dist_1st*=1.3333f;
+ }
+ else {
+ normalize_v3(dvec);
+ mul_v3_fl(dvec, dist_1st - dot);
+ add_v3_v3(key->co, dvec);
+ }
+ if (k == 1) {
+ dist_1st *= 1.3333f;
}
}
+ }
- invert_m4_m4(hairimat, hairmat);
+ invert_m4_m4(hairimat, hairmat);
- LOOP_KEYS {
- mul_m4_v3(hairimat, key->co);
- }
+ LOOP_KEYS {
+ mul_m4_v3(hairimat, key->co);
}
}
-/* force set distances between neighboring keys */
-static void PE_apply_lengths(Scene *scene, PTCacheEdit *edit)
-{
- ParticleEditSettings *pset=PE_settings(scene);
- POINT_P; KEY_K;
- float dv1[3];
+/* tries to stop edited particles from going through the emitter's surface */
+static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit)
+{
+ ParticleEditSettings *pset = PE_settings(scene);
+ ParticleSystem *psys;
+ const float dist = ED_view3d_select_dist_px() * 0.01f;
- if (edit==0 || (pset->flag & PE_KEEP_LENGTHS)==0)
+ if (edit == NULL || edit->psys == NULL ||
+ (pset->flag & PE_DEFLECT_EMITTER) == 0 ||
+ (edit->psys->flag & PSYS_GLOBAL_HAIR))
+ {
return;
+ }
- if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR)
+ psys = edit->psys;
+
+ if (!edit->psmd_eval->mesh_final) {
return;
+ }
- LOOP_EDITED_POINTS {
- LOOP_KEYS {
- if (k) {
- sub_v3_v3v3(dv1, key->co, (key - 1)->co);
- normalize_v3(dv1);
- mul_v3_fl(dv1, (key - 1)->length);
- add_v3_v3v3(key->co, (key - 1)->co, dv1);
- }
+ DeflectEmitterIter iter_data;
+ iter_data.object = ob;
+ iter_data.psys = psys;
+ iter_data.edit = edit;
+ iter_data.dist = dist;
+ iter_data.emitterdist = pset->emitterdist;
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC;
+ BLI_task_parallel_range(0, edit->totpoint, &iter_data, deflect_emitter_iter, &settings);
+}
+
+typedef struct ApplyLengthsIterData {
+ PTCacheEdit *edit;
+} ApplyLengthsIterData;
+
+static void apply_lengths_iter(
+ void *__restrict iter_data_v,
+ const int iter,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
+ {
+ ApplyLengthsIterData *iter_data = (ApplyLengthsIterData *)iter_data_v;
+ PTCacheEdit *edit = iter_data->edit;
+ PTCacheEditPoint *point = &edit->points[iter];
+ if ((point->flag & PEP_EDIT_RECALC) == 0) {
+ return;
+ }
+ PTCacheEditKey *key;
+ int k;
+ LOOP_KEYS {
+ if (k) {
+ float dv1[3];
+ sub_v3_v3v3(dv1, key->co, (key - 1)->co);
+ normalize_v3(dv1);
+ mul_v3_fl(dv1, (key - 1)->length);
+ add_v3_v3v3(key->co, (key - 1)->co, dv1);
}
}
}
-/* try to find a nice solution to keep distances between neighboring keys */
-static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit)
+
+/* force set distances between neighboring keys */
+static void PE_apply_lengths(Scene *scene, PTCacheEdit *edit)
{
ParticleEditSettings *pset=PE_settings(scene);
- POINT_P;
- PTCacheEditKey *key;
- int j, k;
- float tlen;
- float dv0[3] = {0.0f, 0.0f, 0.0f};
- float dv1[3] = {0.0f, 0.0f, 0.0f};
- float dv2[3] = {0.0f, 0.0f, 0.0f};
if (edit==0 || (pset->flag & PE_KEEP_LENGTHS)==0)
return;
@@ -1050,43 +1175,91 @@ static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit)
if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR)
return;
- LOOP_EDITED_POINTS {
- for (j=1; j<point->totkey; j++) {
- float mul= 1.0f / (float)point->totkey;
-
- if (pset->flag & PE_LOCK_FIRST) {
- key= point->keys + 1;
- k= 1;
- dv1[0] = dv1[1] = dv1[2] = 0.0;
- }
- else {
- key= point->keys;
- k= 0;
- dv0[0] = dv0[1] = dv0[2] = 0.0;
- }
-
- for (; k<point->totkey; k++, key++) {
- if (k) {
- sub_v3_v3v3(dv0, (key - 1)->co, key->co);
- tlen= normalize_v3(dv0);
- mul_v3_fl(dv0, (mul * (tlen - (key - 1)->length)));
- }
+ ApplyLengthsIterData iter_data;
+ iter_data.edit = edit;
- if (k < point->totkey - 1) {
- sub_v3_v3v3(dv2, (key + 1)->co, key->co);
- tlen= normalize_v3(dv2);
- mul_v3_fl(dv2, mul * (tlen - key->length));
- }
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC;
+ BLI_task_parallel_range(0, edit->totpoint, &iter_data, apply_lengths_iter, &settings);
+}
- if (k) {
- add_v3_v3((key-1)->co, dv1);
- }
+typedef struct IterateLengthsIterData {
+ PTCacheEdit *edit;
+ ParticleEditSettings *pset;
+} IterateLengthsIterData;
+
+static void iterate_lengths_iter(
+ void *__restrict iter_data_v,
+ const int iter,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
+{
+ IterateLengthsIterData *iter_data = (IterateLengthsIterData *)iter_data_v;
+ PTCacheEdit *edit = iter_data->edit;
+ PTCacheEditPoint *point = &edit->points[iter];
+ if ((point->flag & PEP_EDIT_RECALC) == 0) {
+ return;
+ }
+ ParticleEditSettings *pset = iter_data->pset;
+ float tlen;
+ float dv0[3] = {0.0f, 0.0f, 0.0f};
+ float dv1[3] = {0.0f, 0.0f, 0.0f};
+ float dv2[3] = {0.0f, 0.0f, 0.0f};
+ for (int j = 1; j < point->totkey; j++) {
+ PTCacheEditKey *key;
+ int k;
+ float mul = 1.0f / (float)point->totkey;
+ if (pset->flag & PE_LOCK_FIRST) {
+ key = point->keys + 1;
+ k = 1;
+ dv1[0] = dv1[1] = dv1[2] = 0.0;
+ }
+ else {
+ key = point->keys;
+ k = 0;
+ dv0[0] = dv0[1] = dv0[2] = 0.0;
+ }
- add_v3_v3v3(dv1, dv0, dv2);
+ for (; k < point->totkey; k++, key++) {
+ if (k) {
+ sub_v3_v3v3(dv0, (key - 1)->co, key->co);
+ tlen = normalize_v3(dv0);
+ mul_v3_fl(dv0, (mul * (tlen - (key - 1)->length)));
+ }
+ if (k < point->totkey - 1) {
+ sub_v3_v3v3(dv2, (key + 1)->co, key->co);
+ tlen = normalize_v3(dv2);
+ mul_v3_fl(dv2, mul * (tlen - key->length));
+ }
+ if (k) {
+ add_v3_v3((key-1)->co, dv1);
}
+ add_v3_v3v3(dv1, dv0, dv2);
}
}
}
+
+/* try to find a nice solution to keep distances between neighboring keys */
+static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit)
+{
+ ParticleEditSettings *pset = PE_settings(scene);
+ if (edit==0 || (pset->flag & PE_KEEP_LENGTHS)==0) {
+ return;
+ }
+ if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR) {
+ return;
+ }
+
+ IterateLengthsIterData iter_data;
+ iter_data.edit = edit;
+ iter_data.pset = pset;
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC;
+ BLI_task_parallel_range(0, edit->totpoint, &iter_data, iterate_lengths_iter, &settings);
+}
+
/* set current distances to be kept between neighbouting keys */
void recalc_lengths(PTCacheEdit *edit)
{
@@ -1104,10 +1277,10 @@ void recalc_lengths(PTCacheEdit *edit)
}
/* calculate a tree for finding nearest emitter's vertice */
-void recalc_emitter_field(Depsgraph *UNUSED(depsgraph), Object *ob, ParticleSystem *psys)
+void recalc_emitter_field(Depsgraph *UNUSED(depsgraph), Object *UNUSED(ob), ParticleSystem *psys)
{
- Mesh *mesh = psys_get_modifier(ob, psys)->mesh_final;
PTCacheEdit *edit = psys->edit;
+ Mesh *mesh = edit->psmd_eval->mesh_final;
float *vec, *nor;
int i, totface /*, totvert*/;
@@ -1197,16 +1370,16 @@ static void PE_update_selection(Depsgraph *depsgraph, Scene *scene, Object *ob,
void update_world_cos(Depsgraph *UNUSED(depsgraph), Object *ob, PTCacheEdit *edit)
{
ParticleSystem *psys = edit->psys;
- ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
+ ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
POINT_P; KEY_K;
float hairmat[4][4];
- if (psys == 0 || psys->edit == 0 || psmd->mesh_final == NULL)
+ if (psys == 0 || psys->edit == 0 || psmd_eval->mesh_final == NULL)
return;
LOOP_POINTS {
if (!(psys->flag & PSYS_GLOBAL_HAIR))
- psys_mat_hair_to_global(ob, psmd->mesh_final, psys->part->from, psys->particles+p, hairmat);
+ psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, psys->particles+p, hairmat);
LOOP_KEYS {
copy_v3_v3(key->world_co, key->co);
@@ -1638,8 +1811,6 @@ static int select_random_exec(bContext *C, wmOperator *op)
{
PEData data;
int type;
- Scene *scene;
- Object *ob;
/* used by LOOP_VISIBLE_POINTS, LOOP_VISIBLE_KEYS and LOOP_KEYS */
PTCacheEdit *edit;
@@ -1657,9 +1828,7 @@ static int select_random_exec(bContext *C, wmOperator *op)
PE_set_data(C, &data);
data.select_action = SEL_SELECT;
- scene = CTX_data_scene(C);
- ob = CTX_data_active_object(C);
- edit = PE_get_current(scene, ob);
+ edit = PE_get_current(data.scene, data.ob);
rng = BLI_rng_new_srandom(seed);
@@ -1833,7 +2002,7 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, bool
ParticleEditSettings *pset= PE_settings(scene);
PTCacheEdit *edit = PE_get_current(scene, ob);
ParticleSystem *psys = edit->psys;
- ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
+ ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
POINT_P; KEY_K;
float co[3], mat[4][4];
int screen_co[2];
@@ -1853,7 +2022,7 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, bool
LOOP_VISIBLE_POINTS {
if (edit->psys && !(psys->flag & PSYS_GLOBAL_HAIR))
- psys_mat_hair_to_global(ob, psmd->mesh_final, psys->part->from, psys->particles + p, mat);
+ psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, mat);
if (pset->selectmode==SCE_SELECT_POINT) {
LOOP_KEYS {
@@ -2290,15 +2459,15 @@ static int remove_tagged_particles(Object *ob, ParticleSystem *psys, int mirror)
ParticleData *pa, *npa=0, *new_pars=0;
POINT_P;
PTCacheEditPoint *npoint=0, *new_points=0;
- ParticleSystemModifierData *psmd;
+ ParticleSystemModifierData *psmd_eval;
int i, new_totpart= psys->totpart, removed= 0;
if (mirror) {
/* mirror tags */
- psmd= psys_get_modifier(ob, psys);
+ psmd_eval = edit->psmd_eval;
LOOP_TAGGED_POINTS {
- PE_mirror_particle(ob, psmd->mesh_final, psys, psys->particles + p, NULL);
+ PE_mirror_particle(ob, psmd_eval->mesh_final, psys, psys->particles + p, NULL);
}
}
@@ -2369,16 +2538,16 @@ static void remove_tagged_keys(Object *ob, ParticleSystem *psys)
HairKey *hkey, *nhkey, *new_hkeys=0;
POINT_P; KEY_K;
PTCacheEditKey *nkey, *new_keys;
- ParticleSystemModifierData *psmd;
+ ParticleSystemModifierData *psmd_eval;
short new_totkey;
if (pe_x_mirror(ob)) {
/* mirror key tags */
- psmd= psys_get_modifier(ob, psys);
+ psmd_eval = psys_get_modifier(ob, psys);
LOOP_POINTS {
LOOP_TAGGED_KEYS {
- PE_mirror_particle(ob, psmd->mesh_final, psys, psys->particles + p, NULL);
+ PE_mirror_particle(ob, psmd_eval->mesh_final, psys, psys->particles + p, NULL);
break;
}
}
@@ -2572,7 +2741,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
Object *ob= CTX_data_active_object(C);
PTCacheEdit *edit= PE_get_current(scene, ob);
ParticleSystem *psys = edit->psys;
- ParticleSystemModifierData *psmd;
+ ParticleSystemModifierData *psmd_eval;
KDTree *tree;
KDTreeNearest nearest[10];
POINT_P;
@@ -2583,7 +2752,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
edit= psys->edit;
- psmd= psys_get_modifier(ob, psys);
+ psmd_eval = edit->psmd_eval;
totremoved= 0;
do {
@@ -2593,7 +2762,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
/* insert particles into kd tree */
LOOP_SELECTED_POINTS {
- psys_mat_hair_to_object(ob, psmd->mesh_final, psys->part->from, psys->particles+p, mat);
+ psys_mat_hair_to_object(ob, psmd_eval->mesh_final, psys->part->from, psys->particles+p, mat);
copy_v3_v3(co, point->keys->co);
mul_m4_v3(mat, co);
BLI_kdtree_insert(tree, p, co);
@@ -2603,7 +2772,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
/* tag particles to be removed */
LOOP_SELECTED_POINTS {
- psys_mat_hair_to_object(ob, psmd->mesh_final, psys->part->from, psys->particles+p, mat);
+ psys_mat_hair_to_object(ob, psmd_eval->mesh_final, psys->part->from, psys->particles+p, mat);
copy_v3_v3(co, point->keys->co);
mul_m4_v3(mat, co);
@@ -2824,7 +2993,7 @@ static void PE_mirror_x(
Scene *scene, Object *ob, int tagged)
{
Mesh *me= (Mesh *)(ob->data);
- ParticleSystemModifierData *psmd;
+ ParticleSystemModifierData *psmd_eval;
PTCacheEdit *edit = PE_get_current(scene, ob);
ParticleSystem *psys = edit->psys;
ParticleData *pa, *newpa, *new_pars;
@@ -2837,18 +3006,18 @@ static void PE_mirror_x(
if (psys->flag & PSYS_GLOBAL_HAIR)
return;
- psmd= psys_get_modifier(ob, psys);
- if (!psmd->mesh_final)
+ psmd_eval = edit->psmd_eval;
+ if (!psmd_eval->mesh_final)
return;
- const bool use_dm_final_indices = (psys->part->use_modifier_stack && !psmd->mesh_final->runtime.deformed_only);
+ const bool use_dm_final_indices = (psys->part->use_modifier_stack && !psmd_eval->mesh_final->runtime.deformed_only);
/* NOTE: this is not nice to use tessfaces but hard to avoid since pa->num uses tessfaces */
BKE_mesh_tessface_ensure(me);
/* Note: In case psys uses Mesh tessface indices, we mirror final Mesh itself, not orig mesh. Avoids an (impossible)
* mesh -> orig -> mesh tessface indices conversion... */
- mirrorfaces = mesh_get_x_mirror_faces__real_mesh(ob, NULL, use_dm_final_indices ? psmd->mesh_final : NULL);
+ mirrorfaces = mesh_get_x_mirror_faces__real_mesh(ob, NULL, use_dm_final_indices ? psmd_eval->mesh_final : NULL);
if (!edit->mirror_cache)
PE_update_mirror_cache(ob, psys);
@@ -2862,7 +3031,7 @@ static void PE_mirror_x(
if (point_is_selected(point)) {
if (edit->mirror_cache[p] != -1) {
/* already has a mirror, don't need to duplicate */
- PE_mirror_particle(ob, psmd->mesh_final, psys, pa, NULL);
+ PE_mirror_particle(ob, psmd_eval->mesh_final, psys, pa, NULL);
continue;
}
else
@@ -2875,7 +3044,7 @@ static void PE_mirror_x(
}
if (newtotpart != psys->totpart) {
- MFace *mtessface = use_dm_final_indices ? psmd->mesh_final->mface : me->mface;
+ MFace *mtessface = use_dm_final_indices ? psmd_eval->mesh_final->mface : me->mface;
/* allocate new arrays and copy existing */
new_pars= MEM_callocN(newtotpart*sizeof(ParticleData), "ParticleData new");
@@ -2944,7 +3113,7 @@ static void PE_mirror_x(
}
else {
newpa->num_dmcache = psys_particle_dm_face_lookup(
- psmd->mesh_final, psmd->mesh_original, newpa->num, newpa->fuv, NULL);
+ psmd_eval->mesh_final, psmd_eval->mesh_original, newpa->num, newpa->fuv, NULL);
}
/* update edit key pointers */
@@ -2955,7 +3124,7 @@ static void PE_mirror_x(
}
/* map key positions as mirror over x axis */
- PE_mirror_particle(ob, psmd->mesh_final, psys, pa, newpa);
+ PE_mirror_particle(ob, psmd_eval->mesh_final, psys, pa, newpa);
newpa++;
newpoint++;
@@ -3030,8 +3199,11 @@ static void brush_cut(PEData *data, int pa_index)
int k, cut, keys= (int)pow(2.0, (double)pset->draw_step);
int screen_co[2];
+ BLI_assert(data->rng != NULL);
/* blunt scissors */
- if (BLI_frand() > data->cutfac) return;
+ if (BLI_rng_get_float(data->rng) > data->cutfac) {
+ return;
+ }
/* don't cut hidden */
if (edit->points[pa_index].flag & PEP_HIDE)
@@ -3360,14 +3532,13 @@ static void intersect_dm_quad_weights(const float v1[3], const float v2[3], cons
}
/* check intersection with a derivedmesh */
-static int particle_intersect_mesh(const bContext *C, Scene *scene, Object *ob, Mesh *mesh,
- float *vert_cos,
- const float co1[3], const float co2[3],
- float *min_d, int *min_face, float *min_w,
- float *face_minmax, float *pa_minmax,
- float radius, float *ipoint)
+static int particle_intersect_mesh(Depsgraph *depsgraph, Scene *scene, Object *ob, Mesh *mesh,
+ float *vert_cos,
+ const float co1[3], const float co2[3],
+ float *min_d, int *min_face, float *min_w,
+ float *face_minmax, float *pa_minmax,
+ float radius, float *ipoint)
{
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
MFace *mface= NULL;
MVert *mvert= NULL;
int i, totface, intersect=0;
@@ -3496,6 +3667,109 @@ static int particle_intersect_mesh(const bContext *C, Scene *scene, Object *ob,
return intersect;
}
+typedef struct BrushAddCountIterData {
+ Depsgraph *depsgraph;
+ Scene *scene;
+ Object *object;
+ Mesh *mesh;
+ PEData *data;
+ int number;
+ short size;
+ float imat[4][4];
+ ParticleData *add_pars;
+ int num_added;
+} BrushAddCountIterData;
+
+typedef struct BrushAddCountIterTLSData {
+ RNG *rng;
+ int num_added;
+} BrushAddCountIterTLSData;
+
+static void brush_add_count_iter(
+ void *__restrict iter_data_v,
+ const int iter,
+ const ParallelRangeTLS *__restrict tls_v)
+{
+ BrushAddCountIterData *iter_data = (BrushAddCountIterData *)iter_data_v;
+ Depsgraph *depsgraph = iter_data->depsgraph;
+ PEData *data = iter_data->data;
+ PTCacheEdit *edit = data->edit;
+ ParticleSystem *psys = edit->psys;
+ ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
+ ParticleData *add_pars = iter_data->add_pars;
+ BrushAddCountIterTLSData *tls = tls_v->userdata_chunk;
+ const int number = iter_data->number;
+ const short size = iter_data->size;
+ const short size2 = size*size;
+ float dmx, dmy;
+ if (number > 1) {
+ dmx = size;
+ dmy = size;
+ if (tls->rng == NULL) {
+ tls->rng = BLI_rng_new_srandom(
+ psys->seed + data->mval[0] + data->mval[1] + tls_v->thread_id);
+ }
+ /* rejection sampling to get points in circle */
+ while (dmx*dmx + dmy*dmy > size2) {
+ dmx = (2.0f*BLI_rng_get_float(tls->rng) - 1.0f)*size;
+ dmy = (2.0f*BLI_rng_get_float(tls->rng) - 1.0f)*size;
+ }
+ }
+ else {
+ dmx = 0.0f;
+ dmy = 0.0f;
+ }
+
+ float mco[2];
+ mco[0] = data->mval[0] + dmx;
+ mco[1] = data->mval[1] + dmy;
+
+ float co1[3], co2[3];
+ ED_view3d_win_to_segment(depsgraph, data->vc.ar, data->vc.v3d, mco, co1, co2, true);
+
+ mul_m4_v3(iter_data->imat, co1);
+ mul_m4_v3(iter_data->imat, co2);
+ float min_d = 2.0;
+
+ /* warning, returns the derived mesh face */
+ BLI_assert(iter_data->mesh != NULL);
+ if (particle_intersect_mesh(depsgraph, iter_data->scene, iter_data->object, iter_data->mesh,
+ 0, co1, co2,
+ &min_d,
+ &add_pars[iter].num_dmcache,
+ add_pars[iter].fuv,
+ 0, 0, 0, 0)) {
+ if (psys->part->use_modifier_stack && !psmd_eval->mesh_final->runtime.deformed_only) {
+ add_pars[iter].num = add_pars[iter].num_dmcache;
+ add_pars[iter].num_dmcache = DMCACHE_ISCHILD;
+ }
+ else if (iter_data->mesh == psmd_eval->mesh_original) {
+ /* Final DM is not same topology as orig mesh, we have to map num_dmcache to real final dm. */
+ add_pars[iter].num = add_pars[iter].num_dmcache;
+ add_pars[iter].num_dmcache = psys_particle_dm_face_lookup(
+ psmd_eval->mesh_final, psmd_eval->mesh_original,
+ add_pars[iter].num, add_pars[iter].fuv, NULL);
+ }
+ else {
+ add_pars[iter].num = add_pars[iter].num_dmcache;
+ }
+ if (add_pars[iter].num != DMCACHE_NOTFOUND) {
+ tls->num_added++;
+ }
+ }
+}
+
+static void brush_add_count_iter_finalize(void *__restrict userdata_v,
+ void *__restrict userdata_chunk_v)
+{
+ BrushAddCountIterData *iter_data = (BrushAddCountIterData *)userdata_v;
+ BrushAddCountIterTLSData *tls = (BrushAddCountIterTLSData *)userdata_chunk_v;
+ iter_data->num_added += tls->num_added;
+ if (tls->rng != NULL) {
+ BLI_rng_free(tls->rng);
+ }
+}
+
static int brush_add(const bContext *C, PEData *data, short number)
{
Depsgraph *depsgraph = CTX_data_depsgraph(C);
@@ -3505,16 +3779,13 @@ static int brush_add(const bContext *C, PEData *data, short number)
PTCacheEdit *edit = data->edit;
ParticleSystem *psys= edit->psys;
ParticleData *add_pars;
- ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
+ ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
ParticleSimulationData sim= {0};
ParticleEditSettings *pset= PE_settings(scene);
int i, k, n= 0, totpart= psys->totpart;
- float mco[2];
- float dmx, dmy;
- float co1[3], co2[3], min_d, imat[4][4];
+ float co1[3], imat[4][4];
float framestep, timestep;
short size= pset->brush[PE_BRUSH_ADD].size;
- short size2= size*size;
RNG *rng;
invert_m4_m4(imat, ob->obmat);
@@ -3527,67 +3798,65 @@ static int brush_add(const bContext *C, PEData *data, short number)
rng = BLI_rng_new_srandom(psys->seed+data->mval[0]+data->mval[1]);
sim.depsgraph = depsgraph;
- sim.scene= scene;
- sim.ob= ob;
- sim.psys= psys;
- sim.psmd= psmd;
+ sim.scene = scene;
+ sim.ob = ob;
+ sim.psys = psys;
+ sim.psmd = psmd_eval;
- timestep= psys_get_timestep(&sim);
+ timestep = psys_get_timestep(&sim);
- if (psys->part->use_modifier_stack || psmd->mesh_final->runtime.deformed_only) {
- mesh = psmd->mesh_final;
+ if (psys->part->use_modifier_stack || psmd_eval->mesh_final->runtime.deformed_only) {
+ mesh = psmd_eval->mesh_final;
}
else {
- mesh = psmd->mesh_original;
+ mesh = psmd_eval->mesh_original;
}
BLI_assert(mesh);
- for (i=0; i<number; i++) {
- if (number>1) {
- dmx = size;
- dmy = size;
-
- /* rejection sampling to get points in circle */
- while (dmx*dmx + dmy*dmy > size2) {
- dmx= (2.0f*BLI_rng_get_float(rng) - 1.0f)*size;
- dmy= (2.0f*BLI_rng_get_float(rng) - 1.0f)*size;
- }
+ /* Calculate positions of new particles to add, based on brush interseciton
+ * with object. New particle data is assigned to a correponding to check
+ * index element of add_pars array. This means, that add_pars is a sparse
+ * array.
+ */
+ BrushAddCountIterData iter_data;
+ iter_data.depsgraph = depsgraph;
+ iter_data.scene = scene;
+ iter_data.object = ob;
+ iter_data.mesh = mesh;
+ iter_data.data = data;
+ iter_data.number = number;
+ iter_data.size = size;
+ iter_data.add_pars = add_pars;
+ iter_data.num_added = 0;
+ copy_m4_m4(iter_data.imat, imat);
+
+ BrushAddCountIterTLSData tls = {NULL};
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC;
+ settings.userdata_chunk = &tls;
+ settings.userdata_chunk_size = sizeof(BrushAddCountIterTLSData);
+ settings.func_finalize = brush_add_count_iter_finalize;
+ BLI_task_parallel_range(0, number, &iter_data, brush_add_count_iter, &settings);
+
+ /* Convert add_parse to a dense array, where all new particles are in the
+ * beginnign of the array.
+ */
+ n = iter_data.num_added;
+ for (int current_iter = 0, new_index = 0; current_iter < number; current_iter++) {
+ if (add_pars[current_iter].num == DMCACHE_NOTFOUND) {
+ continue;
}
- else {
- dmx = 0.0f;
- dmy = 0.0f;
- }
-
- mco[0] = data->mval[0] + dmx;
- mco[1] = data->mval[1] + dmy;
- ED_view3d_win_to_segment(depsgraph, data->vc.ar, data->vc.v3d, mco, co1, co2, true);
-
- mul_m4_v3(imat, co1);
- mul_m4_v3(imat, co2);
- min_d=2.0;
-
- /* warning, returns the derived mesh face */
- if (particle_intersect_mesh(C, scene, ob, mesh, 0, co1, co2, &min_d, &add_pars[n].num_dmcache, add_pars[n].fuv, 0, 0, 0, 0)) {
- if (psys->part->use_modifier_stack && !psmd->mesh_final->runtime.deformed_only) {
- add_pars[n].num = add_pars[n].num_dmcache;
- add_pars[n].num_dmcache = DMCACHE_ISCHILD;
- }
- else if (mesh == psmd->mesh_original) {
- /* Final DM is not same topology as orig mesh, we have to map num_dmcache to real final dm. */
- add_pars[n].num = add_pars[n].num_dmcache;
- add_pars[n].num_dmcache = psys_particle_dm_face_lookup(
- psmd->mesh_final, psmd->mesh_original,
- add_pars[n].num, add_pars[n].fuv, NULL);
- }
- else {
- add_pars[n].num = add_pars[n].num_dmcache;
- }
-
- if (add_pars[n].num != DMCACHE_NOTFOUND) {
- n++;
- }
+ if (new_index != current_iter) {
+ new_index++;
+ continue;
}
+ memcpy(add_pars + new_index, add_pars + current_iter, sizeof(ParticleData));
+ new_index++;
}
+
+ /* TODO(sergey): Consider multi-threading this part as well. */
if (n) {
int newtotpart=totpart+n;
float hairmat[4][4], cur_co[3];
@@ -3618,7 +3887,7 @@ static int brush_add(const bContext *C, PEData *data, short number)
tree=BLI_kdtree_new(psys->totpart);
for (i=0, pa=psys->particles; i<totpart; i++, pa++) {
- psys_particle_on_dm(psmd->mesh_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, cur_co, 0, 0, 0, 0);
+ psys_particle_on_dm(psmd_eval->mesh_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, cur_co, 0, 0, 0, 0);
BLI_kdtree_insert(tree, i, cur_co);
}
@@ -3662,7 +3931,7 @@ static int brush_add(const bContext *C, PEData *data, short number)
int w, maxw;
float maxd, totw=0.0, weight[3];
- psys_particle_on_dm(psmd->mesh_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co1, 0, 0, 0, 0);
+ psys_particle_on_dm(psmd_eval->mesh_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co1, 0, 0, 0, 0);
maxw = BLI_kdtree_find_nearest_n(tree, co1, ptn, 3);
maxd= ptn[maxw-1].dist;
@@ -3727,7 +3996,7 @@ static int brush_add(const bContext *C, PEData *data, short number)
}
}
for (k=0, hkey=pa->hair; k<pset->totaddkey; k++, hkey++) {
- psys_mat_hair_to_global(ob, psmd->mesh_final, psys->part->from, pa, hairmat);
+ psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, pa, hairmat);
invert_m4_m4(imat, hairmat);
mul_m4_v3(imat, hkey->co);
}
@@ -3792,6 +4061,7 @@ static int brush_edit_init(bContext *C, wmOperator *op)
/* cache view depths and settings for re-use */
PE_set_view3d_data(C, &bedit->data);
+ PE_create_random_generator(&bedit->data);
return 1;
}
@@ -3804,7 +4074,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
Object *ob= bedit->ob;
PTCacheEdit *edit= bedit->edit;
ParticleEditSettings *pset= PE_settings(scene);
- ParticleSystemModifierData *psmd= edit->psys ? psys_get_modifier(ob, edit->psys) : NULL;
+ ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
ParticleBrushData *brush= &pset->brush[pset->brushtype];
ARegion *ar= CTX_wm_region(C);
float vec[3], mousef[2];
@@ -3840,7 +4110,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
if (((pset->brushtype == PE_BRUSH_ADD) ?
(sqrtf(dx * dx + dy * dy) > pset->brush[PE_BRUSH_ADD].step) : (dx != 0 || dy != 0)) || bedit->first)
{
- PEData data= bedit->data;
+ PEData data = bedit->data;
data.context = C; // TODO(mai): why isnt this set in bedit->data?
view3d_operator_needs_opengl(C);
@@ -3919,7 +4189,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
case PE_BRUSH_PUFF:
{
if (edit->psys) {
- data.mesh = psmd->mesh_final;
+ data.mesh = psmd_eval->mesh_final;
data.mval= mval;
data.rad= pe_brush_size_get(scene, brush);
data.select= selected;
@@ -3975,7 +4245,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
case PE_BRUSH_WEIGHT:
{
if (edit->psys) {
- data.mesh = psmd->mesh_final;
+ data.mesh = psmd_eval->mesh_final;
data.mval= mval;
data.rad= pe_brush_size_get(scene, brush);
@@ -4006,7 +4276,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
if (edit->psys) {
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
BKE_particle_batch_cache_dirty(edit->psys, BKE_PARTICLE_BATCH_DIRTY_ALL);
- DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
+ DEG_id_tag_update(&ob->id, DEG_TAG_SELECT_UPDATE);
}
else {
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
@@ -4025,6 +4295,7 @@ static void brush_edit_exit(wmOperator *op)
{
BrushEdit *bedit= op->customdata;
+ PE_free_random_generator(&bedit->data);
MEM_freeN(bedit);
}
@@ -4079,8 +4350,11 @@ static int brush_edit_modal(bContext *C, wmOperator *op, const wmEvent *event)
case LEFTMOUSE:
case MIDDLEMOUSE:
case RIGHTMOUSE: // XXX hardcoded
- brush_edit_exit(op);
- return OPERATOR_FINISHED;
+ if (event->val == KM_RELEASE) {
+ brush_edit_exit(op);
+ return OPERATOR_FINISHED;
+ }
+ break;
case MOUSEMOVE:
brush_edit_apply_event(C, op, event);
break;
@@ -4271,7 +4545,7 @@ static int shape_cut_exec(bContext *C, wmOperator *UNUSED(op))
if (edit->psys) {
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
BKE_particle_batch_cache_dirty(edit->psys, BKE_PARTICLE_BATCH_DIRTY_ALL);
- DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
+ DEG_id_tag_update(&ob->id, DEG_TAG_SELECT_UPDATE);
}
else {
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
@@ -4308,7 +4582,7 @@ int PE_minmax(Scene *scene, ViewLayer *view_layer, float min[3], float max[3])
Object *ob= OBACT(view_layer);
PTCacheEdit *edit= PE_get_current(scene, ob);
ParticleSystem *psys;
- ParticleSystemModifierData *psmd = NULL;
+ ParticleSystemModifierData *psmd_eval = NULL;
POINT_P; KEY_K;
float co[3], mat[4][4];
int ok= 0;
@@ -4316,13 +4590,13 @@ int PE_minmax(Scene *scene, ViewLayer *view_layer, float min[3], float max[3])
if (!edit) return ok;
if ((psys = edit->psys))
- psmd= psys_get_modifier(ob, psys);
+ psmd_eval = edit->psmd_eval;
else
unit_m4(mat);
LOOP_VISIBLE_POINTS {
if (psys)
- psys_mat_hair_to_global(ob, psmd->mesh_final, psys->part->from, psys->particles+p, mat);
+ psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, psys->particles+p, mat);
LOOP_SELECTED_KEYS {
copy_v3_v3(co, key->co);
@@ -4342,19 +4616,43 @@ int PE_minmax(Scene *scene, ViewLayer *view_layer, float min[3], float max[3])
/************************ particle edit toggle operator ************************/
+static struct ParticleSystem *psys_eval_get(Depsgraph *depsgraph,
+ Object *object,
+ ParticleSystem *psys)
+{
+ Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
+ if (object_eval == object) {
+ return psys;
+ }
+ ParticleSystem *psys_eval = object_eval->particlesystem.first;
+ while (psys_eval != NULL) {
+ if (psys_eval->orig_psys == psys) {
+ return psys_eval;
+ }
+ psys_eval = psys_eval->next;
+ }
+ return psys_eval;
+}
+
/* initialize needed data for bake edit */
void PE_create_particle_edit(
Depsgraph *depsgraph, Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys)
{
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
PTCacheEdit *edit;
ParticleSystemModifierData *psmd = (psys) ? psys_get_modifier(ob, psys) : NULL;
+ ParticleSystemModifierData *psmd_eval = NULL;
POINT_P; KEY_K;
ParticleData *pa = NULL;
HairKey *hkey;
int totpoint;
+ if (psmd != NULL) {
+ psmd_eval = (ParticleSystemModifierData *)modifiers_findByName(ob_eval, psmd->modifier.name);
+ }
+
/* no psmd->dm happens in case particle system modifier is not enabled */
- if (!(psys && psmd && psmd->mesh_final) && !cache)
+ if (!(psys && psmd && psmd_eval->mesh_final) && !cache)
return;
if (cache && cache->flag & PTCACHE_DISK_CACHE)
@@ -4366,6 +4664,9 @@ void PE_create_particle_edit(
edit = (psys) ? psys->edit : cache->edit;
if (!edit) {
+ ParticleSystem *psys_eval = psys_eval_get(depsgraph, ob, psys);
+ psys_copy_particles(psys, psys_eval);
+
totpoint = psys ? psys->totpart : (int)((PTCacheMem *)cache->mem_cache.first)->totpoint;
edit= MEM_callocN(sizeof(PTCacheEdit), "PE_create_particle_edit");
@@ -4373,8 +4674,11 @@ void PE_create_particle_edit(
edit->totpoint = totpoint;
if (psys && !cache) {
- psys->edit= edit;
+ edit->psmd = psmd;
+ edit->psmd_eval = psmd_eval;
+ psys->edit = edit;
edit->psys = psys;
+ edit->psys_eval = psys_eval;
psys->free_edit= PE_free_ptcache_edit;
@@ -4439,9 +4743,14 @@ void PE_create_particle_edit(
psys = NULL;
}
+ /* Causes assert on startup. */
+#if 0
UI_GetThemeColor3ubv(TH_EDGE_SELECT, edit->sel_col);
UI_GetThemeColor3ubv(TH_WIRE, edit->nosel_col);
-
+#else
+ memset(edit->sel_col, 0xff, sizeof(edit->sel_col));
+ memset(edit->nosel_col, 0x00, sizeof(edit->nosel_col));
+#endif
recalc_lengths(edit);
if (psys && !cache)
recalc_emitter_field(depsgraph, ob, psys);
@@ -4484,14 +4793,6 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *op)
if (!is_mode_set) {
PTCacheEdit *edit;
- /* Particle edit mode requires original object to have all strands
- * cached. A bit annoying to do update here, but is simpler than
- * rewriting the while edit mode code.
- */
- ob->id.recalc |= (ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- BKE_scene_graph_update_tagged(depsgraph, CTX_data_main(C));
- BKE_object_eval_transform_all(depsgraph, scene, ob);
- BKE_object_handle_data_update(depsgraph, scene, ob);
ob->mode |= mode_flag;
edit= PE_create_current(depsgraph, scene, ob);
@@ -4678,7 +4979,6 @@ static int unify_length_exec(bContext *C, wmOperator *UNUSED(op))
}
scale_points_to_length(edit, average_length);
-
PE_update_object(depsgraph, scene, ob, 1);
if (edit->psys) {
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
diff --git a/source/blender/editors/physics/particle_edit_undo.c b/source/blender/editors/physics/particle_edit_undo.c
index 6576d692f70..fdf765e4557 100644
--- a/source/blender/editors/physics/particle_edit_undo.c
+++ b/source/blender/editors/physics/particle_edit_undo.c
@@ -44,9 +44,9 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
+#include "BKE_context.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
-#include "BKE_context.h"
#include "BKE_undo_system.h"
#include "DEG_depsgraph.h"
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index fbccdcfcdba..8a9eb369e66 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -82,13 +82,14 @@ static float I[4][4] = {{1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f}, {0.0
static int particle_system_add_exec(bContext *C, wmOperator *UNUSED(op))
{
+ Main *bmain = CTX_data_main(C);
Object *ob= ED_object_context(C);
Scene *scene = CTX_data_scene(C);
if (!scene || !ob)
return OPERATOR_CANCELLED;
- object_add_particle_system(scene, ob, NULL);
+ object_add_particle_system(bmain, scene, ob, NULL);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
@@ -113,6 +114,7 @@ void OBJECT_OT_particle_system_add(wmOperatorType *ot)
static int particle_system_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
+ Main *bmain = CTX_data_main(C);
Object *ob = ED_object_context(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -122,7 +124,7 @@ static int particle_system_remove_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
mode_orig = ob->mode;
- object_remove_particle_system(scene, ob);
+ object_remove_particle_system(bmain, scene, ob);
/* possible this isn't the active object
* object_remove_particle_system() clears the mode on the last psys
diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c
index 130dcba060d..904e4242ed1 100644
--- a/source/blender/editors/physics/physics_fluid.c
+++ b/source/blender/editors/physics/physics_fluid.c
@@ -399,7 +399,7 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid
/* XXX: This can't be used due to an anim sys optimization that ignores recalc object animation,
* leaving it for the depgraph (this ignores object animation such as modifier properties though... :/ )
- * --> BKE_animsys_evaluate_all_animation(G.main, eval_time);
+ * --> BKE_animsys_evaluate_all_animation(CTX_data_main(C), eval_time);
* This doesn't work with drivers:
* --> BKE_animsys_evaluate_animdata(&fsDomain->id, fsDomain->adt, eval_time, ADT_RECALC_ALL);
*/
diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c
index 45172774d55..343804726bf 100644
--- a/source/blender/editors/physics/physics_pointcache.c
+++ b/source/blender/editors/physics/physics_pointcache.c
@@ -140,7 +140,7 @@ static void ptcache_job_endjob(void *customdata)
G.is_rendering = false;
BKE_spacedata_draw_locks(false);
- WM_set_locked_interface(G.main->wm.first, false);
+ WM_set_locked_interface(G_MAIN->wm.first, false);
WM_main_add_notifier(NC_SCENE | ND_FRAME, scene);
WM_main_add_notifier(NC_OBJECT | ND_POINTCACHE, job->baker->pid.ob);
@@ -164,7 +164,7 @@ static PTCacheBaker *ptcache_baker_create(bContext *C, wmOperator *op, bool all)
{
PTCacheBaker *baker = MEM_callocN(sizeof(PTCacheBaker), "PTCacheBaker");
- baker->main = CTX_data_main(C);
+ baker->bmain = CTX_data_main(C);
baker->scene = CTX_data_scene(C);
baker->view_layer = CTX_data_view_layer(C);
baker->depsgraph = CTX_data_depsgraph(C);
diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c
index 99976898ac1..bdfbc47b22f 100644
--- a/source/blender/editors/physics/rigidbody_object.c
+++ b/source/blender/editors/physics/rigidbody_object.c
@@ -110,6 +110,7 @@ bool ED_rigidbody_object_add(Main *bmain, Scene *scene, Object *ob, int type, Re
}
if (rbw->group == NULL) {
rbw->group = BKE_collection_add(bmain, NULL, "RigidBodyWorld");
+ id_fake_user_set(&rbw->group->id);
}
/* make rigidbody object settings */
@@ -130,11 +131,7 @@ bool ED_rigidbody_object_add(Main *bmain, Scene *scene, Object *ob, int type, Re
void ED_rigidbody_object_remove(Main *bmain, Scene *scene, Object *ob)
{
- RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
-
- BKE_rigidbody_remove_object(scene, ob);
- if (rbw)
- BKE_collection_object_remove(bmain, rbw->group, ob, false);
+ BKE_rigidbody_remove_object(bmain, scene, ob);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&ob->id, OB_RECALC_OB);
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index d990f0b34d0..6a5844e323f 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -673,14 +673,14 @@ static void render_endjob(void *rjv)
* would be re-assigned. assign dummy callbacks to avoid referencing freed renderjobs bug [#24508] */
RE_InitRenderCB(rj->re);
- if (rj->main != G.main)
+ if (rj->main != G_MAIN)
BKE_main_free(rj->main);
/* else the frame will not update for the original value */
if (rj->anim && !(rj->scene->r.scemode & R_NO_FRAME_UPDATE)) {
/* possible this fails of loading new file while rendering */
- if (G.main->wm.first) {
- ED_update_for_newframe(G.main, rj->depsgraph);
+ if (G_MAIN->wm.first) {
+ ED_update_for_newframe(G_MAIN, rj->depsgraph);
}
}
@@ -741,7 +741,7 @@ static void render_endjob(void *rjv)
* and using one from Global will unlock exactly the same manager as
* was locked before running the job.
*/
- WM_set_locked_interface(G.main->wm.first, false);
+ WM_set_locked_interface(G_MAIN->wm.first, false);
/* We've freed all the derived caches before rendering, which is
* effectively the same as if we re-loaded the file.
@@ -749,11 +749,11 @@ static void render_endjob(void *rjv)
* So let's not try being smart here and just reset all updated
* scene layers and use generic DAG_on_visible_update.
*/
- for (scene = G.main->scene.first; scene; scene = scene->id.next) {
+ for (scene = G_MAIN->scene.first; scene; scene = scene->id.next) {
scene->lay_updated = 0;
}
- DEG_on_visible_update(G.main, false);
+ DEG_on_visible_update(G_MAIN, false);
}
}
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 4a3c7a3fd4b..cdd79f43a72 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -176,6 +176,9 @@ typedef struct ShaderPreview {
Main *bmain;
Main *pr_main;
+
+ void *gl_context;
+ bool gl_context_owner;
} ShaderPreview;
typedef struct IconPreviewSize {
@@ -191,6 +194,8 @@ typedef struct IconPreview {
void *owner;
ID *id;
ListBase sizes;
+
+ void *gl_context;
} IconPreview;
/* *************************** Preview for buttons *********************** */
@@ -741,6 +746,10 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs
/* set this for all previews, default is react to G.is_break still */
RE_test_break_cb(re, sp, shader_preview_break);
+ if (sp->gl_context) {
+ RE_gl_context_set(re, sp->gl_context);
+ }
+
/* lens adjust */
oldlens = ((Camera *)sce->camera->data)->lens;
if (sizex > sp->sizey)
@@ -860,6 +869,10 @@ static void shader_preview_free(void *customdata)
}
MEM_freeN(sp->lampcopy);
}
+ if (sp->gl_context_owner && sp->gl_context) {
+ WM_opengl_context_dispose(sp->gl_context);
+ sp->gl_context = NULL;
+ }
MEM_freeN(sp);
}
@@ -1075,6 +1088,8 @@ static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short
sp->pr_rect = cur_size->rect;
sp->id = ip->id;
sp->bmain = ip->bmain;
+ sp->gl_context = ip->gl_context;
+ sp->gl_context_owner = false;
if (is_render) {
BLI_assert(ip->id);
@@ -1091,6 +1106,11 @@ static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short
common_preview_startjob(sp, stop, do_update, progress);
shader_preview_free(sp);
}
+
+ if (ip->gl_context) {
+ WM_opengl_context_dispose(ip->gl_context);
+ ip->gl_context = NULL;
+ }
}
static void icon_preview_endjob(void *customdata)
@@ -1174,8 +1194,17 @@ void ED_preview_icon_job(const bContext *C, void *owner, ID *id, unsigned int *r
/* render all resolutions from suspended job too */
old_ip = WM_jobs_customdata_get(wm_job);
- if (old_ip)
+ if (old_ip) {
BLI_movelisttolist(&ip->sizes, &old_ip->sizes);
+ /* NOTE: This assumes that it will be the same thread
+ * that will be used when resuming the job. */
+ ip->gl_context = old_ip->gl_context;
+ }
+
+ if (ip->gl_context == NULL) {
+ /* Create context in the main thread. */
+ ip->gl_context = WM_opengl_context_create();
+ }
/* customdata for preview thread */
ip->bmain = CTX_data_main(C);
@@ -1206,7 +1235,7 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M
{
Object *ob = CTX_data_active_object(C);
wmJob *wm_job;
- ShaderPreview *sp;
+ ShaderPreview *sp, *old_sp;
Scene *scene = CTX_data_scene(C);
short id_type = GS(id->name);
@@ -1223,6 +1252,21 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M
WM_JOB_EXCL_RENDER, WM_JOB_TYPE_RENDER_PREVIEW);
sp = MEM_callocN(sizeof(ShaderPreview), "shader preview");
+ /* Reuse previous gl context. */
+ old_sp = WM_jobs_customdata_get(wm_job);
+ if (old_sp) {
+ /* NOTE: This assumes that it will be the same thread
+ * that will be used when resuming the job. */
+ old_sp->gl_context_owner = false; /* Don't free it */
+ sp->gl_context = old_sp->gl_context;
+ }
+
+ if (sp->gl_context == NULL) {
+ /* Create context in the main thread. */
+ sp->gl_context = WM_opengl_context_create();
+ }
+ sp->gl_context_owner = true;
+
/* customdata for preview thread */
sp->scene = scene;
sp->depsgraph = CTX_data_depsgraph(C);
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 3f32242cd1b..a822dabf7b4 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -303,6 +303,7 @@ static int material_slot_de_select(bContext *C, bool select)
}
}
+ DEG_id_tag_update(ob->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index f73ce24c24b..d9851487569 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -953,6 +953,9 @@ static void region_overlap_fix(ScrArea *sa, ARegion *ar)
}
if (ar1->overlap && ((ar1->alignment & RGN_SPLIT_PREV) == 0)) {
+ if (ELEM(ar1->alignment, RGN_ALIGN_FLOAT)) {
+ continue;
+ }
align1 = ar1->alignment;
if (BLI_rcti_isect(&ar1->winrct, &ar->winrct, NULL)) {
if (align1 != align) {
@@ -994,6 +997,9 @@ static void region_overlap_fix(ScrArea *sa, ARegion *ar)
if (ar1->flag & (RGN_FLAG_HIDDEN)) {
continue;
}
+ if (ELEM(ar1->alignment, RGN_ALIGN_FLOAT)) {
+ continue;
+ }
if (ar1->overlap && (ar1->alignment & RGN_SPLIT_PREV) == 0) {
if ((ar1->alignment != align) && BLI_rcti_isect(&ar1->winrct, &ar->winrct, NULL)) {
@@ -1008,6 +1014,9 @@ static void region_overlap_fix(ScrArea *sa, ARegion *ar)
/* overlapping regions only in the following restricted cases */
bool ED_region_is_overlap(int spacetype, int regiontype)
{
+ if (regiontype == RGN_TYPE_HUD) {
+ return 1;
+ }
if (U.uiflag2 & USER_REGION_OVERLAP) {
if (ELEM(spacetype, SPACE_VIEW3D, SPACE_SEQ, SPACE_IMAGE)) {
if (ELEM(regiontype, RGN_TYPE_TOOLS, RGN_TYPE_UI, RGN_TYPE_TOOL_PROPS))
@@ -1052,8 +1061,9 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti
/* clear state flags first */
ar->flag &= ~RGN_FLAG_TOO_SMALL;
/* user errors */
- if (ar->next == NULL && alignment != RGN_ALIGN_QSPLIT)
+ if ((ar->next == NULL) && !ELEM(alignment, RGN_ALIGN_QSPLIT, RGN_ALIGN_FLOAT)) {
alignment = RGN_ALIGN_NONE;
+ }
/* prefsize, taking into account DPI */
prefsizex = UI_DPI_FAC * ((ar->sizex > 1) ? ar->sizex + 0.5f : ar->type->prefsizex);
@@ -1076,7 +1086,28 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti
/* hidden is user flag */
}
else if (alignment == RGN_ALIGN_FLOAT) {
- /* XXX floating area region, not handled yet here */
+ /**
+ * \note Currently this window type is only used for #RGN_TYPE_HUD,
+ * We expect the panel to resize it's self to be larger.
+ *
+ * This aligns to the lower left of the area.
+ */
+ rcti overlap_remainder_margin = *overlap_remainder;
+ BLI_rcti_resize(
+ &overlap_remainder_margin,
+ max_ii(0, BLI_rcti_size_x(overlap_remainder) - UI_UNIT_X / 2),
+ max_ii(0, BLI_rcti_size_y(overlap_remainder) - UI_UNIT_Y / 2));
+ ar->winrct.xmin = overlap_remainder_margin.xmin;
+ ar->winrct.ymin = overlap_remainder_margin.ymin;
+ ar->winrct.xmax = ar->winrct.xmin + ar->sizex - 1;
+ ar->winrct.ymax = ar->winrct.ymin + ar->sizey - 1;
+
+ BLI_rcti_isect(&ar->winrct, &overlap_remainder_margin, &ar->winrct);
+ if (BLI_rcti_size_x(&ar->winrct) < UI_UNIT_X ||
+ BLI_rcti_size_y(&ar->winrct) < UI_UNIT_Y)
+ {
+ ar->flag |= RGN_FLAG_TOO_SMALL;
+ }
}
else if (rct_fits(remainder, 'v', 1) < 0 || rct_fits(remainder, 'h', 1) < 0) {
/* remainder is too small for any usage */
@@ -1215,7 +1246,7 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti
if (ar->winy > 1) ar->sizey = (ar->winy + 0.5f) / UI_DPI_FAC;
/* exception for multiple overlapping regions on same spot */
- if (ar->overlap) {
+ if (ar->overlap & (alignment != RGN_ALIGN_FLOAT)) {
region_overlap_fix(sa, ar);
}
@@ -1424,7 +1455,7 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa)
}
for (ar = sa->regionbase.first; ar; ar = ar->next)
- ar->type = BKE_regiontype_from_id(sa->type, ar->regiontype);
+ ar->type = BKE_regiontype_from_id_or_first(sa->type, ar->regiontype);
/* area sizes */
area_calc_totrct(sa, &window_rect);
@@ -1480,13 +1511,13 @@ static void region_update_rect(ARegion *ar)
/**
* Call to move a popup window (keep OpenGL context free!)
*/
-void ED_region_update_rect(bContext *UNUSED(C), ARegion *ar)
+void ED_region_update_rect(ARegion *ar)
{
region_update_rect(ar);
}
/* externally called for floating regions like menus */
-void ED_region_init(bContext *UNUSED(C), ARegion *ar)
+void ED_region_init(ARegion *ar)
{
/* refresh can be called before window opened */
region_subwindow(ar);
@@ -1781,7 +1812,10 @@ static ThemeColorID region_background_color_id(const bContext *C, const ARegion
static void region_clear_color(const bContext *C, const ARegion *ar, ThemeColorID colorid)
{
- if (ar->overlap) {
+ if (ar->alignment == RGN_ALIGN_FLOAT) {
+ /* handle our own drawing. */
+ }
+ else if (ar->overlap) {
/* view should be in pixelspace */
UI_view2d_view_restore(C);
@@ -1806,15 +1840,16 @@ BLI_INLINE bool streq_array_any(const char *s, const char *arr[])
return false;
}
-static void ed_panel_draw(const bContext *C,
- ScrArea *sa,
- ARegion *ar,
- ListBase *lb,
- PanelType *pt,
- Panel *panel,
- int w,
- int em,
- bool vertical)
+static void ed_panel_draw(
+ const bContext *C,
+ ScrArea *sa,
+ ARegion *ar,
+ ListBase *lb,
+ PanelType *pt,
+ Panel *panel,
+ int w,
+ int em,
+ bool vertical)
{
uiStyle *style = UI_style_get_dpi();
@@ -1827,6 +1862,21 @@ static void ed_panel_draw(const bContext *C,
/* bad fixed values */
int xco, yco, h = 0;
+ if (pt->draw_header_preset && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) {
+ /* for preset menu */
+ panel->layout = UI_block_layout(
+ block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER,
+ 0, (UI_UNIT_Y * 1.1f) + style->panelspace, UI_UNIT_Y, 1, 0, style);
+
+ pt->draw_header_preset(C, panel);
+
+ int headerend = w - UI_UNIT_X;
+
+ UI_block_layout_resolve(block, &xco, &yco);
+ UI_block_translate(block, headerend - xco, 0);
+ panel->layout = NULL;
+ }
+
if (pt->draw_header && !(pt->flag & PNL_NO_HEADER) && (open || vertical)) {
int labelx, labely;
UI_panel_label_offset(block, &labelx, &labely);
@@ -1891,13 +1941,16 @@ static void ed_panel_draw(const bContext *C,
* Matching against any of these strings will draw the panel.
* Can be NULL to skip context checks.
*/
-void ED_region_panels(const bContext *C, ARegion *ar, const char *contexts[], int contextnr, const bool vertical)
+void ED_region_panels_layout_ex(
+ const bContext *C, ARegion *ar,
+ const char *contexts[], int contextnr, const bool vertical)
{
+ ar->runtime.category = NULL;
+
const WorkSpace *workspace = CTX_wm_workspace(C);
ScrArea *sa = CTX_wm_area(C);
PanelType *pt;
View2D *v2d = &ar->v2d;
- View2DScrollers *scrollers;
int x, y, w, em;
bool is_context_new = 0;
int scroll;
@@ -1908,6 +1961,7 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *contexts[], in
const char *category = NULL;
const int category_tabs_width = UI_PANEL_CATEGORY_MARGIN_WIDTH;
int margin_x = 0;
+ const bool region_layout_based = ar->flag & RGN_FLAG_DYNAMIC_SIZE;
BLI_SMALLSTACK_DECLARE(pt_stack, PanelType *);
@@ -2018,7 +2072,28 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *contexts[], in
UI_panels_end(C, ar, &x, &y);
/* before setting the view */
- if (vertical) {
+ if (region_layout_based) {
+ /* XXX, only single panel support atm.
+ * Can't use x/y values calculated above because they're not using the real height of panels,
+ * instead they calculate offsets for the next panel to start drawing. */
+ Panel *panel = ar->panels.last;
+ if (panel != NULL) {
+ int size_dyn[2] = {
+ UI_UNIT_X * ((panel->flag & PNL_CLOSED) ? 8 : 14),
+ UI_panel_size_y(panel),
+ };
+ /* region size is layout based and needs to be updated */
+ if ((ar->sizex != size_dyn[0]) ||
+ (ar->sizey != size_dyn[1]))
+ {
+ ar->sizex = size_dyn[0];
+ ar->sizey = size_dyn[1];
+ sa->flag |= AREA_FLAG_REGION_SIZE_UPDATE;
+ }
+ y = ABS(ar->sizey - 1);
+ }
+ }
+ else if (vertical) {
/* we always keep the scroll offset - so the total view gets increased with the scrolled away part */
if (v2d->cur.ymax < -FLT_EPSILON) {
/* Clamp to lower view boundary */
@@ -2059,7 +2134,22 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *contexts[], in
#endif
}
- region_clear_color(C, ar, (ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK);
+ if (use_category_tabs) {
+ ar->runtime.category = category;
+ }
+}
+void ED_region_panels_layout(const bContext *C, ARegion *ar)
+{
+ ED_region_panels_layout_ex(C, ar, NULL, -1, true);
+}
+
+void ED_region_panels_draw(const bContext *C, ARegion *ar)
+{
+ View2D *v2d = &ar->v2d;
+
+ if (ar->alignment != RGN_ALIGN_FLOAT) {
+ region_clear_color(C, ar, (ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK);
+ }
/* reset line width for drawing tabs */
glLineWidth(1.0f);
@@ -2073,16 +2163,34 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *contexts[], in
/* restore view matrix */
UI_view2d_view_restore(C);
- if (use_category_tabs) {
- UI_panel_category_draw_all(ar, category);
+ /* Set in layout. */
+ if (ar->runtime.category) {
+ UI_panel_category_draw_all(ar, ar->runtime.category);
}
/* scrollers */
- scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ View2DScrollers *scrollers = UI_view2d_scrollers_calc(
+ C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
UI_view2d_scrollers_draw(C, v2d, scrollers);
UI_view2d_scrollers_free(scrollers);
}
+void ED_region_panels_ex(
+ const bContext *C, ARegion *ar,
+ const char *contexts[], int contextnr, const bool vertical)
+{
+ /* TODO: remove? */
+ ED_region_panels_layout_ex(C, ar, contexts, contextnr, vertical);
+ ED_region_panels_draw(C, ar);
+}
+
+void ED_region_panels(const bContext *C, ARegion *ar)
+{
+ /* TODO: remove? */
+ ED_region_panels_layout(C, ar);
+ ED_region_panels_draw(C, ar);
+}
+
void ED_region_panels_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
@@ -2102,13 +2210,12 @@ void ED_region_header_layout(const bContext *C, ARegion *ar)
Header header = {NULL};
int maxco, xco, yco;
int headery = ED_area_headersize();
- const int start_ofs = UI_HEADER_OFFSET_START;
bool region_layout_based = ar->flag & RGN_FLAG_DYNAMIC_SIZE;
/* set view2d view matrix for scrolling (without scrollers) */
UI_view2d_view_ortho(&ar->v2d);
- xco = maxco = start_ofs;
+ xco = maxco = UI_HEADER_OFFSET;
yco = headery + (ar->winy - headery) / 2 - floor(0.2f * UI_UNIT_Y);
/* XXX workaround for 1 px alignment issue. Not sure what causes it... Would prefer a proper fix - Julian */
@@ -2139,7 +2246,7 @@ void ED_region_header_layout(const bContext *C, ARegion *ar)
if (xco > maxco)
maxco = xco;
- int new_sizex = (maxco + start_ofs) / UI_DPI_FAC;
+ int new_sizex = (maxco + UI_HEADER_OFFSET) / UI_DPI_FAC;
if (region_layout_based && (ar->sizex != new_sizex)) {
/* region size is layout based and needs to be updated */
@@ -2152,8 +2259,12 @@ void ED_region_header_layout(const bContext *C, ARegion *ar)
UI_block_end(C, block);
}
+ if (!region_layout_based) {
+ maxco += UI_HEADER_OFFSET;
+ }
+
/* always as last */
- UI_view2d_totRect_set(&ar->v2d, maxco + (region_layout_based ? 0 : UI_UNIT_X + 80), headery);
+ UI_view2d_totRect_set(&ar->v2d, maxco, headery);
/* restore view matrix */
UI_view2d_view_restore(C);
@@ -2161,11 +2272,11 @@ void ED_region_header_layout(const bContext *C, ARegion *ar)
void ED_region_header_draw(const bContext *C, ARegion *ar)
{
- UI_view2d_view_ortho(&ar->v2d);
-
/* clear */
region_clear_color(C, ar, region_background_color_id(C, ar));
+ UI_view2d_view_ortho(&ar->v2d);
+
/* View2D matrix might have changed due to dynamic sized regions. */
UI_blocklist_update_window_matrix(C, &ar->uiblocks);
@@ -2687,6 +2798,9 @@ void ED_region_visible_rect(ARegion *ar, rcti *rect)
rect->ymax = arn->winrct.ymin;
}
}
+ else if (arn->alignment == RGN_ALIGN_FLOAT) {
+ /* Skip floating. */
+ }
else {
BLI_assert(!"Region overlap with unknown alignment");
}
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index ac4ab3461a3..53abe3ed4ea 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -832,13 +832,13 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win)
}
/* file read, set all screens, ... */
-void ED_screens_initialize(Main *UNUSED(bmain), wmWindowManager *wm)
+void ED_screens_initialize(Main *bmain, wmWindowManager *wm)
{
wmWindow *win;
for (win = wm->windows.first; win; win = win->next) {
if (WM_window_get_active_workspace(win) == NULL) {
- WM_window_set_active_workspace(win, G.main->workspaces.first);
+ WM_window_set_active_workspace(win, bmain->workspaces.first);
}
if (BLI_listbase_is_empty(&win->global_areas.areabase)) {
@@ -961,7 +961,7 @@ static void screen_cursor_set(wmWindow *win, const int xy[2])
ScrArea *sa;
for (sa = screen->areabase.first; sa; sa = sa->next)
- if ((az = is_in_area_actionzone(sa, xy)))
+ if ((az = ED_area_actionzone_find_xy(sa, xy)))
break;
if (sa) {
@@ -1003,7 +1003,7 @@ void ED_screen_set_active_region(bContext *C, wmWindow *win, const int xy[2])
ED_screen_areas_iter(win, scr, area_iter) {
if (xy[0] > area_iter->totrct.xmin && xy[0] < area_iter->totrct.xmax) {
if (xy[1] > area_iter->totrct.ymin && xy[1] < area_iter->totrct.ymax) {
- if (is_in_area_actionzone(area_iter, xy) == NULL) {
+ if (ED_area_actionzone_refresh_xy(area_iter, xy) == NULL) {
sa = area_iter;
break;
}
@@ -1073,7 +1073,7 @@ int ED_screen_area_active(const bContext *C)
ScrArea *sa = CTX_wm_area(C);
if (win && sc && sa) {
- AZone *az = is_in_area_actionzone(sa, &win->eventstate->x);
+ AZone *az = ED_area_actionzone_find_xy(sa, &win->eventstate->x);
ARegion *ar;
if (az && az->type == AZONE_REGION)
diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h
index b02198764e0..2c343fb9d70 100644
--- a/source/blender/editors/screen/screen_intern.h
+++ b/source/blender/editors/screen/screen_intern.h
@@ -67,7 +67,8 @@ ScrEdge *screen_find_active_scredge(
const wmWindow *win, const bScreen *screen,
const int mx, const int my);
-struct AZone *is_in_area_actionzone(ScrArea *sa, const int xy[2]);
+struct AZone *ED_area_actionzone_find_xy(ScrArea *sa, const int xy[2]);
+struct AZone *ED_area_actionzone_refresh_xy(ScrArea *sa, const int xy[2]);
/* screen_context.c */
int ed_screen_context(
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 1ecc3f72355..e08755c84c6 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -679,7 +679,7 @@ static void fullscreen_click_rcti_init(rcti *rect, const short x1, const short y
BLI_rcti_init(rect, x, x + icon_size, y, y + icon_size);
}
-AZone *is_in_area_actionzone(ScrArea *sa, const int xy[2])
+static AZone *area_actionzone_refresh_xy(ScrArea *sa, const int xy[2], const bool test_only)
{
AZone *az = NULL;
@@ -687,102 +687,117 @@ AZone *is_in_area_actionzone(ScrArea *sa, const int xy[2])
if (BLI_rcti_isect_pt_v(&az->rect, xy)) {
if (az->type == AZONE_AREA) {
/* no triangle intersect but a hotspot circle based on corner */
- int radius = (xy[0] - az->x1) * (xy[0] - az->x1) + (xy[1] - az->y1) * (xy[1] - az->y1);
-
- if (radius <= AZONESPOT * AZONESPOT)
+ int radius_sq = SQUARE(xy[0] - az->x1) + SQUARE(xy[1] - az->y1);
+ if (radius_sq <= SQUARE(AZONESPOT)) {
break;
+ }
}
else if (az->type == AZONE_REGION) {
break;
}
else if (az->type == AZONE_FULLSCREEN) {
- int mouse_radius, spot_radius, fadein_radius, fadeout_radius;
rcti click_rect;
-
fullscreen_click_rcti_init(&click_rect, az->x1, az->y1, az->x2, az->y2);
+ const bool click_isect = BLI_rcti_isect_pt_v(&click_rect, xy);
- if (BLI_rcti_isect_pt_v(&click_rect, xy)) {
- az->alpha = 1.0f;
+ if (test_only) {
+ if (click_isect) {
+ break;
+ }
}
else {
- mouse_radius = (xy[0] - az->x2) * (xy[0] - az->x2) + (xy[1] - az->y2) * (xy[1] - az->y2);
- spot_radius = AZONESPOT * AZONESPOT;
- fadein_radius = AZONEFADEIN * AZONEFADEIN;
- fadeout_radius = AZONEFADEOUT * AZONEFADEOUT;
-
- if (mouse_radius < spot_radius) {
+ if (click_isect) {
az->alpha = 1.0f;
}
- else if (mouse_radius < fadein_radius) {
- az->alpha = 1.0f;
- }
- else if (mouse_radius < fadeout_radius) {
- az->alpha = 1.0f - ((float)(mouse_radius - fadein_radius)) / ((float)(fadeout_radius - fadein_radius));
- }
else {
- az->alpha = 0.0f;
+ const int mouse_sq = SQUARE(xy[0] - az->x2) + SQUARE(xy[1] - az->y2);
+ const int spot_sq = SQUARE(AZONESPOT);
+ const int fadein_sq = SQUARE(AZONEFADEIN);
+ const int fadeout_sq = SQUARE(AZONEFADEOUT);
+
+ if (mouse_sq < spot_sq) {
+ az->alpha = 1.0f;
+ }
+ else if (mouse_sq < fadein_sq) {
+ az->alpha = 1.0f;
+ }
+ else if (mouse_sq < fadeout_sq) {
+ az->alpha = 1.0f - ((float)(mouse_sq - fadein_sq)) / ((float)(fadeout_sq - fadein_sq));
+ }
+ else {
+ az->alpha = 0.0f;
+ }
+
+ /* fade in/out but no click */
+ az = NULL;
}
- /* fade in/out but no click */
- az = NULL;
+ /* XXX force redraw to show/hide the action zone */
+ ED_area_tag_redraw(sa);
+ break;
}
-
- /* XXX force redraw to show/hide the action zone */
- ED_area_tag_redraw_no_rebuild(sa);
- break;
}
else if (az->type == AZONE_REGION_SCROLL) {
ARegion *ar = az->ar;
View2D *v2d = &ar->v2d;
const short isect_value = UI_view2d_mouse_in_scrollers(ar, v2d, xy[0], xy[1]);
- bool redraw = false;
-
- if (isect_value == 'h') {
- if (az->direction == AZ_SCROLL_HOR) {
- az->alpha = 1.0f;
- v2d->alpha_hor = 255;
- v2d->size_hor = V2D_SCROLL_HEIGHT;
- redraw = true;
- }
- }
- else if (isect_value == 'v') {
- if (az->direction == AZ_SCROLL_VERT) {
- az->alpha = 1.0f;
- v2d->alpha_vert = 255;
- v2d->size_vert = V2D_SCROLL_WIDTH;
- redraw = true;
+ if (test_only) {
+ if (isect_value != 0) {
+ break;
}
}
else {
- const int local_xy[2] = {xy[0] - ar->winrct.xmin, xy[1] - ar->winrct.ymin};
- float dist_fac = 0.0f, alpha = 0.0f;
-
- if (az->direction == AZ_SCROLL_HOR) {
- dist_fac = BLI_rcti_length_y(&v2d->hor, local_xy[1]) / AZONEFADEIN;
- CLAMP(dist_fac, 0.0f, 1.0f);
- alpha = 1.0f - dist_fac;
+ bool redraw = false;
- v2d->alpha_hor = alpha * 255;
- v2d->size_hor = round_fl_to_int(V2D_SCROLL_HEIGHT -
- ((V2D_SCROLL_HEIGHT - V2D_SCROLL_HEIGHT_MIN) * dist_fac));
+ if (isect_value == 'h') {
+ if (az->direction == AZ_SCROLL_HOR) {
+ az->alpha = 1.0f;
+ v2d->alpha_hor = 255;
+ v2d->size_hor = V2D_SCROLL_HEIGHT;
+ redraw = true;
+ }
}
- else if (az->direction == AZ_SCROLL_VERT) {
- dist_fac = BLI_rcti_length_x(&v2d->vert, local_xy[0]) / AZONEFADEIN;
- CLAMP(dist_fac, 0.0f, 1.0f);
- alpha = 1.0f - dist_fac;
-
- v2d->alpha_vert = alpha * 255;
- v2d->size_vert = round_fl_to_int(V2D_SCROLL_WIDTH -
- ((V2D_SCROLL_WIDTH - V2D_SCROLL_WIDTH_MIN) * dist_fac));
+ else if (isect_value == 'v') {
+ if (az->direction == AZ_SCROLL_VERT) {
+ az->alpha = 1.0f;
+ v2d->alpha_vert = 255;
+ v2d->size_vert = V2D_SCROLL_WIDTH;
+ redraw = true;
+ }
+ }
+ else {
+ const int local_xy[2] = {xy[0] - ar->winrct.xmin, xy[1] - ar->winrct.ymin};
+ float dist_fac = 0.0f, alpha = 0.0f;
+
+ if (az->direction == AZ_SCROLL_HOR) {
+ dist_fac = BLI_rcti_length_y(&v2d->hor, local_xy[1]) / AZONEFADEIN;
+ CLAMP(dist_fac, 0.0f, 1.0f);
+ alpha = 1.0f - dist_fac;
+
+ v2d->alpha_hor = alpha * 255;
+ v2d->size_hor = round_fl_to_int(
+ V2D_SCROLL_HEIGHT -
+ ((V2D_SCROLL_HEIGHT - V2D_SCROLL_HEIGHT_MIN) * dist_fac));
+ }
+ else if (az->direction == AZ_SCROLL_VERT) {
+ dist_fac = BLI_rcti_length_x(&v2d->vert, local_xy[0]) / AZONEFADEIN;
+ CLAMP(dist_fac, 0.0f, 1.0f);
+ alpha = 1.0f - dist_fac;
+
+ v2d->alpha_vert = alpha * 255;
+ v2d->size_vert = round_fl_to_int(
+ V2D_SCROLL_WIDTH -
+ ((V2D_SCROLL_WIDTH - V2D_SCROLL_WIDTH_MIN) * dist_fac));
+ }
+ az->alpha = alpha;
+ redraw = true;
}
- az->alpha = alpha;
- redraw = true;
- }
- if (redraw) {
- ED_area_tag_redraw_no_rebuild(sa);
+ if (redraw) {
+ ED_area_tag_redraw_no_rebuild(sa);
+ }
+ /* Don't return! */
}
- /* Don't return! */
}
}
}
@@ -790,6 +805,15 @@ AZone *is_in_area_actionzone(ScrArea *sa, const int xy[2])
return az;
}
+AZone *ED_area_actionzone_find_xy(ScrArea *sa, const int xy[2])
+{
+ return area_actionzone_refresh_xy(sa, xy, true);
+}
+
+AZone *ED_area_actionzone_refresh_xy(ScrArea *sa, const int xy[2])
+{
+ return area_actionzone_refresh_xy(sa, xy, false);
+}
static void actionzone_exit(wmOperator *op)
{
@@ -827,7 +851,7 @@ static void actionzone_apply(bContext *C, wmOperator *op, int type)
static int actionzone_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ScrArea *sa = CTX_wm_area(C);
- AZone *az = is_in_area_actionzone(sa, &event->x);
+ AZone *az = ED_area_actionzone_find_xy(sa, &event->x);
sActionzoneData *sad;
/* quick escape */
@@ -888,7 +912,7 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event)
WM_window_screen_rect_calc(win, &screen_rect);
/* once we drag outside the actionzone, register a gesture
* check we're not on an edge so join finds the other area */
- is_gesture = ((is_in_area_actionzone(sad->sa1, &event->x) != sad->az) &&
+ is_gesture = ((ED_area_actionzone_find_xy(sad->sa1, &event->x) != sad->az) &&
(screen_area_map_find_active_scredge(
AREAMAP_FROM_SCREEN(sc), &screen_rect, event->x, event->y) == NULL));
}
@@ -2262,7 +2286,7 @@ static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event)
case MOUSEMOVE:
{
const float aspect = BLI_rctf_size_x(&rmd->ar->v2d.cur) / (BLI_rcti_size_x(&rmd->ar->v2d.mask) + 1);
- const int snap_size_threshold = (U.widget_unit * 3) / aspect;
+ const int snap_size_threshold = (U.widget_unit * 2) / aspect;
if (rmd->edge == AE_LEFT_TO_TOPRIGHT || rmd->edge == AE_RIGHT_TO_TOPLEFT) {
delta = event->x - rmd->origx;
if (rmd->edge == AE_LEFT_TO_TOPRIGHT) delta = -delta;
@@ -2454,7 +2478,7 @@ static void SCREEN_OT_frame_offset(wmOperatorType *ot)
ot->poll = ED_operator_screenactive_norender;
ot->flag = OPTYPE_UNDO_GROUPED;
- ot->undo_group = "FRAME_CHANGE";
+ ot->undo_group = "Frame Change";
/* rna */
RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
@@ -2513,7 +2537,7 @@ static void SCREEN_OT_frame_jump(wmOperatorType *ot)
ot->poll = ED_operator_screenactive_norender;
ot->flag = OPTYPE_UNDO_GROUPED;
- ot->undo_group = "FRAME_CHANGE";
+ ot->undo_group = "Frame Change";
/* rna */
RNA_def_boolean(ot->srna, "end", 0, "Last Frame", "Jump to the last frame of the frame range");
@@ -2626,7 +2650,7 @@ static void SCREEN_OT_keyframe_jump(wmOperatorType *ot)
ot->poll = ED_operator_screenactive_norender;
ot->flag = OPTYPE_UNDO_GROUPED;
- ot->undo_group = "FRAME_CHANGE";
+ ot->undo_group = "Frame Change";
/* properties */
RNA_def_boolean(ot->srna, "next", true, "Next Keyframe", "");
@@ -2693,7 +2717,7 @@ static void SCREEN_OT_marker_jump(wmOperatorType *ot)
ot->poll = ED_operator_screenactive_norender;
ot->flag = OPTYPE_UNDO_GROUPED;
- ot->undo_group = "FRAME_CHANGE";
+ ot->undo_group = "Frame Change";
/* properties */
RNA_def_boolean(ot->srna, "next", true, "Next Marker", "");
diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c
index 7e50f8d41c4..e7b075dd5d0 100644
--- a/source/blender/editors/screen/screendump.c
+++ b/source/blender/editors/screen/screendump.c
@@ -234,7 +234,7 @@ static int screenshot_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
char filepath[FILE_MAX] = "//screen";
if (G.relbase_valid) {
BLI_strncpy(filepath, BKE_main_blendfile_path_from_global(), sizeof(filepath));
- BLI_replace_extension(filepath, sizeof(filepath), ""); /* strip '.blend' */
+ BLI_path_extension_replace(filepath, sizeof(filepath), ""); /* strip '.blend' */
}
RNA_string_set(op->ptr, "filepath", filepath);
diff --git a/source/blender/editors/screen/workspace_layout_edit.c b/source/blender/editors/screen/workspace_layout_edit.c
index 0c7431cb2e7..6d504c05dd1 100644
--- a/source/blender/editors/screen/workspace_layout_edit.c
+++ b/source/blender/editors/screen/workspace_layout_edit.c
@@ -57,7 +57,7 @@ WorkSpaceLayout *ED_workspace_layout_add(
WM_window_screen_rect_calc(win, &screen_rect);
screen = screen_add(bmain, name, &screen_rect);
- return BKE_workspace_layout_add(workspace, screen, name);
+ return BKE_workspace_layout_add(bmain, workspace, screen, name);
}
WorkSpaceLayout *ED_workspace_layout_duplicate(
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index f6cf0f56764..62bc379241f 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -354,28 +354,30 @@ typedef struct ProjPaintState {
SpinLock *tile_lock;
- DerivedMesh *dm;
- int dm_totlooptri;
- int dm_totpoly;
- int dm_totedge;
- int dm_totvert;
- bool dm_release;
+ Mesh *me_eval;
+ int totlooptri_eval;
+ int totpoly_eval;
+ int totedge_eval;
+ int totvert_eval;
- const MVert *dm_mvert;
- const MEdge *dm_medge;
- const MPoly *dm_mpoly;
- const MLoop *dm_mloop;
- const MLoopTri *dm_mlooptri;
+ const MVert *mvert_eval;
+ const MEdge *medge_eval;
+ const MPoly *mpoly_eval;
+ const MLoop *mloop_eval;
+ const MLoopTri *mlooptri_eval;
- const MLoopUV *dm_mloopuv_stencil;
+ const MLoopUV *mloopuv_stencil_eval;
/**
- * \note These UV layers are aligned to \a dm_mpoly
+ * \note These UV layers are aligned to \a mpoly_eval
* but each pointer references the start of the layer,
* so a loop indirection is needed as well.
*/
- const MLoopUV **dm_mloopuv;
- const MLoopUV **dm_mloopuv_clone; /* other UV map, use for cloning between layers */
+ const MLoopUV **poly_to_loop_uv;
+ const MLoopUV **poly_to_loop_uv_clone; /* other UV map, use for cloning between layers */
+
+ /* Actual material for each index, either from object or Mesh datablock... */
+ Material **mat_array;
bool use_colormanagement;
} ProjPaintState;
@@ -441,13 +443,13 @@ typedef struct {
BLI_INLINE const MPoly *ps_tri_index_to_mpoly(const ProjPaintState *ps, int tri_index)
{
- return &ps->dm_mpoly[ps->dm_mlooptri[tri_index].poly];
+ return &ps->mpoly_eval[ps->mlooptri_eval[tri_index].poly];
}
#define PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) \
- ps->dm_mloop[lt->tri[0]].v, \
- ps->dm_mloop[lt->tri[1]].v, \
- ps->dm_mloop[lt->tri[2]].v,
+ ps->mloop_eval[lt->tri[0]].v, \
+ ps->mloop_eval[lt->tri[1]].v, \
+ ps->mloop_eval[lt->tri[2]].v,
#define PS_LOOPTRI_AS_UV_3(uvlayer, lt) \
uvlayer[lt->poly][lt->tri[0]].uv, \
@@ -469,7 +471,7 @@ BLI_INLINE const MPoly *ps_tri_index_to_mpoly(const ProjPaintState *ps, int tri_
static TexPaintSlot *project_paint_face_paint_slot(const ProjPaintState *ps, int tri_index)
{
const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
- Material *ma = ps->dm->mat[mp->mat_nr];
+ Material *ma = ps->mat_array[mp->mat_nr];
return ma ? ma->texpaintslot + ma->paint_active_slot : NULL;
}
@@ -480,7 +482,7 @@ static Image *project_paint_face_paint_image(const ProjPaintState *ps, int tri_i
}
else {
const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
- Material *ma = ps->dm->mat[mp->mat_nr];
+ Material *ma = ps->mat_array[mp->mat_nr];
TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_active_slot : NULL;
return slot ? slot->ima : ps->canvas_ima;
}
@@ -489,14 +491,14 @@ static Image *project_paint_face_paint_image(const ProjPaintState *ps, int tri_i
static TexPaintSlot *project_paint_face_clone_slot(const ProjPaintState *ps, int tri_index)
{
const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
- Material *ma = ps->dm->mat[mp->mat_nr];
+ Material *ma = ps->mat_array[mp->mat_nr];
return ma ? ma->texpaintslot + ma->paint_clone_slot : NULL;
}
static Image *project_paint_face_clone_image(const ProjPaintState *ps, int tri_index)
{
const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
- Material *ma = ps->dm->mat[mp->mat_nr];
+ Material *ma = ps->mat_array[mp->mat_nr];
TexPaintSlot *slot = ma ? ma->texpaintslot + ma->paint_clone_slot : NULL;
return slot ? slot->ima : ps->clone_ima;
}
@@ -597,11 +599,11 @@ static int project_paint_PickFace(
for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
const int tri_index = GET_INT_FROM_POINTER(node->link);
- const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+ const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const float *vtri_ss[3] = {
- ps->screenCoords[ps->dm_mloop[lt->tri[0]].v],
- ps->screenCoords[ps->dm_mloop[lt->tri[1]].v],
- ps->screenCoords[ps->dm_mloop[lt->tri[2]].v],
+ ps->screenCoords[ps->mloop_eval[lt->tri[0]].v],
+ ps->screenCoords[ps->mloop_eval[lt->tri[1]].v],
+ ps->screenCoords[ps->mloop_eval[lt->tri[2]].v],
};
@@ -656,8 +658,8 @@ static bool project_paint_PickColor(
if (tri_index == -1)
return 0;
- lt = &ps->dm_mlooptri[tri_index];
- PS_LOOPTRI_ASSIGN_UV_3(lt_tri_uv, ps->dm_mloopuv, lt);
+ lt = &ps->mlooptri_eval[tri_index];
+ PS_LOOPTRI_ASSIGN_UV_3(lt_tri_uv, ps->poly_to_loop_uv, lt);
interp_v2_v2v2v2(uv, UNPACK3(lt_tri_uv), w);
@@ -813,19 +815,19 @@ static bool project_bucket_point_occluded(
const int tri_index = GET_INT_FROM_POINTER(bucketFace->link);
if (orig_face != tri_index) {
- const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+ const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const float *vtri_ss[3] = {
- ps->screenCoords[ps->dm_mloop[lt->tri[0]].v],
- ps->screenCoords[ps->dm_mloop[lt->tri[1]].v],
- ps->screenCoords[ps->dm_mloop[lt->tri[2]].v],
+ ps->screenCoords[ps->mloop_eval[lt->tri[0]].v],
+ ps->screenCoords[ps->mloop_eval[lt->tri[1]].v],
+ ps->screenCoords[ps->mloop_eval[lt->tri[2]].v],
};
float w[3];
if (do_clip) {
const float *vtri_co[3] = {
- ps->dm_mvert[ps->dm_mloop[lt->tri[0]].v].co,
- ps->dm_mvert[ps->dm_mloop[lt->tri[1]].v].co,
- ps->dm_mvert[ps->dm_mloop[lt->tri[2]].v].co,
+ ps->mvert_eval[ps->mloop_eval[lt->tri[0]].v].co,
+ ps->mvert_eval[ps->mloop_eval[lt->tri[1]].v].co,
+ ps->mvert_eval[ps->mloop_eval[lt->tri[2]].v].co,
};
isect_ret = project_paint_occlude_ptv_clip(
pixelScreenCo, UNPACK3(vtri_ss), UNPACK3(vtri_co),
@@ -1005,8 +1007,8 @@ static bool pixel_bounds_array(float (*uv)[2], rcti *bounds_px, const int ibuf_x
static void project_face_winding_init(const ProjPaintState *ps, const int tri_index)
{
/* detect the winding of faces in uv space */
- const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
- const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv, lt) };
+ const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
+ const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt) };
float winding = cross_tri_v2(lt_tri_uv[0], lt_tri_uv[1], lt_tri_uv[2]);
if (winding > 0)
@@ -1022,11 +1024,11 @@ static bool check_seam(
const int orig_face, const int orig_i1_fidx, const int orig_i2_fidx,
int *other_face, int *orig_fidx)
{
- const MLoopTri *orig_lt = &ps->dm_mlooptri[orig_face];
- const float *orig_lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv, orig_lt) };
+ const MLoopTri *orig_lt = &ps->mlooptri_eval[orig_face];
+ const float *orig_lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, orig_lt) };
/* vert indices from face vert order indices */
- const unsigned int i1 = ps->dm_mloop[orig_lt->tri[orig_i1_fidx]].v;
- const unsigned int i2 = ps->dm_mloop[orig_lt->tri[orig_i2_fidx]].v;
+ const unsigned int i1 = ps->mloop_eval[orig_lt->tri[orig_i1_fidx]].v;
+ const unsigned int i2 = ps->mloop_eval[orig_lt->tri[orig_i2_fidx]].v;
LinkNode *node;
int i1_fidx = -1, i2_fidx = -1; /* index in face */
@@ -1034,7 +1036,7 @@ static bool check_seam(
const int tri_index = GET_INT_FROM_POINTER(node->link);
if (tri_index != orig_face) {
- const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+ const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
/* could check if the 2 faces images match here,
* but then there wouldn't be a way to return the opposite face's info */
@@ -1047,7 +1049,7 @@ static bool check_seam(
/* Only need to check if 'i2_fidx' is valid because we know i1_fidx is the same vert on both faces */
if (i2_fidx != -1) {
- const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv, lt) };
+ const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt) };
Image *tpage = project_paint_face_paint_image(ps, tri_index);
Image *orig_tpage = project_paint_face_paint_image(ps, orig_face);
@@ -1351,8 +1353,8 @@ static float project_paint_uvpixel_mask(
Image *other_tpage = ps->stencil_ima;
if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
- const MLoopTri *lt_other = &ps->dm_mlooptri[tri_index];
- const float *lt_other_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv, lt_other) };
+ const MLoopTri *lt_other = &ps->mlooptri_eval[tri_index];
+ const float *lt_other_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt_other) };
/* BKE_image_acquire_ibuf - TODO - this may be slow */
unsigned char rgba_ub[4];
@@ -1385,7 +1387,7 @@ static float project_paint_uvpixel_mask(
}
if (ps->do_mask_cavity) {
- const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+ const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
float ca1, ca2, ca3, ca_mask;
ca1 = ps->cavities[lt_vtri[0]];
@@ -1400,16 +1402,16 @@ static float project_paint_uvpixel_mask(
/* calculate mask */
if (ps->do_mask_normal) {
- const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+ const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
- const MPoly *mp = &ps->dm_mpoly[lt->poly];
+ const MPoly *mp = &ps->mpoly_eval[lt->poly];
float no[3], angle_cos;
if (mp->flag & ME_SMOOTH) {
const short *no1, *no2, *no3;
- no1 = ps->dm_mvert[lt_vtri[0]].no;
- no2 = ps->dm_mvert[lt_vtri[1]].no;
- no3 = ps->dm_mvert[lt_vtri[2]].no;
+ no1 = ps->mvert_eval[lt_vtri[0]].no;
+ no2 = ps->mvert_eval[lt_vtri[1]].no;
+ no3 = ps->mvert_eval[lt_vtri[2]].no;
no[0] = w[0] * no1[0] + w[1] * no2[0] + w[2] * no3[0];
no[1] = w[0] * no1[1] + w[1] * no2[1] + w[2] * no3[1];
@@ -1421,9 +1423,9 @@ static float project_paint_uvpixel_mask(
#if 1
/* normalizing per pixel isn't optimal, we could cache or check ps->*/
normal_tri_v3(no,
- ps->dm_mvert[lt_vtri[0]].co,
- ps->dm_mvert[lt_vtri[1]].co,
- ps->dm_mvert[lt_vtri[2]].co);
+ ps->mvert_eval[lt_vtri[0]].co,
+ ps->mvert_eval[lt_vtri[1]].co,
+ ps->mvert_eval[lt_vtri[2]].co);
#else
/* don't use because some modifiers dont have normal data (subsurf for eg) */
copy_v3_v3(no, (float *)ps->dm->getTessFaceData(ps->dm, tri_index, CD_NORMAL));
@@ -1442,9 +1444,9 @@ static float project_paint_uvpixel_mask(
/* Annoying but for the perspective view we need to get the pixels location in 3D space :/ */
float viewDirPersp[3];
const float *co1, *co2, *co3;
- co1 = ps->dm_mvert[lt_vtri[0]].co;
- co2 = ps->dm_mvert[lt_vtri[1]].co;
- co3 = ps->dm_mvert[lt_vtri[2]].co;
+ co1 = ps->mvert_eval[lt_vtri[0]].co;
+ co2 = ps->mvert_eval[lt_vtri[1]].co;
+ co3 = ps->mvert_eval[lt_vtri[2]].co;
/* Get the direction from the viewPoint to the pixel and normalize */
viewDirPersp[0] = (ps->viewPos[0] - (w[0] * co1[0] + w[1] * co2[0] + w[2] * co3[0]));
@@ -1613,13 +1615,13 @@ static ProjPixel *project_paint_uvpixel_init(
/* done with view3d_project_float inline */
if (ps->tool == PAINT_TOOL_CLONE) {
- if (ps->dm_mloopuv_clone) {
+ if (ps->poly_to_loop_uv_clone) {
ImBuf *ibuf_other;
Image *other_tpage = project_paint_face_clone_image(ps, tri_index);
if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) {
- const MLoopTri *lt_other = &ps->dm_mlooptri[tri_index];
- const float *lt_other_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv_clone, lt_other) };
+ const MLoopTri *lt_other = &ps->mlooptri_eval[tri_index];
+ const float *lt_other_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv_clone, lt_other) };
/* BKE_image_acquire_ibuf - TODO - this may be slow */
@@ -2510,9 +2512,9 @@ static void project_paint_face_init(
ps->projImages + image_index
};
- const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+ const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
- const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->dm_mloopuv, lt) };
+ const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt) };
/* UV/pixel seeking data */
int x; /* Image X-Pixel */
@@ -2546,9 +2548,9 @@ static void project_paint_face_init(
const bool do_backfacecull = ps->do_backfacecull;
const bool do_clip = ps->rv3d ? ps->rv3d->rflag & RV3D_CLIPPING : 0;
- vCo[0] = ps->dm_mvert[lt_vtri[0]].co;
- vCo[1] = ps->dm_mvert[lt_vtri[1]].co;
- vCo[2] = ps->dm_mvert[lt_vtri[2]].co;
+ vCo[0] = ps->mvert_eval[lt_vtri[0]].co;
+ vCo[1] = ps->mvert_eval[lt_vtri[1]].co;
+ vCo[2] = ps->mvert_eval[lt_vtri[2]].co;
/* Use lt_uv_pxoffset instead of lt_tri_uv so we can offset the UV half a pixel
@@ -2632,9 +2634,9 @@ static void project_paint_face_init(
if (do_clip || do_3d_mapping) {
interp_v3_v3v3v3(
wco,
- ps->dm_mvert[lt_vtri[0]].co,
- ps->dm_mvert[lt_vtri[1]].co,
- ps->dm_mvert[lt_vtri[2]].co,
+ ps->mvert_eval[lt_vtri[0]].co,
+ ps->mvert_eval[lt_vtri[1]].co,
+ ps->mvert_eval[lt_vtri[2]].co,
w);
if (do_clip && ED_view3d_clipping_test(ps->rv3d, wco, true)) {
continue; /* Watch out that no code below this needs to run */
@@ -2814,7 +2816,7 @@ static void project_paint_face_init(
!project_bucket_point_occluded(ps, bucketFaceNodes, tri_index, pixelScreenCo))
{
/* Only bother calculating the weights if we intersect */
- if (ps->do_mask_normal || ps->dm_mloopuv_clone) {
+ if (ps->do_mask_normal || ps->poly_to_loop_uv_clone) {
const float uv_fac = fac1 + (fac * (fac2 - fac1));
#if 0
/* get the UV on the line since we want to copy the pixels from there for bleeding */
@@ -3067,24 +3069,6 @@ static void project_paint_delayed_face_init(ProjPaintState *ps, const MLoopTri *
#endif
}
-/**
- * \note when using subsurf or multires, some arrays are thrown away, we need to keep a copy
- */
-static void proj_paint_state_non_cddm_init(ProjPaintState *ps)
-{
- if (ps->dm->type != DM_TYPE_CDDM) {
- ps->dm_mvert = MEM_dupallocN(ps->dm_mvert);
- ps->dm_mpoly = MEM_dupallocN(ps->dm_mpoly);
- ps->dm_mloop = MEM_dupallocN(ps->dm_mloop);
- /* looks like these are ok for now.*/
-#if 0
- ps->dm_mloopuv = MEM_dupallocN(ps->dm_mloopuv);
- ps->dm_mloopuv_clone = MEM_dupallocN(ps->dm_mloopuv_clone);
- ps->dm_mloopuv_stencil = MEM_dupallocN(ps->dm_mloopuv_stencil);
-#endif
- }
-}
-
static void proj_paint_state_viewport_init(
ProjPaintState *ps, const Depsgraph *depsgraph, const char symmetry_flag)
{
@@ -3204,11 +3188,11 @@ static void proj_paint_state_screen_coords_init(ProjPaintState *ps, const int di
INIT_MINMAX2(ps->screenMin, ps->screenMax);
- ps->screenCoords = MEM_mallocN(sizeof(float) * ps->dm_totvert * 4, "ProjectPaint ScreenVerts");
+ ps->screenCoords = MEM_mallocN(sizeof(float) * ps->totvert_eval * 4, "ProjectPaint ScreenVerts");
projScreenCo = *ps->screenCoords;
if (ps->is_ortho) {
- for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++, projScreenCo += 4) {
+ for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++, projScreenCo += 4) {
mul_v3_m4v3(projScreenCo, ps->projectMat, mv->co);
/* screen space, not clamped */
@@ -3218,7 +3202,7 @@ static void proj_paint_state_screen_coords_init(ProjPaintState *ps, const int di
}
}
else {
- for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++, projScreenCo += 4) {
+ for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++, projScreenCo += 4) {
copy_v3_v3(projScreenCo, mv->co);
projScreenCo[3] = 1.0f;
@@ -3279,21 +3263,21 @@ static void proj_paint_state_cavity_init(ProjPaintState *ps)
int a;
if (ps->do_mask_cavity) {
- int *counter = MEM_callocN(sizeof(int) * ps->dm_totvert, "counter");
- float (*edges)[3] = MEM_callocN(sizeof(float) * 3 * ps->dm_totvert, "edges");
- ps->cavities = MEM_mallocN(sizeof(float) * ps->dm_totvert, "ProjectPaint Cavities");
+ int *counter = MEM_callocN(sizeof(int) * ps->totvert_eval, "counter");
+ float (*edges)[3] = MEM_callocN(sizeof(float) * 3 * ps->totvert_eval, "edges");
+ ps->cavities = MEM_mallocN(sizeof(float) * ps->totvert_eval, "ProjectPaint Cavities");
cavities = ps->cavities;
- for (a = 0, me = ps->dm_medge; a < ps->dm_totedge; a++, me++) {
+ for (a = 0, me = ps->medge_eval; a < ps->totedge_eval; a++, me++) {
float e[3];
- sub_v3_v3v3(e, ps->dm_mvert[me->v1].co, ps->dm_mvert[me->v2].co);
+ sub_v3_v3v3(e, ps->mvert_eval[me->v1].co, ps->mvert_eval[me->v2].co);
normalize_v3(e);
add_v3_v3(edges[me->v2], e);
counter[me->v2]++;
sub_v3_v3(edges[me->v1], e);
counter[me->v1]++;
}
- for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++) {
+ for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++) {
if (counter[a] > 0) {
float no[3];
mul_v3_fl(edges[a], 1.0f / counter[a]);
@@ -3314,10 +3298,10 @@ static void proj_paint_state_cavity_init(ProjPaintState *ps)
static void proj_paint_state_seam_bleed_init(ProjPaintState *ps)
{
if (ps->seam_bleed_px > 0.0f) {
- ps->vertFaces = MEM_callocN(sizeof(LinkNode *) * ps->dm_totvert, "paint-vertFaces");
- ps->faceSeamFlags = MEM_callocN(sizeof(char) * ps->dm_totlooptri, "paint-faceSeamFlags");
- ps->faceWindingFlags = MEM_callocN(sizeof(char) * ps->dm_totlooptri, "paint-faceWindindFlags");
- ps->faceSeamUVs = MEM_mallocN(sizeof(float[3][2]) * ps->dm_totlooptri, "paint-faceSeamUVs");
+ ps->vertFaces = MEM_callocN(sizeof(LinkNode *) * ps->totvert_eval, "paint-vertFaces");
+ ps->faceSeamFlags = MEM_callocN(sizeof(char) * ps->totlooptri_eval, "paint-faceSeamFlags");
+ ps->faceWindingFlags = MEM_callocN(sizeof(char) * ps->totlooptri_eval, "paint-faceWindindFlags");
+ ps->faceSeamUVs = MEM_mallocN(sizeof(float[3][2]) * ps->totlooptri_eval, "paint-faceSeamUVs");
}
}
#endif
@@ -3361,9 +3345,9 @@ static void proj_paint_state_vert_flags_init(ProjPaintState *ps)
float no[3];
int a;
- ps->vertFlags = MEM_callocN(sizeof(char) * ps->dm_totvert, "paint-vertFlags");
+ ps->vertFlags = MEM_callocN(sizeof(char) * ps->totvert_eval, "paint-vertFlags");
- for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++) {
+ for (a = 0, mv = ps->mvert_eval; a < ps->totvert_eval; a++, mv++) {
normal_short_to_float_v3(no, mv->no);
if (UNLIKELY(ps->is_flip_object)) {
negate_v3(no);
@@ -3408,58 +3392,63 @@ static void project_paint_bleed_add_face_user(
}
#endif
-/* Return true if DM can be painted on, false otherwise */
-static bool proj_paint_state_dm_init(const bContext *C, ProjPaintState *ps)
+/* Return true if evaluated mesh can be painted on, false otherwise */
+static bool proj_paint_state_mesh_eval_init(const bContext *C, ProjPaintState *ps)
{
Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Scene *sce = ps->scene;
+ Object *ob = ps->ob;
/* Workaround for subsurf selection, try the display mesh first */
+ /* XXX Don't think this is easily doable with new system, and not sure why that was needed in the first place :/ */
+#if 0
if (ps->source == PROJ_SRC_IMAGE_CAM) {
/* using render mesh, assume only camera was rendered from */
- ps->dm = mesh_create_derived_render(depsgraph, ps->scene, ps->ob, ps->scene->customdata_mask | CD_MASK_MTFACE);
+ ps->dm = mesh_create_derived_render(
+ depsgraph, ps->scene, ps->ob, ps->scene->customdata_mask | CD_MASK_MLOOPUV | CD_MASK_MTFACE);
ps->dm_release = true;
}
- else if (ps->ob->derivedFinal &&
- CustomData_has_layer(&ps->ob->derivedFinal->loopData, CD_MLOOPUV) &&
- (ps->do_face_sel == false || CustomData_has_layer(&ps->ob->derivedFinal->polyData, CD_ORIGINDEX)))
- {
- ps->dm = ps->ob->derivedFinal;
- ps->dm_release = false;
- }
else {
ps->dm = mesh_get_derived_final(
depsgraph, ps->scene, ps->ob,
- ps->scene->customdata_mask | CD_MASK_MTFACE | (ps->do_face_sel ? CD_ORIGINDEX : 0));
- ps->dm_release = true;
+ ps->scene->customdata_mask | CD_MASK_MLOOPUV | CD_MASK_MTFACE | (ps->do_face_sel ? CD_MASK_ORIGINDEX : 0));
+ ps->dm_release = false;
}
-
- if (!CustomData_has_layer(&ps->dm->loopData, CD_MLOOPUV)) {
-
- if (ps->dm_release)
- ps->dm->release(ps->dm);
-
- ps->dm = NULL;
+#endif
+ ps->me_eval = mesh_get_eval_final(
+ depsgraph, sce, ob,
+ sce->customdata_mask | CD_MASK_MLOOPUV | CD_MASK_MTFACE | (ps->do_face_sel ? CD_MASK_ORIGINDEX : 0));
+ if (!CustomData_has_layer(&ps->me_eval->ldata, CD_MLOOPUV)) {
+ ps->me_eval = NULL;
return false;
}
- DM_update_materials(ps->dm, ps->ob);
-
- ps->dm_mvert = ps->dm->getVertArray(ps->dm);
-
- if (ps->do_mask_cavity)
- ps->dm_medge = ps->dm->getEdgeArray(ps->dm);
+ /* Build final material array, we use this a lot here. */
+ const int totmat = ob->totcol + 1; /* materials start from 1, default material is 0 */
+ ps->mat_array = MEM_malloc_arrayN(totmat, sizeof(*ps->mat_array), __func__);
+ /* We leave last material as empty - rationale here is being able to index
+ * the materials by using the mf->mat_nr directly and leaving the last
+ * material as NULL in case no materials exist on mesh, so indexing will not fail. */
+ for (int i = 0; i < totmat - 1; i++) {
+ ps->mat_array[i] = give_current_material(ob, i + 1);
+ }
+ ps->mat_array[totmat - 1] = NULL;
- ps->dm_mloop = ps->dm->getLoopArray(ps->dm);
- ps->dm_mpoly = ps->dm->getPolyArray(ps->dm);
+ ps->mvert_eval = ps->me_eval->mvert;
+ if (ps->do_mask_cavity) {
+ ps->medge_eval = ps->me_eval->medge;
+ }
+ ps->mloop_eval = ps->me_eval->mloop;
+ ps->mpoly_eval = ps->me_eval->mpoly;
- ps->dm_mlooptri = ps->dm->getLoopTriArray(ps->dm);
+ ps->totvert_eval = ps->me_eval->totvert;
+ ps->totedge_eval = ps->me_eval->totedge;
+ ps->totpoly_eval = ps->me_eval->totpoly;
- ps->dm_totvert = ps->dm->getNumVerts(ps->dm);
- ps->dm_totedge = ps->dm->getNumEdges(ps->dm);
- ps->dm_totpoly = ps->dm->getNumPolys(ps->dm);
- ps->dm_totlooptri = ps->dm->getNumLoopTri(ps->dm);
+ ps->mlooptri_eval = BKE_mesh_runtime_looptri_ensure(ps->me_eval);
+ ps->totlooptri_eval = ps->me_eval->runtime.looptris.len;
- ps->dm_mloopuv = MEM_mallocN(ps->dm_totpoly * sizeof(MLoopUV *), "proj_paint_mtfaces");
+ ps->poly_to_loop_uv = MEM_mallocN(ps->totpoly_eval * sizeof(MLoopUV *), "proj_paint_mtfaces");
return true;
}
@@ -3480,14 +3469,14 @@ static void proj_paint_layer_clone_init(
if (ps->do_layer_clone) {
const int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->ldata, CD_MLOOPUV);
- ps->dm_mloopuv_clone = MEM_mallocN(ps->dm_totpoly * sizeof(MLoopUV *), "proj_paint_mtfaces");
+ ps->poly_to_loop_uv_clone = MEM_mallocN(ps->totpoly_eval * sizeof(MLoopUV *), "proj_paint_mtfaces");
if (layer_num != -1)
- mloopuv_clone_base = CustomData_get_layer_n(&ps->dm->loopData, CD_MLOOPUV, layer_num);
+ mloopuv_clone_base = CustomData_get_layer_n(&ps->me_eval->ldata, CD_MLOOPUV, layer_num);
if (mloopuv_clone_base == NULL) {
/* get active instead */
- mloopuv_clone_base = CustomData_get_layer(&ps->dm->loopData, CD_MLOOPUV);
+ mloopuv_clone_base = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
}
}
@@ -3517,17 +3506,17 @@ static bool project_paint_clone_face_skip(
if (lc->slot_clone != lc->slot_last_clone) {
if (!slot->uvname ||
!(lc->mloopuv_clone_base = CustomData_get_layer_named(
- &ps->dm->loopData, CD_MLOOPUV,
+ &ps->me_eval->ldata, CD_MLOOPUV,
lc->slot_clone->uvname)))
{
- lc->mloopuv_clone_base = CustomData_get_layer(&ps->dm->loopData, CD_MLOOPUV);
+ lc->mloopuv_clone_base = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
}
lc->slot_last_clone = lc->slot_clone;
}
}
/* will set multiple times for 4+ sided poly */
- ps->dm_mloopuv_clone[ps->dm_mlooptri[tri_index].poly] = lc->mloopuv_clone_base;
+ ps->poly_to_loop_uv_clone[ps->mlooptri_eval[tri_index].poly] = lc->mloopuv_clone_base;
}
return false;
}
@@ -3544,7 +3533,7 @@ static void proj_paint_face_lookup_init(
{
memset(face_lookup, 0, sizeof(*face_lookup));
if (ps->do_face_sel) {
- face_lookup->index_mp_to_orig = ps->dm->getPolyDataArray(ps->dm, CD_ORIGINDEX);
+ face_lookup->index_mp_to_orig = CustomData_get_layer(&ps->me_eval->pdata, CD_ORIGINDEX);
face_lookup->mpoly_orig = ((Mesh *)ps->ob->data)->mpoly;
}
}
@@ -3565,7 +3554,7 @@ static bool project_paint_check_face_sel(
mp = &face_lookup->mpoly_orig[orig_index];
}
else {
- mp = &ps->dm_mpoly[lt->poly];
+ mp = &ps->mpoly_eval[lt->poly];
}
return ((mp->flag & ME_FACE_SEL) != 0);
@@ -3679,7 +3668,7 @@ static void project_paint_prepare_all_faces(
int image_index = -1, tri_index;
int prev_poly = -1;
- for (tri_index = 0, lt = ps->dm_mlooptri; tri_index < ps->dm_totlooptri; tri_index++, lt++) {
+ for (tri_index = 0, lt = ps->mlooptri_eval; tri_index < ps->totlooptri_eval; tri_index++, lt++) {
bool is_face_sel;
#ifndef PROJ_DEBUG_NOSEAMBLEED
@@ -3692,13 +3681,13 @@ static void project_paint_prepare_all_faces(
slot = project_paint_face_paint_slot(ps, tri_index);
/* all faces should have a valid slot, reassert here */
if (slot == NULL) {
- mloopuv_base = CustomData_get_layer(&ps->dm->loopData, CD_MLOOPUV);
+ mloopuv_base = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
tpage = ps->canvas_ima;
}
else {
if (slot != slot_last) {
- if (!slot->uvname || !(mloopuv_base = CustomData_get_layer_named(&ps->dm->loopData, CD_MLOOPUV, slot->uvname)))
- mloopuv_base = CustomData_get_layer(&ps->dm->loopData, CD_MLOOPUV);
+ if (!slot->uvname || !(mloopuv_base = CustomData_get_layer_named(&ps->me_eval->ldata, CD_MLOOPUV, slot->uvname)))
+ mloopuv_base = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
slot_last = slot;
}
@@ -3706,7 +3695,7 @@ static void project_paint_prepare_all_faces(
if (slot->ima == ps->stencil_ima) {
/* While this shouldn't be used, face-winding reads all polys.
* It's less trouble to set all faces to valid UV's, avoiding NULL checks all over. */
- ps->dm_mloopuv[lt->poly] = mloopuv_base;
+ ps->poly_to_loop_uv[lt->poly] = mloopuv_base;
continue;
}
@@ -3717,7 +3706,7 @@ static void project_paint_prepare_all_faces(
tpage = ps->stencil_ima;
}
- ps->dm_mloopuv[lt->poly] = mloopuv_base;
+ ps->poly_to_loop_uv[lt->poly] = mloopuv_base;
if (project_paint_clone_face_skip(ps, layer_clone, slot, tri_index)) {
continue;
@@ -3748,11 +3737,11 @@ static void project_paint_prepare_all_faces(
if (prev_poly != lt->poly) {
int iloop;
bool culled = true;
- const MPoly *poly = ps->dm_mpoly + lt->poly;
+ const MPoly *poly = ps->mpoly_eval + lt->poly;
int poly_loops = poly->totloop;
prev_poly = lt->poly;
for (iloop = 0; iloop < poly_loops; iloop++) {
- if (!(ps->vertFlags[ps->dm_mloop[poly->loopstart + iloop].v] & PROJ_VERT_CULL)) {
+ if (!(ps->vertFlags[ps->mloop_eval[poly->loopstart + iloop].v] & PROJ_VERT_CULL)) {
culled = false;
break;
}
@@ -3831,7 +3820,7 @@ static void project_paint_begin(
/* paint onto the derived mesh */
if (ps->is_shared_user == false) {
- if (!proj_paint_state_dm_init(C, ps)) {
+ if (!proj_paint_state_mesh_eval_init(C, ps)) {
return;
}
}
@@ -3840,24 +3829,22 @@ static void project_paint_begin(
proj_paint_layer_clone_init(ps, &layer_clone);
if (ps->do_layer_stencil || ps->do_stencil_brush) {
- //int layer_num = CustomData_get_stencil_layer(&ps->dm->loopData, CD_MLOOPUV);
+ //int layer_num = CustomData_get_stencil_layer(&ps->me_eval->ldata, CD_MLOOPUV);
int layer_num = CustomData_get_stencil_layer(&((Mesh *)ps->ob->data)->ldata, CD_MLOOPUV);
if (layer_num != -1)
- ps->dm_mloopuv_stencil = CustomData_get_layer_n(&ps->dm->loopData, CD_MLOOPUV, layer_num);
+ ps->mloopuv_stencil_eval = CustomData_get_layer_n(&ps->me_eval->ldata, CD_MLOOPUV, layer_num);
- if (ps->dm_mloopuv_stencil == NULL) {
+ if (ps->mloopuv_stencil_eval == NULL) {
/* get active instead */
- ps->dm_mloopuv_stencil = CustomData_get_layer(&ps->dm->loopData, CD_MLOOPUV);
+ ps->mloopuv_stencil_eval = CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV);
}
if (ps->do_stencil_brush)
- mloopuv_base = ps->dm_mloopuv_stencil;
+ mloopuv_base = ps->mloopuv_stencil_eval;
}
/* when using subsurf or multires, mface arrays are thrown away, we need to keep a copy */
if (ps->is_shared_user == false) {
- proj_paint_state_non_cddm_init(ps);
-
proj_paint_state_cavity_init(ps);
}
@@ -3947,14 +3934,17 @@ static void project_paint_end(ProjPaintState *ps)
MEM_freeN(ps->bucketFlags);
if (ps->is_shared_user == false) {
+ if (ps->mat_array != NULL) {
+ MEM_freeN(ps->mat_array);
+ }
/* must be set for non-shared */
- BLI_assert(ps->dm_mloopuv || ps->is_shared_user);
- if (ps->dm_mloopuv)
- MEM_freeN((void *)ps->dm_mloopuv);
+ BLI_assert(ps->poly_to_loop_uv || ps->is_shared_user);
+ if (ps->poly_to_loop_uv)
+ MEM_freeN((void *)ps->poly_to_loop_uv);
if (ps->do_layer_clone)
- MEM_freeN((void *)ps->dm_mloopuv_clone);
+ MEM_freeN((void *)ps->poly_to_loop_uv_clone);
if (ps->thread_tot > 1) {
BLI_spin_end(ps->tile_lock);
MEM_freeN((void *)ps->tile_lock);
@@ -3974,22 +3964,6 @@ static void project_paint_end(ProjPaintState *ps)
if (ps->do_mask_cavity) {
MEM_freeN(ps->cavities);
}
-
- /* copy for subsurf/multires, so throw away */
- if (ps->dm->type != DM_TYPE_CDDM) {
- if (ps->dm_mvert) MEM_freeN((void *)ps->dm_mvert);
- if (ps->dm_mpoly) MEM_freeN((void *)ps->dm_mpoly);
- if (ps->dm_mloop) MEM_freeN((void *)ps->dm_mloop);
- /* looks like these don't need copying */
-#if 0
- if (ps->dm_mloopuv) MEM_freeN(ps->dm_mloopuv);
- if (ps->dm_mloopuv_clone) MEM_freeN(ps->dm_mloopuv_clone);
- if (ps->dm_mloopuv_stencil) MEM_freeN(ps->dm_mloopuv_stencil);
-#endif
- }
-
- if (ps->dm_release)
- ps->dm->release(ps->dm);
}
if (ps->blurkernel) {
@@ -4864,7 +4838,7 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po
struct ImagePool *pool;
if (!project_bucket_iter_init(ps, pos)) {
- return 0;
+ return touch_any;
}
if (ps->thread_tot > 1)
@@ -4930,16 +4904,16 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po
tri_index = project_paint_PickFace(ps, pos, w);
if (tri_index != -1) {
- const MLoopTri *lt = &ps->dm_mlooptri[tri_index];
+ const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
const int lt_vtri[3] = { PS_LOOPTRI_AS_VERT_INDEX_3(ps, lt) };
float world[3];
UnifiedPaintSettings *ups = &ps->scene->toolsettings->unified_paint_settings;
interp_v3_v3v3v3(
world,
- ps->dm_mvert[lt_vtri[0]].co,
- ps->dm_mvert[lt_vtri[1]].co,
- ps->dm_mvert[lt_vtri[2]].co,
+ ps->mvert_eval[lt_vtri[0]].co,
+ ps->mvert_eval[lt_vtri[1]].co,
+ ps->mvert_eval[lt_vtri[2]].co,
w);
ups->average_stroke_counter++;
@@ -5228,13 +5202,11 @@ void *paint_proj_new_stroke(bContext *C, Object *ob, const float mouse[2], int m
}
project_paint_begin(C, ps, is_multi_view, symmetry_flag_views[i]);
-
- paint_proj_begin_clone(ps, mouse);
-
- if (ps->dm == NULL) {
+ if (ps->me_eval == NULL) {
goto fail;
- return NULL;
}
+
+ paint_proj_begin_clone(ps, mouse);
}
paint_brush_init_tex(ps_handle->brush);
@@ -5382,8 +5354,9 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
/* allocate and initialize spatial data structures */
project_paint_begin(C, &ps, false, 0);
- if (ps.dm == NULL) {
+ if (ps.me_eval == NULL) {
BKE_brush_size_set(scene, ps.brush, orig_brush_size);
+ BKE_report(op->reports, RPT_ERROR, "Could not get valid evaluated mesh");
return OPERATOR_CANCELLED;
}
else {
@@ -5791,6 +5764,7 @@ void PAINT_OT_add_texture_paint_slot(wmOperatorType *ot)
static int add_simple_uvs_exec(bContext *C, wmOperator *UNUSED(op))
{
/* no checks here, poll function does them for us */
+ Main *bmain = CTX_data_main(C);
Object *ob = CTX_data_active_object(C);
Scene *scene = CTX_data_scene(C);
Mesh *me = ob->data;
@@ -5815,7 +5789,7 @@ static int add_simple_uvs_exec(bContext *C, wmOperator *UNUSED(op))
/* set the margin really quickly before the packing operation*/
scene->toolsettings->uvcalc_margin = 0.001f;
ED_uvedit_pack_islands(scene, ob, bm, false, false, true);
- BM_mesh_bm_to_me(bm, me, (&(struct BMeshToMeshParams){0}));
+ BM_mesh_bm_to_me(bmain, bm, me, (&(struct BMeshToMeshParams){0}));
BM_mesh_free(bm);
if (synch_selection)
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index b63f9461401..a7aa19807dd 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -38,6 +38,8 @@
#include "BLI_rand.h"
#include "BLI_listbase.h"
+#include "PIL_time.h"
+
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_brush_types.h"
@@ -86,6 +88,7 @@ typedef struct PaintStroke {
void *mode_data;
void *stroke_cursor;
wmTimer *timer;
+ struct RNG *rng;
/* Cached values */
ViewContext vc;
@@ -403,17 +406,24 @@ static bool paint_brush_update(bContext *C,
}
}
+ if ((do_random || do_random_mask) && stroke->rng == NULL) {
+ /* Lazy initialization. */
+ uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
+ rng_seed ^= (uint)GET_INT_FROM_POINTER(brush);
+ stroke->rng = BLI_rng_new(rng_seed);
+ }
+
if (do_random) {
if (brush->mtex.brush_angle_mode & MTEX_ANGLE_RANDOM) {
ups->brush_rotation += -brush->mtex.random_angle / 2.0f +
- brush->mtex.random_angle * BLI_frand();
+ brush->mtex.random_angle * BLI_rng_get_float(stroke->rng);
}
}
if (do_random_mask) {
if (brush->mask_mtex.brush_angle_mode & MTEX_ANGLE_RANDOM) {
ups->brush_rotation_sec += -brush->mask_mtex.random_angle / 2.0f +
- brush->mask_mtex.random_angle * BLI_frand();
+ brush->mask_mtex.random_angle * BLI_rng_get_float(stroke->rng);
}
}
@@ -785,6 +795,10 @@ static void stroke_done(struct bContext *C, struct wmOperator *op)
stroke->timer);
}
+ if (stroke->rng) {
+ BLI_rng_free(stroke->rng);
+ }
+
if (stroke->stroke_cursor)
WM_paint_cursor_end(CTX_wm_manager(C), stroke->stroke_cursor);
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index ac6bfe019a1..85a1f11be4b 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -967,15 +967,20 @@ static void do_weight_paint_vertex(
/* Toggle operator for turning vertex paint mode on or off (copied from sculpt.c) */
-static void vertex_paint_init_session(Depsgraph *depsgraph, Scene *scene, Object *ob)
+static void vertex_paint_init_session(Depsgraph *depsgraph, Scene *scene, Object *ob, eObjectMode object_mode)
{
/* Create persistent sculpt mode data */
BKE_sculpt_toolsettings_data_ensure(scene);
- if (ob->sculpt == NULL) {
- ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session");
- BKE_sculpt_update_mesh_elements(depsgraph, scene, scene->toolsettings->sculpt, ob, false, false);
- }
+ BLI_assert(ob->sculpt == NULL);
+ ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session");
+ ob->sculpt->mode_type = object_mode;
+ BKE_sculpt_update_mesh_elements(depsgraph, scene, scene->toolsettings->sculpt, ob, false, false);
+}
+
+static void vertex_paint_init_stroke(Depsgraph *depsgraph, Scene *scene, Object *ob)
+{
+ BKE_sculpt_update_mesh_elements(depsgraph, scene, scene->toolsettings->sculpt, ob, false, false);
}
static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob)
@@ -986,12 +991,12 @@ static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob)
if (ob->mode == OB_MODE_VERTEX_PAINT) {
gmap = &ob->sculpt->mode.vpaint.gmap;
brush = BKE_paint_brush(&ts->vpaint->paint);
- ob->sculpt->mode_type = OB_MODE_VERTEX_PAINT;
+ BLI_assert(ob->sculpt->mode_type == OB_MODE_VERTEX_PAINT);
}
else if (ob->mode == OB_MODE_WEIGHT_PAINT) {
gmap = &ob->sculpt->mode.wpaint.gmap;
brush = BKE_paint_brush(&ts->wpaint->paint);
- ob->sculpt->mode_type = OB_MODE_WEIGHT_PAINT;
+ BLI_assert(ob->sculpt->mode_type == OB_MODE_WEIGHT_PAINT);
}
else {
ob->sculpt->mode_type = 0;
@@ -1113,7 +1118,7 @@ static void ed_vwpaintmode_enter_generic(
BKE_sculptsession_free(ob);
}
- vertex_paint_init_session(depsgraph, scene, ob);
+ vertex_paint_init_session(depsgraph, scene, ob, mode_flag);
/* Flush object mode. */
DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
@@ -1556,7 +1561,7 @@ static bool wpaint_stroke_test_start(bContext *C, wmOperator *op, const float mo
}
/* If not previously created, create vertex/weight paint mode session data */
- vertex_paint_init_session(depsgraph, scene, ob);
+ vertex_paint_init_stroke(depsgraph, scene, ob);
vwpaint_update_cache_invariants(C, vp, ss, op, mouse);
vertex_paint_init_session_data(ts, ob);
@@ -2545,7 +2550,7 @@ static bool vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const f
}
/* If not previously created, create vertex/weight paint mode session data */
- vertex_paint_init_session(depsgraph, scene, ob);
+ vertex_paint_init_stroke(depsgraph, scene, ob);
vwpaint_update_cache_invariants(C, vp, ss, op, mouse);
vertex_paint_init_session_data(ts, ob);
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
index 7c2977a0788..01c62704db3 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
@@ -51,6 +51,7 @@
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_mesh.h"
+#include "BKE_mesh_iterators.h"
#include "BKE_mesh_mapping.h"
#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
@@ -534,21 +535,21 @@ void PAINT_OT_weight_set(wmOperatorType *ot)
* \{ */
/* *** VGroups Gradient *** */
-typedef struct DMGradient_vertStore {
+typedef struct WPGradient_vertStore {
float sco[2];
float weight_orig;
enum {
VGRAD_STORE_NOP = 0,
VGRAD_STORE_DW_EXIST = (1 << 0)
} flag;
-} DMGradient_vertStore;
+} WPGradient_vertStore;
-typedef struct DMGradient_vertStoreBase {
+typedef struct WPGradient_vertStoreBase {
struct WPaintPrev wpp;
- DMGradient_vertStore elem[0];
-} DMGradient_vertStoreBase;
+ WPGradient_vertStore elem[0];
+} WPGradient_vertStoreBase;
-typedef struct DMGradient_userData {
+typedef struct WPGradient_userData {
struct ARegion *ar;
Scene *scene;
Mesh *me;
@@ -558,7 +559,7 @@ typedef struct DMGradient_userData {
float sco_line_div; /* store (1.0f / len_v2v2(sco_start, sco_end)) */
int def_nr;
bool is_init;
- DMGradient_vertStoreBase *vert_cache;
+ WPGradient_vertStoreBase *vert_cache;
/* only for init */
BLI_bitmap *vert_visit;
@@ -566,12 +567,12 @@ typedef struct DMGradient_userData {
short use_select;
short type;
float weightpaint;
-} DMGradient_userData;
+} WPGradient_userData;
-static void gradientVert_update(DMGradient_userData *grad_data, int index)
+static void gradientVert_update(WPGradient_userData *grad_data, int index)
{
Mesh *me = grad_data->me;
- DMGradient_vertStore *vs = &grad_data->vert_cache->elem[index];
+ WPGradient_vertStore *vs = &grad_data->vert_cache->elem[index];
float alpha;
if (grad_data->type == WPAINT_GRADIENT_TYPE_LINEAR) {
@@ -619,10 +620,10 @@ static void gradientVertUpdate__mapFunc(
void *userData, int index, const float UNUSED(co[3]),
const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
{
- DMGradient_userData *grad_data = userData;
+ WPGradient_userData *grad_data = userData;
Mesh *me = grad_data->me;
if ((grad_data->use_select == false) || (me->mvert[index].flag & SELECT)) {
- DMGradient_vertStore *vs = &grad_data->vert_cache->elem[index];
+ WPGradient_vertStore *vs = &grad_data->vert_cache->elem[index];
if (vs->sco[0] != FLT_MAX) {
gradientVert_update(grad_data, index);
}
@@ -633,7 +634,7 @@ static void gradientVertInit__mapFunc(
void *userData, int index, const float co[3],
const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
{
- DMGradient_userData *grad_data = userData;
+ WPGradient_userData *grad_data = userData;
Mesh *me = grad_data->me;
if ((grad_data->use_select == false) || (me->mvert[index].flag & SELECT)) {
@@ -642,7 +643,7 @@ static void gradientVertInit__mapFunc(
* updating the mesh may move them about (entering feedback loop) */
if (BLI_BITMAP_TEST(grad_data->vert_visit, index) == 0) {
- DMGradient_vertStore *vs = &grad_data->vert_cache->elem[index];
+ WPGradient_vertStore *vs = &grad_data->vert_cache->elem[index];
if (ED_view3d_project_float_object(grad_data->ar,
co, vs->sco,
V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
@@ -675,7 +676,7 @@ static void gradientVertInit__mapFunc(
static int paint_weight_gradient_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
wmGesture *gesture = op->customdata;
- DMGradient_vertStoreBase *vert_cache = gesture->userdata;
+ WPGradient_vertStoreBase *vert_cache = gesture->userdata;
int ret = WM_gesture_straightline_modal(C, op, event);
if (ret & OPERATOR_RUNNING_MODAL) {
@@ -711,7 +712,7 @@ static int paint_weight_gradient_modal(bContext *C, wmOperator *op, const wmEven
static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
{
wmGesture *gesture = op->customdata;
- DMGradient_vertStoreBase *vert_cache;
+ WPGradient_vertStoreBase *vert_cache;
struct ARegion *ar = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
@@ -726,20 +727,18 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
Depsgraph *depsgraph = CTX_data_depsgraph(C);
- DerivedMesh *dm = mesh_get_derived_final(depsgraph, scene, ob, scene->customdata_mask);
-
- DMGradient_userData data = {NULL};
+ WPGradient_userData data = {NULL};
if (is_interactive) {
if (gesture->userdata == NULL) {
gesture->userdata = MEM_mallocN(
- sizeof(DMGradient_vertStoreBase) +
- (sizeof(DMGradient_vertStore) * me->totvert),
+ sizeof(WPGradient_vertStoreBase) +
+ (sizeof(WPGradient_vertStore) * me->totvert),
__func__);
gesture->userdata_free = false;
data.is_init = true;
- wpaint_prev_create(&((DMGradient_vertStoreBase *)gesture->userdata)->wpp, me->dvert, me->totvert);
+ wpaint_prev_create(&((WPGradient_vertStoreBase *)gesture->userdata)->wpp, me->dvert, me->totvert);
/* on init only, convert face -> vert sel */
if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
@@ -756,8 +755,8 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
data.is_init = true;
vert_cache = MEM_mallocN(
- sizeof(DMGradient_vertStoreBase) +
- (sizeof(DMGradient_vertStore) * me->totvert),
+ sizeof(WPGradient_vertStoreBase) +
+ (sizeof(WPGradient_vertStore) * me->totvert),
__func__);
}
@@ -786,16 +785,17 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
ED_view3d_init_mats_rv3d(ob, ar->regiondata);
+ Mesh *me_eval = mesh_get_eval_final(depsgraph, scene, ob, scene->customdata_mask | CD_MASK_ORIGINDEX);
if (data.is_init) {
data.vert_visit = BLI_BITMAP_NEW(me->totvert, __func__);
- dm->foreachMappedVert(dm, gradientVertInit__mapFunc, &data, DM_FOREACH_NOP);
+ BKE_mesh_foreach_mapped_vert(me_eval, gradientVertInit__mapFunc, &data, MESH_FOREACH_NOP);
MEM_freeN(data.vert_visit);
data.vert_visit = NULL;
}
else {
- dm->foreachMappedVert(dm, gradientVertUpdate__mapFunc, &data, DM_FOREACH_NOP);
+ BKE_mesh_foreach_mapped_vert(me_eval, gradientVertUpdate__mapFunc, &data, MESH_FOREACH_NOP);
}
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 1c76f20d45c..414b9f2062f 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -4808,7 +4808,7 @@ static void sculpt_brush_init_tex(const Scene *scene, Sculpt *sd, SculptSession
sculpt_update_tex(scene, sd, ss);
}
-static bool sculpt_brush_stroke_init(bContext *C, wmOperator *op)
+static void sculpt_brush_stroke_init(bContext *C, wmOperator *op)
{
Depsgraph *depsgraph = CTX_data_depsgraph(C);
Scene *scene = CTX_data_scene(C);
@@ -4829,8 +4829,6 @@ static bool sculpt_brush_stroke_init(bContext *C, wmOperator *op)
is_smooth = sculpt_any_smooth_mode(brush, NULL, mode);
BKE_sculpt_update_mesh_elements(depsgraph, scene, sd, ob, is_smooth, need_mask);
-
- return 1;
}
static void sculpt_restore_mesh(Sculpt *sd, Object *ob)
@@ -5075,8 +5073,7 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent
int ignore_background_click;
int retval;
- if (!sculpt_brush_stroke_init(C, op))
- return OPERATOR_CANCELLED;
+ sculpt_brush_stroke_init(C, op);
stroke = paint_stroke_new(C, op, sculpt_stroke_get_location,
sculpt_stroke_test_start,
@@ -5108,8 +5105,7 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent
static int sculpt_brush_stroke_exec(bContext *C, wmOperator *op)
{
- if (!sculpt_brush_stroke_init(C, op))
- return OPERATOR_CANCELLED;
+ sculpt_brush_stroke_init(C, op);
op->customdata = paint_stroke_new(C, op, sculpt_stroke_get_location, sculpt_stroke_test_start,
sculpt_stroke_update_step, NULL, sculpt_stroke_done, 0);
@@ -5666,7 +5662,7 @@ void ED_object_sculptmode_enter_ex(
/* Make sure derived final from original object does not reference possibly
* freed memory.
*/
- BKE_object_free_derived_mesh_caches(ob);
+ BKE_object_free_derived_caches(ob);
sculpt_init_session(depsgraph, scene, ob);
@@ -5737,7 +5733,7 @@ void ED_object_sculptmode_enter_ex(
}
}
- // ED_workspace_object_mode_sync_from_object(G.main->wm.first, workspace, ob);
+ // ED_workspace_object_mode_sync_from_object(bmain->wm.first, workspace, ob);
/* Flush object mode. */
DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
@@ -5789,14 +5785,14 @@ void ED_object_sculptmode_exit_ex(
/* Leave sculptmode */
ob->mode &= ~mode_flag;
- // ED_workspace_object_mode_sync_from_object(G.main->wm.first, workspace, ob);
+ // ED_workspace_object_mode_sync_from_object(G_MAIN->wm.first, workspace, ob);
BKE_sculptsession_free(ob);
paint_cursor_delete_textures();
/* Never leave derived meshes behind. */
- BKE_object_free_derived_mesh_caches(ob);
+ BKE_object_free_derived_caches(ob);
/* Flush object mode. */
DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index b7a80a92998..049feea2d8a 100644
--- a/source/blender/editors/sound/sound_ops.c
+++ b/source/blender/editors/sound/sound_ops.c
@@ -455,10 +455,10 @@ static bool sound_mixdown_check(bContext *UNUSED(C), wmOperator *op)
prop = RNA_struct_find_property(op->ptr, "filepath");
RNA_property_string_get(op->ptr, prop, filepath);
- if (BLI_testextensie_array(filepath, snd_ext_sound))
- check = BLI_replace_extension(filepath, FILE_MAX, extension);
+ if (BLI_path_extension_check_array(filepath, snd_ext_sound))
+ check = BLI_path_extension_replace(filepath, FILE_MAX, extension);
else
- check = BLI_ensure_extension(filepath, FILE_MAX, extension);
+ check = BLI_path_extension_ensure(filepath, FILE_MAX, extension);
if (!check)
return check;
diff --git a/source/blender/editors/space_action/action_buttons.c b/source/blender/editors/space_action/action_buttons.c
index a5cc66add87..55ad773f4df 100644
--- a/source/blender/editors/space_action/action_buttons.c
+++ b/source/blender/editors/space_action/action_buttons.c
@@ -117,7 +117,7 @@ static int action_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
void ACTION_OT_properties(wmOperatorType *ot)
{
- ot->name = "Properties";
+ ot->name = "Toggle Sidebar";
ot->idname = "ACTION_OT_properties";
ot->description = "Toggle the properties region visibility";
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index 7c8be943a87..35ebb62a7cc 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -436,7 +436,7 @@ void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene)
continue;
gpuPushMatrix();
- gpuTranslate2f(0.0, (float)V2D_SCROLL_HEIGHT + yoffs);
+ gpuTranslate2f(0.0, (float)V2D_SCROLL_HEIGHT_TEXT + yoffs);
gpuScale2f(1.0, cache_draw_height);
switch (pid->type) {
diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c
index e130ea9369c..527e382ec1e 100644
--- a/source/blender/editors/space_action/space_action.c
+++ b/source/blender/editors/space_action/space_action.c
@@ -116,7 +116,7 @@ static SpaceLink *action_new(const ScrArea *sa, const Scene *scene)
BLI_addtail(&saction->regionbase, ar);
ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = RGN_ALIGN_BOTTOM;
+ ar->alignment = RGN_ALIGN_TOP;
/* channel list region */
ar = MEM_callocN(sizeof(ARegion), "channel region for action");
@@ -752,7 +752,7 @@ static void action_buttons_area_init(wmWindowManager *wm, ARegion *ar)
static void action_buttons_area_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
static void action_region_listener(
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index be687d365f3..4fe3423e730 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -144,7 +144,7 @@ static void buttons_main_region_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler(&ar->handlers, keymap);
}
-static void buttons_main_region_draw_properties(const bContext *C, SpaceButs *sbuts, ARegion *ar)
+static void buttons_main_region_layout_properties(const bContext *C, SpaceButs *sbuts, ARegion *ar)
{
const bool vertical = (sbuts->align == BUT_VERTICAL);
@@ -203,12 +203,10 @@ static void buttons_main_region_draw_properties(const bContext *C, SpaceButs *sb
break;
}
- if (contexts[0]) {
- ED_region_panels(C, ar, contexts, sbuts->mainb, vertical);
- }
+ ED_region_panels_layout_ex(C, ar, contexts, sbuts->mainb, vertical);
}
-static void buttons_main_region_draw_tool(const bContext *C, SpaceButs *sbuts, ARegion *ar)
+static void buttons_main_region_layout_tool(const bContext *C, SpaceButs *sbuts, ARegion *ar)
{
const bool vertical = (sbuts->align == BUT_VERTICAL);
const char *contexts[3] = {NULL};
@@ -260,30 +258,24 @@ static void buttons_main_region_draw_tool(const bContext *C, SpaceButs *sbuts, A
ARRAY_SET_ITEMS(contexts, ".todo");
break;
}
- if (contexts[0]) {
- ED_region_panels(C, ar, contexts, -1, vertical);
- }
}
else if (workspace->tools_space_type == SPACE_IMAGE) {
/* TODO */
}
- if (contexts[0] == NULL) {
- UI_ThemeClearColor(TH_BACK);
- glClear(GL_COLOR_BUFFER_BIT);
- }
+ ED_region_panels_layout_ex(C, ar, contexts, -1, vertical);
}
-static void buttons_main_region_draw(const bContext *C, ARegion *ar)
+static void buttons_main_region_layout(const bContext *C, ARegion *ar)
{
/* draw entirely, view changes should be handled here */
SpaceButs *sbuts = CTX_wm_space_buts(C);
if (sbuts->mainb == BCONTEXT_TOOL) {
- buttons_main_region_draw_tool(C, sbuts, ar);
+ buttons_main_region_layout_tool(C, sbuts, ar);
}
else {
- buttons_main_region_draw_properties(C, sbuts, ar);
+ buttons_main_region_layout_properties(C, sbuts, ar);
}
sbuts->re_align = 0;
@@ -619,7 +611,8 @@ void ED_spacetype_buttons(void)
art = MEM_callocN(sizeof(ARegionType), "spacetype buttons region");
art->regionid = RGN_TYPE_WINDOW;
art->init = buttons_main_region_init;
- art->draw = buttons_main_region_draw;
+ art->layout = buttons_main_region_layout;
+ art->draw = ED_region_panels_draw;
art->listener = buttons_main_region_listener;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
BLI_addhead(&st->regiontypes, art);
diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c
index 469d94fed3a..f2fe06874d7 100644
--- a/source/blender/editors/space_clip/clip_buttons.c
+++ b/source/blender/editors/space_clip/clip_buttons.c
@@ -387,7 +387,7 @@ void uiTemplateMarker(uiLayout *layout, PointerRNA *ptr, const char *propname, P
else
tip = TIP_("Marker is enabled at current frame");
- bt = uiDefIconButBitI(block, UI_BTYPE_TOGGLE_N, MARKER_DISABLED, 0, ICON_RESTRICT_VIEW_OFF, 0, 0, UI_UNIT_X, UI_UNIT_Y,
+ bt = uiDefIconButBitI(block, UI_BTYPE_TOGGLE_N, MARKER_DISABLED, 0, ICON_HIDE_OFF, 0, 0, UI_UNIT_X, UI_UNIT_Y,
&cb->marker_flag, 0, 0, 1, 0, tip);
UI_but_funcN_set(bt, marker_update_cb, cb, NULL);
}
diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h
index ab8a7add009..e5c4f567d5c 100644
--- a/source/blender/editors/space_clip/clip_intern.h
+++ b/source/blender/editors/space_clip/clip_intern.h
@@ -145,6 +145,8 @@ void clip_view_center_to_point(SpaceClip *sc, float x, float y);
void clip_draw_sfra_efra(struct View2D *v2d, struct Scene *scene);
+void clip_on_marker_selection_changed(struct bContext *C);
+
/* tracking_ops.c */
struct MovieTrackingTrack *tracking_marker_check_slide(struct bContext *C, const struct wmEvent *event,
int *area_r, int *action_r, int *corner_r);
diff --git a/source/blender/editors/space_clip/clip_toolbar.c b/source/blender/editors/space_clip/clip_toolbar.c
index 61bd8df3dbf..3e4d0cd5bb4 100644
--- a/source/blender/editors/space_clip/clip_toolbar.c
+++ b/source/blender/editors/space_clip/clip_toolbar.c
@@ -106,7 +106,7 @@ static int properties_exec(bContext *C, wmOperator *UNUSED(op))
void CLIP_OT_properties(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Properties";
+ ot->name = "Toggle Sidebar";
ot->description = "Toggle the properties region visibility";
ot->idname = "CLIP_OT_properties";
@@ -170,7 +170,7 @@ static int tools_exec(bContext *C, wmOperator *UNUSED(op))
void CLIP_OT_tools(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Tools";
+ ot->name = "Toggle Toolbar";
ot->description = "Toggle clip tools panel";
ot->idname = "CLIP_OT_tools";
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index f022bb7e6f8..b050e991140 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -1435,7 +1435,7 @@ static void clip_tools_region_init(wmWindowManager *wm, ARegion *ar)
static void clip_tools_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
/****************** tool properties region ******************/
@@ -1484,7 +1484,7 @@ static void clip_properties_region_draw(const bContext *C, ARegion *ar)
BKE_movieclip_update_scopes(sc->clip, &sc->user, &sc->scopes);
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
static void clip_properties_region_listener(
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 8123bed541c..09e2660a762 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -267,10 +267,11 @@ typedef struct FileListEntryPreview {
ImBuf *img;
} FileListEntryPreview;
+
typedef struct FileListFilter {
unsigned int filter;
unsigned int filter_id;
- char filter_glob[256];
+ char filter_glob[FILE_MAXFILE];
char filter_search[66]; /* + 2 for heading/trailing implicit '*' wildcards. */
short flags;
} FileListFilter;
@@ -1973,31 +1974,31 @@ int ED_path_extension_type(const char *path)
else if (file_is_blend_backup(path)) {
return FILE_TYPE_BLENDER_BACKUP;
}
- else if (BLI_testextensie(path, ".app")) {
+ else if (BLI_path_extension_check(path, ".app")) {
return FILE_TYPE_APPLICATIONBUNDLE;
}
- else if (BLI_testextensie(path, ".py")) {
+ else if (BLI_path_extension_check(path, ".py")) {
return FILE_TYPE_PYSCRIPT;
}
- else if (BLI_testextensie_n(path, ".txt", ".glsl", ".osl", ".data", ".pov", ".ini", ".mcr", ".inc", NULL)) {
+ else if (BLI_path_extension_check_n(path, ".txt", ".glsl", ".osl", ".data", ".pov", ".ini", ".mcr", ".inc", NULL)) {
return FILE_TYPE_TEXT;
}
- else if (BLI_testextensie_n(path, ".ttf", ".ttc", ".pfb", ".otf", ".otc", NULL)) {
+ else if (BLI_path_extension_check_n(path, ".ttf", ".ttc", ".pfb", ".otf", ".otc", NULL)) {
return FILE_TYPE_FTFONT;
}
- else if (BLI_testextensie(path, ".btx")) {
+ else if (BLI_path_extension_check(path, ".btx")) {
return FILE_TYPE_BTX;
}
- else if (BLI_testextensie(path, ".dae")) {
+ else if (BLI_path_extension_check(path, ".dae")) {
return FILE_TYPE_COLLADA;
}
- else if (BLI_testextensie(path, ".abc")) {
+ else if (BLI_path_extension_check(path, ".abc")) {
return FILE_TYPE_ALEMBIC;
}
- else if (BLI_testextensie_array(path, imb_ext_image)) {
+ else if (BLI_path_extension_check_array(path, imb_ext_image)) {
return FILE_TYPE_IMAGE;
}
- else if (BLI_testextensie(path, ".ogg")) {
+ else if (BLI_path_extension_check(path, ".ogg")) {
if (IMB_isanim(path)) {
return FILE_TYPE_MOVIE;
}
@@ -2005,10 +2006,10 @@ int ED_path_extension_type(const char *path)
return FILE_TYPE_SOUND;
}
}
- else if (BLI_testextensie_array(path, imb_ext_movie)) {
+ else if (BLI_path_extension_check_array(path, imb_ext_movie)) {
return FILE_TYPE_MOVIE;
}
- else if (BLI_testextensie_array(path, imb_ext_audio)) {
+ else if (BLI_path_extension_check_array(path, imb_ext_audio)) {
return FILE_TYPE_SOUND;
}
return 0;
@@ -2233,7 +2234,7 @@ static int filelist_readjob_list_dir(
/* Otherwise, do not check extensions for directories! */
else if (!(entry->typeflag & FILE_TYPE_DIR)) {
entry->typeflag = file_extension_type(root, entry->relpath);
- if (filter_glob[0] && BLI_testextensie_glob(entry->relpath, filter_glob)) {
+ if (filter_glob[0] && BLI_path_extension_check_glob(entry->relpath, filter_glob)) {
entry->typeflag |= FILE_TYPE_OPERATOR;
}
}
@@ -2464,7 +2465,7 @@ static void filelist_readjob_do(
BLI_Stack *todo_dirs;
TodoDir *td_dir;
char dir[FILE_MAX_LIBEXTRA];
- char filter_glob[64]; /* TODO should be define! */
+ char filter_glob[FILE_MAXFILE];
const char *root = filelist->filelist.root;
const int max_recursion = filelist->max_recursion;
int nbr_done_dirs = 0, nbr_todo_dirs = 1;
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index 418a9f8c16f..cb014f30d95 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -196,6 +196,10 @@ short ED_fileselect_set_params(SpaceFile *sfile)
if (tmp != params->filter_glob) {
BLI_strncpy(params->filter_glob, tmp, sizeof(params->filter_glob));
MEM_freeN(tmp);
+
+ /* Fix stupid things that truncating might have generated,
+ * like last group being a 'match everything' wildcard-only one... */
+ BLI_path_extension_glob_validate(params->filter_glob);
}
params->filter |= (FILE_TYPE_OPERATOR | FILE_TYPE_FOLDER);
}
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index 62e7c7923e8..7b045a42595 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -636,7 +636,7 @@ static void file_tools_region_init(wmWindowManager *wm, ARegion *ar)
static void file_tools_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
static void file_tools_region_listener(
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index 4f3de0398a2..2a0d5baa5c3 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -801,7 +801,7 @@ static void graph_draw_driver_settings_panel(uiLayout *layout, ID *id, FCurve *f
if ((G.f & G_SCRIPT_AUTOEXEC) == 0) {
/* TODO: Add button to enable? */
- uiItemL(col, IFACE_("ERROR: Python auto-execution disabled"), ICON_CANCEL);
+ uiItemL(col, IFACE_("WARNING: Python expressions limited for security"), ICON_ERROR);
}
else if (driver->flag & DRIVER_FLAG_INVALID) {
uiItemL(col, IFACE_("ERROR: Invalid Python expression"), ICON_CANCEL);
@@ -1207,7 +1207,7 @@ static int graph_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
void GRAPH_OT_properties(wmOperatorType *ot)
{
- ot->name = "Properties";
+ ot->name = "Toggle Sidebar";
ot->idname = "GRAPH_OT_properties";
ot->description = "Toggle the properties region visibility";
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index 56236ea8f47..d208ead317b 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -181,14 +181,14 @@ static void graph_free(SpaceLink *sl)
/* spacetype; init callback */
-static void graph_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
+static void graph_init(struct wmWindowManager *wm, ScrArea *sa)
{
SpaceIpo *sipo = (SpaceIpo *)sa->spacedata.first;
/* init dopesheet data if non-existent (i.e. for old files) */
if (sipo->ads == NULL) {
sipo->ads = MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet");
- sipo->ads->source = (ID *)(G.main->scene.first); // FIXME: this is a really nasty hack here for now...
+ sipo->ads->source = (ID *)WM_window_get_active_scene(wm->winactive);
}
/* force immediate init of any invalid F-Curve colors */
@@ -422,7 +422,7 @@ static void graph_buttons_region_init(wmWindowManager *wm, ARegion *ar)
static void graph_buttons_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
static void graph_region_listener(
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index 8b8aabb2ce0..7236a99ad80 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -291,23 +291,24 @@ static void ui_imageuser_slot_menu(bContext *UNUSED(C), uiLayout *layout, void *
{
uiBlock *block = uiLayoutGetBlock(layout);
Image *image = image_p;
- int slot;
+ int slot_id;
uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("Slot"),
0, 0, UI_UNIT_X * 5, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
uiItemS(layout);
- slot = IMA_MAX_RENDER_SLOT;
- while (slot--) {
+ slot_id = BLI_listbase_count(&image->renderslots) - 1;
+ for (RenderSlot *slot = image->renderslots.last; slot; slot = slot->prev) {
char str[64];
- if (image->render_slots[slot].name[0] != '\0') {
- BLI_strncpy(str, image->render_slots[slot].name, sizeof(str));
+ if (slot->name[0] != '\0') {
+ BLI_strncpy(str, slot->name, sizeof(str));
}
else {
- BLI_snprintf(str, sizeof(str), IFACE_("Slot %d"), slot + 1);
+ BLI_snprintf(str, sizeof(str), IFACE_("Slot %d"), slot_id + 1);
}
uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, str, 0, 0,
- UI_UNIT_X * 5, UI_UNIT_X, &image->render_slot, (float) slot, 0.0, 0, -1, "");
+ UI_UNIT_X * 5, UI_UNIT_X, &image->render_slot, (float) slot_id, 0.0, 0, -1, "");
+ slot_id--;
}
}
@@ -708,8 +709,9 @@ static void uiblock_layer_pass_buttons(
/* menu buts */
if (render_slot) {
char str[64];
- if (image->render_slots[*render_slot].name[0] != '\0') {
- BLI_strncpy(str, image->render_slots[*render_slot].name, sizeof(str));
+ RenderSlot *slot = BKE_image_get_renderslot(image, *render_slot);
+ if (slot->name[0] != '\0') {
+ BLI_strncpy(str, slot->name, sizeof(str));
}
else {
BLI_snprintf(str, sizeof(str), IFACE_("Slot %d"), *render_slot + 1);
@@ -1313,7 +1315,7 @@ static int image_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
void IMAGE_OT_properties(wmOperatorType *ot)
{
- ot->name = "Properties";
+ ot->name = "Toggle Sidebar";
ot->idname = "IMAGE_OT_properties";
ot->description = "Toggle the properties region visibility";
@@ -1337,7 +1339,7 @@ static int image_scopes_toggle_exec(bContext *C, wmOperator *UNUSED(op))
void IMAGE_OT_toolshelf(wmOperatorType *ot)
{
- ot->name = "Tool Shelf";
+ ot->name = "Toggle Toolbar";
ot->idname = "IMAGE_OT_toolshelf";
ot->description = "Toggles tool shelf display";
diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c
index 0eb6a2400d2..f4ecd2e7d34 100644
--- a/source/blender/editors/space_image/image_edit.c
+++ b/source/blender/editors/space_image/image_edit.c
@@ -34,6 +34,7 @@
#include "DNA_scene_types.h"
#include "BLI_rect.h"
+#include "BLI_listbase.h"
#include "BKE_colortools.h"
#include "BKE_context.h"
@@ -302,17 +303,19 @@ bool ED_image_slot_cycle(struct Image *image, int direction)
BLI_assert(ELEM(direction, -1, 1));
- for (i = 1; i < IMA_MAX_RENDER_SLOT; i++) {
- slot = (cur + ((direction == -1) ? -i : i)) % IMA_MAX_RENDER_SLOT;
- if (slot < 0) slot += IMA_MAX_RENDER_SLOT;
+ int num_slots = BLI_listbase_count(&image->renderslots);
+ for (i = 1; i < num_slots; i++) {
+ slot = (cur + ((direction == -1) ? -i : i)) % num_slots;
+ if (slot < 0) slot += num_slots;
- if (image->renders[slot] || slot == image->last_render_slot) {
+ RenderSlot *render_slot = BKE_image_get_renderslot(image, slot);
+ if ((render_slot && render_slot->render) || slot == image->last_render_slot) {
image->render_slot = slot;
break;
}
}
- if (i == IMA_MAX_RENDER_SLOT) {
+ if (i == num_slots) {
image->render_slot = ((cur == 1) ? 0 : 1);
}
diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h
index 9167a193f2d..49c2690daaf 100644
--- a/source/blender/editors/space_image/image_intern.h
+++ b/source/blender/editors/space_image/image_intern.h
@@ -83,6 +83,9 @@ void IMAGE_OT_unpack(struct wmOperatorType *ot);
void IMAGE_OT_invert(struct wmOperatorType *ot);
void IMAGE_OT_cycle_render_slot(struct wmOperatorType *ot);
+void IMAGE_OT_clear_render_slot(struct wmOperatorType *ot);
+void IMAGE_OT_add_render_slot(struct wmOperatorType *ot);
+void IMAGE_OT_remove_render_slot(struct wmOperatorType *ot);
void IMAGE_OT_sample(struct wmOperatorType *ot);
void IMAGE_OT_sample_line(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 39544eb55dd..b2116b1a770 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -1538,7 +1538,7 @@ static int image_replace_exec(bContext *C, wmOperator *op)
BKE_image_signal(bmain, sima->image, &sima->iuser, IMA_SIGNAL_SRC_CHANGE);
}
- if (BLI_testextensie_array(str, imb_ext_movie))
+ if (BLI_path_extension_check_array(str, imb_ext_movie))
sima->image->source = IMA_SRC_MOVIE;
else
sima->image->source = IMA_SRC_FILE;
@@ -3464,7 +3464,8 @@ static int image_cycle_render_slot_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
/* no undo push for browsing existing */
- if (ima->renders[ima->render_slot] || ima->render_slot == ima->last_render_slot)
+ RenderSlot *slot = BKE_image_get_renderslot(ima, ima->render_slot);
+ if ((slot && slot->render) || ima->render_slot == ima->last_render_slot)
return OPERATOR_CANCELLED;
return OPERATOR_FINISHED;
@@ -3487,6 +3488,97 @@ void IMAGE_OT_cycle_render_slot(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "reverse", 0, "Cycle in Reverse", "");
}
+/********************* clear render slot operator *********************/
+
+static int image_clear_render_slot_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Image *ima = CTX_data_edit_image(C);
+
+ if (!BKE_image_clear_renderslot(ima, &sima->iuser, ima->render_slot)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void IMAGE_OT_clear_render_slot(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Clear Render Slot";
+ ot->idname = "IMAGE_OT_clear_render_slot";
+ ot->description = "Clear the currently selected render slot";
+
+ /* api callbacks */
+ ot->exec = image_clear_render_slot_exec;
+ ot->poll = image_cycle_render_slot_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
+}
+
+/********************* add render slot operator *********************/
+
+static int image_add_render_slot_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Image *ima = CTX_data_edit_image(C);
+
+ RenderSlot *slot = BKE_image_add_renderslot(ima, NULL);
+ ima->render_slot = BLI_findindex(&ima->renderslots, slot);
+
+ WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void IMAGE_OT_add_render_slot(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Render Slot";
+ ot->idname = "IMAGE_OT_add_render_slot";
+ ot->description = "Add a new render slot";
+
+ /* api callbacks */
+ ot->exec = image_add_render_slot_exec;
+ ot->poll = image_cycle_render_slot_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
+}
+
+/********************* remove render slot operator *********************/
+
+static int image_remove_render_slot_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ SpaceImage *sima = CTX_wm_space_image(C);
+ Image *ima = CTX_data_edit_image(C);
+
+ if (!BKE_image_remove_renderslot(ima, &sima->iuser, ima->render_slot)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void IMAGE_OT_remove_render_slot(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Render Slot";
+ ot->idname = "IMAGE_OT_remove_render_slot";
+ ot->description = "Remove the current render slot";
+
+ /* api callbacks */
+ ot->exec = image_remove_render_slot_exec;
+ ot->poll = image_cycle_render_slot_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER;
+}
+
/********************** change frame operator *********************/
static int change_frame_poll(bContext *C)
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index c143ebbcd67..e84b596530e 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -272,6 +272,9 @@ static void image_operatortypes(void)
WM_operatortype_append(IMAGE_OT_invert);
WM_operatortype_append(IMAGE_OT_cycle_render_slot);
+ WM_operatortype_append(IMAGE_OT_clear_render_slot);
+ WM_operatortype_append(IMAGE_OT_add_render_slot);
+ WM_operatortype_append(IMAGE_OT_remove_render_slot);
WM_operatortype_append(IMAGE_OT_sample);
WM_operatortype_append(IMAGE_OT_sample_line);
@@ -358,7 +361,7 @@ static void image_keymap(struct wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "toggle", true);
/* fast switch to render slots */
- for (i = 0; i < MIN2(IMA_MAX_RENDER_SLOT, 9); i++) {
+ for (i = 0; i < 9; i++) {
kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_int", ONEKEY + i, KM_PRESS, 0, 0);
RNA_string_set(kmi->ptr, "data_path", "space_data.image.render_slots.active_index");
RNA_int_set(kmi->ptr, "value", i);
@@ -869,7 +872,7 @@ static void image_buttons_region_init(wmWindowManager *wm, ARegion *ar)
static void image_buttons_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
static void image_buttons_region_listener(
@@ -944,7 +947,7 @@ static void image_tools_region_draw(const bContext *C, ARegion *ar)
}
ED_space_image_release_buffer(sima, ibuf, lock);
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
static void image_tools_region_listener(
@@ -1096,7 +1099,6 @@ void ED_spacetype_image(void)
art->init = image_main_region_init;
art->draw = image_main_region_draw;
art->listener = image_main_region_listener;
-
BLI_addhead(&st->regiontypes, art);
/* regions: listview/buttons */
@@ -1134,5 +1136,9 @@ void ED_spacetype_image(void)
BLI_addhead(&st->regiontypes, art);
+ /* regions: hud */
+ art = ED_area_type_hud(st->spaceid);
+ BLI_addhead(&st->regiontypes, art);
+
BKE_spacetype_register(st);
}
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index a26e6b0280e..cafb40626ee 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -574,7 +574,7 @@ static int nla_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
void NLA_OT_properties(wmOperatorType *ot)
{
- ot->name = "Properties";
+ ot->name = "Toggle Sidebar";
ot->idname = "NLA_OT_properties";
ot->description = "Toggle the properties region visibility";
diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c
index 26ac06446c4..23cd504978c 100644
--- a/source/blender/editors/space_nla/nla_edit.c
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -1057,7 +1057,7 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *op)
/* if selected, split the strip at its midpoint */
if (strip->flag & NLASTRIP_FLAG_SELECT) {
/* make a copy (assume that this is possible) */
- nstrip = BKE_nlastrip_copy(strip, linked);
+ nstrip = BKE_nlastrip_copy(ac.bmain, strip, linked);
/* in case there's no space in the track above, or we haven't got a reference to it yet, try adding */
if (BKE_nlatrack_add_strip(nlt->next, nstrip) == 0) {
@@ -1207,7 +1207,7 @@ void NLA_OT_delete(wmOperatorType *ot)
// - variable-length splits?
/* split a given Action-Clip strip */
-static void nlaedit_split_strip_actclip(AnimData *adt, NlaTrack *nlt, NlaStrip *strip, float cfra)
+static void nlaedit_split_strip_actclip(Main *bmain, AnimData *adt, NlaTrack *nlt, NlaStrip *strip, float cfra)
{
NlaStrip *nstrip;
float splitframe, splitaframe;
@@ -1242,7 +1242,7 @@ static void nlaedit_split_strip_actclip(AnimData *adt, NlaTrack *nlt, NlaStrip *
/* make a copy (assume that this is possible) and append
* it immediately after the current strip
*/
- nstrip = BKE_nlastrip_copy(strip, true);
+ nstrip = BKE_nlastrip_copy(bmain, strip, true);
BLI_insertlinkafter(&nlt->strips, strip, nstrip);
/* set the endpoint of the first strip and the start of the new strip
@@ -1303,7 +1303,7 @@ static int nlaedit_split_exec(bContext *C, wmOperator *UNUSED(op))
/* splitting method depends on the type of strip */
switch (strip->type) {
case NLASTRIP_TYPE_CLIP: /* action-clip */
- nlaedit_split_strip_actclip(adt, nlt, strip, (float)ac.scene->r.cfra);
+ nlaedit_split_strip_actclip(ac.bmain, adt, nlt, strip, (float)ac.scene->r.cfra);
break;
case NLASTRIP_TYPE_META: /* meta-strips need special handling */
diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c
index 318d8bf777b..745cea37ea3 100644
--- a/source/blender/editors/space_nla/space_nla.c
+++ b/source/blender/editors/space_nla/space_nla.c
@@ -178,14 +178,14 @@ static void nla_free(SpaceLink *sl)
/* spacetype; init callback */
-static void nla_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
+static void nla_init(struct wmWindowManager *wm, ScrArea *sa)
{
SpaceNla *snla = (SpaceNla *)sa->spacedata.first;
/* init dopesheet data if non-existent (i.e. for old files) */
if (snla->ads == NULL) {
snla->ads = MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet");
- snla->ads->source = (ID *)G.main->scene.first; // XXX this is bad, but we need this to be set correct
+ snla->ads->source = (ID *)WM_window_get_active_scene(wm->winactive);
}
ED_area_tag_refresh(sa);
@@ -360,7 +360,7 @@ static void nla_buttons_region_init(wmWindowManager *wm, ARegion *ar)
static void nla_buttons_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
static void nla_region_listener(
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index db718da12ef..a162a863038 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -1080,6 +1080,13 @@ static void node_shader_buts_bevel(uiLayout *layout, bContext *UNUSED(C), Pointe
uiItemR(layout, ptr, "samples", 0, NULL, ICON_NONE);
}
+static void node_shader_buts_ambient_occlusion(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "samples", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "inside", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "only_local", 0, NULL, ICON_NONE);
+}
+
/* only once called */
static void node_shader_set_butfunc(bNodeType *ntype)
{
@@ -1210,6 +1217,9 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_BEVEL:
ntype->draw_buttons = node_shader_buts_bevel;
break;
+ case SH_NODE_AMBIENT_OCCLUSION:
+ ntype->draw_buttons = node_shader_buts_ambient_occlusion;
+ break;
}
}
diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c
index 0a656ee1deb..38183637750 100644
--- a/source/blender/editors/space_node/node_buttons.c
+++ b/source/blender/editors/space_node/node_buttons.c
@@ -224,7 +224,7 @@ static int node_properties_poll(bContext *C)
void NODE_OT_properties(wmOperatorType *ot)
{
- ot->name = "Properties";
+ ot->name = "Toggle Sidebar";
ot->description = "Toggle the properties region visibility";
ot->idname = "NODE_OT_properties";
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index 91101d1101e..ff87dcf409a 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -656,6 +656,7 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
if (wo->nodetree && wo->use_nodes && ntreeHasTree(wo->nodetree, ntree))
GPU_material_free(&wo->gpumaterial);
+ ED_node_tag_update_nodetree(bmain, ntree, node);
WM_main_add_notifier(NC_IMAGE, NULL);
}
@@ -929,11 +930,13 @@ static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event)
case LEFTMOUSE:
case MIDDLEMOUSE:
case RIGHTMOUSE:
+ if (event->val == KM_RELEASE) {
+ node_resize_exit(C, op, false);
+ ED_node_post_apply_transform(C, snode->edittree);
- node_resize_exit(C, op, false);
- ED_node_post_apply_transform(C, snode->edittree);
-
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
+ }
+ break;
}
return OPERATOR_RUNNING_MODAL;
diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c
index 5d326a0be38..926fff7a3b6 100644
--- a/source/blender/editors/space_node/node_group.c
+++ b/source/blender/editors/space_node/node_group.c
@@ -260,7 +260,7 @@ static int node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode)
waction = wgroup->adt->action = BKE_action_copy(bmain, wgroup->adt->action);
/* now perform the moving */
- BKE_animdata_separate_by_basepath(&wgroup->id, &ntree->id, &anim_basepaths);
+ BKE_animdata_separate_by_basepath(bmain, &wgroup->id, &ntree->id, &anim_basepaths);
/* paths + their wrappers need to be freed */
for (ld = anim_basepaths.first; ld; ld = ldn) {
@@ -397,7 +397,8 @@ void NODE_OT_group_ungroup(wmOperatorType *ot)
/* ******************** Separate operator ********************** */
/* returns 1 if its OK */
-static int node_group_separate_selected(bNodeTree *ntree, bNodeTree *ngroup, float offx, float offy, int make_copy)
+static int node_group_separate_selected(
+ Main *bmain, bNodeTree *ntree, bNodeTree *ngroup, float offx, float offy, int make_copy)
{
bNodeLink *link, *link_next;
bNode *node, *node_next, *newnode;
@@ -492,7 +493,7 @@ static int node_group_separate_selected(bNodeTree *ntree, bNodeTree *ngroup, flo
LinkData *ld, *ldn = NULL;
/* now perform the moving */
- BKE_animdata_separate_by_basepath(&ngroup->id, &ntree->id, &anim_basepaths);
+ BKE_animdata_separate_by_basepath(bmain, &ngroup->id, &ntree->id, &anim_basepaths);
/* paths + their wrappers need to be freed */
for (ld = anim_basepaths.first; ld; ld = ldn) {
@@ -524,12 +525,13 @@ static const EnumPropertyItem node_group_separate_types[] = {
static int node_group_separate_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
SpaceNode *snode = CTX_wm_space_node(C);
bNodeTree *ngroup, *nparent;
int type = RNA_enum_get(op->ptr, "type");
float offx, offy;
- ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
+ ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
/* are we inside of a group? */
ngroup = snode->edittree;
@@ -543,13 +545,13 @@ static int node_group_separate_exec(bContext *C, wmOperator *op)
switch (type) {
case NODE_GS_COPY:
- if (!node_group_separate_selected(nparent, ngroup, offx, offy, 1)) {
+ if (!node_group_separate_selected(bmain, nparent, ngroup, offx, offy, 1)) {
BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes");
return OPERATOR_CANCELLED;
}
break;
case NODE_GS_MOVE:
- if (!node_group_separate_selected(nparent, ngroup, offx, offy, 0)) {
+ if (!node_group_separate_selected(bmain, nparent, ngroup, offx, offy, 0)) {
BKE_report(op->reports, RPT_WARNING, "Cannot separate nodes");
return OPERATOR_CANCELLED;
}
@@ -681,6 +683,7 @@ static int node_get_selected_minmax(bNodeTree *ntree, bNode *gnode, float *min,
static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree, bNode *gnode)
{
+ Main *bmain = CTX_data_main(C);
bNodeTree *ngroup = (bNodeTree *)gnode->id;
bNodeLink *link, *linkn;
bNode *node, *nextn;
@@ -742,7 +745,7 @@ static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree,
if (ntree->adt) {
LinkData *ld, *ldn = NULL;
- BKE_animdata_separate_by_basepath(&ntree->id, &ngroup->id, &anim_basepaths);
+ BKE_animdata_separate_by_basepath(bmain, &ntree->id, &ngroup->id, &anim_basepaths);
/* paths + their wrappers need to be freed */
for (ld = anim_basepaths.first; ld; ld = ldn) {
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index 36886d0ab32..441ab03cb28 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -603,7 +603,7 @@ static void node_buttons_region_init(wmWindowManager *wm, ARegion *ar)
static void node_buttons_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
/* add handlers, stuff you only do once or on area/region changes */
@@ -619,7 +619,7 @@ static void node_toolbar_region_init(wmWindowManager *wm, ARegion *ar)
static void node_toolbar_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
static void node_cursor(wmWindow *win, ScrArea *sa, ARegion *ar)
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index 909938ad606..a700f8e20e0 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -320,7 +320,10 @@ static int collection_objects_select_exec(bContext *C, wmOperator *op)
}
BKE_layer_collection_objects_select(view_layer, layer_collection, deselect);
- WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
+
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index a514d7f1335..a3f3acf1c32 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -92,8 +92,9 @@ static void outliner_height(SpaceOops *soops, ListBase *lb, int *h)
TreeElement *te = lb->first;
while (te) {
TreeStoreElem *tselem = TREESTORE(te);
- if (TSELEM_OPEN(tselem, soops))
+ if (TSELEM_OPEN(tselem, soops)) {
outliner_height(soops, &te->subtree, h);
+ }
(*h) += UI_UNIT_Y;
te = te->next;
}
@@ -132,8 +133,9 @@ static void outliner_rna_width(SpaceOops *soops, ListBase *lb, int *w, int start
if (startx + 100 > *w)
*w = startx + 100;
- if (TSELEM_OPEN(tselem, soops))
+ if (TSELEM_OPEN(tselem, soops)) {
outliner_rna_width(soops, &te->subtree, w, startx + UI_UNIT_X);
+ }
te = te->next;
}
}
@@ -276,6 +278,44 @@ static void restrictbutton_id_user_toggle(bContext *UNUSED(C), void *poin, void
}
}
+static void hidebutton_base_flag_cb(bContext *C, void *poin, void *poin2)
+{
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = poin;
+ Base *base = poin2;
+ bool extend = (CTX_wm_window(C)->eventstate->ctrl == 0);
+
+ /* Undo button toggle, let function do it. */
+ base->flag ^= BASE_HIDE;
+
+ BKE_base_set_visible(scene, view_layer, base, extend);
+
+ if (!extend && (base->flag & BASE_VISIBLED)) {
+ /* Auto select solo-ed object. */
+ ED_object_base_select(base, BA_SELECT);
+ view_layer->basact = base;
+ }
+
+ DEG_id_tag_update(&scene->id, DEG_TAG_BASE_FLAGS_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+}
+
+static void hidebutton_layer_collection_flag_cb(bContext *C, void *poin, void *poin2)
+{
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = poin;
+ LayerCollection *lc = poin2;
+ bool extend = (CTX_wm_window(C)->eventstate->ctrl == 0);
+
+ /* Undo button toggle, let function do it. */
+ lc->runtime_flag ^= LAYER_COLLECTION_HAS_VISIBLE_OBJECTS;
+
+ BKE_layer_collection_set_visible(scene, view_layer, lc, extend);
+
+ DEG_id_tag_update(&scene->id, DEG_TAG_BASE_FLAGS_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+}
+
static void namebutton_cb(bContext *C, void *tsep, char *oldname)
{
Main *bmain = CTX_data_main(C);
@@ -432,172 +472,214 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
}
}
-static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops, ListBase *lb)
+static void outliner_draw_restrictbuts(
+ uiBlock *block, Scene *scene, ViewLayer *view_layer, ARegion *ar, SpaceOops *soops, ListBase *lb)
{
uiBut *bt;
- TreeElement *te;
- TreeStoreElem *tselem;
- Object *ob = NULL;
/* get RNA properties (once for speed) */
- PropertyRNA *collection_prop_hide_viewport;
- PropertyRNA *collection_prop_hide_select;
- PropertyRNA *collection_prop_hide_render;
+ PropertyRNA *object_prop_hide_viewport, *object_prop_hide_select, *object_prop_hide_render;
+ PropertyRNA *collection_prop_hide_viewport, *collection_prop_hide_select, *collection_prop_hide_render;
+
+ object_prop_hide_viewport = RNA_struct_type_find_property(&RNA_Object, "hide_viewport");
+ object_prop_hide_select = RNA_struct_type_find_property(&RNA_Object, "hide_select");
+ object_prop_hide_render = RNA_struct_type_find_property(&RNA_Object, "hide_render");
collection_prop_hide_select = RNA_struct_type_find_property(&RNA_Collection, "hide_select");
collection_prop_hide_viewport = RNA_struct_type_find_property(&RNA_Collection, "hide_viewport");
collection_prop_hide_render = RNA_struct_type_find_property(&RNA_Collection, "hide_render");
- BLI_assert(collection_prop_hide_viewport &&
+
+ BLI_assert(object_prop_hide_viewport &&
+ object_prop_hide_select &&
+ object_prop_hide_render &&
+ collection_prop_hide_viewport &&
collection_prop_hide_select &&
collection_prop_hide_render);
- for (te = lb->first; te; te = te->next) {
- tselem = TREESTORE(te);
+ for (TreeElement *te = lb->first; te; te = te->next) {
+ TreeStoreElem *tselem = TREESTORE(te);
if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
if (tselem->type == TSE_R_LAYER && (soops->outlinevis == SO_SCENES)) {
/* View layer render toggle. */
- ViewLayer *view_layer = te->directdata;
-
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ ViewLayer *layer = te->directdata;
- bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE_N, VIEW_LAYER_RENDER, 0, ICON_RESTRICT_RENDER_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &view_layer->flag, 0, 0, 0, 0, TIP_("Use view layer for rendering"));
+ bt = uiDefIconButBitS(
+ block, UI_BTYPE_ICON_TOGGLE_N, VIEW_LAYER_RENDER, 0, ICON_RESTRICT_RENDER_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &layer->flag, 0, 0, 0, 0, TIP_("Use view layer for rendering"));
UI_but_func_set(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
+ else if (tselem->type == 0 && te->idcode == ID_OB) {
+ Object *ob = (Object *)tselem->id;
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+
+ if (base) {
+ bt = uiDefIconButBitS(
+ block, UI_BTYPE_ICON_TOGGLE, BASE_HIDE, 0, ICON_HIDE_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_HIDEX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &base->flag, 0, 0, 0, 0,
+ TIP_("Hide object in viewport (Ctrl to isolate)"));
+ UI_but_func_set(bt, hidebutton_base_flag_cb, view_layer, base);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
+
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)ob, &RNA_Object, ob, &ptr);
+
+ bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_VIEW_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y,
+ &ptr, object_prop_hide_viewport, -1, 0, 0, -1, -1,
+ TIP_("Restrict viewport visibility"));
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+
+ bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_SELECT_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X, UI_UNIT_Y,
+ &ptr, object_prop_hide_select, -1, 0, 0, -1, -1,
+ TIP_("Restrict viewport selection"));
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+
+ bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_RENDER_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, UI_UNIT_Y,
+ &ptr, object_prop_hide_render, -1, 0, 0, -1, -1,
+ TIP_("Restrict render visibility"));
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- UI_block_emboss_set(block, UI_EMBOSS);
}
else if (tselem->type == TSE_MODIFIER) {
ModifierData *md = (ModifierData *)te->directdata;
- ob = (Object *)tselem->id;
+ Object *ob = (Object *)tselem->id;
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE_N, eModifierMode_Realtime, 0, ICON_RESTRICT_VIEW_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &(md->mode), 0, 0, 0, 0,
- TIP_("Restrict/Allow visibility in the 3D View"));
+ bt = uiDefIconButBitI(
+ block, UI_BTYPE_ICON_TOGGLE_N, eModifierMode_Realtime, 0, ICON_RESTRICT_VIEW_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &(md->mode), 0, 0, 0, 0,
+ TIP_("Restrict/Allow visibility in the 3D View"));
UI_but_func_set(bt, restrictbutton_modifier_cb, scene, ob);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE_N, eModifierMode_Render, 0, ICON_RESTRICT_RENDER_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &(md->mode), 0, 0, 0, 0, TIP_("Restrict/Allow renderability"));
+ bt = uiDefIconButBitI(
+ block, UI_BTYPE_ICON_TOGGLE_N, eModifierMode_Render, 0, ICON_RESTRICT_RENDER_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &(md->mode), 0, 0, 0, 0, TIP_("Restrict/Allow renderability"));
UI_but_func_set(bt, restrictbutton_modifier_cb, scene, ob);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
-
- UI_block_emboss_set(block, UI_EMBOSS);
}
else if (tselem->type == TSE_POSE_CHANNEL) {
bPoseChannel *pchan = (bPoseChannel *)te->directdata;
Bone *bone = pchan->bone;
- ob = (Object *)tselem->id;
+ Object *ob = (Object *)tselem->id;
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE, BONE_HIDDEN_P, 0, ICON_RESTRICT_VIEW_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &(bone->flag), 0, 0, 0, 0,
- TIP_("Restrict/Allow visibility in the 3D View"));
+ bt = uiDefIconButBitI(
+ block, UI_BTYPE_ICON_TOGGLE, BONE_HIDDEN_P, 0, ICON_HIDE_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &(bone->flag), 0, 0, 0, 0,
+ TIP_("Restrict/Allow visibility in the 3D View"));
UI_but_func_set(bt, restrictbutton_bone_visibility_cb, ob->data, bone);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &(bone->flag), 0, 0, 0, 0,
- TIP_("Restrict/Allow selection in the 3D View"));
+ bt = uiDefIconButBitI(
+ block, UI_BTYPE_ICON_TOGGLE, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &(bone->flag), 0, 0, 0, 0,
+ TIP_("Restrict/Allow selection in the 3D View"));
UI_but_func_set(bt, restrictbutton_bone_select_cb, ob->data, bone);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
-
- UI_block_emboss_set(block, UI_EMBOSS);
}
else if (tselem->type == TSE_EBONE) {
EditBone *ebone = (EditBone *)te->directdata;
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE, BONE_HIDDEN_A, 0, ICON_RESTRICT_VIEW_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &(ebone->flag), 0, 0, 0, 0,
- TIP_("Restrict/Allow visibility in the 3D View"));
+ bt = uiDefIconButBitI(
+ block, UI_BTYPE_ICON_TOGGLE, BONE_HIDDEN_A, 0, ICON_RESTRICT_VIEW_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &(ebone->flag), 0, 0, 0, 0,
+ TIP_("Restrict/Allow visibility in the 3D View"));
UI_but_func_set(bt, restrictbutton_ebone_visibility_cb, NULL, ebone);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- bt = uiDefIconButBitI(block, UI_BTYPE_ICON_TOGGLE, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &(ebone->flag), 0, 0, 0, 0,
- TIP_("Restrict/Allow selection in the 3D View"));
+ bt = uiDefIconButBitI(
+ block, UI_BTYPE_ICON_TOGGLE, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &(ebone->flag), 0, 0, 0, 0,
+ TIP_("Restrict/Allow selection in the 3D View"));
UI_but_func_set(bt, restrictbutton_ebone_select_cb, NULL, ebone);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
-
- UI_block_emboss_set(block, UI_EMBOSS);
}
else if (tselem->type == TSE_GP_LAYER) {
bGPDlayer *gpl = (bGPDlayer *)te->directdata;
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
-
- bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE, GP_LAYER_HIDE, 0, ICON_RESTRICT_VIEW_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &gpl->flag, 0, 0, 0, 0,
- TIP_("Restrict/Allow visibility in the 3D View"));
+ bt = uiDefIconButBitS(
+ block, UI_BTYPE_ICON_TOGGLE, GP_LAYER_HIDE, 0, ICON_HIDE_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &gpl->flag, 0, 0, 0, 0,
+ TIP_("Restrict/Allow visibility in the 3D View"));
UI_but_func_set(bt, restrictbutton_gp_layer_flag_cb, NULL, gpl);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- bt = uiDefIconButBitS(block, UI_BTYPE_ICON_TOGGLE, GP_LAYER_LOCKED, 0, ICON_UNLOCKED,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &gpl->flag, 0, 0, 0, 0,
- TIP_("Restrict/Allow editing of strokes and keyframes in this layer"));
+ bt = uiDefIconButBitS(
+ block, UI_BTYPE_ICON_TOGGLE, GP_LAYER_LOCKED, 0, ICON_UNLOCKED,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &gpl->flag, 0, 0, 0, 0,
+ TIP_("Restrict/Allow editing of strokes and keyframes in this layer"));
UI_but_func_set(bt, restrictbutton_gp_layer_flag_cb, NULL, gpl);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
/* TODO: visibility in renders */
-
- UI_block_emboss_set(block, UI_EMBOSS);
}
else if (outliner_is_collection_tree_element(te)) {
LayerCollection *lc = (tselem->type == TSE_LAYER_COLLECTION) ? te->directdata : NULL;
Collection *collection = outliner_collection_from_tree_element(te);
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
-
if ((!lc || !(lc->flag & LAYER_COLLECTION_EXCLUDE)) &&
!(collection->flag & COLLECTION_IS_MASTER))
{
+ if (lc && (lc->runtime_flag & LAYER_COLLECTION_HAS_ENABLED_OBJECTS)) {
+ bt = uiDefIconButBitS(
+ block, UI_BTYPE_ICON_TOGGLE_N, LAYER_COLLECTION_HAS_VISIBLE_OBJECTS, 0, ICON_HIDE_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_HIDEX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &lc->runtime_flag, 0, 0, 0, 0,
+ TIP_("Hide collection in viewport (Ctrl to isolate)"));
+ UI_but_func_set(bt, hidebutton_layer_collection_flag_cb, view_layer, lc);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
+
PointerRNA collection_ptr;
RNA_id_pointer_create(&collection->id, &collection_ptr);
- bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_VIEW_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &collection_ptr, collection_prop_hide_viewport, -1, 0, 0, 0, 0, NULL);
+ bt = uiDefIconButR_prop(
+ block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_VIEW_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &collection_ptr, collection_prop_hide_viewport, -1, 0, 0, 0, 0, NULL);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_RENDER_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &collection_ptr, collection_prop_hide_render, -1, 0, 0, 0, 0, NULL);
+ bt = uiDefIconButR_prop(
+ block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_RENDER_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &collection_ptr, collection_prop_hide_render, -1, 0, 0, 0, 0, NULL);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_SELECT_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &collection_ptr, collection_prop_hide_select, -1, 0, 0, 0, 0, NULL);
+ bt = uiDefIconButR_prop(
+ block, UI_BTYPE_ICON_TOGGLE, 0, ICON_RESTRICT_SELECT_OFF,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys, UI_UNIT_X,
+ UI_UNIT_Y, &collection_ptr, collection_prop_hide_select, -1, 0, 0, 0, 0, NULL);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
}
-
- UI_block_emboss_set(block, UI_EMBOSS);
}
}
- if (TSELEM_OPEN(tselem, soops)) outliner_draw_restrictbuts(block, scene, ar, soops, &te->subtree);
+ if (TSELEM_OPEN(tselem, soops)) {
+ outliner_draw_restrictbuts(block, scene, view_layer, ar, soops, &te->subtree);
+ }
}
}
static void outliner_draw_userbuts(uiBlock *block, ARegion *ar, SpaceOops *soops, ListBase *lb)
{
- uiBut *bt;
- TreeElement *te;
- TreeStoreElem *tselem;
- for (te = lb->first; te; te = te->next) {
- tselem = TREESTORE(te);
+ for (TreeElement *te = lb->first; te; te = te->next) {
+ TreeStoreElem *tselem = TREESTORE(te);
if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
if (tselem->type == 0) {
+ uiBut *bt;
ID *id = tselem->id;
const char *tip = NULL;
int icon = ICON_NONE;
@@ -607,8 +689,6 @@ static void outliner_draw_userbuts(uiBlock *block, ARegion *ar, SpaceOops *soops
if (ID_IS_LINKED(id))
but_flag |= UI_BUT_DISABLED;
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
-
if (id->flag & LIB_FAKEUSER) {
icon = ICON_FILE_TICK;
tip = TIP_("Data-block will be retained using a fake user");
@@ -617,34 +697,37 @@ static void outliner_draw_userbuts(uiBlock *block, ARegion *ar, SpaceOops *soops
icon = ICON_X;
tip = TIP_("Data-block has no users and will be deleted");
}
- bt = uiDefIconButBitS(block, UI_BTYPE_TOGGLE, LIB_FAKEUSER, 1, icon,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y,
- &id->flag, 0, 0, 0, 0, tip);
+ bt = uiDefIconButBitS(
+ block, UI_BTYPE_TOGGLE, LIB_FAKEUSER, 1, icon,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), te->ys, UI_UNIT_X, UI_UNIT_Y,
+ &id->flag, 0, 0, 0, 0, tip);
UI_but_func_set(bt, restrictbutton_id_user_toggle, id, NULL);
UI_but_flag_enable(bt, but_flag);
BLI_str_format_int_grouped(buf, id->us);
- bt = uiDefBut(block, UI_BTYPE_BUT, 1, buf,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys,
- UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0,
- TIP_("Number of users of this data-block"));
+ bt = uiDefBut(
+ block, UI_BTYPE_BUT, 1, buf,
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), te->ys,
+ UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0,
+ TIP_("Number of users of this data-block"));
UI_but_flag_enable(bt, but_flag);
- bt = uiDefButBitS(block, UI_BTYPE_TOGGLE, LIB_FAKEUSER, 1, (id->flag & LIB_FAKEUSER) ? "F" : " ",
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, UI_UNIT_Y,
- &id->flag, 0, 0, 0, 0,
- TIP_("Data-block has a 'fake' user which will keep it in the file "
- "even if nothing else uses it"));
+ bt = uiDefButBitS(
+ block, UI_BTYPE_TOGGLE, LIB_FAKEUSER, 1, (id->flag & LIB_FAKEUSER) ? "F" : " ",
+ (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X, UI_UNIT_Y,
+ &id->flag, 0, 0, 0, 0,
+ TIP_("Data-block has a 'fake' user which will keep it in the file "
+ "even if nothing else uses it"));
UI_but_func_set(bt, restrictbutton_id_user_toggle, id, NULL);
UI_but_flag_enable(bt, but_flag);
-
- UI_block_emboss_set(block, UI_EMBOSS);
}
}
- if (TSELEM_OPEN(tselem, soops)) outliner_draw_userbuts(block, ar, soops, &te->subtree);
+ if (TSELEM_OPEN(tselem, soops)) {
+ outliner_draw_userbuts(block, ar, soops, &te->subtree);
+ }
}
}
@@ -676,13 +759,11 @@ static void outliner_draw_rnacols(ARegion *ar, int sizex)
static void outliner_draw_rnabuts(uiBlock *block, ARegion *ar, SpaceOops *soops, int sizex, ListBase *lb)
{
- TreeElement *te;
- TreeStoreElem *tselem;
PointerRNA *ptr;
PropertyRNA *prop;
- for (te = lb->first; te; te = te->next) {
- tselem = TREESTORE(te);
+ for (TreeElement *te = lb->first; te; te = te->next) {
+ TreeStoreElem *tselem = TREESTORE(te);
if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
if (tselem->type == TSE_RNA_PROPERTY) {
ptr = &te->rnaptr;
@@ -690,17 +771,20 @@ static void outliner_draw_rnabuts(uiBlock *block, ARegion *ar, SpaceOops *soops,
if (!TSELEM_OPEN(tselem, soops)) {
if (RNA_property_type(prop) == PROP_POINTER) {
- uiBut *but = uiDefAutoButR(block, ptr, prop, -1, "", ICON_NONE, sizex, te->ys,
- OL_RNA_COL_SIZEX, UI_UNIT_Y - 1);
+ uiBut *but = uiDefAutoButR(
+ block, ptr, prop, -1, "", ICON_NONE, sizex, te->ys,
+ OL_RNA_COL_SIZEX, UI_UNIT_Y - 1);
UI_but_flag_enable(but, UI_BUT_DISABLED);
}
else if (RNA_property_type(prop) == PROP_ENUM) {
- uiDefAutoButR(block, ptr, prop, -1, NULL, ICON_NONE, sizex, te->ys, OL_RNA_COL_SIZEX,
- UI_UNIT_Y - 1);
+ uiDefAutoButR(
+ block, ptr, prop, -1, NULL, ICON_NONE, sizex, te->ys, OL_RNA_COL_SIZEX,
+ UI_UNIT_Y - 1);
}
else {
- uiDefAutoButR(block, ptr, prop, -1, "", ICON_NONE, sizex, te->ys, OL_RNA_COL_SIZEX,
- UI_UNIT_Y - 1);
+ uiDefAutoButR(
+ block, ptr, prop, -1, "", ICON_NONE, sizex, te->ys, OL_RNA_COL_SIZEX,
+ UI_UNIT_Y - 1);
}
}
}
@@ -708,15 +792,16 @@ static void outliner_draw_rnabuts(uiBlock *block, ARegion *ar, SpaceOops *soops,
ptr = &te->rnaptr;
prop = te->directdata;
- uiDefAutoButR(block, ptr, prop, te->index, "", ICON_NONE, sizex, te->ys, OL_RNA_COL_SIZEX,
- UI_UNIT_Y - 1);
+ uiDefAutoButR(
+ block, ptr, prop, te->index, "", ICON_NONE, sizex, te->ys, OL_RNA_COL_SIZEX,
+ UI_UNIT_Y - 1);
}
}
- if (TSELEM_OPEN(tselem, soops)) outliner_draw_rnabuts(block, ar, soops, sizex, &te->subtree);
+ if (TSELEM_OPEN(tselem, soops)) {
+ outliner_draw_rnabuts(block, ar, soops, sizex, &te->subtree);
+ }
}
-
- UI_block_emboss_set(block, UI_EMBOSS);
}
static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, TreeElement *te)
@@ -740,8 +825,9 @@ static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, Tre
spx = te->xs + 1.8f * UI_UNIT_X;
dx = ar->v2d.cur.xmax - (spx + 3.2f * UI_UNIT_X);
- bt = uiDefBut(block, UI_BTYPE_TEXT, OL_NAMEBUTTON, "", spx, te->ys, dx, UI_UNIT_Y - 1, (void *)te->name,
- 1.0, (float)len, 0, 0, "");
+ bt = uiDefBut(
+ block, UI_BTYPE_TEXT, OL_NAMEBUTTON, "", spx, te->ys, dx, UI_UNIT_Y - 1, (void *)te->name,
+ 1.0, (float)len, 0, 0, "");
UI_but_func_rename_set(bt, namebutton_cb, tselem);
/* returns false if button got removed */
@@ -773,9 +859,10 @@ static void tselem_draw_icon_uibut(struct DrawIconArg *arg, int icon)
glDisable(GL_BLEND);
}
else {
- uiBut *but = uiDefIconBut(arg->block, UI_BTYPE_LABEL, 0, icon, arg->xb, arg->yb, UI_UNIT_X, UI_UNIT_Y, NULL,
- 0.0, 0.0, 1.0, arg->alpha,
- (arg->id && ID_IS_LINKED(arg->id)) ? arg->id->lib->name : "");
+ uiBut *but = uiDefIconBut(
+ arg->block, UI_BTYPE_LABEL, 0, icon, arg->xb, arg->yb, UI_UNIT_X, UI_UNIT_Y, NULL,
+ 0.0, 0.0, 1.0, arg->alpha,
+ (arg->id && ID_IS_LINKED(arg->id)) ? arg->id->lib->name : "");
if (arg->id)
UI_but_drag_set_id(but, arg->id);
@@ -816,8 +903,9 @@ static void UNUSED_FUNCTION(tselem_draw_gp_icon_uibut)(struct DrawIconArg *arg,
}
}
-static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeStoreElem *tselem, TreeElement *te,
- float alpha)
+static void tselem_draw_icon(
+ uiBlock *block, int xmax, float x, float y, TreeStoreElem *tselem, TreeElement *te,
+ float alpha)
{
struct DrawIconArg arg;
float aspect;
@@ -1248,17 +1336,15 @@ static void outliner_draw_iconrow(
bContext *C, uiBlock *block, Scene *scene, ViewLayer *view_layer, SpaceOops *soops,
ListBase *lb, int level, int xmax, int *offsx, int ys, float alpha_fac)
{
- TreeElement *te;
- TreeStoreElem *tselem;
eOLDrawState active;
const Object *obact = OBACT(view_layer);
- for (te = lb->first; te; te = te->next) {
+ for (TreeElement *te = lb->first; te; te = te->next) {
/* exit drawing early */
if ((*offsx) - UI_UNIT_X > xmax)
break;
- tselem = TREESTORE(te);
+ TreeStoreElem *tselem = TREESTORE(te);
/* object hierarchy always, further constrained on level */
if (level < 1 || (tselem->type == 0 && te->idcode == ID_OB)) {
@@ -1437,12 +1523,16 @@ static void outliner_draw_tree_element(
int icon_x = startx;
// icons a bit higher
- if (TSELEM_OPEN(tselem, soops))
- UI_icon_draw_alpha((float)icon_x + 2 * ufac, (float)*starty + 1 * ufac, ICON_DISCLOSURE_TRI_DOWN,
- alpha_fac);
- else
- UI_icon_draw_alpha((float)icon_x + 2 * ufac, (float)*starty + 1 * ufac, ICON_DISCLOSURE_TRI_RIGHT,
- alpha_fac);
+ if (TSELEM_OPEN(tselem, soops)) {
+ UI_icon_draw_alpha(
+ (float)icon_x + 2 * ufac, (float)*starty + 1 * ufac, ICON_DISCLOSURE_TRI_DOWN,
+ alpha_fac);
+ }
+ else {
+ UI_icon_draw_alpha(
+ (float)icon_x + 2 * ufac, (float)*starty + 1 * ufac, ICON_DISCLOSURE_TRI_RIGHT,
+ alpha_fac);
+ }
}
offsx += UI_UNIT_X;
@@ -1457,22 +1547,26 @@ static void outliner_draw_tree_element(
if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION) && ID_IS_LINKED(tselem->id)) {
if (tselem->id->tag & LIB_TAG_MISSING) {
- UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_BROKEN,
- alpha_fac);
+ UI_icon_draw_alpha(
+ (float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_BROKEN,
+ alpha_fac);
}
else if (tselem->id->tag & LIB_TAG_INDIRECT) {
- UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_INDIRECT,
- alpha_fac);
+ UI_icon_draw_alpha(
+ (float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_INDIRECT,
+ alpha_fac);
}
else {
- UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_DIRECT,
- alpha_fac);
+ UI_icon_draw_alpha(
+ (float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_DIRECT,
+ alpha_fac);
}
offsx += UI_UNIT_X + 2 * ufac;
}
else if (ELEM(tselem->type, 0, TSE_LAYER_COLLECTION) && ID_IS_STATIC_OVERRIDE(tselem->id)) {
- UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_OVERRIDE,
- alpha_fac);
+ UI_icon_draw_alpha(
+ (float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_OVERRIDE,
+ alpha_fac);
offsx += UI_UNIT_X + 2 * ufac;
}
glDisable(GL_BLEND);
@@ -1612,12 +1706,12 @@ static void outliner_draw_tree_element_floating(
immUnbindProgram();
}
-static void outliner_draw_hierarchy_lines_recursive(unsigned pos, SpaceOops *soops, ListBase *lb, int startx,
- const unsigned char col[4], bool draw_grayed_out,
- int *starty)
+static void outliner_draw_hierarchy_lines_recursive(
+ unsigned pos, SpaceOops *soops, ListBase *lb, int startx,
+ const unsigned char col[4], bool draw_grayed_out,
+ int *starty)
{
TreeElement *te, *te_vertical_line_last = NULL;
- TreeStoreElem *tselem;
int y1, y2;
if (BLI_listbase_is_empty(lb)) {
@@ -1630,7 +1724,7 @@ static void outliner_draw_hierarchy_lines_recursive(unsigned pos, SpaceOops *soo
y1 = y2 = *starty;
for (te = lb->first; te; te = te->next) {
bool draw_childs_grayed_out = draw_grayed_out || (te->drag_data != NULL);
- tselem = TREESTORE(te);
+ TreeStoreElem *tselem = TREESTORE(te);
if (draw_childs_grayed_out) {
immUniformColor3ubvAlpha(col, grayed_alpha);
@@ -1653,8 +1747,9 @@ static void outliner_draw_hierarchy_lines_recursive(unsigned pos, SpaceOops *soo
*starty -= UI_UNIT_Y;
if (TSELEM_OPEN(tselem, soops))
- outliner_draw_hierarchy_lines_recursive(pos, soops, &te->subtree, startx + UI_UNIT_X,
- col, draw_childs_grayed_out, starty);
+ outliner_draw_hierarchy_lines_recursive(
+ pos, soops, &te->subtree, startx + UI_UNIT_X,
+ col, draw_childs_grayed_out, starty);
}
if (draw_grayed_out) {
@@ -1690,14 +1785,11 @@ static void outliner_draw_hierarchy_lines(SpaceOops *soops, ListBase *lb, int st
static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase *lb, int *starty)
{
- TreeElement *te;
- TreeStoreElem *tselem;
-
- for (te = lb->first; te; te = te->next) {
- tselem = TREESTORE(te);
+ for (TreeElement *te = lb->first; te; te = te->next) {
+ TreeStoreElem *tselem = TREESTORE(te);
/* selection status */
- if (TSELEM_OPEN(tselem, soops))
+ if (TSELEM_OPEN(tselem, soops)) {
if (tselem->type == TSE_RNA_STRUCT) {
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
@@ -1706,6 +1798,7 @@ static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase *
immRecti(pos, 0, *starty + 1, (int)ar->v2d.cur.xmax, *starty + UI_UNIT_Y - 1);
immUnbindProgram();
}
+ }
*starty -= UI_UNIT_Y;
if (TSELEM_OPEN(tselem, soops)) {
@@ -1732,10 +1825,11 @@ static void outliner_draw_highlights_recursive(
const float col_selection[4], const float col_highlight[4], const float col_searchmatch[4],
int start_x, int *io_start_y)
{
- const bool is_searching = SEARCHING_OUTLINER(soops) ||
- (soops->outlinevis == SO_DATA_API &&
- (soops->filter & SO_FILTER_SEARCH) &&
- soops->search_string[0] != 0);
+ const bool is_searching = (
+ SEARCHING_OUTLINER(soops) ||
+ (soops->outlinevis == SO_DATA_API &&
+ (soops->filter & SO_FILTER_SEARCH) &&
+ soops->search_string[0] != 0));
for (TreeElement *te = lb->first; te; te = te->next) {
const TreeStoreElem *tselem = TREESTORE(te);
@@ -1784,8 +1878,9 @@ static void outliner_draw_highlights(ARegion *ar, SpaceOops *soops, int startx,
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- outliner_draw_highlights_recursive(pos, ar, soops, &soops->tree, col_selection, col_highlight, col_searchmatch,
- startx, starty);
+ outliner_draw_highlights_recursive(
+ pos, ar, soops, &soops->tree, col_selection, col_highlight, col_searchmatch,
+ startx, starty);
immUnbindProgram();
glDisable(GL_BLEND);
}
@@ -1890,7 +1985,10 @@ static void outliner_draw_restrictcols(ARegion *ar)
unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_I32, 2, GWN_FETCH_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColorShadeAlpha(TH_BACK, -15, -200);
- immBegin(GWN_PRIM_LINES, 6);
+ immBegin(GWN_PRIM_LINES, 8);
+
+ immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_HIDEX), (int)ar->v2d.cur.ymax);
+ immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_HIDEX), (int)ar->v2d.cur.ymin);
immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)ar->v2d.cur.ymax);
immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)ar->v2d.cur.ymin);
@@ -1976,10 +2074,16 @@ void draw_outliner(const bContext *C)
(bContext *)C, block, scene, view_layer,
ar, soops, has_restrict_icons, &te_edit);
+ /* Default to no emboss for outliner UI. */
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+
if (soops->outlinevis == SO_DATA_API) {
/* draw rna buttons */
outliner_draw_rnacols(ar, sizex_rna);
+
+ UI_block_emboss_set(block, UI_EMBOSS);
outliner_draw_rnabuts(block, ar, soops, sizex_rna, &soops->tree);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
}
else if ((soops->outlinevis == SO_ID_ORPHANS) && has_restrict_icons) {
/* draw user toggle columns */
@@ -1989,7 +2093,8 @@ void draw_outliner(const bContext *C)
else if (has_restrict_icons) {
/* draw restriction columns */
outliner_draw_restrictcols(ar);
- outliner_draw_restrictbuts(block, scene, ar, soops, &soops->tree);
+
+ outliner_draw_restrictbuts(block, scene, view_layer, ar, soops, &soops->tree);
}
/* draw edit buttons if nessecery */
@@ -1997,6 +2102,8 @@ void draw_outliner(const bContext *C)
outliner_buttons(C, block, ar, te_edit);
}
+ UI_block_emboss_set(block, UI_EMBOSS);
+
UI_block_end(C, block);
UI_block_draw(C, block);
}
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 2a694e2e2e3..a455f8c076a 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -63,6 +63,7 @@
#include "BKE_scene.h"
#include "BKE_material.h"
+#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
#include "../blenloader/BLO_readfile.h"
@@ -252,6 +253,55 @@ void OUTLINER_OT_item_openclose(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "all", 1, "All", "Close or open all items");
}
+/* -------------------------------------------------------------------- */
+/** \name Object Mode Enter/Exit
+ * \{ */
+
+static void item_object_mode_enter_exit(
+ bContext *C, ReportList *reports, Object *ob,
+ bool enter)
+{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *obact = OBACT(view_layer);
+
+ if ((ob->type != obact->type) || ID_IS_LINKED(ob->data)) {
+ return;
+ }
+ if (((ob->mode & obact->mode) != 0) == enter) {
+ return;
+ }
+
+ if (ob == obact) {
+ BKE_report(reports, RPT_WARNING, "Active object mode not changed");
+ return;
+ }
+
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+ if (base == NULL) {
+ return;
+ }
+ Scene *scene = CTX_data_scene(C);
+ outliner_object_mode_toggle(C, scene, view_layer, base);
+}
+
+void item_object_mode_enter_cb(
+ bContext *C, ReportList *reports, Scene *UNUSED(scene), TreeElement *UNUSED(te),
+ TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
+{
+ Object *ob = (Object *)tselem->id;
+ item_object_mode_enter_exit(C, reports, ob, true);
+}
+
+void item_object_mode_exit_cb(
+ bContext *C, ReportList *reports, Scene *UNUSED(scene), TreeElement *UNUSED(te),
+ TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
+{
+ Object *ob = (Object *)tselem->id;
+ item_object_mode_enter_exit(C, reports, ob, false);
+}
+
+/** \} */
+
/* Rename --------------------------------------------------- */
static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem,
@@ -901,6 +951,7 @@ static int outliner_toggle_selected_exec(bContext *C, wmOperator *UNUSED(op))
else
outliner_set_flag(&soops->tree, TSE_SELECTED, 1);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
ED_region_tag_redraw_no_rebuild(ar);
@@ -2169,6 +2220,7 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
DEG_relations_tag_update(bmain);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index 8ac09648d60..1f8320f73a0 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -151,11 +151,12 @@ typedef enum {
/* size constants */
#define OL_Y_OFFSET 2
+#define OL_TOG_HIDEX (UI_UNIT_X * 4.0f)
#define OL_TOG_RESTRICT_SELECTX (UI_UNIT_X * 3.0f)
#define OL_TOG_RESTRICT_VIEWX (UI_UNIT_X * 2.0f)
#define OL_TOG_RESTRICT_RENDERX UI_UNIT_X
-#define OL_TOGW OL_TOG_RESTRICT_SELECTX
+#define OL_TOGW OL_TOG_HIDEX
#define OL_RNA_COLX (UI_UNIT_X * 15)
#define OL_RNA_COL_SIZEX (UI_UNIT_X * 7.5f)
@@ -226,6 +227,10 @@ void outliner_item_select(
struct SpaceOops *soops, const struct TreeElement *te,
const bool extend, const bool toggle);
+void outliner_object_mode_toggle(
+ struct bContext *C, Scene *scene, ViewLayer *view_layer,
+ Base *base);
+
/* outliner_edit.c ---------------------------------------------- */
typedef void (*outliner_operation_cb)(
struct bContext *C, struct ReportList *, struct Scene *scene,
@@ -271,6 +276,13 @@ void id_remap_cb(
struct bContext *C, struct ReportList *reports, struct Scene *scene, struct TreeElement *te,
struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
+void item_object_mode_enter_cb(
+ struct bContext *C, struct ReportList *reports, struct Scene *scene,
+ TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
+void item_object_mode_exit_cb(
+ struct bContext *C, struct ReportList *reports, struct Scene *scene,
+ TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem, void *user_data);
+
TreeElement *outliner_dropzone_find(const struct SpaceOops *soops, const float fmval[2], const bool children);
void outliner_set_coordinates(struct ARegion *ar, struct SpaceOops *soops);
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index ecfd12618e5..316caf0e239 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -560,6 +560,13 @@ void outliner_keymap(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "OBJECT_OT_move_to_collection", MKEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "OBJECT_OT_link_to_collection", MKEY, KM_PRESS, KM_SHIFT, 0);
+ kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_clear", HKEY, KM_PRESS, KM_ALT, 0);
+ RNA_boolean_set(kmi->ptr, "select", false);
+ kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "unselected", false);
+ kmi = WM_keymap_add_item(keymap, "OBJECT_OT_hide_view_set", HKEY, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "unselected", true);
+
outliner_item_drag_drop_modal_keymap(keyconf);
}
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 36fd37e1134..38ae0683d4b 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -81,6 +81,7 @@ static void do_outliner_activate_obdata(bContext *C, Scene *scene, ViewLayer *vi
if (obact == NULL) {
ED_object_base_activate(C, base);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
obact = base->object;
use_all = true;
@@ -104,6 +105,7 @@ static void do_outliner_activate_obdata(bContext *C, Scene *scene, ViewLayer *vi
}
if (ok) {
ED_object_base_select(base, (ob->mode & OB_MODE_EDIT) ? BA_SELECT : BA_DESELECT);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
}
@@ -118,6 +120,7 @@ static void do_outliner_activate_pose(bContext *C, ViewLayer *view_layer, Base *
if (obact == NULL) {
ED_object_base_activate(C, base);
Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
obact = base->object;
use_all = true;
@@ -144,6 +147,7 @@ static void do_outliner_activate_pose(bContext *C, ViewLayer *view_layer, Base *
ED_object_base_select(base, (ob->mode & OB_MODE_POSE) ? BA_SELECT : BA_DESELECT);
Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
@@ -151,6 +155,20 @@ static void do_outliner_activate_pose(bContext *C, ViewLayer *view_layer, Base *
}
}
+/* For draw callback to run mode switching */
+void outliner_object_mode_toggle(
+ bContext *C, Scene *scene, ViewLayer *view_layer,
+ Base *base)
+{
+ Object *obact = OBACT(view_layer);
+ if (obact->mode & OB_MODE_EDIT) {
+ do_outliner_activate_obdata(C, scene, view_layer, base);
+ }
+ else if (obact->mode & OB_MODE_POSE) {
+ do_outliner_activate_pose(C, view_layer, base);
+ }
+}
+
/* ****************************************************** */
/* Outliner Element Selection/Activation on Click */
@@ -251,22 +269,22 @@ static eOLDrawState tree_element_set_active_object(
/* find associated base in current scene */
base = BKE_view_layer_base_find(view_layer, ob);
-#ifdef USE_OBJECT_MODE_STRICT
- if (base != NULL) {
- Object *obact = OBACT(view_layer);
- const eObjectMode object_mode = obact ? obact->mode : OB_MODE_OBJECT;
- if (base && !BKE_object_is_mode_compat(base->object, object_mode)) {
- if (object_mode == OB_MODE_OBJECT) {
- struct Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- ED_object_mode_generic_exit(bmain, depsgraph, scene, base->object);
- }
- if (!BKE_object_is_mode_compat(base->object, object_mode)) {
- base = NULL;
+ if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
+ if (base != NULL) {
+ Object *obact = OBACT(view_layer);
+ const eObjectMode object_mode = obact ? obact->mode : OB_MODE_OBJECT;
+ if (base && !BKE_object_is_mode_compat(base->object, object_mode)) {
+ if (object_mode == OB_MODE_OBJECT) {
+ struct Main *bmain = CTX_data_main(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ ED_object_mode_generic_exit(bmain, depsgraph, scene, base->object);
+ }
+ if (!BKE_object_is_mode_compat(base->object, object_mode)) {
+ base = NULL;
+ }
}
}
}
-#endif
if (base) {
if (set == OL_SETSEL_EXTEND) {
@@ -278,13 +296,11 @@ static eOLDrawState tree_element_set_active_object(
}
else {
/* deleselect all */
-#ifdef USE_OBJECT_MODE_STRICT
+
/* Only in object mode so we can switch the active object,
* keeping all objects in the current 'mode' selected, useful for multi-pose/edit mode.
* This keeps the convention that all objects in the current mode are also selected. see T55246. */
- if (ob->mode == OB_MODE_OBJECT)
-#endif
- {
+ if ((scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ? (ob->mode == OB_MODE_OBJECT) : true) {
BKE_view_layer_base_deselect_all(view_layer);
}
ED_object_base_select(base, BA_SELECT);
@@ -297,6 +313,7 @@ static eOLDrawState tree_element_set_active_object(
if (set != OL_SETSEL_NONE) {
ED_object_base_activate(C, base); /* adds notifier */
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
@@ -976,6 +993,7 @@ static void do_outliner_item_activate_tree_element(
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
else if (OB_DATA_SUPPORT_EDITMODE(te->idcode)) {
@@ -1176,6 +1194,7 @@ static int outliner_border_select_exec(bContext *C, wmOperator *op)
outliner_item_border_select(scene, &rectf, te, select);
}
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
ED_region_tag_redraw(ar);
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 8a01e5a7f2f..32918806765 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -893,6 +893,7 @@ static void object_delete_hierarchy_cb(
#endif
}
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
}
@@ -910,6 +911,8 @@ enum {
OL_OP_TOGSEL,
OL_OP_TOGREN,
OL_OP_RENAME,
+ OL_OP_OBJECT_MODE_ENTER,
+ OL_OP_OBJECT_MODE_EXIT,
};
static const EnumPropertyItem prop_object_op_types[] = {
@@ -921,6 +924,8 @@ static const EnumPropertyItem prop_object_op_types[] = {
{OL_OP_REMAP, "REMAP", 0, "Remap Users",
"Make all users of selected data-blocks to use instead a new chosen one"},
{OL_OP_RENAME, "RENAME", 0, "Rename", ""},
+ {OL_OP_OBJECT_MODE_ENTER, "OBJECT_MODE_ENTER", 0, "Enter Mode", ""},
+ {OL_OP_OBJECT_MODE_EXIT, "OBJECT_MODE_EXIT", 0, "Exit Mode", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -947,6 +952,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
}
str = "Select Objects";
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
else if (event == OL_OP_SELECT_HIERARCHY) {
@@ -956,11 +962,13 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
WM_window_change_active_scene(bmain, C, win, sce);
}
str = "Select Object Hierarchy";
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
else if (event == OL_OP_DESELECT) {
outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_deselect_cb);
str = "Deselect Objects";
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
else if (event == OL_OP_DELETE) {
@@ -975,6 +983,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
DEG_relations_tag_update(bmain);
str = "Delete Objects";
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
}
else if (event == OL_OP_DELETE_HIERARCHY) {
@@ -985,6 +994,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
DEG_relations_tag_update(bmain);
str = "Delete Object Hierarchy";
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
}
else if (event == OL_OP_REMAP) {
@@ -999,6 +1009,14 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, item_rename_cb);
str = "Rename Object";
}
+ else if (event == OL_OP_OBJECT_MODE_ENTER) {
+ outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, item_object_mode_enter_cb);
+ str = "Enter Current Mode";
+ }
+ else if (event == OL_OP_OBJECT_MODE_EXIT) {
+ outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, item_object_mode_exit_cb);
+ str = "Exit Current Mode";
+ }
else {
BLI_assert(0);
return OPERATOR_CANCELLED;
@@ -1568,8 +1586,8 @@ void OUTLINER_OT_animdata_operation(wmOperatorType *ot)
/* **************************************** */
static const EnumPropertyItem prop_constraint_op_types[] = {
- {OL_CONSTRAINTOP_ENABLE, "ENABLE", ICON_RESTRICT_VIEW_OFF, "Enable", ""},
- {OL_CONSTRAINTOP_DISABLE, "DISABLE", ICON_RESTRICT_VIEW_ON, "Disable", ""},
+ {OL_CONSTRAINTOP_ENABLE, "ENABLE", ICON_HIDE_OFF, "Enable", ""},
+ {OL_CONSTRAINTOP_DISABLE, "DISABLE", ICON_HIDE_ON, "Disable", ""},
{OL_CONSTRAINTOP_DELETE, "DELETE", ICON_X, "Delete", ""},
{0, NULL, 0, NULL, NULL}
};
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index d155457a208..13b62b766f5 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -1469,6 +1469,10 @@ static void outliner_add_layer_collection_objects(
Base *base = BKE_view_layer_base_find(layer, cob->ob);
TreeElement *te_object = outliner_add_element(soops, tree, base->object, ten, 0, 0);
te_object->directdata = base;
+
+ if (!(base->flag & BASE_VISIBLED)) {
+ te_object->flag |= TE_DISABLED;
+ }
}
}
@@ -1487,7 +1491,9 @@ static void outliner_add_layer_collections_recursive(
ten->reinsert_poll = outliner_collections_reorder_poll;
const bool exclude = (lc->flag & LAYER_COLLECTION_EXCLUDE) != 0;
- if (exclude) {
+ if (exclude ||
+ ((layer->runtime_flag & VIEW_LAYER_HAS_HIDE) &&
+ !(lc->runtime_flag & LAYER_COLLECTION_HAS_VISIBLE_OBJECTS))) {
ten->flag |= TE_DISABLED;
}
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index b24817f2af8..a78b3ee79c1 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -3874,7 +3874,7 @@ static int sequencer_export_subtitles_invoke(bContext *C, wmOperator *op, const
else
BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath));
- BLI_replace_extension(filepath, sizeof(filepath), ".srt");
+ BLI_path_extension_replace(filepath, sizeof(filepath), ".srt");
RNA_string_set(op->ptr, "filepath", filepath);
}
@@ -3899,7 +3899,7 @@ static int sequencer_export_subtitles_exec(bContext *C, wmOperator *op)
}
RNA_string_get(op->ptr, "filepath", filepath);
- BLI_ensure_extension(filepath, sizeof(filepath), ".srt");
+ BLI_path_extension_ensure(filepath, sizeof(filepath), ".srt");
/* Avoid File write exceptions */
if (!BLI_exists(filepath)) {
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index 75734963a0e..fc47934bc1e 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -708,7 +708,7 @@ static void sequencer_buttons_region_init(wmWindowManager *wm, ARegion *ar)
static void sequencer_buttons_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
static void sequencer_buttons_region_listener(
diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c
index 5885312e255..e827f4f0149 100644
--- a/source/blender/editors/space_text/space_text.c
+++ b/source/blender/editors/space_text/space_text.c
@@ -551,7 +551,7 @@ static void text_properties_region_draw(const bContext *C, ARegion *ar)
{
SpaceText *st = CTX_wm_space_text(C);
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
/* this flag trick is make sure buttons have been added already */
if (st->flags & ST_FIND_ACTIVATE) {
diff --git a/source/blender/editors/space_text/text_header.c b/source/blender/editors/space_text/text_header.c
index 50a8739c5b4..3d964d07908 100644
--- a/source/blender/editors/space_text/text_header.c
+++ b/source/blender/editors/space_text/text_header.c
@@ -91,7 +91,7 @@ static int text_properties_exec(bContext *C, wmOperator *UNUSED(op))
void TEXT_OT_properties(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Properties";
+ ot->name = "Toggle Sidebar";
ot->description = "Toggle the properties region visibility";
ot->idname = "TEXT_OT_properties";
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index b3815d73c5c..e34edc8908f 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -2071,7 +2071,9 @@ void TEXT_OT_delete(wmOperatorType *ot)
ot->flag = OPTYPE_UNDO;
/* properties */
- RNA_def_enum(ot->srna, "type", delete_type_items, DEL_NEXT_CHAR, "Type", "Which part of the text to delete");
+ PropertyRNA *prop;
+ prop = RNA_def_enum(ot->srna, "type", delete_type_items, DEL_NEXT_CHAR, "Type", "Which part of the text to delete");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
/******************* toggle overwrite operator **********************/
@@ -2243,13 +2245,15 @@ static int text_scroll_modal(bContext *C, wmOperator *op, const wmEvent *event)
case LEFTMOUSE:
case RIGHTMOUSE:
case MIDDLEMOUSE:
- if (ELEM(tsc->zone, SCROLLHANDLE_MIN_OUTSIDE, SCROLLHANDLE_MAX_OUTSIDE)) {
- txt_screen_skip(st, ar, st->viewlines * (tsc->zone == SCROLLHANDLE_MIN_OUTSIDE ? 1 : -1));
+ if (event->val == KM_RELEASE) {
+ if (ELEM(tsc->zone, SCROLLHANDLE_MIN_OUTSIDE, SCROLLHANDLE_MAX_OUTSIDE)) {
+ txt_screen_skip(st, ar, st->viewlines * (tsc->zone == SCROLLHANDLE_MIN_OUTSIDE ? 1 : -1));
- ED_area_tag_redraw(CTX_wm_area(C));
+ ED_area_tag_redraw(CTX_wm_area(C));
+ }
+ scroll_exit(C, op);
+ return OPERATOR_FINISHED;
}
- scroll_exit(C, op);
- return OPERATOR_FINISHED;
}
return OPERATOR_RUNNING_MODAL;
diff --git a/source/blender/editors/space_topbar/space_topbar.c b/source/blender/editors/space_topbar/space_topbar.c
index 4342fa87f89..c7ef6591c0d 100644
--- a/source/blender/editors/space_topbar/space_topbar.c
+++ b/source/blender/editors/space_topbar/space_topbar.c
@@ -57,9 +57,6 @@
#include "WM_types.h"
#include "WM_message.h"
-
-void topbar_panels_register(ARegionType *art);
-
/* ******************** default callbacks for topbar space ***************** */
static SpaceLink *topbar_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene))
@@ -277,64 +274,9 @@ void ED_spacetype_topbar(void)
art->layout = ED_region_header_layout;
art->draw = ED_region_header_draw;
- /* For popovers. */
- topbar_panels_register(art);
-
BLI_addhead(&st->regiontypes, art);
recent_files_menu_register();
BKE_spacetype_register(st);
}
-
-
-/* -------------------------------------------------------------------- */
-/** \name Redo Panel
- * \{ */
-
-static int topbar_panel_operator_redo_poll(const bContext *C, PanelType *UNUSED(pt))
-{
- wmOperator *op = WM_operator_last_redo(C);
- if (op == NULL) {
- return false;
- }
-
- bool success = false;
- if (!WM_operator_check_ui_empty(op->type)) {
- const OperatorRepeatContextHandle *context_info;
- context_info = ED_operator_repeat_prepare_context((bContext *)C, op);
- success = WM_operator_poll((bContext *)C, op->type);
- ED_operator_repeat_reset_context((bContext *)C, context_info);
- }
- return success;
-}
-
-static void topbar_panel_operator_redo(const bContext *C, Panel *pa)
-{
- wmOperator *op = WM_operator_last_redo(C);
- if (op == NULL) {
- return;
- }
- if (!WM_operator_check_ui_enabled(C, op->type->name)) {
- uiLayoutSetEnabled(pa->layout, false);
- }
- uiLayout *col = uiLayoutColumn(pa->layout, false);
- uiTemplateOperatorRedoProperties(col, C);
-}
-
-void topbar_panels_register(ARegionType *art)
-{
- PanelType *pt;
-
- pt = MEM_callocN(sizeof(PanelType), __func__);
- strcpy(pt->idname, "TOPBAR_PT_redo");
- strcpy(pt->label, N_("Redo"));
- strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
- pt->draw = topbar_panel_operator_redo;
- pt->poll = topbar_panel_operator_redo_poll;
- pt->space_type = SPACE_TOPBAR;
- pt->region_type = RGN_TYPE_HEADER;
- BLI_addtail(&art->paneltypes, pt);
-}
-
-/** \} */
diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c
index b3f45de518b..1d3c24c518a 100644
--- a/source/blender/editors/space_userpref/space_userpref.c
+++ b/source/blender/editors/space_userpref/space_userpref.c
@@ -64,7 +64,7 @@ static SpaceLink *userpref_new(const ScrArea *UNUSED(area), const Scene *UNUSED(
BLI_addtail(&spref->regionbase, ar);
ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = RGN_ALIGN_TOP;
+ ar->alignment = RGN_ALIGN_BOTTOM;
/* main region */
ar = MEM_callocN(sizeof(ARegion), "main region for userpref");
@@ -113,7 +113,7 @@ static void userpref_main_region_init(wmWindowManager *wm, ARegion *ar)
static void userpref_main_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
static void userpref_operatortypes(void)
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 63d7d98b689..d77b13630e3 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -296,8 +296,10 @@ void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *sa)
ARegion *ar;
for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiondata)
+ if ((ar->regiontype == RGN_TYPE_WINDOW) && ar->regiondata) {
ED_view3d_stop_render_preview(wm, ar);
+ break;
+ }
}
}
}
@@ -820,7 +822,6 @@ static void view3d_main_region_listener(
break;
case ND_OB_ACTIVE:
case ND_OB_SELECT:
- DEG_id_tag_update((ID *)&scene->id, DEG_TAG_SELECT_UPDATE);
ATTR_FALLTHROUGH;
case ND_FRAME:
case ND_TRANSFORM:
@@ -875,18 +876,6 @@ static void view3d_main_region_listener(
case ND_SELECT:
{
WM_manipulatormap_tag_refresh(mmap);
-
- ID *ob_data = wmn->reference;
- if (ob_data == NULL) {
- BLI_assert(wmn->window); // Use `WM_event_add_notifier` instead of `WM_main_add_notifier`
- ViewLayer *view_layer = WM_window_get_active_view_layer(wmn->window);
- ob_data = OBEDIT_FROM_VIEW_LAYER(view_layer)->data;
- }
- if (ob_data) {
- BLI_assert(OB_DATA_SUPPORT_ID(GS(ob_data->name)));
- /* TODO(sergey): Notifiers shouldn't really be doing DEG tags. */
- DEG_id_tag_update(ob_data, DEG_TAG_SELECT_UPDATE);
- }
ATTR_FALLTHROUGH;
}
case ND_DATA:
@@ -1232,7 +1221,7 @@ static void view3d_buttons_region_init(wmWindowManager *wm, ARegion *ar)
static void view3d_buttons_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
static void view3d_buttons_region_listener(
@@ -1361,7 +1350,7 @@ static void view3d_tools_region_init(wmWindowManager *wm, ARegion *ar)
static void view3d_tools_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, (const char * []){CTX_data_mode_string(C), NULL}, -1, true);
+ ED_region_panels_ex(C, ar, (const char * []){CTX_data_mode_string(C), NULL}, -1, true);
}
/* area (not region) level listener */
@@ -1565,5 +1554,9 @@ void ED_spacetype_view3d(void)
art->message_subscribe = view3d_header_region_message_subscribe;
BLI_addhead(&st->regiontypes, art);
+ /* regions: hud */
+ art = ED_area_type_hud(st->spaceid);
+ BLI_addhead(&st->regiontypes, art);
+
BKE_spacetype_register(st);
}
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index 69e8aa07d3f..6ebed88728e 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -69,6 +69,7 @@
#include "RNA_access.h"
#include "ED_armature.h"
+#include "ED_object.h"
#include "ED_mesh.h"
#include "ED_screen.h"
@@ -1163,6 +1164,11 @@ static void view3d_panel_transform(const bContext *C, Panel *pa)
}
}
+static void hide_collections_menu_draw(const bContext *C, Menu *menu)
+{
+ ED_hide_collections_menu_draw(C, menu->layout);
+}
+
void view3d_buttons_register(ARegionType *art)
{
PanelType *pt;
@@ -1182,6 +1188,15 @@ void view3d_buttons_register(ARegionType *art)
pt->draw = view3d_panel_vgroup;
pt->poll = view3d_panel_vgroup_poll;
BLI_addtail(&art->paneltypes, pt);
+
+ MenuType *mt;
+
+ mt = MEM_callocN(sizeof(MenuType), "spacetype view3d menu collections");
+ strcpy(mt->idname, "VIEW3D_MT_collection");
+ strcpy(mt->label, N_("Collection"));
+ strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ mt->draw = hide_collections_menu_draw;
+ WM_menutype_add(mt);
}
static int view3d_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
@@ -1197,7 +1212,7 @@ static int view3d_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
void VIEW3D_OT_properties(wmOperatorType *ot)
{
- ot->name = "Properties";
+ ot->name = "Toggle Sidebar";
ot->description = "Toggle the properties region visibility";
ot->idname = "VIEW3D_OT_properties";
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index cdf2106d8bf..bae186097a8 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -1112,7 +1112,6 @@ static void view3d_ndof_pan_zoom(
static void view3d_ndof_orbit(
const struct wmNDOFMotionData *ndof, ScrArea *sa, ARegion *ar,
- /* optional, can be NULL*/
ViewOpsData *vod, const bool apply_dyn_ofs)
{
View3D *v3d = sa->spacedata.first;
@@ -1445,7 +1444,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
ED_view3d_distance_set(rv3d, 0.0f);
if (has_rotation) {
- view3d_ndof_orbit(ndof, vod->sa, vod->ar, NULL, false);
+ view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, false);
}
ED_view3d_distance_set(rv3d, dist_backup);
@@ -1812,7 +1811,7 @@ static void view_zoom_to_window_xy_camera(
{
RegionView3D *rv3d = ar->regiondata;
const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom);
- const float zoomfac_new = CLAMPIS(zoomfac * (1.0f / dfac), RV3D_CAMZOOM_MIN_FACTOR, RV3D_CAMZOOM_MAX_FACTOR);
+ const float zoomfac_new = clamp_f(zoomfac * (1.0f / dfac), RV3D_CAMZOOM_MIN_FACTOR, RV3D_CAMZOOM_MAX_FACTOR);
const float camzoom_new = BKE_screen_view3d_zoom_from_fac(zoomfac_new);
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_camera.c b/source/blender/editors/space_view3d/view3d_manipulator_camera.c
index 49fa83e82fc..023e16c070e 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_camera.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_camera.c
@@ -109,7 +109,7 @@ static void WIDGETGROUP_camera_setup(const bContext *C, wmManipulatorGroup *mgro
mpr = camgroup->focal_len = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL);
mpr->flag |= WM_MANIPULATOR_DRAW_NO_SCALE;
RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_ARROW_STYLE_CONE);
- RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED);
+ RNA_enum_set(mpr->ptr, "transform", ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED);
UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color);
UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi);
@@ -117,7 +117,7 @@ static void WIDGETGROUP_camera_setup(const bContext *C, wmManipulatorGroup *mgro
mpr = camgroup->ortho_scale = WM_manipulator_new_ptr(wt_arrow, mgroup, NULL);
mpr->flag |= WM_MANIPULATOR_DRAW_NO_SCALE;
RNA_enum_set(mpr->ptr, "draw_style", ED_MANIPULATOR_ARROW_STYLE_CONE);
- RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED);
+ RNA_enum_set(mpr->ptr, "transform", ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED);
UI_GetThemeColor3fv(TH_MANIPULATOR_PRIMARY, mpr->color);
UI_GetThemeColor3fv(TH_MANIPULATOR_HI, mpr->color_hi);
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c b/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c
index 2a1fdee8e8a..305085be370 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_forcefield.c
@@ -72,7 +72,7 @@ static void WIDGETGROUP_forcefield_setup(const bContext *UNUSED(C), wmManipulato
wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_arrow_3d", mgroup, NULL);
wmManipulator *mpr = wwrapper->manipulator;
- RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_CONSTRAINED);
+ RNA_enum_set(mpr->ptr, "transform", ED_MANIPULATOR_ARROW_XFORM_FLAG_CONSTRAINED);
ED_manipulator_arrow3d_set_ui_range(mpr, -200.0f, 200.0f);
ED_manipulator_arrow3d_set_range_fac(mpr, 6.0f);
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_lamp.c b/source/blender/editors/space_view3d/view3d_manipulator_lamp.c
index 01c38cfd899..f98a2f336bc 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_lamp.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_lamp.c
@@ -74,7 +74,7 @@ static void WIDGETGROUP_lamp_spot_setup(const bContext *UNUSED(C), wmManipulator
wwrapper->manipulator = WM_manipulator_new("MANIPULATOR_WT_arrow_3d", mgroup, NULL);
wmManipulator *mpr = wwrapper->manipulator;
- RNA_enum_set(mpr->ptr, "draw_options", ED_MANIPULATOR_ARROW_STYLE_INVERTED);
+ RNA_enum_set(mpr->ptr, "transform", ED_MANIPULATOR_ARROW_XFORM_FLAG_INVERTED);
mgroup->customdata = wwrapper;
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_navigate.c b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
index c869e23d552..22b7af48de6 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
@@ -51,13 +51,13 @@
* \{ */
/* Offset from screen edge. */
-#define MANIPULATOR_OFFSET_FAC 2.5
+#define MANIPULATOR_OFFSET_FAC 1.5f
/* Size of main icon. */
#define MANIPULATOR_SIZE 64
/* Factor for size of smaller button. */
-#define MANIPULATOR_MINI_FAC 0.5
+#define MANIPULATOR_MINI_FAC 0.35f
/* How much mini buttons offset from the primary. */
-#define MANIPULATOR_MINI_OFFSET_FAC 0.6666f
+#define MANIPULATOR_MINI_OFFSET_FAC 0.42f
enum {
@@ -297,10 +297,21 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmManipulatorGr
navgroup->state.rv3d.is_camera = (rv3d->persp == RV3D_CAMOB);
navgroup->state.rv3d.viewlock = rv3d->viewlock;
+ const bool show_rotate = (
+ ((rv3d->viewlock & RV3D_LOCKED) == 0) &&
+ (navgroup->state.rv3d.is_camera == false));
+ const bool show_fixed_offset = navgroup->state.rv3d.is_camera;
const float icon_size = MANIPULATOR_SIZE;
- const float icon_offset = (icon_size / 2.0) * MANIPULATOR_OFFSET_FAC * UI_DPI_FAC;
+ const float icon_offset = (icon_size * 0.52f) * MANIPULATOR_OFFSET_FAC * UI_DPI_FAC;
const float icon_offset_mini = icon_size * MANIPULATOR_MINI_OFFSET_FAC * UI_DPI_FAC;
- const float co[2] = {rect_visible.xmax - icon_offset, rect_visible.ymax - icon_offset};
+ const float co_rotate[2] = {
+ rect_visible.xmax - icon_offset,
+ rect_visible.ymax - icon_offset,
+ };
+ const float co[2] = {
+ rect_visible.xmax - ((show_rotate || show_fixed_offset) ? (icon_offset * 2.0f) : (icon_offset_mini * 0.75f)),
+ rect_visible.ymax - icon_offset_mini * 0.75f,
+ };
wmManipulator *mpr;
@@ -309,48 +320,36 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmManipulatorGr
WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true);
}
- if (((rv3d->viewlock & RV3D_LOCKED) == 0) && (navgroup->state.rv3d.is_camera == false)) {
+ /* RV3D_LOCKED or Camera: only show supported buttons. */
+ if (show_rotate) {
mpr = navgroup->mpr_array[MPR_ROTATE];
- mpr->matrix_basis[3][0] = co[0];
- mpr->matrix_basis[3][1] = co[1];
+ mpr->matrix_basis[3][0] = co_rotate[0];
+ mpr->matrix_basis[3][1] = co_rotate[1];
WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+ }
- mpr = navgroup->mpr_array[MPR_MOVE];
- mpr->matrix_basis[3][0] = co[0] + icon_offset_mini;
- mpr->matrix_basis[3][1] = co[1] - icon_offset_mini;
- WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+ int icon_mini_slot = 0;
- mpr = navgroup->mpr_array[MPR_ZOOM];
- mpr->matrix_basis[3][0] = co[0] - icon_offset_mini;
- mpr->matrix_basis[3][1] = co[1] - icon_offset_mini;
- WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+ mpr = navgroup->mpr_array[MPR_ZOOM];
+ mpr->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
+ mpr->matrix_basis[3][1] = co[1];
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
- mpr = navgroup->mpr_array[rv3d->is_persp ? MPR_ORTHO : MPR_PERSP];
- mpr->matrix_basis[3][0] = co[0] + icon_offset_mini;
- mpr->matrix_basis[3][1] = co[1] + icon_offset_mini;
- WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+ mpr = navgroup->mpr_array[MPR_MOVE];
+ mpr->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
+ mpr->matrix_basis[3][1] = co[1];
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+ if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
mpr = navgroup->mpr_array[MPR_CAMERA];
- mpr->matrix_basis[3][0] = co[0] - icon_offset_mini;
- mpr->matrix_basis[3][1] = co[1] + icon_offset_mini;
- WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
- }
- else {
- /* RV3D_LOCKED or Camera: only show supported buttons. */
- mpr = navgroup->mpr_array[MPR_MOVE];
- mpr->matrix_basis[3][0] = co[0] + icon_offset_mini;
- mpr->matrix_basis[3][1] = co[1] + icon_offset_mini;
- WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
-
- mpr = navgroup->mpr_array[MPR_ZOOM];
- mpr->matrix_basis[3][0] = co[0];
- mpr->matrix_basis[3][1] = co[1] + icon_offset_mini;
+ mpr->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
+ mpr->matrix_basis[3][1] = co[1];
WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
- if (navgroup->state.rv3d.is_camera) {
- mpr = navgroup->mpr_array[MPR_CAMERA];
- mpr->matrix_basis[3][0] = co[0] - icon_offset_mini;
- mpr->matrix_basis[3][1] = co[1] + icon_offset_mini;
+ if (navgroup->state.rv3d.is_camera == false) {
+ mpr = navgroup->mpr_array[rv3d->is_persp ? MPR_PERSP : MPR_ORTHO];
+ mpr->matrix_basis[3][0] = co[0] - (icon_offset_mini * icon_mini_slot++);
+ mpr->matrix_basis[3][1] = co[1];
WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
}
}
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c
index cd918695f60..8178c2f5be9 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c
@@ -382,6 +382,7 @@ static bool view3d_ruler_item_mousemove(
static bool view3d_ruler_to_gpencil(bContext *C, wmManipulatorGroup *mgroup)
{
// RulerInfo *ruler_info = mgroup->customdata;
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
bGPDlayer *gpl;
bGPDframe *gpf;
@@ -393,7 +394,7 @@ static bool view3d_ruler_to_gpencil(bContext *C, wmManipulatorGroup *mgroup)
bool changed = false;
if (scene->gpd == NULL) {
- scene->gpd = BKE_gpencil_data_addnew("GPencil");
+ scene->gpd = BKE_gpencil_data_addnew(bmain, "GPencil");
}
gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info));
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index b3211ed1108..267712b3339 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -302,7 +302,7 @@ void view3d_keymap(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_view_all", CKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "center", true);
- WM_keymap_add_menu_pie(keymap, "VIEW3D_PIE_view", ACCENTGRAVEKEY, KM_CLICK_DRAG, 0, 0);
+ WM_keymap_add_menu_pie(keymap, "VIEW3D_MT_view_pie", ACCENTGRAVEKEY, KM_CLICK_DRAG, 0, 0);
/* numpad view hotkeys*/
RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD0, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_CAMERA);
diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c
index c30b72bfb95..e001ed9112b 100644
--- a/source/blender/editors/space_view3d/view3d_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_ruler.c
@@ -297,6 +297,7 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state)
#define RULER_ID "RulerData3D"
static bool view3d_ruler_to_gpencil(bContext *C, RulerInfo *ruler_info)
{
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
bGPDlayer *gpl;
bGPDframe *gpf;
@@ -308,7 +309,7 @@ static bool view3d_ruler_to_gpencil(bContext *C, RulerInfo *ruler_info)
bool changed = false;
if (scene->gpd == NULL) {
- scene->gpd = BKE_gpencil_data_addnew("GPencil");
+ scene->gpd = BKE_gpencil_data_addnew(bmain, "GPencil");
}
gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info));
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index f4e39c7a563..b4f3be178aa 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -424,10 +424,8 @@ static void do_lasso_select_objects(
for (base = vc->view_layer->object_bases.first; base; base = base->next) {
if (BASE_SELECTABLE(base)) { /* use this to avoid un-needed lasso lookups */
- if (
-#ifdef USE_OBJECT_MODE_STRICT
- (is_pose_mode == false) &&
-#endif
+ if (((vc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ?
+ (is_pose_mode == false) : true) &&
ED_view3d_project_base(vc->ar, base) == V3D_PROJ_RET_OK)
{
if (BLI_lasso_is_point_inside(mcords, moves, base->sx, base->sy, IS_CLIPPED)) {
@@ -855,6 +853,7 @@ static void view3d_lasso_select(
}
else {
do_lasso_select_objects(vc, mcords, moves, extend, select);
+ DEG_id_tag_update(&vc->scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene);
}
}
@@ -885,6 +884,7 @@ static void view3d_lasso_select(
break;
}
+ DEG_id_tag_update(vc->obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc->obedit->data);
}
FOREACH_OBJECT_IN_MODE_END;
@@ -1009,7 +1009,9 @@ static int object_select_menu_exec(bContext *C, wmOperator *op)
/* undo? */
if (changed) {
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
+ Scene *scene = CTX_data_scene(C);
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
return OPERATOR_FINISHED;
}
else {
@@ -1170,7 +1172,7 @@ static int selectbuffer_ret_hits_5(unsigned int *buffer, const int hits15, const
/* so check three selection levels and compare */
static int mixed_bones_object_selectbuffer(
ViewContext *vc, unsigned int *buffer, const int mval[2],
- bool use_cycle, bool enumerate,
+ bool use_cycle, bool enumerate, eV3DSelectObjectFilter select_filter,
bool *r_do_nearest)
{
rcti rect;
@@ -1209,7 +1211,7 @@ static int mixed_bones_object_selectbuffer(
view3d_opengl_select_cache_begin();
BLI_rcti_init_pt_radius(&rect, mval, 14);
- hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode);
+ hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter);
if (hits15 == 1) {
hits = selectbuffer_ret_hits_15(buffer, hits15);
goto finally;
@@ -1220,7 +1222,7 @@ static int mixed_bones_object_selectbuffer(
offs = 4 * hits15;
BLI_rcti_init_pt_radius(&rect, mval, 9);
- hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode);
+ hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode, select_filter);
if (hits9 == 1) {
hits = selectbuffer_ret_hits_9(buffer, hits15, hits9);
goto finally;
@@ -1230,7 +1232,7 @@ static int mixed_bones_object_selectbuffer(
offs += 4 * hits9;
BLI_rcti_init_pt_radius(&rect, mval, 5);
- hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode);
+ hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode, select_filter);
if (hits5 == 1) {
hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5);
goto finally;
@@ -1252,8 +1254,7 @@ static int mixed_bones_object_selectbuffer(
finally:
view3d_opengl_select_cache_end();
-#ifdef USE_OBJECT_MODE_STRICT
- {
+ if (vc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
const bool is_pose_mode = (vc->obact && vc->obact->mode & OB_MODE_POSE);
struct {
uint data[4];
@@ -1269,7 +1270,6 @@ finally:
}
hits = j;
}
-#endif
return hits;
}
@@ -1373,7 +1373,10 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2])
ED_view3d_viewcontext_init(C, &vc);
- hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, false, false, &do_nearest);
+ hits = mixed_bones_object_selectbuffer(
+ &vc, buffer, mval,
+ false, false, VIEW3D_SELECT_FILTER_NOP,
+ &do_nearest);
if (hits > 0) {
const bool has_bones = selectbuffer_has_bones(buffer, hits);
@@ -1466,19 +1469,19 @@ static bool ed_object_select_pick(
if (base == startbase) break;
}
}
-#ifdef USE_OBJECT_MODE_STRICT
- if (is_obedit == false) {
- if (basact && !BKE_object_is_mode_compat(basact->object, object_mode)) {
- if (object_mode == OB_MODE_OBJECT) {
- struct Main *bmain = CTX_data_main(C);
- ED_object_mode_generic_exit(bmain, vc.depsgraph, scene, basact->object);
- }
- if (!BKE_object_is_mode_compat(basact->object, object_mode)) {
- basact = NULL;
+ if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
+ if (is_obedit == false) {
+ if (basact && !BKE_object_is_mode_compat(basact->object, object_mode)) {
+ if (object_mode == OB_MODE_OBJECT) {
+ struct Main *bmain = CTX_data_main(C);
+ ED_object_mode_generic_exit(bmain, vc.depsgraph, scene, basact->object);
+ }
+ if (!BKE_object_is_mode_compat(basact->object, object_mode)) {
+ basact = NULL;
+ }
}
}
}
-#endif
}
else {
unsigned int buffer[MAXPICKBUF];
@@ -1487,7 +1490,13 @@ static bool ed_object_select_pick(
// TIMEIT_START(select_time);
/* if objects have posemode set, the bones are in the same selection buffer */
- hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, true, enumerate, &do_nearest);
+ const eV3DSelectObjectFilter select_filter = (
+ (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ?
+ VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK : VIEW3D_SELECT_FILTER_NOP);
+ hits = mixed_bones_object_selectbuffer(
+ &vc, buffer, mval,
+ true, enumerate, select_filter,
+ &do_nearest);
// TIMEIT_END(select_time);
@@ -1503,19 +1512,19 @@ static bool ed_object_select_pick(
basact = mouse_select_eval_buffer(&vc, buffer, hits, startbase, has_bones, do_nearest);
}
-#ifdef USE_OBJECT_MODE_STRICT
- if (is_obedit == false) {
- if (basact && !BKE_object_is_mode_compat(basact->object, object_mode)) {
- if (object_mode == OB_MODE_OBJECT) {
- struct Main *bmain = CTX_data_main(C);
- ED_object_mode_generic_exit(bmain, vc.depsgraph, scene, basact->object);
- }
- if (!BKE_object_is_mode_compat(basact->object, object_mode)) {
- basact = NULL;
+ if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
+ if (is_obedit == false) {
+ if (basact && !BKE_object_is_mode_compat(basact->object, object_mode)) {
+ if (object_mode == OB_MODE_OBJECT) {
+ struct Main *bmain = CTX_data_main(C);
+ ED_object_mode_generic_exit(bmain, vc.depsgraph, scene, basact->object);
+ }
+ if (!BKE_object_is_mode_compat(basact->object, object_mode)) {
+ basact = NULL;
+ }
}
}
}
-#endif
if (has_bones && basact) {
if (basact->object->type == OB_CAMERA) {
@@ -1562,6 +1571,7 @@ static bool ed_object_select_pick(
retval = true;
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, track);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
@@ -1604,19 +1614,19 @@ static bool ed_object_select_pick(
}
}
-#ifdef USE_OBJECT_MODE_STRICT
- /* Disallow switching modes,
- * special exception for edit-mode - vertex-parent operator. */
- if (is_obedit == false) {
- if (oldbasact && basact) {
- if ((oldbasact->object->mode != basact->object->mode) &&
- (oldbasact->object->mode & basact->object->mode) == 0)
- {
- basact = NULL;
+ if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
+ /* Disallow switching modes,
+ * special exception for edit-mode - vertex-parent operator. */
+ if (is_obedit == false) {
+ if (oldbasact && basact) {
+ if ((oldbasact->object->mode != basact->object->mode) &&
+ (oldbasact->object->mode & basact->object->mode) == 0)
+ {
+ basact = NULL;
+ }
}
}
}
-#endif
/* so, do we have something selected? */
if (basact) {
@@ -1658,6 +1668,7 @@ static bool ed_object_select_pick(
}
}
+ DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
@@ -1966,7 +1977,9 @@ static int do_meta_box_select(
unsigned int buffer[MAXPICKBUF];
int hits;
- hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL);
+ hits = view3d_opengl_select(
+ vc, buffer, MAXPICKBUF, rect,
+ VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
if (extend == false && select)
BKE_mball_deselect_all(mb);
@@ -2000,7 +2013,9 @@ static int do_armature_box_select(
unsigned int buffer[MAXPICKBUF];
int hits;
- hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL);
+ hits = view3d_opengl_select(
+ vc, buffer, MAXPICKBUF, rect,
+ VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(vc->view_layer, &objects_len);
@@ -2148,7 +2163,12 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b
/* selection buffer now has bones potentially too, so we add MAXPICKBUF */
vbuffer = MEM_mallocN(4 * (totobj + MAXPICKELEMS) * sizeof(unsigned int), "selection buffer");
- hits = view3d_opengl_select(vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL);
+ const eV3DSelectObjectFilter select_filter = (
+ (vc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) ?
+ VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK : VIEW3D_SELECT_FILTER_NOP);
+ hits = view3d_opengl_select(
+ vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect,
+ VIEW3D_SELECT_ALL, select_filter);
/*
* LOGIC NOTES (theeth):
* The buffer and ListBase have the same relative order, which makes the selection
@@ -2241,6 +2261,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b
MEM_freeN(bases);
+ DEG_id_tag_update(&vc->scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene);
}
MEM_freeN(vbuffer);
@@ -2276,6 +2297,7 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
vc.em = BKE_editmesh_from_object(vc.obedit);
ret |= do_mesh_box_select(&vc, &rect, select, extend);
if (ret & OPERATOR_FINISHED) {
+ DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
}
break;
@@ -2283,24 +2305,28 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
case OB_SURF:
ret |= do_nurbs_box_select(&vc, &rect, select, extend);
if (ret & OPERATOR_FINISHED) {
+ DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
}
break;
case OB_MBALL:
ret |= do_meta_box_select(&vc, &rect, select, extend);
if (ret & OPERATOR_FINISHED) {
+ DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
}
break;
case OB_ARMATURE:
ret |= do_armature_box_select(&vc, &rect, select, extend);
if (ret & OPERATOR_FINISHED) {
+ DEG_id_tag_update(&vc.obedit->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, vc.obedit);
}
break;
case OB_LATTICE:
ret |= do_lattice_box_select(&vc, &rect, select, extend);
if (ret & OPERATOR_FINISHED) {
+ DEG_id_tag_update(vc.obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
}
break;
@@ -2403,6 +2429,7 @@ static bool ed_wpaint_vertex_select_pick(
}
paintvert_flush_flags(obact);
+ DEG_id_tag_update(obact->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
return true;
}
@@ -3004,14 +3031,17 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
if (CTX_data_edit_object(C)) {
obedit_circle_select(&vc, select, mval, (float)radius);
+ DEG_id_tag_update(obact->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
}
else if (BKE_paint_select_face_test(obact)) {
paint_facesel_circle_select(&vc, select, mval, (float)radius);
+ DEG_id_tag_update(obact->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
}
else if (BKE_paint_select_vert_test(obact)) {
paint_vertsel_circle_select(&vc, select, mval, (float)radius);
+ DEG_id_tag_update(obact->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
}
else if (obact->mode & OB_MODE_POSE) {
@@ -3028,6 +3058,7 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
}
else {
if (object_circle_select(&vc, select, mval, (float)radius)) {
+ DEG_id_tag_update(&vc.scene->id, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc.scene);
}
}
diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c
index 8ea33927c4d..acceb40beaa 100644
--- a/source/blender/editors/space_view3d/view3d_toolbar.c
+++ b/source/blender/editors/space_view3d/view3d_toolbar.c
@@ -190,7 +190,7 @@ static int view3d_toolshelf_toggle_exec(bContext *C, wmOperator *UNUSED(op))
void VIEW3D_OT_toolshelf(wmOperatorType *ot)
{
- ot->name = "Tool Shelf";
+ ot->name = "Toggle Toolbar";
ot->description = "Toggles tool shelf display";
ot->idname = "VIEW3D_OT_toolshelf";
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 73b9a67ac56..abb8c688e05 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -896,6 +896,13 @@ static bool drw_select_loop_pass(eDRWSelectStage stage, void *user_data)
}
#endif /* WITH_OPENGL_LEGACY */
+/** Implement #VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK. */
+static bool drw_select_filter_object_mode_lock(Object *ob, void *user_data)
+{
+ const Object *obact = user_data;
+ return BKE_object_is_mode_compat(ob, obact->mode);
+}
+
/**
* \warning be sure to account for a negative return value
* This is an error, "Too many objects in select buffer"
@@ -905,7 +912,7 @@ static bool drw_select_loop_pass(eDRWSelectStage stage, void *user_data)
*/
int view3d_opengl_select(
ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const rcti *input,
- eV3DSelectMode select_mode)
+ eV3DSelectMode select_mode, eV3DSelectObjectFilter select_filter)
{
struct bThemeState theme_state;
Depsgraph *depsgraph = vc->depsgraph;
@@ -953,6 +960,25 @@ int view3d_opengl_select(
}
}
+ struct {
+ DRW_ObjectFilterFn fn;
+ void *user_data;
+ } object_filter = {NULL, NULL};
+ switch (select_filter) {
+ case VIEW3D_SELECT_FILTER_OBJECT_MODE_LOCK:
+ {
+ Object *obact = OBACT(vc->view_layer);
+ if (obact && obact->mode != OB_MODE_OBJECT) {
+ object_filter.fn = drw_select_filter_object_mode_lock;
+ object_filter.user_data = obact;
+ }
+ break;
+ }
+ case VIEW3D_SELECT_FILTER_NOP:
+ break;
+
+ }
+
/* Tools may request depth outside of regular drawing code. */
UI_Theme_Store(&theme_state);
UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
@@ -1014,7 +1040,8 @@ int view3d_opengl_select(
DRW_draw_select_loop(
depsgraph, ar, v3d,
use_obedit_skip, use_nearest, &rect,
- drw_select_loop_pass, &drw_select_loop_user_data);
+ drw_select_loop_pass, &drw_select_loop_user_data,
+ object_filter.fn, object_filter.user_data);
hits = drw_select_loop_user_data.hits;
}
#endif /* WITH_OPENGL_LEGACY */
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index c2548fe497f..d72d311e0f6 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -65,6 +65,7 @@ struct wmEvent;
struct wmTimer;
struct ARegion;
struct ReportList;
+struct RNG;
struct EditBone;
struct RenderEngineType;
struct SnapObjectContext;
@@ -536,6 +537,9 @@ typedef struct TransInfo {
void *draw_handle_pixel;
void *draw_handle_cursor;
+ /** Currently only used for random curve of proportional editing. */
+ struct RNG *rng;
+
/** Typically for mode settings. */
TransCustomDataContainer custom;
} TransInfo;
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 6c608a0b5e4..8462004c549 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -1255,7 +1255,7 @@ static void createTransArmatureVerts(TransInfo *t)
bool mirror = ((arm->flag & ARM_MIRROR_EDIT) != 0);
int total_mirrored = 0, i;
int oldtot;
- BoneInitData *bid;
+ BoneInitData *bid = NULL;
tc->data_len = 0;
for (ebo = edbo->first; ebo; ebo = ebo->next) {
@@ -2120,7 +2120,6 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
void flushTransParticles(TransInfo *t)
{
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
-
Scene *scene = t->scene;
ViewLayer *view_layer = t->view_layer;
Object *ob = OBACT(view_layer);
@@ -8633,6 +8632,10 @@ void createTransData(bContext *C, TransInfo *t)
createTransPaintCurveVerts(C, t);
countAndCleanTransDataContainer(t);
}
+ /* Mark as initialized if above checks fail. */
+ if (t->data_len_all == -1) {
+ t->data_len_all = 0;
+ }
}
else {
createTransObject(C, t);
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 8bef63dba1a..053647cbfea 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -58,6 +58,8 @@
#include "BLI_rand.h"
#include "BLI_utildefines.h"
+#include "PIL_time.h"
+
#include "BLT_translation.h"
#include "RNA_access.h"
@@ -74,6 +76,7 @@
#include "BKE_fcurve.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
+#include "BKE_main.h"
#include "BKE_nla.h"
#include "BKE_context.h"
#include "BKE_paint.h"
@@ -1695,6 +1698,10 @@ void postTrans(bContext *C, TransInfo *t)
MEM_freeN(t->mouse.data);
}
+ if (t->rng != NULL) {
+ BLI_rng_free(t->rng);
+ }
+
freeSnapping(t);
}
@@ -2163,7 +2170,12 @@ void calculatePropRatio(TransInfo *t)
td->factor = sqrtf(2 * dist - dist * dist);
break;
case PROP_RANDOM:
- td->factor = BLI_frand() * dist;
+ if (t->rng == NULL) {
+ /* Lazy initialization. */
+ uint rng_seed = (uint)(PIL_check_seconds_timer_i() & UINT_MAX);
+ t->rng = BLI_rng_new(rng_seed);
+ }
+ td->factor = BLI_rng_get_float(t->rng) * dist;
break;
case PROP_INVSQUARE:
td->factor = dist * (2.0f - dist);
diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c
index 270ef08be50..5b5c4902377 100644
--- a/source/blender/editors/transform/transform_input.c
+++ b/source/blender/editors/transform/transform_input.c
@@ -375,8 +375,11 @@ void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode)
MEM_freeN(mi_data_prev);
}
- /* bootstrap mouse input with initial values */
- applyMouseInput(t, mi, mi->imval, t->values);
+ /* Don't write into the values when non-modal because they are already set from operator redo values. */
+ if (t->flag & T_MODAL) {
+ /* bootstrap mouse input with initial values */
+ applyMouseInput(t, mi, mi->imval, t->values);
+ }
}
void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *t, float values[3]))
diff --git a/source/blender/editors/transform/transform_manipulator_3d.c b/source/blender/editors/transform/transform_manipulator_3d.c
index b6782470f96..75da0fc2d23 100644
--- a/source/blender/editors/transform/transform_manipulator_3d.c
+++ b/source/blender/editors/transform/transform_manipulator_3d.c
@@ -107,8 +107,15 @@
#define MAN_SCALE_C (MAN_SCALE_X | MAN_SCALE_Y | MAN_SCALE_Z)
/* threshold for testing view aligned manipulator axis */
-#define TW_AXIS_DOT_MIN 0.02f
-#define TW_AXIS_DOT_MAX 0.1f
+struct {
+ float min, max;
+} g_tw_axis_range[2] = {
+ /* Regular range */
+ {0.02f, 0.1f},
+ /* Use a different range because we flip the dot product,
+ * also the view aligned planes are harder to see so hiding early is preferred. */
+ {0.175f, 0.25f},
+};
/* axes as index */
enum {
@@ -247,16 +254,18 @@ static bool manipulator_is_axis_visible(
const RegionView3D *rv3d, const int twtype,
const float idot[3], const int axis_type, const int axis_idx)
{
- bool is_plane = false;
- const uint aidx_norm = manipulator_orientation_axis(axis_idx, &is_plane);
- /* don't draw axis perpendicular to the view */
- if (aidx_norm < 3) {
- float idot_axis = idot[aidx_norm];
- if (is_plane) {
- idot_axis = 1.0f - idot_axis;
- }
- if (idot_axis < TW_AXIS_DOT_MIN) {
- return false;
+ if ((axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END) == 0) {
+ bool is_plane = false;
+ const uint aidx_norm = manipulator_orientation_axis(axis_idx, &is_plane);
+ /* don't draw axis perpendicular to the view */
+ if (aidx_norm < 3) {
+ float idot_axis = idot[aidx_norm];
+ if (is_plane) {
+ idot_axis = 1.0f - idot_axis;
+ }
+ if (idot_axis < g_tw_axis_range[is_plane].min) {
+ return false;
+ }
}
}
@@ -333,22 +342,31 @@ static void manipulator_get_axis_color(
const float alpha_hi = 1.0f;
float alpha_fac;
- bool is_plane = false;
- const int axis_idx_norm = manipulator_orientation_axis(axis_idx, &is_plane);
- /* get alpha fac based on axis angle, to fade axis out when hiding it because it points towards view */
- if (axis_idx_norm < 3) {
- float idot_axis = idot[axis_idx_norm];
- if (is_plane) {
- idot_axis = 1.0f - idot_axis;
- }
- alpha_fac = (idot_axis > TW_AXIS_DOT_MAX) ?
- 1.0f : (idot_axis < TW_AXIS_DOT_MIN) ?
- 0.0f : ((idot_axis - TW_AXIS_DOT_MIN) / (TW_AXIS_DOT_MAX - TW_AXIS_DOT_MIN));
- }
- else {
+ if (axis_idx >= MAN_AXIS_RANGE_ROT_START && axis_idx < MAN_AXIS_RANGE_ROT_END) {
+ /* Never fade rotation rings. */
/* trackball rotation axis is a special case, we only draw a slight overlay */
alpha_fac = (axis_idx == MAN_AXIS_ROT_T) ? 0.1f : 1.0f;
}
+ else {
+ bool is_plane = false;
+ const int axis_idx_norm = manipulator_orientation_axis(axis_idx, &is_plane);
+ /* get alpha fac based on axis angle, to fade axis out when hiding it because it points towards view */
+ if (axis_idx_norm < 3) {
+ const float idot_min = g_tw_axis_range[is_plane].min;
+ const float idot_max = g_tw_axis_range[is_plane].max;
+ float idot_axis = idot[axis_idx_norm];
+ if (is_plane) {
+ idot_axis = 1.0f - idot_axis;
+ }
+ alpha_fac = (
+ (idot_axis > idot_max) ?
+ 1.0f : (idot_axis < idot_min) ?
+ 0.0f : ((idot_axis - idot_min) / (idot_max - idot_min)));
+ }
+ else {
+ alpha_fac = 1.0f;
+ }
+ }
switch (axis_idx) {
case MAN_AXIS_TRANS_X:
@@ -1238,9 +1256,14 @@ static ManipulatorGroup *manipulatorgroup_init(wmManipulatorGroup *mgroup)
* Custom handler for manipulator widgets
*/
static int manipulator_modal(
- bContext *C, wmManipulator *widget, const wmEvent *UNUSED(event),
+ bContext *C, wmManipulator *widget, const wmEvent *event,
eWM_ManipulatorTweak UNUSED(tweak_flag))
{
+ /* Avoid unnecessary updates, partially address: T55458. */
+ if (ELEM(event->type, TIMER, INBETWEEN_MOUSEMOVE)) {
+ return OPERATOR_RUNNING_MODAL;
+ }
+
const ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
View3D *v3d = sa->spacedata.first;
@@ -1315,6 +1338,14 @@ static void WIDGETGROUP_manipulator_setup(const bContext *C, wmManipulatorGroup
case MAN_AXIS_SCALE_X:
case MAN_AXIS_SCALE_Y:
case MAN_AXIS_SCALE_Z:
+ if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) {
+ int draw_options = 0;
+ if ((man->twtype & (V3D_MANIP_ROTATE | V3D_MANIP_SCALE)) == 0) {
+ draw_options |= ED_MANIPULATOR_ARROW_DRAW_FLAG_STEM;
+ }
+ RNA_enum_set(axis->ptr, "draw_options", draw_options);
+ }
+
WM_manipulator_set_line_width(axis, MANIPULATOR_AXIS_LINE_WIDTH);
break;
case MAN_AXIS_ROT_X:
@@ -1348,6 +1379,7 @@ static void WIDGETGROUP_manipulator_setup(const bContext *C, wmManipulatorGroup
}
else if (axis_idx == MAN_AXIS_ROT_C) {
WM_manipulator_set_flag(axis, WM_MANIPULATOR_DRAW_VALUE, true);
+ WM_manipulator_set_scale(axis, 1.2f);
}
else {
WM_manipulator_set_scale(axis, 0.2f);
@@ -1447,6 +1479,13 @@ static void WIDGETGROUP_manipulator_refresh(const bContext *C, wmManipulatorGrou
WM_manipulator_set_matrix_rotation_from_z_axis(axis, rv3d->twmat[aidx_norm]);
RNA_float_set(axis->ptr, "length", len);
+
+ if (axis_idx >= MAN_AXIS_RANGE_TRANS_START && axis_idx < MAN_AXIS_RANGE_TRANS_END) {
+ if (man->twtype & V3D_MANIP_ROTATE) {
+ /* Avoid rotate and translate arrows overlap. */
+ start_co[2] += 0.215f;
+ }
+ }
WM_manipulator_set_matrix_offset_location(axis, start_co);
WM_manipulator_set_flag(axis, WM_MANIPULATOR_DRAW_OFFSET_SCALE, true);
break;
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 18d30db7a21..d98e3e3261a 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -45,6 +45,7 @@
#include "RNA_enum_types.h"
#include "WM_api.h"
+#include "WM_message.h"
#include "WM_types.h"
#include "UI_interface.h"
@@ -170,6 +171,9 @@ static int select_orientation_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL);
+ struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+ WM_msg_publish_rna_prop(mbus, &scene->id, scene, Scene, transform_orientation);
+
return OPERATOR_FINISHED;
}
@@ -537,7 +541,7 @@ void Transform_Properties(struct wmOperatorType *ot, int flags)
if (flags & P_PROPORTIONAL) {
RNA_def_enum(ot->srna, "proportional", rna_enum_proportional_editing_items, 0, "Proportional Editing", "");
prop = RNA_def_enum(ot->srna, "proportional_edit_falloff", rna_enum_proportional_falloff_items, 0,
- "Proportional Editing Falloff", "Falloff type for proportional editing mode");
+ "Proportional Falloff", "Falloff type for proportional editing mode");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */
RNA_def_float(ot->srna, "proportional_size", 1, T_PROP_SIZE_MIN, T_PROP_SIZE_MAX,
"Proportional Size", "", 0.001f, 100.0f);
@@ -563,17 +567,20 @@ void Transform_Properties(struct wmOperatorType *ot, int flags)
}
if (flags & P_GPENCIL_EDIT) {
- RNA_def_boolean(ot->srna, "gpencil_strokes", 0, "Edit Grease Pencil", "Edit selected Grease Pencil strokes");
+ prop = RNA_def_boolean(ot->srna, "gpencil_strokes", 0, "Edit Grease Pencil", "Edit selected Grease Pencil strokes");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
if (flags & P_CURSOR_EDIT) {
- RNA_def_boolean(ot->srna, "cursor_transform", 0, "Transform Cursor", "");
+ prop = RNA_def_boolean(ot->srna, "cursor_transform", 0, "Transform Cursor", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
if ((flags & P_OPTIONS) && !(flags & P_NO_TEXSPACE)) {
- RNA_def_boolean(ot->srna, "texture_space", 0, "Edit Texture Space", "Edit Object data texture space");
+ prop = RNA_def_boolean(ot->srna, "texture_space", 0, "Edit Texture Space", "Edit Object data texture space");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_boolean(ot->srna, "remove_on_cancel", 0, "Remove on Cancel", "Remove elements on cancel");
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
if (flags & P_CORRECT_UV) {
diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c
index d2ac346df10..478e004743d 100644
--- a/source/blender/editors/undo/ed_undo.c
+++ b/source/blender/editors/undo/ed_undo.c
@@ -148,15 +148,10 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
void ED_undo_grouped_push(bContext *C, const char *str)
{
/* do nothing if previous undo task is the same as this one (or from the same undo group) */
- {
- wmWindowManager *wm = CTX_wm_manager(C);
- if (wm->undo_stack->steps.last) {
- const UndoStep *us = wm->undo_stack->steps.last;
- if (STREQ(str, us->name)) {
- return;
- }
- }
-
+ wmWindowManager *wm = CTX_wm_manager(C);
+ const UndoStep *us = wm->undo_stack->step_active;
+ if (us && STREQ(str, us->name)) {
+ BKE_undosys_stack_clear_active(wm->undo_stack);
}
/* push as usual */
@@ -210,7 +205,7 @@ bool ED_undo_is_valid(const bContext *C, const char *undoname)
*/
UndoStack *ED_undo_stack_get(void)
{
- wmWindowManager *wm = G.main->wm.first;
+ wmWindowManager *wm = G_MAIN->wm.first;
return wm->undo_stack;
}
@@ -307,36 +302,6 @@ void ED_OT_undo_redo(wmOperatorType *ot)
/** \} */
-struct OperatorRepeatContextHandle {
- ScrArea *restore_area;
- ARegion *restore_region;
-};
-
-/**
- * Resets the context to the state \a op was executed in (or at least, was in when registering).
- * #ED_operator_repeat_reset_context should be called when done repeating!
- */
-const OperatorRepeatContextHandle *ED_operator_repeat_prepare_context(bContext *C, wmOperator *op)
-{
- static OperatorRepeatContextHandle context_info;
-
- context_info.restore_area = CTX_wm_area(C);
- context_info.restore_region = CTX_wm_region(C);
-
- CTX_wm_area_set(C, op->execution_area);
- CTX_wm_region_set(C, op->execution_region);
-
- return &context_info;
-}
-/**
- * Resets context to the old state from before #ED_operator_repeat_prepare_context was called.
- */
-void ED_operator_repeat_reset_context(bContext *C, const OperatorRepeatContextHandle *context_info)
-{
- CTX_wm_area_set(C, context_info->restore_area);
- CTX_wm_region_set(C, context_info->restore_region);
-}
-
/* -------------------------------------------------------------------- */
/** \name Operator Repeat
* \{ */
@@ -351,8 +316,13 @@ int ED_undo_operator_repeat(bContext *C, wmOperator *op)
wmWindowManager *wm = CTX_wm_manager(C);
struct Scene *scene = CTX_data_scene(C);
- const OperatorRepeatContextHandle *context_info;
- context_info = ED_operator_repeat_prepare_context(C, op);
+ /* keep in sync with logic in view3d_panel_operator_redo() */
+ ARegion *ar_orig = CTX_wm_region(C);
+ ARegion *ar_win = BKE_area_find_region_active_win(CTX_wm_area(C));
+
+ if (ar_win) {
+ CTX_wm_region_set(C, ar_win);
+ }
if ((WM_operator_repeat_check(C, op)) &&
(WM_operator_poll(C, op->type)) &&
@@ -398,7 +368,8 @@ int ED_undo_operator_repeat(bContext *C, wmOperator *op)
}
}
- ED_operator_repeat_reset_context(C, context_info);
+ /* set region back */
+ CTX_wm_region_set(C, ar_orig);
}
else {
CLOG_WARN(&LOG, "called with NULL 'op'");
@@ -440,7 +411,7 @@ static const EnumPropertyItem *rna_undo_itemf(bContext *C, int *totitem)
item_tmp.identifier = us->name;
item_tmp.name = IFACE_(us->name);
if (us == wm->undo_stack->step_active) {
- item_tmp.icon = ICON_RESTRICT_VIEW_OFF;
+ item_tmp.icon = ICON_HIDE_OFF;
}
else {
item_tmp.icon = ICON_NONE;
diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt
index 24cfde90804..fa21facefc2 100644
--- a/source/blender/editors/util/CMakeLists.txt
+++ b/source/blender/editors/util/CMakeLists.txt
@@ -87,6 +87,7 @@ set(SRC
../include/ED_transform_snap_object_context.h
../include/ED_transverts.h
../include/ED_types.h
+ ../include/ED_undo.h
../include/ED_util.h
../include/ED_uvedit.h
../include/ED_view3d.h
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index a829f8c1144..549b9b7de77 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -145,8 +145,8 @@ void ED_editors_exit(bContext *C)
return;
/* frees all editmode undos */
- if (G.main->wm.first) {
- wmWindowManager *wm = G.main->wm.first;
+ if (G_MAIN->wm.first) {
+ wmWindowManager *wm = G_MAIN->wm.first;
/* normally we don't check for NULL undo stack, do here since it may run in different context. */
if (wm->undo_stack) {
BKE_undosys_stack_destroy(wm->undo_stack);
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 45a6ccfe28b..e3d2537c040 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -1362,7 +1362,7 @@ static int uv_select_more_less(bContext *C, const bool select)
else {
EDBM_select_less(em, true);
}
-
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
}
@@ -1434,6 +1434,7 @@ static int uv_select_more_less(bContext *C, const bool select)
uv_select_flush_from_tag_loop(sima, scene, obedit, select);
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -2058,6 +2059,7 @@ static int uv_select_all_exec(bContext *C, wmOperator *op)
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
@@ -2371,7 +2373,7 @@ static int uv_mouse_select_multi(
#endif
}
- DEG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED;
@@ -2547,7 +2549,7 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
- DEG_id_tag_update(obedit->data, 0);
+ DEG_id_tag_update(obedit->data, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
@@ -3052,6 +3054,7 @@ static int uv_border_select_exec(bContext *C, wmOperator *op)
uv_select_sync_flush(ts, em, select);
if (ts->uv_flag & UV_SYNC_SELECTION) {
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
}
@@ -3181,6 +3184,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
if (changed) {
uv_select_sync_flush(ts, em, select);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
@@ -3314,6 +3318,7 @@ static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mo
uv_select_sync_flush(scene->toolsettings, em, select);
if (ts->uv_flag & UV_SYNC_SELECTION) {
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
}
@@ -3746,6 +3751,7 @@ static int uv_select_pinned_exec(bContext *C, wmOperator *UNUSED(op))
}
}
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -3812,6 +3818,8 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
if (ts->uv_flag & UV_SYNC_SELECTION) {
EDBM_mesh_hide(em, swap);
+
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -3880,6 +3888,8 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
EDBM_selectmode_flush_ex(em, SCE_SELECT_VERTEX | SCE_SELECT_EDGE);
BM_select_history_validate(em->bm);
+
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -3933,6 +3943,7 @@ static int uv_reveal_exec(bContext *C, wmOperator *op)
/* call the mesh function if we are in mesh sync sel */
if (ts->uv_flag & UV_SYNC_SELECTION) {
EDBM_mesh_reveal(em, select);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
@@ -4022,6 +4033,7 @@ static int uv_reveal_exec(bContext *C, wmOperator *op)
/* re-select tagged faces */
BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, false, BM_ELEM_TAG);
+ DEG_id_tag_update(obedit->data, DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
return OPERATOR_FINISHED;