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:
authorYimingWu <xp8110@outlook.com>2019-05-16 04:48:45 +0300
committerYimingWu <xp8110@outlook.com>2019-05-16 04:48:45 +0300
commit54804117e89931a1e7bfa67b2aaf4fe237881ab6 (patch)
tree72f60f4ee18426243c986e973029508ab706569a /source/blender/editors
parent2753611c4e2482885021416f1b2af46250fd09dd (diff)
parent2384564149b54374572ea28f91b5f64dc61143e2 (diff)
Merge branch 'master' into soc-2018-npr
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/animation/CMakeLists.txt1
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c10
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c5
-rw-r--r--source/blender/editors/animation/anim_filter.c4
-rw-r--r--source/blender/editors/animation/anim_markers.c4
-rw-r--r--source/blender/editors/animation/anim_ops.c6
-rw-r--r--source/blender/editors/animation/drivers.c3
-rw-r--r--source/blender/editors/animation/keyframing.c8
-rw-r--r--source/blender/editors/animation/time_scrub_ui.c214
-rw-r--r--source/blender/editors/armature/armature_intern.h2
-rw-r--r--source/blender/editors/armature/armature_naming.c10
-rw-r--r--source/blender/editors/armature/armature_ops.c2
-rw-r--r--source/blender/editors/armature/armature_relations.c37
-rw-r--r--source/blender/editors/armature/armature_select.c8
-rw-r--r--source/blender/editors/armature/armature_utils.c3
-rw-r--r--source/blender/editors/armature/pose_slide.c255
-rw-r--r--source/blender/editors/armature/pose_transform.c337
-rw-r--r--source/blender/editors/curve/editcurve.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_merge.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_primitive.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c2
-rw-r--r--source/blender/editors/include/ED_anim_api.h10
-rw-r--r--source/blender/editors/include/ED_mesh.h16
-rw-r--r--source/blender/editors/include/ED_screen.h10
-rw-r--r--source/blender/editors/include/ED_time_scrub_ui.h43
-rw-r--r--source/blender/editors/include/ED_view3d.h5
-rw-r--r--source/blender/editors/include/UI_icons.h36
-rw-r--r--source/blender/editors/include/UI_interface.h15
-rw-r--r--source/blender/editors/include/UI_interface_icons.h25
-rw-r--r--source/blender/editors/include/UI_resources.h6
-rw-r--r--source/blender/editors/include/UI_view2d.h8
-rw-r--r--source/blender/editors/interface/interface.c5
-rw-r--r--source/blender/editors/interface/interface_anim.c5
-rw-r--r--source/blender/editors/interface/interface_context_menu.c160
-rw-r--r--source/blender/editors/interface/interface_handlers.c42
-rw-r--r--source/blender/editors/interface/interface_icons.c543
-rw-r--r--source/blender/editors/interface/interface_intern.h6
-rw-r--r--source/blender/editors/interface/interface_layout.c3
-rw-r--r--source/blender/editors/interface/interface_panel.c151
-rw-r--r--source/blender/editors/interface/interface_region_menu_pie.c2
-rw-r--r--source/blender/editors/interface/interface_region_menu_popup.c25
-rw-r--r--source/blender/editors/interface/interface_region_popover.c10
-rw-r--r--source/blender/editors/interface/interface_region_popup.c8
-rw-r--r--source/blender/editors/interface/interface_region_tooltip.c4
-rw-r--r--source/blender/editors/interface/interface_templates.c36
-rw-r--r--source/blender/editors/interface/interface_widgets.c50
-rw-r--r--source/blender/editors/interface/resources.c26
-rw-r--r--source/blender/editors/interface/view2d.c24
-rw-r--r--source/blender/editors/interface/view2d_ops.c4
-rw-r--r--source/blender/editors/mask/mask_ops.c8
-rw-r--r--source/blender/editors/mesh/CMakeLists.txt1
-rw-r--r--source/blender/editors/mesh/editface.c6
-rw-r--r--source/blender/editors/mesh/editmesh_bevel.c3
-rw-r--r--source/blender/editors/mesh/editmesh_extrude.c4
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c1
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c69
-rw-r--r--source/blender/editors/mesh/editmesh_select.c368
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c21
-rw-r--r--source/blender/editors/mesh/meshtools.c8
-rw-r--r--source/blender/editors/metaball/mball_edit.c2
-rw-r--r--source/blender/editors/object/object_add.c72
-rw-r--r--source/blender/editors/object/object_bake_api.c3
-rw-r--r--source/blender/editors/object/object_constraint.c4
-rw-r--r--source/blender/editors/object/object_edit.c4
-rw-r--r--source/blender/editors/render/render_internal.c49
-rw-r--r--source/blender/editors/render/render_preview.c11
-rw-r--r--source/blender/editors/screen/area.c127
-rw-r--r--source/blender/editors/screen/screen_ops.c200
-rw-r--r--source/blender/editors/screen/workspace_edit.c12
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c3
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c18
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c1
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c4
-rw-r--r--source/blender/editors/sound/CMakeLists.txt1
-rw-r--r--source/blender/editors/sound/sound_ops.c55
-rw-r--r--source/blender/editors/space_action/action_draw.c2
-rw-r--r--source/blender/editors/space_action/action_select.c1
-rw-r--r--source/blender/editors/space_action/space_action.c26
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c7
-rw-r--r--source/blender/editors/space_buttons/buttons_ops.c5
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c108
-rw-r--r--source/blender/editors/space_clip/clip_intern.h2
-rw-r--r--source/blender/editors/space_clip/clip_ops.c8
-rw-r--r--source/blender/editors/space_clip/space_clip.c44
-rw-r--r--source/blender/editors/space_clip/tracking_ops.c10
-rw-r--r--source/blender/editors/space_file/file_draw.c2
-rw-r--r--source/blender/editors/space_file/file_ops.c5
-rw-r--r--source/blender/editors/space_file/fsmenu.c161
-rw-r--r--source/blender/editors/space_file/fsmenu.h2
-rw-r--r--source/blender/editors/space_file/space_file.c13
-rw-r--r--source/blender/editors/space_graph/graph_edit.c1
-rw-r--r--source/blender/editors/space_graph/graph_ops.c2
-rw-r--r--source/blender/editors/space_graph/graph_select.c2
-rw-r--r--source/blender/editors/space_graph/space_graph.c45
-rw-r--r--source/blender/editors/space_image/image_ops.c5
-rw-r--r--source/blender/editors/space_image/space_image.c18
-rw-r--r--source/blender/editors/space_info/info_ops.c12
-rw-r--r--source/blender/editors/space_nla/nla_channels.c4
-rw-r--r--source/blender/editors/space_nla/nla_draw.c10
-rw-r--r--source/blender/editors/space_nla/nla_edit.c3
-rw-r--r--source/blender/editors/space_nla/nla_select.c3
-rw-r--r--source/blender/editors/space_nla/space_nla.c24
-rw-r--r--source/blender/editors/space_node/drawnode.c12
-rw-r--r--source/blender/editors/space_node/node_edit.c9
-rw-r--r--source/blender/editors/space_node/node_select.c186
-rw-r--r--source/blender/editors/space_node/space_node.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c24
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c1350
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c4
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h9
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c3
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c12
-rw-r--r--source/blender/editors/space_outliner/outliner_utils.c39
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c1
-rw-r--r--source/blender/editors/space_sequencer/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c8
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c43
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c3
-rw-r--r--source/blender/editors/space_sequencer/sequencer_preview.c4
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c8
-rw-r--r--source/blender/editors/space_text/text_draw.c6
-rw-r--r--source/blender/editors/space_text/text_ops.c2
-rw-r--r--source/blender/editors/space_topbar/space_topbar.c7
-rw-r--r--source/blender/editors/space_userpref/space_userpref.c2
-rw-r--r--source/blender/editors/space_view3d/drawobject.c231
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c109
-rw-r--r--source/blender/editors/space_view3d/view3d_draw_legacy.c16
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c17
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h7
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c33
-rw-r--r--source/blender/editors/transform/transform.c3
-rw-r--r--source/blender/editors/transform/transform.h33
-rw-r--r--source/blender/editors/transform/transform_conversions.c183
-rw-r--r--source/blender/editors/transform/transform_generics.c83
-rw-r--r--source/blender/editors/transform/transform_gizmo_3d.c9
-rw-r--r--source/blender/editors/util/CMakeLists.txt1
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c3
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c4
140 files changed, 4116 insertions, 2130 deletions
diff --git a/source/blender/editors/animation/CMakeLists.txt b/source/blender/editors/animation/CMakeLists.txt
index 978bd772b6f..ce6778a1ff9 100644
--- a/source/blender/editors/animation/CMakeLists.txt
+++ b/source/blender/editors/animation/CMakeLists.txt
@@ -51,6 +51,7 @@ set(SRC
keyframes_general.c
keyframing.c
keyingsets.c
+ time_scrub_ui.c
anim_intern.h
)
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index 6d1ee08d5e9..00025112835 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -485,16 +485,10 @@ static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float ymi
static void acf_summary_name(bAnimListElem *UNUSED(ale), char *name)
{
if (name) {
- BLI_strncpy(name, IFACE_("Dope Sheet Summary"), ANIM_CHAN_NAME_SIZE);
+ BLI_strncpy(name, IFACE_("Summary"), ANIM_CHAN_NAME_SIZE);
}
}
-// FIXME: this is really a temp icon I think
-static int acf_summary_icon(bAnimListElem *UNUSED(ale))
-{
- return ICON_BORDERMOVE;
-}
-
/* check if some setting exists for this channel */
static bool acf_summary_setting_valid(bAnimContext *UNUSED(ac),
bAnimListElem *UNUSED(ale),
@@ -557,7 +551,7 @@ static bAnimChannelType ACF_SUMMARY = {
acf_summary_name, /* name */
NULL, /* name prop */
- acf_summary_icon, /* icon */
+ NULL, /* icon */
acf_summary_setting_valid, /* has setting */
acf_summary_setting_flag, /* flag for setting */
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index adc6ec3f6be..9e09fc485a6 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -55,6 +55,7 @@
#include "DEG_depsgraph_build.h"
#include "UI_view2d.h"
+#include "UI_interface.h"
#include "ED_anim_api.h"
#include "ED_armature.h"
@@ -2542,7 +2543,7 @@ static void box_select_anim_channels(bAnimContext *ac, rcti *rect, short selectm
float ymax;
if (ac->datatype == ANIMCONT_NLA) {
- ymax = NLACHANNEL_FIRST_TOP(snla);
+ ymax = NLACHANNEL_FIRST_TOP(ac);
}
else {
ymax = ACHANNEL_FIRST_TOP(ac);
@@ -2735,7 +2736,7 @@ static int animchannels_channel_get(bAnimContext *ac, const int mval[2])
UI_view2d_listview_view_to_cell(NLACHANNEL_NAMEWIDTH,
NLACHANNEL_STEP(snla),
0,
- NLACHANNEL_FIRST_TOP(snla),
+ NLACHANNEL_FIRST_TOP(ac),
x,
y,
NULL,
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index b94d0e3ada7..a228d819286 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -1823,7 +1823,7 @@ static size_t animdata_filter_gpencil(bAnimContext *ac,
}
/* outliner restrict-flag */
- if (ob->restrictflag & OB_RESTRICT_VIEW) {
+ if (ob->restrictflag & OB_RESTRICT_VIEWPORT) {
continue;
}
}
@@ -3022,7 +3022,7 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Base *base, int filter_m
}
/* outliner restrict-flag */
- if (ob->restrictflag & OB_RESTRICT_VIEW) {
+ if (ob->restrictflag & OB_RESTRICT_VIEWPORT) {
return false;
}
}
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index 66cdae07a36..876bc9ae3e4 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -481,7 +481,9 @@ static void draw_markers_background(rctf *rect)
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- const unsigned char shade[4] = {0, 0, 0, 16};
+ unsigned char shade[4];
+ UI_GetThemeColor4ubv(TH_SCRUBBING_BACKGROUND, shade);
+
immUniformColor4ubv(shade);
GPU_blend(true);
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c
index 97ba7132c3d..45bb8f3b11e 100644
--- a/source/blender/editors/animation/anim_ops.c
+++ b/source/blender/editors/animation/anim_ops.c
@@ -52,9 +52,6 @@
#include "ED_sequencer.h"
#include "ED_util.h"
-#include "DEG_depsgraph.h"
-#include "DEG_depsgraph_query.h"
-
#include "anim_intern.h"
/* ********************** frame change operator ***************************/
@@ -91,6 +88,7 @@ static bool change_frame_poll(bContext *C)
/* Set the new frame number */
static void change_frame_apply(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
float frame = RNA_float_get(op->ptr, "frame");
bool do_snap = RNA_boolean_get(op->ptr, "snap");
@@ -116,7 +114,7 @@ static void change_frame_apply(bContext *C, wmOperator *op)
FRAMENUMBER_MIN_CLAMP(CFRA);
/* do updates */
- BKE_sound_update_and_seek(CTX_data_main(C), CTX_data_depsgraph(C));
+ BKE_sound_seek_scene(bmain, scene);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index 2a8702802aa..fe079eb59a0 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -1249,7 +1249,8 @@ static int paste_driver_button_exec(bContext *C, wmOperator *op)
UI_context_update_anim_flag(C);
DEG_relations_tag_update(CTX_data_main(C));
- DEG_id_tag_update(ptr.id.data, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+
+ DEG_id_tag_update(ptr.id.data, ID_RECALC_ANIMATION);
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); // XXX
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index a0433b49b16..97d85d25d66 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -1307,8 +1307,8 @@ static bool insert_keyframe_fcurve_value(Main *bmain,
* - if we're replacing keyframes only, DO NOT create new F-Curves if they do not exist yet
* but still try to get the F-Curve if it exists...
*/
- FCurve *fcu = verify_fcurve(
- bmain, act, group, ptr, rna_path, array_index, (flag & INSERTKEY_REPLACE) == 0);
+ bool can_create_curve = (flag & (INSERTKEY_REPLACE | INSERTKEY_AVAILABLE)) == 0;
+ FCurve *fcu = verify_fcurve(bmain, act, group, ptr, rna_path, array_index, can_create_curve);
/* we may not have a F-Curve when we're replacing only... */
if (fcu) {
@@ -1432,7 +1432,7 @@ short insert_keyframe(Main *bmain,
/* Key the entire array. */
if (array_index == -1 || force_all) {
/* In force mode, if any of the curves succeeds, drop the replace mode and restart. */
- if (force_all && (flag & INSERTKEY_REPLACE) != 0) {
+ if (force_all && (flag & (INSERTKEY_REPLACE | INSERTKEY_AVAILABLE)) != 0) {
int exclude = -1;
for (array_index = 0; array_index < value_count; array_index++) {
@@ -1455,7 +1455,7 @@ short insert_keyframe(Main *bmain,
}
if (exclude != -1) {
- flag &= ~INSERTKEY_REPLACE;
+ flag &= ~(INSERTKEY_REPLACE | INSERTKEY_AVAILABLE);
for (array_index = 0; array_index < value_count; array_index++) {
if (array_index != exclude) {
diff --git a/source/blender/editors/animation/time_scrub_ui.c b/source/blender/editors/animation/time_scrub_ui.c
new file mode 100644
index 00000000000..37e7eab74d4
--- /dev/null
+++ b/source/blender/editors/animation/time_scrub_ui.c
@@ -0,0 +1,214 @@
+/*
+ * 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) 2019 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edanimation
+ */
+
+#include "BKE_context.h"
+
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+#include "GPU_state.h"
+
+#include "ED_time_scrub_ui.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_interface_icons.h"
+#include "UI_view2d.h"
+#include "UI_resources.h"
+
+#include "DNA_scene_types.h"
+
+#include "BLI_rect.h"
+#include "BLI_math.h"
+#include "BLI_string.h"
+#include "BLI_timecode.h"
+
+#include "RNA_access.h"
+
+static void get_scrubbing_region_rect(const ARegion *ar, rcti *rect)
+{
+ rect->xmin = 0;
+ rect->xmax = ar->winx;
+ rect->ymax = ar->winy;
+ rect->ymin = rect->ymax - UI_SCRUBBING_MARGIN_Y;
+}
+
+static int get_centered_text_y(const rcti *rect)
+{
+ return BLI_rcti_cent_y(rect) - UI_DPI_FAC * 4;
+}
+
+static void draw_background(const rcti *rect)
+{
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformThemeColor(TH_SCRUBBING_BACKGROUND);
+
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+
+ GPU_blend(false);
+
+ immUnbindProgram();
+}
+
+static void get_current_time_str(
+ const Scene *scene, bool display_seconds, int frame, uint max_len, char *r_str)
+{
+ if (display_seconds) {
+ BLI_timecode_string_from_time(r_str, max_len, 0, FRA2TIME(frame), FPS, U.timecode_style);
+ }
+ else {
+ BLI_snprintf(r_str, max_len, "%d", frame);
+ }
+}
+
+static void draw_current_frame(const Scene *scene,
+ bool display_seconds,
+ const View2D *v2d,
+ const rcti *scrubbing_region_rect,
+ int current_frame)
+{
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
+ const unsigned char color[] = {255, 255, 255, 255};
+ int frame_x = UI_view2d_view_to_region_x(v2d, current_frame);
+
+ char frame_str[64];
+ get_current_time_str(scene, display_seconds, current_frame, sizeof(frame_str), frame_str);
+ float text_width = UI_fontstyle_string_width(fstyle, frame_str);
+ float box_width = MAX2(text_width + 8 * UI_DPI_FAC, 24 * UI_DPI_FAC);
+ float box_padding = 3 * UI_DPI_FAC;
+
+ float bg_color[4];
+ UI_GetThemeColorShade4fv(TH_CFRAME, -5, bg_color);
+
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+
+ UI_draw_roundbox_3fvAlpha(true,
+ frame_x - box_width / 2 + U.pixelsize / 2,
+ scrubbing_region_rect->ymin + box_padding,
+ frame_x + box_width / 2 + U.pixelsize / 2,
+ scrubbing_region_rect->ymax - box_padding,
+ 4 * UI_DPI_FAC,
+ bg_color,
+ 1.0f);
+
+ UI_GetThemeColorShade4fv(TH_CFRAME, 5, bg_color);
+ UI_draw_roundbox_aa(false,
+ frame_x - box_width / 2 + U.pixelsize / 2,
+ scrubbing_region_rect->ymin + box_padding,
+ frame_x + box_width / 2 + U.pixelsize / 2,
+ scrubbing_region_rect->ymax - box_padding,
+ 4 * UI_DPI_FAC,
+ bg_color);
+
+ UI_fontstyle_draw_simple(fstyle,
+ frame_x - text_width / 2 + U.pixelsize / 2,
+ get_centered_text_y(scrubbing_region_rect),
+ frame_str,
+ color);
+}
+
+void ED_scrubbing_draw(const ARegion *ar,
+ const Scene *scene,
+ bool display_seconds,
+ bool discrete_frames)
+{
+ const View2D *v2d = &ar->v2d;
+
+ GPU_matrix_push_projection();
+ wmOrtho2_region_pixelspace(ar);
+
+ rcti scrubbing_region_rect;
+ get_scrubbing_region_rect(ar, &scrubbing_region_rect);
+
+ draw_background(&scrubbing_region_rect);
+
+ rcti numbers_rect = scrubbing_region_rect;
+ numbers_rect.ymin = get_centered_text_y(&scrubbing_region_rect) - 4 * UI_DPI_FAC;
+ if (discrete_frames) {
+ UI_view2d_draw_scale_x__discrete_frames_or_seconds(
+ ar, v2d, &numbers_rect, scene, display_seconds, TH_TEXT);
+ }
+ else {
+ UI_view2d_draw_scale_x__frames_or_seconds(
+ ar, v2d, &numbers_rect, scene, display_seconds, TH_TEXT);
+ }
+
+ draw_current_frame(scene, display_seconds, v2d, &scrubbing_region_rect, scene->r.cfra);
+
+ GPU_matrix_pop_projection();
+}
+
+bool ED_event_in_scrubbing_region(const ARegion *ar, const wmEvent *event)
+{
+ rcti rect = ar->winrct;
+ rect.ymin = rect.ymax - UI_SCRUBBING_MARGIN_Y;
+ return BLI_rcti_isect_pt(&rect, event->x, event->y);
+}
+
+void ED_channel_search_draw(const bContext *C, ARegion *ar, bDopeSheet *dopesheet)
+{
+ GPU_matrix_push_projection();
+ wmOrtho2_region_pixelspace(ar);
+
+ rcti rect;
+ rect.xmin = 0;
+ rect.xmax = ceilf(ar->sizex * UI_DPI_FAC);
+ rect.ymin = ar->sizey * UI_DPI_FAC - UI_SCRUBBING_MARGIN_Y;
+ rect.ymax = ceilf(ar->sizey * UI_DPI_FAC);
+
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_BACK);
+ immRectf(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ immUnbindProgram();
+
+ uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+
+ PointerRNA ptr;
+ RNA_pointer_create(&CTX_wm_screen(C)->id, &RNA_DopeSheet, dopesheet, &ptr);
+ PropertyRNA *prop = RNA_struct_find_property(&ptr, "filter_text");
+
+ int padding = 2 * UI_DPI_FAC;
+ uiDefAutoButR(block,
+ &ptr,
+ prop,
+ -1,
+ "",
+ ICON_NONE,
+ rect.xmin + padding,
+ rect.ymin + padding,
+ BLI_rcti_size_x(&rect) - 2 * padding,
+ BLI_rcti_size_y(&rect) - 2 * padding);
+
+ UI_block_end(C, block);
+ UI_block_draw(C, block);
+
+ GPU_matrix_pop_projection();
+}
diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h
index 6c2d9fe8f42..569eb7e2e04 100644
--- a/source/blender/editors/armature/armature_intern.h
+++ b/source/blender/editors/armature/armature_intern.h
@@ -210,6 +210,8 @@ void POSELIB_OT_apply_pose(struct wmOperatorType *ot);
void POSE_OT_push(struct wmOperatorType *ot);
void POSE_OT_relax(struct wmOperatorType *ot);
+void POSE_OT_push_rest(struct wmOperatorType *ot);
+void POSE_OT_relax_rest(struct wmOperatorType *ot);
void POSE_OT_breakdown(struct wmOperatorType *ot);
void POSE_OT_propagate(struct wmOperatorType *ot);
diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c
index 083967d5d41..9a1582679a4 100644
--- a/source/blender/editors/armature/armature_naming.c
+++ b/source/blender/editors/armature/armature_naming.c
@@ -180,7 +180,17 @@ void ED_armature_bone_rename(Main *bmain,
if (bone) {
unique_bone_name(arm, newname);
+
+ if (arm->bonehash) {
+ BLI_assert(BLI_ghash_haskey(arm->bonehash, bone->name));
+ BLI_ghash_remove(arm->bonehash, bone->name, NULL, NULL);
+ }
+
BLI_strncpy(bone->name, newname, MAXBONENAME);
+
+ if (arm->bonehash) {
+ BLI_ghash_insert(arm->bonehash, bone->name, bone);
+ }
}
else {
return;
diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c
index b53ae813f10..a29d0f5f158 100644
--- a/source/blender/editors/armature/armature_ops.c
+++ b/source/blender/editors/armature/armature_ops.c
@@ -146,6 +146,8 @@ void ED_operatortypes_armature(void)
/* POSE SLIDING */
WM_operatortype_append(POSE_OT_push);
WM_operatortype_append(POSE_OT_relax);
+ WM_operatortype_append(POSE_OT_push_rest);
+ WM_operatortype_append(POSE_OT_relax_rest);
WM_operatortype_append(POSE_OT_breakdown);
}
diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c
index b2ca1d84520..2c61818d902 100644
--- a/source/blender/editors/armature/armature_relations.c
+++ b/source/blender/editors/armature/armature_relations.c
@@ -66,10 +66,16 @@
/* *************************************** Join *************************************** */
/* NOTE: no operator define here as this is exported to the Object-level operator */
-static void joined_armature_fix_links_constraints(
- Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone, ListBase *lb)
+static void joined_armature_fix_links_constraints(Main *bmain,
+ Object *ob,
+ Object *tarArm,
+ Object *srcArm,
+ bPoseChannel *pchan,
+ EditBone *curbone,
+ ListBase *lb)
{
bConstraint *con;
+ bool changed = false;
for (con = lb->first; con; con = con->next) {
const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
@@ -84,10 +90,12 @@ static void joined_armature_fix_links_constraints(
if (ct->tar == srcArm) {
if (ct->subtarget[0] == '\0') {
ct->tar = tarArm;
+ changed = true;
}
else if (STREQ(ct->subtarget, pchan->name)) {
ct->tar = tarArm;
BLI_strncpy(ct->subtarget, curbone->name, sizeof(ct->subtarget));
+ changed = true;
}
}
}
@@ -104,13 +112,21 @@ static void joined_armature_fix_links_constraints(
if (data->act) {
BKE_action_fix_paths_rename(
&tarArm->id, data->act, "pose.bones[", pchan->name, curbone->name, 0, 0, false);
+
+ DEG_id_tag_update_ex(bmain, &data->act->id, ID_RECALC_COPY_ON_WRITE);
}
}
}
+
+ if (changed) {
+ DEG_id_tag_update_ex(bmain, &ob->id, ID_RECALC_COPY_ON_WRITE);
+ }
}
/* userdata for joined_armature_fix_animdata_cb() */
typedef struct tJoinArmature_AdtFixData {
+ Main *bmain;
+
Object *srcArm;
Object *tarArm;
@@ -129,6 +145,7 @@ static void joined_armature_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data
ID *dst_id = &afd->tarArm->id;
GHashIterator gh_iter;
+ bool changed = false;
/* Fix paths - If this is the target object, it will have some "dirty" paths */
if ((id == src_id) && strstr(fcu->rna_path, "pose.bones[")) {
@@ -142,6 +159,8 @@ static void joined_armature_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data
fcu->rna_path = BKE_animsys_fix_rna_path_rename(
id, fcu->rna_path, "pose.bones", old_name, new_name, 0, 0, false);
+ changed = true;
+
/* we don't want to apply a second remapping on this driver now,
* so stop trying names, but keep fixing drivers
*/
@@ -163,6 +182,8 @@ static void joined_armature_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data
if (dtar->id == src_id) {
dtar->id = dst_id;
+ changed = true;
+
/* also check on the subtarget...
* XXX: We duplicate the logic from drivers_path_rename_fix() here, with our own
* little twists so that we know that it isn't going to clobber the wrong data
@@ -193,6 +214,10 @@ static void joined_armature_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data
DRIVER_TARGETS_LOOPER_END;
}
}
+
+ if (changed) {
+ DEG_id_tag_update_ex(afd->bmain, id, ID_RECALC_COPY_ON_WRITE);
+ }
}
/* Helper function for armature joining - link fixing */
@@ -210,13 +235,14 @@ static void joined_armature_fix_links(
pose = ob->pose;
for (pchant = pose->chanbase.first; pchant; pchant = pchant->next) {
joined_armature_fix_links_constraints(
- tarArm, srcArm, pchan, curbone, &pchant->constraints);
+ bmain, ob, tarArm, srcArm, pchan, curbone, &pchant->constraints);
}
}
/* fix object-level constraints */
if (ob != srcArm) {
- joined_armature_fix_links_constraints(tarArm, srcArm, pchan, curbone, &ob->constraints);
+ joined_armature_fix_links_constraints(
+ bmain, ob, tarArm, srcArm, pchan, curbone, &ob->constraints);
}
/* See if an object is parented to this armature */
@@ -231,6 +257,8 @@ static void joined_armature_fix_links(
/* make tar armature be new parent */
ob->parent = tarArm;
+
+ DEG_id_tag_update_ex(bmain, &ob->id, ID_RECALC_COPY_ON_WRITE);
}
}
}
@@ -286,6 +314,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
BLI_assert(ob_active->data != ob_iter->data);
/* init callback data for fixing up AnimData links later */
+ afd.bmain = bmain;
afd.srcArm = ob_iter;
afd.tarArm = ob_active;
afd.names_map = BLI_ghash_str_new("join_armature_adt_fix");
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index fbbb68d2003..23ddf77e63d 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -70,7 +70,7 @@ Base *ED_armature_base_and_ebone_from_select_buffer(Base **bases,
EditBone *ebone = NULL;
/* TODO(campbell): optimize, eg: sort & binary search. */
for (uint base_index = 0; base_index < bases_len; base_index++) {
- if (bases[base_index]->object->select_id == hit_object) {
+ if (bases[base_index]->object->runtime.select_id == hit_object) {
base = bases[base_index];
break;
}
@@ -94,7 +94,7 @@ Object *ED_armature_object_and_ebone_from_select_buffer(Object **objects,
EditBone *ebone = NULL;
/* TODO(campbell): optimize, eg: sort & binary search. */
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- if (objects[ob_index]->select_id == hit_object) {
+ if (objects[ob_index]->runtime.select_id == hit_object) {
ob = objects[ob_index];
break;
}
@@ -118,7 +118,7 @@ Base *ED_armature_base_and_bone_from_select_buffer(Base **bases,
Bone *bone = NULL;
/* TODO(campbell): optimize, eg: sort & binary search. */
for (uint base_index = 0; base_index < bases_len; base_index++) {
- if (bases[base_index]->object->select_id == hit_object) {
+ if (bases[base_index]->object->runtime.select_id == hit_object) {
base = bases[base_index];
break;
}
@@ -300,6 +300,7 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, const wmEv
const bool sel = !RNA_boolean_get(op->ptr, "deselect");
view3d_operator_needs_opengl(C);
+ BKE_object_update_select_id(CTX_data_main(C));
Base *base = NULL;
bone = get_nearest_bone(C, event->mval, true, &base);
@@ -1817,6 +1818,7 @@ static int armature_shortest_path_pick_invoke(bContext *C, wmOperator *op, const
Base *base_dst = NULL;
view3d_operator_needs_opengl(C);
+ BKE_object_update_select_id(CTX_data_main(C));
ebone_src = arm->act_edbone;
ebone_dst = get_nearest_bone(C, event->mval, false, &base_dst);
diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c
index b23081cd6fa..20dc7b6c826 100644
--- a/source/blender/editors/armature/armature_utils.c
+++ b/source/blender/editors/armature/armature_utils.c
@@ -650,6 +650,7 @@ void ED_armature_from_edit(Main *bmain, bArmature *arm)
Object *obt;
/* armature bones */
+ BKE_armature_bone_hash_free(arm);
BKE_armature_bonelist_free(&arm->bonebase);
arm->act_bone = NULL;
@@ -754,6 +755,8 @@ void ED_armature_from_edit(Main *bmain, bArmature *arm)
/* Finalize definition of restpose data (roll, bone_mat, arm_mat, head/tail...). */
armature_finalize_restpose(&arm->bonebase, arm->edbo);
+ BKE_armature_bone_hash_make(arm);
+
/* so all users of this armature should get rebuilt */
for (obt = bmain->objects.first; obt; obt = obt->id.next) {
if (obt->data == arm) {
diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c
index d683c599f7b..9bc204c9e3b 100644
--- a/source/blender/editors/armature/pose_slide.c
+++ b/source/blender/editors/armature/pose_slide.c
@@ -134,6 +134,8 @@ typedef enum ePoseSlide_Modes {
POSESLIDE_PUSH = 0, /* exaggerate the pose... */
POSESLIDE_RELAX, /* soften the pose... */
POSESLIDE_BREAKDOWN, /* slide between the endpoint poses, finding a 'soft' spot */
+ POSESLIDE_PUSH_REST,
+ POSESLIDE_RELAX_REST,
} ePoseSlide_Modes;
/* Transforms/Channels to Affect */
@@ -627,6 +629,103 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
MEM_freeN(path);
}
+static void pose_slide_rest_pose_apply_vec3(tPoseSlideOp *pso, float vec[3], float default_value)
+{
+ /* We only slide to the rest pose. So only use the default rest pose value */
+ const int lock = pso->axislock;
+ for (int idx = 0; idx < 3; idx++) {
+ if ((lock == 0) || ((lock & PS_LOCK_X) && (idx == 0)) || ((lock & PS_LOCK_Y) && (idx == 1)) ||
+ ((lock & PS_LOCK_Z) && (idx == 2))) {
+ float diff_val = default_value - vec[idx];
+ if (pso->mode == POSESLIDE_RELAX_REST) {
+ vec[idx] += pso->percentage * diff_val;
+ }
+ else {
+ /* Push */
+ vec[idx] -= pso->percentage * diff_val;
+ }
+ }
+ }
+}
+
+static void pose_slide_rest_pose_apply_other_rot(tPoseSlideOp *pso, float vec[4], bool quat)
+{
+ /* We only slide to the rest pose. So only use the default rest pose value */
+ float default_values[] = {1.0f, 0.0f, 0.0f, 0.0f};
+ if (!quat) {
+ /* Axis Angle */
+ default_values[0] = 0.0f;
+ default_values[2] = 1.0f;
+ }
+ for (int idx = 0; idx < 4; idx++) {
+ float diff_val = default_values[idx] - vec[idx];
+ if (pso->mode == POSESLIDE_RELAX_REST) {
+ vec[idx] += pso->percentage * diff_val;
+ }
+ else {
+ /* Push */
+ vec[idx] -= pso->percentage * diff_val;
+ }
+ }
+}
+
+/* apply() - perform the pose sliding between the current pose and the rest pose */
+static void pose_slide_rest_pose_apply(bContext *C, tPoseSlideOp *pso)
+{
+ tPChanFCurveLink *pfl;
+
+ /* for each link, handle each set of transforms */
+ for (pfl = pso->pfLinks.first; pfl; pfl = pfl->next) {
+ /* valid transforms for each PoseChannel should have been noted already
+ * - sliding the pose should be a straightforward exercise for location+rotation,
+ * but rotations get more complicated since we may want to use quaternion blending
+ * for quaternions instead...
+ */
+ bPoseChannel *pchan = pfl->pchan;
+
+ if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_LOC) && (pchan->flag & POSE_LOC)) {
+ /* calculate these for the 'location' vector, and use location curves */
+ pose_slide_rest_pose_apply_vec3(pso, pchan->loc, 0.0f);
+ }
+
+ if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_SIZE) && (pchan->flag & POSE_SIZE)) {
+ /* calculate these for the 'scale' vector, and use scale curves */
+ pose_slide_rest_pose_apply_vec3(pso, pchan->size, 1.0f);
+ }
+
+ if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_ROT) && (pchan->flag & POSE_ROT)) {
+ /* everything depends on the rotation mode */
+ if (pchan->rotmode > 0) {
+ /* eulers - so calculate these for the 'eul' vector, and use euler_rotation curves */
+ pose_slide_rest_pose_apply_vec3(pso, pchan->eul, 0.0f);
+ }
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ pose_slide_rest_pose_apply_other_rot(pso, pchan->quat, false);
+ }
+ else {
+ /* quaternions - use quaternion blending */
+ pose_slide_rest_pose_apply_other_rot(pso, pchan->quat, true);
+ }
+ }
+
+ if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_BBONE_SHAPE) && (pchan->flag & POSE_BBONE_SHAPE)) {
+ /* bbone properties - they all start a "bbone_" prefix */
+ // TODO Not implemented
+ // pose_slide_apply_props(pso, pfl, "bbone_");
+ }
+
+ if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_PROPS) && (pfl->oldprops)) {
+ /* Not strictly a transform, but custom properties contribute
+ * to the pose produced in many rigs (e.g. the facial rigs used in Sintel). */
+ // TODO Not implemented
+ // pose_slide_apply_props(pso, pfl, "[\""); /* dummy " for texteditor bugs */
+ }
+ }
+
+ /* depsgraph updates + redraws */
+ pose_slide_refresh(C, pso);
+}
+
/* apply() - perform the pose sliding based on weighting various poses */
static void pose_slide_apply(bContext *C, tPoseSlideOp *pso)
{
@@ -888,7 +987,12 @@ static int pose_slide_invoke_common(bContext *C, wmOperator *op, tPoseSlideOp *p
/* initial apply for operator... */
/* TODO: need to calculate percentage for initial round too... */
- pose_slide_apply(C, pso);
+ if (pso->mode != POSESLIDE_PUSH_REST && pso->mode != POSESLIDE_RELAX_REST) {
+ pose_slide_apply(C, pso);
+ }
+ else {
+ pose_slide_rest_pose_apply(C, pso);
+ }
/* depsgraph updates + redraws */
pose_slide_refresh(C, pso);
@@ -1122,7 +1226,12 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
pose_slide_reset(pso);
/* apply... */
- pose_slide_apply(C, pso);
+ if (pso->mode != POSESLIDE_PUSH_REST && pso->mode != POSESLIDE_RELAX_REST) {
+ pose_slide_apply(C, pso);
+ }
+ else {
+ pose_slide_rest_pose_apply(C, pso);
+ }
}
/* still running... */
@@ -1140,7 +1249,12 @@ static void pose_slide_cancel(bContext *UNUSED(C), wmOperator *op)
static int pose_slide_exec_common(bContext *C, wmOperator *op, tPoseSlideOp *pso)
{
/* settings should have been set up ok for applying, so just apply! */
- pose_slide_apply(C, pso);
+ if (pso->mode != POSESLIDE_PUSH_REST && pso->mode != POSESLIDE_RELAX_REST) {
+ pose_slide_apply(C, pso);
+ }
+ else {
+ pose_slide_rest_pose_apply(C, pso);
+ }
/* insert keyframes if needed */
pose_slide_autoKeyframe(C, pso);
@@ -1200,7 +1314,7 @@ static void pose_slide_opdef_properties(wmOperatorType *ot)
/* ------------------------------------ */
-/* invoke() - for 'push' mode */
+/* invoke() - for 'push from breakdown' mode */
static int pose_slide_push_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
tPoseSlideOp *pso;
@@ -1242,9 +1356,9 @@ static int pose_slide_push_exec(bContext *C, wmOperator *op)
void POSE_OT_push(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Push Pose";
+ ot->name = "Push Pose from Breakdown";
ot->idname = "POSE_OT_push";
- ot->description = "Exaggerate the current pose";
+ ot->description = "Exaggerate the current pose in regards to the breakdown pose";
/* callbacks */
ot->exec = pose_slide_push_exec;
@@ -1262,7 +1376,7 @@ void POSE_OT_push(wmOperatorType *ot)
/* ........................ */
-/* invoke() - for 'relax' mode */
+/* invoke() - for 'relax to breakdown' mode */
static int pose_slide_relax_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
tPoseSlideOp *pso;
@@ -1304,9 +1418,9 @@ static int pose_slide_relax_exec(bContext *C, wmOperator *op)
void POSE_OT_relax(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Relax Pose";
+ ot->name = "Relax Pose to Breakdown";
ot->idname = "POSE_OT_relax";
- ot->description = "Make the current pose more similar to its surrounding ones";
+ ot->description = "Make the current pose more similar to its breakdown pose";
/* callbacks */
ot->exec = pose_slide_relax_exec;
@@ -1323,6 +1437,129 @@ void POSE_OT_relax(wmOperatorType *ot)
}
/* ........................ */
+/* invoke() - for 'push from rest pose' mode */
+static int pose_slide_push_rest_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ tPoseSlideOp *pso;
+
+ /* initialize data */
+ if (pose_slide_init(C, op, POSESLIDE_PUSH_REST) == 0) {
+ pose_slide_exit(op);
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ pso = op->customdata;
+ }
+
+ /* initialise percentage so that it won't pop on first mouse move */
+ pose_slide_mouse_update_percentage(pso, op, event);
+
+ /* do common setup work */
+ return pose_slide_invoke_common(C, op, pso);
+}
+
+/* exec() - for push */
+static int pose_slide_push_rest_exec(bContext *C, wmOperator *op)
+{
+ tPoseSlideOp *pso;
+
+ /* initialize data (from RNA-props) */
+ if (pose_slide_init(C, op, POSESLIDE_PUSH_REST) == 0) {
+ pose_slide_exit(op);
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ pso = op->customdata;
+ }
+
+ /* do common exec work */
+ return pose_slide_exec_common(C, op, pso);
+}
+
+void POSE_OT_push_rest(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Push Pose from Rest Pose";
+ ot->idname = "POSE_OT_push_rest";
+ ot->description = "Push the current pose further away from the rest pose";
+
+ /* callbacks */
+ ot->exec = pose_slide_push_rest_exec;
+ ot->invoke = pose_slide_push_rest_invoke;
+ ot->modal = pose_slide_modal;
+ ot->cancel = pose_slide_cancel;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_USE_EVAL_DATA;
+
+ /* Properties */
+ pose_slide_opdef_properties(ot);
+}
+
+/* ........................ */
+
+/* invoke() - for 'relax' mode */
+static int pose_slide_relax_rest_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ tPoseSlideOp *pso;
+
+ /* initialize data */
+ if (pose_slide_init(C, op, POSESLIDE_RELAX_REST) == 0) {
+ pose_slide_exit(op);
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ pso = op->customdata;
+ }
+
+ /* initialise percentage so that it won't pop on first mouse move */
+ pose_slide_mouse_update_percentage(pso, op, event);
+
+ /* do common setup work */
+ return pose_slide_invoke_common(C, op, pso);
+}
+
+/* exec() - for relax */
+static int pose_slide_relax_rest_exec(bContext *C, wmOperator *op)
+{
+ tPoseSlideOp *pso;
+
+ /* initialize data (from RNA-props) */
+ if (pose_slide_init(C, op, POSESLIDE_RELAX_REST) == 0) {
+ pose_slide_exit(op);
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ pso = op->customdata;
+ }
+
+ /* do common exec work */
+ return pose_slide_exec_common(C, op, pso);
+}
+
+void POSE_OT_relax_rest(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Relax Pose to Rest Pose";
+ ot->idname = "POSE_OT_relax_rest";
+ ot->description = "Make the current pose more similar to the rest pose";
+
+ /* callbacks */
+ ot->exec = pose_slide_relax_rest_exec;
+ ot->invoke = pose_slide_relax_rest_invoke;
+ ot->modal = pose_slide_modal;
+ ot->cancel = pose_slide_cancel;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_USE_EVAL_DATA;
+
+ /* Properties */
+ pose_slide_opdef_properties(ot);
+}
+
+/* ........................ */
/* invoke() - for 'breakdown' mode */
static int pose_slide_breakdown_invoke(bContext *C, wmOperator *op, const wmEvent *event)
diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c
index 6207d5412cf..49b66429515 100644
--- a/source/blender/editors/armature/pose_transform.c
+++ b/source/blender/editors/armature/pose_transform.c
@@ -59,6 +59,9 @@
#include "ED_screen.h"
#include "ED_util.h"
+#include "UI_interface.h"
+#include "UI_resources.h"
+
#include "armature_intern.h"
/* ********************************************** */
@@ -87,6 +90,229 @@ static void applyarmature_fix_boneparents(const bContext *C, Scene *scene, Objec
}
}
+/* Sets the bone head, tail and roll to match the supplied parameters. */
+static void applyarmature_set_edit_position(EditBone *curbone,
+ const float pose_mat[4][4],
+ const float new_tail[3],
+ float r_new_arm_mat[4][4])
+{
+ /* Simply copy the head/tail values from pchan over to curbone. */
+ copy_v3_v3(curbone->head, pose_mat[3]);
+ copy_v3_v3(curbone->tail, new_tail);
+
+ /* Fix roll:
+ * 1. find auto-calculated roll value for this bone now
+ * 2. remove this from the 'visual' y-rotation
+ */
+ {
+ float premat[3][3], pmat[3][3];
+ float delta[3];
+
+ /* Obtain new auto y-rotation. */
+ sub_v3_v3v3(delta, curbone->tail, curbone->head);
+
+ copy_m3_m4(pmat, pose_mat);
+ mat3_vec_to_roll(pmat, delta, &curbone->roll);
+
+ /* Compute new rest pose matrix if requested. */
+ if (r_new_arm_mat) {
+ vec_roll_to_mat3(delta, curbone->roll, premat);
+ copy_m4_m3(r_new_arm_mat, premat);
+ copy_v3_v3(r_new_arm_mat[3], pose_mat[3]);
+ }
+ }
+}
+
+/* Copy properties over from pchan to curbone and reset channels. */
+static void applyarmature_transfer_properties(EditBone *curbone,
+ bPoseChannel *pchan,
+ const bPoseChannel *pchan_eval)
+{
+ /* Combine pose and rest values for bendy bone settings,
+ * then clear the pchan values (so we don't get a double-up).
+ */
+ if (pchan->bone->segments > 1) {
+ /* Combine rest/pose values. */
+ curbone->curve_in_x += pchan_eval->curve_in_x;
+ curbone->curve_in_y += pchan_eval->curve_in_y;
+ curbone->curve_out_x += pchan_eval->curve_out_x;
+ curbone->curve_out_y += pchan_eval->curve_out_y;
+ curbone->roll1 += pchan_eval->roll1;
+ curbone->roll2 += pchan_eval->roll2;
+ curbone->ease1 += pchan_eval->ease1;
+ curbone->ease2 += pchan_eval->ease2;
+
+ curbone->scale_in_x *= pchan_eval->scale_in_x;
+ curbone->scale_in_y *= pchan_eval->scale_in_y;
+ curbone->scale_out_x *= pchan_eval->scale_out_x;
+ curbone->scale_out_y *= pchan_eval->scale_out_y;
+
+ /* Reset pose values. */
+ pchan->curve_in_x = pchan->curve_out_x = 0.0f;
+ pchan->curve_in_y = pchan->curve_out_y = 0.0f;
+ pchan->roll1 = pchan->roll2 = 0.0f;
+ pchan->ease1 = pchan->ease2 = 0.0f;
+ pchan->scale_in_x = pchan->scale_in_y = 1.0f;
+ pchan->scale_out_x = pchan->scale_out_y = 1.0f;
+ }
+
+ /* Clear transform values for pchan. */
+ zero_v3(pchan->loc);
+ zero_v3(pchan->eul);
+ unit_qt(pchan->quat);
+ unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
+ pchan->size[0] = pchan->size[1] = pchan->size[2] = 1.0f;
+
+ /* Set anim lock. */
+ curbone->flag |= BONE_UNKEYED;
+}
+
+/* Adjust the current edit position of the bone using the pose space matrix. */
+static void applyarmature_adjust_edit_position(bArmature *arm,
+ bPoseChannel *pchan,
+ const float delta_mat[4][4],
+ float r_new_arm_mat[4][4])
+{
+ EditBone *curbone = ED_armature_ebone_find_name(arm->edbo, pchan->name);
+ float delta[3], new_tail[3], premat[3][3], new_pose[4][4];
+
+ /* Current orientation matrix. */
+ sub_v3_v3v3(delta, curbone->tail, curbone->head);
+ vec_roll_to_mat3(delta, curbone->roll, premat);
+
+ /* New location and orientation. */
+ mul_m4_m4m3(new_pose, delta_mat, premat);
+ mul_v3_m4v3(new_pose[3], delta_mat, curbone->head);
+ mul_v3_m4v3(new_tail, delta_mat, curbone->tail);
+
+ applyarmature_set_edit_position(curbone, new_pose, new_tail, r_new_arm_mat);
+}
+
+/* Data about parent position for Apply To Selected mode. */
+typedef struct ApplyArmature_ParentState {
+ Bone *bone;
+
+ /* New rest position of the bone with scale included. */
+ float new_rest_mat[4][4];
+ /* New arm_mat of the bone == new_rest_mat without scale. */
+ float new_arm_mat[4][4];
+} ApplyArmature_ParentState;
+
+/* Recursive walk for Apply To Selected mode; pstate NULL unless child of an applied bone. */
+static void applyarmature_process_selected_rec(bArmature *arm,
+ bPose *pose,
+ bPose *pose_eval,
+ Bone *bone,
+ ListBase *selected,
+ ApplyArmature_ParentState *pstate)
+{
+ bPoseChannel *pchan = BKE_pose_channel_find_name(pose, bone->name);
+ const bPoseChannel *pchan_eval = BKE_pose_channel_find_name(pose_eval, bone->name);
+
+ if (!pchan || !pchan_eval)
+ return;
+
+ ApplyArmature_ParentState new_pstate = {.bone = bone};
+
+ if (BLI_findptr(selected, pchan, offsetof(CollectionPointerLink, ptr.data))) {
+ /* SELECTED BONE: Snap to final pose transform minus unapplied parent effects.
+ *
+ * I.e. bone position with accumulated parent effects but no local
+ * transformation will match the original final pose_mat.
+ *
+ * Pose channels are reset as expected.
+ */
+ EditBone *curbone = ED_armature_ebone_find_name(arm->edbo, pchan->name);
+ BoneParentTransform invparent;
+ float new_tail[3];
+
+ if (pchan->parent) {
+ BoneParentTransform old_bpt, new_bpt;
+ float offs_bone[4][4];
+
+ /* Parent effects on the bone transform that have to be removed. */
+ BKE_bone_offset_matrix_get(bone, offs_bone);
+ BKE_bone_parent_transform_calc_from_matrices(
+ bone->flag, offs_bone, bone->parent->arm_mat, pchan_eval->parent->pose_mat, &old_bpt);
+
+ /* Applied parent effects that have to be kept, if any. */
+ float(*new_parent_pose)[4] = pstate ? pstate->new_rest_mat : bone->parent->arm_mat;
+ BKE_bone_parent_transform_calc_from_matrices(
+ bone->flag, offs_bone, bone->parent->arm_mat, new_parent_pose, &new_bpt);
+
+ BKE_bone_parent_transform_invert(&old_bpt);
+ BKE_bone_parent_transform_combine(&new_bpt, &old_bpt, &invparent);
+ }
+ else {
+ BKE_bone_parent_transform_clear(&invparent);
+ }
+
+ /* Apply change without inherited unapplied parent transformations. */
+ BKE_bone_parent_transform_apply(&invparent, pchan_eval->pose_mat, new_pstate.new_rest_mat);
+
+ copy_v3_fl3(new_tail, 0.0, bone->length, 0.0);
+ mul_m4_v3(new_pstate.new_rest_mat, new_tail);
+
+ applyarmature_set_edit_position(
+ curbone, new_pstate.new_rest_mat, new_tail, new_pstate.new_arm_mat);
+ applyarmature_transfer_properties(curbone, pchan, pchan_eval);
+
+ pstate = &new_pstate;
+ }
+ else if (pstate) {
+ /* UNSELECTED CHILD OF SELECTED: Include applied parent effects.
+ *
+ * The inherited transform of applied (selected) bones is baked
+ * into the rest pose so that the final bone position doesn't
+ * change.
+ *
+ * Pose channels are not changed, with the exception of the inherited
+ * applied parent scale being baked into the location pose channel.
+ */
+ BoneParentTransform bpt;
+ float offs_bone[4][4], delta[4][4], old_chan_loc[3];
+
+ /* Include applied parent effects. */
+ BKE_bone_offset_matrix_get(bone, offs_bone);
+ BKE_bone_parent_transform_calc_from_matrices(
+ bone->flag, offs_bone, pstate->bone->arm_mat, pstate->new_rest_mat, &bpt);
+
+ unit_m4(new_pstate.new_rest_mat);
+ BKE_bone_parent_transform_apply(&bpt, new_pstate.new_rest_mat, new_pstate.new_rest_mat);
+
+ /* Bone location channel in pose space relative to bone head. */
+ mul_v3_mat3_m4v3(old_chan_loc, bpt.loc_mat, pchan_eval->loc);
+
+ /* Apply the change to the rest bone position. */
+ invert_m4_m4(delta, bone->arm_mat);
+ mul_m4_m4m4(delta, new_pstate.new_rest_mat, delta);
+
+ applyarmature_adjust_edit_position(arm, pchan, delta, new_pstate.new_arm_mat);
+
+ /* Location pose channel has to be updated, because it is affected
+ * by parent scaling, and the rest pose has no scale by definition. */
+ if (!(bone->flag & BONE_CONNECTED) && !is_zero_v3(old_chan_loc)) {
+ float inv_parent_arm[4][4];
+
+ /* Compute the channel coordinate space matrices for the new rest state. */
+ invert_m4_m4(inv_parent_arm, pstate->new_arm_mat);
+ mul_m4_m4m4(offs_bone, inv_parent_arm, new_pstate.new_arm_mat);
+ BKE_bone_parent_transform_calc_from_matrices(
+ bone->flag, offs_bone, pstate->new_arm_mat, pstate->new_arm_mat, &bpt);
+
+ /* Re-apply the location to keep the final effect. */
+ invert_m4(bpt.loc_mat);
+ mul_v3_mat3_m4v3(pchan->loc, bpt.loc_mat, old_chan_loc);
+ }
+
+ pstate = &new_pstate;
+ }
+
+ for (Bone *child = bone->childbase.first; child; child = child->next) {
+ applyarmature_process_selected_rec(arm, pose, pose_eval, child, selected, pstate);
+ }
+}
+
/* set the current pose as the restpose */
static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
{
@@ -99,7 +325,9 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
bArmature *arm = BKE_armature_from_object(ob);
bPose *pose;
bPoseChannel *pchan;
- EditBone *curbone;
+ ListBase selected_bones;
+
+ const bool use_selected = RNA_boolean_get(op->ptr, "selected");
/* don't check if editmode (should be done by caller) */
if (ob->type != OB_ARMATURE) {
@@ -119,80 +347,37 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
"transforms stored are relative to the old rest pose");
}
+ /* Find selected bones before switching to edit mode. */
+ if (use_selected) {
+ CTX_data_selected_pose_bones(C, &selected_bones);
+
+ if (!selected_bones.first) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+
/* Get editbones of active armature to alter */
ED_armature_to_edit(arm);
/* get pose of active object and move it out of posemode */
pose = ob->pose;
- for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- const bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
- curbone = ED_armature_ebone_find_name(arm->edbo, pchan->name);
-
- /* simply copy the head/tail values from pchan over to curbone */
- copy_v3_v3(curbone->head, pchan_eval->pose_head);
- copy_v3_v3(curbone->tail, pchan_eval->pose_tail);
-
- /* fix roll:
- * 1. find auto-calculated roll value for this bone now
- * 2. remove this from the 'visual' y-rotation
- */
- {
- float premat[3][3], imat[3][3], pmat[3][3], tmat[3][3];
- float delta[3], eul[3];
-
- /* obtain new auto y-rotation */
- sub_v3_v3v3(delta, curbone->tail, curbone->head);
- vec_roll_to_mat3(delta, 0.0f, premat);
- invert_m3_m3(imat, premat);
-
- /* get pchan 'visual' matrix */
- copy_m3_m4(pmat, pchan_eval->pose_mat);
-
- /* remove auto from visual and get euler rotation */
- mul_m3_m3m3(tmat, imat, pmat);
- mat3_to_eul(eul, tmat);
-
- /* just use this euler-y as new roll value */
- curbone->roll = eul[1];
+ if (use_selected) {
+ /* The selected only mode requires a recursive walk to handle parent-child relations. */
+ for (Bone *bone = arm->bonebase.first; bone; bone = bone->next) {
+ applyarmature_process_selected_rec(arm, pose, ob_eval->pose, bone, &selected_bones, NULL);
}
- /* combine pose and rest values for bendy bone settings,
- * then clear the pchan values (so we don't get a double-up)
- */
- if (pchan->bone->segments > 1) {
- /* combine rest/pose values */
- curbone->curve_in_x += pchan_eval->curve_in_x;
- curbone->curve_in_y += pchan_eval->curve_in_y;
- curbone->curve_out_x += pchan_eval->curve_out_x;
- curbone->curve_out_y += pchan_eval->curve_out_y;
- curbone->roll1 += pchan_eval->roll1;
- curbone->roll2 += pchan_eval->roll2;
- curbone->ease1 += pchan_eval->ease1;
- curbone->ease2 += pchan_eval->ease2;
- curbone->scale_in_x *= pchan_eval->scale_in_x;
- curbone->scale_in_y *= pchan_eval->scale_in_y;
- curbone->scale_out_x *= pchan_eval->scale_out_x;
- curbone->scale_out_y *= pchan_eval->scale_out_y;
-
- /* reset pose values */
- pchan->curve_in_x = pchan->curve_out_x = 0.0f;
- pchan->curve_in_y = pchan->curve_out_y = 0.0f;
- pchan->roll1 = pchan->roll2 = 0.0f;
- pchan->ease1 = pchan->ease2 = 0.0f;
- pchan->scale_in_x = pchan->scale_in_y = 1.0f;
- pchan->scale_out_x = pchan->scale_out_y = 1.0f;
- }
-
- /* clear transform values for pchan */
- zero_v3(pchan->loc);
- zero_v3(pchan->eul);
- unit_qt(pchan->quat);
- unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
- pchan->size[0] = pchan->size[1] = pchan->size[2] = 1.0f;
+ BLI_freelistN(&selected_bones);
+ }
+ else {
+ for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
+ const bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
+ EditBone *curbone = ED_armature_ebone_find_name(arm->edbo, pchan->name);
- /* set anim lock */
- curbone->flag |= BONE_UNKEYED;
+ applyarmature_set_edit_position(curbone, pchan_eval->pose_mat, pchan_eval->pose_tail, NULL);
+ applyarmature_transfer_properties(curbone, pchan, pchan_eval);
+ }
}
/* convert editbones back to bones, and then free the edit-data */
@@ -212,6 +397,17 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+static void apply_armature_pose2bones_ui(bContext *C, wmOperator *op)
+{
+ uiLayout *layout = op->layout;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ PointerRNA ptr;
+
+ RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
+
+ uiItemR(layout, &ptr, "selected", 0, NULL, ICON_NONE);
+}
+
void POSE_OT_armature_apply(wmOperatorType *ot)
{
/* identifiers */
@@ -222,9 +418,16 @@ void POSE_OT_armature_apply(wmOperatorType *ot)
/* callbacks */
ot->exec = apply_armature_pose2bones_exec;
ot->poll = ED_operator_posemode;
+ ot->ui = apply_armature_pose2bones_ui;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
+
+ RNA_def_boolean(ot->srna,
+ "selected",
+ false,
+ "Selected Only",
+ "Only apply the selected bones (with propagation to children)");
}
/* set the current pose as the restpose */
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index a787b45c13c..65f502d5cd2 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -5551,6 +5551,8 @@ static int add_vertex_exec(bContext *C, wmOperator *op)
}
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
DEG_id_tag_update(obedit->data, 0);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 463c2144276..9ef0657ae83 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -314,7 +314,7 @@ static int gpencil_paintmode_toggle_exec(bContext *C, wmOperator *op)
BKE_paint_ensure(ts, (Paint **)&ts->gp_paint);
Paint *paint = &ts->gp_paint->paint;
/* if not exist, create a new one */
- if (paint->brush == NULL) {
+ if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) {
BKE_brush_gpencil_presets(C);
}
BKE_paint_toolslots_brush_validate(bmain, &ts->gp_paint->paint);
diff --git a/source/blender/editors/gpencil/gpencil_merge.c b/source/blender/editors/gpencil/gpencil_merge.c
index 9d3c2a6e271..93d8555e014 100644
--- a/source/blender/editors/gpencil/gpencil_merge.c
+++ b/source/blender/editors/gpencil/gpencil_merge.c
@@ -110,7 +110,7 @@ static bGPDstroke *gpencil_prepare_stroke(bContext *C, wmOperator *op, int totpo
Paint *paint = &ts->gp_paint->paint;
/* if not exist, create a new one */
- if (paint->brush == NULL) {
+ if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) {
/* create new brushes */
BKE_brush_gpencil_presets(C);
}
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index b1b29356060..cd1ebc91fbb 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -1819,7 +1819,7 @@ static void gp_init_drawing_brush(bContext *C, tGPsdata *p)
Paint *paint = &ts->gp_paint->paint;
bool changed = false;
/* if not exist, create a new one */
- if (paint->brush == NULL) {
+ if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) {
/* create new brushes */
BKE_brush_gpencil_presets(C);
changed = true;
diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c
index 08fee2bb393..bff17bf5078 100644
--- a/source/blender/editors/gpencil/gpencil_primitive.c
+++ b/source/blender/editors/gpencil/gpencil_primitive.c
@@ -314,7 +314,7 @@ static void gp_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi)
/* if brush doesn't exist, create a new one */
Paint *paint = &ts->gp_paint->paint;
/* if not exist, create a new one */
- if (paint->brush == NULL) {
+ if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) {
/* create new brushes */
BKE_brush_gpencil_presets(C);
}
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index 129bd01574c..93a80f0fcf8 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -1387,7 +1387,7 @@ void ED_gpencil_add_defaults(bContext *C, Object *ob)
BKE_paint_ensure(ts, (Paint **)&ts->gp_paint);
Paint *paint = &ts->gp_paint->paint;
/* if not exist, create a new one */
- if (paint->brush == NULL) {
+ if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) {
/* create new brushes */
BKE_brush_gpencil_presets(C);
}
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index 6342a8b26d9..cd68981dee3 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -403,7 +403,8 @@ typedef enum eAnimFilter_Flags {
/* -------------- Channel Defines -------------- */
/* channel heights */
-#define ACHANNEL_FIRST_TOP(ac) (-0.4f * (ac)->yscale_fac * U.widget_unit)
+#define ACHANNEL_FIRST_TOP(ac) \
+ (UI_view2d_scale_get_y(&(ac)->ar->v2d) * -UI_SCRUBBING_MARGIN_Y - ACHANNEL_SKIP)
#define ACHANNEL_HEIGHT(ac) (0.8f * (ac)->yscale_fac * U.widget_unit)
#define ACHANNEL_SKIP (0.1f * U.widget_unit)
#define ACHANNEL_STEP(ac) (ACHANNEL_HEIGHT(ac) + ACHANNEL_SKIP)
@@ -420,14 +421,15 @@ typedef enum eAnimFilter_Flags {
/* -------------- NLA Channel Defines -------------- */
/* NLA channel heights */
-#define NLACHANNEL_FIRST_TOP(snla) (-0.4f * U.widget_unit)
+#define NLACHANNEL_FIRST_TOP(ac) \
+ (UI_view2d_scale_get_y(&(ac)->ar->v2d) * -UI_SCRUBBING_MARGIN_Y - NLACHANNEL_SKIP)
#define NLACHANNEL_HEIGHT(snla) \
((snla && (snla->flag & SNLA_NOSTRIPCURVES)) ? (0.8f * U.widget_unit) : (1.2f * U.widget_unit))
#define NLACHANNEL_SKIP (0.1f * U.widget_unit)
#define NLACHANNEL_STEP(snla) (NLACHANNEL_HEIGHT(snla) + NLACHANNEL_SKIP)
/* Additional offset to give some room at the end. */
-#define NLACHANNEL_TOT_HEIGHT(snla, item_amount) \
- (-NLACHANNEL_FIRST_TOP(snla) + NLACHANNEL_STEP(snla) * (item_amount + 1))
+#define NLACHANNEL_TOT_HEIGHT(ac, item_amount) \
+ (-NLACHANNEL_FIRST_TOP(ac) + NLACHANNEL_STEP(((SpaceNla *)(ac)->sl)) * (item_amount + 1))
/* channel widths */
#define NLACHANNEL_NAMEWIDTH (10 * U.widget_unit)
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index ce8521a1f6a..c6d25e6f988 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -163,7 +163,10 @@ bool EDBM_backbuf_circle_init(struct ViewContext *vc, short xs, short ys, short
struct BMVert *EDBM_vert_find_nearest_ex(struct ViewContext *vc,
float *r_dist,
const bool use_select_bias,
- bool use_cycle);
+ bool use_cycle,
+ struct Base **bases,
+ uint bases_len,
+ uint *r_base_index);
struct BMVert *EDBM_vert_find_nearest(struct ViewContext *vc, float *r_dist);
struct BMEdge *EDBM_edge_find_nearest_ex(struct ViewContext *vc,
@@ -171,7 +174,10 @@ struct BMEdge *EDBM_edge_find_nearest_ex(struct ViewContext *vc,
float *r_dist_center,
const bool use_select_bias,
const bool use_cycle,
- struct BMEdge **r_eed_zbuf);
+ struct BMEdge **r_eed_zbuf,
+ struct Base **bases,
+ uint bases_len,
+ uint *r_base_index);
struct BMEdge *EDBM_edge_find_nearest(struct ViewContext *vc, float *r_dist);
struct BMFace *EDBM_face_find_nearest_ex(struct ViewContext *vc,
@@ -179,7 +185,10 @@ struct BMFace *EDBM_face_find_nearest_ex(struct ViewContext *vc,
float *r_dist_center,
const bool use_select_bias,
const bool use_cycle,
- struct BMFace **r_efa_zbuf);
+ struct BMFace **r_efa_zbuf,
+ struct Base **bases,
+ uint bases_len,
+ uint *r_base_index);
struct BMFace *EDBM_face_find_nearest(struct ViewContext *vc, float *r_dist);
bool EDBM_unified_findnearest(struct ViewContext *vc,
@@ -230,6 +239,7 @@ void em_setup_viewcontext(struct bContext *C, struct ViewContext *vc); /* rename
bool EDBM_mesh_deselect_all_multi_ex(struct Base **bases, const uint bases_len);
bool EDBM_mesh_deselect_all_multi(struct bContext *C);
+/* Only use for modes that don't support multi-edit-modes (painting). */
extern unsigned int bm_vertoffs, bm_solidoffs, bm_wireoffs;
/* editmesh_preselect_edgering.c */
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index 264eb6abdf1..a7a95a4a659 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -87,9 +87,12 @@ void ED_region_panels_ex(const struct bContext *C,
void ED_region_panels(const struct bContext *C, struct ARegion *ar);
void ED_region_panels_layout_ex(const struct bContext *C,
struct ARegion *ar,
+ struct ListBase *paneltypes,
const char *contexts[],
int contextnr,
- const bool vertical);
+ const bool vertical,
+ const char *category_override);
+
void ED_region_panels_layout(const struct bContext *C, struct ARegion *ar);
void ED_region_panels_draw(const struct bContext *C, struct ARegion *ar);
@@ -440,8 +443,9 @@ enum {
ED_KEYMAP_ANIMATION = (1 << 6),
ED_KEYMAP_FRAMES = (1 << 7),
ED_KEYMAP_HEADER = (1 << 8),
- ED_KEYMAP_GPENCIL = (1 << 9),
- ED_KEYMAP_FOOTER = (1 << 10),
+ ED_KEYMAP_FOOTER = (1 << 9),
+ ED_KEYMAP_GPENCIL = (1 << 10),
+ ED_KEYMAP_NAVBAR = (1 << 11),
};
/* SCREEN_OT_space_context_cycle direction */
diff --git a/source/blender/editors/include/ED_time_scrub_ui.h b/source/blender/editors/include/ED_time_scrub_ui.h
new file mode 100644
index 00000000000..a2e3098e949
--- /dev/null
+++ b/source/blender/editors/include/ED_time_scrub_ui.h
@@ -0,0 +1,43 @@
+/*
+ * 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) 2019 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup editors
+ */
+
+#ifndef __ED_SCRUBBING_H__
+#define __ED_SCRUBBING_H__
+
+struct View2DGrid;
+struct bContext;
+struct bDopeSheet;
+struct wmEvent;
+
+void ED_scrubbing_draw(const struct ARegion *ar,
+ const struct Scene *scene,
+ bool display_seconds,
+ bool discrete_frames);
+
+bool ED_event_in_scrubbing_region(const struct ARegion *ar, const struct wmEvent *event);
+
+void ED_channel_search_draw(const struct bContext *C,
+ struct ARegion *ar,
+ struct bDopeSheet *dopesheet);
+
+#endif /* __ED_SCRUBBING_H__ */
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index fd51419a3ee..3503d38ad92 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -730,4 +730,9 @@ void ED_view3d_gizmo_mesh_preselect_get_active(struct bContext *C,
struct Base **r_base,
struct BMElem **r_ele);
+/* space_view3d.c */
+void ED_view3d_buttons_region_layout_ex(const struct bContext *C,
+ struct ARegion *ar,
+ const char *category_override);
+
#endif /* __ED_VIEW3D_H__ */
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index b4d345a3344..9ee9e952856 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -24,6 +24,9 @@
/* Note: this is included multiple times with different #defines for DEF_ICON. */
/* Auto define more specific types for places that do not need the distinction. */
+#ifndef DEF_ICON_SCENE
+# define DEF_ICON_SCENE DEF_ICON
+#endif
#ifndef DEF_ICON_COLLECTION
# define DEF_ICON_COLLECTION DEF_ICON
#endif
@@ -133,8 +136,8 @@ DEF_ICON_SHADING(MATERIAL)
DEF_ICON_SHADING(TEXTURE)
DEF_ICON(ANIM)
DEF_ICON_SHADING(WORLD)
-DEF_ICON(SCENE)
-DEF_ICON(OUTPUT)
+DEF_ICON_SCENE(SCENE)
+DEF_ICON_SCENE(OUTPUT)
DEF_ICON_BLANK(145)
DEF_ICON_BLANK(146)
DEF_ICON(SCRIPT)
@@ -142,7 +145,7 @@ DEF_ICON_MODIFIER(PARTICLES)
DEF_ICON_MODIFIER(PHYSICS)
DEF_ICON_OBJECT_DATA(SPEAKER)
DEF_ICON_BLANK(151)
-DEF_ICON(TOOL_SETTINGS)
+DEF_ICON_SCENE(TOOL_SETTINGS)
DEF_ICON_MODIFIER(SHADERFX)
DEF_ICON_MODIFIER(MODIFIER)
DEF_ICON_BLANK(155)
@@ -211,8 +214,8 @@ DEF_ICON(TRACKING_REFINE_FORWARDS)
DEF_ICON_BLANK(77b)
/* DATA */
-DEF_ICON(SCENE_DATA)
-DEF_ICON(RENDERLAYERS)
+DEF_ICON_SCENE(SCENE_DATA)
+DEF_ICON_SCENE(RENDERLAYERS)
DEF_ICON_SHADING(WORLD_DATA)
DEF_ICON_OBJECT(OBJECT_DATA)
DEF_ICON_OBJECT_DATA(MESH_DATA)
@@ -243,8 +246,8 @@ DEF_ICON_SHADING(BRUSH_DATA)
DEF_ICON_SHADING(IMAGE_DATA)
DEF_ICON(FILE)
DEF_ICON(FCURVE)
-DEF_ICON(FONT_DATA)
-DEF_ICON(RENDER_RESULT)
+DEF_ICON_OBJECT_DATA(FONT_DATA)
+DEF_ICON_SCENE(RENDER_RESULT)
DEF_ICON_OBJECT_DATA(SURFACE_DATA)
DEF_ICON_OBJECT_DATA(EMPTY_DATA)
DEF_ICON(PRESET)
@@ -320,7 +323,7 @@ DEF_ICON(RESTRICT_SELECT_ON)
DEF_ICON(RESTRICT_SELECT_OFF)
DEF_ICON(RESTRICT_RENDER_ON)
DEF_ICON(RESTRICT_RENDER_OFF)
-DEF_ICON_BLANK(330)
+DEF_ICON(RESTRICT_INSTANCED_OFF)
/* OUTLINER */
DEF_ICON_OBJECT_DATA(OUTLINER_DATA_EMPTY)
@@ -334,7 +337,7 @@ DEF_ICON_OBJECT_DATA(OUTLINER_DATA_ARMATURE)
DEF_ICON_OBJECT_DATA(OUTLINER_DATA_FONT)
DEF_ICON_OBJECT_DATA(OUTLINER_DATA_SURFACE)
DEF_ICON_OBJECT_DATA(OUTLINER_DATA_SPEAKER)
-DEF_ICON_BLANK(344)
+DEF_ICON_OBJECT_DATA(OUTLINER_DATA_LIGHTPROBE)
DEF_ICON_BLANK(345)
DEF_ICON_OBJECT_DATA(OUTLINER_DATA_GREASEPENCIL)
DEF_ICON(GP_SELECT_POINTS)
@@ -348,7 +351,7 @@ DEF_ICON(ONIONSKIN_OFF)
DEF_ICON(ONIONSKIN_ON)
DEF_ICON(RESTRICT_VIEW_ON)
DEF_ICON(RESTRICT_VIEW_OFF)
-DEF_ICON_BLANK(353)
+DEF_ICON(RESTRICT_INSTANCED_ON)
/* PRIMITIVES */
DEF_ICON(MESH_PLANE)
@@ -456,11 +459,11 @@ DEF_ICON_BLANK(707)
DEF_ICON_BLANK(708)
DEF_ICON_BLANK(709)
DEF_ICON_BLANK(710)
-DEF_ICON_BLANK(711)
-DEF_ICON_BLANK(712)
-DEF_ICON_BLANK(713)
-DEF_ICON_BLANK(714)
-DEF_ICON_BLANK(715)
+DEF_ICON(SELECT_SET)
+DEF_ICON(SELECT_EXTEND)
+DEF_ICON(SELECT_SUBTRACT)
+DEF_ICON(SELECT_INTERSECT)
+DEF_ICON(SELECT_DIFFERENCE)
/* EMPTY */
DEF_ICON(ALIGN_LEFT)
@@ -708,7 +711,7 @@ DEF_ICON_BLANK(240)
DEF_ICON_BLANK(241)
DEF_ICON_BLANK(242)
DEF_ICON_BLANK(243)
-DEF_ICON_BLANK(244)
+DEF_ICON(GIZMO)
DEF_ICON(ORIENTATION_CURSOR)
DEF_ICON(NORMALS_VERTEX)
DEF_ICON(NORMALS_FACE)
@@ -1022,6 +1025,7 @@ DEF_ICON_COLOR(EVENT_RETURN)
#undef DEF_ICON
#undef DEF_ICON_ERROR
+#undef DEF_ICON_SCENE
#undef DEF_ICON_COLLECTION
#undef DEF_ICON_OBJECT
#undef DEF_ICON_OBJECT_DATA
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 18960853011..14d681ee817 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -228,6 +228,7 @@ enum {
#define UI_PANEL_WIDTH 340
#define UI_COMPACT_PANEL_WIDTH 160
+#define UI_SIDEBAR_PANEL_WIDTH 220
#define UI_NAVIGATION_REGION_WIDTH UI_COMPACT_PANEL_WIDTH
#define UI_NARROW_NAVIGATION_REGION_WIDTH 100
@@ -594,9 +595,16 @@ struct uiLayout *UI_pie_menu_layout(struct uiPieMenu *pie);
typedef uiBlock *(*uiBlockCreateFunc)(struct bContext *C, struct ARegion *ar, void *arg1);
typedef void (*uiBlockCancelFunc)(struct bContext *C, void *arg1);
-void UI_popup_block_invoke(struct bContext *C, uiBlockCreateFunc func, void *arg);
-void UI_popup_block_invoke_ex(
- struct bContext *C, uiBlockCreateFunc func, void *arg, const char *opname, int opcontext);
+void UI_popup_block_invoke(struct bContext *C,
+ uiBlockCreateFunc func,
+ void *arg,
+ void (*arg_free)(void *arg));
+void UI_popup_block_invoke_ex(struct bContext *C,
+ uiBlockCreateFunc func,
+ void *arg,
+ void (*arg_free)(void *arg),
+ const char *opname,
+ int opcontext);
void UI_popup_block_ex(struct bContext *C,
uiBlockCreateFunc func,
uiBlockHandleFunc popup_func,
@@ -641,6 +649,7 @@ enum {
UI_BLOCK_THEME_STYLE_POPUP = 1,
};
void UI_block_theme_style_set(uiBlock *block, char theme_style);
+char UI_block_emboss_get(uiBlock *block);
void UI_block_emboss_set(uiBlock *block, char dt);
void UI_block_free(const struct bContext *C, uiBlock *block);
diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h
index 5666421c27f..1f15fa3bd4d 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -52,8 +52,11 @@ typedef struct IconFile {
* Resizable Icons for Blender
*/
void UI_icons_init(void);
+void UI_icons_reload_internal_textures(void);
+
int UI_icon_get_width(int icon_id);
int UI_icon_get_height(int icon_id);
+bool UI_icon_get_theme_color(int icon_id, unsigned char color[4]);
void UI_id_icon_render(const struct bContext *C,
struct Scene *scene,
@@ -64,16 +67,17 @@ int UI_preview_render_size(enum eIconSizes size);
void UI_icon_draw(float x, float y, int icon_id);
void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha);
-void UI_icon_draw_preview(float x, float y, int icon_id);
-void UI_icon_draw_preview_aspect(float x, float y, int icon_id, float aspect);
-void UI_icon_draw_preview_aspect_size(
- float x, float y, int icon_id, float aspect, float alpha, int size);
-
-void UI_icon_draw_aspect(
- float x, float y, int icon_id, float aspect, float alpha, const char mono_color[4]);
-void UI_icon_draw_aspect_color(
- float x, float y, int icon_id, float aspect, const float rgb[3], const char mono_color[4]);
-void UI_icon_draw_size(float x, float y, int size, int icon_id, float alpha);
+void UI_icon_draw_preview(float x, float y, int icon_id, float aspect, float alpha, int size);
+
+void UI_icon_draw_ex(float x,
+ float y,
+ int icon_id,
+ float aspect,
+ float alpha,
+ float desaturate,
+ const char mono_color[4],
+ const bool mono_border);
+
void UI_icon_draw_desaturate(float x,
float y,
int icon_id,
@@ -81,6 +85,7 @@ void UI_icon_draw_desaturate(float x,
float alpha,
float desaturate,
const char mono_color[4]);
+
void UI_icons_free(void);
void UI_icons_free_drawinfo(void *drawinfo);
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index af94889a1bb..7abc27c5b37 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -105,6 +105,7 @@ typedef enum ThemeColorID {
TH_FACE_DOT,
TH_FACEDOT_SIZE,
TH_CFRAME,
+ TH_SCRUBBING_BACKGROUND,
TH_TIME_KEYFRAME,
TH_TIME_GP_KEYFRAME,
TH_NURB_ULINE,
@@ -261,12 +262,15 @@ typedef enum ThemeColorID {
TH_ANIM_INACTIVE, /* no active action */
TH_ANIM_PREVIEW_RANGE, /* preview range overlay */
+ TH_ICON_SCENE,
TH_ICON_COLLECTION,
TH_ICON_OBJECT,
TH_ICON_OBJECT_DATA,
TH_ICON_MODIFIER,
TH_ICON_SHADING,
+ TH_SCROLL_TEXT,
+
TH_NLA_TWEAK, /* 'tweaking' track in NLA */
TH_NLA_TWEAK_DUPLI, /* error/warning flag for other strips referencing dupli strip */
@@ -380,7 +384,7 @@ void UI_GetThemeColorType3ubv(int colorid, int spacetype, unsigned char col[3]);
void UI_GetThemeColorType4ubv(int colorid, int spacetype, unsigned char col[4]);
// get theme color for coloring monochrome icons
-bool UI_GetIconThemeColor4fv(int colorid, float col[4]);
+bool UI_GetIconThemeColor4ubv(int colorid, unsigned char col[4]);
// shade a 3 byte color (same as UI_GetColorPtrBlendShade3ubv with 0.0 factor)
void UI_GetColorPtrShade3ubv(const unsigned char cp1[3], unsigned char col[3], int offset);
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index 064951d40ed..d03d4b1b4f5 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -63,9 +63,9 @@ enum eView2D_CommonViewTypes {
/* scroller area */
#define V2D_SCROLL_HEIGHT (0.45f * U.widget_unit)
#define V2D_SCROLL_WIDTH (0.45f * U.widget_unit)
-/* For scrollers with scale markings (text written onto them) */
-#define V2D_SCROLL_HEIGHT_TEXT (0.79f * U.widget_unit)
-#define V2D_SCROLL_WIDTH_TEXT (0.79f * U.widget_unit)
+/* For scrollers with scale handlers */
+#define V2D_SCROLL_HEIGHT_HANDLES (0.6f * U.widget_unit)
+#define V2D_SCROLL_WIDTH_HANDLES (0.6f * U.widget_unit)
/* scroller 'handles' hotspot radius for mouse */
#define V2D_SCROLLER_HANDLE_SIZE (0.6f * U.widget_unit)
@@ -258,6 +258,8 @@ void UI_view2d_smooth_view(struct bContext *C,
struct ARegion *ar,
const struct rctf *cur,
const int smooth_viewtx);
+
#define UI_MARKER_MARGIN_Y (42 * UI_DPI_FAC)
+#define UI_SCRUBBING_MARGIN_Y (23 * UI_DPI_FAC)
#endif /* __UI_VIEW2D_H__ */
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 42f4b4495c3..7c60ac75df8 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -3235,6 +3235,11 @@ uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, sh
return block;
}
+char UI_block_emboss_get(uiBlock *block)
+{
+ return block->dt;
+}
+
void UI_block_emboss_set(uiBlock *block, char dt)
{
block->dt = dt;
diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c
index b9de504f3b2..e34d67b6996 100644
--- a/source/blender/editors/interface/interface_anim.c
+++ b/source/blender/editors/interface/interface_anim.c
@@ -82,6 +82,11 @@ void ui_but_anim_flag(uiBut *but, float cfra)
if (fcu) {
if (!driven) {
+ /* Empty curves are ignored by the animation evaluation system. */
+ if (fcu->totvert == 0) {
+ return;
+ }
+
but->flag |= UI_BUT_ANIMATED;
/* T41525 - When the active action is a NLA strip being edited,
diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c
index 748d6e6c183..0055349d4be 100644
--- a/source/blender/editors/interface/interface_context_menu.c
+++ b/source/blender/editors/interface/interface_context_menu.c
@@ -58,30 +58,90 @@
/** \name Button Context Menu
* \{ */
-static void but_shortcut_name_func(bContext *C, void *arg1, int UNUSED(event))
+static IDProperty *shortcut_property_from_rna(bContext *C, uiBut *but)
{
- uiBut *but = (uiBut *)arg1;
+ /* Compute data path from context to property. */
+ const char *member_id = WM_context_member_from_ptr(C, &but->rnapoin);
+ const char *data_path = RNA_path_from_ID_to_struct(&but->rnapoin);
+ const char *member_id_data_path = member_id;
+
+ if (data_path) {
+ member_id_data_path = BLI_sprintfN("%s.%s", member_id, data_path);
+ MEM_freeN((void *)data_path);
+ }
- if (but->optype) {
- char shortcut_str[128];
+ const char *prop_id = RNA_property_identifier(but->rnaprop);
+ const char *final_data_path = BLI_sprintfN("%s.%s", member_id_data_path, prop_id);
- IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
+ if (member_id != member_id_data_path) {
+ MEM_freeN((void *)member_id_data_path);
+ }
+
+ /* Create ID property of data path, to pass to the operator. */
+ IDProperty *prop;
+ IDPropertyTemplate val = {0};
+ prop = IDP_New(IDP_GROUP, &val, __func__);
+ IDP_AddToGroup(prop, IDP_NewString(final_data_path, "data_path", strlen(final_data_path) + 1));
+
+ MEM_freeN((void *)final_data_path);
+
+ return prop;
+}
- /* complex code to change name of button */
- if (WM_key_event_operator_string(C,
- but->optype->idname,
- but->opcontext,
- prop,
- true,
- shortcut_str,
- sizeof(shortcut_str))) {
- ui_but_add_shortcut(but, shortcut_str, true);
+static const char *shortcut_get_operator_property(bContext *C, uiBut *but, IDProperty **prop)
+{
+ if (but->optype) {
+ /* Operator */
+ *prop = (but->opptr) ? IDP_CopyProperty(but->opptr->data) : NULL;
+ return but->optype->idname;
+ }
+ else if (but->rnaprop) {
+ if (RNA_property_type(but->rnaprop) == PROP_BOOLEAN) {
+ /* Boolean */
+ *prop = shortcut_property_from_rna(C, but);
+ return "WM_OT_context_toggle";
}
- else {
- /* simply strip the shortcut */
- ui_but_add_shortcut(but, NULL, true);
+ else if (RNA_property_type(but->rnaprop) == PROP_ENUM) {
+ /* Enum */
+ *prop = shortcut_property_from_rna(C, but);
+ return "WM_OT_context_menu_enum";
}
}
+
+ *prop = NULL;
+ return NULL;
+}
+
+static void shortcut_free_operator_property(IDProperty *prop)
+{
+ if (prop) {
+ IDP_FreeProperty(prop);
+ MEM_freeN(prop);
+ }
+}
+
+static void but_shortcut_name_func(bContext *C, void *arg1, int UNUSED(event))
+{
+ uiBut *but = (uiBut *)arg1;
+ char shortcut_str[128];
+
+ IDProperty *prop;
+ const char *idname = shortcut_get_operator_property(C, but, &prop);
+ if (idname == NULL) {
+ return;
+ }
+
+ /* complex code to change name of button */
+ if (WM_key_event_operator_string(
+ C, idname, but->opcontext, prop, true, shortcut_str, sizeof(shortcut_str))) {
+ ui_but_add_shortcut(but, shortcut_str, true);
+ }
+ else {
+ /* simply strip the shortcut */
+ ui_but_add_shortcut(but, NULL, true);
+ }
+
+ shortcut_free_operator_property(prop);
}
static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg)
@@ -94,15 +154,18 @@ static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg)
PointerRNA ptr;
uiLayout *layout;
uiStyle *style = UI_style_get_dpi();
- IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
+ IDProperty *prop;
+ const char *idname = shortcut_get_operator_property(C, but, &prop);
kmi = WM_key_event_operator(C,
- but->optype->idname,
+ idname,
but->opcontext,
prop,
EVT_TYPE_MASK_HOTKEY_INCLUDE,
EVT_TYPE_MASK_HOTKEY_EXCLUDE,
&km);
+ U.runtime.is_dirty = true;
+
BLI_assert(kmi != NULL);
RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr);
@@ -118,6 +181,8 @@ static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg)
UI_block_bounds_set_popup(block, 6, (const int[2]){-50, 26});
+ shortcut_free_operator_property(prop);
+
return block;
}
@@ -135,25 +200,24 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg)
PointerRNA ptr;
uiLayout *layout;
uiStyle *style = UI_style_get_dpi();
- IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
int kmi_id;
+ IDProperty *prop;
+ const char *idname = shortcut_get_operator_property(C, but, &prop);
/* XXX this guess_opname can potentially return a different keymap
* than being found on adding later... */
- km = WM_keymap_guess_opname(C, but->optype->idname);
- kmi = WM_keymap_add_item(km, but->optype->idname, AKEY, KM_PRESS, 0, 0);
+ km = WM_keymap_guess_opname(C, idname);
+ kmi = WM_keymap_add_item(km, idname, AKEY, KM_PRESS, 0, 0);
kmi_id = kmi->id;
- /* copy properties, prop can be NULL for reset */
- if (prop) {
- prop = IDP_CopyProperty(prop);
- }
+ /* This takes ownership of prop, or prop can be NULL for reset. */
WM_keymap_item_properties_reset(kmi, prop);
/* update and get pointers again */
WM_keyconfig_update(wm);
+ U.runtime.is_dirty = true;
- km = WM_keymap_guess_opname(C, but->optype->idname);
+ km = WM_keymap_guess_opname(C, idname);
kmi = WM_keymap_item_find_id(km, kmi_id);
RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr);
@@ -171,6 +235,7 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg)
#ifdef USE_KEYMAP_ADD_HACK
g_kmi_id_hack = kmi_id;
#endif
+
return block;
}
@@ -179,20 +244,21 @@ static void menu_add_shortcut_cancel(struct bContext *C, void *arg1)
uiBut *but = (uiBut *)arg1;
wmKeyMap *km;
wmKeyMapItem *kmi;
-#ifndef USE_KEYMAP_ADD_HACK
- IDProperty *prop;
-#endif
int kmi_id;
+ IDProperty *prop;
+ const char *idname = shortcut_get_operator_property(C, but, &prop);
+
#ifdef USE_KEYMAP_ADD_HACK
- km = WM_keymap_guess_opname(C, but->optype->idname);
+ km = WM_keymap_guess_opname(C, idname);
kmi_id = g_kmi_id_hack;
UNUSED_VARS(but);
#else
- prop = (but->opptr) ? but->opptr->data : NULL;
- kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, true, &km);
+ kmi_id = WM_key_event_operator_id(C, idname, but->opcontext, prop, true, &km);
#endif
+ shortcut_free_operator_property(prop);
+
kmi = WM_keymap_item_find_id(km, kmi_id);
WM_keymap_remove_item(km, kmi);
}
@@ -200,7 +266,7 @@ static void menu_add_shortcut_cancel(struct bContext *C, void *arg1)
static void popup_change_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
{
uiBut *but = (uiBut *)arg1;
- UI_popup_block_invoke(C, menu_change_shortcut, but);
+ UI_popup_block_invoke(C, menu_change_shortcut, but, NULL);
}
static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
@@ -208,10 +274,11 @@ static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
uiBut *but = (uiBut *)arg1;
wmKeyMap *km;
wmKeyMapItem *kmi;
- IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
+ IDProperty *prop;
+ const char *idname = shortcut_get_operator_property(C, but, &prop);
kmi = WM_key_event_operator(C,
- but->optype->idname,
+ idname,
but->opcontext,
prop,
EVT_TYPE_MASK_HOTKEY_INCLUDE,
@@ -220,7 +287,9 @@ static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
BLI_assert(kmi != NULL);
WM_keymap_remove_item(km, kmi);
+ U.runtime.is_dirty = true;
+ shortcut_free_operator_property(prop);
but_shortcut_name_func(C, but, 0);
}
@@ -323,6 +392,7 @@ static void popup_user_menu_add_or_replace_func(bContext *C, void *arg1, void *U
{
uiBut *but = arg1;
bUserMenu *um = ED_screen_user_menu_ensure(C);
+ U.runtime.is_dirty = true;
ui_but_user_menu_add(C, but, um);
}
@@ -330,6 +400,7 @@ static void popup_user_menu_remove_func(bContext *UNUSED(C), void *arg1, void *a
{
bUserMenu *um = arg1;
bUserMenuItem *umi = arg2;
+ U.runtime.is_dirty = true;
ED_screen_user_menu_item_remove(&um->items, umi);
}
@@ -890,16 +961,18 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
uiItemS(layout);
}
- /* Operator buttons */
- if (but->optype) {
+ /* Shortcut menu */
+ IDProperty *prop;
+ const char *idname = shortcut_get_operator_property(C, but, &prop);
+ if (idname != NULL) {
uiBlock *block = uiLayoutGetBlock(layout);
uiBut *but2;
- IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
int w = uiLayoutGetWidth(layout);
wmKeyMap *km;
+
/* We want to know if this op has a shortcut, be it hotkey or not. */
wmKeyMapItem *kmi = WM_key_event_operator(
- C, but->optype->idname, but->opcontext, prop, EVT_TYPE_MASK_ALL, 0, &km);
+ C, idname, but->opcontext, prop, EVT_TYPE_MASK_ALL, 0, &km);
/* We do have a shortcut, but only keyboard ones are editable that way... */
if (kmi) {
@@ -971,7 +1044,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
}
}
/* only show 'assign' if there's a suitable key map for it to go in */
- else if (WM_keymap_guess_opname(C, but->optype->idname)) {
+ else if (WM_keymap_guess_opname(C, idname)) {
but2 = uiDefIconTextBut(block,
UI_BTYPE_BUT,
0,
@@ -990,6 +1063,8 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
UI_but_func_set(but2, popup_add_shortcut_func, but, NULL);
}
+ shortcut_free_operator_property(prop);
+
/* Set the operator pointer for python access */
uiLayoutSetContextFromBut(layout, but);
@@ -1108,6 +1183,9 @@ void ui_popup_context_menu_for_panel(bContext *C, ARegion *ar, Panel *pa)
if (!any_item_visible) {
return;
}
+ if (pa->type->parent != NULL) {
+ return;
+ }
RNA_pointer_create(&sc->id, &RNA_Panel, pa, &ptr);
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 111dfe01319..e4adf757c80 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -551,6 +551,32 @@ static bool ui_but_dragedit_update_mval(uiHandleButtonData *data, int mx)
return true;
}
+static void ui_but_update_preferences_dirty(uiBut *but)
+{
+ /* Not very elegant, but ensures preference changes force re-save. */
+ bool tag = false;
+ if (but->rnaprop) {
+ if (but->rnapoin.data == &U) {
+ /* Exclude navigation from setting dirty. */
+ extern PropertyRNA rna_Preferences_active_section;
+ if (!ELEM(but->rnaprop, &rna_Preferences_active_section)) {
+ tag = true;
+ }
+ }
+ else {
+ StructRNA *base = RNA_struct_base(but->rnapoin.type);
+ if (ELEM(base, &RNA_AddonPreferences, &RNA_KeyConfigPreferences)) {
+ tag = true;
+ }
+ }
+ }
+
+ if (tag) {
+ U.runtime.is_dirty = true;
+ WM_main_add_notifier(NC_WINDOW, NULL);
+ }
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -1334,6 +1360,9 @@ static bool ui_drag_toggle_set_xy_xy(
if (do_check) {
ui_but_update_edited(but);
}
+ if (U.runtime.is_dirty == false) {
+ ui_but_update_preferences_dirty(but);
+ }
changed = true;
}
}
@@ -3769,7 +3798,7 @@ static void ui_block_open_begin(bContext *C, uiBut *but, uiHandleButtonData *dat
}
if (func || handlefunc) {
- data->menu = ui_popup_block_create(C, data->region, but, func, handlefunc, arg);
+ data->menu = ui_popup_block_create(C, data->region, but, func, handlefunc, arg, NULL);
if (but->block->handle) {
data->menu->popup = but->block->handle->popup;
}
@@ -5622,6 +5651,13 @@ static int ui_do_but_UNITVEC(
}
}
}
+ else if (event->type == ESCKEY || event->type == RIGHTMOUSE) {
+ if (event->val == KM_PRESS) {
+ data->cancel = true;
+ data->escapecancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ }
else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
@@ -7566,6 +7602,10 @@ static void button_activate_exit(
if (block->flag & UI_BLOCK_POPUP_MEMORY) {
ui_popup_menu_memory_set(block, but);
}
+
+ if (U.runtime.is_dirty == false) {
+ ui_but_update_preferences_dirty(but);
+ }
}
/* disable tooltips until mousemove + last active flag */
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 7e295f83390..e53e9694617 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -37,6 +37,7 @@
#include "BLI_utildefines.h"
#include "BLI_fileops_types.h"
#include "BLI_math_vector.h"
+#include "BLI_math_color_blend.h"
#include "DNA_brush_types.h"
#include "DNA_curve_types.h"
@@ -83,6 +84,7 @@
# define ICON_GRID_COLS 26
# define ICON_GRID_ROWS 30
+# define ICON_MONO_BORDER_OUTSET 2
# define ICON_GRID_MARGIN 10
# define ICON_GRID_W 32
# define ICON_GRID_H 32
@@ -138,7 +140,8 @@ typedef struct DrawInfo {
} DrawInfo;
typedef struct IconTexture {
- GLuint id;
+ GLuint id[2];
+ int num_textures;
int w;
int h;
float invw;
@@ -154,12 +157,13 @@ typedef struct IconType {
/* static here to cache results of icon directory scan, so it's not
* scanning the filesystem each time the menu is drawn */
static struct ListBase iconfilelist = {NULL, NULL};
-static IconTexture icongltex = {0, 0, 0, 0.0f, 0.0f};
+static IconTexture icongltex = {{0, 0}, 0, 0, 0, 0.0f, 0.0f};
#ifndef WITH_HEADLESS
static const IconType icontypes[] = {
# define DEF_ICON(name) {ICON_TYPE_MONO_TEXTURE, 0},
+# define DEF_ICON_SCENE(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_SCENE},
# define DEF_ICON_COLLECTION(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_COLLECTION},
# define DEF_ICON_OBJECT(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_OBJECT},
# define DEF_ICON_OBJECT_DATA(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_OBJECT_DATA},
@@ -713,38 +717,146 @@ static void icon_verify_datatoc(IconImage *iimg)
}
}
-static void init_internal_icons(void)
+static ImBuf *create_mono_icon_with_border(ImBuf *buf,
+ int resolution_divider,
+ float border_intensity)
{
- // bTheme *btheme = UI_GetTheme();
- ImBuf *b16buf = NULL, *b32buf = NULL;
- int x, y;
+ ImBuf *result = IMB_dupImBuf(buf);
+ const float border_sharpness = 16.0 / (resolution_divider * resolution_divider);
-# if 0 // temp disabled
- if ((btheme != NULL) && btheme->tui.iconfile[0]) {
- char *icondir = BKE_appdir_folder_id(BLENDER_DATAFILES, "icons");
- char iconfilestr[FILE_MAX];
+ float blurred_alpha_buffer[(ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) *
+ (ICON_GRID_H + 2 * ICON_MONO_BORDER_OUTSET)];
+ const int icon_width = (ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) / resolution_divider;
+ const int icon_height = (ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) / resolution_divider;
- if (icondir) {
- BLI_join_dirfile(iconfilestr, sizeof(iconfilestr), icondir, btheme->tui.iconfile);
+ for (int y = 0; y < ICON_GRID_ROWS; y++) {
+ for (int x = 0; x < ICON_GRID_COLS; x++) {
+ IconType icontype = icontypes[y * ICON_GRID_COLS + x];
+ if (icontype.type != ICON_TYPE_MONO_TEXTURE) {
+ continue;
+ }
- /* if the image is missing bbuf will just be NULL */
- bbuf = IMB_loadiffname(iconfilestr, IB_rect, NULL);
+ int sx = x * (ICON_GRID_W + ICON_GRID_MARGIN) + ICON_GRID_MARGIN - ICON_MONO_BORDER_OUTSET;
+ int sy = y * (ICON_GRID_H + ICON_GRID_MARGIN) + ICON_GRID_MARGIN - ICON_MONO_BORDER_OUTSET;
+ sx = sx / resolution_divider;
+ sy = sy / resolution_divider;
+
+ /* blur the alpha channel and store it in blurred_alpha_buffer */
+ int blur_size = 2 / resolution_divider;
+ for (int bx = 0; bx < icon_width; bx++) {
+ const int asx = MAX2(bx - blur_size, 0);
+ const int aex = MIN2(bx + blur_size + 1, icon_width);
+ for (int by = 0; by < icon_height; by++) {
+ const int asy = MAX2(by - blur_size, 0);
+ const int aey = MIN2(by + blur_size + 1, icon_height);
+
+ // blur alpha channel
+ const int write_offset = by * (ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) + bx;
+ float alpha_accum = 0.0;
+ unsigned int alpha_samples = 0;
+ for (int ax = asx; ax < aex; ax++) {
+ for (int ay = asy; ay < aey; ay++) {
+ const int offset_read = (sy + ay) * buf->x + (sx + ax);
+ unsigned int color_read = buf->rect[offset_read];
+ const float alpha_read = ((color_read & 0xff000000) >> 24) / 255.0;
+ alpha_accum += alpha_read;
+ alpha_samples += 1;
+ }
+ }
+ blurred_alpha_buffer[write_offset] = alpha_accum / alpha_samples;
+ }
+ }
- if (bbuf && (bbuf->x < ICON_IMAGE_W || bbuf->y < ICON_IMAGE_H)) {
- printf(
- "\n***WARNING***\n"
- "Icons file '%s' too small.\n"
- "Using built-in Icons instead\n",
- iconfilestr);
- IMB_freeImBuf(bbuf);
- bbuf = NULL;
+ /* apply blurred alpha */
+ for (int bx = 0; bx < icon_width; bx++) {
+ for (int by = 0; by < icon_height; by++) {
+ const int blurred_alpha_offset = by * (ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) + bx;
+ const int offset_write = (sy + by) * buf->x + (sx + bx);
+ const float blurred_alpha = blurred_alpha_buffer[blurred_alpha_offset];
+ float border_srgb[4] = {
+ 0, 0, 0, MIN2(1.0, blurred_alpha * border_sharpness) * border_intensity};
+
+ const unsigned int color_read = buf->rect[offset_write];
+ const unsigned char *orig_color = (unsigned char *)&color_read;
+
+ float border_rgba[4];
+ float orig_rgba[4];
+ float dest_rgba[4];
+ float dest_srgb[4];
+
+ srgb_to_linearrgb_v4(border_rgba, border_srgb);
+ srgb_to_linearrgb_uchar4(orig_rgba, orig_color);
+ blend_color_interpolate_float(dest_rgba, orig_rgba, border_rgba, 1.0 - orig_rgba[3]);
+ linearrgb_to_srgb_v4(dest_srgb, dest_rgba);
+
+ unsigned int alpha_mask = ((unsigned int)(dest_srgb[3] * 255)) << 24;
+ unsigned int cpack = rgb_to_cpack(dest_srgb[0], dest_srgb[1], dest_srgb[2]) | alpha_mask;
+ result->rect[offset_write] = cpack;
+ }
}
}
- else {
- printf("%s: 'icons' data path not found, continuing\n", __func__);
+ }
+ return result;
+}
+
+/* Generate the mipmap levels for the icon textures
+ * During creation the source16 ImBuf will be freed to reduce memory overhead
+ * A new ImBuf will be returned that needs is owned by the caller.
+ *
+ * FIXME: Mipmap levels are generated until the width of the image is 1, which
+ * are too many levels than that are needed.*/
+static ImBuf *create_mono_icon_mipmaps(ImBuf *source32, ImBuf *source16, int level)
+{
+ if (level == 0) {
+ glTexImage2D(GL_TEXTURE_2D,
+ level,
+ GL_RGBA8,
+ source32->x,
+ source32->y,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ source32->rect);
+ return create_mono_icon_mipmaps(source32, source16, level + 1);
+ }
+ else {
+ glTexImage2D(GL_TEXTURE_2D,
+ level,
+ GL_RGBA8,
+ source16->x,
+ source16->y,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ source16->rect);
+ if (source16->x > 1) {
+ ImBuf *nbuf = IMB_onehalf(source16);
+ IMB_freeImBuf(source16);
+ source16 = create_mono_icon_mipmaps(source32, nbuf, level + 1);
}
+ return source16;
}
-# endif
+}
+
+static void free_icons_textures(void)
+{
+ if (icongltex.num_textures > 0) {
+ glDeleteTextures(icongltex.num_textures, icongltex.id);
+ icongltex.id[0] = 0;
+ icongltex.id[1] = 0;
+ icongltex.num_textures = 0;
+ }
+}
+
+/* Reload the textures for internal icons.
+ * This function will release the previous textures. */
+void UI_icons_reload_internal_textures(void)
+{
+ bTheme *btheme = UI_GetTheme();
+ ImBuf *b16buf = NULL, *b32buf = NULL, *b16buf_border = NULL, *b32buf_border = NULL;
+ const float icon_border_intensity = btheme->tui.icon_border_intensity;
+ bool need_icons_with_border = icon_border_intensity > 0.0f;
+
if (b16buf == NULL) {
b16buf = IMB_ibImageFromMemory((const uchar *)datatoc_blender_icons16_png,
datatoc_blender_icons16_png_size,
@@ -753,6 +865,10 @@ static void init_internal_icons(void)
"<blender icons>");
}
if (b16buf) {
+ if (need_icons_with_border) {
+ b16buf_border = create_mono_icon_with_border(b16buf, 2, icon_border_intensity);
+ IMB_premultiply_alpha(b16buf_border);
+ }
IMB_premultiply_alpha(b16buf);
}
@@ -764,88 +880,97 @@ static void init_internal_icons(void)
"<blender icons>");
}
if (b32buf) {
+ if (need_icons_with_border) {
+ b32buf_border = create_mono_icon_with_border(b32buf, 1, icon_border_intensity);
+ IMB_premultiply_alpha(b32buf_border);
+ }
IMB_premultiply_alpha(b32buf);
}
if (b16buf && b32buf) {
/* Free existing texture if any. */
- if (icongltex.id) {
- glDeleteTextures(1, &icongltex.id);
- icongltex.id = 0;
- }
+ free_icons_textures();
/* Allocate OpenGL texture. */
- glGenTextures(1, &icongltex.id);
-
- if (icongltex.id) {
- int level = 2;
+ icongltex.num_textures = need_icons_with_border ? 2 : 1;
+ glGenTextures(icongltex.num_textures, icongltex.id);
+ if (icongltex.id[0]) {
icongltex.w = b32buf->x;
icongltex.h = b32buf->y;
icongltex.invw = 1.0f / b32buf->x;
icongltex.invh = 1.0f / b32buf->y;
- glBindTexture(GL_TEXTURE_2D, icongltex.id);
-
- glTexImage2D(GL_TEXTURE_2D,
- 0,
- GL_RGBA8,
- b32buf->x,
- b32buf->y,
- 0,
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- b32buf->rect);
- glTexImage2D(GL_TEXTURE_2D,
- 1,
- GL_RGBA8,
- b16buf->x,
- b16buf->y,
- 0,
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- b16buf->rect);
-
- while (b16buf->x > 1) {
- ImBuf *nbuf = IMB_onehalf(b16buf);
- glTexImage2D(GL_TEXTURE_2D,
- level,
- GL_RGBA8,
- nbuf->x,
- nbuf->y,
- 0,
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- nbuf->rect);
- level++;
- IMB_freeImBuf(b16buf);
- b16buf = nbuf;
- }
-
+ glBindTexture(GL_TEXTURE_2D, icongltex.id[0]);
+ b16buf = create_mono_icon_mipmaps(b32buf, b16buf, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+ if (need_icons_with_border && icongltex.id[1]) {
+ glBindTexture(GL_TEXTURE_2D, icongltex.id[1]);
+ b16buf_border = create_mono_icon_mipmaps(b32buf_border, b16buf_border, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
}
+ }
- /* Define icons. */
- for (y = 0; y < ICON_GRID_ROWS; y++) {
- /* Row W has monochrome icons. */
- for (x = 0; x < ICON_GRID_COLS; x++) {
- IconType icontype = icontypes[y * ICON_GRID_COLS + x];
- if (!ELEM(icontype.type, ICON_TYPE_COLOR_TEXTURE, ICON_TYPE_MONO_TEXTURE)) {
- continue;
- }
+ IMB_freeImBuf(b16buf);
+ IMB_freeImBuf(b32buf);
+ IMB_freeImBuf(b16buf_border);
+ IMB_freeImBuf(b32buf_border);
+}
+
+static void init_internal_icons(void)
+{
+ int x, y;
+
+# if 0 // temp disabled
+ if ((btheme != NULL) && btheme->tui.iconfile[0]) {
+ char *icondir = BKE_appdir_folder_id(BLENDER_DATAFILES, "icons");
+ char iconfilestr[FILE_MAX];
+
+ if (icondir) {
+ BLI_join_dirfile(iconfilestr, sizeof(iconfilestr), icondir, btheme->tui.iconfile);
+
+ /* if the image is missing bbuf will just be NULL */
+ bbuf = IMB_loadiffname(iconfilestr, IB_rect, NULL);
- def_internal_icon(b32buf,
- BIFICONID_FIRST + y * ICON_GRID_COLS + x,
- x * (ICON_GRID_W + ICON_GRID_MARGIN) + ICON_GRID_MARGIN,
- y * (ICON_GRID_H + ICON_GRID_MARGIN) + ICON_GRID_MARGIN,
- ICON_GRID_W,
- icontype.type,
- icontype.theme_color);
+ if (bbuf && (bbuf->x < ICON_IMAGE_W || bbuf->y < ICON_IMAGE_H)) {
+ printf(
+ "\n***WARNING***\n"
+ "Icons file '%s' too small.\n"
+ "Using built-in Icons instead\n",
+ iconfilestr);
+ IMB_freeImBuf(bbuf);
+ bbuf = NULL;
}
}
+ else {
+ printf("%s: 'icons' data path not found, continuing\n", __func__);
+ }
+ }
+# endif
+
+ /* Define icons. */
+ for (y = 0; y < ICON_GRID_ROWS; y++) {
+ /* Row W has monochrome icons. */
+ for (x = 0; x < ICON_GRID_COLS; x++) {
+ IconType icontype = icontypes[y * ICON_GRID_COLS + x];
+ if (!ELEM(icontype.type, ICON_TYPE_COLOR_TEXTURE, ICON_TYPE_MONO_TEXTURE)) {
+ continue;
+ }
+
+ def_internal_icon(NULL,
+ BIFICONID_FIRST + y * ICON_GRID_COLS + x,
+ x * (ICON_GRID_W + ICON_GRID_MARGIN) + ICON_GRID_MARGIN,
+ y * (ICON_GRID_H + ICON_GRID_MARGIN) + ICON_GRID_MARGIN,
+ ICON_GRID_W,
+ icontype.type,
+ icontype.theme_color);
+ }
}
def_internal_vicon(ICON_SMALL_TRI_RIGHT_VEC, vicon_small_tri_right_draw);
@@ -882,9 +1007,6 @@ static void init_internal_icons(void)
def_internal_vicon(ICON_COLORSET_18_VEC, vicon_colorset_draw_18);
def_internal_vicon(ICON_COLORSET_19_VEC, vicon_colorset_draw_19);
def_internal_vicon(ICON_COLORSET_20_VEC, vicon_colorset_draw_20);
-
- IMB_freeImBuf(b16buf);
- IMB_freeImBuf(b32buf);
}
# endif /* WITH_HEADLESS */
@@ -990,11 +1112,7 @@ ListBase *UI_iconfile_list(void)
void UI_icons_free(void)
{
#ifndef WITH_HEADLESS
- if (icongltex.id) {
- glDeleteTextures(1, &icongltex.id);
- icongltex.id = 0;
- }
-
+ free_icons_textures();
free_iconfile_list(&iconfilelist);
BKE_icons_free();
#endif
@@ -1104,10 +1222,22 @@ int UI_icon_get_height(int icon_id)
return 0;
}
+bool UI_icon_get_theme_color(int icon_id, uchar color[4])
+{
+ Icon *icon = BKE_icon_get(icon_id);
+ if (icon == NULL) {
+ return false;
+ }
+
+ DrawInfo *di = icon_ensure_drawinfo(icon);
+ return UI_GetIconThemeColor4ubv(di->data.texture.theme_color, color);
+}
+
void UI_icons_init()
{
#ifndef WITH_HEADLESS
init_iconfile_list(&iconfilelist);
+ UI_icons_reload_internal_textures();
init_internal_icons();
init_brush_icons();
init_event_icons();
@@ -1348,7 +1478,6 @@ static void icon_draw_rect(float x,
int rh,
uint *rect,
float alpha,
- const float rgb[3],
const float desaturate)
{
ImBuf *ima = NULL;
@@ -1366,12 +1495,6 @@ static void icon_draw_rect(float x,
/* modulate color */
float col[4] = {1.0f, 1.0f, 1.0f, alpha};
- if (rgb) {
- col[0] = rgb[0];
- col[1] = rgb[1];
- col[2] = rgb[2];
- }
-
/* rect contains image in 'rendersize', we only scale if needed */
if (rw != w || rh != h) {
/* preserve aspect ratio and center */
@@ -1439,12 +1562,17 @@ typedef struct IconDrawCall {
float color[4];
} IconDrawCall;
-static struct {
+typedef struct IconTextureDrawCall {
IconDrawCall drawcall_cache[ICON_DRAW_CACHE_SIZE];
int calls; /* Number of calls batched together */
+} IconTextureDrawCall;
+
+static struct {
+ IconTextureDrawCall normal;
+ IconTextureDrawCall border;
bool enabled;
float mat[4][4];
-} g_icon_draw_cache = {{{{0}}}};
+} g_icon_draw_cache = {{{{{0}}}}};
void UI_icon_draw_cache_begin(void)
{
@@ -1452,19 +1580,15 @@ void UI_icon_draw_cache_begin(void)
g_icon_draw_cache.enabled = true;
}
-static void icon_draw_cache_flush_ex(void)
+static void icon_draw_cache_texture_flush_ex(GLuint texture,
+ IconTextureDrawCall *texture_draw_calls)
{
- if (g_icon_draw_cache.calls == 0) {
+ if (texture_draw_calls->calls == 0) {
return;
}
- /* We need to flush widget base first to ensure correct ordering. */
- UI_widgetbase_draw_cache_flush();
-
- GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
-
glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, icongltex.id);
+ glBindTexture(GL_TEXTURE_2D, texture);
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR);
GPU_shader_bind(shader);
@@ -1473,16 +1597,43 @@ static void icon_draw_cache_flush_ex(void)
int data_loc = GPU_shader_get_uniform_ensure(shader, "calls_data[0]");
glUniform1i(img_loc, 0);
- glUniform4fv(data_loc, ICON_DRAW_CACHE_SIZE * 3, (float *)g_icon_draw_cache.drawcall_cache);
+ glUniform4fv(data_loc, ICON_DRAW_CACHE_SIZE * 3, (float *)texture_draw_calls->drawcall_cache);
- GPU_draw_primitive(GPU_PRIM_TRIS, 6 * g_icon_draw_cache.calls);
+ GPU_draw_primitive(GPU_PRIM_TRIS, 6 * texture_draw_calls->calls);
glBindTexture(GL_TEXTURE_2D, 0);
- g_icon_draw_cache.calls = 0;
+ texture_draw_calls->calls = 0;
+}
- GPU_blend_set_func_separate(
- GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+static void icon_draw_cache_flush_ex(bool only_full_caches)
+{
+ bool should_draw = false;
+ if (only_full_caches) {
+ should_draw = g_icon_draw_cache.normal.calls == ICON_DRAW_CACHE_SIZE ||
+ g_icon_draw_cache.border.calls == ICON_DRAW_CACHE_SIZE;
+ }
+ else {
+ should_draw = g_icon_draw_cache.normal.calls || g_icon_draw_cache.border.calls;
+ }
+
+ if (should_draw) {
+ /* We need to flush widget base first to ensure correct ordering. */
+ UI_widgetbase_draw_cache_flush();
+
+ GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ if (!only_full_caches || g_icon_draw_cache.normal.calls == ICON_DRAW_CACHE_SIZE) {
+ icon_draw_cache_texture_flush_ex(icongltex.id[0], &g_icon_draw_cache.normal);
+ }
+
+ if (!only_full_caches || g_icon_draw_cache.border.calls == ICON_DRAW_CACHE_SIZE) {
+ icon_draw_cache_texture_flush_ex(icongltex.id[1], &g_icon_draw_cache.border);
+ }
+
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ }
}
void UI_icon_draw_cache_end(void)
@@ -1491,12 +1642,12 @@ void UI_icon_draw_cache_end(void)
g_icon_draw_cache.enabled = false;
/* Don't change blend state if it's not needed. */
- if (g_icon_draw_cache.calls == 0) {
+ if (g_icon_draw_cache.border.calls == 0 && g_icon_draw_cache.normal.calls == 0) {
return;
}
GPU_blend(true);
- icon_draw_cache_flush_ex();
+ icon_draw_cache_flush_ex(false);
GPU_blend(false);
}
@@ -1509,14 +1660,18 @@ static void icon_draw_texture_cached(float x,
int UNUSED(iw),
int ih,
float alpha,
- const float rgb[3])
+ const float rgb[3],
+ bool with_border)
{
float mvp[4][4];
GPU_matrix_model_view_projection_get(mvp);
- IconDrawCall *call = &g_icon_draw_cache.drawcall_cache[g_icon_draw_cache.calls];
- g_icon_draw_cache.calls++;
+ IconTextureDrawCall *texture_call = with_border ? &g_icon_draw_cache.border :
+ &g_icon_draw_cache.normal;
+
+ IconDrawCall *call = &texture_call->drawcall_cache[texture_call->calls];
+ texture_call->calls++;
/* Manual mat4*vec2 */
call->pos.xmin = x * mvp[0][0] + y * mvp[1][0] + mvp[3][0];
@@ -1536,8 +1691,8 @@ static void icon_draw_texture_cached(float x,
copy_v4_fl(call->color, alpha);
}
- if (g_icon_draw_cache.calls == ICON_DRAW_CACHE_SIZE) {
- icon_draw_cache_flush_ex();
+ if (texture_call->calls == ICON_DRAW_CACHE_SIZE) {
+ icon_draw_cache_flush_ex(true);
}
}
@@ -1550,10 +1705,11 @@ static void icon_draw_texture(float x,
int iw,
int ih,
float alpha,
- const float rgb[3])
+ const float rgb[3],
+ bool with_border)
{
if (g_icon_draw_cache.enabled) {
- icon_draw_texture_cached(x, y, w, h, ix, iy, iw, ih, alpha, rgb);
+ icon_draw_texture_cached(x, y, w, h, ix, iy, iw, ih, alpha, rgb, with_border);
return;
}
@@ -1570,7 +1726,7 @@ static void icon_draw_texture(float x,
y2 = (iy + ih) * icongltex.invh;
glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, icongltex.id);
+ glBindTexture(GL_TEXTURE_2D, with_border ? icongltex.id[1] : icongltex.id[0]);
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR);
GPU_shader_bind(shader);
@@ -1614,11 +1770,11 @@ static void icon_draw_size(float x,
int icon_id,
float aspect,
float alpha,
- const float rgb[3],
enum eIconSizes size,
int draw_size,
const float desaturate,
- const char mono_rgba[4])
+ const char mono_rgba[4],
+ const bool mono_border)
{
bTheme *btheme = UI_GetTheme();
Icon *icon = NULL;
@@ -1675,7 +1831,7 @@ static void icon_draw_size(float x,
GPU_blend_set_func_separate(
GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- icon_draw_rect(x, y, w, h, aspect, w, h, ibuf->rect, alpha, rgb, desaturate);
+ icon_draw_rect(x, y, w, h, aspect, w, h, ibuf->rect, alpha, desaturate);
GPU_blend_set_func_separate(
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
}
@@ -1695,36 +1851,42 @@ static void icon_draw_size(float x,
di->data.texture.w,
di->data.texture.h,
alpha,
- rgb);
+ NULL,
+ false);
}
else if (di->type == ICON_TYPE_MONO_TEXTURE) {
- /* icon that matches text color, assumed to be white */
+ /* Monochrome icon that uses text or theme color. */
+ bool with_border = mono_border && (btheme->tui.icon_border_intensity > 0.0f);
float color[4];
- if (!UI_GetIconThemeColor4fv(di->data.texture.theme_color, color)) {
- if (mono_rgba) {
- rgba_uchar_to_float(color, (const uchar *)mono_rgba);
- }
- else {
- UI_GetThemeColor4fv(TH_TEXT, color);
- }
+ if (mono_rgba) {
+ rgba_uchar_to_float(color, (const uchar *)mono_rgba);
}
-
- if (rgb) {
- mul_v3_v3(color, rgb);
+ else {
+ UI_GetThemeColor4fv(TH_TEXT, color);
}
mul_v4_fl(color, alpha);
- icon_draw_texture(x,
- y,
- (float)w,
- (float)h,
- di->data.texture.x,
- di->data.texture.y,
- di->data.texture.w,
- di->data.texture.h,
+ float border_outset = 0.0;
+ unsigned int border_texel = 0;
+#ifndef WITH_HEADLESS
+ if (with_border) {
+ const float scale = (float)ICON_GRID_W / (float)ICON_DEFAULT_WIDTH;
+ border_texel = ICON_MONO_BORDER_OUTSET;
+ border_outset = ICON_MONO_BORDER_OUTSET / (scale * aspect);
+ }
+#endif
+ icon_draw_texture(x - border_outset,
+ y - border_outset,
+ (float)w + 2 * border_outset,
+ (float)h + 2 * border_outset,
+ di->data.texture.x - border_texel,
+ di->data.texture.y - border_texel,
+ di->data.texture.w + 2 * border_texel,
+ di->data.texture.h + 2 * border_texel,
color[3],
- color);
+ color,
+ with_border);
}
else if (di->type == ICON_TYPE_BUFFER) {
@@ -1738,7 +1900,7 @@ static void icon_draw_size(float x,
return;
}
- icon_draw_rect(x, y, w, h, aspect, iimg->w, iimg->h, iimg->rect, alpha, rgb, desaturate);
+ icon_draw_rect(x, y, w, h, aspect, iimg->w, iimg->h, iimg->rect, alpha, desaturate);
}
else if (di->type == ICON_TYPE_PREVIEW) {
PreviewImage *pi = (icon->id_type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) :
@@ -1755,7 +1917,7 @@ static void icon_draw_size(float x,
GPU_blend_set_func_separate(
GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
icon_draw_rect(
- x, y, w, h, aspect, pi->w[size], pi->h[size], pi->rect[size], alpha, rgb, desaturate);
+ x, y, w, h, aspect, pi->w[size], pi->h[size], pi->rect[size], alpha, desaturate);
GPU_blend_set_func_separate(
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
}
@@ -2057,7 +2219,7 @@ int UI_idcode_icon_get(const int idcode)
case ID_PC:
return ICON_CURVE_BEZCURVE; /* TODO! this would need its own icon! */
case ID_LP:
- return ICON_LIGHTPROBE_CUBEMAP;
+ return ICON_OUTLINER_DATA_LIGHTPROBE;
case ID_SCE:
return ICON_SCENE_DATA;
case ID_SPK:
@@ -2077,71 +2239,40 @@ int UI_idcode_icon_get(const int idcode)
}
}
-static void icon_draw_at_size(float x,
- float y,
- int icon_id,
- float aspect,
- float alpha,
- enum eIconSizes size,
- const float desaturate,
- const char mono_color[4])
-{
- int draw_size = get_draw_size(size);
- icon_draw_size(x, y, icon_id, aspect, alpha, NULL, size, draw_size, desaturate, mono_color);
-}
-
-void UI_icon_draw_aspect(
- float x, float y, int icon_id, float aspect, float alpha, const char mono_color[4])
-{
- icon_draw_at_size(x, y, icon_id, aspect, alpha, ICON_SIZE_ICON, 0.0f, mono_color);
-}
-
-void UI_icon_draw_aspect_color(
- float x, float y, int icon_id, float aspect, const float rgb[3], const char mono_color[4])
-{
- int draw_size = get_draw_size(ICON_SIZE_ICON);
- icon_draw_size(x, y, icon_id, aspect, 1.0f, rgb, ICON_SIZE_ICON, draw_size, false, mono_color);
-}
-
-void UI_icon_draw_desaturate(float x,
- float y,
- int icon_id,
- float aspect,
- float alpha,
- float desaturate,
- const char mono_color[4])
-{
- icon_draw_at_size(x, y, icon_id, aspect, alpha, ICON_SIZE_ICON, desaturate, mono_color);
-}
-
/* draws icon with dpi scale factor */
void UI_icon_draw(float x, float y, int icon_id)
{
- UI_icon_draw_aspect(x, y, icon_id, 1.0f / UI_DPI_FAC, 1.0f, NULL);
+ UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, 1.0f, 0.0f, NULL, false);
}
void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha)
{
- UI_icon_draw_aspect(x, y, icon_id, 1.0f / UI_DPI_FAC, alpha, NULL);
-}
-
-void UI_icon_draw_size(float x, float y, int size, int icon_id, float alpha)
-{
- icon_draw_size(x, y, icon_id, 1.0f, alpha, NULL, ICON_SIZE_ICON, size, false, NULL);
+ UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, alpha, 0.0f, NULL, false);
}
-void UI_icon_draw_preview(float x, float y, int icon_id)
+void UI_icon_draw_preview(float x, float y, int icon_id, float aspect, float alpha, int size)
{
- icon_draw_at_size(x, y, icon_id, 1.0f, 1.0f, ICON_SIZE_PREVIEW, false, NULL);
+ icon_draw_size(x, y, icon_id, aspect, alpha, ICON_SIZE_PREVIEW, size, false, NULL, false);
}
-void UI_icon_draw_preview_aspect(float x, float y, int icon_id, float aspect)
+void UI_icon_draw_ex(float x,
+ float y,
+ int icon_id,
+ float aspect,
+ float alpha,
+ float desaturate,
+ const char mono_color[4],
+ const bool mono_border)
{
- icon_draw_at_size(x, y, icon_id, aspect, 1.0f, ICON_SIZE_PREVIEW, false, NULL);
-}
-
-void UI_icon_draw_preview_aspect_size(
- float x, float y, int icon_id, float aspect, float alpha, int size)
-{
- icon_draw_size(x, y, icon_id, aspect, alpha, NULL, ICON_SIZE_PREVIEW, size, false, NULL);
+ int draw_size = get_draw_size(ICON_SIZE_ICON);
+ icon_draw_size(x,
+ y,
+ icon_id,
+ aspect,
+ alpha,
+ ICON_SIZE_ICON,
+ draw_size,
+ desaturate,
+ mono_color,
+ mono_border);
}
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 4af7fdd779f..33288df15ba 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -539,13 +539,12 @@ struct uiKeyNavLock {
typedef uiBlock *(*uiBlockHandleCreateFunc)(struct bContext *C,
struct uiPopupBlockHandle *handle,
void *arg1);
-typedef void (*uiBlockHandleFreeFunc)(struct uiPopupBlockHandle *handle, void *arg1);
struct uiPopupBlockCreate {
uiBlockCreateFunc create_func;
uiBlockHandleCreateFunc handle_create_func;
- uiBlockHandleFreeFunc free_func;
void *arg;
+ void (*arg_free)(void *arg);
int event_xy[2];
@@ -662,7 +661,8 @@ uiPopupBlockHandle *ui_popup_block_create(struct bContext *C,
uiBut *but,
uiBlockCreateFunc create_func,
uiBlockHandleCreateFunc handle_create_func,
- void *arg);
+ void *arg,
+ void (*arg_free)(void *arg));
uiPopupBlockHandle *ui_popup_menu_create(struct bContext *C,
struct ARegion *butregion,
uiBut *but,
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 15e507483ad..37ef0948dee 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -764,7 +764,8 @@ static void ui_item_enum_expand_elem_exec(uiLayout *layout,
if (RNA_property_flag(prop) & PROP_ENUM_FLAG) {
/* If this is set, assert since we're clobbering someone elses callback. */
- BLI_assert(but->func == NULL);
+ /* Buttons get their block's func by default, so we cannot assert in that case either. */
+ BLI_assert(ELEM(but->func, NULL, block->func));
UI_but_func_set(but, ui_item_enum_expand_handle, but, POINTER_FROM_INT(value));
}
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 87e58a4b3b5..46b1279643e 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -258,43 +258,16 @@ static void panels_collapse_all(ScrArea *sa, ARegion *ar, const Panel *from_pa)
}
}
-static void ui_panel_copy_offset(Panel *pa, Panel *papar)
-{
- /* with respect to sizes... papar is parent */
-
- pa->ofsx = papar->ofsx;
- pa->ofsy = papar->ofsy + papar->sizey - pa->sizey;
-}
-
-/**
- * XXX Disabled paneltab handling for now. Old 2.4x feature,
- * *DO NOT* confuse it with new tool tabs in 2.70. ;)
- * See also T41704.
- */
-/* #define UI_USE_PANELTAB */
-
Panel *UI_panel_find_by_type(ListBase *lb, PanelType *pt)
{
Panel *pa;
const char *idname = pt->idname;
-#ifdef UI_USE_PANELTAB
- const char *tabname = pt->idname;
- for (pa = lb->first; pa; pa = pa->next) {
- if (STREQLEN(pa->panelname, idname, sizeof(pa->panelname))) {
- if (STREQLEN(pa->tabname, tabname, sizeof(pa->tabname))) {
- return pa;
- }
- }
- }
-#else
for (pa = lb->first; pa; pa = pa->next) {
if (STREQLEN(pa->panelname, idname, sizeof(pa->panelname))) {
return pa;
}
}
-#endif
-
return NULL;
}
@@ -307,10 +280,6 @@ Panel *UI_panel_begin(
Panel *palast, *panext;
const char *drawname = CTX_IFACE_(pt->translation_context, pt->label);
const char *idname = pt->idname;
-#ifdef UI_USE_PANELTAB
- const char *tabname = pt->idname;
- const char *hookname = NULL;
-#endif
const bool newpanel = (pa == NULL);
int align = panel_aligned(sa, ar);
@@ -341,28 +310,6 @@ Panel *UI_panel_begin(
pa->runtime_flag |= PNL_NEW_ADDED;
BLI_addtail(lb, pa);
-
-#ifdef UI_USE_PANELTAB
- BLI_strncpy(pa->tabname, tabname, sizeof(pa->tabname));
-
- /* make new Panel tabbed? */
- if (hookname) {
- Panel *patab;
- for (patab = lb->first; patab; patab = patab->next) {
- if ((patab->runtime_flag & PNL_ACTIVE) && patab->paneltab == NULL) {
- if (STREQLEN(hookname, patab->panelname, sizeof(patab->panelname))) {
- if (STREQLEN(tabname, patab->tabname, sizeof(patab->tabname))) {
- pa->paneltab = patab;
- ui_panel_copy_offset(pa, patab);
- break;
- }
- }
- }
- }
- }
-#else
- BLI_strncpy(pa->tabname, idname, sizeof(pa->tabname));
-#endif
}
/* Do not allow closed panels without headers! Else user could get "disappeared" UI! */
@@ -411,9 +358,6 @@ Panel *UI_panel_begin(
*r_open = false;
- if (pa->paneltab) {
- return pa;
- }
if (pa->flag & PNL_CLOSED) {
return pa;
}
@@ -706,9 +650,6 @@ void ui_draw_aligned_panel(uiStyle *style,
* can't be dragged. This may be changed in future. */
show_background);
- if (panel->paneltab) {
- return;
- }
if (panel->type && (panel->type->flag & PNL_NO_HEADER)) {
return;
}
@@ -765,12 +706,14 @@ void ui_draw_aligned_panel(uiStyle *style,
panel_title_color_get(show_background, col_title);
GPU_blend(true);
- UI_icon_draw_aspect(headrect.xmax - ((PNL_ICON * 2.2f) / block->aspect),
- headrect.ymin + (5.0f / block->aspect),
- (panel->flag & PNL_PIN) ? ICON_PINNED : ICON_UNPINNED,
- (block->aspect / UI_DPI_FAC),
- 1.0f,
- (const char *)col_title);
+ UI_icon_draw_ex(headrect.xmax - ((PNL_ICON * 2.2f) / block->aspect),
+ headrect.ymin + (5.0f / block->aspect),
+ (panel->flag & PNL_PIN) ? ICON_PINNED : ICON_UNPINNED,
+ (block->aspect * U.inv_dpi_fac),
+ 1.0f,
+ 0.0f,
+ (const char *)col_title,
+ false);
GPU_blend(false);
}
@@ -934,12 +877,6 @@ static int get_panel_real_ofsy(Panel *pa)
if (pa->flag & PNL_CLOSEDY) {
return pa->ofsy + pa->sizey;
}
- else if (pa->paneltab && (pa->paneltab->flag & PNL_CLOSEDY)) {
- return pa->ofsy + pa->sizey;
- }
- else if (pa->paneltab) {
- return pa->paneltab->ofsy;
- }
else {
return pa->ofsy;
}
@@ -950,9 +887,6 @@ static int get_panel_real_ofsx(Panel *pa)
if (pa->flag & PNL_CLOSEDX) {
return pa->ofsx + get_panel_header(pa);
}
- else if (pa->paneltab && (pa->paneltab->flag & PNL_CLOSEDX)) {
- return pa->ofsx + get_panel_header(pa);
- }
else {
return pa->ofsx + pa->sizex;
}
@@ -1067,7 +1001,7 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo
/* count active, not tabbed panels */
for (pa = ar->panels.first; pa; pa = pa->next) {
- if ((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab == NULL) {
+ if (pa->runtime_flag & PNL_ACTIVE) {
tot++;
}
}
@@ -1078,7 +1012,7 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo
/* extra; change close direction? */
for (pa = ar->panels.first; pa; pa = pa->next) {
- if ((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab == NULL) {
+ if (pa->runtime_flag & PNL_ACTIVE) {
if ((pa->flag & PNL_CLOSEDX) && (align == BUT_VERTICAL)) {
pa->flag ^= PNL_CLOSED;
}
@@ -1093,7 +1027,7 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo
ps = panelsort;
for (pa = ar->panels.first; pa; pa = pa->next) {
- if ((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab == NULL) {
+ if (pa->runtime_flag & PNL_ACTIVE) {
ps->pa = MEM_dupallocN(pa);
ps->orig = pa;
ps++;
@@ -1160,9 +1094,6 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo
/* set locations for tabbed and sub panels */
for (pa = ar->panels.first; pa; pa = pa->next) {
if (pa->runtime_flag & PNL_ACTIVE) {
- if (pa->paneltab) {
- ui_panel_copy_offset(pa, pa->paneltab);
- }
if (pa->children.first) {
align_sub_panels(pa);
}
@@ -1265,7 +1196,7 @@ void UI_panels_end(const bContext *C, ARegion *ar, int *r_x, int *r_y)
{
ScrArea *sa = CTX_wm_area(C);
uiBlock *block;
- Panel *panot, *panew, *patest, *pa, *firstpa;
+ Panel *pa, *firstpa;
/* offset contents */
for (block = ar->uiblocks.first; block; block = block->next) {
@@ -1274,31 +1205,6 @@ void UI_panels_end(const bContext *C, ARegion *ar, int *r_x, int *r_y)
}
}
- /* consistency; are panels not made, whilst they have tabs */
- for (panot = ar->panels.first; panot; panot = panot->next) {
- if ((panot->runtime_flag & PNL_ACTIVE) == 0) { /* not made */
-
- for (panew = ar->panels.first; panew; panew = panew->next) {
- if ((panew->runtime_flag & PNL_ACTIVE)) {
- if (panew->paneltab == panot) { /* panew is tab in notmade pa */
- break;
- }
- }
- }
- /* now panew can become the new parent, check all other tabs */
- if (panew) {
- for (patest = ar->panels.first; patest; patest = patest->next) {
- if (patest->paneltab == panot) {
- patest->paneltab = panew;
- }
- }
- panot->paneltab = panew;
- panew->paneltab = NULL;
- ED_region_tag_redraw(ar); /* the buttons panew were not made */
- }
- }
- }
-
/* re-align, possibly with animation */
if (panels_need_realign(sa, ar, &pa)) {
if (pa) {
@@ -1380,7 +1286,7 @@ static void check_panel_overlap(ARegion *ar, Panel *panel)
for (pa = ar->panels.first; pa; pa = pa->next) {
pa->flag &= ~PNL_OVERLAP;
if (panel && (pa != panel)) {
- if (pa->paneltab == NULL && (pa->runtime_flag & PNL_ACTIVE)) {
+ if (pa->runtime_flag & PNL_ACTIVE) {
float safex = 0.2, safey = 0.2;
if (pa->flag & PNL_CLOSEDX) {
@@ -1623,11 +1529,11 @@ static void ui_handle_panel_header(
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
- Panel *pa;
#ifdef USE_PIN_HIDDEN
- const bool show_pin = UI_panel_category_is_visible(ar) && (block->panel->flag & PNL_PIN);
+ const bool show_pin = UI_panel_category_is_visible(ar) && (block->panel->type->parent == NULL) &&
+ (block->panel->flag & PNL_PIN);
#else
- const bool show_pin = UI_panel_category_is_visible(ar);
+ const bool show_pin = UI_panel_category_is_visible(ar) && (block->panel->type->parent == NULL);
#endif
const bool is_subpanel = (block->panel->type && block->panel->type->parent);
const bool show_drag = !is_subpanel;
@@ -1658,8 +1564,10 @@ static void ui_handle_panel_header(
button = 1;
}
else if (ELEM(event, 0, RETKEY, LEFTMOUSE) && shift) {
- block->panel->flag ^= PNL_PIN;
- button = 2;
+ if (block->panel->type->parent == NULL) {
+ block->panel->flag ^= PNL_PIN;
+ button = 2;
+ }
}
else if (block->panel->flag & PNL_CLOSEDX) {
if (my >= block->rect.ymax) {
@@ -1720,17 +1628,6 @@ static void ui_handle_panel_header(
ui_panel_drag_collapse_handler_add(C, true);
}
}
-
- for (pa = ar->panels.first; pa; pa = pa->next) {
- if (pa->paneltab == block->panel) {
- if (block->panel->flag & PNL_CLOSED) {
- pa->flag |= PNL_CLOSED;
- }
- else {
- pa->flag &= ~PNL_CLOSED;
- }
- }
- }
}
if (align) {
@@ -2067,7 +1964,11 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
ui_fontscale(&fstyle_points, aspect / (U.pixelsize * 1.1f));
BLF_size(fontid, fstyle_points, U.dpi);
- BLI_assert(UI_panel_category_is_visible(ar));
+ /* Check the region type supports categories to avoid an assert
+ * for showing 3D view panels in the properties space. */
+ if ((1 << ar->regiontype) & RGN_TYPE_HAS_CATEGORY_MASK) {
+ BLI_assert(UI_panel_category_is_visible(ar));
+ }
/* calculate tab rect's and check if we need to scale down */
for (pc_dyn = ar->panels_category.first; pc_dyn; pc_dyn = pc_dyn->next) {
@@ -2378,7 +2279,7 @@ int ui_handler_panel_region(bContext *C,
/* checks for mouse position inside */
pa = block->panel;
- if (!pa || pa->paneltab != NULL) {
+ if (!pa) {
continue;
}
/* XXX - accessed freed panels when scripts reload, need to fix. */
diff --git a/source/blender/editors/interface/interface_region_menu_pie.c b/source/blender/editors/interface/interface_region_menu_pie.c
index dcbbde259f2..330a9d48ff4 100644
--- a/source/blender/editors/interface/interface_region_menu_pie.c
+++ b/source/blender/editors/interface/interface_region_menu_pie.c
@@ -208,7 +208,7 @@ void UI_pie_menu_end(bContext *C, uiPieMenu *pie)
wmWindow *window = CTX_wm_window(C);
uiPopupBlockHandle *menu;
- menu = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_PIE, pie);
+ menu = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_PIE, pie, NULL);
menu->popup = true;
menu->towardstime = PIL_check_seconds_timer();
diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.c
index b97cbcdfef5..ab3a86ec9e1 100644
--- a/source/blender/editors/interface/interface_region_menu_popup.c
+++ b/source/blender/editors/interface/interface_region_menu_popup.c
@@ -351,7 +351,7 @@ uiPopupBlockHandle *ui_popup_menu_create(
pup->menu_func = menu_func;
pup->menu_arg = arg;
- handle = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPUP, pup);
+ handle = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPUP, pup, NULL);
if (!but) {
handle->popup = true;
@@ -463,7 +463,7 @@ void UI_popup_menu_end(bContext *C, uiPopupMenu *pup)
butregion = pup->butregion;
}
- menu = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPUP, pup);
+ menu = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPUP, pup, NULL);
menu->popup = true;
UI_popup_handlers_add(C, &window->modalhandlers, menu, 0);
@@ -581,13 +581,17 @@ int UI_popup_menu_invoke(bContext *C, const char *idname, ReportList *reports)
/** \name Popup Block API
* \{ */
-void UI_popup_block_invoke_ex(
- bContext *C, uiBlockCreateFunc func, void *arg, const char *opname, int opcontext)
+void UI_popup_block_invoke_ex(bContext *C,
+ uiBlockCreateFunc func,
+ void *arg,
+ void (*arg_free)(void *arg),
+ const char *opname,
+ int opcontext)
{
wmWindow *window = CTX_wm_window(C);
uiPopupBlockHandle *handle;
- handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg);
+ handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg, arg_free);
handle->popup = true;
handle->can_refresh = true;
handle->optype = (opname) ? WM_operatortype_find(opname, 0) : NULL;
@@ -598,9 +602,12 @@ void UI_popup_block_invoke_ex(
WM_event_add_mousemove(C);
}
-void UI_popup_block_invoke(bContext *C, uiBlockCreateFunc func, void *arg)
+void UI_popup_block_invoke(bContext *C,
+ uiBlockCreateFunc func,
+ void *arg,
+ void (*arg_free)(void *arg))
{
- UI_popup_block_invoke_ex(C, func, arg, NULL, WM_OP_INVOKE_DEFAULT);
+ UI_popup_block_invoke_ex(C, func, arg, arg_free, NULL, WM_OP_INVOKE_DEFAULT);
}
void UI_popup_block_ex(bContext *C,
@@ -613,7 +620,7 @@ void UI_popup_block_ex(bContext *C,
wmWindow *window = CTX_wm_window(C);
uiPopupBlockHandle *handle;
- handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg);
+ handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg, NULL);
handle->popup = true;
handle->retvalue = 1;
handle->can_refresh = true;
@@ -635,7 +642,7 @@ void uiPupBlockOperator(bContext *C, uiBlockCreateFunc func, wmOperator *op, int
wmWindow *window = CTX_wm_window(C);
uiPopupBlockHandle *handle;
- handle = ui_popup_block_create(C, NULL, NULL, func, NULL, op);
+ handle = ui_popup_block_create(C, NULL, NULL, func, NULL, op, NULL);
handle->popup = 1;
handle->retvalue = 1;
handle->can_refresh = true;
diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c
index f149ccd626c..22c62ecd6f7 100644
--- a/source/blender/editors/interface/interface_region_popover.c
+++ b/source/blender/editors/interface/interface_region_popover.c
@@ -244,7 +244,7 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v
return block;
}
-static void ui_block_free_func_POPOVER(uiPopupBlockHandle *UNUSED(handle), void *arg_pup)
+static void ui_block_free_func_POPOVER(void *arg_pup)
{
uiPopover *pup = arg_pup;
if (pup->keymap != NULL) {
@@ -282,8 +282,8 @@ uiPopupBlockHandle *ui_popover_panel_create(
/* Create popup block. */
uiPopupBlockHandle *handle;
- handle = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPOVER, pup);
- handle->popup_create_vars.free_func = ui_block_free_func_POPOVER;
+ handle = ui_popup_block_create(
+ C, butregion, but, NULL, ui_block_func_POPOVER, pup, ui_block_free_func_POPOVER);
handle->can_refresh = true;
/* Add handlers. If attached to a button, the button will already
@@ -386,8 +386,8 @@ void UI_popover_end(bContext *C, uiPopover *pup, wmKeyMap *keymap)
WM_event_set_keymap_handler_post_callback(pup->keymap_handler, popover_keymap_fn, pup);
}
- handle = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_POPOVER, pup);
- handle->popup_create_vars.free_func = ui_block_free_func_POPOVER;
+ handle = ui_popup_block_create(
+ C, NULL, NULL, NULL, ui_block_func_POPOVER, pup, ui_block_free_func_POPOVER);
/* Add handlers. */
UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c
index c4bcd7074d8..bd87439ca9e 100644
--- a/source/blender/editors/interface/interface_region_popup.c
+++ b/source/blender/editors/interface/interface_region_popup.c
@@ -748,7 +748,8 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C,
uiBut *but,
uiBlockCreateFunc create_func,
uiBlockHandleCreateFunc handle_create_func,
- void *arg)
+ void *arg,
+ void (*arg_free)(void *arg))
{
wmWindow *window = CTX_wm_window(C);
uiBut *activebut = UI_context_active_but_get(C);
@@ -775,6 +776,7 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C,
handle->popup_create_vars.create_func = create_func;
handle->popup_create_vars.handle_create_func = handle_create_func;
handle->popup_create_vars.arg = arg;
+ handle->popup_create_vars.arg_free = arg_free;
handle->popup_create_vars.but = but;
handle->popup_create_vars.butregion = but ? butregion : NULL;
copy_v2_v2_int(handle->popup_create_vars.event_xy, &window->eventstate->x);
@@ -820,8 +822,8 @@ void ui_popup_block_free(bContext *C, uiPopupBlockHandle *handle)
}
}
- if (handle->popup_create_vars.free_func) {
- handle->popup_create_vars.free_func(handle, handle->popup_create_vars.arg);
+ if (handle->popup_create_vars.arg_free) {
+ handle->popup_create_vars.arg_free(handle->popup_create_vars.arg);
}
ui_popup_block_remove(C, handle);
diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c
index 4a9c7b689c1..5b205de21b8 100644
--- a/source/blender/editors/interface/interface_region_tooltip.c
+++ b/source/blender/editors/interface/interface_region_tooltip.c
@@ -891,11 +891,11 @@ static uiTooltipData *ui_tooltip_data_from_gizmo(bContext *C, wmGizmo *gz)
} gzop_actions[] = {
{
.part = gz->highlight_part,
- .prefix = use_drag ? TIP_("Click") : NULL,
+ .prefix = use_drag ? CTX_TIP_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Click") : NULL,
},
{
.part = use_drag ? gz->drag_part : -1,
- .prefix = use_drag ? TIP_("Drag") : NULL,
+ .prefix = use_drag ? CTX_TIP_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Drag") : NULL,
},
};
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index e96141eaa05..9e91505f5e8 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -4042,6 +4042,11 @@ static uiBlock *curvemap_brush_tools_func(bContext *C, ARegion *ar, void *cumap_
return curvemap_tools_func(C, ar, cumap_v, false, UICURVE_FUNC_RESET_NEG);
}
+static uiBlock *curvemap_brush_tools_negslope_func(bContext *C, ARegion *ar, void *cumap_v)
+{
+ return curvemap_tools_func(C, ar, cumap_v, false, UICURVE_FUNC_RESET_POS);
+}
+
static void curvemap_buttons_redraw(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
{
ED_region_tag_redraw(CTX_wm_region(C));
@@ -4217,7 +4222,19 @@ static void curvemap_buttons_layout(uiLayout *layout,
TIP_("Zoom out"));
UI_but_func_set(bt, curvemap_buttons_zoom_out, cumap, NULL);
- if (brush) {
+ if (brush && neg_slope) {
+ bt = uiDefIconBlockBut(block,
+ curvemap_brush_tools_negslope_func,
+ cumap,
+ 0,
+ ICON_DOWNARROW_HLT,
+ 0,
+ 0,
+ dx,
+ dx,
+ TIP_("Tools"));
+ }
+ else if (brush) {
bt = uiDefIconBlockBut(block,
curvemap_brush_tools_func,
cumap,
@@ -6744,12 +6761,17 @@ int uiTemplateRecentFiles(uiLayout *layout, int rows)
for (recent = G.recent_files.first, i = 0; (i < rows) && (recent); recent = recent->next, i++) {
const char *filename = BLI_path_basename(recent->filepath);
- uiItemStringO(layout,
- filename,
- BLO_has_bfile_extension(filename) ? ICON_FILE_BLEND : ICON_FILE_BACKUP,
- "WM_OT_open_mainfile",
- "filepath",
- recent->filepath);
+ PointerRNA ptr;
+ uiItemFullO(layout,
+ "WM_OT_open_mainfile",
+ filename,
+ BLO_has_bfile_extension(filename) ? ICON_FILE_BLEND : ICON_FILE_BACKUP,
+ NULL,
+ WM_OP_INVOKE_DEFAULT,
+ 0,
+ &ptr);
+ RNA_string_set(&ptr, "filepath", recent->filepath);
+ RNA_boolean_set(&ptr, "display_file_selector", false);
}
return i;
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index a9cd2f9cee1..594793371ae 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -1421,7 +1421,7 @@ static void widget_draw_preview(BIFIconID icon, float alpha, const rcti *rect)
int x = rect->xmin + w / 2 - size / 2;
int y = rect->ymin + h / 2 - size / 2;
- UI_icon_draw_preview_aspect_size(x, y, icon, 1.0f, alpha, size);
+ UI_icon_draw_preview(x, y, icon, 1.0f, alpha, size);
}
}
@@ -1450,7 +1450,7 @@ static void widget_draw_icon(
return;
}
- aspect = but->block->aspect / UI_DPI_FAC;
+ aspect = but->block->aspect * U.inv_dpi_fac;
height = ICON_DEFAULT_HEIGHT / aspect;
/* calculate blend color */
@@ -1506,18 +1506,27 @@ static void widget_draw_icon(
ys = (int)(ys + 0.1f);
}
+ /* Get theme color. */
+ char color[4] = {mono_color[0], mono_color[1], mono_color[2], mono_color[3]};
+ bool has_theme = UI_icon_get_theme_color(icon, (uchar *)color);
+
/* to indicate draggable */
if (but->dragpoin && (but->flag & UI_ACTIVE)) {
- float rgb[3] = {1.25f, 1.25f, 1.25f};
- UI_icon_draw_aspect_color(xs, ys, icon, aspect, rgb, mono_color);
+ UI_icon_draw_ex(xs, ys, icon, aspect, 1.25f, 0.0f, color, has_theme);
+ }
+ else if ((but->flag & (UI_ACTIVE | UI_SELECT | UI_SELECT_DRAW))) {
+ UI_icon_draw_ex(xs, ys, icon, aspect, alpha, 0.0f, color, has_theme);
}
- else if ((but->flag & (UI_ACTIVE | UI_SELECT | UI_SELECT_DRAW)) || !UI_but_is_tool(but)) {
- UI_icon_draw_aspect(xs, ys, icon, aspect, alpha, mono_color);
+ else if (!UI_but_is_tool(but)) {
+ if (has_theme) {
+ alpha *= 0.8f;
+ }
+ UI_icon_draw_ex(xs, ys, icon, aspect, alpha, 0.0f, color, has_theme);
}
else {
const bTheme *btheme = UI_GetTheme();
- UI_icon_draw_desaturate(
- xs, ys, icon, aspect, alpha, 1.0 - btheme->tui.icon_saturation, mono_color);
+ const float desaturate = 1.0 - btheme->tui.icon_saturation;
+ UI_icon_draw_ex(xs, ys, icon, aspect, alpha, desaturate, color, has_theme);
}
}
@@ -1528,7 +1537,7 @@ static void widget_draw_submenu_tria(const uiBut *but,
const rcti *rect,
const uiWidgetColors *wcol)
{
- const float aspect = but->block->aspect / UI_DPI_FAC;
+ const float aspect = but->block->aspect * U.inv_dpi_fac;
const int tria_height = (int)(ICON_DEFAULT_HEIGHT / aspect);
const int tria_width = (int)(ICON_DEFAULT_WIDTH / aspect) - 2 * U.pixelsize;
const int xs = rect->xmax - tria_width;
@@ -1584,7 +1593,8 @@ static void ui_text_clip_right_ex(const uiFontStyle *fstyle,
BLI_assert(str[0]);
/* If the trailing ellipsis takes more than 20% of all available width, just cut the string
- * (as using the ellipsis would remove even more useful chars, and we cannot show much already!).
+ * (as using the ellipsis would remove even more useful chars, and we cannot show much
+ * already!).
*/
if (sep_strwidth / okwidth > 0.2f) {
l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, okwidth, &tmp);
@@ -1699,7 +1709,8 @@ float UI_text_clip_middle_ex(const uiFontStyle *fstyle,
/* Corner case, the str already takes all available mem,
* and the ellipsis chars would actually add more chars.
* Better to just trim one or two letters to the right in this case...
- * Note: with a single-char ellipsis, this should never happen! But better be safe here...
+ * Note: with a single-char ellipsis, this should never happen! But better be safe
+ * here...
*/
ui_text_clip_right_ex(
fstyle, str, max_len, okwidth, sep, sep_len, sep_strwidth, &final_lpart_len);
@@ -2346,7 +2357,7 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle,
const BIFIconID icon = widget_icon_id(but);
int icon_size_init = is_tool ? ICON_DEFAULT_HEIGHT_TOOLBAR : ICON_DEFAULT_HEIGHT;
- const float icon_size = icon_size_init / (but->block->aspect / UI_DPI_FAC);
+ const float icon_size = icon_size_init / (but->block->aspect * U.inv_dpi_fac);
const float icon_padding = 2 * UI_DPI_FAC;
#ifdef USE_UI_TOOLBAR_HACK
@@ -3494,8 +3505,11 @@ void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *s
wcol->item[3] = 255;
if (horizontal) {
- shape_preset_init_scroll_circle(&wtb.tria1, slider, 0.6f, 'l');
- shape_preset_init_scroll_circle(&wtb.tria2, slider, 0.6f, 'r');
+ rcti slider_inset = *slider;
+ slider_inset.xmin += 0.05 * U.widget_unit;
+ slider_inset.xmax -= 0.05 * U.widget_unit;
+ shape_preset_init_scroll_circle(&wtb.tria1, &slider_inset, 0.6f, 'l');
+ shape_preset_init_scroll_circle(&wtb.tria2, &slider_inset, 0.6f, 'r');
}
else {
shape_preset_init_scroll_circle(&wtb.tria1, slider, 0.6f, 'b');
@@ -4631,6 +4645,9 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
break;
case UI_BTYPE_COLORBAND:
+ /* do not draw right to edge of rect */
+ rect->xmin += (0.25f * UI_UNIT_X);
+ rect->xmax -= (0.3f * UI_UNIT_X);
ui_draw_but_COLORBAND(but, &tui->wcol_regular, rect);
break;
@@ -4655,6 +4672,9 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
break;
case UI_BTYPE_CURVE:
+ /* do not draw right to edge of rect */
+ rect->xmin += (0.2f * UI_UNIT_X);
+ rect->xmax -= (0.2f * UI_UNIT_X);
ui_draw_but_CURVE(ar, but, &tui->wcol_regular, rect);
break;
@@ -5198,7 +5218,7 @@ void ui_draw_menu_item(
GPU_blend(true);
/* XXX scale weak get from fstyle? */
- UI_icon_draw_aspect(xs, ys, iconid, aspect, 1.0f, wt->wcol.text);
+ UI_icon_draw_ex(xs, ys, iconid, aspect, 1.0f, 0.0f, wt->wcol.text, false);
GPU_blend(false);
}
}
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 8ed7dd87e9f..14fad2f3072 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -309,6 +309,9 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
case TH_GRID:
cp = ts->grid;
break;
+ case TH_SCRUBBING_BACKGROUND:
+ cp = ts->scrubbing_background;
+ break;
case TH_VIEW_OVERLAY:
cp = ts->view_overlay;
break;
@@ -865,6 +868,9 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
cp = btheme->tui.gizmo_b;
break;
+ case TH_ICON_SCENE:
+ cp = btheme->tui.icon_scene;
+ break;
case TH_ICON_COLLECTION:
cp = btheme->tui.icon_collection;
break;
@@ -881,6 +887,10 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
cp = btheme->tui.icon_shading;
break;
+ case TH_SCROLL_TEXT:
+ cp = btheme->tui.wcol_scroll.text;
+ break;
+
case TH_INFO_SELECTED:
cp = ts->info_selected;
break;
@@ -1347,7 +1357,7 @@ void UI_GetThemeColorType4ubv(int colorid, int spacetype, uchar col[4])
col[3] = cp[3];
}
-bool UI_GetIconThemeColor4fv(int colorid, float col[4])
+bool UI_GetIconThemeColor4ubv(int colorid, uchar col[4])
{
if (colorid == 0) {
return false;
@@ -1357,17 +1367,15 @@ bool UI_GetIconThemeColor4fv(int colorid, float col[4])
* to stay monochrome and out of the way except a few places where it
* is important to communicate different data types. */
if (!((theme_spacetype == SPACE_OUTLINER && theme_regionid == RGN_TYPE_WINDOW) ||
- (theme_spacetype == SPACE_PROPERTIES && theme_regionid == RGN_TYPE_NAV_BAR) ||
- (theme_regionid == RGN_TYPE_TEMPORARY))) {
+ (theme_spacetype == SPACE_PROPERTIES && theme_regionid == RGN_TYPE_NAV_BAR))) {
return false;
}
- const uchar *cp;
- cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
- col[0] = ((float)cp[0]) / 255.0f;
- col[1] = ((float)cp[1]) / 255.0f;
- col[2] = ((float)cp[2]) / 255.0f;
- col[3] = ((float)cp[3]) / 255.0f;
+ const uchar *cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ col[0] = cp[0];
+ col[1] = cp[1];
+ col[2] = cp[2];
+ col[3] = cp[3];
return true;
}
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index 9de7a33b757..f2d4faff479 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -138,7 +138,7 @@ static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scr
if (check_scrollers) {
/* check size if hiding flag is set: */
if (v2d->scroll & V2D_SCROLL_HORIZONTAL_HIDE) {
- if (!(v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL)) {
+ if (!(v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES)) {
if (BLI_rctf_size_x(&v2d->tot) > BLI_rctf_size_x(&v2d->cur)) {
v2d->scroll &= ~V2D_SCROLL_HORIZONTAL_FULLR;
}
@@ -148,7 +148,7 @@ static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scr
}
}
if (v2d->scroll & V2D_SCROLL_VERTICAL_HIDE) {
- if (!(v2d->scroll & V2D_SCROLL_SCALE_VERTICAL)) {
+ if (!(v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES)) {
if (BLI_rctf_size_y(&v2d->tot) + 0.01f > BLI_rctf_size_y(&v2d->cur)) {
v2d->scroll &= ~V2D_SCROLL_VERTICAL_FULLR;
}
@@ -166,10 +166,11 @@ static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scr
* - if they overlap, they must not occupy the corners (which are reserved for other widgets)
*/
if (scroll) {
- const int scroll_width = (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) ? V2D_SCROLL_WIDTH_TEXT :
- V2D_SCROLL_WIDTH;
- const int scroll_height = (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) ?
- V2D_SCROLL_HEIGHT_TEXT :
+ const int scroll_width = (v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES) ?
+ V2D_SCROLL_WIDTH_HANDLES :
+ V2D_SCROLL_WIDTH;
+ const int scroll_height = (v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES) ?
+ V2D_SCROLL_HEIGHT_HANDLES :
V2D_SCROLL_HEIGHT;
/* vertical scroller */
@@ -185,6 +186,13 @@ static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scr
v2d->vert.xmin = v2d->vert.xmax - scroll_width;
}
+ /* Currently, all regions that have vertical scale handles,
+ * also have the scrubbing area at the top.
+ * So the scrollbar has to move down a bit. */
+ if (scroll & V2D_SCROLL_VERTICAL_HANDLES) {
+ v2d->vert.ymax -= UI_SCRUBBING_MARGIN_Y;
+ }
+
/* horizontal scroller */
if (scroll & (V2D_SCROLL_BOTTOM)) {
/* on bottom edge of region */
@@ -1589,7 +1597,7 @@ void UI_view2d_scrollers_draw(View2D *v2d, View2DScrollers *vs)
* (workaround to make sure that button windows don't show these,
* and only the time-grids with their zoomability can do so)
*/
- if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0 && (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) &&
+ if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0 && (v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES) &&
(BLI_rcti_size_x(&slider) > V2D_SCROLLER_HANDLE_SIZE)) {
state |= UI_SCROLL_ARROWS;
}
@@ -1623,7 +1631,7 @@ void UI_view2d_scrollers_draw(View2D *v2d, View2DScrollers *vs)
* (workaround to make sure that button windows don't show these,
* and only the time-grids with their zoomability can do so)
*/
- if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0 && (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) &&
+ if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0 && (v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES) &&
(BLI_rcti_size_y(&slider) > V2D_SCROLLER_HANDLE_SIZE)) {
state |= UI_SCROLL_ARROWS;
}
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index ab8d1cf9bf6..68ee38bc99f 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -2032,8 +2032,8 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, const wmEvent *
* NOTE: see view2d.c for latest conditions, and keep this in sync with that
*/
if (ELEM(vsm->zone, SCROLLHANDLE_MIN, SCROLLHANDLE_MAX)) {
- if (((vsm->scroller == 'h') && (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) == 0) ||
- ((vsm->scroller == 'v') && (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) == 0)) {
+ if (((vsm->scroller == 'h') && (v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES) == 0) ||
+ ((vsm->scroller == 'v') && (v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES) == 0)) {
/* switch to bar (i.e. no scaling gets handled) */
vsm->zone = SCROLLHANDLE_BAR;
}
diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c
index c0f3b1f8338..1f825c0bb31 100644
--- a/source/blender/editors/mask/mask_ops.c
+++ b/source/blender/editors/mask/mask_ops.c
@@ -1992,9 +1992,9 @@ static int mask_hide_view_clear_exec(bContext *C, wmOperator *op)
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- if (masklay->restrictflag & OB_RESTRICT_VIEW) {
+ if (masklay->restrictflag & OB_RESTRICT_VIEWPORT) {
ED_mask_layer_select_set(masklay, select);
- masklay->restrictflag &= ~OB_RESTRICT_VIEW;
+ masklay->restrictflag &= ~OB_RESTRICT_VIEWPORT;
changed = true;
}
}
@@ -2045,7 +2045,7 @@ static int mask_hide_view_set_exec(bContext *C, wmOperator *op)
if (ED_mask_layer_select_check(masklay)) {
ED_mask_layer_select_set(masklay, false);
- masklay->restrictflag |= OB_RESTRICT_VIEW;
+ masklay->restrictflag |= OB_RESTRICT_VIEWPORT;
changed = true;
if (masklay == BKE_mask_layer_active(mask)) {
BKE_mask_layer_active_set(mask, NULL);
@@ -2054,7 +2054,7 @@ static int mask_hide_view_set_exec(bContext *C, wmOperator *op)
}
else {
if (!ED_mask_layer_select_check(masklay)) {
- masklay->restrictflag |= OB_RESTRICT_VIEW;
+ masklay->restrictflag |= OB_RESTRICT_VIEWPORT;
changed = true;
if (masklay == BKE_mask_layer_active(mask)) {
BKE_mask_layer_active_set(mask, NULL);
diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt
index 57bf67e825e..9a779db4812 100644
--- a/source/blender/editors/mesh/CMakeLists.txt
+++ b/source/blender/editors/mesh/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INC
../../blentranslation
../../bmesh
../../depsgraph
+ ../../draw
../../gpu
../../imbuf
../../makesdna
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index 990250792a1..fdbcc3449b2 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -461,13 +461,13 @@ bool do_paintface_box_select(ViewContext *vc, const rcti *rect, int sel_op)
}
else {
MPoly *mpoly;
- uint *rt;
+ uint *rt, *buf, buf_len;
int a, index;
char *selar = MEM_callocN(me->totpoly + 1, "selar");
- uint buf_len;
- uint *buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len);
+ ED_view3d_select_id_validate(vc);
+ buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len);
rt = buf;
diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c
index f5810d9ff61..1cd4e95314b 100644
--- a/source/blender/editors/mesh/editmesh_bevel.c
+++ b/source/blender/editors/mesh/editmesh_bevel.c
@@ -907,7 +907,8 @@ void MESH_OT_bevel(wmOperatorType *ot)
/* identifiers */
ot->name = "Bevel";
- ot->description = "Cut into selected items at an angle to create flat or rounded bevel or chamfer";
+ ot->description =
+ "Cut into selected items at an angle to create flat or rounded bevel or chamfer";
ot->idname = "MESH_OT_bevel";
/* api callbacks */
diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c
index 82cff8363f8..0da4d20c6b5 100644
--- a/source/blender/editors/mesh/editmesh_extrude.c
+++ b/source/blender/editors/mesh/editmesh_extrude.c
@@ -36,6 +36,7 @@
#include "RNA_access.h"
#include "WM_types.h"
+#include "WM_api.h"
#include "ED_mesh.h"
#include "ED_screen.h"
@@ -860,6 +861,9 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
EDBM_mesh_normals_update(vc.em);
EDBM_update_generic(vc.em, true, true);
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
MEM_freeN(objects);
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index cc0c2f5bbe4..e45c15b3e53 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -2811,6 +2811,7 @@ wmKeyMap *knifetool_modal_keymap(wmKeyConfig *keyconf)
{KNF_MODAL_CUT_THROUGH_TOGGLE, "CUT_THROUGH_TOGGLE", 0, "Toggle Cut Through", ""},
{KNF_MODAL_NEW_CUT, "NEW_CUT", 0, "End Current Cut", ""},
{KNF_MODAL_ADD_CUT, "ADD_CUT", 0, "Add Cut", ""},
+ {KNF_MODAL_ADD_CUT_CLOSED, "ADD_CUT_CLOSED", 0, "Add Cut Closed", ""},
{KNF_MODAL_PANNING, "PANNING", 0, "Panning", ""},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index 528235e693a..59355890428 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -79,11 +79,11 @@ typedef struct RingSelOpData {
Depsgraph *depsgraph;
- Object **objects;
- uint objects_len;
+ Base **bases;
+ uint bases_len;
/* These values switch objects based on the object under the cursor. */
- uint ob_index;
+ uint base_index;
Object *ob;
BMEditMesh *em;
BMEdge *eed;
@@ -111,8 +111,8 @@ static void edgering_select(RingSelOpData *lcd)
}
if (!lcd->extend) {
- for (uint ob_index = 0; ob_index < lcd->objects_len; ob_index++) {
- Object *ob_iter = lcd->objects[ob_index];
+ for (uint base_index = 0; base_index < lcd->bases_len; base_index++) {
+ Object *ob_iter = lcd->bases[base_index]->object;
BMEditMesh *em = BKE_editmesh_from_object(ob_iter);
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
@@ -252,7 +252,7 @@ static void ringsel_exit(bContext *UNUSED(C), wmOperator *op)
EDBM_preselect_edgering_destroy(lcd->presel_edgering);
- MEM_freeN(lcd->objects);
+ MEM_freeN(lcd->bases);
ED_region_tag_redraw(lcd->ar);
@@ -307,21 +307,21 @@ static void ringcut_cancel(bContext *C, wmOperator *op)
}
static void loopcut_update_edge(RingSelOpData *lcd,
- uint ob_index,
+ uint base_index,
BMEdge *e,
const int previewlines)
{
if (e != lcd->eed) {
lcd->eed = e;
lcd->ob = lcd->vc.obedit;
- lcd->ob_index = ob_index;
+ lcd->base_index = base_index;
lcd->em = lcd->vc.em;
ringsel_find_edge(lcd, previewlines);
}
else if (e == NULL) {
lcd->ob = NULL;
lcd->em = NULL;
- lcd->ob_index = UINT_MAX;
+ lcd->base_index = UINT_MAX;
}
}
@@ -331,27 +331,26 @@ static void loopcut_mouse_move(RingSelOpData *lcd, const int previewlines)
Object *ob;
BMEdge *eed;
float dist;
- int ob_index;
+ int base_index;
} best = {
.dist = ED_view3d_select_dist_px(),
};
- for (uint ob_index = 0; ob_index < lcd->objects_len; ob_index++) {
- Object *ob_iter = lcd->objects[ob_index];
- ED_view3d_viewcontext_init_object(&lcd->vc, ob_iter);
- BMEdge *eed_test = EDBM_edge_find_nearest_ex(&lcd->vc, &best.dist, NULL, false, false, NULL);
- if (eed_test) {
- best.ob = ob_iter;
- best.eed = eed_test;
- best.ob_index = ob_index;
- }
+ uint base_index;
+ BMEdge *eed_test = EDBM_edge_find_nearest_ex(
+ &lcd->vc, &best.dist, NULL, false, false, NULL, lcd->bases, lcd->bases_len, &base_index);
+
+ if (eed_test) {
+ best.ob = lcd->bases[base_index]->object;
+ best.eed = eed_test;
+ best.base_index = base_index;
}
if (best.eed) {
ED_view3d_viewcontext_init_object(&lcd->vc, best.ob);
}
- loopcut_update_edge(lcd, best.ob_index, best.eed, previewlines);
+ loopcut_update_edge(lcd, best.base_index, best.eed, previewlines);
}
/* called by both init() and exec() */
@@ -361,22 +360,22 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event)
/* Use for redo - intentionally wrap int to uint. */
const struct {
- uint ob_index;
+ uint base_index;
uint e_index;
} exec_data = {
- .ob_index = (uint)RNA_int_get(op->ptr, "object_index"),
+ .base_index = (uint)RNA_int_get(op->ptr, "object_index"),
.e_index = (uint)RNA_int_get(op->ptr, "edge_index"),
};
ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
- view_layer, CTX_wm_view3d(C), &objects_len);
+ uint bases_len;
+ Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(
+ view_layer, CTX_wm_view3d(C), &bases_len);
if (is_interactive) {
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob_iter = objects[ob_index];
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Object *ob_iter = bases[base_index]->object;
if (modifiers_isDeformedByLattice(ob_iter) || modifiers_isDeformedByArmature(ob_iter)) {
BKE_report(
op->reports, RPT_WARNING, "Loop cut does not work well on deformed edit mesh display");
@@ -390,12 +389,12 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event)
/* for re-execution, check edge index is in range before we setup ringsel */
bool ok = true;
if (is_interactive == false) {
- if (exec_data.ob_index >= objects_len) {
+ if (exec_data.base_index >= bases_len) {
return OPERATOR_CANCELLED;
ok = false;
}
else {
- Object *ob_iter = objects[exec_data.ob_index];
+ Object *ob_iter = bases[exec_data.base_index]->object;
BMEditMesh *em = BKE_editmesh_from_object(ob_iter);
if (exec_data.e_index >= em->bm->totedge) {
ok = false;
@@ -404,7 +403,7 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event)
}
if (!ok || !ringsel_init(C, op, true)) {
- MEM_freeN(objects);
+ MEM_freeN(bases);
return OPERATOR_CANCELLED;
}
@@ -416,8 +415,8 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event)
RingSelOpData *lcd = op->customdata;
- lcd->objects = objects;
- lcd->objects_len = objects_len;
+ lcd->bases = bases;
+ lcd->bases_len = bases_len;
if (is_interactive) {
copy_v2_v2_int(lcd->vc.mval, event->mval);
@@ -425,13 +424,13 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event)
}
else {
- Object *ob_iter = objects[exec_data.ob_index];
+ Object *ob_iter = bases[exec_data.base_index]->object;
ED_view3d_viewcontext_init_object(&lcd->vc, ob_iter);
BMEdge *e;
BM_mesh_elem_table_ensure(lcd->vc.em->bm, BM_EDGE);
e = BM_edge_at_index(lcd->vc.em->bm, exec_data.e_index);
- loopcut_update_edge(lcd, exec_data.ob_index, e, 0);
+ loopcut_update_edge(lcd, exec_data.base_index, e, 0);
}
#ifdef USE_LOOPSLIDE_HACK
@@ -503,7 +502,7 @@ static int loopcut_finish(RingSelOpData *lcd, bContext *C, wmOperator *op)
if (lcd->eed) {
/* set for redo */
BM_mesh_elem_index_ensure(lcd->em->bm, BM_EDGE);
- RNA_int_set(op->ptr, "object_index", lcd->ob_index);
+ RNA_int_set(op->ptr, "object_index", lcd->base_index);
RNA_int_set(op->ptr, "edge_index", BM_elem_index_get(lcd->eed));
/* execute */
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 9df03a81762..5344537e2d1 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -67,6 +67,8 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
+#include "DRW_engine.h"
+
#include "mesh_intern.h" /* own include */
/* use bmesh operator flags for a few operators */
@@ -196,7 +198,87 @@ void EDBM_automerge(Scene *scene, Object *obedit, bool update, const char hflag)
/** \name Back-Buffer OpenGL Selection
* \{ */
-/* set in drawobject.c ... for colorindices */
+struct EDBMBaseOffset {
+ uint face;
+ uint edge;
+ uint vert;
+};
+
+static struct EDBMBaseOffset *base_array_index_offsets = NULL;
+
+static void edbm_select_pick_cache_alloc(uint bases_len)
+{
+ BLI_assert(base_array_index_offsets == NULL);
+ base_array_index_offsets = MEM_mallocN(sizeof(struct EDBMBaseOffset) * bases_len, __func__);
+}
+
+static void edbm_select_pick_cache_free(void)
+{
+ MEM_SAFE_FREE(base_array_index_offsets);
+}
+
+static bool check_ob_drawface_dot(short select_mode, View3D *vd, char dt)
+{
+ if ((select_mode & SCE_SELECT_FACE) == 0) {
+ return false;
+ }
+
+ /* if its drawing textures with zbuf sel, then don't draw dots */
+ if (dt == OB_TEXTURE && vd->shading.type == OB_TEXTURE) {
+ return false;
+ }
+
+ return true;
+}
+
+static void edbm_select_pick_draw_bases(ViewContext *vc,
+ Base **bases,
+ uint bases_len,
+ short select_mode)
+{
+ Scene *scene_eval = (Scene *)DEG_get_evaluated_id(vc->depsgraph, &vc->scene->id);
+ DRW_framebuffer_select_id_setup(vc->ar, true);
+
+ uint offset = 0;
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph, bases[base_index]->object);
+ struct EDBMBaseOffset *base_ofs = &base_array_index_offsets[base_index];
+
+ bool draw_facedot = check_ob_drawface_dot(select_mode, vc->v3d, ob_eval->dt);
+
+ DRW_draw_select_id_object(scene_eval,
+ vc->rv3d,
+ ob_eval,
+ select_mode,
+ draw_facedot,
+ offset,
+ &base_ofs->vert,
+ &base_ofs->edge,
+ &base_ofs->face);
+
+ offset = base_ofs->vert;
+ }
+
+ DRW_framebuffer_select_id_release(vc->ar);
+}
+
+static uint edbm_select_pick_base_index_find(uint bases_len, uint elem_index, uint *r_offset)
+{
+ *r_offset = 0;
+ uint base_index = 0;
+ for (; base_index < bases_len; base_index++) {
+ struct EDBMBaseOffset *base_ofs = &base_array_index_offsets[base_index];
+ if (base_ofs->vert > elem_index) {
+ break;
+ }
+ *r_offset = base_ofs->vert;
+ }
+
+ *r_offset += 1;
+ return base_index;
+}
+
+/* set in view3d_draw_legacy.c ... for colorindices */
unsigned int bm_solidoffs = 0, bm_wireoffs = 0, bm_vertoffs = 0;
/* facilities for box select and circle select */
@@ -217,6 +299,7 @@ bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xma
return false;
}
+ ED_view3d_select_id_validate(vc);
buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, &buf_len);
if ((buf == NULL) || (bm_vertoffs == 0)) {
return false;
@@ -303,6 +386,7 @@ bool EDBM_backbuf_border_mask_init(ViewContext *vc,
return false;
}
+ ED_view3d_select_id_validate(vc);
buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, &buf_len);
if ((buf == NULL) || (bm_vertoffs == 0)) {
return false;
@@ -354,6 +438,8 @@ bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads)
xmax = xs + rads;
ymin = ys - rads;
ymax = ys + rads;
+
+ ED_view3d_select_id_validate(vc);
buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, NULL);
if ((buf == NULL) || (bm_vertoffs == 0)) {
return false;
@@ -470,29 +556,46 @@ static void findnearestvert__doClosest(void *userData,
BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc,
float *r_dist,
const bool use_select_bias,
- bool use_cycle)
+ bool use_cycle,
+ Base **bases,
+ uint bases_len,
+ uint *r_base_index)
{
- BMesh *bm = vc->em->bm;
+ uint base_index = 0;
if (!XRAY_FLAG_ENABLED(vc->v3d)) {
uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist);
- unsigned int index;
+ uint index, offset;
BMVert *eve;
/* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */
{
- FAKE_SELECT_MODE_BEGIN (vc, fake_select_mode, select_mode, SCE_SELECT_VERTEX)
- ;
- ED_view3d_select_id_validate_with_select_mode(vc, select_mode);
+ FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_VERTEX);
+
+ edbm_select_pick_cache_alloc(bases_len);
+ edbm_select_pick_draw_bases(vc, bases, bases_len, select_mode);
+
+ index = ED_view3d_select_id_read_nearest(vc, vc->mval, 1, UINT_MAX, &dist_px);
+
+ if (index) {
+ base_index = edbm_select_pick_base_index_find(bases_len, index, &offset);
+ ED_view3d_viewcontext_init_object(vc, bases[base_index]->object);
+ eve = BM_vert_at_index_find_or_table(vc->em->bm, index - offset);
+ }
+ else {
+ eve = NULL;
+ }
- index = ED_view3d_select_id_read_nearest(vc, vc->mval, bm_wireoffs, 0xFFFFFF, &dist_px);
- eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL;
+ edbm_select_pick_cache_free();
FAKE_SELECT_MODE_END(vc, fake_select_mode);
}
if (eve) {
if (dist_px < *r_dist) {
+ if (r_base_index) {
+ *r_base_index = base_index;
+ }
*r_dist = dist_px;
return eve;
}
@@ -509,7 +612,7 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc,
if ((use_cycle == false) ||
(prev_select_elem &&
- (prev_select_elem != BM_vert_at_index_find_or_table(bm, prev_select_index)))) {
+ (prev_select_elem != BM_vert_at_index_find_or_table(vc->em->bm, prev_select_index)))) {
prev_select_index = 0;
prev_select_elem = NULL;
}
@@ -518,14 +621,26 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc,
data.mval_fl[1] = vc->mval[1];
data.use_select_bias = use_select_bias;
data.use_cycle = use_cycle;
- data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
data.cycle_index_prev = prev_select_index;
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, clip_flag);
+ for (; base_index < bases_len; base_index++) {
+ Base *base_iter = bases[base_index];
+ ED_view3d_viewcontext_init_object(vc, base_iter->object);
+ data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias =
+ *r_dist;
- hit = (data.use_cycle && data.hit_cycle.vert) ? &data.hit_cycle : &data.hit;
- *r_dist = hit->dist;
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+ mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, clip_flag);
+
+ hit = (data.use_cycle && data.hit_cycle.vert) ? &data.hit_cycle : &data.hit;
+
+ if (hit->dist < *r_dist) {
+ if (r_base_index) {
+ *r_base_index = base_index;
+ }
+ *r_dist = hit->dist;
+ }
+ }
prev_select_elem = hit->vert;
prev_select_index = hit->index;
@@ -536,7 +651,8 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc,
BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist)
{
- return EDBM_vert_find_nearest_ex(vc, r_dist, false, false);
+ Base *base = BKE_view_layer_base_find(vc->view_layer, vc->obact);
+ return EDBM_vert_find_nearest_ex(vc, r_dist, false, false, &base, 1, NULL);
}
/* find the distance to the edge we already have */
@@ -659,23 +775,37 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
float *r_dist_center,
const bool use_select_bias,
const bool use_cycle,
- BMEdge **r_eed_zbuf)
+ BMEdge **r_eed_zbuf,
+ Base **bases,
+ uint bases_len,
+ uint *r_base_index)
{
- BMesh *bm = vc->em->bm;
+ uint base_index = 0;
if (!XRAY_FLAG_ENABLED(vc->v3d)) {
uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist);
- unsigned int index;
+ uint index, offset;
BMEdge *eed;
/* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */
{
- FAKE_SELECT_MODE_BEGIN (vc, fake_select_mode, select_mode, SCE_SELECT_EDGE)
- ;
- ED_view3d_select_id_validate_with_select_mode(vc, select_mode);
+ FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_EDGE);
+
+ edbm_select_pick_cache_alloc(bases_len);
+ edbm_select_pick_draw_bases(vc, bases, bases_len, select_mode);
+
+ index = ED_view3d_select_id_read_nearest(vc, vc->mval, 1, UINT_MAX, &dist_px);
- index = ED_view3d_select_id_read_nearest(vc, vc->mval, bm_solidoffs, bm_wireoffs, &dist_px);
- eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL;
+ if (index) {
+ base_index = edbm_select_pick_base_index_find(bases_len, index, &offset);
+ ED_view3d_viewcontext_init_object(vc, bases[base_index]->object);
+ eed = BM_edge_at_index_find_or_table(vc->em->bm, index - offset);
+ }
+ else {
+ eed = NULL;
+ }
+
+ edbm_select_pick_cache_free();
FAKE_SELECT_MODE_END(vc, fake_select_mode);
}
@@ -704,6 +834,9 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
if (eed) {
if (dist_px < *r_dist) {
+ if (r_base_index) {
+ *r_base_index = base_index;
+ }
*r_dist = dist_px;
return eed;
}
@@ -721,7 +854,7 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
if ((use_cycle == false) ||
(prev_select_elem &&
- (prev_select_elem != BM_edge_at_index_find_or_table(bm, prev_select_index)))) {
+ (prev_select_elem != BM_edge_at_index_find_or_table(vc->em->bm, prev_select_index)))) {
prev_select_index = 0;
prev_select_elem = NULL;
}
@@ -731,14 +864,27 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
data.mval_fl[1] = vc->mval[1];
data.use_select_bias = use_select_bias;
data.use_cycle = use_cycle;
- data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
data.cycle_index_prev = prev_select_index;
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenEdge(vc, find_nearest_edge__doClosest, &data, clip_flag);
+ for (; base_index < bases_len; base_index++) {
+ Base *base_iter = bases[base_index];
+ ED_view3d_viewcontext_init_object(vc, base_iter->object);
+ data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias =
+ *r_dist;
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+ mesh_foreachScreenEdge(vc, find_nearest_edge__doClosest, &data, clip_flag);
+
+ hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit;
+
+ if (hit->dist < *r_dist) {
+ if (r_base_index) {
+ *r_base_index = base_index;
+ }
+ *r_dist = hit->dist;
+ }
+ }
- hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit;
- *r_dist = hit->dist;
if (r_dist_center) {
*r_dist_center = hit->dist_center;
}
@@ -752,7 +898,8 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist)
{
- return EDBM_edge_find_nearest_ex(vc, r_dist, NULL, false, false, NULL);
+ Base *base = BKE_view_layer_base_find(vc->view_layer, vc->obact);
+ return EDBM_edge_find_nearest_ex(vc, r_dist, NULL, false, false, NULL, &base, 1, NULL);
}
/* find the distance to the face we already have */
@@ -832,22 +979,36 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
float *r_dist_center,
const bool use_select_bias,
const bool use_cycle,
- BMFace **r_efa_zbuf)
+ BMFace **r_efa_zbuf,
+ Base **bases,
+ uint bases_len,
+ uint *r_base_index)
{
- BMesh *bm = vc->em->bm;
+ uint base_index = 0;
if (!XRAY_FLAG_ENABLED(vc->v3d)) {
float dist_test = 0.0f;
- unsigned int index;
+ uint index, offset;
BMFace *efa;
{
- FAKE_SELECT_MODE_BEGIN (vc, fake_select_mode, select_mode, SCE_SELECT_FACE)
- ;
- ED_view3d_select_id_validate_with_select_mode(vc, select_mode);
+ FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_FACE);
+
+ edbm_select_pick_cache_alloc(bases_len);
+ edbm_select_pick_draw_bases(vc, bases, bases_len, select_mode);
index = ED_view3d_select_id_sample(vc, vc->mval[0], vc->mval[1]);
- efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL;
+
+ if (index) {
+ base_index = edbm_select_pick_base_index_find(bases_len, index, &offset);
+ ED_view3d_viewcontext_init_object(vc, bases[base_index]->object);
+ efa = BM_face_at_index_find_or_table(vc->em->bm, index - offset);
+ }
+ else {
+ efa = NULL;
+ }
+
+ edbm_select_pick_cache_free();
FAKE_SELECT_MODE_END(vc, fake_select_mode);
}
@@ -876,6 +1037,9 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
if (efa) {
if (dist_test < *r_dist) {
+ if (r_base_index) {
+ *r_base_index = base_index;
+ }
*r_dist = dist_test;
return efa;
}
@@ -892,7 +1056,7 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
if ((use_cycle == false) ||
(prev_select_elem &&
- (prev_select_elem != BM_face_at_index_find_or_table(bm, prev_select_index)))) {
+ (prev_select_elem != BM_face_at_index_find_or_table(vc->em->bm, prev_select_index)))) {
prev_select_index = 0;
prev_select_elem = NULL;
}
@@ -901,14 +1065,28 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
data.mval_fl[1] = vc->mval[1];
data.use_select_bias = use_select_bias;
data.use_cycle = use_cycle;
- data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
data.cycle_index_prev = prev_select_index;
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag);
+ for (; base_index < bases_len; base_index++) {
+ Base *base_iter = bases[base_index];
+ ED_view3d_viewcontext_init_object(vc, base_iter->object);
+
+ data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias =
+ *r_dist;
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+ mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag);
+
+ hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit;
+
+ if (hit->dist < *r_dist) {
+ if (r_base_index) {
+ *r_base_index = base_index;
+ }
+ *r_dist = hit->dist;
+ }
+ }
- hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit;
- *r_dist = hit->dist;
if (r_dist_center) {
*r_dist_center = hit->dist;
}
@@ -922,7 +1100,8 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist)
{
- return EDBM_face_find_nearest_ex(vc, r_dist, NULL, false, false, NULL);
+ Base *base = BKE_view_layer_base_find(vc->view_layer, vc->obact);
+ return EDBM_face_find_nearest_ex(vc, r_dist, NULL, false, false, NULL, &base, 1, NULL);
}
#undef FIND_NEAR_SELECT_BIAS
@@ -965,75 +1144,64 @@ static bool unified_findnearest(ViewContext *vc,
} f, f_zbuf;
} hit = {{NULL}};
- /* TODO(campbell): perform selection as one pass
- * instead of many smaller passes (which doesn't work for zbuf occlusion). */
-
/* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
+ short selectmode = vc->scene->toolsettings->selectmode;
- if ((dist > 0.0f) && em->selectmode & SCE_SELECT_FACE) {
+ if ((dist > 0.0f) && (selectmode & SCE_SELECT_FACE)) {
float dist_center = 0.0f;
float *dist_center_p = (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_VERTEX)) ?
&dist_center :
NULL;
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Base *base_iter = bases[base_index];
- Object *obedit = base_iter->object;
- ED_view3d_viewcontext_init_object(vc, obedit);
- BLI_assert(vc->em->selectmode == em->selectmode);
- BMFace *efa_zbuf = NULL;
- BMFace *efa_test = EDBM_face_find_nearest_ex(
- vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf);
- if (efa_test && dist_center_p) {
- dist = min_ff(dist_margin, dist_center);
- }
- if (efa_test) {
- hit.f.base_index = base_index;
- hit.f.ele = efa_test;
- }
- if (efa_zbuf) {
- hit.f_zbuf.base_index = base_index;
- hit.f_zbuf.ele = efa_zbuf;
- }
- } /* bases */
+ uint base_index = 0;
+ BMFace *efa_zbuf = NULL;
+ BMFace *efa_test = EDBM_face_find_nearest_ex(
+ vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf, bases, bases_len, &base_index);
+
+ if (efa_test && dist_center_p) {
+ dist = min_ff(dist_margin, dist_center);
+ }
+ if (efa_test) {
+ hit.f.base_index = base_index;
+ hit.f.ele = efa_test;
+ }
+ if (efa_zbuf) {
+ hit.f_zbuf.base_index = base_index;
+ hit.f_zbuf.ele = efa_zbuf;
+ }
}
- if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) {
+ if ((dist > 0.0f) && (selectmode & SCE_SELECT_EDGE)) {
float dist_center = 0.0f;
float *dist_center_p = (em->selectmode & SCE_SELECT_VERTEX) ? &dist_center : NULL;
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Base *base_iter = bases[base_index];
- Object *obedit = base_iter->object;
- ED_view3d_viewcontext_init_object(vc, obedit);
- BMEdge *eed_zbuf = NULL;
- BMEdge *eed_test = EDBM_edge_find_nearest_ex(
- vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf);
- if (eed_test && dist_center_p) {
- dist = min_ff(dist_margin, dist_center);
- }
- if (eed_test) {
- hit.e.base_index = base_index;
- hit.e.ele = eed_test;
- }
- if (eed_zbuf) {
- hit.e_zbuf.base_index = base_index;
- hit.e_zbuf.ele = eed_zbuf;
- }
- } /* bases */
+ uint base_index = 0;
+ BMEdge *eed_zbuf = NULL;
+ BMEdge *eed_test = EDBM_edge_find_nearest_ex(
+ vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf, bases, bases_len, &base_index);
+
+ if (eed_test && dist_center_p) {
+ dist = min_ff(dist_margin, dist_center);
+ }
+ if (eed_test) {
+ hit.e.base_index = base_index;
+ hit.e.ele = eed_test;
+ }
+ if (eed_zbuf) {
+ hit.e_zbuf.base_index = base_index;
+ hit.e_zbuf.ele = eed_zbuf;
+ }
}
- if ((dist > 0.0f) && em->selectmode & SCE_SELECT_VERTEX) {
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Base *base_iter = bases[base_index];
- Object *obedit = base_iter->object;
- ED_view3d_viewcontext_init_object(vc, obedit);
- BMVert *eve_test = EDBM_vert_find_nearest_ex(vc, &dist, true, use_cycle);
- if (eve_test) {
- hit.v.base_index = base_index;
- hit.v.ele = eve_test;
- }
- } /* bases */
+ if ((dist > 0.0f) && (selectmode & SCE_SELECT_VERTEX)) {
+ uint base_index = 0;
+ BMVert *eve_test = EDBM_vert_find_nearest_ex(
+ vc, &dist, true, use_cycle, bases, bases_len, &base_index);
+
+ if (eve_test) {
+ hit.v.base_index = base_index;
+ hit.v.ele = eve_test;
+ }
}
/* return only one of 3 pointers, for frontbuffer redraws */
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 2181bf01583..331be744932 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -1124,7 +1124,7 @@ static int edbm_mark_sharp_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
- if (bm->totedgesel == 0) {
+ if ((use_verts && bm->totvertsel == 0) || (!use_verts && bm->totedgesel == 0)) {
continue;
}
@@ -8955,7 +8955,6 @@ void MESH_OT_smoothen_normals(struct wmOperatorType *ot)
static int edbm_mod_weighted_strength_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
@@ -8974,7 +8973,7 @@ static int edbm_mod_weighted_strength_exec(bContext *C, wmOperator *op)
const int cd_prop_int_offset = CustomData_get_n_offset(
&bm->pdata, CD_PROP_INT, cd_prop_int_index);
- const int face_strength = scene->toolsettings->face_strength;
+ const int face_strength = RNA_enum_get(op->ptr, "face_strength");
const bool set = RNA_boolean_get(op->ptr, "set");
BM_mesh_elem_index_ensure(bm, BM_FACE);
@@ -9003,6 +9002,13 @@ static int edbm_mod_weighted_strength_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+static const EnumPropertyItem prop_mesh_face_strength_types[] = {
+ {FACE_STRENGTH_WEAK, "WEAK", 0, "Weak", ""},
+ {FACE_STRENGTH_MEDIUM, "MEDIUM", 0, "Medium", ""},
+ {FACE_STRENGTH_STRONG, "STRONG", 0, "Strong", ""},
+ {0, NULL, 0, NULL, NULL},
+};
+
void MESH_OT_mod_weighted_strength(struct wmOperatorType *ot)
{
/* identifiers */
@@ -9018,5 +9024,12 @@ void MESH_OT_mod_weighted_strength(struct wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ot->prop = RNA_def_boolean(ot->srna, "set", 0, "Set value", "Set Value of faces");
- RNA_def_property_flag(ot->prop, PROP_HIDDEN);
+
+ ot->prop = RNA_def_enum(
+ ot->srna,
+ "face_strength",
+ prop_mesh_face_strength_types,
+ FACE_STRENGTH_MEDIUM,
+ "Face Strength",
+ "Strength to use for assigning or selecting face influence for weighted normal modifier");
}
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index c32fef42d27..e29cfa6b6e0 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -1109,13 +1109,11 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], uint dist_px,
}
ED_view3d_viewcontext_init(C, &vc);
+ ED_view3d_select_id_validate(&vc);
if (dist_px) {
/* sample rect to increase chances of selecting, so that when clicking
* on an edge in the backbuf, we can still select a face */
-
- ED_view3d_select_id_validate(&vc);
-
*r_index = ED_view3d_select_id_read_nearest(&vc, mval, 1, me->totpoly + 1, &dist_px);
}
else {
@@ -1291,14 +1289,12 @@ bool ED_mesh_pick_vert(
}
ED_view3d_viewcontext_init(C, &vc);
+ ED_view3d_select_id_validate(&vc);
if (use_zbuf) {
if (dist_px > 0) {
/* sample rect to increase chances of selecting, so that when clicking
* on an face in the backbuf, we can still select a vert */
-
- ED_view3d_select_id_validate(&vc);
-
*r_index = ED_view3d_select_id_read_nearest(&vc, mval, 1, me->totvert + 1, &dist_px);
}
else {
diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c
index 54143822b61..18ff7ae1a5e 100644
--- a/source/blender/editors/metaball/mball_edit.c
+++ b/source/blender/editors/metaball/mball_edit.c
@@ -738,7 +738,7 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese
}
const uint hit_object = hitresult & 0xFFFF;
- if (vc.obedit->select_id != hit_object) {
+ if (vc.obedit->runtime.select_id != hit_object) {
continue;
}
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index f8a13579732..f8760f93f2f 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -161,6 +161,18 @@ static EnumPropertyItem lightprobe_type_items[] = {
{0, NULL, 0, NULL, NULL},
};
+enum ObjectAlign {
+ ALIGN_WORLD,
+ ALIGN_VIEW,
+ ALIGN_CURSOR,
+} ALIGN_OPTIONS;
+
+static const EnumPropertyItem align_options[] = {
+ {ALIGN_WORLD, "WORLD", 0, "World", "Align the new object to the world"},
+ {ALIGN_VIEW, "VIEW", 0, "View", "Align the new object to the view"},
+ {ALIGN_CURSOR, "CURSOR", 0, "3D Cursor", "Use the 3D cursor orientation for the new object"},
+ {0, NULL, 0, NULL, NULL}};
+
/************************** Exported *****************************/
void ED_object_location_from_view(bContext *C, float loc[3])
@@ -291,16 +303,15 @@ void ED_object_add_generic_props(wmOperatorType *ot, bool do_editmode)
{
PropertyRNA *prop;
- /* note: this property gets hidden for add-camera operator */
- prop = RNA_def_boolean(
- ot->srna, "view_align", 0, "Align to View", "Align the new object to the view");
- RNA_def_property_update_runtime(prop, view_align_update);
-
if (do_editmode) {
prop = RNA_def_boolean(
ot->srna, "enter_editmode", 0, "Enter Editmode", "Enter editmode when adding this object");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
+ /* note: this property gets hidden for add-camera operator */
+ prop = RNA_def_enum(
+ ot->srna, "align", align_options, ALIGN_WORLD, "Align", "The alignment of the new object");
+ RNA_def_property_update_runtime(prop, view_align_update);
prop = RNA_def_float_vector_xyz(ot->srna,
"location",
@@ -392,23 +403,42 @@ bool ED_object_add_generic_get_opts(bContext *C,
rot = _rot;
}
+ prop = RNA_struct_find_property(op->ptr, "align");
+ int alignment = RNA_property_enum_get(op->ptr, prop);
+ bool alignment_set = RNA_property_is_set(op->ptr, prop);
+
if (RNA_struct_property_is_set(op->ptr, "rotation")) {
*is_view_aligned = false;
}
- else if (RNA_struct_property_is_set(op->ptr, "view_align")) {
- *is_view_aligned = RNA_boolean_get(op->ptr, "view_align");
+ else if (alignment_set) {
+ *is_view_aligned = alignment == ALIGN_VIEW;
}
else {
*is_view_aligned = (U.flag & USER_ADD_VIEWALIGNED) != 0;
- RNA_boolean_set(op->ptr, "view_align", *is_view_aligned);
+ if (*is_view_aligned) {
+ RNA_property_enum_set(op->ptr, prop, ALIGN_VIEW);
+ alignment = ALIGN_VIEW;
+ }
+ else if (U.flag & USER_ADD_CURSORALIGNED) {
+ RNA_property_enum_set(op->ptr, prop, ALIGN_CURSOR);
+ alignment = ALIGN_CURSOR;
+ }
}
- if (*is_view_aligned) {
- ED_object_rotation_from_view(C, rot, view_align_axis);
- RNA_float_set_array(op->ptr, "rotation", rot);
- }
- else {
- RNA_float_get_array(op->ptr, "rotation", rot);
+ switch (alignment) {
+ case ALIGN_WORLD:
+ RNA_float_get_array(op->ptr, "rotation", rot);
+ break;
+ case ALIGN_VIEW:
+ ED_object_rotation_from_view(C, rot, view_align_axis);
+ RNA_float_set_array(op->ptr, "rotation", rot);
+ break;
+ case ALIGN_CURSOR: {
+ const Scene *scene = CTX_data_scene(C);
+ copy_v3_v3(rot, scene->cursor.rotation_euler);
+ RNA_float_set_array(op->ptr, "rotation", rot);
+ break;
+ }
}
}
@@ -690,7 +720,7 @@ static int object_camera_add_exec(bContext *C, wmOperator *op)
float loc[3], rot[3];
/* force view align for cameras */
- RNA_boolean_set(op->ptr, "view_align", true);
+ RNA_enum_set(op->ptr, "align", ALIGN_VIEW);
if (!ED_object_add_generic_get_opts(
C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
@@ -732,7 +762,7 @@ void OBJECT_OT_camera_add(wmOperatorType *ot)
ED_object_add_generic_props(ot, true);
/* hide this for cameras, default */
- prop = RNA_struct_type_find_property(ot->srna, "view_align");
+ prop = RNA_struct_type_find_property(ot->srna, "align");
RNA_def_property_flag(prop, PROP_HIDDEN);
}
@@ -1176,7 +1206,6 @@ static const char *get_light_defname(int type)
static int object_light_add_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
Object *ob;
Light *la;
int type = RNA_enum_get(op->ptr, "type");
@@ -1207,9 +1236,8 @@ static int object_light_add_exec(bContext *C, wmOperator *op)
la = (Light *)ob->data;
la->type = type;
- if (BKE_scene_uses_cycles(scene)) {
- ED_node_shader_default(C, &la->id);
- la->use_nodes = true;
+ if (type == LA_SUN) {
+ la->energy = 1.0f;
}
return OPERATOR_FINISHED;
@@ -1656,7 +1684,7 @@ static void make_object_duplilist_real(
for (dob = lb_duplis->first; dob; dob = dob->next) {
Object *ob_src = DEG_get_original_object(dob->ob);
- Object *ob_dst = ID_NEW_SET(dob->ob, BKE_object_copy(bmain, ob_src));
+ Object *ob_dst = ID_NEW_SET(ob_src, BKE_object_copy(bmain, ob_src));
Base *base_dst;
/* font duplis can have a totcol without material, we get them from parent
@@ -2481,7 +2509,7 @@ static int add_named_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- basen->object->restrictflag &= ~OB_RESTRICT_VIEW;
+ basen->object->restrictflag &= ~OB_RESTRICT_VIEWPORT;
if (event) {
ARegion *ar = CTX_wm_region(C);
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index 5ae757cac56..da95db92332 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -277,7 +277,8 @@ static bool write_internal_bake_pixels(Image *image,
RE_bake_margin(ibuf, mask_buffer, margin);
}
- ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID | IB_BITMAPDIRTY;
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+ BKE_image_mark_dirty(image, ibuf);
if (ibuf->rect_float) {
ibuf->userflags |= IB_RECT_INVALID;
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 078135f46ff..abdf64af595 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -2025,8 +2025,8 @@ static const EnumPropertyItem *object_constraint_add_itemf(bContext *UNUSED(C),
EnumPropertyItem *object_constraint_items = NULL;
int totitem = 0;
- while(item->identifier) {
- if((item->value != CONSTRAINT_TYPE_KINEMATIC) && (item->value != CONSTRAINT_TYPE_SPLINEIK)) {
+ while (item->identifier) {
+ if ((item->value != CONSTRAINT_TYPE_KINEMATIC) && (item->value != CONSTRAINT_TYPE_SPLINEIK)) {
RNA_enum_item_add(&object_constraint_items, &totitem, item);
}
item++;
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 795e1dd66a5..9fba0d89c4a 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -314,7 +314,7 @@ void ED_collection_hide_menu_draw(const bContext *C, uiLayout *layout)
continue;
}
- if (lc->collection->flag & COLLECTION_RESTRICT_VIEW) {
+ if (lc->collection->flag & COLLECTION_RESTRICT_VIEWPORT) {
continue;
}
@@ -722,7 +722,7 @@ static bool editmode_toggle_poll(bContext *C)
}
/* if hidden but in edit mode, we still display */
- if ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT)) {
+ if ((ob->restrictflag & OB_RESTRICT_VIEWPORT) && !(ob->mode & OB_MODE_EDIT)) {
return 0;
}
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 09bcc0a3058..1e85c895f71 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -356,7 +356,7 @@ static int screen_render_exec(bContext *C, wmOperator *op)
/* cleanup sequencer caches before starting user triggered render.
* otherwise, invalidated cache entries can make their way into
- * the output rendering. We can't put that into RE_BlenderFrame,
+ * the output rendering. We can't put that into RE_RenderFrame,
* since sequence rendering can call that recursively... (peter) */
BKE_sequencer_cache_cleanup(scene);
@@ -364,18 +364,17 @@ static int screen_render_exec(bContext *C, wmOperator *op)
BLI_threaded_malloc_begin();
if (is_animation) {
- RE_BlenderAnim(re,
- mainp,
- scene,
- single_layer,
- camera_override,
- scene->r.sfra,
- scene->r.efra,
- scene->r.frame_step);
+ RE_RenderAnim(re,
+ mainp,
+ scene,
+ single_layer,
+ camera_override,
+ scene->r.sfra,
+ scene->r.efra,
+ scene->r.frame_step);
}
else {
- RE_BlenderFrame(
- re, mainp, scene, single_layer, camera_override, scene->r.cfra, is_write_still);
+ RE_RenderFrame(re, mainp, scene, single_layer, camera_override, scene->r.cfra, is_write_still);
}
BLI_threaded_malloc_end();
@@ -671,23 +670,23 @@ static void render_startjob(void *rjv, short *stop, short *do_update, float *pro
RE_SetReports(rj->re, rj->reports);
if (rj->anim) {
- RE_BlenderAnim(rj->re,
+ RE_RenderAnim(rj->re,
+ rj->main,
+ rj->scene,
+ rj->single_layer,
+ rj->camera_override,
+ rj->scene->r.sfra,
+ rj->scene->r.efra,
+ rj->scene->r.frame_step);
+ }
+ else {
+ RE_RenderFrame(rj->re,
rj->main,
rj->scene,
rj->single_layer,
rj->camera_override,
- rj->scene->r.sfra,
- rj->scene->r.efra,
- rj->scene->r.frame_step);
- }
- else {
- RE_BlenderFrame(rj->re,
- rj->main,
- rj->scene,
- rj->single_layer,
- rj->camera_override,
- rj->scene->r.cfra,
- rj->write_still);
+ rj->scene->r.cfra,
+ rj->write_still);
}
RE_SetReports(rj->re, NULL);
@@ -976,7 +975,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
/* cleanup sequencer caches before starting user triggered render.
* otherwise, invalidated cache entries can make their way into
- * the output rendering. We can't put that into RE_BlenderFrame,
+ * the output rendering. We can't put that into RE_RenderFrame,
* since sequence rendering can call that recursively... (peter) */
BKE_sequencer_cache_cleanup(scene);
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 64f20a4a348..e082e961b45 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -270,7 +270,7 @@ static const char *preview_collection_name(const char pr_type)
case MA_FLUID:
return "Fluid";
case MA_SPHERE_A:
- return "World Shader Ball";
+ return "World Sphere";
case MA_LAMP:
return "Lamp";
case MA_SKY:
@@ -437,7 +437,14 @@ static Scene *preview_prepare_scene(
sce->world->horb = 0.05f;
}
- set_preview_visibility(sce, view_layer, mat->pr_type, sp->pr_method);
+ if (sp->pr_method == PR_ICON_RENDER && sp->pr_main == G_pr_main_grease_pencil) {
+ /* For grease pencil, always use sphere for icon renders. */
+ set_preview_visibility(sce, view_layer, MA_SPHERE_A, sp->pr_method);
+ }
+ else {
+ /* Use specified preview shape for both preview panel and icon previews. */
+ set_preview_visibility(sce, view_layer, mat->pr_type, sp->pr_method);
+ }
if (sp->pr_method != PR_ICON_RENDER) {
if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) {
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 8c73f4cd649..c2f9beb5d78 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -50,6 +50,7 @@
#include "ED_screen.h"
#include "ED_screen_types.h"
#include "ED_space_api.h"
+#include "ED_time_scrub_ui.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
@@ -202,7 +203,7 @@ static void area_draw_azone_fullscreen(short x1, short y1, short x2, short y2, f
alpha = min_ff(alpha, 0.75f);
- UI_icon_draw_aspect(x, y, ICON_FULLSCREEN_EXIT, 0.7f / UI_DPI_FAC, alpha, NULL);
+ UI_icon_draw_ex(x, y, ICON_FULLSCREEN_EXIT, 0.7f * U.inv_dpi_fac, 0.0f, alpha, NULL, false);
/* debug drawing :
* The click_rect is the same as defined in fullscreen_click_rcti_init
@@ -1058,11 +1059,11 @@ static void region_azones_scrollbars_initialize(ScrArea *sa, ARegion *ar)
{
const View2D *v2d = &ar->v2d;
- if ((v2d->scroll & V2D_SCROLL_VERTICAL) && ((v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) == 0)) {
+ if ((v2d->scroll & V2D_SCROLL_VERTICAL) && ((v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES) == 0)) {
region_azone_scrollbar_initialize(sa, ar, AZ_SCROLL_VERT);
}
if ((v2d->scroll & V2D_SCROLL_HORIZONTAL) &&
- ((v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) == 0)) {
+ ((v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES) == 0)) {
region_azone_scrollbar_initialize(sa, ar, AZ_SCROLL_HOR);
}
}
@@ -1604,14 +1605,19 @@ static void ed_default_handlers(
wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "View2D", 0, 0);
WM_event_add_keymap_handler(handlers, keymap);
}
- if (flag & ED_KEYMAP_MARKERS) {
+ if (flag & ED_KEYMAP_ANIMATION) {
+ wmKeyMap *keymap;
+
/* time-markers */
- wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Markers", 0, 0);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Markers", 0, 0);
WM_event_add_keymap_handler_poll(handlers, keymap, event_in_markers_region);
- }
- if (flag & ED_KEYMAP_ANIMATION) {
+
+ /* time-scrubbing */
+ keymap = WM_keymap_ensure(wm->defaultconf, "Scrubbing", 0, 0);
+ WM_event_add_keymap_handler_poll(handlers, keymap, ED_event_in_scrubbing_region);
+
/* frame changing and timeline operators (for time spaces) */
- wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Animation", 0, 0);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Animation", 0, 0);
WM_event_add_keymap_handler(handlers, keymap);
}
if (flag & ED_KEYMAP_FRAMES) {
@@ -1621,14 +1627,19 @@ static void ed_default_handlers(
}
if (flag & ED_KEYMAP_HEADER) {
/* standard keymap for headers regions */
- wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Header", 0, 0);
+ wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Region Context Menu", 0, 0);
WM_event_add_keymap_handler(handlers, keymap);
}
if (flag & ED_KEYMAP_FOOTER) {
/* standard keymap for footer regions */
- wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Footer", 0, 0);
+ wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Region Context Menu", 0, 0);
WM_event_add_keymap_handler(handlers, keymap);
}
+ if (flag & ED_KEYMAP_NAVBAR) {
+ /* standard keymap for Navigation bar regions */
+ wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Region Context Menu", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+ }
/* Keep last because of LMB/RMB handling, see: T57527. */
if (flag & ED_KEYMAP_GPENCIL) {
@@ -2289,34 +2300,62 @@ 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_layout_ex(
- const bContext *C, ARegion *ar, const char *contexts[], int contextnr, const bool vertical)
+void ED_region_panels_layout_ex(const bContext *C,
+ ARegion *ar,
+ ListBase *paneltypes,
+ const char *contexts[],
+ int contextnr,
+ const bool vertical,
+ const char *category_override)
{
+ /* collect panels to draw */
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ LinkNode *panel_types_stack = NULL;
+ for (PanelType *pt = paneltypes->last; pt; pt = pt->prev) {
+ /* Only draw top level panels. */
+ if (pt->parent) {
+ continue;
+ }
+
+ if (category_override) {
+ if (!STREQ(pt->category, category_override)) {
+ continue;
+ }
+ }
+
+ /* verify context */
+ if (contexts && pt->context[0] && !streq_array_any(pt->context, contexts)) {
+ continue;
+ }
+
+ /* If we're tagged, only use compatible. */
+ if (pt->owner_id[0] && BKE_workspace_owner_id_check(workspace, pt->owner_id) == false) {
+ continue;
+ }
+
+ /* draw panel */
+ if (pt->draw && (!pt->poll || pt->poll(C, pt))) {
+ BLI_linklist_prepend_alloca(&panel_types_stack, pt);
+ }
+ }
+
ar->runtime.category = NULL;
- const WorkSpace *workspace = CTX_wm_workspace(C);
ScrArea *sa = CTX_wm_area(C);
- PanelType *pt;
View2D *v2d = &ar->v2d;
int x, y, w, em;
- bool is_context_new = 0;
- int scroll;
/* XXX, should use some better check? */
/* For now also has hardcoded check for clip editor until it supports actual toolbar. */
- bool use_category_tabs = ((1 << ar->regiontype) & RGN_TYPE_HAS_CATEGORY_MASK) ||
- (ar->regiontype == RGN_TYPE_TOOLS && sa->spacetype == SPACE_CLIP);
+ bool use_category_tabs = (category_override == NULL) &&
+ ((((1 << ar->regiontype) & RGN_TYPE_HAS_CATEGORY_MASK) ||
+ (ar->regiontype == RGN_TYPE_TOOLS && sa->spacetype == SPACE_CLIP)));
/* offset panels for small vertical tab area */
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 *);
-
- if (contextnr != -1) {
- is_context_new = UI_view2d_tab_set(v2d, contextnr);
- }
+ const bool is_context_new = (contextnr != -1) ? UI_view2d_tab_set(v2d, contextnr) : false;
/* before setting the view */
if (vertical) {
@@ -2334,45 +2373,21 @@ void ED_region_panels_layout_ex(
v2d->scroll |= (V2D_SCROLL_BOTTOM);
v2d->scroll &= ~(V2D_SCROLL_RIGHT);
}
-
- scroll = v2d->scroll;
-
- /* collect panels to draw */
- for (pt = ar->type->paneltypes.last; pt; pt = pt->prev) {
- /* Only draw top level panels. */
- if (pt->parent) {
- continue;
- }
-
- /* verify context */
- if (contexts && pt->context[0] && !streq_array_any(pt->context, contexts)) {
- continue;
- }
-
- /* If we're tagged, only use compatible. */
- if (pt->owner_id[0] && BKE_workspace_owner_id_check(workspace, pt->owner_id) == false) {
- continue;
- }
-
- /* draw panel */
- if (pt->draw && (!pt->poll || pt->poll(C, pt))) {
- BLI_SMALLSTACK_PUSH(pt_stack, pt);
- }
- }
+ const int scroll = v2d->scroll;
/* collect categories */
if (use_category_tabs) {
UI_panel_category_clear_all(ar);
/* gather unique categories */
- BLI_SMALLSTACK_ITER_BEGIN (pt_stack, pt) {
+ for (LinkNode *pt_link = panel_types_stack; pt_link; pt_link = pt_link->next) {
+ PanelType *pt = pt_link->link;
if (pt->category[0]) {
if (!UI_panel_category_find(ar, pt->category)) {
UI_panel_category_add(ar, pt->category);
}
}
}
- BLI_SMALLSTACK_ITER_END;
if (!UI_panel_category_is_visible(ar)) {
use_category_tabs = false;
@@ -2400,7 +2415,8 @@ void ED_region_panels_layout_ex(
/* set view2d view matrix - UI_block_begin() stores it */
UI_view2d_view_ortho(v2d);
- BLI_SMALLSTACK_ITER_BEGIN (pt_stack, pt) {
+ for (LinkNode *pt_link = panel_types_stack; pt_link; pt_link = pt_link->next) {
+ PanelType *pt = pt_link->link;
Panel *panel = UI_panel_find_by_type(&ar->panels, pt);
if (use_category_tabs && pt->category[0] && !STREQ(category, pt->category)) {
@@ -2411,7 +2427,6 @@ void ED_region_panels_layout_ex(
ed_panel_draw(C, sa, ar, &ar->panels, pt, panel, w, em, vertical);
}
- BLI_SMALLSTACK_ITER_END;
/* align panels and return size */
UI_panels_end(C, ar, &x, &y);
@@ -2482,9 +2497,11 @@ void ED_region_panels_layout_ex(
ar->runtime.category = category;
}
}
+
void ED_region_panels_layout(const bContext *C, ARegion *ar)
{
- ED_region_panels_layout_ex(C, ar, NULL, -1, true);
+ bool vertical = true;
+ ED_region_panels_layout_ex(C, ar, &ar->type->paneltypes, NULL, -1, vertical, NULL);
}
void ED_region_panels_draw(const bContext *C, ARegion *ar)
@@ -2533,7 +2550,7 @@ 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_layout_ex(C, ar, &ar->type->paneltypes, contexts, contextnr, vertical, NULL);
ED_region_panels_draw(C, ar);
}
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 61fa05f243f..af90bbc9975 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -67,7 +67,6 @@
#include "WM_types.h"
#include "DEG_depsgraph.h"
-#include "DEG_depsgraph_query.h"
#include "ED_anim_api.h"
#include "ED_armature.h"
@@ -343,7 +342,7 @@ bool ED_operator_console_active(bContext *C)
static bool ed_object_hidden(Object *ob)
{
/* if hidden but in edit mode, we still display, can happen with animation */
- return ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT));
+ return ((ob->restrictflag & OB_RESTRICT_VIEWPORT) && !(ob->mode & OB_MODE_EDIT));
}
bool ED_operator_object_active(bContext *C)
@@ -632,24 +631,6 @@ static bool screen_active_editable(bContext *C)
return 0;
}
-static ARegion *screen_find_region_type(bContext *C, int type)
-{
- ARegion *ar = CTX_wm_region(C);
-
- /* find the header region
- * - try context first, but upon failing, search all regions in area...
- */
- if ((ar == NULL) || (ar->regiontype != type)) {
- ScrArea *sa = CTX_wm_area(C);
- ar = BKE_area_find_region_type(sa, type);
- }
- else {
- ar = NULL;
- }
-
- return ar;
-}
-
/** \} */
/* -------------------------------------------------------------------- */
@@ -2771,7 +2752,7 @@ static int frame_offset_exec(bContext *C, wmOperator *op)
areas_do_frame_follow(C, false);
- BKE_sound_update_and_seek(bmain, CTX_data_depsgraph(C));
+ BKE_sound_seek_scene(bmain, scene);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
@@ -2833,7 +2814,7 @@ static int frame_jump_exec(bContext *C, wmOperator *op)
areas_do_frame_follow(C, true);
- BKE_sound_update_and_seek(bmain, CTX_data_depsgraph(C));
+ BKE_sound_seek_scene(bmain, scene);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
@@ -2949,7 +2930,7 @@ static int keyframe_jump_exec(bContext *C, wmOperator *op)
else {
areas_do_frame_follow(C, true);
- BKE_sound_update_and_seek(bmain, CTX_data_depsgraph(C));
+ BKE_sound_seek_scene(bmain, scene);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
@@ -3016,7 +2997,7 @@ static int marker_jump_exec(bContext *C, wmOperator *op)
areas_do_frame_follow(C, true);
- BKE_sound_update_and_seek(bmain, CTX_data_depsgraph(C));
+ BKE_sound_seek_scene(bmain, scene);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
@@ -3956,10 +3937,10 @@ static void SCREEN_OT_header_toggle_menus(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Header Tools Operator
+/** \name Region Context Menu Operator (Header/Footer/Navbar)
* \{ */
-static bool header_context_menu_poll(bContext *C)
+static bool screen_region_context_menu_poll(bContext *C)
{
ScrArea *sa = CTX_wm_area(C);
return (sa && sa->spacetype != SPACE_STATUSBAR);
@@ -4009,89 +3990,17 @@ void ED_screens_header_tools_menu_create(bContext *C, uiLayout *layout, void *UN
}
}
-static int header_context_menu_invoke(bContext *C,
- wmOperator *UNUSED(op),
- const wmEvent *UNUSED(event))
-{
- uiPopupMenu *pup;
- uiLayout *layout;
-
- pup = UI_popup_menu_begin(C, IFACE_("Header"), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
-
- ED_screens_header_tools_menu_create(C, layout, NULL);
-
- UI_popup_menu_end(C, pup);
-
- return OPERATOR_INTERFACE;
-}
-
-static void SCREEN_OT_header_context_menu(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Header Context Menu";
- ot->description = "Display header region context menu";
- ot->idname = "SCREEN_OT_header_context_menu";
-
- /* api callbacks */
- ot->poll = header_context_menu_poll;
- ot->invoke = header_context_menu_invoke;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Footer Toggle Operator
- * \{ */
-
-static int footer_exec(bContext *C, wmOperator *UNUSED(op))
-{
- ARegion *ar = screen_find_region_type(C, RGN_TYPE_FOOTER);
-
- if (ar == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- ar->flag ^= RGN_FLAG_HIDDEN;
-
- ED_area_tag_redraw(CTX_wm_area(C));
-
- WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
-}
-
-static void SCREEN_OT_footer(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Toggle Footer";
- ot->description = "Toggle footer display";
- ot->idname = "SCREEN_OT_footer";
-
- /* api callbacks */
- ot->exec = footer_exec;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Footer Tools Operator
- * \{ */
-
-static bool footer_context_menu_poll(bContext *C)
-{
- ScrArea *sa = CTX_wm_area(C);
- return sa;
-}
-
void ED_screens_footer_tools_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg))
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
const char *but_flip_str = (ar->alignment == RGN_ALIGN_TOP) ? IFACE_("Flip to Bottom") :
IFACE_("Flip to Top");
-
- uiItemO(layout, IFACE_("Toggle Footer"), ICON_NONE, "SCREEN_OT_footer");
+ {
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)CTX_wm_screen(C), &RNA_Space, sa->spacedata.first, &ptr);
+ uiItemR(layout, &ptr, "show_region_footer", 0, IFACE_("Show Footer"), ICON_NONE);
+ }
/* default is WM_OP_INVOKE_REGION_WIN, which we don't want here. */
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
@@ -4108,51 +4017,58 @@ void ED_screens_footer_tools_menu_create(bContext *C, uiLayout *layout, void *UN
}
}
-static int footer_context_menu_invoke(bContext *C,
+void ED_screens_navigation_bar_tools_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg))
+{
+ const ARegion *ar = CTX_wm_region(C);
+ const char *but_flip_str = (ar->alignment == RGN_ALIGN_LEFT) ? IFACE_("Flip to Right") :
+ IFACE_("Flip to Left");
+
+ /* default is WM_OP_INVOKE_REGION_WIN, which we don't want here. */
+ uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
+
+ uiItemO(layout, but_flip_str, ICON_NONE, "SCREEN_OT_region_flip");
+}
+
+static int screen_context_menu_invoke(bContext *C,
wmOperator *UNUSED(op),
const wmEvent *UNUSED(event))
{
uiPopupMenu *pup;
uiLayout *layout;
+ const ARegion *ar = CTX_wm_region(C);
- pup = UI_popup_menu_begin(C, IFACE_("Footer"), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
-
- ED_screens_footer_tools_menu_create(C, layout, NULL);
-
- UI_popup_menu_end(C, pup);
+ if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) {
+ pup = UI_popup_menu_begin(C, IFACE_("Header"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+ ED_screens_header_tools_menu_create(C, layout, NULL);
+ UI_popup_menu_end(C, pup);
+ }
+ else if (ar->regiontype == RGN_TYPE_FOOTER) {
+ pup = UI_popup_menu_begin(C, IFACE_("Footer"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+ ED_screens_footer_tools_menu_create(C, layout, NULL);
+ UI_popup_menu_end(C, pup);
+ }
+ else if (ar->regiontype == RGN_TYPE_NAV_BAR) {
+ pup = UI_popup_menu_begin(C, IFACE_("Navigation Bar"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+ ED_screens_navigation_bar_tools_menu_create(C, layout, NULL);
+ UI_popup_menu_end(C, pup);
+ }
return OPERATOR_INTERFACE;
}
-static void SCREEN_OT_footer_context_menu(wmOperatorType *ot)
+static void SCREEN_OT_region_context_menu(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Footer Context Menu";
- ot->description = "Display footer region context menu";
- ot->idname = "SCREEN_OT_footer_context_menu";
+ ot->name = "Region Context Menu";
+ ot->description = "Display region context menu";
+ ot->idname = "SCREEN_OT_region_context_menu";
/* api callbacks */
- ot->poll = footer_context_menu_poll;
- ot->invoke = footer_context_menu_invoke;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Navigation Bar Tools Menu
- * \{ */
-
-void ED_screens_navigation_bar_tools_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg))
-{
- const ARegion *ar = CTX_wm_region(C);
- const char *but_flip_str = (ar->alignment == RGN_ALIGN_LEFT) ? IFACE_("Flip to Right") :
- IFACE_("Flip to Left");
-
- /* default is WM_OP_INVOKE_REGION_WIN, which we don't want here. */
- uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
-
- uiItemO(layout, but_flip_str, ICON_NONE, "SCREEN_OT_region_flip");
+ ot->poll = screen_region_context_menu_poll;
+ ot->invoke = screen_context_menu_invoke;
}
/** \} */
@@ -4288,8 +4204,7 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
if (screen->animtimer && screen->animtimer == event->customdata) {
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
wmTimer *wt = screen->animtimer;
ScreenAnimData *sad = wt->customdata;
wmWindowManager *wm = CTX_wm_manager(C);
@@ -4310,7 +4225,7 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
}
if ((scene->audio.flag & AUDIO_SYNC) && (sad->flag & ANIMPLAY_FLAG_REVERSE) == false &&
- isfinite(time = BKE_sound_sync_scene(scene_eval))) {
+ isfinite(time = BKE_sound_sync_scene(scene))) {
double newfra = (double)time * FPS;
/* give some space here to avoid jumps */
@@ -4403,7 +4318,7 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
}
if (sad->flag & ANIMPLAY_FLAG_JUMPED) {
- BKE_sound_update_and_seek(bmain, depsgraph);
+ BKE_sound_seek_scene(bmain, scene);
#ifdef PROFILE_AUDIO_SYNCH
old_frame = CFRA;
#endif
@@ -4525,12 +4440,11 @@ int ED_screen_animation_play(bContext *C, int sync, int mode)
{
bScreen *screen = CTX_wm_screen(C);
Scene *scene = CTX_data_scene(C);
- Scene *scene_eval = DEG_get_evaluated_scene(CTX_data_depsgraph(C));
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
/* stop playback now */
ED_screen_animation_timer(C, 0, 0, 0, 0);
- BKE_sound_stop_scene(scene_eval);
+ BKE_sound_stop_scene(scene);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
@@ -4539,7 +4453,7 @@ int ED_screen_animation_play(bContext *C, int sync, int mode)
int refresh = SPACE_ACTION;
if (mode == 1) { /* XXX only play audio forwards!? */
- BKE_sound_play_scene(scene_eval);
+ BKE_sound_play_scene(scene);
}
ED_screen_animation_timer(C, screen->redraws_flag, refresh, sync, mode);
@@ -5302,9 +5216,7 @@ void ED_operatortypes_screen(void)
WM_operatortype_append(SCREEN_OT_region_scale);
WM_operatortype_append(SCREEN_OT_region_flip);
WM_operatortype_append(SCREEN_OT_header_toggle_menus);
- WM_operatortype_append(SCREEN_OT_header_context_menu);
- WM_operatortype_append(SCREEN_OT_footer);
- WM_operatortype_append(SCREEN_OT_footer_context_menu);
+ WM_operatortype_append(SCREEN_OT_region_context_menu);
WM_operatortype_append(SCREEN_OT_screen_set);
WM_operatortype_append(SCREEN_OT_screen_full_area);
WM_operatortype_append(SCREEN_OT_back_to_previous);
diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c
index 2dfa05cf6b0..863e3a15120 100644
--- a/source/blender/editors/screen/workspace_edit.c
+++ b/source/blender/editors/screen/workspace_edit.c
@@ -373,13 +373,15 @@ static int workspace_append_activate_exec(bContext *C, wmOperator *op)
&bmain->workspaces, idname, offsetof(ID, name) + 2);
BLI_assert(appended_workspace != NULL);
- /* Reorder to last position. */
- BKE_id_reorder(&bmain->workspaces, &appended_workspace->id, NULL, true);
+ if (appended_workspace) {
+ /* Reorder to last position. */
+ BKE_id_reorder(&bmain->workspaces, &appended_workspace->id, NULL, true);
- /* Changing workspace changes context. Do delayed! */
- WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, appended_workspace);
+ /* Changing workspace changes context. Do delayed! */
+ WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, appended_workspace);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
+ }
}
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 5a45f4946f2..f7a589350f9 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -47,6 +47,7 @@
#include "BKE_colorband.h"
#include "BKE_context.h"
#include "BKE_brush.h"
+#include "BKE_image.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
@@ -154,7 +155,7 @@ void ED_imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int
}
}
- ibuf->userflags |= IB_BITMAPDIRTY;
+ BKE_image_mark_dirty(ima, ibuf);
if (tmpibuf) {
IMB_freeImBuf(tmpibuf);
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 0340a4989e1..d7553d18d3b 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -1837,7 +1837,7 @@ static int project_paint_undo_subtiles(const TileInfo *tinf, int tx, int ty)
false);
}
- pjIma->ibuf->userflags |= IB_BITMAPDIRTY;
+ BKE_image_mark_dirty(pjIma->ima, pjIma->ibuf);
/* tile ready, publish */
if (tinf->lock) {
BLI_spin_lock(tinf->lock);
@@ -6394,7 +6394,7 @@ static const EnumPropertyItem layer_type_items[] = {
{0, NULL, 0, NULL, NULL},
};
-static Image *proj_paint_image_create(wmOperator *op, Main *bmain)
+static Image *proj_paint_image_create(wmOperator *op, Main *bmain, bool is_data)
{
Image *ima;
float color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
@@ -6417,6 +6417,11 @@ static Image *proj_paint_image_create(wmOperator *op, Main *bmain)
ima = BKE_image_add_generated(
bmain, width, height, imagename, alpha ? 32 : 24, use_float, gen_type, color, false);
+ if (is_data) {
+ STRNCPY(ima->colorspace_settings.name,
+ IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DATA));
+ }
+
return ima;
}
@@ -6487,6 +6492,7 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
if (ma) {
Main *bmain = CTX_data_main(C);
int type = RNA_enum_get(op->ptr, "type");
+ bool is_data = (type > LAYER_BASE_COLOR);
bNode *imanode;
bNodeTree *ntree = ma->nodetree;
@@ -6501,7 +6507,7 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
/* try to add an image node */
imanode = nodeAddStaticNode(C, ntree, SH_NODE_TEX_IMAGE);
- ima = proj_paint_image_create(op, bmain);
+ ima = proj_paint_image_create(op, bmain, is_data);
imanode->id = &ima->id;
nodeSetActive(ntree, imanode);
@@ -6553,12 +6559,6 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
}
}
- if (type > LAYER_BASE_COLOR) {
- /* This is a "non color data" image */
- NodeTexImage *tex = imanode->storage;
- tex->color_space = SHD_COLORSPACE_NONE;
- }
-
/* Check if the socket in already connected to something */
bNodeLink *link = in_sock ? in_sock->link : NULL;
if (in_sock != NULL && link == NULL) {
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index 6d003820723..84b4a130183 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -389,6 +389,7 @@ static int imapaint_pick_face(ViewContext *vc,
}
/* sample only on the exact position */
+ ED_view3d_select_id_validate(vc);
*r_index = ED_view3d_select_id_sample(vc, mval[0], mval[1]);
if ((*r_index) == 0 || (*r_index) > (unsigned int)totpoly) {
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 c1c2964156f..c904bf2005b 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
@@ -161,7 +161,7 @@ void PAINT_OT_weight_from_bones(wmOperatorType *ot)
ot->poll = weight_from_bones_poll;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
/* properties */
ot->prop = RNA_def_enum(
@@ -880,7 +880,7 @@ void PAINT_OT_weight_gradient(wmOperatorType *ot)
ot->cancel = WM_gesture_straightline_cancel;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
prop = RNA_def_enum(ot->srna, "type", gradient_types, 0, "Type", "");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
diff --git a/source/blender/editors/sound/CMakeLists.txt b/source/blender/editors/sound/CMakeLists.txt
index 7f4b5a45aa3..c2a88041a85 100644
--- a/source/blender/editors/sound/CMakeLists.txt
+++ b/source/blender/editors/sound/CMakeLists.txt
@@ -19,7 +19,6 @@ set(INC
../include
../../blenkernel
../../blenlib
- ../../depsgraph
../../makesdna
../../makesrna
../../windowmanager
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index 8ac49e447fe..25c05e2d1d0 100644
--- a/source/blender/editors/sound/sound_ops.c
+++ b/source/blender/editors/sound/sound_ops.c
@@ -62,8 +62,6 @@
# include <AUD_Special.h>
#endif
-#include "DEG_depsgraph_query.h"
-
#include "ED_sound.h"
#include "ED_util.h"
@@ -90,6 +88,7 @@ static int sound_open_exec(bContext *C, wmOperator *op)
bSound *sound;
PropertyPointerRNA *pprop;
PointerRNA idptr;
+ AUD_SoundInfo info;
Main *bmain = CTX_data_main(C);
RNA_string_get(op->ptr, "filepath", path);
@@ -99,8 +98,29 @@ static int sound_open_exec(bContext *C, wmOperator *op)
sound_open_init(C, op);
}
+ if (sound->playback_handle == NULL) {
+ if (op->customdata) {
+ MEM_freeN(op->customdata);
+ }
+ BKE_id_free(bmain, sound);
+ BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
+ return OPERATOR_CANCELLED;
+ }
+
+ info = AUD_getInfo(sound->playback_handle);
+
+ if (info.specs.channels == AUD_CHANNELS_INVALID) {
+ BKE_id_free(bmain, sound);
+ if (op->customdata) {
+ MEM_freeN(op->customdata);
+ }
+ BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
+ return OPERATOR_CANCELLED;
+ }
+
if (RNA_boolean_get(op->ptr, "mono")) {
sound->flags |= SOUND_FLAGS_MONO;
+ BKE_sound_load(bmain, sound);
}
if (RNA_boolean_get(op->ptr, "cache")) {
@@ -120,8 +140,6 @@ static int sound_open_exec(bContext *C, wmOperator *op)
RNA_property_update(C, &pprop->ptr, pprop->prop);
}
- DEG_relations_tag_update(bmain);
-
MEM_freeN(op->customdata);
return OPERATOR_FINISHED;
}
@@ -343,9 +361,8 @@ static int sound_mixdown_exec(bContext *C, wmOperator *op)
#ifdef WITH_AUDASPACE
char path[FILE_MAX];
char filename[FILE_MAX];
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
- Main *bmain = CTX_data_main(C);
+ Scene *scene;
+ Main *bmain;
int split;
int bitrate, accuracy;
@@ -363,20 +380,18 @@ static int sound_mixdown_exec(bContext *C, wmOperator *op)
container = RNA_enum_get(op->ptr, "container");
codec = RNA_enum_get(op->ptr, "codec");
split = RNA_boolean_get(op->ptr, "split_channels");
- specs.channels = scene_eval->r.ffcodecdata.audio_channels;
- specs.rate = scene_eval->r.ffcodecdata.audio_mixrate;
+ scene = CTX_data_scene(C);
+ bmain = CTX_data_main(C);
+ specs.channels = scene->r.ffcodecdata.audio_channels;
+ specs.rate = scene->r.ffcodecdata.audio_mixrate;
BLI_strncpy(filename, path, sizeof(filename));
BLI_path_abs(filename, BKE_main_blendfile_path(bmain));
- const double fps = (((double)scene_eval->r.frs_sec) / (double)scene_eval->r.frs_sec_base);
- const int start_frame = scene_eval->r.sfra;
- const int end_frame = scene_eval->r.efra;
-
if (split) {
- result = AUD_mixdown_per_channel(scene_eval->sound_scene,
- start_frame * specs.rate / fps,
- (end_frame - start_frame + 1) * specs.rate / fps,
+ result = AUD_mixdown_per_channel(scene->sound_scene,
+ SFRA * specs.rate / FPS,
+ (EFRA - SFRA + 1) * specs.rate / FPS,
accuracy,
filename,
specs,
@@ -385,9 +400,9 @@ static int sound_mixdown_exec(bContext *C, wmOperator *op)
bitrate);
}
else {
- result = AUD_mixdown(scene_eval->sound_scene,
- start_frame * specs.rate / fps,
- (end_frame - start_frame + 1) * specs.rate / fps,
+ result = AUD_mixdown(scene->sound_scene,
+ SFRA * specs.rate / FPS,
+ (EFRA - SFRA + 1) * specs.rate / FPS,
accuracy,
filename,
specs,
@@ -396,7 +411,7 @@ static int sound_mixdown_exec(bContext *C, wmOperator *op)
bitrate);
}
- BKE_sound_reset_scene_specs(scene_eval);
+ BKE_sound_reset_scene_specs(scene);
if (result) {
BKE_report(op->reports, RPT_ERROR, result);
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index 2a6ae93fc99..f32207fe08b 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -411,7 +411,7 @@ void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene)
}
GPU_matrix_push();
- GPU_matrix_translate_2f(0.0, (float)V2D_SCROLL_HEIGHT_TEXT + yoffs);
+ GPU_matrix_translate_2f(0.0, (float)V2D_SCROLL_HEIGHT_HANDLES + yoffs);
GPU_matrix_scale_2f(1.0, cache_draw_height);
switch (pid->type) {
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index 8ecd25bda76..1371305487e 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -47,6 +47,7 @@
#include "BKE_gpencil.h"
#include "UI_view2d.h"
+#include "UI_interface.h"
#include "ED_anim_api.h"
#include "ED_gpencil.h"
diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c
index 5ac6297e108..972f19bb643 100644
--- a/source/blender/editors/space_action/space_action.c
+++ b/source/blender/editors/space_action/space_action.c
@@ -45,6 +45,7 @@
#include "WM_types.h"
#include "WM_message.h"
+#include "UI_interface.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -52,6 +53,7 @@
#include "ED_screen.h"
#include "ED_anim_api.h"
#include "ED_markers.h"
+#include "ED_time_scrub_ui.h"
#include "action_intern.h" /* own include */
#include "GPU_framebuffer.h"
@@ -69,7 +71,7 @@ static SpaceLink *action_new(const ScrArea *sa, const Scene *scene)
saction->autosnap = SACTSNAP_FRAME;
saction->mode = SACTCONT_DOPESHEET;
saction->mode_prev = SACTCONT_DOPESHEET;
- saction->flag = SACTION_SHOW_INTERPOLATION;
+ saction->flag = SACTION_SHOW_INTERPOLATION | SACTION_SHOW_MARKER_LINES;
saction->ads.filterflag |= ADS_FILTER_SUMMARY;
@@ -125,7 +127,7 @@ static SpaceLink *action_new(const ScrArea *sa, const Scene *scene)
ar->v2d.minzoom = 0.01f;
ar->v2d.maxzoom = 50;
- ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
+ ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
ar->v2d.scroll |= (V2D_SCROLL_RIGHT);
ar->v2d.keepzoom = V2D_LOCKZOOM_Y;
ar->v2d.keepofs = V2D_KEEPOFS_Y;
@@ -234,20 +236,13 @@ static void action_main_region_draw(const bContext *C, ARegion *ar)
/* reset view matrix */
UI_view2d_view_restore(C);
+ /* scrubbing region */
+ ED_scrubbing_draw(ar, scene, saction->flag & SACTION_DRAWTIME, true);
+
/* scrollers */
scrollers = UI_view2d_scrollers_calc(v2d, NULL);
UI_view2d_scrollers_draw(v2d, scrollers);
UI_view2d_scrollers_free(scrollers);
-
- /* frame numbers */
- UI_view2d_draw_scale_x__discrete_frames_or_seconds(
- ar, v2d, &v2d->hor, scene, saction->flag & SACTION_DRAWTIME, TH_TEXT);
-
- /* draw current frame number-indicator on top of scrollers */
- if ((saction->flag & SACTION_NODRAWCFRANUM) == 0) {
- UI_view2d_view_orthoSpecial(ar, v2d, 1);
- ANIM_draw_cfra_number(C, v2d, cfra_flag);
- }
}
/* add handlers, stuff you only do once or on area/region changes */
@@ -285,6 +280,9 @@ static void action_channel_region_draw(const bContext *C, ARegion *ar)
draw_channel_names((bContext *)C, &ac, ar);
}
+ /* channel filter next to scrubbing area */
+ ED_channel_search_draw(C, ar, ac.ads);
+
/* reset view matrix */
UI_view2d_view_restore(C);
@@ -869,7 +867,7 @@ void ED_spacetype_action(void)
art->draw = action_main_region_draw;
art->listener = action_main_region_listener;
art->message_subscribe = saction_main_region_message_subscribe;
- art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
+ art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
BLI_addhead(&st->regiontypes, art);
@@ -901,7 +899,7 @@ void ED_spacetype_action(void)
/* regions: UI buttons */
art = MEM_callocN(sizeof(ARegionType), "spacetype action region");
art->regionid = RGN_TYPE_UI;
- art->prefsizex = 200;
+ art->prefsizex = UI_SIDEBAR_PANEL_WIDTH;
art->keymapflag = ED_KEYMAP_UI;
art->listener = action_region_listener;
art->init = action_buttons_area_init;
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index 577f7a7af8a..fde8b8f85f8 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -785,8 +785,11 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
SpaceProperties *sbuts = CTX_wm_space_properties(C);
ButsContextPath *path = sbuts ? sbuts->path : NULL;
- /* A zero sized path will be set for 'BCONTEXT_TOOL'. */
- if (!path || !path->len) {
+ if (sbuts->mainb == BCONTEXT_TOOL) {
+ return 0;
+ }
+
+ if (!path) {
return 0;
}
diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c
index fe4ed0209bf..500efe4bb4d 100644
--- a/source/blender/editors/space_buttons/buttons_ops.c
+++ b/source/blender/editors/space_buttons/buttons_ops.c
@@ -56,15 +56,10 @@
static int context_menu_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
- const ARegion *ar = CTX_wm_region(C);
uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Context Menu"), ICON_NONE);
uiLayout *layout = UI_popup_menu_layout(pup);
uiItemM(layout, "INFO_MT_area", NULL, ICON_NONE);
- if (ar->regiontype == RGN_TYPE_NAV_BAR) {
- ED_screens_navigation_bar_tools_menu_create(C, layout, NULL);
- }
-
UI_popup_menu_end(C, pup);
return OPERATOR_INTERFACE;
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index f9244049d54..9b0150d731d 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -34,6 +34,7 @@
#include "ED_space_api.h"
#include "ED_screen.h"
+#include "ED_view3d.h" /* To draw toolbar UI. */
#include "WM_api.h"
#include "WM_types.h"
@@ -198,105 +199,7 @@ static void buttons_main_region_layout_properties(const bContext *C,
}
const bool vertical = true;
- ED_region_panels_layout_ex(C, ar, contexts, sbuts->mainb, vertical);
-}
-
-static void buttons_main_region_layout_tool(const bContext *C, ARegion *ar)
-{
- const enum eContextObjectMode mode = CTX_data_mode_enum(C);
-
- const char *contexts_base[5] = {NULL};
- contexts_base[0] = ".active_tool";
- const char **contexts = &contexts_base[1];
-
- /* Hard coded to 3D view. */
- {
- switch (mode) {
- case CTX_MODE_EDIT_MESH:
- ARRAY_SET_ITEMS(contexts, ".mesh_edit");
- break;
- case CTX_MODE_EDIT_CURVE:
- ARRAY_SET_ITEMS(contexts, ".curve_edit");
- break;
- case CTX_MODE_EDIT_SURFACE:
- ARRAY_SET_ITEMS(contexts, ".curve_edit");
- break;
- case CTX_MODE_EDIT_TEXT:
- ARRAY_SET_ITEMS(contexts, ".text_edit");
- break;
- case CTX_MODE_EDIT_ARMATURE:
- ARRAY_SET_ITEMS(contexts, ".armature_edit");
- break;
- case CTX_MODE_EDIT_METABALL:
- ARRAY_SET_ITEMS(contexts, ".mball_edit");
- break;
- case CTX_MODE_EDIT_LATTICE:
- ARRAY_SET_ITEMS(contexts, ".lattice_edit");
- break;
- case CTX_MODE_POSE:
- ARRAY_SET_ITEMS(contexts, ".posemode");
- break;
- case CTX_MODE_SCULPT:
- ARRAY_SET_ITEMS(contexts, ".paint_common", ".sculpt_mode");
- break;
- case CTX_MODE_PAINT_WEIGHT:
- ARRAY_SET_ITEMS(contexts, ".paint_common", ".weightpaint");
- break;
- case CTX_MODE_PAINT_VERTEX:
- ARRAY_SET_ITEMS(contexts, ".paint_common", ".vertexpaint");
- break;
- case CTX_MODE_PAINT_TEXTURE:
- ARRAY_SET_ITEMS(contexts, ".paint_common", ".imagepaint");
- break;
- case CTX_MODE_PARTICLE:
- ARRAY_SET_ITEMS(contexts, ".paint_common", ".particlemode");
- break;
- case CTX_MODE_OBJECT:
- ARRAY_SET_ITEMS(contexts, ".objectmode");
- break;
- case CTX_MODE_PAINT_GPENCIL:
- ARRAY_SET_ITEMS(contexts, ".greasepencil_paint");
- break;
- case CTX_MODE_SCULPT_GPENCIL:
- ARRAY_SET_ITEMS(contexts, ".greasepencil_sculpt");
- break;
- case CTX_MODE_WEIGHT_GPENCIL:
- ARRAY_SET_ITEMS(contexts, ".greasepencil_weight");
- break;
- default:
- break;
- }
- }
-
- /* for grease pencil we don't use tool system yet, so we need check outside
- * workspace->tools_space_type because this value is not available
- */
- switch (mode) {
- case CTX_MODE_PAINT_GPENCIL:
- ARRAY_SET_ITEMS(contexts, ".greasepencil_paint");
- break;
- case CTX_MODE_SCULPT_GPENCIL:
- ARRAY_SET_ITEMS(contexts, ".greasepencil_sculpt");
- break;
- case CTX_MODE_WEIGHT_GPENCIL:
- ARRAY_SET_ITEMS(contexts, ".greasepencil_weight");
- break;
- case CTX_MODE_EDIT_GPENCIL:
- ARRAY_SET_ITEMS(contexts, ".greasepencil_edit");
- break;
- default:
- break;
- }
-
- int i = 0;
- while (contexts_base[i]) {
- i++;
- }
- BLI_assert(i < ARRAY_SIZE(contexts_base));
- contexts_base[i] = ".workspace";
-
- const bool vertical = true;
- ED_region_panels_layout_ex(C, ar, contexts_base, -1, vertical);
+ ED_region_panels_layout_ex(C, ar, &ar->type->paneltypes, contexts, sbuts->mainb, vertical, NULL);
}
static void buttons_main_region_layout(const bContext *C, ARegion *ar)
@@ -305,7 +208,7 @@ static void buttons_main_region_layout(const bContext *C, ARegion *ar)
SpaceProperties *sbuts = CTX_wm_space_properties(C);
if (sbuts->mainb == BCONTEXT_TOOL) {
- buttons_main_region_layout_tool(C, ar);
+ ED_view3d_buttons_region_layout_ex(C, ar, "Tool");
}
else {
buttons_main_region_layout_properties(C, sbuts, ar);
@@ -400,9 +303,6 @@ static void buttons_header_region_message_subscribe(const bContext *UNUSED(C),
static void buttons_navigation_bar_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Property Editor", SPACE_PROPERTIES, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
-
ar->flag |= RGN_FLAG_PREFSIZE_OR_HIDDEN;
ED_region_panels_init(wm, ar);
@@ -749,7 +649,7 @@ void ED_spacetype_buttons(void)
art->regionid = RGN_TYPE_NAV_BAR;
art->prefsizex = AREAMINX - 3; /* XXX Works and looks best,
* should we update AREAMINX accordingly? */
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES | ED_KEYMAP_NAVBAR;
art->init = buttons_navigation_bar_region_init;
art->draw = buttons_navigation_bar_region_draw;
art->message_subscribe = buttons_navigation_bar_region_message_subscribe;
diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h
index 70dc1caf36f..081515ca4bc 100644
--- a/source/blender/editors/space_clip/clip_intern.h
+++ b/source/blender/editors/space_clip/clip_intern.h
@@ -35,7 +35,7 @@ struct bContext;
struct wmOperatorType;
/* channel heights */
-#define CHANNEL_FIRST (-0.8f * U.widget_unit)
+#define CHANNEL_FIRST (-UI_SCRUBBING_MARGIN_Y - CHANNEL_HEIGHT_HALF - CHANNEL_SKIP)
#define CHANNEL_HEIGHT (0.8f * U.widget_unit)
#define CHANNEL_HEIGHT_HALF (0.4f * U.widget_unit)
#define CHANNEL_SKIP (0.1f * U.widget_unit)
diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c
index 8b3f221f3a5..a6b1db1aa83 100644
--- a/source/blender/editors/space_clip/clip_ops.c
+++ b/source/blender/editors/space_clip/clip_ops.c
@@ -955,10 +955,10 @@ static bool change_frame_poll(bContext *C)
{
/* prevent changes during render */
if (G.is_rendering) {
- return 0;
+ return false;
}
-
- return ED_space_clip_poll(C);
+ SpaceClip *space_clip = CTX_wm_space_clip(C);
+ return space_clip != NULL;
}
static void change_frame_apply(bContext *C, wmOperator *op)
@@ -971,7 +971,7 @@ static void change_frame_apply(bContext *C, wmOperator *op)
SUBFRA = 0.0f;
/* do updates */
- BKE_sound_update_and_seek(CTX_data_main(C), CTX_data_depsgraph(C));
+ BKE_sound_seek_scene(CTX_data_main(C), scene);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index 5364c4bc3ca..13d190e6861 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -47,6 +47,7 @@
#include "ED_mask.h"
#include "ED_space_api.h"
#include "ED_screen.h"
+#include "ED_time_scrub_ui.h"
#include "ED_select_utils.h"
#include "ED_clip.h"
#include "ED_transform.h"
@@ -94,7 +95,7 @@ static void init_preview_region(const Scene *scene,
ar->v2d.minzoom = 0.01f;
ar->v2d.maxzoom = 50;
- ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
+ ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
ar->v2d.scroll |= (V2D_SCROLL_RIGHT);
ar->v2d.keepzoom = V2D_LOCKZOOM_Y;
ar->v2d.keepofs = V2D_KEEPOFS_Y;
@@ -115,8 +116,8 @@ static void init_preview_region(const Scene *scene,
ar->v2d.max[0] = MAXFRAMEF;
ar->v2d.max[1] = FLT_MAX;
- ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
- ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_SCALE_VERTICAL);
+ ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
+ ar->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HANDLES);
ar->v2d.minzoom = 0.0f;
ar->v2d.maxzoom = 0.0f;
@@ -249,7 +250,7 @@ static SpaceLink *clip_new(const ScrArea *sa, const Scene *scene)
sc->zoom = 1.0f;
sc->path_length = 20;
sc->scopes.track_preview_height = 120;
- sc->around = V3D_AROUND_LOCAL_ORIGINS;
+ sc->around = V3D_AROUND_CENTER_MEDIAN;
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for clip");
@@ -1001,9 +1002,13 @@ static void clip_preview_region_init(wmWindowManager *wm, ARegion *ar)
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
/* own keymap */
+
keymap = WM_keymap_ensure(wm->defaultconf, "Clip", SPACE_CLIP, 0);
WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Clip Scrubbing", SPACE_CLIP, RGN_TYPE_PREVIEW);
+ WM_event_add_keymap_handler_poll(&ar->handlers, keymap, ED_event_in_scrubbing_region);
+
keymap = WM_keymap_ensure(wm->defaultconf, "Clip Graph Editor", SPACE_CLIP, 0);
WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
@@ -1041,22 +1046,24 @@ static void graph_region_draw(const bContext *C, ARegion *ar)
/* reset view matrix */
UI_view2d_view_restore(C);
+ /* time-scrubbing */
+ ED_scrubbing_draw(ar, scene, sc->flag & SC_SHOW_SECONDS, true);
+
/* scrollers */
scrollers = UI_view2d_scrollers_calc(v2d, NULL);
UI_view2d_scrollers_draw(v2d, scrollers);
UI_view2d_scrollers_free(scrollers);
/* scale indicators */
- UI_view2d_draw_scale_x__discrete_frames_or_seconds(
- ar, v2d, &v2d->hor, scene, sc->flag & SC_SHOW_SECONDS, TH_TEXT);
- UI_view2d_draw_scale_y__values(ar, v2d, &v2d->vert, TH_TEXT);
-
- /* current frame indicator */
- if (sc->flag & SC_SHOW_SECONDS) {
- cfra_flag |= DRAWCFRA_UNIT_SECONDS;
+ {
+ rcti rect;
+ BLI_rcti_init(&rect,
+ 0,
+ 15 * UI_DPI_FAC,
+ 15 * UI_DPI_FAC,
+ UI_DPI_FAC * ar->sizey - UI_SCRUBBING_MARGIN_Y);
+ UI_view2d_draw_scale_y__values(ar, v2d, &rect, TH_TEXT);
}
- UI_view2d_view_orthoSpecial(ar, v2d, 1);
- ANIM_draw_cfra_number(C, v2d, cfra_flag);
}
static void dopesheet_region_draw(const bContext *C, ARegion *ar)
@@ -1093,18 +1100,13 @@ static void dopesheet_region_draw(const bContext *C, ARegion *ar)
/* reset view matrix */
UI_view2d_view_restore(C);
+ /* time-scrubbing */
+ ED_scrubbing_draw(ar, scene, sc->flag & SC_SHOW_SECONDS, true);
+
/* scrollers */
scrollers = UI_view2d_scrollers_calc(v2d, NULL);
UI_view2d_scrollers_draw(v2d, scrollers);
UI_view2d_scrollers_free(scrollers);
-
- /* frame numbers */
- UI_view2d_draw_scale_x__discrete_frames_or_seconds(
- ar, v2d, &v2d->hor, scene, sc->flag & SC_SHOW_SECONDS, TH_TEXT);
-
- /* current frame number indicator */
- UI_view2d_view_orthoSpecial(ar, v2d, 1);
- ANIM_draw_cfra_number(C, v2d, cfra_flag);
}
static void clip_preview_region_draw(const bContext *C, ARegion *ar)
diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c
index 441e65cefe4..b51baafbcf5 100644
--- a/source/blender/editors/space_clip/tracking_ops.c
+++ b/source/blender/editors/space_clip/tracking_ops.c
@@ -1299,6 +1299,12 @@ void CLIP_OT_hide_tracks_clear(wmOperatorType *ot)
/********************** frame jump operator *********************/
+static bool frame_jump_poll(bContext *C)
+{
+ SpaceClip *space_clip = CTX_wm_space_clip(C);
+ return space_clip != NULL;
+}
+
static int frame_jump_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -1350,7 +1356,7 @@ static int frame_jump_exec(bContext *C, wmOperator *op)
if (CFRA != sc->user.framenr) {
CFRA = sc->user.framenr;
- BKE_sound_update_and_seek(CTX_data_main(C), CTX_data_depsgraph(C));
+ BKE_sound_seek_scene(CTX_data_main(C), scene);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
@@ -1377,7 +1383,7 @@ void CLIP_OT_frame_jump(wmOperatorType *ot)
/* api callbacks */
ot->exec = frame_jump_exec;
- ot->poll = ED_space_clip_poll;
+ ot->poll = frame_jump_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index bb8680682d2..6b3baa1e766 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -478,7 +478,7 @@ static void file_draw_preview(uiBlock *block,
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
if (icon) {
- UI_icon_draw_aspect((float)xco, (float)yco, icon, icon_aspect, 1.0f, NULL);
+ UI_icon_draw_ex((float)xco, (float)yco, icon, icon_aspect, 1.0f, 0.0f, NULL, false);
}
/* border */
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index 674735f3e1d..5ac7ff72aed 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -1011,7 +1011,7 @@ static int bookmark_cleanup_exec(bContext *C, wmOperator *UNUSED(op))
BLI_make_file_string(
"/", name, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
fsmenu_write_file(fsmenu, name);
- fsmenu_refresh_bookmarks_status(fsmenu);
+ fsmenu_refresh_bookmarks_status(CTX_wm_manager(C), fsmenu);
ED_area_tag_refresh(sa);
ED_area_tag_redraw(sa);
}
@@ -1567,6 +1567,9 @@ static int file_refresh_exec(bContext *C, wmOperator *UNUSED(unused))
/* refresh system directory menu */
fsmenu_refresh_system_category(fsmenu);
+ /* Update bookmarks 'valid' state. */
+ fsmenu_refresh_bookmarks_status(wm, fsmenu);
+
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c
index 38423a87447..b50c37baae6 100644
--- a/source/blender/editors/space_file/fsmenu.c
+++ b/source/blender/editors/space_file/fsmenu.c
@@ -44,6 +44,9 @@
# include "BLI_winstuff.h"
#endif
+#include "WM_api.h"
+#include "WM_types.h"
+
#ifdef __APPLE__
# include <Carbon/Carbon.h>
#endif /* __APPLE__ */
@@ -721,31 +724,59 @@ void fsmenu_refresh_system_category(struct FSMenu *fsmenu)
fsmenu_read_system(fsmenu, true);
}
-void fsmenu_refresh_bookmarks_status(struct FSMenu *fsmenu)
+static void fsmenu_free_ex(FSMenu **fsmenu)
{
- int categories[] = {
- FS_CATEGORY_SYSTEM, FS_CATEGORY_SYSTEM_BOOKMARKS, FS_CATEGORY_BOOKMARKS, FS_CATEGORY_RECENT};
- int i;
-
- for (i = sizeof(categories) / sizeof(*categories); i--;) {
- FSMenuEntry *fsm_iter = ED_fsmenu_get_category(fsmenu, categories[i]);
- for (; fsm_iter; fsm_iter = fsm_iter->next) {
- fsmenu_entry_refresh_valid(fsm_iter);
- }
+ if (*fsmenu != NULL) {
+ fsmenu_free_category(*fsmenu, FS_CATEGORY_SYSTEM);
+ fsmenu_free_category(*fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS);
+ fsmenu_free_category(*fsmenu, FS_CATEGORY_BOOKMARKS);
+ fsmenu_free_category(*fsmenu, FS_CATEGORY_RECENT);
+ MEM_freeN(*fsmenu);
}
+
+ *fsmenu = NULL;
}
void fsmenu_free(void)
{
- if (g_fsmenu) {
- fsmenu_free_category(g_fsmenu, FS_CATEGORY_SYSTEM);
- fsmenu_free_category(g_fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS);
- fsmenu_free_category(g_fsmenu, FS_CATEGORY_BOOKMARKS);
- fsmenu_free_category(g_fsmenu, FS_CATEGORY_RECENT);
- MEM_freeN(g_fsmenu);
+ fsmenu_free_ex(&g_fsmenu);
+}
+
+static void fsmenu_copy_category(struct FSMenu *fsmenu_dst,
+ struct FSMenu *fsmenu_src,
+ const FSMenuCategory category)
+{
+ FSMenuEntry *fsm_dst_prev = NULL, *fsm_dst_head = NULL;
+ FSMenuEntry *fsm_src_iter = ED_fsmenu_get_category(fsmenu_src, category);
+
+ for (; fsm_src_iter != NULL; fsm_src_iter = fsm_src_iter->next) {
+ FSMenuEntry *fsm_dst = MEM_dupallocN(fsm_src_iter);
+ if (fsm_dst->path != NULL) {
+ fsm_dst->path = MEM_dupallocN(fsm_dst->path);
+ }
+
+ if (fsm_dst_prev != NULL) {
+ fsm_dst_prev->next = fsm_dst;
+ }
+ else {
+ fsm_dst_head = fsm_dst;
+ }
+ fsm_dst_prev = fsm_dst;
}
- g_fsmenu = NULL;
+ ED_fsmenu_set_category(fsmenu_dst, category, fsm_dst_head);
+}
+
+static FSMenu *fsmenu_copy(FSMenu *fsmenu)
+{
+ FSMenu *fsmenu_copy = MEM_dupallocN(fsmenu);
+
+ fsmenu_copy_category(fsmenu_copy, fsmenu_copy, FS_CATEGORY_SYSTEM);
+ fsmenu_copy_category(fsmenu_copy, fsmenu_copy, FS_CATEGORY_SYSTEM_BOOKMARKS);
+ fsmenu_copy_category(fsmenu_copy, fsmenu_copy, FS_CATEGORY_BOOKMARKS);
+ fsmenu_copy_category(fsmenu_copy, fsmenu_copy, FS_CATEGORY_RECENT);
+
+ return fsmenu_copy;
}
int fsmenu_get_active_indices(struct FSMenu *fsmenu, enum FSMenuCategory category, const char *dir)
@@ -761,3 +792,99 @@ int fsmenu_get_active_indices(struct FSMenu *fsmenu, enum FSMenuCategory categor
return -1;
}
+
+/* Thanks to some bookmarks sometimes being network drives that can have tens of seconds of delay
+ * before being defined as unreachable by the OS, we need to validate the bookmarks in an async
+ * job...
+ */
+static void fsmenu_bookmark_validate_job_startjob(void *fsmenuv,
+ short *stop,
+ short *do_update,
+ float *UNUSED(progress))
+{
+ FSMenu *fsmenu = fsmenuv;
+
+ int categories[] = {
+ FS_CATEGORY_SYSTEM, FS_CATEGORY_SYSTEM_BOOKMARKS, FS_CATEGORY_BOOKMARKS, FS_CATEGORY_RECENT};
+
+ for (size_t i = ARRAY_SIZE(categories); i--;) {
+ FSMenuEntry *fsm_iter = ED_fsmenu_get_category(fsmenu, categories[i]);
+ for (; fsm_iter; fsm_iter = fsm_iter->next) {
+ if (*stop) {
+ return;
+ }
+ /* Note that we do not really need atomics primitives or thread locks here, since this only
+ * sets one short, which is assumed to be 'atomic'-enough for us here. */
+ fsmenu_entry_refresh_valid(fsm_iter);
+ *do_update = true;
+ }
+ }
+}
+
+static void fsmenu_bookmark_validate_job_update(void *fsmenuv)
+{
+ FSMenu *fsmenu_job = fsmenuv;
+
+ int categories[] = {
+ FS_CATEGORY_SYSTEM, FS_CATEGORY_SYSTEM_BOOKMARKS, FS_CATEGORY_BOOKMARKS, FS_CATEGORY_RECENT};
+
+ for (size_t i = ARRAY_SIZE(categories); i--;) {
+ FSMenuEntry *fsm_iter_src = ED_fsmenu_get_category(fsmenu_job, categories[i]);
+ FSMenuEntry *fsm_iter_dst = ED_fsmenu_get_category(ED_fsmenu_get(), categories[i]);
+ for (; fsm_iter_dst != NULL; fsm_iter_dst = fsm_iter_dst->next) {
+ while (fsm_iter_src != NULL && !STREQ(fsm_iter_dst->path, fsm_iter_src->path)) {
+ fsm_iter_src = fsm_iter_src->next;
+ }
+ if (fsm_iter_src == NULL) {
+ return;
+ }
+ fsm_iter_dst->valid = fsm_iter_src->valid;
+ }
+ }
+}
+
+static void fsmenu_bookmark_validate_job_end(void *fsmenuv)
+{
+ /* In case there would be some dangling update... */
+ fsmenu_bookmark_validate_job_update(fsmenuv);
+}
+
+static void fsmenu_bookmark_validate_job_free(void *fsmenuv)
+{
+ FSMenu *fsmenu = fsmenuv;
+ fsmenu_free_ex(&fsmenu);
+}
+
+static void fsmenu_bookmark_validate_job_start(wmWindowManager *wm)
+{
+ wmJob *wm_job;
+ FSMenu *fsmenu_job = fsmenu_copy(g_fsmenu);
+
+ /* setup job */
+ wm_job = WM_jobs_get(
+ wm, wm->winactive, wm, "Validating Bookmarks...", 0, WM_JOB_TYPE_FSMENU_BOOKMARK_VALIDATE);
+ WM_jobs_customdata_set(wm_job, fsmenu_job, fsmenu_bookmark_validate_job_free);
+ WM_jobs_timer(wm_job, 0.01, NC_SPACE | ND_SPACE_FILE_LIST, NC_SPACE | ND_SPACE_FILE_LIST);
+ WM_jobs_callbacks(wm_job,
+ fsmenu_bookmark_validate_job_startjob,
+ NULL,
+ fsmenu_bookmark_validate_job_update,
+ fsmenu_bookmark_validate_job_end);
+
+ /* start the job */
+ WM_jobs_start(wm, wm_job);
+}
+
+static void fsmenu_bookmark_validate_job_stop(wmWindowManager *wm)
+{
+ WM_jobs_kill_type(wm, wm, WM_JOB_TYPE_FSMENU_BOOKMARK_VALIDATE);
+}
+
+void fsmenu_refresh_bookmarks_status(wmWindowManager *wm, FSMenu *fsmenu)
+{
+ BLI_assert(fsmenu == ED_fsmenu_get());
+ UNUSED_VARS_NDEBUG(fsmenu);
+
+ fsmenu_bookmark_validate_job_stop(wm);
+ fsmenu_bookmark_validate_job_start(wm);
+}
diff --git a/source/blender/editors/space_file/fsmenu.h b/source/blender/editors/space_file/fsmenu.h
index cb0dccf0499..d9850cb855d 100644
--- a/source/blender/editors/space_file/fsmenu.h
+++ b/source/blender/editors/space_file/fsmenu.h
@@ -68,7 +68,7 @@ void fsmenu_free(void);
void fsmenu_refresh_system_category(struct FSMenu *fsmenu);
/** Refresh 'valid' status of all menu entries */
-void fsmenu_refresh_bookmarks_status(struct FSMenu *fsmenu);
+void fsmenu_refresh_bookmarks_status(struct wmWindowManager *wm, struct FSMenu *fsmenu);
/** Get active index based on given directory. */
int fsmenu_get_active_indices(struct FSMenu *fsmenu,
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index 4629f33d210..1fd878e4662 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -83,7 +83,6 @@ static SpaceLink *file_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scen
BLI_addtail(&sfile->regionbase, ar);
ar->regiontype = RGN_TYPE_TOOL_PROPS;
ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
- ar->flag |= RGN_FLAG_DYNAMIC_SIZE;
/* ui list region */
ar = MEM_callocN(sizeof(ARegion), "ui region for file");
@@ -143,18 +142,16 @@ static void file_free(SpaceLink *sl)
}
/* spacetype; init callback, area size changes, screen set, etc */
-static void file_init(wmWindowManager *UNUSED(wm), ScrArea *sa)
+static void file_init(wmWindowManager *wm, ScrArea *sa)
{
SpaceFile *sfile = (SpaceFile *)sa->spacedata.first;
+ struct FSMenu *fsmenu = ED_fsmenu_get();
/* refresh system directory list */
- fsmenu_refresh_system_category(ED_fsmenu_get());
+ fsmenu_refresh_system_category(fsmenu);
- /* Update bookmarks 'valid' state.
- * Done here, because it seems BLI_is_dir() can have huge impact on performances
- * in some cases, on win systems... See T43684.
- */
- fsmenu_refresh_bookmarks_status(ED_fsmenu_get());
+ /* Update bookmarks 'valid' state. */
+ fsmenu_refresh_bookmarks_status(wm, fsmenu);
if (sfile->layout) {
sfile->layout->dirty = true;
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index 0954538e430..c5f8c32ec7a 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -2820,6 +2820,7 @@ void GRAPH_OT_fmodifier_add(wmOperatorType *ot)
/* id-props */
prop = RNA_def_enum(ot->srna, "type", rna_enum_fmodifier_type_items, 0, "Type", "");
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ACTION);
RNA_def_enum_funcs(prop, graph_fmodifier_itemf);
ot->prop = prop;
diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c
index 054a1e3d8ee..5c7035a4c04 100644
--- a/source/blender/editors/space_graph/graph_ops.c
+++ b/source/blender/editors/space_graph/graph_ops.c
@@ -105,7 +105,7 @@ static void graphview_cursor_apply(bContext *C, wmOperator *op)
}
SUBFRA = 0.0f;
- BKE_sound_update_and_seek(bmain, CTX_data_depsgraph(C));
+ BKE_sound_seek_scene(bmain, scene);
}
/* set the cursor value */
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c
index 13a42f091f6..5ea07c56286 100644
--- a/source/blender/editors/space_graph/graph_select.c
+++ b/source/blender/editors/space_graph/graph_select.c
@@ -1141,7 +1141,7 @@ typedef enum eGraphVertIndex {
/* Tolerance for absolute radius (in pixels) of the vert from the cursor to use */
// TODO: perhaps this should depend a bit on the size that the user set the vertices to be?
-#define GVERTSEL_TOL 10
+#define GVERTSEL_TOL (10 * U.pixelsize)
/* ....... */
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index 390ea0cf00b..4e131c653f8 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -42,6 +42,7 @@
#include "ED_screen.h"
#include "ED_anim_api.h"
#include "ED_markers.h"
+#include "ED_time_scrub_ui.h"
#include "GPU_immediate.h"
#include "GPU_state.h"
@@ -57,6 +58,7 @@
#include "UI_resources.h"
#include "UI_view2d.h"
+#include "UI_interface.h"
#include "graph_intern.h" // own include
@@ -79,7 +81,7 @@ static SpaceLink *graph_new(const ScrArea *UNUSED(sa), const Scene *scene)
/* settings for making it easier by default to just see what you're interested in tweaking */
sipo->ads->filterflag |= ADS_FILTER_ONLYSEL;
- sipo->flag |= SIPO_SELVHANDLESONLY;
+ sipo->flag |= SIPO_SELVHANDLESONLY | SIPO_MARKER_LINES;
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for graphedit");
@@ -124,8 +126,8 @@ static SpaceLink *graph_new(const ScrArea *UNUSED(sa), const Scene *scene)
ar->v2d.max[0] = MAXFRAMEF;
ar->v2d.max[1] = FLT_MAX;
- ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
- ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_SCALE_VERTICAL);
+ ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
+ ar->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HANDLES);
ar->v2d.keeptot = 0;
@@ -291,12 +293,14 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar)
}
/* markers */
- UI_view2d_view_orthoSpecial(ar, v2d, 1);
- int marker_draw_flag = DRAW_MARKERS_MARGIN;
- if (sipo->flag & SIPO_MARKER_LINES) {
- marker_draw_flag |= DRAW_MARKERS_LINES;
+ if (sipo->mode != SIPO_MODE_DRIVERS) {
+ UI_view2d_view_orthoSpecial(ar, v2d, 1);
+ int marker_draw_flag = DRAW_MARKERS_MARGIN;
+ if (sipo->flag & SIPO_MARKER_LINES) {
+ marker_draw_flag |= DRAW_MARKERS_LINES;
+ }
+ ED_markers_draw(C, marker_draw_flag);
}
- ED_markers_draw(C, marker_draw_flag);
/* preview range */
UI_view2d_view_ortho(v2d);
@@ -309,6 +313,9 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar)
/* reset view matrix */
UI_view2d_view_restore(C);
+ /* time-scrubbing */
+ ED_scrubbing_draw(ar, scene, display_seconds, false);
+
/* scrollers */
// FIXME: args for scrollers depend on the type of data being shown...
scrollers = UI_view2d_scrollers_calc(v2d, NULL);
@@ -316,13 +323,14 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar)
UI_view2d_scrollers_free(scrollers);
/* scale numbers */
- UI_view2d_draw_scale_x__frames_or_seconds(ar, v2d, &v2d->hor, scene, display_seconds, TH_TEXT);
- UI_view2d_draw_scale_y__values(ar, v2d, &v2d->vert, TH_TEXT);
-
- /* draw current frame number-indicator on top of scrollers */
- if ((sipo->mode != SIPO_MODE_DRIVERS) && ((sipo->flag & SIPO_NODRAWCFRANUM) == 0)) {
- UI_view2d_view_orthoSpecial(ar, v2d, 1);
- ANIM_draw_cfra_number(C, v2d, cfra_flag);
+ {
+ rcti rect;
+ BLI_rcti_init(&rect,
+ 0,
+ 15 * UI_DPI_FAC,
+ 15 * UI_DPI_FAC,
+ UI_DPI_FAC * ar->sizey - UI_SCRUBBING_MARGIN_Y);
+ UI_view2d_draw_scale_y__values(ar, v2d, &rect, TH_SCROLL_TEXT);
}
}
@@ -367,6 +375,9 @@ static void graph_channel_region_draw(const bContext *C, ARegion *ar)
graph_draw_channel_names((bContext *)C, &ac, ar);
}
+ /* channel filter next to scrubbing area */
+ ED_channel_search_draw(C, ar, ac.ads);
+
/* reset view matrix */
UI_view2d_view_restore(C);
@@ -849,7 +860,7 @@ void ED_spacetype_ipo(void)
art->draw = graph_main_region_draw;
art->listener = graph_region_listener;
art->message_subscribe = graph_region_message_subscribe;
- art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
+ art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
BLI_addhead(&st->regiontypes, art);
@@ -880,7 +891,7 @@ void ED_spacetype_ipo(void)
/* regions: UI buttons */
art = MEM_callocN(sizeof(ARegionType), "spacetype graphedit region");
art->regionid = RGN_TYPE_UI;
- art->prefsizex = 200;
+ art->prefsizex = UI_SIDEBAR_PANEL_WIDTH;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
art->listener = graph_region_listener;
art->init = graph_buttons_region_init;
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 0710ecf3bd6..c317cb26cb7 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -2494,7 +2494,8 @@ static int image_invert_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID;
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+ BKE_image_mark_dirty(ima, ibuf);
if (ibuf->mipmap[0]) {
ibuf->userflags |= IB_MIPMAP_INVALID;
@@ -3542,7 +3543,7 @@ static void change_frame_apply(bContext *C, wmOperator *op)
SUBFRA = 0.0f;
/* do updates */
- BKE_sound_update_and_seek(CTX_data_main(C), CTX_data_depsgraph(C));
+ BKE_sound_seek_scene(CTX_data_main(C), scene);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 3b2386d94e6..cbe655fc9ae 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -567,7 +567,8 @@ static void image_main_region_draw(const bContext *C, ARegion *ar)
Object *obedit = CTX_data_edit_object(C);
Depsgraph *depsgraph = CTX_data_depsgraph(C);
Mask *mask = NULL;
- bool curve = false;
+ bool show_uvedit = false;
+ bool show_curve = false;
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
View2D *v2d = &ar->v2d;
@@ -609,13 +610,13 @@ static void image_main_region_draw(const bContext *C, ARegion *ar)
/* check for mask (delay draw) */
if (ED_space_image_show_uvedit(sima, obedit)) {
- /* pass */
+ show_uvedit = true;
}
else if (sima->mode == SI_MODE_MASK) {
mask = ED_space_image_get_mask(sima);
}
else if (ED_space_image_paint_curve(C)) {
- curve = true;
+ show_curve = true;
}
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
@@ -669,12 +670,9 @@ static void image_main_region_draw(const bContext *C, ARegion *ar)
false,
NULL,
C);
-
- UI_view2d_view_ortho(v2d);
- ED_image_draw_cursor(ar, sima->cursor);
- UI_view2d_view_restore(C);
}
- else if (curve) {
+
+ if (show_uvedit || mask || show_curve) {
UI_view2d_view_ortho(v2d);
ED_image_draw_cursor(ar, sima->cursor);
UI_view2d_view_restore(C);
@@ -764,7 +762,7 @@ static void image_buttons_region_layout(const bContext *C, ARegion *ar)
}
const bool vertical = true;
- ED_region_panels_layout_ex(C, ar, contexts_base, -1, vertical);
+ ED_region_panels_layout_ex(C, ar, &ar->type->paneltypes, contexts_base, -1, vertical, NULL);
}
static void image_buttons_region_draw(const bContext *C, ARegion *ar)
@@ -1035,7 +1033,7 @@ void ED_spacetype_image(void)
/* regions: listview/buttons/scopes */
art = MEM_callocN(sizeof(ARegionType), "spacetype image region");
art->regionid = RGN_TYPE_UI;
- art->prefsizex = 220; // XXX
+ art->prefsizex = UI_SIDEBAR_PANEL_WIDTH;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
art->listener = image_buttons_region_listener;
art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_ui;
diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c
index 171d8505222..bf43e493cc5 100644
--- a/source/blender/editors/space_info/info_ops.c
+++ b/source/blender/editors/space_info/info_ops.c
@@ -160,19 +160,11 @@ static int pack_all_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(ev
{
Main *bmain = CTX_data_main(C);
Image *ima;
- ImBuf *ibuf;
// first check for dirty images
for (ima = bmain->images.first; ima; ima = ima->id.next) {
- if (BKE_image_has_loaded_ibuf(ima)) { /* XXX FIX */
- ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
-
- if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) {
- BKE_image_release_ibuf(ima, ibuf, NULL);
- break;
- }
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ if (BKE_image_is_dirty(ima)) {
+ break;
}
}
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index 3e4eb6af098..e5c116e85de 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -52,6 +52,8 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "UI_interface.h"
+
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
@@ -389,7 +391,7 @@ static int nlachannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmEv
UI_view2d_listview_view_to_cell(NLACHANNEL_NAMEWIDTH,
NLACHANNEL_STEP(snla),
0,
- NLACHANNEL_FIRST_TOP(snla),
+ NLACHANNEL_FIRST_TOP(&ac),
x,
y,
NULL,
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
index b821a246dc5..68cbfd76331 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -689,11 +689,11 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
* - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
* start of list offset, and the second is as a correction for the scrollers.
*/
- int height = NLACHANNEL_TOT_HEIGHT(snla, items);
+ int height = NLACHANNEL_TOT_HEIGHT(ac, items);
v2d->tot.ymin = -height;
/* loop through channels, and set up drawing depending on their type */
- float ymax = NLACHANNEL_FIRST_TOP(snla);
+ float ymax = NLACHANNEL_FIRST_TOP(ac);
for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next, ymax -= NLACHANNEL_STEP(snla)) {
float ymin = ymax - NLACHANNEL_HEIGHT(snla);
@@ -822,7 +822,7 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar)
* - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
* start of list offset, and the second is as a correction for the scrollers.
*/
- int height = NLACHANNEL_TOT_HEIGHT(snla, items);
+ int height = NLACHANNEL_TOT_HEIGHT(ac, items);
v2d->tot.ymin = -height;
/* need to do a view-sync here, so that the keys area doesn't jump around
@@ -832,7 +832,7 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar)
/* draw channels */
{ /* first pass: just the standard GL-drawing for backdrop + text */
size_t channel_index = 0;
- float ymax = NLACHANNEL_FIRST_TOP(snla);
+ float ymax = NLACHANNEL_FIRST_TOP(ac);
for (ale = anim_data.first; ale;
ale = ale->next, ymax -= NLACHANNEL_STEP(snla), channel_index++) {
@@ -849,7 +849,7 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar)
{ /* second pass: UI widgets */
uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
size_t channel_index = 0;
- float ymax = NLACHANNEL_FIRST_TOP(snla);
+ float ymax = NLACHANNEL_FIRST_TOP(ac);
/* set blending again, as may not be set in previous step */
GPU_blend_set_func_separate(
diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c
index 07853e5850a..acb3d913114 100644
--- a/source/blender/editors/space_nla/nla_edit.c
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -429,7 +429,7 @@ static bool nla_channels_get_selected_extents(bAnimContext *ac, float *min, floa
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* loop through all channels, finding the first one that's selected */
- float ymax = NLACHANNEL_FIRST_TOP(snla);
+ float ymax = NLACHANNEL_FIRST_TOP(ac);
for (ale = anim_data.first; ale; ale = ale->next, ymax -= NLACHANNEL_STEP(snla)) {
const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
@@ -2446,6 +2446,7 @@ void NLA_OT_fmodifier_add(wmOperatorType *ot)
/* id-props */
ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_fmodifier_type_items, 0, "Type", "");
+ RNA_def_property_translation_context(ot->prop, BLT_I18NCONTEXT_ID_ACTION);
RNA_def_enum_funcs(ot->prop, nla_fmodifier_itemf);
RNA_def_boolean(ot->srna,
diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c
index accd82525f5..0de9acfec25 100644
--- a/source/blender/editors/space_nla/nla_select.c
+++ b/source/blender/editors/space_nla/nla_select.c
@@ -47,6 +47,7 @@
#include "WM_types.h"
#include "UI_view2d.h"
+#include "UI_interface.h"
#include "nla_intern.h" // own include
@@ -542,7 +543,7 @@ static void mouse_nla_strips(
* (i.e a row in the list) where keyframe was */
UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
UI_view2d_listview_view_to_cell(
- 0, NLACHANNEL_STEP(snla), 0, NLACHANNEL_FIRST_TOP(snla), x, y, NULL, &channel_index);
+ 0, NLACHANNEL_STEP(snla), 0, NLACHANNEL_FIRST_TOP(ac), x, y, NULL, &channel_index);
/* x-range to check is +/- 7 (in screen/region-space) on either side of mouse click
* (that is the size of keyframe icons, so user should be expecting similar tolerances)
diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c
index ba660945d32..4b7dfe5d653 100644
--- a/source/blender/editors/space_nla/space_nla.c
+++ b/source/blender/editors/space_nla/space_nla.c
@@ -40,6 +40,7 @@
#include "ED_anim_api.h"
#include "ED_markers.h"
#include "ED_screen.h"
+#include "ED_time_scrub_ui.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -47,6 +48,7 @@
#include "RNA_access.h"
+#include "UI_interface.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -69,6 +71,7 @@ static SpaceLink *nla_new(const ScrArea *sa, const Scene *scene)
/* set auto-snapping settings */
snla->autosnap = SACTSNAP_FRAME;
+ snla->flag = SNLA_SHOW_MARKER_LINES;
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for nla");
@@ -116,7 +119,7 @@ static SpaceLink *nla_new(const ScrArea *sa, const Scene *scene)
ar->v2d.minzoom = 0.01f;
ar->v2d.maxzoom = 50;
- ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
+ ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
ar->v2d.scroll |= (V2D_SCROLL_RIGHT);
ar->v2d.keepzoom = V2D_LOCKZOOM_Y;
ar->v2d.keepofs = V2D_KEEPOFS_Y;
@@ -201,6 +204,9 @@ static void nla_channel_region_draw(const bContext *C, ARegion *ar)
draw_nla_channel_list(C, &ac, ar);
}
+ /* channel filter next to scrubbing area */
+ ED_channel_search_draw(C, ar, ac.ads);
+
/* reset view matrix */
UI_view2d_view_restore(C);
@@ -284,20 +290,12 @@ static void nla_main_region_draw(const bContext *C, ARegion *ar)
/* reset view matrix */
UI_view2d_view_restore(C);
+ ED_scrubbing_draw(ar, scene, snla->flag & SNLA_DRAWTIME, true);
+
/* scrollers */
scrollers = UI_view2d_scrollers_calc(v2d, NULL);
UI_view2d_scrollers_draw(v2d, scrollers);
UI_view2d_scrollers_free(scrollers);
-
- /* frame numbers */
- UI_view2d_draw_scale_x__discrete_frames_or_seconds(
- ar, v2d, &v2d->hor, scene, snla->flag & SNLA_DRAWTIME, TH_TEXT);
-
- /* draw current frame number-indicator on top of scrollers */
- if ((snla->flag & SNLA_NODRAWCFRANUM) == 0) {
- UI_view2d_view_orthoSpecial(ar, v2d, 1);
- ANIM_draw_cfra_number(C, v2d, cfra_flag);
- }
}
/* add handlers, stuff you only do once or on area/region changes */
@@ -614,7 +612,7 @@ void ED_spacetype_nla(void)
art->draw = nla_main_region_draw;
art->listener = nla_main_region_listener;
art->message_subscribe = nla_main_region_message_subscribe;
- art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
+ art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
BLI_addhead(&st->regiontypes, art);
@@ -645,7 +643,7 @@ void ED_spacetype_nla(void)
/* regions: UI buttons */
art = MEM_callocN(sizeof(ARegionType), "spacetype nla region");
art->regionid = RGN_TYPE_UI;
- art->prefsizex = 200;
+ art->prefsizex = UI_SIDEBAR_PANEL_WIDTH;
art->keymapflag = ED_KEYMAP_UI;
art->listener = nla_region_listener;
art->init = nla_buttons_region_init;
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 447fea8098c..bf6ec961a5d 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -708,6 +708,11 @@ static void node_buts_image_user(uiLayout *layout,
col = uiLayoutColumn(layout, false);
uiItemR(col, ptr, "layer", 0, NULL, ICON_NONE);
}
+
+ uiLayout *split = uiLayoutSplit(layout, 0.5f, true);
+ PointerRNA colorspace_settings_ptr = RNA_pointer_get(imaptr, "colorspace_settings");
+ uiItemL(split, IFACE_("Color Space"), ICON_NONE);
+ uiItemR(split, &colorspace_settings_ptr, "name", 0, "", ICON_NONE);
}
static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -782,7 +787,6 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA
NULL,
UI_TEMPLATE_ID_FILTER_ALL,
false);
- uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE);
uiItemR(layout, ptr, "interpolation", 0, "", ICON_NONE);
uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
@@ -820,11 +824,10 @@ static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, Poin
UI_TEMPLATE_ID_FILTER_ALL,
false);
- node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr, false);
-
- uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE);
uiItemR(layout, ptr, "interpolation", 0, "", ICON_NONE);
uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
+
+ node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr, false);
}
static void node_shader_buts_tex_environment_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
@@ -875,7 +878,6 @@ static void node_shader_buts_tex_environment_ex(uiLayout *layout, bContext *C, P
uiTemplateImageInfo(layout, C, ima, iuserptr.data);
}
- uiItemR(layout, ptr, "color_space", 0, IFACE_("Color Space"), ICON_NONE);
uiItemR(layout, ptr, "interpolation", 0, IFACE_("Interpolation"), ICON_NONE);
uiItemR(layout, ptr, "projection", 0, IFACE_("Projection"), ICON_NONE);
}
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index 3e73cc52c52..fb34d9dc459 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -453,13 +453,8 @@ void ED_node_shader_default(const bContext *C, ID *id)
output_type = SH_NODE_OUTPUT_LIGHT;
shader_type = SH_NODE_EMISSION;
- copy_v3_v3(color, &la->r);
- if (la->type == LA_LOCAL || la->type == LA_SPOT || la->type == LA_AREA) {
- strength = 100.0f;
- }
- else {
- strength = 1.0f;
- }
+ copy_v3_fl3(color, 1.0f, 1.0f, 1.0f);
+ strength = 1.0f;
break;
}
default:
diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c
index b52d1d3b78f..aab328249fe 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -429,19 +429,24 @@ void node_select_single(bContext *C, bNode *node)
WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
}
-static int node_mouse_select(Main *bmain,
- SpaceNode *snode,
- ARegion *ar,
+static int node_mouse_select(bContext *C,
const int mval[2],
const bool extend,
const bool socket_select,
- const bool deselect_all)
+ const bool deselect_all,
+ const bool wait_to_deselect_others)
{
+ Main *bmain = CTX_data_main(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ ARegion *ar = CTX_wm_region(C);
bNode *node, *tnode;
bNodeSocket *sock = NULL;
bNodeSocket *tsock;
float cursor[2];
- bool selected = false;
+ int ret_value = OPERATOR_CANCELLED;
+
+ /* Waiting to deselect others is only allowed for basic selection. */
+ BLI_assert(!(extend || socket_select) || !wait_to_deselect_others);
/* get mouse coordinates in view2d space */
UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &cursor[0], &cursor[1]);
@@ -449,89 +454,104 @@ static int node_mouse_select(Main *bmain,
/* first do socket selection, these generally overlap with nodes. */
if (socket_select) {
if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN)) {
- node_socket_toggle(node, sock, 1);
- selected = true;
+ /* NOTE: SOCK_IN does not take into account the extend case...
+ * This feature is not really used anyway currently? */
+ node_socket_toggle(node, sock, true);
+ ret_value = OPERATOR_FINISHED;
}
else if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_OUT)) {
if (sock->flag & SELECT) {
if (extend) {
- node_socket_deselect(node, sock, 1);
+ node_socket_deselect(node, sock, true);
}
else {
- selected = true;
+ ret_value = OPERATOR_FINISHED;
}
}
else {
- /* only allow one selected output per node, for sensible linking.
- * allows selecting outputs from different nodes though. */
+ /* Only allow one selected output per node, for sensible linking.
+ * Allow selecting outputs from different nodes though, if extend is true. */
if (node) {
for (tsock = node->outputs.first; tsock; tsock = tsock->next) {
- node_socket_deselect(node, tsock, 1);
+ if (tsock == sock) {
+ continue;
+ }
+ node_socket_deselect(node, tsock, true);
}
}
- if (extend) {
- /* only allow one selected output per node, for sensible linking.
- * allows selecting outputs from different nodes though. */
- for (tsock = node->outputs.first; tsock; tsock = tsock->next) {
- if (tsock != sock) {
- node_socket_deselect(node, tsock, 1);
+ if (!extend) {
+ for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) {
+ if (tnode == node) {
+ continue;
+ }
+ for (tsock = tnode->outputs.first; tsock; tsock = tsock->next) {
+ node_socket_deselect(tnode, tsock, true);
}
}
}
node_socket_select(node, sock);
- selected = true;
+ ret_value = OPERATOR_FINISHED;
}
}
}
if (!sock) {
- if (extend) {
- /* find the closest visible node */
- node = node_under_mouse_select(snode->edittree, cursor[0], cursor[1]);
+ /* find the closest visible node */
+ node = node_under_mouse_select(snode->edittree, (int)cursor[0], (int)cursor[1]);
- if (node) {
- if ((node->flag & SELECT) && (node->flag & NODE_ACTIVE) == 0) {
- /* if node is selected but not active make it active */
- ED_node_set_active(bmain, snode->edittree, node);
- }
- else {
+ if (extend) {
+ if (node != NULL) {
+ /* If node is selected but not active, we want to make it active,
+ * but not toggle (deselect) it. */
+ if (!((node->flag & SELECT) && (node->flag & NODE_ACTIVE) == 0)) {
node_toggle(node);
- ED_node_set_active(bmain, snode->edittree, node);
}
- selected = true;
+ ret_value = OPERATOR_FINISHED;
}
}
- else {
- /* find the closest visible node */
- node = node_under_mouse_select(snode->edittree, cursor[0], cursor[1]);
+ else if (deselect_all && node == NULL) {
+ /* Deselect in empty space. */
+ for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) {
+ nodeSetSelected(tnode, false);
+ }
+ ret_value = OPERATOR_FINISHED;
+ }
+ else if (node != NULL) {
+ /* When clicking on an already selected node, we want to wait to deselect
+ * others and allow the user to start moving the node without that. */
+ if (wait_to_deselect_others && (node->flag & SELECT)) {
+ ret_value = OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ nodeSetSelected(node, true);
- if (node != NULL || deselect_all) {
for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) {
- nodeSetSelected(tnode, false);
- }
- selected = true;
- if (node != NULL) {
- nodeSetSelected(node, true);
- ED_node_set_active(bmain, snode->edittree, node);
+ if (tnode != node) {
+ nodeSetSelected(tnode, false);
+ }
}
+
+ ret_value = OPERATOR_FINISHED;
}
}
}
/* update node order */
- if (selected) {
+ if (ret_value != OPERATOR_CANCELLED) {
+ if (node != NULL && ret_value != OPERATOR_RUNNING_MODAL) {
+ ED_node_set_active(bmain, snode->edittree, node);
+ }
ED_node_set_active_viewer_key(snode);
ED_node_sort(snode->edittree);
+
+ WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
}
- return selected;
+ return ret_value;
}
static int node_select_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- ARegion *ar = CTX_wm_region(C);
int mval[2];
/* get settings from RNA properties for operator */
@@ -544,17 +564,70 @@ static int node_select_exec(bContext *C, wmOperator *op)
const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
/* perform the select */
- if (node_mouse_select(bmain, snode, ar, mval, extend, socket_select, deselect_all)) {
- /* send notifiers */
- WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
+ const int ret_value = node_mouse_select(C, mval, extend, socket_select, deselect_all, false);
- /* allow tweak event to work too */
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ /* allow tweak event to work too */
+ return ret_value | OPERATOR_PASS_THROUGH;
+}
+
+static int node_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ const short init_event_type = (short)POINTER_AS_INT(op->customdata);
+
+ /* get settings from RNA properties for operator */
+ int mval[2];
+ mval[0] = RNA_int_get(op->ptr, "mouse_x");
+ mval[1] = RNA_int_get(op->ptr, "mouse_y");
+
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ /* always do socket_select when extending selection. */
+ const bool socket_select = extend || RNA_boolean_get(op->ptr, "socket_select");
+ const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
+
+ /* These cases are never modal. */
+ if (extend || socket_select) {
+ return node_select_exec(C, op);
}
- else {
- /* allow tweak event to work too */
- return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
+
+ if (init_event_type == 0) {
+ if (event->val == KM_PRESS) {
+ const int ret_value = node_mouse_select(C, mval, extend, socket_select, deselect_all, true);
+
+ op->customdata = POINTER_FROM_INT((int)event->type);
+ if (ret_value & OPERATOR_RUNNING_MODAL) {
+ WM_event_add_modal_handler(C, op);
+ }
+ return ret_value | OPERATOR_PASS_THROUGH;
+ }
+ else {
+ /* If we are in init phase, and cannot validate init of modal operations,
+ * just fall back to basic exec.
+ */
+ return node_select_exec(C, op);
+ }
}
+ else if (event->type == init_event_type && event->val == KM_RELEASE) {
+ const int ret_value = node_mouse_select(C, mval, extend, socket_select, deselect_all, false);
+ return ret_value | OPERATOR_PASS_THROUGH;
+ }
+ else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
+ const int dx = mval[0] - event->mval[0];
+ const int dy = mval[1] - event->mval[1];
+ const float tweak_threshold = U.tweak_threshold * U.dpi_fac;
+ /* If user moves mouse more than defined threshold, we consider select operator as
+ * finished. Otherwise, it is still running until we get an 'release' event. In any
+ * case, we pass through event, but select op is not finished yet. */
+ if (abs(dx) + abs(dy) > tweak_threshold) {
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ }
+ else {
+ /* Important not to return anything other than PASS_THROUGH here,
+ * otherwise it prevents underlying tweak detection code to work properly. */
+ return OPERATOR_PASS_THROUGH;
+ }
+ }
+
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
}
static int node_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
@@ -562,7 +635,9 @@ static int node_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
RNA_int_set(op->ptr, "mouse_x", event->mval[0]);
RNA_int_set(op->ptr, "mouse_y", event->mval[1]);
- return node_select_exec(C, op);
+ op->customdata = POINTER_FROM_INT(0);
+
+ return node_select_modal(C, op, event);
}
void NODE_OT_select(wmOperatorType *ot)
@@ -575,6 +650,7 @@ void NODE_OT_select(wmOperatorType *ot)
/* api callbacks */
ot->invoke = node_select_invoke;
ot->exec = node_select_exec;
+ ot->modal = node_select_modal;
ot->poll = ED_operator_node_active;
/* flags */
@@ -1186,7 +1262,7 @@ static uiBlock *node_find_menu(bContext *C, ARegion *ar, void *arg_op)
static int node_find_node_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- UI_popup_block_invoke(C, node_find_menu, op);
+ UI_popup_block_invoke(C, node_find_menu, op, NULL);
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index 2152bb9847a..2351d437294 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -998,7 +998,7 @@ void ED_spacetype_node(void)
/* regions: listview/buttons */
art = MEM_callocN(sizeof(ARegionType), "spacetype node region");
art->regionid = RGN_TYPE_UI;
- art->prefsizex = 180; // XXX
+ art->prefsizex = UI_SIDEBAR_PANEL_WIDTH;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
art->listener = node_region_listener;
art->init = node_buttons_region_init;
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index 6da42ecb3c0..21e54a29fb9 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -855,7 +855,7 @@ static int collection_view_layer_exec(bContext *C, wmOperator *op)
void OUTLINER_OT_collection_exclude_set(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Set Exclude";
+ ot->name = "Disable from View Layer";
ot->idname = "OUTLINER_OT_collection_exclude_set";
ot->description = "Exclude collection from the active view layer";
@@ -870,7 +870,7 @@ void OUTLINER_OT_collection_exclude_set(wmOperatorType *ot)
void OUTLINER_OT_collection_exclude_clear(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Clear Exclude";
+ ot->name = "Enable in View Layer";
ot->idname = "OUTLINER_OT_collection_exclude_clear";
ot->description = "Include collection in the active view layer";
@@ -965,8 +965,8 @@ static int collection_isolate_exec(bContext *C, wmOperator *op)
LayerCollection *lc_master = view_layer->layer_collections.first;
for (LayerCollection *lc_iter = lc_master->layer_collections.first; lc_iter;
lc_iter = lc_iter->next) {
- lc_iter->flag |= LAYER_COLLECTION_RESTRICT_VIEW;
- layer_collection_flag_recursive_set(lc_iter, LAYER_COLLECTION_RESTRICT_VIEW);
+ lc_iter->flag |= LAYER_COLLECTION_HIDE;
+ layer_collection_flag_recursive_set(lc_iter, LAYER_COLLECTION_HIDE);
}
}
@@ -1023,12 +1023,12 @@ void OUTLINER_OT_collection_isolate(wmOperatorType *ot)
static bool collection_show_poll(bContext *C)
{
- return collections_view_layer_poll(C, true, LAYER_COLLECTION_RESTRICT_VIEW);
+ return collections_view_layer_poll(C, true, LAYER_COLLECTION_HIDE);
}
static bool collection_hide_poll(bContext *C)
{
- return collections_view_layer_poll(C, false, LAYER_COLLECTION_RESTRICT_VIEW);
+ return collections_view_layer_poll(C, false, LAYER_COLLECTION_HIDE);
}
static bool collection_inside_poll(bContext *C)
@@ -1163,12 +1163,12 @@ static bool collection_flag_poll(bContext *C, bool clear, int flag)
static bool collection_enable_poll(bContext *C)
{
- return collection_flag_poll(C, true, COLLECTION_RESTRICT_VIEW);
+ return collection_flag_poll(C, true, COLLECTION_RESTRICT_VIEWPORT);
}
static bool collection_disable_poll(bContext *C)
{
- return collection_flag_poll(C, false, COLLECTION_RESTRICT_VIEW);
+ return collection_flag_poll(C, false, COLLECTION_RESTRICT_VIEWPORT);
}
static bool collection_enable_render_poll(bContext *C)
@@ -1188,7 +1188,7 @@ static int collection_flag_exec(bContext *C, wmOperator *op)
SpaceOutliner *soops = CTX_wm_space_outliner(C);
const bool is_render = strstr(op->idname, "render");
const bool clear = strstr(op->idname, "show") || strstr(op->idname, "enable");
- int flag = is_render ? COLLECTION_RESTRICT_RENDER : COLLECTION_RESTRICT_VIEW;
+ int flag = is_render ? COLLECTION_RESTRICT_RENDER : COLLECTION_RESTRICT_VIEWPORT;
struct CollectionEditData data = {
.scene = scene,
.soops = soops,
@@ -1215,7 +1215,7 @@ static int collection_flag_exec(bContext *C, wmOperator *op)
/* Make sure (at least for this view layer) the collection is visible. */
if (clear && !is_render) {
- layer_collection->flag &= ~LAYER_COLLECTION_RESTRICT_VIEW;
+ layer_collection->flag &= ~LAYER_COLLECTION_HIDE;
}
}
BLI_gset_free(data.collections_to_edit, NULL);
@@ -1408,8 +1408,8 @@ static int outliner_unhide_all_exec(bContext *C, wmOperator *UNUSED(op))
LayerCollection *lc_master = view_layer->layer_collections.first;
for (LayerCollection *lc_iter = lc_master->layer_collections.first; lc_iter;
lc_iter = lc_iter->next) {
- lc_iter->flag &= ~LAYER_COLLECTION_RESTRICT_VIEW;
- layer_collection_flag_recursive_set(lc_iter, LAYER_COLLECTION_RESTRICT_VIEW);
+ lc_iter->flag &= ~LAYER_COLLECTION_HIDE;
+ layer_collection_flag_recursive_set(lc_iter, LAYER_COLLECTION_HIDE);
}
/* Unhide all objects. */
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 9d6008ce3a8..6547b46a6e6 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -270,127 +270,413 @@ static void restrictbutton_id_user_toggle(bContext *UNUSED(C), void *poin, void
}
}
-static int base_pushed_state_cb(bContext *UNUSED(C), void *poin)
+static void outliner_object_set_flag_recursive_cb(bContext *C,
+ Base *base,
+ Object *ob,
+ const char *propname)
+{
+ Main *bmain = CTX_data_main(C);
+ wmWindow *win = CTX_wm_window(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ PointerRNA ptr;
+
+ bool extend = (win->eventstate->shift != 0);
+
+ if (!extend) {
+ return;
+ }
+
+ /* Create PointerRNA and PropertyRNA for either Object or Base. */
+ ID *id = ob ? &ob->id : &scene->id;
+ StructRNA *struct_rna = ob ? &RNA_Object : &RNA_ObjectBase;
+ void *data = ob ? (void *)ob : (void *)base;
+
+ RNA_pointer_create(id, struct_rna, data, &ptr);
+ PropertyRNA *base_or_object_prop = RNA_struct_type_find_property(struct_rna, propname);
+ const bool value = RNA_property_boolean_get(&ptr, base_or_object_prop);
+
+ Object *ob_parent = ob ? ob : base->object;
+
+ for (Object *ob_iter = bmain->objects.first; ob_iter; ob_iter = ob_iter->id.next) {
+ if (BKE_object_is_child_recursive(ob_parent, ob_iter)) {
+ if (ob) {
+ RNA_id_pointer_create(&ob_iter->id, &ptr);
+ DEG_id_tag_update(&ob_iter->id, ID_RECALC_COPY_ON_WRITE);
+ }
+ else {
+ Base *base_iter = BKE_view_layer_base_find(view_layer, ob_iter);
+ RNA_pointer_create(&scene->id, &RNA_ObjectBase, base_iter, &ptr);
+ }
+ RNA_property_boolean_set(&ptr, base_or_object_prop, value);
+ }
+ }
+
+ /* We don't call RNA_property_update() due to performance, so we batch update them. */
+ if (ob) {
+ BKE_main_collection_sync_remap(bmain);
+ DEG_relations_tag_update(bmain);
+ }
+ else {
+ BKE_layer_collection_sync(scene, view_layer);
+ DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+ }
+}
+
+/**
+ * Object properties.
+ * */
+static void outliner__object_set_flag_recursive_cb(bContext *C, void *poin, void *poin2)
+{
+ Object *ob = poin;
+ char *propname = poin2;
+ outliner_object_set_flag_recursive_cb(C, NULL, ob, propname);
+}
+
+/**
+ * Base properties.
+ * */
+static void outliner__base_set_flag_recursive_cb(bContext *C, void *poin, void *poin2)
{
Base *base = poin;
- Object *ob = base->object;
+ char *propname = poin2;
+ outliner_object_set_flag_recursive_cb(C, base, NULL, propname);
+}
- const bool is_visible = ((base->flag & BASE_HIDDEN) == 0) &&
- ((ob->restrictflag & OB_RESTRICT_VIEW) == 0);
- return !is_visible;
+/** Create either a RNA_LayerCollection or a RNA_Collection pointer. */
+static void outliner_layer_or_collection_pointer_create(Scene *scene,
+ LayerCollection *layer_collection,
+ Collection *collection,
+ PointerRNA *ptr)
+{
+ if (collection) {
+ RNA_id_pointer_create(&collection->id, ptr);
+ }
+ else {
+ RNA_pointer_create(&scene->id, &RNA_LayerCollection, layer_collection, ptr);
+ }
}
-static void hidebutton_base_flag_cb(bContext *C, void *poin, void *poin2)
+/** Create either a RNA_ObjectBase or a RNA_Object pointer. */
+static void outliner_base_or_object_pointer_create(ViewLayer *view_layer,
+ Collection *collection,
+ Object *ob,
+ PointerRNA *ptr)
{
- wmWindow *win = CTX_wm_window(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = poin;
- Base *base = poin2;
- Object *ob = base->object;
- bool do_disable = (CTX_wm_window(C)->eventstate->alt != 0);
- bool do_isolate = (win->eventstate->ctrl != 0) && !do_disable;
- bool extend = (win->eventstate->shift != 0);
- bool depsgraph_changed = false;
- const bool is_linked = ID_IS_LINKED(ob);
+ if (collection) {
+ RNA_id_pointer_create(&ob->id, ptr);
+ }
+ else {
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+ RNA_pointer_create(&base->object->id, &RNA_ObjectBase, base, ptr);
+ }
+}
- if (do_disable) {
- if (!is_linked) {
- ob->restrictflag |= OB_RESTRICT_VIEW;
- depsgraph_changed = true;
- }
+/* Note: Collection is only valid when we want to change the collection data, otherwise we get it
+ * from layer collection. Layer collection is valid whenever we are looking at a view layer. */
+static void outliner_collection_set_flag_recursive(Scene *scene,
+ ViewLayer *view_layer,
+ LayerCollection *layer_collection,
+ Collection *collection,
+ PropertyRNA *layer_or_collection_prop,
+ PropertyRNA *base_or_object_prop,
+ const bool value)
+{
+ if (layer_collection && layer_collection->flag & LAYER_COLLECTION_EXCLUDE) {
+ return;
}
- else if (do_isolate) {
- depsgraph_changed = (!is_linked) && ((ob->restrictflag & OB_RESTRICT_VIEW) != 0);
+ PointerRNA ptr;
+ outliner_layer_or_collection_pointer_create(scene, layer_collection, collection, &ptr);
+ RNA_property_boolean_set(&ptr, layer_or_collection_prop, value);
- if (!extend) {
- /* Make only one base visible. */
- for (Base *other = view_layer->object_bases.first; other; other = other->next) {
- other->flag |= BASE_HIDDEN;
- }
+ /* Set the same flag for the nested objects as well. */
+ if (base_or_object_prop) {
+ /* Note: We can't use BKE_collection_object_cache_get()
+ * otherwise we would not take collection exclusion into account. */
+ for (CollectionObject *cob = layer_collection->collection->gobject.first; cob;
+ cob = cob->next) {
- base->flag &= ~BASE_HIDDEN;
- }
- else {
- /* Toggle visibility of one base. */
- base->flag ^= BASE_HIDDEN;
- }
+ outliner_base_or_object_pointer_create(view_layer, collection, cob->ob, &ptr);
+ RNA_property_boolean_set(&ptr, base_or_object_prop, value);
- if (!is_linked) {
- ob->restrictflag &= ~OB_RESTRICT_VIEW;
+ if (collection) {
+ DEG_id_tag_update(&cob->ob->id, ID_RECALC_COPY_ON_WRITE);
+ }
}
}
- else if (ob->restrictflag & OB_RESTRICT_VIEW) {
- if (!is_linked) {
- ob->restrictflag &= ~OB_RESTRICT_VIEW;
- base->flag &= ~BASE_HIDDEN;
+
+ /* Keep going recursively. */
+ ListBase *lb = (layer_collection ? &layer_collection->layer_collections : &collection->children);
+ for (Link *link = lb->first; link; link = link->next) {
+ LayerCollection *layer_collection_iter = layer_collection ? (LayerCollection *)link : NULL;
+ Collection *collection_iter = layer_collection ?
+ (collection ? layer_collection_iter->collection : NULL) :
+ ((CollectionChild *)link)->collection;
+ outliner_collection_set_flag_recursive(scene,
+ view_layer,
+ layer_collection_iter,
+ collection_iter,
+ layer_or_collection_prop,
+ base_or_object_prop,
+ value);
+ }
+
+ if (collection) {
+ DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
+ }
+}
+
+/** Check if collection is already isolated.
+ *
+ * A collection is isolated if all its parents and children are "visible".
+ * All the other collections must be "invisible".
+ *
+ * Note: We could/should boost performance by iterating over the tree twice.
+ * First tagging all the children/parent collections, then getting their values and comparing.
+ * To run BKE_collection_has_collection() so many times is silly and slow.
+ */
+static bool outliner_collection_is_isolated(Scene *scene,
+ const LayerCollection *layer_collection_cmp,
+ const Collection *collection_cmp,
+ const bool value_cmp,
+ const PropertyRNA *layer_or_collection_prop,
+ LayerCollection *layer_collection,
+ Collection *collection)
+{
+ PointerRNA ptr;
+ outliner_layer_or_collection_pointer_create(scene, layer_collection, collection, &ptr);
+ const bool value = RNA_property_boolean_get(&ptr, (PropertyRNA *)layer_or_collection_prop);
+ Collection *collection_ensure = collection ? collection : layer_collection->collection;
+ const Collection *collection_ensure_cmp = collection_cmp ? collection_cmp :
+ layer_collection_cmp->collection;
+
+ if (collection_ensure->flag & COLLECTION_IS_MASTER) {
+ }
+ else if (collection_ensure == collection_ensure_cmp) {
+ }
+ else if (BKE_collection_has_collection(collection_ensure, (Collection *)collection_ensure_cmp) ||
+ BKE_collection_has_collection((Collection *)collection_ensure_cmp, collection_ensure)) {
+ /* This collection is either a parent or a child of the collection.
+ * We expect it to be set "visble" already. */
+ if (value != value_cmp) {
+ return false;
}
- depsgraph_changed = true;
}
else {
- base->flag ^= BASE_HIDDEN;
+ /* This collection is neither a parent nor a child of the collection.
+ * We expect it to be "invisble". */
+ if (value == value_cmp) {
+ return false;
+ }
}
- if (depsgraph_changed) {
- BKE_main_collection_sync_remap(bmain);
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
- DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_OBJECT | ND_DRAW, &ob->id);
+ /* Keep going recursively. */
+ ListBase *lb = (layer_collection ? &layer_collection->layer_collections : &collection->children);
+ for (Link *link = lb->first; link; link = link->next) {
+ LayerCollection *layer_collection_iter = layer_collection ? (LayerCollection *)link : NULL;
+ Collection *collection_iter = layer_collection ?
+ (collection ? layer_collection_iter->collection : NULL) :
+ ((CollectionChild *)link)->collection;
+ if (layer_collection_iter && layer_collection_iter->flag & LAYER_COLLECTION_EXCLUDE) {
+ continue;
+ }
+ if (!outliner_collection_is_isolated(scene,
+ layer_collection_cmp,
+ collection_cmp,
+ value_cmp,
+ layer_or_collection_prop,
+ layer_collection_iter,
+ collection_iter)) {
+ return false;
+ }
}
- if (!do_disable) {
- BKE_layer_collection_sync(scene, view_layer);
- DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- }
+ return true;
}
-static int layer_collection_pushed_state_cb(bContext *UNUSED(C), void *poin)
+static void outliner_collection_isolate_flag(Scene *scene,
+ ViewLayer *view_layer,
+ LayerCollection *layer_collection,
+ Collection *collection,
+ PropertyRNA *layer_or_collection_prop,
+ const char *propname,
+ const bool value)
{
- LayerCollection *lc = poin;
- Collection *collection = lc->collection;
+ PointerRNA ptr;
+ const bool is_hide = strstr(propname, "hide_") != NULL;
+
+ LayerCollection *top_layer_collection = layer_collection ? view_layer->layer_collections.first :
+ NULL;
+ Collection *top_collection = collection ? scene->master_collection : NULL;
+
+ bool was_isolated = (value == is_hide);
+ was_isolated &= outliner_collection_is_isolated(scene,
+ layer_collection,
+ collection,
+ !is_hide,
+ layer_or_collection_prop,
+ top_layer_collection,
+ top_collection);
+
+ if (was_isolated) {
+ const bool default_value = RNA_property_boolean_get_default(NULL, layer_or_collection_prop);
+ /* Make every collection go back to its default "visibility" state. */
+ outliner_collection_set_flag_recursive(scene,
+ view_layer,
+ top_layer_collection,
+ top_collection,
+ layer_or_collection_prop,
+ NULL,
+ default_value);
+ return;
+ }
- const bool is_visible = ((lc->flag & LAYER_COLLECTION_RESTRICT_VIEW) == 0) &&
- ((collection->flag & COLLECTION_RESTRICT_VIEW) == 0);
- return !is_visible;
+ /* Make every collection "invisible". */
+ outliner_collection_set_flag_recursive(scene,
+ view_layer,
+ top_layer_collection,
+ top_collection,
+ layer_or_collection_prop,
+ NULL,
+ is_hide);
+
+ /* Make this collection and its children collections the only "visible". */
+ outliner_collection_set_flag_recursive(
+ scene, view_layer, layer_collection, collection, layer_or_collection_prop, NULL, !is_hide);
+
+ /* Make this collection direct parents also "visible". */
+ if (layer_collection) {
+ LayerCollection *lc_parent = layer_collection;
+ for (LayerCollection *lc_iter = top_layer_collection->layer_collections.first; lc_iter;
+ lc_iter = lc_iter->next) {
+ if (BKE_layer_collection_has_layer_collection(lc_iter, layer_collection)) {
+ lc_parent = lc_iter;
+ break;
+ }
+ }
+
+ while (lc_parent != layer_collection) {
+ outliner_layer_or_collection_pointer_create(
+ scene, lc_parent, collection ? lc_parent->collection : NULL, &ptr);
+ RNA_property_boolean_set(&ptr, layer_or_collection_prop, !is_hide);
+
+ for (LayerCollection *lc_iter = lc_parent->layer_collections.first; lc_iter;
+ lc_iter = lc_iter->next) {
+ if (BKE_layer_collection_has_layer_collection(lc_iter, layer_collection)) {
+ lc_parent = lc_iter;
+ break;
+ }
+ }
+ }
+ }
+ else {
+ CollectionParent *parent;
+ Collection *child = collection;
+ while ((parent = child->parents.first)) {
+ if (parent->collection->flag & COLLECTION_IS_MASTER) {
+ break;
+ }
+ RNA_id_pointer_create(&parent->collection->id, &ptr);
+ RNA_property_boolean_set(&ptr, layer_or_collection_prop, !is_hide);
+ child = parent->collection;
+ }
+ }
}
-static void hidebutton_layer_collection_flag_cb(bContext *C, void *poin, void *poin2)
+static void outliner_collection_set_flag_recursive_cb(bContext *C,
+ LayerCollection *layer_collection,
+ Collection *collection,
+ const char *propname)
{
Main *bmain = CTX_data_main(C);
wmWindow *win = CTX_wm_window(C);
Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = poin;
- LayerCollection *lc = poin2;
- Collection *collection = lc->collection;
- bool do_disable = (win->eventstate->alt != 0);
- bool do_isolate = (win->eventstate->ctrl != 0) && !do_disable;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ PointerRNA ptr;
+
+ bool do_isolate = (win->eventstate->ctrl != 0);
bool extend = (win->eventstate->shift != 0);
- bool depsgraph_changed = false;
- if (do_disable) {
- if (!ID_IS_LINKED(collection)) {
- collection->flag |= COLLECTION_RESTRICT_VIEW;
- depsgraph_changed = true;
- }
+ if (!ELEM(true, do_isolate, extend)) {
+ return;
+ }
+
+ /* Create PointerRNA and PropertyRNA for either Collection or LayerCollection. */
+ ID *id = collection ? &collection->id : &scene->id;
+ StructRNA *struct_rna = collection ? &RNA_Collection : &RNA_LayerCollection;
+ void *data = collection ? (void *)collection : (void *)layer_collection;
+
+ RNA_pointer_create(id, struct_rna, data, &ptr);
+ outliner_layer_or_collection_pointer_create(scene, layer_collection, collection, &ptr);
+ PropertyRNA *layer_or_collection_prop = RNA_struct_type_find_property(struct_rna, propname);
+ const bool value = RNA_property_boolean_get(&ptr, layer_or_collection_prop);
+
+ PropertyRNA *base_or_object_prop = NULL;
+ if (layer_collection != NULL) {
+ /* If we are toggling Layer collections we still want to change the properties of the base
+ * or the objects. If we have a matching property, toggle it as well, it can be NULL. */
+ struct_rna = collection ? &RNA_Object : &RNA_ObjectBase;
+ base_or_object_prop = RNA_struct_type_find_property(struct_rna, propname);
}
- else if (do_isolate) {
- depsgraph_changed |= BKE_layer_collection_isolate(scene, view_layer, lc, extend);
+
+ if (extend) {
+ outliner_collection_set_flag_recursive(scene,
+ view_layer,
+ layer_collection,
+ collection,
+ layer_or_collection_prop,
+ base_or_object_prop,
+ value);
}
else {
- bool make_visible = ((lc->flag & LAYER_COLLECTION_RESTRICT_VIEW) != 0) ||
- ((collection->flag & COLLECTION_RESTRICT_VIEW) != 0);
- depsgraph_changed |= BKE_layer_collection_set_visible(view_layer, lc, make_visible, extend);
- }
+ outliner_collection_isolate_flag(scene,
+ view_layer,
+ layer_collection,
+ collection,
+ layer_or_collection_prop,
+ propname,
+ value);
+ }
+
+ /* We don't call RNA_property_update() due to performance, so we batch update them. */
+ BKE_main_collection_sync_remap(bmain);
+ DEG_relations_tag_update(bmain);
+}
- BKE_layer_collection_sync(scene, view_layer);
- DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+/**
+ * Layer collection properties called from the ViewLayer mode.
+ * Change the (non-excluded) collection children, and the objects nested to them all.
+ */
+static void view_layer__layer_collection_set_flag_recursive_cb(bContext *C,
+ void *poin,
+ void *poin2)
+{
+ LayerCollection *layer_collection = poin;
+ char *propname = poin2;
+ outliner_collection_set_flag_recursive_cb(C, layer_collection, NULL, propname);
+}
- if (depsgraph_changed) {
- BKE_main_collection_sync_remap(bmain);
- DEG_relations_tag_update(bmain);
- }
- WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL);
+/**
+ * Collection properties called from the ViewLayer mode.
+ * Change the (non-excluded) collection children, and the objects nested to them all.
+ */
+static void view_layer__collection_set_flag_recursive_cb(bContext *C, void *poin, void *poin2)
+{
+ LayerCollection *layer_collection = poin;
+ char *propname = poin2;
+ outliner_collection_set_flag_recursive_cb(
+ C, layer_collection, layer_collection->collection, propname);
+}
+
+/**
+ * Collection properties called from the Scenes mode.
+ * Change the collection children but no objects.
+ */
+static void scenes__collection_set_flag_recursive_cb(bContext *C, void *poin, void *poin2)
+{
+ Collection *collection = poin;
+ char *propname = poin2;
+ outliner_collection_set_flag_recursive_cb(C, NULL, collection, propname);
}
static void namebutton_cb(bContext *C, void *tsep, char *oldname)
@@ -580,7 +866,10 @@ static void outliner_draw_restrictbuts(uiBlock *block,
bool initialized;
PropertyRNA *object_hide_viewport, *object_hide_select, *object_hide_render;
+ PropertyRNA *base_hide_viewport;
PropertyRNA *collection_hide_viewport, *collection_hide_select, *collection_hide_render;
+ PropertyRNA *layer_collection_holdout, *layer_collection_indirect_only,
+ *layer_collection_hide_viewport;
PropertyRNA *modifier_show_viewport, *modifier_show_render;
} props = {false};
@@ -588,16 +877,57 @@ static void outliner_draw_restrictbuts(uiBlock *block,
props.object_hide_viewport = RNA_struct_type_find_property(&RNA_Object, "hide_viewport");
props.object_hide_select = RNA_struct_type_find_property(&RNA_Object, "hide_select");
props.object_hide_render = RNA_struct_type_find_property(&RNA_Object, "hide_render");
- props.collection_hide_select = RNA_struct_type_find_property(&RNA_Collection, "hide_select");
+ props.base_hide_viewport = RNA_struct_type_find_property(&RNA_ObjectBase, "hide_viewport");
props.collection_hide_viewport = RNA_struct_type_find_property(&RNA_Collection,
"hide_viewport");
+ props.collection_hide_select = RNA_struct_type_find_property(&RNA_Collection, "hide_select");
props.collection_hide_render = RNA_struct_type_find_property(&RNA_Collection, "hide_render");
+ props.layer_collection_holdout = RNA_struct_type_find_property(&RNA_LayerCollection,
+ "holdout");
+ props.layer_collection_indirect_only = RNA_struct_type_find_property(&RNA_LayerCollection,
+ "indirect_only");
+ props.layer_collection_hide_viewport = RNA_struct_type_find_property(&RNA_LayerCollection,
+ "hide_viewport");
props.modifier_show_viewport = RNA_struct_type_find_property(&RNA_Modifier, "show_viewport");
props.modifier_show_render = RNA_struct_type_find_property(&RNA_Modifier, "show_render");
props.initialized = true;
}
+ struct {
+ int select;
+ int hide;
+ int viewport;
+ int render;
+ int indirect_only;
+ int holdout;
+ } restrict_offsets = {0};
+ int restrict_column_offset = 0;
+
+ /* This will determine the order of drawing from RIGHT to LEFT. */
+ if (soops->outlinevis == SO_VIEW_LAYER) {
+ if (soops->show_restrict_flags & SO_RESTRICT_INDIRECT_ONLY) {
+ restrict_offsets.indirect_only = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH;
+ }
+ if (soops->show_restrict_flags & SO_RESTRICT_HOLDOUT) {
+ restrict_offsets.holdout = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH;
+ }
+ }
+ if (soops->show_restrict_flags & SO_RESTRICT_RENDER) {
+ restrict_offsets.render = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH;
+ }
+ if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) {
+ restrict_offsets.viewport = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH;
+ }
+ if (soops->show_restrict_flags & SO_RESTRICT_HIDE) {
+ restrict_offsets.hide = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH;
+ }
+ if (soops->show_restrict_flags & SO_RESTRICT_SELECT) {
+ restrict_offsets.select = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH;
+ }
+ BLI_assert((restrict_column_offset * UI_UNIT_X + V2D_SCROLL_WIDTH) ==
+ outliner_restrict_columns_width(soops));
+
/* Create buttons. */
uiBut *bt;
@@ -605,27 +935,29 @@ static void outliner_draw_restrictbuts(uiBlock *block,
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 *layer = te->directdata;
+ if (soops->show_restrict_flags & SO_RESTRICT_RENDER) {
+ /* View layer render toggle. */
+ 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,
- &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);
- UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
+ bt = uiDefIconButBitS(block,
+ UI_BTYPE_ICON_TOGGLE_N,
+ VIEW_LAYER_RENDER,
+ 0,
+ ICON_RESTRICT_RENDER_OFF,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.render),
+ 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);
+ UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
+ }
}
else if ((tselem->type == 0 && te->idcode == ID_OB) &&
(te->flag & TE_CHILD_NOT_IN_COLLECTION)) {
@@ -634,40 +966,65 @@ static void outliner_draw_restrictbuts(uiBlock *block,
else if (tselem->type == 0 && te->idcode == ID_OB) {
PointerRNA ptr;
Object *ob = (Object *)tselem->id;
- RNA_pointer_create(&ob->id, &RNA_Object, ob, &ptr);
- Base *base = BKE_view_layer_base_find(view_layer, ob);
-
- if (base) {
- int icon = ICON_RESTRICT_VIEW_ON;
- if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0) {
- icon = (base->flag & BASE_HIDDEN) != 0 ? ICON_HIDE_ON : ICON_HIDE_OFF;
+ RNA_id_pointer_create(&ob->id, &ptr);
+
+ if (soops->show_restrict_flags & SO_RESTRICT_HIDE) {
+ Base *base = (te->directdata) ? (Base *)te->directdata :
+ BKE_view_layer_base_find(view_layer, ob);
+ if (base) {
+ PointerRNA base_ptr;
+ RNA_pointer_create(&ob->id, &RNA_ObjectBase, base, &base_ptr);
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.hide),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &base_ptr,
+ props.base_hide_viewport,
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Temporarly hide in viewport\n"
+ "* Shift to set children"));
+ UI_but_func_set(
+ bt, outliner__base_set_flag_recursive_cb, base, (void *)"hide_viewport");
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
}
- bt = uiDefIconBut(block,
- UI_BTYPE_ICON_TOGGLE,
- 0,
- icon,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
- te->ys,
- UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- TIP_("Hide object in viewport\n"
- "* Alt to disable for all viewports\n"
- "* Ctrl to isolate visibility"));
- UI_but_func_set(bt, hidebutton_base_flag_cb, view_layer, base);
- UI_but_func_pushed_state_set(bt, base_pushed_state_cb, base);
+ }
+
+ if (soops->show_restrict_flags & SO_RESTRICT_SELECT) {
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.select),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &ptr,
+ props.object_hide_select,
+ -1,
+ 0,
+ 0,
+ -1,
+ -1,
+ TIP_("Disable selection in viewport\n"
+ "* Shift to set children"));
+ UI_but_func_set(bt, outliner__object_set_flag_recursive_cb, ob, (char *)"hide_select");
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
}
- else {
+
+ if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) {
bt = uiDefIconButR_prop(block,
UI_BTYPE_ICON_TOGGLE,
0,
0,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
+ (int)(ar->v2d.cur.xmax - restrict_offsets.viewport),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -678,256 +1035,320 @@ static void outliner_draw_restrictbuts(uiBlock *block,
0,
-1,
-1,
+ TIP_("Globally disable in viewports\n"
+ "* Shift to set children"));
+ UI_but_func_set(bt, outliner__object_set_flag_recursive_cb, ob, (void *)"hide_viewport");
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
+
+ if (soops->show_restrict_flags & SO_RESTRICT_RENDER) {
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.render),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &ptr,
+ props.object_hide_render,
+ -1,
+ 0,
+ 0,
+ -1,
+ -1,
+ TIP_("Globally disable in renders\n"
+ "* Shift to set children"));
+ UI_but_func_set(bt, outliner__object_set_flag_recursive_cb, ob, (char *)"hide_render");
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
+ }
+ else if (tselem->type == TSE_MODIFIER) {
+ ModifierData *md = (ModifierData *)te->directdata;
+
+ PointerRNA ptr;
+ RNA_pointer_create(tselem->id, &RNA_Modifier, md, &ptr);
+
+ if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) {
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.viewport),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &ptr,
+ props.modifier_show_viewport,
+ -1,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
+
+ if (soops->show_restrict_flags & SO_RESTRICT_RENDER) {
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.render),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &ptr,
+ props.modifier_show_render,
+ -1,
+ 0,
+ 0,
+ -1,
+ -1,
NULL);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
}
+ }
+ else if (tselem->type == TSE_POSE_CHANNEL) {
+ bPoseChannel *pchan = (bPoseChannel *)te->directdata;
+ Bone *bone = pchan->bone;
+ Object *ob = (Object *)tselem->id;
- bt = uiDefIconButR_prop(block,
+ if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) {
+ bt = uiDefIconButBitI(block,
UI_BTYPE_ICON_TOGGLE,
+ BONE_HIDDEN_P,
0,
- 0,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
+ ICON_HIDE_OFF,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.viewport),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
- &ptr,
- props.object_hide_select,
- -1,
+ &(bone->flag),
+ 0,
0,
0,
- -1,
- -1,
- NULL);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ 0,
+ TIP_("Restrict 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);
+ UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
+ }
- bt = uiDefIconButR_prop(block,
+ if (soops->show_restrict_flags & SO_RESTRICT_SELECT) {
+ bt = uiDefIconButBitI(block,
UI_BTYPE_ICON_TOGGLE,
+ BONE_UNSELECTABLE,
0,
- 0,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
+ ICON_RESTRICT_SELECT_OFF,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.select),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
- &ptr,
- props.object_hide_render,
- -1,
+ &(bone->flag),
+ 0,
0,
0,
- -1,
- -1,
- NULL);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ 0,
+ TIP_("Restrict 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_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
+ }
}
- else if (tselem->type == TSE_MODIFIER) {
- ModifierData *md = (ModifierData *)te->directdata;
-
- PointerRNA ptr;
- RNA_pointer_create(tselem->id, &RNA_Modifier, md, &ptr);
+ else if (tselem->type == TSE_EBONE) {
+ EditBone *ebone = (EditBone *)te->directdata;
- bt = uiDefIconButR_prop(block,
+ if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) {
+ bt = uiDefIconButBitI(block,
UI_BTYPE_ICON_TOGGLE,
+ BONE_HIDDEN_A,
0,
- 0,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
+ ICON_RESTRICT_VIEW_OFF,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.viewport),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
- &ptr,
- props.modifier_show_viewport,
- -1,
+ &(ebone->flag),
+ 0,
0,
0,
- -1,
- -1,
- NULL);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ 0,
+ TIP_("Restrict 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);
+ UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
+ }
- bt = uiDefIconButR_prop(block,
+ if (soops->show_restrict_flags & SO_RESTRICT_SELECT) {
+ bt = uiDefIconButBitI(block,
UI_BTYPE_ICON_TOGGLE,
+ BONE_UNSELECTABLE,
0,
- 0,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
+ ICON_RESTRICT_SELECT_OFF,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.select),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
- &ptr,
- props.modifier_show_render,
- -1,
+ &(ebone->flag),
0,
0,
- -1,
- -1,
- NULL);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- }
- else if (tselem->type == TSE_POSE_CHANNEL) {
- bPoseChannel *pchan = (bPoseChannel *)te->directdata;
- Bone *bone = pchan->bone;
- Object *ob = (Object *)tselem->id;
-
- 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);
- UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
-
- 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_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
- }
- else if (tselem->type == TSE_EBONE) {
- EditBone *ebone = (EditBone *)te->directdata;
-
- 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);
- UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
-
- 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_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
+ 0,
+ 0,
+ TIP_("Restrict 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_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
+ }
}
else if (tselem->type == TSE_GP_LAYER) {
ID *id = tselem->id;
bGPDlayer *gpl = (bGPDlayer *)te->directdata;
- 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, id, gpl);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
-
- 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, id, gpl);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) {
+ bt = uiDefIconButBitS(block,
+ UI_BTYPE_ICON_TOGGLE,
+ GP_LAYER_HIDE,
+ 0,
+ ICON_HIDE_OFF,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.viewport),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &gpl->flag,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Restrict visibility in the 3D View"));
+ UI_but_func_set(bt, restrictbutton_gp_layer_flag_cb, id, gpl);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
+ }
+
+ if (soops->show_restrict_flags & SO_RESTRICT_SELECT) {
+ bt = uiDefIconButBitS(block,
+ UI_BTYPE_ICON_TOGGLE,
+ GP_LAYER_LOCKED,
+ 0,
+ ICON_UNLOCKED,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.select),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &gpl->flag,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Restrict editing of strokes and keyframes in this layer"));
+ UI_but_func_set(bt, restrictbutton_gp_layer_flag_cb, id, gpl);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
}
else if (outliner_is_collection_tree_element(te)) {
- LayerCollection *lc = (tselem->type == TSE_LAYER_COLLECTION) ? te->directdata : NULL;
+ LayerCollection *layer_collection = (tselem->type == TSE_LAYER_COLLECTION) ?
+ te->directdata :
+ NULL;
Collection *collection = outliner_collection_from_tree_element(te);
- if ((!lc || !(lc->flag & LAYER_COLLECTION_EXCLUDE)) &&
+ if ((!layer_collection || !(layer_collection->flag & LAYER_COLLECTION_EXCLUDE)) &&
!(collection->flag & COLLECTION_IS_MASTER)) {
PointerRNA collection_ptr;
RNA_id_pointer_create(&collection->id, &collection_ptr);
- if (lc != NULL) {
- int icon = ICON_RESTRICT_VIEW_ON;
- if ((collection->flag & COLLECTION_RESTRICT_VIEW) == 0) {
- icon = (lc->flag & LAYER_COLLECTION_RESTRICT_VIEW) != 0 ? ICON_HIDE_ON :
- ICON_HIDE_OFF;
+ if (layer_collection != NULL) {
+ PointerRNA layer_collection_ptr;
+ RNA_pointer_create(
+ &scene->id, &RNA_LayerCollection, layer_collection, &layer_collection_ptr);
+
+ if (soops->show_restrict_flags & SO_RESTRICT_HIDE) {
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.hide),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &layer_collection_ptr,
+ props.layer_collection_hide_viewport,
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Temporarily hide in viewport\n"
+ "* Ctrl to isolate collection\n"
+ "* Shift to set inside collections and objects"));
+ UI_but_func_set(bt,
+ view_layer__layer_collection_set_flag_recursive_cb,
+ layer_collection,
+ (char *)"hide_viewport");
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
+
+ if (soops->show_restrict_flags & SO_RESTRICT_HOLDOUT) {
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.holdout),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &layer_collection_ptr,
+ props.layer_collection_holdout,
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Mask out objects in collection from view layer\n"
+ "* Ctrl to isolate collection\n"
+ "* Shift to set inside collections"));
+ UI_but_func_set(bt,
+ view_layer__layer_collection_set_flag_recursive_cb,
+ layer_collection,
+ (char *)"holdout");
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
+
+ if (soops->show_restrict_flags & SO_RESTRICT_INDIRECT_ONLY) {
+ bt = uiDefIconButR_prop(
+ block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ (layer_collection->flag & LAYER_COLLECTION_INDIRECT_ONLY) != 0 ? 0 : ICON_REMOVE,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.indirect_only),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &layer_collection_ptr,
+ props.layer_collection_indirect_only,
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Objects in collection only contribute indirectly (through shadows and "
+ "reflections) in the view layer\n"
+ "* Ctrl to isolate collection\n"
+ "* Shift to set inside collections"));
+ UI_but_func_set(bt,
+ view_layer__layer_collection_set_flag_recursive_cb,
+ layer_collection,
+ (char *)"indirect_only");
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
}
- bt = uiDefIconBut(block,
- UI_BTYPE_ICON_TOGGLE,
- 0,
- icon,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
- te->ys,
- UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- TIP_("Hide collection in viewport\n"
- "* Alt to disable for all viewports\n"
- "* Ctrl to isolate visibility\n"
- "* Shift to hide inside objects and collections"));
- UI_but_func_set(bt, hidebutton_layer_collection_flag_cb, view_layer, lc);
- UI_but_func_pushed_state_set(bt, layer_collection_pushed_state_cb, lc);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
}
- else {
+
+ if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) {
bt = uiDefIconButR_prop(block,
UI_BTYPE_ICON_TOGGLE,
0,
0,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
+ (int)(ar->v2d.cur.xmax - restrict_offsets.viewport),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -938,45 +1359,87 @@ static void outliner_draw_restrictbuts(uiBlock *block,
0,
0,
0,
- NULL);
+ TIP_("Globally disable in viewports\n"
+ "* Ctrl to isolate collection\n"
+ "* Shift to set inside collections and objects"));
+ if (layer_collection != NULL) {
+ UI_but_func_set(bt,
+ view_layer__collection_set_flag_recursive_cb,
+ layer_collection,
+ (char *)"hide_viewport");
+ }
+ else {
+ UI_but_func_set(bt,
+ scenes__collection_set_flag_recursive_cb,
+ collection,
+ (char *)"hide_viewport");
+ }
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
}
- bt = uiDefIconButR_prop(block,
- UI_BTYPE_ICON_TOGGLE,
- 0,
- 0,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
- te->ys,
- UI_UNIT_X,
- UI_UNIT_Y,
- &collection_ptr,
- props.collection_hide_render,
- -1,
- 0,
- 0,
- 0,
- 0,
- NULL);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ if (soops->show_restrict_flags & SO_RESTRICT_RENDER) {
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.render),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &collection_ptr,
+ props.collection_hide_render,
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Globally disable in renders\n"
+ "* Ctrl to isolate collection\n"
+ "* Shift to set inside collections and objects"));
+ if (layer_collection != NULL) {
+ UI_but_func_set(bt,
+ view_layer__collection_set_flag_recursive_cb,
+ layer_collection,
+ (char *)"hide_render");
+ }
+ else {
+ UI_but_func_set(
+ bt, scenes__collection_set_flag_recursive_cb, collection, (char *)"hide_render");
+ }
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
- bt = uiDefIconButR_prop(block,
- UI_BTYPE_ICON_TOGGLE,
- 0,
- 0,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
- te->ys,
- UI_UNIT_X,
- UI_UNIT_Y,
- &collection_ptr,
- props.collection_hide_select,
- -1,
- 0,
- 0,
- 0,
- 0,
- NULL);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ if (soops->show_restrict_flags & SO_RESTRICT_SELECT) {
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.select),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &collection_ptr,
+ props.collection_hide_select,
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Disable selection in viewport\n"
+ "* Ctrl to isolate collection\n"
+ "* Shift to set inside collections and objects"));
+ if (layer_collection != NULL) {
+ UI_but_func_set(bt,
+ view_layer__collection_set_flag_recursive_cb,
+ layer_collection,
+ (char *)"hide_select");
+ }
+ else {
+ UI_but_func_set(
+ bt, scenes__collection_set_flag_recursive_cb, collection, (char *)"hide_select");
+ }
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
}
}
}
@@ -1005,6 +1468,23 @@ static void outliner_draw_userbuts(uiBlock *block, ARegion *ar, SpaceOutliner *s
but_flag |= UI_BUT_DISABLED;
}
+ BLI_str_format_int_grouped(buf, id->us);
+ bt = uiDefBut(block,
+ UI_BTYPE_BUT,
+ 1,
+ buf,
+ (int)(ar->v2d.cur.xmax - OL_TOG_USER_BUTS_USERS),
+ 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);
+
if (id->flag & LIB_FAKEUSER) {
icon = ICON_FILE_TICK;
tip = TIP_("Data-block will be retained using a fake user");
@@ -1018,7 +1498,7 @@ static void outliner_draw_userbuts(uiBlock *block, ARegion *ar, SpaceOutliner *s
LIB_FAKEUSER,
1,
icon,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
+ (int)(ar->v2d.cur.xmax - OL_TOG_USER_BUTS_STATUS),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1031,29 +1511,12 @@ static void outliner_draw_userbuts(uiBlock *block, ARegion *ar, SpaceOutliner *s
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"));
- UI_but_flag_enable(bt, but_flag);
-
bt = uiDefButBitS(block,
UI_BTYPE_ICON_TOGGLE,
LIB_FAKEUSER,
1,
(id->flag & LIB_FAKEUSER) ? "F" : " ",
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
+ (int)(ar->v2d.cur.xmax - OL_TOG_USER_BUTS_FAKEUSER),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1179,8 +1642,13 @@ static void outliner_draw_rnabuts(
}
}
-static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, TreeElement *te)
+static void outliner_buttons(const bContext *C,
+ uiBlock *block,
+ ARegion *ar,
+ const float restrict_column_width,
+ TreeElement *te)
{
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
uiBut *bt;
TreeStoreElem *tselem;
int spx, dx, len;
@@ -1206,7 +1674,11 @@ 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);
+ if ((tselem->type == TSE_LAYER_COLLECTION) &&
+ (soops->show_restrict_flags & SO_RESTRICT_ENABLE)) {
+ spx += UI_UNIT_X;
+ }
+ dx = ar->v2d.cur.xmax - (spx + restrict_column_width + 0.2f * UI_UNIT_X);
bt = uiDefBut(block,
UI_BTYPE_TEXT,
@@ -1778,6 +2250,60 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
return data;
}
+static void tselem_draw_layer_collection_enable_icon(
+ Scene *scene, uiBlock *block, int xmax, float x, float y, TreeElement *te, float alpha)
+{
+ /* Get RNA property (once for speed). */
+ static PropertyRNA *exclude_prop = NULL;
+ if (exclude_prop == NULL) {
+ exclude_prop = RNA_struct_type_find_property(&RNA_LayerCollection, "exclude");
+ }
+
+ if (x >= xmax) {
+ /* Placement of icons, copied from interface_widgets.c. */
+ float aspect = (0.8f * UI_UNIT_Y) / ICON_DEFAULT_HEIGHT;
+ x += 2.0f * aspect;
+ y += 2.0f * aspect;
+
+ /* restrict column clip... it has been coded by simply overdrawing,
+ * doesn't work for buttons */
+ char color[4];
+ int icon = RNA_property_ui_icon(exclude_prop);
+ if (UI_icon_get_theme_color(icon, (uchar *)color)) {
+ UI_icon_draw_ex(x, y, icon, U.inv_dpi_fac, alpha, 0.0f, color, true);
+ }
+ else {
+ UI_icon_draw_ex(x, y, icon, U.inv_dpi_fac, alpha, 0.0f, NULL, false);
+ }
+ }
+ else {
+ LayerCollection *layer_collection = te->directdata;
+ PointerRNA layer_collection_ptr;
+ RNA_pointer_create(&scene->id, &RNA_LayerCollection, layer_collection, &layer_collection_ptr);
+
+ char emboss = UI_block_emboss_get(block);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ uiBut *bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ x,
+ y,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &layer_collection_ptr,
+ exclude_prop,
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ UI_block_emboss_set(block, emboss);
+ }
+}
+
static void tselem_draw_icon(uiBlock *block,
int xmax,
float x,
@@ -1801,7 +2327,13 @@ static void tselem_draw_icon(uiBlock *block,
/* restrict column clip... it has been coded by simply overdrawing,
* doesn't work for buttons */
- UI_icon_draw_alpha(x, y, data.icon, alpha);
+ char color[4];
+ if (UI_icon_get_theme_color(data.icon, (uchar *)color)) {
+ UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, color, true);
+ }
+ else {
+ UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, NULL, false);
+ }
}
else {
uiDefIconBut(block,
@@ -2068,6 +2600,7 @@ static void outliner_draw_tree_element(bContext *C,
bool draw_grayed_out,
int startx,
int *starty,
+ const float restrict_column_width,
TreeElement **te_edit)
{
TreeStoreElem *tselem;
@@ -2090,8 +2623,8 @@ static void outliner_draw_tree_element(bContext *C,
}
/* icons can be ui buts, we don't want it to overlap with restrict */
- if ((soops->flag & SO_HIDE_RESTRICTCOLS) == 0) {
- xmax -= OL_TOGW + UI_UNIT_X;
+ if (restrict_column_width > 0) {
+ xmax -= restrict_column_width + UI_UNIT_X;
}
GPU_blend(true);
@@ -2150,13 +2683,21 @@ static void outliner_draw_tree_element(bContext *C,
rgba_float_args_set(color, 0.85f, 0.85f, 1.0f, alpha);
}
+ /* Checkbox to enable collections. */
+ if ((tselem->type == TSE_LAYER_COLLECTION) &&
+ (soops->show_restrict_flags & SO_RESTRICT_ENABLE)) {
+ tselem_draw_layer_collection_enable_icon(
+ scene, block, xmax, (float)startx + offsx + UI_UNIT_X, (float)*starty, te, 0.8f);
+ offsx += UI_UNIT_X;
+ }
+
/* active circle */
if (active != OL_DRAWSEL_NONE) {
UI_draw_roundbox_corner_set(UI_CNR_ALL);
UI_draw_roundbox_aa(true,
- (float)startx + UI_UNIT_X + 1.0f * ufac,
+ (float)startx + offsx + UI_UNIT_X + 1.0f * ufac,
(float)*starty + 1.0f * ufac,
- (float)startx + 2.0f * UI_UNIT_X - 1.0f * ufac,
+ (float)startx + offsx + 2.0f * UI_UNIT_X - 1.0f * ufac,
(float)*starty + UI_UNIT_Y - 1.0f * ufac,
UI_UNIT_Y / 2.0f - 1.0f * ufac,
color);
@@ -2190,7 +2731,6 @@ static void outliner_draw_tree_element(bContext *C,
offsx += UI_UNIT_X;
/* datatype icon */
-
if (!(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, TSE_ID_BASE))) {
tselem_draw_icon(
block, xmax, (float)startx + offsx, (float)*starty, tselem, te, alpha_fac, true);
@@ -2306,6 +2846,7 @@ static void outliner_draw_tree_element(bContext *C,
draw_childs_grayed_out,
startx + UI_UNIT_X,
starty,
+ restrict_column_width,
te_edit);
}
}
@@ -2585,7 +3126,7 @@ static void outliner_draw_tree(bContext *C,
ViewLayer *view_layer,
ARegion *ar,
SpaceOutliner *soops,
- const bool has_restrict_icons,
+ const float restrict_column_width,
TreeElement **te_edit)
{
const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
@@ -2607,8 +3148,8 @@ static void outliner_draw_tree(bContext *C,
/* set scissor so tree elements or lines can't overlap restriction icons */
float scissor[4] = {0};
- if (has_restrict_icons) {
- int mask_x = BLI_rcti_size_x(&ar->v2d.mask) - (int)OL_TOGW + 1;
+ if (restrict_column_width > 0.0f) {
+ int mask_x = BLI_rcti_size_x(&ar->v2d.mask) - (int)restrict_column_width + 1;
CLAMP_MIN(mask_x, 0);
GPU_scissor_get_f(scissor);
@@ -2636,10 +3177,11 @@ static void outliner_draw_tree(bContext *C,
(te->flag & TE_DRAGGING) != 0,
startx,
&starty,
+ restrict_column_width,
te_edit);
}
- if (has_restrict_icons) {
+ if (restrict_column_width > 0.0f) {
/* reset scissor */
GPU_scissor(UNPACK4(scissor));
}
@@ -2694,7 +3236,6 @@ void draw_outliner(const bContext *C)
uiBlock *block;
int sizey = 0, sizex = 0, sizex_rna = 0;
TreeElement *te_edit = NULL;
- bool has_restrict_icons;
outliner_build_tree(mainvar, scene, view_layer, soops, ar); // always
@@ -2704,6 +3245,7 @@ void draw_outliner(const bContext *C)
/* extend size to allow for horizontal scrollbar */
sizey += V2D_SCROLL_HEIGHT;
+ const float restrict_column_width = outliner_restrict_columns_width(soops);
if (soops->outlinevis == SO_DATA_API) {
/* RNA has two columns:
* - column 1 is (max_width + OL_RNA_COL_SPACEX) or
@@ -2719,7 +3261,6 @@ void draw_outliner(const bContext *C)
/* get width of data (for setting 'tot' rect, this is column 1 + column 2 + a bit extra) */
sizex = sizex_rna + OL_RNA_COL_SIZEX + 50;
- has_restrict_icons = false;
}
else {
/* width must take into account restriction columns (if visible)
@@ -2728,13 +3269,8 @@ void draw_outliner(const bContext *C)
// XXX should use outliner_width instead when te->xend will be set correctly...
outliner_rna_width(soops, &soops->tree, &sizex, 0);
- /* constant offset for restriction columns */
- // XXX this isn't that great yet...
- if ((soops->flag & SO_HIDE_RESTRICTCOLS) == 0) {
- sizex += OL_TOGW * 3;
- }
-
- has_restrict_icons = !(soops->flag & SO_HIDE_RESTRICTCOLS);
+ /* Constant offset for restriction columns */
+ sizex += restrict_column_width;
}
/* adds vertical offset */
@@ -2752,7 +3288,7 @@ void draw_outliner(const bContext *C)
outliner_back(ar);
block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
outliner_draw_tree(
- (bContext *)C, block, scene, view_layer, ar, soops, has_restrict_icons, &te_edit);
+ (bContext *)C, block, scene, view_layer, ar, soops, restrict_column_width, &te_edit);
/* Default to no emboss for outliner UI. */
UI_block_emboss_set(block, UI_EMBOSS_NONE);
@@ -2765,20 +3301,20 @@ void draw_outliner(const bContext *C)
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) {
+ else if (soops->outlinevis == SO_ID_ORPHANS) {
/* draw user toggle columns */
outliner_draw_userbuts(block, ar, soops, &soops->tree);
}
- else if (has_restrict_icons) {
+ else if (restrict_column_width > 0.0f) {
/* draw restriction columns */
outliner_draw_restrictbuts(block, scene, view_layer, ar, soops, &soops->tree);
}
UI_block_emboss_set(block, UI_EMBOSS);
- /* draw edit buttons if nessecery */
+ /* Draw edit buttons if necessary. */
if (te_edit) {
- outliner_buttons(C, block, ar, te_edit);
+ outliner_buttons(C, block, ar, restrict_column_width, te_edit);
}
UI_block_end(C, block);
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index a943e972cf5..90180c4ea47 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -1025,8 +1025,8 @@ int common_restrict_check(bContext *C, Object *ob)
Object *obedit = CTX_data_edit_object(C);
if (obedit && obedit == ob) {
/* found object is hidden, reset */
- if (ob->restrictflag & OB_RESTRICT_VIEW) {
- ob->restrictflag &= ~OB_RESTRICT_VIEW;
+ if (ob->restrictflag & OB_RESTRICT_VIEWPORT) {
+ ob->restrictflag &= ~OB_RESTRICT_VIEWPORT;
}
/* found object is unselectable, reset */
if (ob->restrictflag & OB_RESTRICT_SELECT) {
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index 8211e3005c7..15489c61230 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -156,11 +156,9 @@ typedef enum {
/* size constants */
#define OL_Y_OFFSET 2
-#define OL_TOG_RESTRICT_SELECTX (UI_UNIT_X * 3.0f + V2D_SCROLL_WIDTH)
-#define OL_TOG_RESTRICT_VIEWX (UI_UNIT_X * 2.0f + V2D_SCROLL_WIDTH)
-#define OL_TOG_RESTRICT_RENDERX (UI_UNIT_X + V2D_SCROLL_WIDTH)
-
-#define OL_TOGW OL_TOG_RESTRICT_SELECTX
+#define OL_TOG_USER_BUTS_USERS (UI_UNIT_X * 2.0f + V2D_SCROLL_WIDTH)
+#define OL_TOG_USER_BUTS_STATUS (UI_UNIT_X * 3.0f + V2D_SCROLL_WIDTH)
+#define OL_TOG_USER_BUTS_FAKEUSER (UI_UNIT_X + V2D_SCROLL_WIDTH)
#define OL_RNA_COLX (UI_UNIT_X * 15)
#define OL_RNA_COL_SIZEX (UI_UNIT_X * 7.5f)
@@ -449,5 +447,6 @@ bool outliner_tree_traverse(const SpaceOutliner *soops,
int filter_tselem_flag,
TreeTraversalFunc func,
void *customdata);
+float outliner_restrict_columns_width(const struct SpaceOutliner *soops);
#endif /* __OUTLINER_INTERN_H__ */
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 995f41382cd..c6fcf1d8cf7 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -1271,8 +1271,7 @@ static bool outliner_is_co_within_restrict_columns(const SpaceOutliner *soops,
const ARegion *ar,
float view_co_x)
{
- return ((soops->outlinevis != SO_DATA_API) && !(soops->flag & SO_HIDE_RESTRICTCOLS) &&
- (view_co_x > ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX));
+ return (view_co_x > ar->v2d.cur.xmax - outliner_restrict_columns_width(soops));
}
/**
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 4e3fd6037bb..80424f021e2 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -302,6 +302,9 @@ static void outliner_add_scene_contents(SpaceOutliner *soops,
tenlay->directdata = view_layer;
}
+ /* World */
+ outliner_add_element(soops, lb, sce->world, te, 0, 0);
+
/* Collections */
ten = outliner_add_element(soops, lb, &sce->id, te, TSE_SCENE_COLLECTION_BASE, 0);
ten->name = IFACE_("Scene Collection");
@@ -1370,6 +1373,12 @@ static void outliner_add_layer_collections_recursive(SpaceOutliner *soops,
const bool show_objects)
{
for (LayerCollection *lc = layer_collections->first; lc; lc = lc->next) {
+ const bool exclude = (lc->flag & LAYER_COLLECTION_EXCLUDE) != 0;
+
+ if (exclude && ((soops->show_restrict_flags & SO_RESTRICT_ENABLE) == 0)) {
+ continue;
+ }
+
ID *id = &lc->collection->id;
TreeElement *ten = outliner_add_element(soops, tree, id, parent_ten, TSE_LAYER_COLLECTION, 0);
@@ -1382,8 +1391,7 @@ static void outliner_add_layer_collections_recursive(SpaceOutliner *soops,
tselem->flag &= ~TSE_CLOSED;
}
- const bool exclude = (lc->flag & LAYER_COLLECTION_EXCLUDE) != 0;
- if (exclude || ((lc->runtime_flag & LAYER_COLLECTION_VISIBLE) == 0)) {
+ if (exclude || (lc->runtime_flag & LAYER_COLLECTION_VISIBLE) == 0) {
ten->flag |= TE_DISABLED;
}
diff --git a/source/blender/editors/space_outliner/outliner_utils.c b/source/blender/editors/space_outliner/outliner_utils.c
index 03d15088380..f57dce97b38 100644
--- a/source/blender/editors/space_outliner/outliner_utils.c
+++ b/source/blender/editors/space_outliner/outliner_utils.c
@@ -31,6 +31,7 @@
#include "ED_armature.h"
#include "UI_interface.h"
+#include "UI_view2d.h"
#include "outliner_intern.h"
@@ -261,3 +262,41 @@ bool outliner_tree_traverse(const SpaceOutliner *soops,
return true;
}
+
+float outliner_restrict_columns_width(const SpaceOutliner *soops)
+{
+ int num_columns = 0;
+
+ switch (soops->outlinevis) {
+ case SO_DATA_API:
+ case SO_SEQUENCE:
+ case SO_LIBRARIES:
+ return 0.0f;
+ case SO_ID_ORPHANS:
+ num_columns = 3;
+ break;
+ case SO_VIEW_LAYER:
+ if (soops->show_restrict_flags & SO_RESTRICT_HOLDOUT) {
+ num_columns++;
+ }
+ if (soops->show_restrict_flags & SO_RESTRICT_INDIRECT_ONLY) {
+ num_columns++;
+ }
+ ATTR_FALLTHROUGH;
+ case SO_SCENES:
+ if (soops->show_restrict_flags & SO_RESTRICT_SELECT) {
+ num_columns++;
+ }
+ if (soops->show_restrict_flags & SO_RESTRICT_HIDE) {
+ num_columns++;
+ }
+ if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) {
+ num_columns++;
+ }
+ if (soops->show_restrict_flags & SO_RESTRICT_RENDER) {
+ num_columns++;
+ }
+ break;
+ }
+ return (num_columns * UI_UNIT_X + V2D_SCROLL_WIDTH);
+}
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index a8e3129b5b4..6634edfebee 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -302,6 +302,7 @@ static SpaceLink *outliner_new(const ScrArea *UNUSED(area), const Scene *UNUSED(
soutliner = MEM_callocN(sizeof(SpaceOutliner), "initoutliner");
soutliner->spacetype = SPACE_OUTLINER;
soutliner->filter_id_type = ID_GR;
+ soutliner->show_restrict_flags = SO_RESTRICT_ENABLE | SO_RESTRICT_SELECT | SO_RESTRICT_HIDE;
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for outliner");
diff --git a/source/blender/editors/space_sequencer/CMakeLists.txt b/source/blender/editors/space_sequencer/CMakeLists.txt
index d57be0c85c3..4668a9cef90 100644
--- a/source/blender/editors/space_sequencer/CMakeLists.txt
+++ b/source/blender/editors/space_sequencer/CMakeLists.txt
@@ -21,7 +21,6 @@ set(INC
../../blenlib
../../blentranslation
../../gpu
- ../../depsgraph
../../imbuf
../../makesdna
../../makesrna
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index 1cad9e4f734..b5bb79fb430 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -64,8 +64,6 @@
# include <AUD_Sequence.h>
#endif
-#include "DEG_depsgraph.h"
-
/* own include */
#include "sequencer_intern.h"
@@ -357,7 +355,6 @@ static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op)
sequencer_add_apply_replace_sel(C, op, seq);
sequencer_add_apply_overlap(C, op, seq);
- DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
@@ -444,7 +441,6 @@ static int sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op)
sequencer_add_apply_replace_sel(C, op, seq);
sequencer_add_apply_overlap(C, op, seq);
- DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
@@ -531,7 +527,6 @@ static int sequencer_add_mask_strip_exec(bContext *C, wmOperator *op)
sequencer_add_apply_replace_sel(C, op, seq);
sequencer_add_apply_overlap(C, op, seq);
- DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
@@ -646,7 +641,6 @@ static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoad
BKE_sequencer_sort(scene);
BKE_sequencer_update_muting(ed);
- DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
@@ -974,7 +968,6 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
MEM_freeN(op->customdata);
}
- DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
@@ -1130,7 +1123,6 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
* it was NOT called in blender 2.4x, but wont hurt */
BKE_sequencer_sort(scene);
- DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 72f186d4c1a..805ec26950a 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -60,6 +60,7 @@
#include "ED_mask.h"
#include "ED_sequencer.h"
#include "ED_screen.h"
+#include "ED_time_scrub_ui.h"
#include "ED_space_api.h"
#include "BIF_glutil.h"
@@ -259,6 +260,11 @@ static void drawseqwave(View2D *v2d,
return;
}
+ if (!sound->spinlock) {
+ sound->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock");
+ BLI_spin_init(sound->spinlock);
+ }
+
BLI_spin_lock(sound->spinlock);
if (!sound->waveform) {
if (!(sound->tags & SOUND_TAGS_WAVEFORM_LOADING)) {
@@ -955,7 +961,7 @@ static void draw_seq_strip(const bContext *C,
x1 = seq->startdisp + handsize_clamped;
x2 = seq->enddisp - handsize_clamped;
- float scroller_vert_xoffs = (V2D_SCROLL_WIDTH_TEXT + SEQ_SCROLLER_TEXT_OFFSET) * pixelx;
+ float scroller_vert_xoffs = (V2D_SCROLL_WIDTH_HANDLES + SEQ_SCROLLER_TEXT_OFFSET) * pixelx;
/* info text on the strip */
if (x1 < v2d->cur.xmin + scroller_vert_xoffs) {
@@ -1842,7 +1848,7 @@ static bool draw_cache_view_cb(
color[2] = 0.2f;
stripe_ht = UI_view2d_region_to_view_y(v2d, 4.0f * UI_DPI_FAC * U.pixelsize) -
v2d->cur.ymin;
- stripe_bot = UI_view2d_region_to_view_y(v2d, V2D_SCROLL_HEIGHT_TEXT);
+ stripe_bot = UI_view2d_region_to_view_y(v2d, V2D_SCROLL_HEIGHT_HANDLES);
stripe_top = stripe_bot + stripe_ht;
break;
}
@@ -1916,12 +1922,16 @@ static void draw_cache_view(const bContext *C)
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- float stripe_bot, stripe_top, stripe_offs;
+ float stripe_bot, stripe_top;
+ float stripe_offs = UI_view2d_region_to_view_y(v2d, 1.0f) - v2d->cur.ymin;
float stripe_ht = UI_view2d_region_to_view_y(v2d, 4.0f * UI_DPI_FAC * U.pixelsize) -
v2d->cur.ymin;
+ CLAMP_MAX(stripe_ht, 0.2f);
+ CLAMP_MIN(stripe_offs, stripe_ht / 2);
+
if (scene->ed->cache_flag & SEQ_CACHE_VIEW_FINAL_OUT) {
- stripe_bot = UI_view2d_region_to_view_y(v2d, V2D_SCROLL_HEIGHT_TEXT);
+ stripe_bot = UI_view2d_region_to_view_y(v2d, V2D_SCROLL_HEIGHT_HANDLES);
stripe_top = stripe_bot + stripe_ht;
float bg_color[4] = {1.0f, 0.4f, 0.2f, 0.1f};
@@ -1938,10 +1948,6 @@ static void draw_cache_view(const bContext *C)
continue;
}
- CLAMP_MAX(stripe_ht, 0.2f);
- stripe_offs = UI_view2d_region_to_view_y(v2d, 1.0f) - v2d->cur.ymin;
- CLAMP_MIN(stripe_offs, stripe_ht / 2);
-
stripe_bot = seq->machine + SEQ_STRIP_OFSBOTTOM + stripe_offs;
stripe_top = stripe_bot + stripe_ht;
@@ -2080,19 +2086,22 @@ void draw_timeline_seq(const bContext *C, ARegion *ar)
/* reset view matrix */
UI_view2d_view_restore(C);
+ /* scrubbing region */
+ ED_scrubbing_draw(ar, scene, !(sseq->flag & SEQ_DRAWFRAMES), true);
+
/* scrollers */
scrollers = UI_view2d_scrollers_calc(v2d, NULL);
UI_view2d_scrollers_draw(v2d, scrollers);
UI_view2d_scrollers_free(scrollers);
- /* scale numbers */
- UI_view2d_draw_scale_x__discrete_frames_or_seconds(
- ar, v2d, &v2d->hor, scene, !(sseq->flag & SEQ_DRAWFRAMES), TH_TEXT);
- UI_view2d_draw_scale_y__block(ar, v2d, &v2d->vert, TH_TEXT);
-
- /* draw current frame number-indicator on top of scrollers */
- if ((sseq->flag & SEQ_NO_DRAW_CFRANUM) == 0) {
- UI_view2d_view_orthoSpecial(ar, v2d, 1);
- ANIM_draw_cfra_number(C, v2d, cfra_flag);
+ /* channel numbers */
+ {
+ rcti rect;
+ BLI_rcti_init(&rect,
+ 0,
+ 15 * UI_DPI_FAC,
+ 15 * UI_DPI_FAC,
+ UI_DPI_FAC * ar->sizey - UI_SCRUBBING_MARGIN_Y);
+ UI_view2d_draw_scale_y__block(ar, v2d, &rect, TH_SCROLL_TEXT);
}
}
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 0f5c02327cc..94437d4871a 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -64,8 +64,6 @@
#include "UI_view2d.h"
#include "UI_interface.h"
-#include "DEG_depsgraph.h"
-
/* own include */
#include "sequencer_intern.h"
@@ -2381,7 +2379,6 @@ static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op))
ms = ms->prev;
}
- DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_sequencer/sequencer_preview.c b/source/blender/editors/space_sequencer/sequencer_preview.c
index 8a4e8c007f7..546c2a8a9f0 100644
--- a/source/blender/editors/space_sequencer/sequencer_preview.c
+++ b/source/blender/editors/space_sequencer/sequencer_preview.c
@@ -50,7 +50,6 @@ typedef struct PreviewJob {
typedef struct PreviewJobAudio {
struct PreviewJobAudio *next, *prev;
- struct Main *bmain;
bSound *sound;
int lr; /* sample left or right */
int startframe;
@@ -80,9 +79,7 @@ static void preview_startjob(void *data, short *stop, short *do_update, float *p
PreviewJobAudio *preview_next;
bSound *sound = previewjb->sound;
- BKE_sound_load_audio(previewjb->bmain, sound);
BKE_sound_read_waveform(sound, stop);
- BKE_sound_free_audio(sound);
if (*stop || G.is_break) {
BLI_mutex_lock(pj->mutex);
@@ -156,7 +153,6 @@ void sequencer_preview_add_sound(const bContext *C, Sequence *seq)
/* attempt to lock mutex of job here */
- audiojob->bmain = CTX_data_main(C);
audiojob->sound = seq->sound;
BLI_mutex_lock(pj->mutex);
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index 2b0c29a02ad..7a02b1850ae 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -157,8 +157,8 @@ static SpaceLink *sequencer_new(const ScrArea *UNUSED(sa), const Scene *scene)
ar->v2d.minzoom = 0.01f;
ar->v2d.maxzoom = 100.0f;
- ar->v2d.scroll |= (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
- ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_SCALE_VERTICAL);
+ ar->v2d.scroll |= (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
+ ar->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HANDLES);
ar->v2d.keepzoom = 0;
ar->v2d.keeptot = 0;
ar->v2d.align = V2D_ALIGN_NO_NEG_Y;
@@ -816,7 +816,7 @@ void ED_spacetype_sequencer(void)
art->draw = sequencer_main_region_draw;
art->listener = sequencer_main_region_listener;
art->message_subscribe = sequencer_main_region_message_subscribe;
- art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_FRAMES | ED_KEYMAP_ANIMATION;
+ art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_ANIMATION;
BLI_addhead(&st->regiontypes, art);
@@ -832,7 +832,7 @@ void ED_spacetype_sequencer(void)
/* regions: listview/buttons */
art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
art->regionid = RGN_TYPE_UI;
- art->prefsizex = 220; // XXX
+ art->prefsizex = UI_SIDEBAR_PANEL_WIDTH;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
art->listener = sequencer_buttons_region_listener;
art->init = sequencer_buttons_region_init;
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 678879018a7..ac1fb4af1c2 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -1665,12 +1665,14 @@ void draw_text_main(SpaceText *st, ARegion *ar)
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ GPU_line_width(2.0f);
+
float viewport_size[4];
GPU_viewport_size_get_f(viewport_size);
immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
- immUniform1i("colors_len", 0); /* "simple" mode */
- immUniformThemeColor(TH_GRID); /* same color as line number background */
+ immUniform1i("colors_len", 0); /* "simple" mode */
+ immUniformThemeColor3(TH_GRID); /* same color as line number background */
immUniform1f("dash_width", 2.0f);
immUniform1f("dash_factor", 0.5f);
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index d0809ec33fc..a3a438c3220 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -101,7 +101,7 @@ static char *buf_tabs_to_spaces(const char *in_buf, const int tab_size)
}
/* Allocate output before with extra space for expanded tabs. */
- const int out_size = strlen(in_buf) + num_tabs * (tab_size - 1);
+ const int out_size = strlen(in_buf) + num_tabs * (tab_size - 1) + 1;
char *out_buf = MEM_mallocN(out_size * sizeof(char), __func__);
/* Fill output buffer. */
diff --git a/source/blender/editors/space_topbar/space_topbar.c b/source/blender/editors/space_topbar/space_topbar.c
index 8b290009a97..725a49e417e 100644
--- a/source/blender/editors/space_topbar/space_topbar.c
+++ b/source/blender/editors/space_topbar/space_topbar.c
@@ -213,12 +213,15 @@ static void recent_files_menu_draw(const bContext *UNUSED(C), Menu *menu)
{
struct RecentFile *recent;
uiLayout *layout = menu->layout;
- uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN);
+ uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
if (!BLI_listbase_is_empty(&G.recent_files)) {
for (recent = G.recent_files.first; (recent); recent = recent->next) {
const char *file = BLI_path_basename(recent->filepath);
const int icon = BLO_has_bfile_extension(file) ? ICON_FILE_BLEND : ICON_FILE_BACKUP;
- uiItemStringO(layout, file, icon, "WM_OT_open_mainfile", "filepath", recent->filepath);
+ PointerRNA ptr;
+ uiItemFullO(layout, "WM_OT_open_mainfile", file, icon, NULL, WM_OP_INVOKE_DEFAULT, 0, &ptr);
+ RNA_string_set(&ptr, "filepath", recent->filepath);
+ RNA_boolean_set(&ptr, "display_file_selector", false);
}
}
else {
diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c
index 2237e8b02bc..4c6f2231cc1 100644
--- a/source/blender/editors/space_userpref/space_userpref.c
+++ b/source/blender/editors/space_userpref/space_userpref.c
@@ -249,7 +249,7 @@ void ED_spacetype_userpref(void)
art->init = userpref_navigation_region_init;
art->draw = userpref_navigation_region_draw;
art->listener = userpref_navigation_region_listener;
- art->keymapflag = ED_KEYMAP_UI;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_NAVBAR;
BLI_addhead(&st->regiontypes, art);
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 638c77fc3cb..cc76c151a29 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -41,7 +41,6 @@
#include "GPU_batch.h"
#include "GPU_matrix.h"
#include "GPU_state.h"
-#include "GPU_framebuffer.h"
#include "ED_mesh.h"
@@ -51,8 +50,6 @@
#include "view3d_intern.h" /* bad level include */
-#include "../../draw/intern/draw_cache_impl.h" /* bad level include (temporary) */
-
int view3d_effective_drawtype(const struct View3D *v3d)
{
if (v3d->shading.type == OB_RENDER) {
@@ -61,24 +58,6 @@ int view3d_effective_drawtype(const struct View3D *v3d)
return v3d->shading.type;
}
-static bool check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
-{
- if ((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0) {
- return false;
- }
-
- if (G.f & G_FLAG_BACKBUFSEL) {
- return false;
- }
-
- /* if its drawing textures with zbuf sel, then don't draw dots */
- if (dt == OB_TEXTURE && vd->shading.type == OB_TEXTURE) {
- return false;
- }
-
- return true;
-}
-
/* OpenGL Circle Drawing - Tables for Optimized Drawing Speed */
/* 32 values of sin function (still same result!) */
#define CIRCLE_RESOL 32
@@ -138,216 +117,6 @@ bool view3d_camera_border_hack_test = false;
/* ***************** BACKBUF SEL (BBS) ********* */
-/** See #DRW_shgroup_world_clip_planes_from_rv3d, same function for draw manager. */
-static void bbs_world_clip_planes_from_rv3d(GPUBatch *batch, const float world_clip_planes[6][4])
-{
- GPU_batch_uniform_4fv_array(batch, "WorldClipPlanes", 6, world_clip_planes[0]);
-}
-
-static void bbs_mesh_verts(GPUBatch *batch, int offset, const float world_clip_planes[6][4])
-{
- GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE));
-
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
- GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
- GPU_batch_uniform_1ui(batch, "offset", offset);
- if (world_clip_planes != NULL) {
- bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
- GPU_batch_draw(batch);
-}
-
-static void bbs_mesh_wire(GPUBatch *batch, int offset, const float world_clip_planes[6][4])
-{
- GPU_line_width(1.0f);
- glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);
-
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
- GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
- GPU_batch_uniform_1ui(batch, "offset", offset);
- if (world_clip_planes != NULL) {
- bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
- GPU_batch_draw(batch);
-
- glProvokingVertex(GL_LAST_VERTEX_CONVENTION);
-}
-
-/* two options, facecolors or black */
-static void bbs_mesh_face(GPUBatch *batch,
- const bool use_select,
- const float world_clip_planes[6][4])
-{
- if (use_select) {
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
- GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
- GPU_batch_uniform_1ui(batch, "offset", 1);
- if (world_clip_planes != NULL) {
- bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
- GPU_batch_draw(batch);
- }
- else {
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
- GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_UNIFORM_SELECT_ID, sh_cfg);
- GPU_batch_uniform_1ui(batch, "id", 0);
- if (world_clip_planes != NULL) {
- bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
- GPU_batch_draw(batch);
- }
-}
-
-static void bbs_mesh_face_dot(GPUBatch *batch, const float world_clip_planes[6][4])
-{
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
- GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
- GPU_batch_uniform_1ui(batch, "offset", 1);
- if (world_clip_planes != NULL) {
- bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
- GPU_batch_draw(batch);
-}
-
-static void bbs_mesh_solid_verts(Depsgraph *UNUSED(depsgraph),
- Scene *UNUSED(scene),
- Object *ob,
- const float world_clip_planes[6][4])
-{
- Mesh *me = ob->data;
-
- GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me);
- GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me);
- DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true);
-
- /* Only draw faces to mask out verts, we don't want their selection ID's. */
- bbs_mesh_face(geom_faces, false, world_clip_planes);
- bbs_mesh_verts(geom_verts, 1, world_clip_planes);
-
- bm_vertoffs = me->totvert + 1;
-}
-
-static void bbs_mesh_solid_faces(Scene *UNUSED(scene),
- Object *ob,
- const float world_clip_planes[6][4])
-{
- Mesh *me = ob->data;
- Mesh *me_orig = DEG_get_original_object(ob)->data;
-
- const bool use_hide = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL);
- GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me);
- DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, use_hide);
-
- bbs_mesh_face(geom_faces, true, world_clip_planes);
-}
-
-void draw_object_select_id(Depsgraph *depsgraph,
- Scene *scene,
- View3D *v3d,
- RegionView3D *rv3d,
- Object *ob,
- short select_mode)
-{
- ToolSettings *ts = scene->toolsettings;
- if (select_mode == -1) {
- select_mode = ts->selectmode;
- }
-
- GPU_matrix_mul(ob->obmat);
- GPU_depth_test(true);
-
- const float(*world_clip_planes)[4] = NULL;
- if (rv3d->rflag & RV3D_CLIPPING) {
- ED_view3d_clipping_local(rv3d, ob->obmat);
- world_clip_planes = rv3d->clip_local;
- }
-
- switch (ob->type) {
- case OB_MESH:
- if (ob->mode & OB_MODE_EDIT) {
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- const bool draw_facedot = check_ob_drawface_dot(scene, v3d, ob->dt);
- const bool use_faceselect = (select_mode & SCE_SELECT_FACE) != 0;
-
- BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE);
-
- GPUBatch *geom_faces, *geom_edges, *geom_verts, *geom_facedots;
- geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me);
- if (select_mode & SCE_SELECT_EDGE) {
- geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me);
- }
- if (select_mode & SCE_SELECT_VERTEX) {
- geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me);
- }
- if (draw_facedot) {
- geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me);
- }
- DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true);
-
- bbs_mesh_face(geom_faces, use_faceselect, world_clip_planes);
-
- if (use_faceselect && draw_facedot) {
- bbs_mesh_face_dot(geom_facedots, world_clip_planes);
- }
-
- if (select_mode & SCE_SELECT_FACE) {
- bm_solidoffs = 1 + em->bm->totface;
- }
- else {
- bm_solidoffs = 1;
- }
-
- ED_view3d_polygon_offset(rv3d, 1.0);
-
- /* we draw edges if edge select mode */
- if (select_mode & SCE_SELECT_EDGE) {
- bbs_mesh_wire(geom_edges, bm_solidoffs, world_clip_planes);
- bm_wireoffs = bm_solidoffs + em->bm->totedge;
- }
- else {
- /* `bm_vertoffs` is calculated from `bm_wireoffs`. (otherwise see T53512) */
- bm_wireoffs = bm_solidoffs;
- }
-
- ED_view3d_polygon_offset(rv3d, 1.1);
-
- /* we draw verts if vert select mode. */
- if (select_mode & SCE_SELECT_VERTEX) {
- bbs_mesh_verts(geom_verts, bm_wireoffs, world_clip_planes);
- bm_vertoffs = bm_wireoffs + em->bm->totvert;
- }
- else {
- bm_vertoffs = bm_wireoffs;
- }
-
- ED_view3d_polygon_offset(rv3d, 0.0);
- }
- else {
- Mesh *me = DEG_get_original_object(ob)->data;
- if ((me->editflag & ME_EDIT_PAINT_VERT_SEL) &&
- /* currently vertex select supports weight paint and vertex paint*/
- ((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT))) {
- bbs_mesh_solid_verts(depsgraph, scene, ob, world_clip_planes);
- }
- else {
- bbs_mesh_solid_faces(scene, ob, world_clip_planes);
- }
- }
- break;
- case OB_CURVE:
- case OB_SURF:
- break;
- }
-
- GPU_matrix_set(rv3d->viewmat);
-}
-
void ED_draw_object_facemap(Depsgraph *depsgraph,
Object *ob,
const float col[4],
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index dbf2160d39b..770172d702b 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -1132,6 +1132,9 @@ static void view3d_header_region_listener(wmWindow *UNUSED(win),
ED_region_tag_redraw(ar);
}
break;
+ case NC_BRUSH:
+ ED_region_tag_redraw(ar);
+ break;
}
/* From topbar, which ones are needed? split per header? */
@@ -1201,9 +1204,106 @@ static void view3d_buttons_region_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler(&ar->handlers, keymap);
}
-static void view3d_buttons_region_draw(const bContext *C, ARegion *ar)
+void ED_view3d_buttons_region_layout_ex(const bContext *C,
+ ARegion *ar,
+ const char *category_override)
{
- ED_region_panels_ex(C, ar, (const char *[]){CTX_data_mode_string(C), NULL}, -1, true);
+ const enum eContextObjectMode mode = CTX_data_mode_enum(C);
+
+ const char *contexts_base[4] = {NULL};
+ contexts_base[0] = CTX_data_mode_string(C);
+
+ const char **contexts = &contexts_base[1];
+
+ switch (mode) {
+ case CTX_MODE_EDIT_MESH:
+ ARRAY_SET_ITEMS(contexts, ".mesh_edit");
+ break;
+ case CTX_MODE_EDIT_CURVE:
+ ARRAY_SET_ITEMS(contexts, ".curve_edit");
+ break;
+ case CTX_MODE_EDIT_SURFACE:
+ ARRAY_SET_ITEMS(contexts, ".curve_edit");
+ break;
+ case CTX_MODE_EDIT_TEXT:
+ ARRAY_SET_ITEMS(contexts, ".text_edit");
+ break;
+ case CTX_MODE_EDIT_ARMATURE:
+ ARRAY_SET_ITEMS(contexts, ".armature_edit");
+ break;
+ case CTX_MODE_EDIT_METABALL:
+ ARRAY_SET_ITEMS(contexts, ".mball_edit");
+ break;
+ case CTX_MODE_EDIT_LATTICE:
+ ARRAY_SET_ITEMS(contexts, ".lattice_edit");
+ break;
+ case CTX_MODE_POSE:
+ ARRAY_SET_ITEMS(contexts, ".posemode");
+ break;
+ case CTX_MODE_SCULPT:
+ ARRAY_SET_ITEMS(contexts, ".paint_common", ".sculpt_mode");
+ break;
+ case CTX_MODE_PAINT_WEIGHT:
+ ARRAY_SET_ITEMS(contexts, ".paint_common", ".weightpaint");
+ break;
+ case CTX_MODE_PAINT_VERTEX:
+ ARRAY_SET_ITEMS(contexts, ".paint_common", ".vertexpaint");
+ break;
+ case CTX_MODE_PAINT_TEXTURE:
+ ARRAY_SET_ITEMS(contexts, ".paint_common", ".imagepaint");
+ break;
+ case CTX_MODE_PARTICLE:
+ ARRAY_SET_ITEMS(contexts, ".paint_common", ".particlemode");
+ break;
+ case CTX_MODE_OBJECT:
+ ARRAY_SET_ITEMS(contexts, ".objectmode");
+ break;
+ case CTX_MODE_PAINT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_paint");
+ break;
+ case CTX_MODE_SCULPT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_sculpt");
+ break;
+ case CTX_MODE_WEIGHT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_weight");
+ break;
+ default:
+ break;
+ }
+
+ switch (mode) {
+ case CTX_MODE_PAINT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_paint");
+ break;
+ case CTX_MODE_SCULPT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_sculpt");
+ break;
+ case CTX_MODE_WEIGHT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_weight");
+ break;
+ case CTX_MODE_EDIT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_edit");
+ break;
+ default:
+ break;
+ }
+
+ ListBase *paneltypes = &ar->type->paneltypes;
+
+ /* Allow drawing 3D view toolbar from non 3D view space type. */
+ if (category_override != NULL) {
+ SpaceType *st = BKE_spacetype_from_id(SPACE_VIEW3D);
+ ARegionType *art = BKE_regiontype_from_id(st, RGN_TYPE_UI);
+ paneltypes = &art->paneltypes;
+ }
+
+ const bool vertical = true;
+ ED_region_panels_layout_ex(C, ar, paneltypes, contexts_base, -1, vertical, category_override);
+}
+
+static void view3d_buttons_region_layout(const bContext *C, ARegion *ar)
+{
+ ED_view3d_buttons_region_layout_ex(C, ar, NULL);
}
static void view3d_buttons_region_listener(wmWindow *UNUSED(win),
@@ -1508,12 +1608,13 @@ void ED_spacetype_view3d(void)
/* regions: listview/buttons */
art = MEM_callocN(sizeof(ARegionType), "spacetype view3d buttons region");
art->regionid = RGN_TYPE_UI;
- art->prefsizex = 180; /* XXX */
+ art->prefsizex = UI_SIDEBAR_PANEL_WIDTH;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
art->listener = view3d_buttons_region_listener;
art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_ui;
art->init = view3d_buttons_region_init;
- art->draw = view3d_buttons_region_draw;
+ art->layout = view3d_buttons_region_layout;
+ art->draw = ED_region_panels_draw;
BLI_addhead(&st->regiontypes, art);
view3d_buttons_register(art);
diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c
index b0cee18f8e3..e0dbe1f6543 100644
--- a/source/blender/editors/space_view3d/view3d_draw_legacy.c
+++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c
@@ -77,6 +77,7 @@
#include "ED_armature.h"
#include "ED_keyframing.h"
#include "ED_gpencil.h"
+#include "ED_mesh.h"
#include "ED_screen.h"
#include "ED_space_api.h"
#include "ED_screen_types.h"
@@ -208,7 +209,16 @@ static void validate_object_select_id(struct Depsgraph *depsgraph,
if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) {
DRW_framebuffer_select_id_setup(ar, true);
- draw_object_select_id(depsgraph, scene_eval, v3d, rv3d, obact_eval, select_mode);
+ DRW_draw_select_id_object(scene_eval,
+ rv3d,
+ obact_eval,
+ select_mode,
+ false,
+ 0,
+ &bm_vertoffs,
+ &bm_wireoffs,
+ &bm_solidoffs);
+
DRW_framebuffer_select_id_release(ar);
}
@@ -271,10 +281,8 @@ void ED_view3d_backbuf_depth_validate(ViewContext *vc)
}
}
-uint *ED_view3d_select_id_read_rect(ViewContext *vc, const rcti *clip, uint *r_buf_len)
+uint *ED_view3d_select_id_read_rect(ViewContext *UNUSED(vc), const rcti *clip, uint *r_buf_len)
{
- ED_view3d_select_id_validate(vc);
-
uint width = BLI_rcti_size_x(clip);
uint height = BLI_rcti_size_y(clip);
uint buf_len = width * height;
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c
index 6f35c0aa748..9cbf179ab49 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c
@@ -304,15 +304,14 @@ static int gizmo_preselect_edgering_test_select(bContext *C, wmGizmo *gz, const
em_setup_viewcontext(C, &vc);
copy_v2_v2_int(vc.mval, mval);
- for (uint base_index = 0; base_index < gz_ring->bases_len; base_index++) {
- Object *ob_iter = gz_ring->bases[base_index]->object;
- ED_view3d_viewcontext_init_object(&vc, ob_iter);
- BMEdge *eed_test = EDBM_edge_find_nearest_ex(&vc, &best.dist, NULL, false, false, NULL);
- if (eed_test) {
- best.ob = ob_iter;
- best.eed = eed_test;
- best.base_index = base_index;
- }
+ uint base_index;
+ BMEdge *eed_test = EDBM_edge_find_nearest_ex(
+ &vc, &best.dist, NULL, false, false, NULL, gz_ring->bases, gz_ring->bases_len, &base_index);
+
+ if (eed_test) {
+ best.ob = gz_ring->bases[base_index]->object;
+ best.eed = eed_test;
+ best.base_index = base_index;
}
BMesh *bm = NULL;
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index 9075909a6fe..e499672acc1 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -127,13 +127,6 @@ void VIEW3D_OT_fly(struct wmOperatorType *ot);
void VIEW3D_OT_walk(struct wmOperatorType *ot);
/* drawobject.c */
-void draw_object_select_id(struct Depsgraph *depsgraph,
- Scene *scene,
- View3D *v3d,
- RegionView3D *rv3d,
- struct Object *ob,
- short select_mode);
-
int view3d_effective_drawtype(const struct View3D *v3d);
/* view3d_draw.c */
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 2ce23486476..419ec87eec8 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -57,6 +57,7 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "BKE_global.h"
+#include "BKE_main.h"
#include "BKE_armature.h"
#include "BKE_context.h"
@@ -134,9 +135,6 @@ void ED_view3d_viewcontext_init_object(ViewContext *vc, Object *obact)
if (vc->obedit) {
BLI_assert(BKE_object_is_in_editmode(obact));
vc->obedit = obact;
- /* previous selections are now invalid. */
- vc->v3d->flag |= V3D_INVALID_BACKBUF;
-
if (vc->em) {
vc->em = BKE_editmesh_from_object(vc->obedit);
}
@@ -1170,6 +1168,7 @@ static int view3d_lasso_select_exec(bContext *C, wmOperator *op)
if (mcords) {
view3d_operator_needs_opengl(C);
+ BKE_object_update_select_id(CTX_data_main(C));
/* setup view context for argument to callbacks */
ED_view3d_viewcontext_init(C, &vc);
@@ -1337,7 +1336,7 @@ static Base *object_mouse_select_menu(
if (buffer) {
for (int a = 0; a < hits; a++) {
/* index was converted */
- if (base->object->select_id == (buffer[(4 * a) + 3] & ~0xFFFF0000)) {
+ if (base->object->runtime.select_id == (buffer[(4 * a) + 3] & ~0xFFFF0000)) {
ok = true;
break;
}
@@ -1609,7 +1608,7 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
else {
/* only exclude active object when it is selected... */
if (BASACT(view_layer) && (BASACT(view_layer)->flag & BASE_SELECTED) && hits > 1) {
- notcol = BASACT(view_layer)->object->select_id;
+ notcol = BASACT(view_layer)->object->runtime.select_id;
}
for (a = 0; a < hits; a++) {
@@ -1623,7 +1622,7 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
base = FIRSTBASE(view_layer);
while (base) {
if (BASE_SELECTABLE(v3d, base)) {
- if (base->object->select_id == selcol) {
+ if (base->object->runtime.select_id == selcol) {
break;
}
}
@@ -1654,13 +1653,13 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
if (has_bones) {
/* skip non-bone objects */
if ((buffer[4 * a + 3] & 0xFFFF0000)) {
- if (base->object->select_id == (buffer[(4 * a) + 3] & 0xFFFF)) {
+ if (base->object->runtime.select_id == (buffer[(4 * a) + 3] & 0xFFFF)) {
basact = base;
}
}
}
else {
- if (base->object->select_id == (buffer[(4 * a) + 3] & 0xFFFF)) {
+ if (base->object->runtime.select_id == (buffer[(4 * a) + 3] & 0xFFFF)) {
basact = base;
}
}
@@ -1693,6 +1692,7 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2])
/* setup view context for argument to callbacks */
view3d_operator_needs_opengl(C);
+ BKE_object_update_select_id(CTX_data_main(C));
ED_view3d_viewcontext_init(C, &vc);
@@ -1878,7 +1878,7 @@ static bool ed_object_select_pick(bContext *C,
/* if there's bundles in buffer select bundles first,
* so non-camera elements should be ignored in buffer */
- if (basact->object->select_id != (hitresult & 0xFFFF)) {
+ if (basact->object->runtime.select_id != (hitresult & 0xFFFF)) {
continue;
}
@@ -2129,6 +2129,7 @@ static int view3d_select_exec(bContext *C, wmOperator *op)
RNA_int_get_array(op->ptr, "location", location);
view3d_operator_needs_opengl(C);
+ BKE_object_update_select_id(CTX_data_main(C));
if (object) {
obedit = NULL;
@@ -2355,14 +2356,14 @@ static bool do_paintvert_box_select(ViewContext *vc, const rcti *rect, const eSe
}
else if (use_zbuf) {
MVert *mvert;
- unsigned int *rt;
+ uint *rt, *buf, buf_len;
int a, index;
char *selar;
selar = MEM_callocN(me->totvert + 1, "selar");
- uint buf_len;
- uint *buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len);
+ ED_view3d_select_id_validate(vc);
+ buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len);
rt = buf;
@@ -2652,7 +2653,7 @@ static bool do_meta_box_select(ViewContext *vc, const rcti *rect, const eSelectO
}
const uint hit_object = hitresult & 0xFFFF;
- if (vc->obedit->select_id != hit_object) {
+ if (vc->obedit->runtime.select_id != hit_object) {
continue;
}
@@ -2803,7 +2804,7 @@ static bool do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const
for (Base *base = vc->view_layer->object_bases.first; base; base = base->next) {
if (BASE_SELECTABLE(v3d, base)) {
- if ((base->object->select_id & 0x0000FFFF) != 0) {
+ if ((base->object->runtime.select_id & 0x0000FFFF) != 0) {
BLI_array_append(bases, base);
}
}
@@ -2893,7 +2894,7 @@ static bool do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const e
/* Select the next bone if we're not switching bases. */
if (col + 4 != col_end) {
- if ((base->object->select_id & 0x0000FFFF) != (col[4] & 0x0000FFFF)) {
+ if ((base->object->runtime.select_id & 0x0000FFFF) != (col[4] & 0x0000FFFF)) {
break;
}
if (base->object->pose != NULL) {
@@ -2930,6 +2931,7 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op)
bool changed_multi = false;
view3d_operator_needs_opengl(C);
+ BKE_object_update_select_id(CTX_data_main(C));
/* setup view context for argument to callbacks */
ED_view3d_viewcontext_init(C, &vc);
@@ -3670,6 +3672,7 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
if (obedit || BKE_paint_select_elem_test(obact) || (obact && (obact->mode & OB_MODE_POSE))) {
view3d_operator_needs_opengl(C);
+ BKE_object_update_select_id(CTX_data_main(C));
FOREACH_OBJECT_IN_MODE_BEGIN (vc.view_layer, vc.v3d, obact->type, obact->mode, ob_iter) {
ED_view3d_viewcontext_init_object(&vc, ob_iter);
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 81405b55ac2..09f198ff14c 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -4917,8 +4917,7 @@ static void initSnapSpatial(TransInfo *t, float r_snap[3])
}
else if (t->spacetype == SPACE_NODE) {
r_snap[0] = 0.0f;
- r_snap[1] = ED_node_grid_size();
- r_snap[2] = ED_node_grid_size();
+ r_snap[1] = r_snap[2] = ED_node_grid_size();
}
else if (t->spacetype == SPACE_GRAPH) {
r_snap[0] = 0.0f;
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 50fc1a276b9..b0f720bfdf7 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -383,6 +383,30 @@ typedef struct BoneInitData {
float zwidth;
} BoneInitData;
+typedef struct PoseInitData_Mirror {
+ /** Points to the bone which this info is initialized & restored to.
+ * A NULL value is used to terminate the array. */
+ struct bPoseChannel *pchan;
+ struct {
+ float loc[3];
+ float size[3];
+ union {
+ float eul[3];
+ float quat[4];
+ float axis_angle[4];
+ };
+ float curve_in_x;
+ float curve_out_x;
+ float roll1;
+ float roll2;
+ } orig;
+ /**
+ * An extra offset to apply after mirroring.
+ * Use with #POSE_MIRROR_RELATIVE.
+ */
+ float offset_mtx[4][4];
+} PoseInitData_Mirror;
+
typedef struct TransData {
/** Distance needed to affect element (for Proportionnal Editing). */
float dist;
@@ -501,7 +525,7 @@ typedef struct TransDataContainer {
struct Object *obedit;
/**
- * Use when #T_LOCAL_MATRIX is set.
+ * Store matrix, this avoids having to have duplicate check all over
* Typically: 'obedit->obmat' or 'poseobj->obmat', but may be used elsewhere too.
*/
bool use_local_mat;
@@ -715,10 +739,8 @@ enum {
T_CURSOR = 1 << 5,
/** Transform points, having no rotation/scale. */
T_POINTS = 1 << 6,
- /**
- * Apply matrix #TransDataContainer.matrix, this avoids having to have duplicate check all over
- * that happen to apply to specific modes (edit & pose for eg). */
- T_LOCAL_MATRIX = 1 << 7,
+
+ /* empty slot - (1 << 7) */
/** restrictions flags */
T_NO_CONSTRAINT = 1 << 8,
@@ -892,6 +914,7 @@ void flushTransSeq(TransInfo *t);
void flushTransTracking(TransInfo *t);
void flushTransMasking(TransInfo *t);
void flushTransPaintCurve(TransInfo *t);
+void restoreMirrorPoseBones(TransDataContainer *tc);
void restoreBones(TransDataContainer *tc);
/*********************** transform_gizmo.c ********** */
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 6c1da5ae825..4037fab2b68 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -198,7 +198,10 @@ void sort_trans_data_dist(TransInfo *t)
}
}
-static void sort_trans_data_container(TransDataContainer *tc)
+/**
+ * Make #TD_SELECTED first in the array.
+ */
+static void sort_trans_data_selected_first_container(TransDataContainer *tc)
{
TransData *sel, *unsel;
TransData temp;
@@ -225,10 +228,10 @@ static void sort_trans_data_container(TransDataContainer *tc)
unsel++;
}
}
-static void sort_trans_data(TransInfo *t)
+static void sort_trans_data_selected_first(TransInfo *t)
{
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- sort_trans_data_container(tc);
+ sort_trans_data_selected_first_container(tc);
}
}
@@ -1201,6 +1204,74 @@ static short pose_grab_with_ik(Main *bmain, Object *ob)
return (tot_ik) ? 1 : 0;
}
+static void pose_mirror_info_init(PoseInitData_Mirror *pid,
+ bPoseChannel *pchan,
+ bPoseChannel *pchan_orig,
+ bool is_mirror_relative)
+{
+ pid->pchan = pchan;
+ copy_v3_v3(pid->orig.loc, pchan->loc);
+ copy_v3_v3(pid->orig.size, pchan->size);
+ pid->orig.curve_in_x = pchan->curve_in_x;
+ pid->orig.curve_out_x = pchan->curve_out_x;
+ pid->orig.roll1 = pchan->roll1;
+ pid->orig.roll2 = pchan->roll2;
+
+ if (pchan->rotmode > 0) {
+ copy_v3_v3(pid->orig.eul, pchan->eul);
+ }
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ copy_v3_v3(pid->orig.axis_angle, pchan->rotAxis);
+ pid->orig.axis_angle[3] = pchan->rotAngle;
+ }
+ else {
+ copy_qt_qt(pid->orig.quat, pchan->quat);
+ }
+
+ if (is_mirror_relative) {
+ float pchan_mtx[4][4];
+ float pchan_mtx_mirror[4][4];
+
+ float flip_mtx[4][4];
+ unit_m4(flip_mtx);
+ flip_mtx[0][0] = -1;
+
+ BKE_pchan_to_mat4(pchan_orig, pchan_mtx_mirror);
+ BKE_pchan_to_mat4(pchan, pchan_mtx);
+
+ mul_m4_m4m4(pchan_mtx_mirror, pchan_mtx_mirror, flip_mtx);
+ mul_m4_m4m4(pchan_mtx_mirror, flip_mtx, pchan_mtx_mirror);
+
+ invert_m4(pchan_mtx_mirror);
+ mul_m4_m4m4(pid->offset_mtx, pchan_mtx, pchan_mtx_mirror);
+ }
+ else {
+ unit_m4(pid->offset_mtx);
+ }
+}
+
+static void pose_mirror_info_restore(const PoseInitData_Mirror *pid)
+{
+ bPoseChannel *pchan = pid->pchan;
+ copy_v3_v3(pchan->loc, pid->orig.loc);
+ copy_v3_v3(pchan->size, pid->orig.size);
+ pchan->curve_in_x = pid->orig.curve_in_x;
+ pchan->curve_out_x = pid->orig.curve_out_x;
+ pchan->roll1 = pid->orig.roll1;
+ pchan->roll2 = pid->orig.roll2;
+
+ if (pchan->rotmode > 0) {
+ copy_v3_v3(pchan->eul, pid->orig.eul);
+ }
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ copy_v3_v3(pchan->rotAxis, pid->orig.axis_angle);
+ pchan->rotAngle = pid->orig.axis_angle[3];
+ }
+ else {
+ copy_qt_qt(pchan->quat, pid->orig.quat);
+ }
+}
+
/**
* When objects array is NULL, use 't->data_container' as is.
*/
@@ -1215,16 +1286,19 @@ static void createTransPose(TransInfo *t)
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
Object *ob = tc->poseobj;
+ bPose *pose = ob->pose;
bArmature *arm;
short ik_on = 0;
/* check validity of state */
arm = BKE_armature_from_object(tc->poseobj);
- if ((arm == NULL) || (ob->pose == NULL)) {
+ if ((arm == NULL) || (pose == NULL)) {
continue;
}
+ const bool mirror = ((pose->flag & POSE_MIRROR_EDIT) != 0);
+
/* set flags and count total */
tc->data_len = count_set_pose_transflags(ob, t->mode, t->around, has_translate_rotate);
if (tc->data_len == 0) {
@@ -1240,13 +1314,32 @@ static void createTransPose(TransInfo *t)
}
/* do we need to add temporal IK chains? */
- if ((arm->flag & ARM_AUTO_IK) && t->mode == TFM_TRANSLATION) {
+ if ((pose->flag & POSE_AUTO_IK) && t->mode == TFM_TRANSLATION) {
ik_on = pose_grab_with_ik(bmain, ob);
if (ik_on) {
t->flag |= T_AUTOIK;
has_translate_rotate[0] = true;
}
}
+
+ if (mirror) {
+ int total_mirrored = 0;
+ for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if ((pchan->bone->flag & BONE_TRANSFORM) &&
+ BKE_pose_channel_get_mirrored(ob->pose, pchan->name)) {
+ total_mirrored++;
+ }
+ }
+
+ PoseInitData_Mirror *pid = MEM_mallocN((total_mirrored + 1) * sizeof(PoseInitData_Mirror),
+ "PoseInitData_Mirror");
+
+ /* Trick to terminate iteration. */
+ pid[total_mirrored].pchan = NULL;
+
+ tc->custom.type.data = pid;
+ tc->custom.type.use_free = true;
+ }
}
/* if there are no translatable bones, do rotation */
@@ -1269,6 +1362,17 @@ static void createTransPose(TransInfo *t)
short ik_on = 0;
int i;
+ PoseInitData_Mirror *pid = tc->custom.type.data;
+ int pid_index = 0;
+ bPose *pose = ob->pose;
+
+ if (pose == NULL) {
+ continue;
+ }
+
+ const bool mirror = ((pose->flag & POSE_MIRROR_EDIT) != 0);
+ const bool is_mirror_relative = ((pose->flag & POSE_MIRROR_RELATIVE) != 0);
+
tc->poseobj = ob; /* we also allow non-active objects to be transformed, in weightpaint */
/* init trans data */
@@ -1285,6 +1389,15 @@ static void createTransPose(TransInfo *t)
for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
if (pchan->bone->flag & BONE_TRANSFORM) {
add_pose_transdata(t, pchan, ob, tc, td);
+
+ if (mirror) {
+ bPoseChannel *pchan_mirror = BKE_pose_channel_get_mirrored(ob->pose, pchan->name);
+ if (pchan_mirror) {
+ pose_mirror_info_init(&pid[pid_index], pchan_mirror, pchan, is_mirror_relative);
+ pid_index++;
+ }
+ }
+
td++;
}
}
@@ -1304,6 +1417,19 @@ static void createTransPose(TransInfo *t)
t->flag &= ~T_PROP_EDIT_ALL;
}
+void restoreMirrorPoseBones(TransDataContainer *tc)
+{
+ bPose *pose = tc->poseobj->pose;
+
+ if (!(pose->flag & POSE_MIRROR_EDIT)) {
+ return;
+ }
+
+ for (PoseInitData_Mirror *pid = tc->custom.type.data; pid->pchan; pid++) {
+ pose_mirror_info_restore(pid);
+ }
+}
+
void restoreBones(TransDataContainer *tc)
{
bArmature *arm;
@@ -9253,7 +9379,7 @@ void createTransData(bContext *C, TransInfo *t)
countAndCleanTransDataContainer(t);
if (t->data_len_all && t->flag & T_PROP_EDIT) {
- sort_trans_data(t); // makes selected become first in array
+ sort_trans_data_selected_first(t);
set_prop_dist(t, 1);
sort_trans_data_dist(t);
}
@@ -9267,7 +9393,7 @@ void createTransData(bContext *C, TransInfo *t)
countAndCleanTransDataContainer(t);
if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- sort_trans_data(t); // makes selected become first in array
+ sort_trans_data_selected_first(t);
set_prop_dist(t, 1);
sort_trans_data_dist(t);
}
@@ -9281,7 +9407,7 @@ void createTransData(bContext *C, TransInfo *t)
countAndCleanTransDataContainer(t);
if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- sort_trans_data(t); // makes selected become first in array
+ sort_trans_data_selected_first(t);
set_prop_dist(t, true);
sort_trans_data_dist(t);
}
@@ -9304,7 +9430,7 @@ void createTransData(bContext *C, TransInfo *t)
t->flag |= T_EDIT;
if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- sort_trans_data(t); // makes selected become first in array
+ sort_trans_data_selected_first(t);
set_prop_dist(t, 1);
sort_trans_data_dist(t);
}
@@ -9321,7 +9447,7 @@ void createTransData(bContext *C, TransInfo *t)
countAndCleanTransDataContainer(t);
if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- sort_trans_data(t); // makes selected become first in array
+ sort_trans_data_selected_first(t);
/* don't do that, distance has been set in createTransActionData already */
// set_prop_dist(t, false);
sort_trans_data_dist(t);
@@ -9351,7 +9477,7 @@ void createTransData(bContext *C, TransInfo *t)
if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
/* makes selected become first in array */
- sort_trans_data(t);
+ sort_trans_data_selected_first(t);
/* don't do that, distance has been set in createTransGraphEditData already */
set_prop_dist(t, false);
@@ -9367,7 +9493,7 @@ void createTransData(bContext *C, TransInfo *t)
countAndCleanTransDataContainer(t);
if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- sort_trans_data(t); // makes selected become first in array
+ sort_trans_data_selected_first(t);
set_prop_dist(t, 1);
sort_trans_data_dist(t);
}
@@ -9386,7 +9512,7 @@ void createTransData(bContext *C, TransInfo *t)
countAndCleanTransDataContainer(t);
if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- sort_trans_data(t); // makes selected become first in array
+ sort_trans_data_selected_first(t);
set_prop_dist(t, true);
sort_trans_data_dist(t);
}
@@ -9426,21 +9552,30 @@ void createTransData(bContext *C, TransInfo *t)
t->flag |= T_EDIT | T_POINTS;
- if (t->data_len_all && t->flag & T_PROP_EDIT) {
- if (ELEM(t->obedit_type, OB_CURVE, OB_MESH)) {
- sort_trans_data(t); // makes selected become first in array
- if ((t->obedit_type == OB_MESH) && (t->flag & T_PROP_CONNECTED)) {
- /* already calculated by editmesh_set_connectivity_distance */
+ if (t->data_len_all) {
+ if (t->flag & T_PROP_EDIT) {
+ if (ELEM(t->obedit_type, OB_CURVE, OB_MESH)) {
+ sort_trans_data_selected_first(t);
+ if ((t->obedit_type == OB_MESH) && (t->flag & T_PROP_CONNECTED)) {
+ /* already calculated by editmesh_set_connectivity_distance */
+ }
+ else {
+ set_prop_dist(t, 0);
+ }
+ sort_trans_data_dist(t);
}
else {
- set_prop_dist(t, 0);
+ sort_trans_data_selected_first(t);
+ set_prop_dist(t, 1);
+ sort_trans_data_dist(t);
}
- sort_trans_data_dist(t);
}
else {
- sort_trans_data(t); // makes selected become first in array
- set_prop_dist(t, 1);
- sort_trans_data_dist(t);
+ if (ELEM(t->obedit_type, OB_CURVE)) {
+ /* Needed because bezier handles can be partially selected
+ * and are still added into transform data. */
+ sort_trans_data_selected_first(t);
+ }
}
}
@@ -9494,7 +9629,7 @@ void createTransData(bContext *C, TransInfo *t)
t->flag |= T_POINTS;
if (t->data_len_all && t->flag & T_PROP_EDIT) {
- sort_trans_data(t); // makes selected become first in array
+ sort_trans_data_selected_first(t);
set_prop_dist(t, 1);
sort_trans_data_dist(t);
}
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index a840c04ab5a..758551be0b5 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -781,6 +781,49 @@ static void recalcData_spaceclip(TransInfo *t)
}
}
+/**
+ * if pose bone (partial) selected, copy data.
+ * context; posemode armature, with mirror editing enabled.
+ *
+ * \param pid: Optional, apply relative transform when set.
+ */
+static void pose_transform_mirror_update(Object *ob, PoseInitData_Mirror *pid)
+{
+ float flip_mtx[4][4];
+ unit_m4(flip_mtx);
+ flip_mtx[0][0] = -1;
+
+ for (bPoseChannel *pchan_orig = ob->pose->chanbase.first; pchan_orig;
+ pchan_orig = pchan_orig->next) {
+ /* no layer check, correct mirror is more important */
+ if (pchan_orig->bone->flag & BONE_TRANSFORM) {
+ bPoseChannel *pchan = BKE_pose_channel_get_mirrored(ob->pose, pchan_orig->name);
+
+ if (pchan) {
+ /* also do bbone scaling */
+ pchan->bone->xwidth = pchan_orig->bone->xwidth;
+ pchan->bone->zwidth = pchan_orig->bone->zwidth;
+
+ /* we assume X-axis flipping for now */
+ pchan->curve_in_x = pchan_orig->curve_in_x * -1;
+ pchan->curve_out_x = pchan_orig->curve_out_x * -1;
+ pchan->roll1 = pchan_orig->roll1 * -1; // XXX?
+ pchan->roll2 = pchan_orig->roll2 * -1; // XXX?
+
+ float pchan_mtx_final[4][4];
+ BKE_pchan_to_mat4(pchan_orig, pchan_mtx_final);
+ mul_m4_m4m4(pchan_mtx_final, pchan_mtx_final, flip_mtx);
+ mul_m4_m4m4(pchan_mtx_final, flip_mtx, pchan_mtx_final);
+ if (pid) {
+ mul_m4_m4m4(pchan_mtx_final, pid->offset_mtx, pchan_mtx_final);
+ pid++;
+ }
+ BKE_pchan_apply_mat4(pchan, pchan_mtx_final, false);
+ }
+ }
+ }
+}
+
/* helper for recalcData() - for object transforms, typically in the 3D view */
static void recalcData_objects(TransInfo *t)
{
@@ -975,12 +1018,22 @@ static void recalcData_objects(TransInfo *t)
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
Object *ob = tc->poseobj;
bArmature *arm = ob->data;
- if (arm->flag & ARM_MIRROR_EDIT) {
- if (t->state != TRANS_CANCEL) {
- ED_armature_edit_transform_mirror_update(ob);
+ if (ob->mode == OB_MODE_EDIT) {
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ if (t->state != TRANS_CANCEL) {
+ ED_armature_edit_transform_mirror_update(ob);
+ }
+ else {
+ restoreBones(tc);
+ }
}
- else {
- restoreBones(tc);
+ }
+ else if (ob->mode == OB_MODE_POSE) {
+ /* actually support TFM_BONESIZE in posemode as well */
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ bPose *pose = ob->pose;
+ if (arm->flag & ARM_MIRROR_EDIT || pose->flag & POSE_MIRROR_EDIT) {
+ pose_transform_mirror_update(ob, NULL);
}
}
}
@@ -991,6 +1044,20 @@ static void recalcData_objects(TransInfo *t)
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
Object *ob = tc->poseobj;
bArmature *arm = ob->data;
+ bPose *pose = ob->pose;
+
+ if (pose->flag & POSE_MIRROR_EDIT) {
+ if (t->state != TRANS_CANCEL) {
+ PoseInitData_Mirror *pid = NULL;
+ if (pose->flag & POSE_MIRROR_RELATIVE) {
+ pid = tc->custom.type.data;
+ }
+ pose_transform_mirror_update(ob, pid);
+ }
+ else {
+ restoreMirrorPoseBones(tc);
+ }
+ }
/* if animtimer is running, and the object already has animation data,
* check if the auto-record feature means that we should record 'samples'
@@ -1121,8 +1188,6 @@ static void recalcData_sequencer(TransInfo *t)
seq_prev = seq;
}
- DEG_id_tag_update(&t->scene->id, ID_RECALC_SEQUENCER);
-
flushTransSeq(t);
}
@@ -1311,7 +1376,9 @@ void initTransDataContainers_FromObjectData(TransInfo *t,
BLI_assert((t->flag & T_2D_EDIT) == 0);
copy_m4_m4(tc->mat, objects[i]->obmat);
copy_m3_m4(tc->mat3, tc->mat);
- invert_m4_m4(tc->imat, tc->mat);
+ /* for non-invertible scale matrices, invert_m4_m4_fallback()
+ * can still provide a valid pivot */
+ invert_m4_m4_fallback(tc->imat, tc->mat);
invert_m3_m3(tc->imat3, tc->mat3);
normalize_m3_m3(tc->mat3_unit, tc->mat3);
}
diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c
index 50610f1b3da..35fda39e8dc 100644
--- a/source/blender/editors/transform/transform_gizmo_3d.c
+++ b/source/blender/editors/transform/transform_gizmo_3d.c
@@ -1762,6 +1762,15 @@ static void WIDGETGROUP_gizmo_refresh(const bContext *C, wmGizmoGroup *gzgroup)
}
}
MAN_ITER_AXES_END;
+
+ /* Ensure rotate disks don't overlap scale arrows, especially in ortho view. */
+ float rotate_select_bias = 0.0f;
+ if ((ggd->twtype & V3D_GIZMO_SHOW_OBJECT_SCALE) && ggd->twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) {
+ rotate_select_bias = -2.0f;
+ }
+ for (int i = MAN_AXIS_RANGE_ROT_START; i < MAN_AXIS_RANGE_ROT_END; i++) {
+ ggd->gizmos[i]->select_bias = rotate_select_bias;
+ }
}
static void WIDGETGROUP_gizmo_message_subscribe(const bContext *C,
diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt
index 3b49784d5eb..0564cb07897 100644
--- a/source/blender/editors/util/CMakeLists.txt
+++ b/source/blender/editors/util/CMakeLists.txt
@@ -84,6 +84,7 @@ set(SRC
../include/ED_sound.h
../include/ED_space_api.h
../include/ED_text.h
+ ../include/ED_time_scrub_ui.h
../include/ED_transform.h
../include/ED_transform_snap_object_context.h
../include/ED_transverts.h
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index 804b9c22104..3a5aead3d44 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -170,6 +170,7 @@ static void uvedit_get_batches(Object *ob,
const bool draw_stretch = (sima->flag & SI_DRAW_STRETCH) != 0;
const bool draw_faces = (sima->flag & SI_NO_DRAWFACES) == 0;
+ DRW_mesh_batch_cache_validate(ob->data);
*edges = DRW_mesh_batch_cache_get_edituv_edges(ob->data);
*verts = DRW_mesh_batch_cache_get_edituv_verts(ob->data);
@@ -206,6 +207,7 @@ static void draw_uvs_shadow(SpaceImage *UNUSED(sima),
float col[4];
UI_GetThemeColor4fv(TH_UV_SHADOW, col);
+ DRW_mesh_batch_cache_validate(me);
GPUBatch *edges = DRW_mesh_batch_cache_get_uv_edges(me);
DRW_mesh_batch_cache_create_requested(eval_ob, me, scene->toolsettings, false, false);
@@ -228,6 +230,7 @@ static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph)
return;
}
+ DRW_mesh_batch_cache_validate(me);
GPUBatch *geom = DRW_mesh_batch_cache_get_uv_edges(me);
DRW_mesh_batch_cache_create_requested(eval_ob, me, scene->toolsettings, false, false);
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 85393925802..717bc347cf7 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -386,6 +386,10 @@ static ParamHandle *construct_param_handle_multi(Scene *scene,
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ if (cd_loop_uv_offset == -1) {
+ continue;
+ }
+
BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
if ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) ||