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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/armature/CMakeLists.txt1
-rw-r--r--source/blender/editors/armature/pose_slide.c454
-rw-r--r--source/blender/editors/gpencil/annotate_paint.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_add_blank.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_add_lineart.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_add_monkey.c4
-rw-r--r--source/blender/editors/gpencil/gpencil_add_stroke.c4
-rw-r--r--source/blender/editors/gpencil/gpencil_convert.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c210
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c27
-rw-r--r--source/blender/editors/gpencil/gpencil_fill.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h1
-rw-r--r--source/blender/editors/gpencil/gpencil_ops.c1
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c10
-rw-r--r--source/blender/editors/gpencil/gpencil_primitive.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_trace_ops.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c38
-rw-r--r--source/blender/editors/include/ED_gpencil.h2
-rw-r--r--source/blender/editors/include/ED_object.h1
-rw-r--r--source/blender/editors/include/ED_screen.h6
-rw-r--r--source/blender/editors/interface/interface.c8
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c11
-rw-r--r--source/blender/editors/interface/interface_handlers.c283
-rw-r--r--source/blender/editors/interface/interface_intern.h1
-rw-r--r--source/blender/editors/interface/interface_widgets.c35
-rw-r--r--source/blender/editors/io/io_alembic.c8
-rw-r--r--source/blender/editors/object/CMakeLists.txt2
-rw-r--r--source/blender/editors/object/object_add.c61
-rw-r--r--source/blender/editors/object/object_bake_api.c129
-rw-r--r--source/blender/editors/object/object_edit.c24
-rw-r--r--source/blender/editors/object/object_modes.c71
-rw-r--r--source/blender/editors/object/object_modifier.c5
-rw-r--r--source/blender/editors/object/object_relations.c2
-rw-r--r--source/blender/editors/physics/particle_edit.c9
-rw-r--r--source/blender/editors/physics/rigidbody_object.c23
-rw-r--r--source/blender/editors/render/render_preview.c12
-rw-r--r--source/blender/editors/screen/area.c21
-rw-r--r--source/blender/editors/screen/screen_draw.c32
-rw-r--r--source/blender/editors/screen/screen_edit.c115
-rw-r--r--source/blender/editors/screen/screen_geometry.c28
-rw-r--r--source/blender/editors/screen/screen_intern.h42
-rw-r--r--source/blender/editors/screen/screen_ops.c165
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c24
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h2
-rw-r--r--source/blender/editors/sculpt_paint/paint_ops.c9
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c6
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c6
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_expand.c49
-rw-r--r--source/blender/editors/space_buttons/CMakeLists.txt2
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c3
-rw-r--r--source/blender/editors/space_buttons/buttons_intern.h2
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c50
-rw-r--r--source/blender/editors/space_clip/tracking_ops_track.c26
-rw-r--r--source/blender/editors/space_file/file_draw.c9
-rw-r--r--source/blender/editors/space_file/filelist.c88
-rw-r--r--source/blender/editors/space_nla/nla_draw.c2
-rw-r--r--source/blender/editors/space_node/drawnode.c18
-rw-r--r--source/blender/editors/space_node/node_edit.c4
-rw-r--r--source/blender/editors/space_node/node_relationships.c69
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c4
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c27
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c37
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c89
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c15
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c14
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_ruler.c2
-rw-r--r--source/blender/editors/transform/transform.c23
-rw-r--r--source/blender/editors/transform/transform.h9
-rw-r--r--source/blender/editors/transform/transform_constraints.c9
-rw-r--r--source/blender/editors/transform/transform_convert.c63
-rw-r--r--source/blender/editors/transform/transform_convert_sequencer.c4
-rw-r--r--source/blender/editors/transform/transform_generics.c23
-rw-r--r--source/blender/editors/transform/transform_mode.c35
-rw-r--r--source/blender/editors/transform/transform_mode.h1
-rw-r--r--source/blender/editors/transform/transform_mode_edge_rotate_normal.c2
-rw-r--r--source/blender/editors/transform/transform_mode_resize.c2
-rw-r--r--source/blender/editors/transform/transform_mode_rotate.c2
-rw-r--r--source/blender/editors/transform/transform_mode_shear.c2
-rw-r--r--source/blender/editors/transform/transform_mode_translate.c2
-rw-r--r--source/blender/editors/transform/transform_orientations.c4
80 files changed, 1837 insertions, 761 deletions
diff --git a/source/blender/editors/armature/CMakeLists.txt b/source/blender/editors/armature/CMakeLists.txt
index 98c050950be..0030e78002b 100644
--- a/source/blender/editors/armature/CMakeLists.txt
+++ b/source/blender/editors/armature/CMakeLists.txt
@@ -17,6 +17,7 @@
set(INC
../include
+ ../../blenfont
../../blenkernel
../../blenlib
../../blentranslation
diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c
index 93d36abe792..f7b54b79601 100644
--- a/source/blender/editors/armature/pose_slide.c
+++ b/source/blender/editors/armature/pose_slide.c
@@ -33,6 +33,7 @@
#include "DNA_armature_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DNA_vec_types.h"
#include "BKE_fcurve.h"
#include "BKE_nla.h"
@@ -41,6 +42,7 @@
#include "BKE_layer.h"
#include "BKE_object.h"
#include "BKE_report.h"
+#include "BKE_screen.h"
#include "BKE_unit.h"
#include "RNA_access.h"
@@ -50,15 +52,28 @@
#include "WM_types.h"
#include "UI_interface.h"
+#include "UI_resources.h"
#include "ED_armature.h"
#include "ED_keyframes_draw.h"
#include "ED_markers.h"
#include "ED_numinput.h"
#include "ED_screen.h"
+#include "ED_space_api.h"
+
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
+#include "GPU_state.h"
#include "armature_intern.h"
+#include "BLF_api.h"
+
+/* Pixel distance from 0% to 100%. */
+#define SLIDE_PIXEL_DISTANCE (300 * U.pixelsize)
+#define OVERSHOOT_RANGE_DELTA 0.2f
+
/* **************************************************** */
/* == POSE 'SLIDING' TOOLS ==
*
@@ -110,15 +125,36 @@ typedef struct tPoseSlideOp {
/** unused for now, but can later get used for storing runtime settings.... */
short flag;
+ /* Store overlay settings when invoking the operator. Bones will be temporarily hidden. */
+ int overlay_flag;
+
/** which transforms/channels are affected (ePoseSlide_Channels) */
short channels;
/** axis-limits for transforms (ePoseSlide_AxisLock) */
short axislock;
- /** 0-1 value for determining the influence of whatever is relevant */
+ /* Allow overshoot or clamp between 0% and 100%. */
+ bool overshoot;
+
+ /* Reduces percentage delta from mouse movement. */
+ bool precision;
+
+ /* Move percentage in 10% steps. */
+ bool increments;
+
+ /* Draw callback handler. */
+ void *draw_handle;
+
+ /* Accumulative, unclamped and unrounded percentage. */
+ float raw_percentage;
+
+ /* 0-1 value for determining the influence of whatever is relevant. */
float percentage;
- /** numeric input */
+ /* Last cursor position in screen space used for mouse movement delta calculation. */
+ int last_cursor_x;
+
+ /* Numeric input. */
NumInput num;
struct tPoseSlideObject *ob_data_array;
@@ -187,6 +223,240 @@ static const EnumPropertyItem prop_axis_lock_types[] = {
/* ------------------------------------ */
+static void draw_overshoot_triangle(const uint8_t color[4],
+ const bool facing_right,
+ const float x,
+ const float y)
+{
+ const uint shdr_pos_2d = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ GPU_blend(GPU_BLEND_ALPHA);
+ GPU_polygon_smooth(true);
+ immUniformColor3ubvAlpha(color, 225);
+ const float triangle_side_length = facing_right ? 6 * U.pixelsize : -6 * U.pixelsize;
+ const float triangle_offset = facing_right ? 2 * U.pixelsize : -2 * U.pixelsize;
+
+ immBegin(GPU_PRIM_TRIS, 3);
+ immVertex2f(shdr_pos_2d, x + triangle_offset + triangle_side_length, y);
+ immVertex2f(shdr_pos_2d, x + triangle_offset, y + triangle_side_length / 2);
+ immVertex2f(shdr_pos_2d, x + triangle_offset, y - triangle_side_length / 2);
+ immEnd();
+
+ GPU_polygon_smooth(false);
+ GPU_blend(GPU_BLEND_NONE);
+ immUnbindProgram();
+}
+
+static void draw_ticks(const float start_percentage,
+ const float end_percentage,
+ const struct vec2f line_start,
+ const float base_tick_height,
+ const float line_width,
+ const uint8_t color_overshoot[4],
+ const uint8_t color_line[4])
+{
+ /* Use percentage represented as 0-100 int to avoid floating point precision problems. */
+ const int tick_increment = 10;
+
+ /* Round initial_tick_percentage up to the next tick_increment. */
+ int tick_percentage = ceil((start_percentage * 100) / tick_increment) * tick_increment;
+ float tick_height = base_tick_height;
+
+ while (tick_percentage <= (int)(end_percentage * 100)) {
+ /* Different ticks have different heights. Multiples of 100% are the tallest, 50% is a bit
+ * smaller and the rest is the minimum size. */
+ if (tick_percentage % 100 == 0) {
+ tick_height = base_tick_height;
+ }
+ else if (tick_percentage % 50 == 0) {
+ tick_height = base_tick_height * 0.8;
+ }
+ else {
+ tick_height = base_tick_height * 0.5;
+ }
+
+ const float x = line_start.x +
+ (((float)tick_percentage / 100) - start_percentage) * SLIDE_PIXEL_DISTANCE;
+ const struct rctf tick_rect = {.xmin = x - (line_width / 2),
+ .xmax = x + (line_width / 2),
+ .ymin = line_start.y - (tick_height / 2),
+ .ymax = line_start.y + (tick_height / 2)};
+
+ if (tick_percentage < 0 || tick_percentage > 100) {
+ UI_draw_roundbox_3ub_alpha(&tick_rect, true, 1, color_overshoot, 255);
+ }
+ else {
+ UI_draw_roundbox_3ub_alpha(&tick_rect, true, 1, color_line, 255);
+ }
+ tick_percentage += tick_increment;
+ }
+}
+
+static void draw_main_line(const struct rctf main_line_rect,
+ const float percentage,
+ const bool overshoot,
+ const uint8_t color_overshoot[4],
+ const uint8_t color_line[4])
+{
+ if (overshoot) {
+ /* In overshoot mode, draw the 0-100% range differently to provide a visual reference. */
+ const float line_zero_percent = main_line_rect.xmin -
+ ((percentage - 0.5f - OVERSHOOT_RANGE_DELTA) *
+ SLIDE_PIXEL_DISTANCE);
+
+ const float clamped_line_zero_percent = clamp_f(
+ line_zero_percent, main_line_rect.xmin, main_line_rect.xmax);
+ const float clamped_line_hundred_percent = clamp_f(
+ line_zero_percent + SLIDE_PIXEL_DISTANCE, main_line_rect.xmin, main_line_rect.xmax);
+
+ const struct rctf left_overshoot_line_rect = {.xmin = main_line_rect.xmin,
+ .xmax = clamped_line_zero_percent,
+ .ymin = main_line_rect.ymin,
+ .ymax = main_line_rect.ymax};
+ const struct rctf right_overshoot_line_rect = {.xmin = clamped_line_hundred_percent,
+ .xmax = main_line_rect.xmax,
+ .ymin = main_line_rect.ymin,
+ .ymax = main_line_rect.ymax};
+ UI_draw_roundbox_3ub_alpha(&left_overshoot_line_rect, true, 0, color_overshoot, 255);
+ UI_draw_roundbox_3ub_alpha(&right_overshoot_line_rect, true, 0, color_overshoot, 255);
+
+ const struct rctf non_overshoot_line_rect = {.xmin = clamped_line_zero_percent,
+ .xmax = clamped_line_hundred_percent,
+ .ymin = main_line_rect.ymin,
+ .ymax = main_line_rect.ymax};
+ UI_draw_roundbox_3ub_alpha(&non_overshoot_line_rect, true, 0, color_line, 255);
+ }
+ else {
+ UI_draw_roundbox_3ub_alpha(&main_line_rect, true, 0, color_line, 255);
+ }
+}
+
+static void draw_backdrop(const int fontid,
+ const struct rctf main_line_rect,
+ const float color_bg[4],
+ const short region_y_size,
+ const float base_tick_height)
+{
+ float string_pixel_size[2];
+ const char *percentage_placeholder = "000%%";
+ BLF_width_and_height(fontid,
+ percentage_placeholder,
+ sizeof(percentage_placeholder),
+ &string_pixel_size[0],
+ &string_pixel_size[1]);
+ const struct vec2f pad = {.x = (region_y_size - base_tick_height) / 2, .y = 2.0f * U.pixelsize};
+ const struct rctf backdrop_rect = {.xmin = main_line_rect.xmin - string_pixel_size[0] - pad.x,
+ .xmax = main_line_rect.xmax + pad.x,
+ .ymin = pad.y,
+ .ymax = region_y_size - pad.y};
+ UI_draw_roundbox_aa(&backdrop_rect, true, 4.0f, color_bg);
+}
+
+/* Draw an on screen Slider for a Pose Slide Operator. */
+static void pose_slide_draw_2d_slider(const struct bContext *UNUSED(C), ARegion *region, void *arg)
+{
+ tPoseSlideOp *pso = arg;
+
+ /* Only draw in region from which the Operator was started. */
+ if (region != pso->region) {
+ return;
+ }
+
+ uint8_t color_text[4];
+ uint8_t color_line[4];
+ uint8_t color_handle[4];
+ uint8_t color_overshoot[4];
+ float color_bg[4];
+
+ /* Get theme colors. */
+ UI_GetThemeColor4ubv(TH_TEXT, color_text);
+ UI_GetThemeColor4ubv(TH_TEXT, color_line);
+ UI_GetThemeColor4ubv(TH_TEXT, color_overshoot);
+ UI_GetThemeColor4ubv(TH_ACTIVE, color_handle);
+ UI_GetThemeColor3fv(TH_BACK, color_bg);
+
+ color_bg[3] = 0.5f;
+ color_overshoot[0] = color_overshoot[0] * 0.7;
+ color_overshoot[1] = color_overshoot[1] * 0.7;
+ color_overshoot[2] = color_overshoot[2] * 0.7;
+
+ /* Get the default font. */
+ const uiStyle *style = UI_style_get();
+ const uiFontStyle *fstyle = &style->widget;
+ const int fontid = fstyle->uifont_id;
+ BLF_color3ubv(fontid, color_text);
+ BLF_rotation(fontid, 0.0f);
+
+ const float line_width = 1.5 * U.pixelsize;
+ const float base_tick_height = 12.0 * U.pixelsize;
+ const float line_y = region->winy / 2;
+
+ struct rctf main_line_rect = {.xmin = (region->winx / 2) - (SLIDE_PIXEL_DISTANCE / 2),
+ .xmax = (region->winx / 2) + (SLIDE_PIXEL_DISTANCE / 2),
+ .ymin = line_y - line_width / 2,
+ .ymax = line_y + line_width / 2};
+ float line_start_percentage = 0;
+ int handle_pos_x = main_line_rect.xmin + SLIDE_PIXEL_DISTANCE * pso->percentage;
+
+ if (pso->overshoot) {
+ main_line_rect.xmin = main_line_rect.xmin - SLIDE_PIXEL_DISTANCE * OVERSHOOT_RANGE_DELTA;
+ main_line_rect.xmax = main_line_rect.xmax + SLIDE_PIXEL_DISTANCE * OVERSHOOT_RANGE_DELTA;
+ line_start_percentage = pso->percentage - 0.5f - OVERSHOOT_RANGE_DELTA;
+ handle_pos_x = region->winx / 2;
+ }
+
+ draw_backdrop(fontid, main_line_rect, color_bg, pso->region->winy, base_tick_height);
+
+ draw_main_line(main_line_rect, pso->percentage, pso->overshoot, color_overshoot, color_line);
+
+ const float percentage_range = pso->overshoot ? 1 + OVERSHOOT_RANGE_DELTA * 2 : 1;
+ const struct vec2f line_start_position = {.x = main_line_rect.xmin, .y = line_y};
+ draw_ticks(line_start_percentage,
+ line_start_percentage + percentage_range,
+ line_start_position,
+ base_tick_height,
+ line_width,
+ color_overshoot,
+ color_line);
+
+ /* Draw triangles at the ends of the line in overshoot mode to indicate direction of 0-100%
+ * range.*/
+ if (pso->overshoot) {
+ if (pso->percentage > 1 + OVERSHOOT_RANGE_DELTA + 0.5) {
+ draw_overshoot_triangle(color_line, false, main_line_rect.xmin, line_y);
+ }
+ if (pso->percentage < 0 - OVERSHOOT_RANGE_DELTA - 0.5) {
+ draw_overshoot_triangle(color_line, true, main_line_rect.xmax, line_y);
+ }
+ }
+
+ char percentage_string[256];
+
+ /* Draw handle indicating current percentage. */
+ const struct rctf handle_rect = {.xmin = handle_pos_x - (line_width),
+ .xmax = handle_pos_x + (line_width),
+ .ymin = line_y - (base_tick_height / 2),
+ .ymax = line_y + (base_tick_height / 2)};
+
+ UI_draw_roundbox_3ub_alpha(&handle_rect, true, 1, color_handle, 255);
+ BLI_snprintf(percentage_string, sizeof(percentage_string), "%.0f%%", pso->percentage * 100);
+
+ /* Draw percentage string. */
+ float percentage_pixel_size[2];
+ BLF_width_and_height(fontid,
+ percentage_string,
+ sizeof(percentage_string),
+ &percentage_pixel_size[0],
+ &percentage_pixel_size[1]);
+
+ BLF_position(fontid,
+ main_line_rect.xmin - 24.0 * U.pixelsize - percentage_pixel_size[0] / 2,
+ (region->winy / 2) - percentage_pixel_size[1] / 2,
+ 0.0f);
+ BLF_draw(fontid, percentage_string, sizeof(percentage_string));
+}
+
/* operator init */
static int pose_slide_init(bContext *C, wmOperator *op, ePoseSlide_Modes mode)
{
@@ -205,6 +475,7 @@ static int pose_slide_init(bContext *C, wmOperator *op, ePoseSlide_Modes mode)
/* set range info from property values - these may get overridden for the invoke() */
pso->percentage = RNA_float_get(op->ptr, "percentage");
+ pso->raw_percentage = pso->percentage;
pso->prevFrame = RNA_int_get(op->ptr, "prev_frame");
pso->nextFrame = RNA_int_get(op->ptr, "next_frame");
@@ -257,6 +528,14 @@ static int pose_slide_init(bContext *C, wmOperator *op, ePoseSlide_Modes mode)
pso->num.val_flag[0] |= NUM_NO_NEGATIVE;
pso->num.unit_type[0] = B_UNIT_NONE; /* percentages don't have any units... */
+ /* Register UI drawing callback. */
+ ARegion *region_header = BKE_area_find_region_type(pso->area, RGN_TYPE_HEADER);
+ if (region_header != NULL) {
+ pso->region = region_header;
+ pso->draw_handle = ED_region_draw_cb_activate(
+ region_header->type, pose_slide_draw_2d_slider, pso, REGION_DRAW_POST_PIXEL);
+ }
+
/* return status is whether we've got all the data we were requested to get */
return 1;
}
@@ -266,6 +545,13 @@ static void pose_slide_exit(wmOperator *op)
{
tPoseSlideOp *pso = op->customdata;
+ /* Hide Bone Overlay. */
+ View3D *v3d = pso->area->spacedata.first;
+ v3d->overlay.flag = pso->overlay_flag;
+
+ /* Remove UI drawing callback. */
+ ED_region_draw_cb_exit(pso->region->type, pso->draw_handle);
+
/* if data exists, clear its data and exit */
if (pso) {
/* free the temp pchan links and their data */
@@ -602,7 +888,7 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
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 */
+ /* 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)) ||
@@ -621,7 +907,7 @@ static void pose_slide_rest_pose_apply_vec3(tPoseSlideOp *pso, float vec[3], flo
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 */
+ /* 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 */
@@ -789,14 +1075,18 @@ static void pose_slide_reset(tPoseSlideOp *pso)
/* ------------------------------------ */
-/* draw percentage indicator in header */
+/* Draw percentage indicator in workspace footer. */
/* TODO: Include hints about locks here... */
-static void pose_slide_draw_status(tPoseSlideOp *pso)
+static void pose_slide_draw_status(bContext *C, tPoseSlideOp *pso)
{
char status_str[UI_MAX_DRAW_STR];
char limits_str[UI_MAX_DRAW_STR];
char axis_str[50];
char mode_str[32];
+ char overshoot_str[50];
+ char precision_str[50];
+ char increments_str[50];
+ char bone_vis_str[50];
switch (pso->mode) {
case POSESLIDE_PUSH:
@@ -871,25 +1161,51 @@ static void pose_slide_draw_status(tPoseSlideOp *pso)
break;
}
+ if (pso->overshoot) {
+ BLI_strncpy(overshoot_str, TIP_("[E] - Disable overshoot"), sizeof(overshoot_str));
+ }
+ else {
+ BLI_strncpy(overshoot_str, TIP_("E - Enable overshoot"), sizeof(overshoot_str));
+ }
+
+ if (pso->precision) {
+ BLI_strncpy(precision_str, TIP_("[Shift] - Precision active"), sizeof(precision_str));
+ }
+ else {
+ BLI_strncpy(precision_str, TIP_("Shift - Hold for precision"), sizeof(precision_str));
+ }
+
+ if (pso->increments) {
+ BLI_strncpy(increments_str, TIP_("[Ctrl] - Increments active"), sizeof(increments_str));
+ }
+ else {
+ BLI_strncpy(increments_str, TIP_("Ctrl - Hold for 10% increments"), sizeof(increments_str));
+ }
+
+ BLI_strncpy(bone_vis_str, TIP_("[H] - Toggle bone visibility"), sizeof(increments_str));
+
if (hasNumInput(&pso->num)) {
Scene *scene = pso->scene;
- char str_ofs[NUM_STR_REP_LEN];
+ char str_offs[NUM_STR_REP_LEN];
- outputNumInput(&pso->num, str_ofs, &scene->unit);
+ outputNumInput(&pso->num, str_offs, &scene->unit);
- BLI_snprintf(
- status_str, sizeof(status_str), "%s: %s | %s", mode_str, str_ofs, limits_str);
+ BLI_snprintf(status_str, sizeof(status_str), "%s: %s | %s", mode_str, str_offs, limits_str);
}
else {
BLI_snprintf(status_str,
sizeof(status_str),
- "%s: %d %% | %s",
+ "%s: %s | %s | %s | %s | %s",
mode_str,
- (int)(pso->percentage * 100.0f),
- limits_str);
+ limits_str,
+ overshoot_str,
+ precision_str,
+ increments_str,
+ bone_vis_str);
}
- ED_area_status_text(pso->area, status_str);
+ ED_workspace_status_text(C, status_str);
+ ED_area_status_text(pso->area, "");
}
/* common code for invoke() methods */
@@ -975,21 +1291,40 @@ static int pose_slide_invoke_common(bContext *C, wmOperator *op, tPoseSlideOp *p
WM_cursor_modal_set(win, WM_CURSOR_EW_SCROLL);
/* header print */
- pose_slide_draw_status(pso);
+ pose_slide_draw_status(C, pso);
/* add a modal handler for this operator */
WM_event_add_modal_handler(C, op);
+
+ /* Hide Bone Overlay. */
+ View3D *v3d = pso->area->spacedata.first;
+ pso->overlay_flag = v3d->overlay.flag;
+ v3d->overlay.flag |= V3D_OVERLAY_HIDE_BONES;
+
return OPERATOR_RUNNING_MODAL;
}
-/* calculate percentage based on position of mouse (we only use x-axis for now.
- * since this is more convenient for users to do), and store new percentage value
+/* Calculate percentage based on mouse movement, clamp or round to increments if
+ * enabled by the user. Store the new percentage value.
*/
static void pose_slide_mouse_update_percentage(tPoseSlideOp *pso,
wmOperator *op,
const wmEvent *event)
{
- pso->percentage = (event->x - pso->region->winrct.xmin) / ((float)pso->region->winx);
+ const float percentage_delta = (event->x - pso->last_cursor_x) / ((float)(SLIDE_PIXEL_DISTANCE));
+ /* Reduced percentage delta in precision mode (shift held). */
+ pso->raw_percentage += pso->precision ? (percentage_delta / 8) : percentage_delta;
+ pso->percentage = pso->raw_percentage;
+ pso->last_cursor_x = event->x;
+
+ if (!pso->overshoot) {
+ pso->percentage = clamp_f(pso->percentage, 0, 1);
+ }
+
+ if (pso->increments) {
+ pso->percentage = round(pso->percentage * 10) / 10;
+ }
+
RNA_float_set(op->ptr, "percentage", pso->percentage);
}
@@ -1056,9 +1391,13 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
case EVT_PADENTER: {
if (event->val == KM_PRESS) {
/* return to normal cursor and header status */
+ ED_workspace_status_text(C, NULL);
ED_area_status_text(pso->area, NULL);
WM_cursor_modal_restore(win);
+ /* Depsgraph updates + redraws. Redraw needed to remove UI. */
+ pose_slide_refresh(C, pso);
+
/* insert keyframes as required... */
pose_slide_autoKeyframe(C, pso);
pose_slide_exit(op);
@@ -1073,13 +1412,14 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
case RIGHTMOUSE: {
if (event->val == KM_PRESS) {
/* return to normal cursor and header status */
+ ED_workspace_status_text(C, NULL);
ED_area_status_text(pso->area, NULL);
WM_cursor_modal_restore(win);
/* reset transforms back to original state */
pose_slide_reset(pso);
- /* depsgraph updates + redraws */
+ /* Depsgraph updates + redraws.*/
pose_slide_refresh(C, pso);
/* clean up temp data */
@@ -1178,10 +1518,58 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
}
+ /* Overshoot. */
+ case EVT_EKEY: {
+ pso->overshoot = !pso->overshoot;
+ do_pose_update = true;
+ break;
+ }
+
+ /* Precision mode. */
+ case EVT_LEFTSHIFTKEY:
+ case EVT_RIGHTSHIFTKEY: {
+ pso->precision = true;
+ do_pose_update = true;
+ break;
+ }
+
+ /* Increments mode. */
+ case EVT_LEFTCTRLKEY:
+ case EVT_RIGHTCTRLKEY: {
+ pso->increments = true;
+ do_pose_update = true;
+ break;
+ }
+
+ /* Toggle Bone visibility. */
+ case EVT_HKEY: {
+ View3D *v3d = pso->area->spacedata.first;
+ v3d->overlay.flag ^= V3D_OVERLAY_HIDE_BONES;
+ }
+
default: /* Some other unhandled key... */
break;
}
}
+ /* Precision and stepping only active while button is held. */
+ else if (event->val == KM_RELEASE) {
+ switch (event->type) {
+ case EVT_LEFTSHIFTKEY:
+ case EVT_RIGHTSHIFTKEY: {
+ pso->precision = false;
+ do_pose_update = true;
+ break;
+ }
+ case EVT_LEFTCTRLKEY:
+ case EVT_RIGHTCTRLKEY: {
+ pso->increments = false;
+ do_pose_update = true;
+ break;
+ }
+ default:
+ break;
+ }
+ }
else {
/* unhandled event - maybe it was some view manipulation? */
/* allow to pass through */
@@ -1193,8 +1581,10 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* Perform pose updates - in response to some user action
* (e.g. pressing a key or moving the mouse). */
if (do_pose_update) {
+ pose_slide_mouse_update_percentage(pso, op, event);
+
/* update percentage indicator in header */
- pose_slide_draw_status(pso);
+ pose_slide_draw_status(C, pso);
/* reset transforms (to avoid accumulation errors) */
pose_slide_reset(pso);
@@ -1247,11 +1637,11 @@ static void pose_slide_opdef_properties(wmOperatorType *ot)
PropertyRNA *prop;
prop = RNA_def_float_factor(ot->srna,
- "factor",
+ "percentage",
0.5f,
0.0f,
1.0f,
- "Factor",
+ "Percentage",
"Weighting factor for which keyframe is favored more",
0.0,
1.0);
@@ -1310,6 +1700,8 @@ static int pose_slide_push_invoke(bContext *C, wmOperator *op, const wmEvent *ev
pso = op->customdata;
+ pso->last_cursor_x = event->x;
+
/* Initialize percentage so that it won't pop on first mouse move. */
pose_slide_mouse_update_percentage(pso, op, event);
@@ -1349,7 +1741,7 @@ void POSE_OT_push(wmOperatorType *ot)
ot->poll = ED_operator_posemode;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR_X;
/* Properties */
pose_slide_opdef_properties(ot);
@@ -1370,6 +1762,8 @@ static int pose_slide_relax_invoke(bContext *C, wmOperator *op, const wmEvent *e
pso = op->customdata;
+ pso->last_cursor_x = event->x;
+
/* Initialize percentage so that it won't pop on first mouse move. */
pose_slide_mouse_update_percentage(pso, op, event);
@@ -1409,7 +1803,7 @@ void POSE_OT_relax(wmOperatorType *ot)
ot->poll = ED_operator_posemode;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR_X;
/* Properties */
pose_slide_opdef_properties(ot);
@@ -1429,6 +1823,8 @@ static int pose_slide_push_rest_invoke(bContext *C, wmOperator *op, const wmEven
pso = op->customdata;
+ pso->last_cursor_x = event->x;
+
/* Initialize percentage so that it won't pop on first mouse move. */
pose_slide_mouse_update_percentage(pso, op, event);
@@ -1468,7 +1864,7 @@ void POSE_OT_push_rest(wmOperatorType *ot)
ot->poll = ED_operator_posemode;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR_X;
/* Properties */
pose_slide_opdef_properties(ot);
@@ -1489,6 +1885,8 @@ static int pose_slide_relax_rest_invoke(bContext *C, wmOperator *op, const wmEve
pso = op->customdata;
+ pso->last_cursor_x = event->x;
+
/* Initialize percentage so that it won't pop on first mouse move. */
pose_slide_mouse_update_percentage(pso, op, event);
@@ -1528,7 +1926,7 @@ void POSE_OT_relax_rest(wmOperatorType *ot)
ot->poll = ED_operator_posemode;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR_X;
/* Properties */
pose_slide_opdef_properties(ot);
@@ -1549,6 +1947,8 @@ static int pose_slide_breakdown_invoke(bContext *C, wmOperator *op, const wmEven
pso = op->customdata;
+ pso->last_cursor_x = event->x;
+
/* Initialize percentage so that it won't pop on first mouse move. */
pose_slide_mouse_update_percentage(pso, op, event);
@@ -1588,7 +1988,7 @@ void POSE_OT_breakdown(wmOperatorType *ot)
ot->poll = ED_operator_posemode;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR_X;
/* Properties */
pose_slide_opdef_properties(ot);
diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c
index 5c40bc8e418..c155587e95a 100644
--- a/source/blender/editors/gpencil/annotate_paint.c
+++ b/source/blender/editors/gpencil/annotate_paint.c
@@ -1548,7 +1548,7 @@ static void annotation_paint_initstroke(tGPsdata *p,
if (p->gpl == NULL) {
/* tag for annotations */
p->gpd->flag |= GP_DATA_ANNOTATIONS;
- p->gpl = BKE_gpencil_layer_addnew(p->gpd, DATA_("Note"), true);
+ p->gpl = BKE_gpencil_layer_addnew(p->gpd, DATA_("Note"), true, false);
if (p->custom_color[3]) {
copy_v3_v3(p->gpl->color, p->custom_color);
diff --git a/source/blender/editors/gpencil/gpencil_add_blank.c b/source/blender/editors/gpencil/gpencil_add_blank.c
index 3bd61d5c88a..3aa16e54597 100644
--- a/source/blender/editors/gpencil/gpencil_add_blank.c
+++ b/source/blender/editors/gpencil/gpencil_add_blank.c
@@ -90,7 +90,7 @@ void ED_gpencil_create_blank(bContext *C, Object *ob, float UNUSED(mat[4][4]))
ob->actcol = color_black + 1;
/* layers */
- bGPDlayer *layer = BKE_gpencil_layer_addnew(gpd, "GP_Layer", true);
+ bGPDlayer *layer = BKE_gpencil_layer_addnew(gpd, "GP_Layer", true, false);
/* frames */
BKE_gpencil_frame_addnew(layer, CFRA);
diff --git a/source/blender/editors/gpencil/gpencil_add_lineart.c b/source/blender/editors/gpencil/gpencil_add_lineart.c
index 6b28c6ec13e..ac0da0ad1db 100644
--- a/source/blender/editors/gpencil/gpencil_add_lineart.c
+++ b/source/blender/editors/gpencil/gpencil_add_lineart.c
@@ -96,7 +96,7 @@ void ED_gpencil_create_lineart(bContext *C, Object *ob)
ob->actcol = color_black + 1;
/* layers */
- bGPDlayer *lines = BKE_gpencil_layer_addnew(gpd, "Lines", true);
+ bGPDlayer *lines = BKE_gpencil_layer_addnew(gpd, "Lines", true, false);
/* frames */
BKE_gpencil_frame_addnew(lines, 0);
diff --git a/source/blender/editors/gpencil/gpencil_add_monkey.c b/source/blender/editors/gpencil/gpencil_add_monkey.c
index 4497d963c6d..d8734c4ae6b 100644
--- a/source/blender/editors/gpencil/gpencil_add_monkey.c
+++ b/source/blender/editors/gpencil/gpencil_add_monkey.c
@@ -837,8 +837,8 @@ void ED_gpencil_create_monkey(bContext *C, Object *ob, float mat[4][4])
/* layers */
/* NOTE: For now, we just add new layers, to make it easier to separate out old/new instances */
- bGPDlayer *Fills = BKE_gpencil_layer_addnew(gpd, "Fills", false);
- bGPDlayer *Lines = BKE_gpencil_layer_addnew(gpd, "Lines", true);
+ bGPDlayer *Fills = BKE_gpencil_layer_addnew(gpd, "Fills", false, false);
+ bGPDlayer *Lines = BKE_gpencil_layer_addnew(gpd, "Lines", true, false);
/* frames */
/* NOTE: No need to check for existing, as this will take care of it for us */
diff --git a/source/blender/editors/gpencil/gpencil_add_stroke.c b/source/blender/editors/gpencil/gpencil_add_stroke.c
index 26237636526..e95496b51ee 100644
--- a/source/blender/editors/gpencil/gpencil_add_stroke.c
+++ b/source/blender/editors/gpencil/gpencil_add_stroke.c
@@ -225,8 +225,8 @@ void ED_gpencil_create_stroke(bContext *C, Object *ob, float mat[4][4])
ob->actcol = color_black + 1;
/* layers */
- bGPDlayer *colors = BKE_gpencil_layer_addnew(gpd, "Colors", false);
- bGPDlayer *lines = BKE_gpencil_layer_addnew(gpd, "Lines", true);
+ bGPDlayer *colors = BKE_gpencil_layer_addnew(gpd, "Colors", false, false);
+ bGPDlayer *lines = BKE_gpencil_layer_addnew(gpd, "Lines", true, false);
/* frames */
bGPDframe *frame_color = BKE_gpencil_frame_addnew(colors, CFRA);
diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c
index ac75ae44c8a..8ab413e907c 100644
--- a/source/blender/editors/gpencil/gpencil_convert.c
+++ b/source/blender/editors/gpencil/gpencil_convert.c
@@ -1857,7 +1857,7 @@ static int image_to_gpencil_exec(bContext *C, wmOperator *op)
/* Add layer and frame. */
bGPdata *gpd = (bGPdata *)ob->data;
- bGPDlayer *gpl = BKE_gpencil_layer_addnew(gpd, "Image Layer", true);
+ bGPDlayer *gpl = BKE_gpencil_layer_addnew(gpd, "Image Layer", true, false);
bGPDframe *gpf = BKE_gpencil_frame_addnew(gpl, CFRA);
done = BKE_gpencil_from_image(sima, gpd, gpf, size, is_mask);
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index c93fcb9eb8c..d9a807d17ab 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -129,7 +129,7 @@ static int gpencil_data_add_exec(bContext *C, wmOperator *op)
gpd->flag |= GP_DATA_ANNOTATIONS;
/* add new layer (i.e. a "note") */
- BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("Note"), true);
+ BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("Note"), true, false);
/* notifiers */
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
@@ -231,7 +231,7 @@ static int gpencil_layer_add_exec(bContext *C, wmOperator *op)
/* mark as annotation */
(*gpd_ptr)->flag |= GP_DATA_ANNOTATIONS;
- BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("Note"), true);
+ BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("Note"), true, false);
gpd = *gpd_ptr;
}
else {
@@ -239,7 +239,7 @@ static int gpencil_layer_add_exec(bContext *C, wmOperator *op)
Object *ob = CTX_data_active_object(C);
if ((ob != NULL) && (ob->type == OB_GPENCIL)) {
gpd = (bGPdata *)ob->data;
- bGPDlayer *gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true);
+ bGPDlayer *gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true, false);
/* Add a new frame to make it visible in Dopesheet. */
if (gpl != NULL) {
gpl->actframe = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_NEW);
@@ -524,7 +524,6 @@ enum {
static bool gpencil_layer_duplicate_object_poll(bContext *C)
{
- ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = CTX_data_active_object(C);
if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
return false;
@@ -537,90 +536,75 @@ static bool gpencil_layer_duplicate_object_poll(bContext *C)
return false;
}
- /* check there are more grease pencil objects */
- LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
- if ((base->object != ob) && (base->object->type == OB_GPENCIL)) {
- return true;
- }
- }
-
- return false;
+ return true;
}
static int gpencil_layer_duplicate_object_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- char name[MAX_ID_NAME - 2];
- RNA_string_get(op->ptr, "object", name);
-
- if (name[0] == '\0') {
- return OPERATOR_CANCELLED;
- }
-
- Object *ob_dst = (Object *)BKE_scene_object_find_by_name(scene, name);
-
- int mode = RNA_enum_get(op->ptr, "mode");
+ const bool only_active = RNA_boolean_get(op->ptr, "only_active");
+ const int mode = RNA_enum_get(op->ptr, "mode");
Object *ob_src = CTX_data_active_object(C);
bGPdata *gpd_src = (bGPdata *)ob_src->data;
- bGPDlayer *gpl_src = BKE_gpencil_layer_active_get(gpd_src);
-
- /* Sanity checks. */
- if (ELEM(NULL, gpd_src, gpl_src, ob_dst)) {
- return OPERATOR_CANCELLED;
- }
- /* Cannot copy itself and check destination type. */
- if ((ob_src == ob_dst) || (ob_dst->type != OB_GPENCIL)) {
- return OPERATOR_CANCELLED;
- }
-
- bGPdata *gpd_dst = (bGPdata *)ob_dst->data;
+ bGPDlayer *gpl_active = BKE_gpencil_layer_active_get(gpd_src);
- /* Create new layer. */
- bGPDlayer *gpl_dst = BKE_gpencil_layer_addnew(gpd_dst, gpl_src->info, true);
- /* Need to copy some variables (not all). */
- gpl_dst->onion_flag = gpl_src->onion_flag;
- gpl_dst->thickness = gpl_src->thickness;
- gpl_dst->line_change = gpl_src->line_change;
- copy_v4_v4(gpl_dst->tintcolor, gpl_src->tintcolor);
- gpl_dst->opacity = gpl_src->opacity;
-
- /* Create all frames. */
- LISTBASE_FOREACH (bGPDframe *, gpf_src, &gpl_src->frames) {
-
- if ((mode == GP_LAYER_COPY_OBJECT_ACT_FRAME) && (gpf_src != gpl_src->actframe)) {
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+ if ((ob == ob_src) || (ob->type != OB_GPENCIL)) {
continue;
}
+ bGPdata *gpd_dst = (bGPdata *)ob->data;
+ LISTBASE_FOREACH_BACKWARD (bGPDlayer *, gpl_src, &gpd_src->layers) {
+ if ((only_active) && (gpl_src != gpl_active)) {
+ continue;
+ }
+ /* Create new layer (adding at head of the list). */
+ bGPDlayer *gpl_dst = BKE_gpencil_layer_addnew(gpd_dst, gpl_src->info, true, true);
+ /* Need to copy some variables (not all). */
+ gpl_dst->onion_flag = gpl_src->onion_flag;
+ gpl_dst->thickness = gpl_src->thickness;
+ gpl_dst->line_change = gpl_src->line_change;
+ copy_v4_v4(gpl_dst->tintcolor, gpl_src->tintcolor);
+ gpl_dst->opacity = gpl_src->opacity;
+
+ /* Create all frames. */
+ LISTBASE_FOREACH (bGPDframe *, gpf_src, &gpl_src->frames) {
+
+ if ((mode == GP_LAYER_COPY_OBJECT_ACT_FRAME) && (gpf_src != gpl_src->actframe)) {
+ continue;
+ }
- /* Create new frame. */
- bGPDframe *gpf_dst = BKE_gpencil_frame_addnew(gpl_dst, gpf_src->framenum);
+ /* Create new frame. */
+ bGPDframe *gpf_dst = BKE_gpencil_frame_addnew(gpl_dst, gpf_src->framenum);
- /* Copy strokes. */
- LISTBASE_FOREACH (bGPDstroke *, gps_src, &gpf_src->strokes) {
+ /* Copy strokes. */
+ LISTBASE_FOREACH (bGPDstroke *, gps_src, &gpf_src->strokes) {
- /* Make copy of source stroke. */
- bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true, true);
+ /* Make copy of source stroke. */
+ bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true, true);
- /* Check if material is in destination object,
- * otherwise add the slot with the material. */
- Material *ma_src = BKE_object_material_get(ob_src, gps_src->mat_nr + 1);
- if (ma_src != NULL) {
- int idx = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma_src);
+ /* Check if material is in destination object,
+ * otherwise add the slot with the material. */
+ Material *ma_src = BKE_object_material_get(ob_src, gps_src->mat_nr + 1);
+ if (ma_src != NULL) {
+ int idx = BKE_gpencil_object_material_ensure(bmain, ob, ma_src);
- /* Reassign the stroke material to the right slot in destination object. */
- gps_dst->mat_nr = idx;
- }
+ /* Reassign the stroke material to the right slot in destination object. */
+ gps_dst->mat_nr = idx;
+ }
- /* Add new stroke to frame. */
- BLI_addtail(&gpf_dst->strokes, gps_dst);
+ /* Add new stroke to frame. */
+ BLI_addtail(&gpf_dst->strokes, gps_dst);
+ }
+ }
}
+ /* notifiers */
+ DEG_id_tag_update(&gpd_dst->id,
+ ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
}
+ CTX_DATA_END;
- /* notifiers */
- DEG_id_tag_update(&gpd_dst->id,
- ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
- DEG_id_tag_update(&ob_dst->id, ID_RECALC_COPY_ON_WRITE);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -628,6 +612,8 @@ static int gpencil_layer_duplicate_object_exec(bContext *C, wmOperator *op)
void GPENCIL_OT_layer_duplicate_object(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
static const EnumPropertyItem copy_mode[] = {
{GP_LAYER_COPY_OBJECT_ALL_FRAME, "ALL", 0, "All Frames", ""},
{GP_LAYER_COPY_OBJECT_ACT_FRAME, "ACTIVE", 0, "Active Frame", ""},
@@ -637,7 +623,7 @@ void GPENCIL_OT_layer_duplicate_object(wmOperatorType *ot)
/* identifiers */
ot->name = "Duplicate Layer to New Object";
ot->idname = "GPENCIL_OT_layer_duplicate_object";
- ot->description = "Make a copy of the active Grease Pencil layer to new object";
+ ot->description = "Make a copy of the active Grease Pencil layer to selected object";
/* callbacks */
ot->exec = gpencil_layer_duplicate_object_exec;
@@ -646,11 +632,14 @@ void GPENCIL_OT_layer_duplicate_object(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- ot->prop = RNA_def_string(
- ot->srna, "object", NULL, MAX_ID_NAME - 2, "Object", "Name of the destination object");
- RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ ot->prop = RNA_def_enum(ot->srna, "mode", copy_mode, GP_LAYER_COPY_OBJECT_ALL_FRAME, "Mode", "");
- RNA_def_enum(ot->srna, "mode", copy_mode, GP_LAYER_COPY_OBJECT_ALL_FRAME, "Mode", "");
+ prop = RNA_def_boolean(ot->srna,
+ "only_active",
+ true,
+ "Only Active",
+ "Copy only active Layer, uncheck to append all layers");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
/* ********************* Duplicate Frame ************************** */
@@ -1443,7 +1432,7 @@ static int gpencil_layer_change_exec(bContext *C, wmOperator *op)
/* Get layer or create new one */
if (layer_num == -1) {
/* Create layer */
- gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true);
+ gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true, false);
}
else {
/* Try to get layer */
@@ -3589,6 +3578,79 @@ void GPENCIL_OT_set_active_material(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/* ********************* Append Materials in a new object ************************** */
+static bool gpencil_materials_copy_to_object_poll(bContext *C)
+{
+ Object *ob = CTX_data_active_object(C);
+ if ((ob == NULL) || (ob->type != OB_GPENCIL)) {
+ return false;
+ }
+ short *totcolp = BKE_object_material_len_p(ob);
+ if (*totcolp == 0) {
+ return false;
+ }
+
+ return true;
+}
+
+static int gpencil_materials_copy_to_object_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ const bool only_active = RNA_boolean_get(op->ptr, "only_active");
+ Object *ob_src = CTX_data_active_object(C);
+ Material *ma_active = BKE_gpencil_material(ob_src, ob_src->actcol);
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+ if ((ob == ob_src) || (ob->type != OB_GPENCIL)) {
+ continue;
+ }
+ /* Duplicate materials. */
+ for (int i = 0; i < ob_src->totcol; i++) {
+ Material *ma_src = BKE_object_material_get(ob_src, i + 1);
+ if (only_active && ma_src != ma_active) {
+ continue;
+ }
+
+ if (ma_src != NULL) {
+ BKE_gpencil_object_material_ensure(bmain, ob, ma_src);
+ }
+ }
+
+ /* notifiers */
+ DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
+ }
+ CTX_DATA_END;
+
+ /* notifiers */
+ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_materials_copy_to_object(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Copy Materials to Selected Object";
+ ot->idname = "GPENCIL_OT_materials_copy_to_object";
+ ot->description = "Append Materials of the active Grease Pencil to other object";
+
+ /* callbacks */
+ ot->exec = gpencil_materials_copy_to_object_exec;
+ ot->poll = gpencil_materials_copy_to_object_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ prop = RNA_def_boolean(ot->srna,
+ "only_active",
+ true,
+ "Only Active",
+ "Append only active material, uncheck to append all materials");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+}
+
/* Parent GPencil object to Lattice */
bool ED_gpencil_add_lattice_modifier(const bContext *C,
ReportList *reports,
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index d90f74fbf4f..e65afa1abff 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -1677,7 +1677,7 @@ static int gpencil_strokes_paste_exec(bContext *C, wmOperator *op)
if (gpl == NULL) {
/* no active layer - let's just create one */
- gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true);
+ gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true, false);
}
else if ((BKE_gpencil_layer_is_editable(gpl) == false) && (type == GP_COPY_TO_ACTIVE)) {
BKE_report(
@@ -1835,7 +1835,7 @@ static int gpencil_move_to_layer_exec(bContext *C, wmOperator *op)
}
else {
/* Create a new layer. */
- target_layer = BKE_gpencil_layer_addnew(gpd, "GP_Layer", true);
+ target_layer = BKE_gpencil_layer_addnew(gpd, "GP_Layer", true, false);
}
if (target_layer == NULL) {
@@ -4544,6 +4544,9 @@ static int gpencil_stroke_separate_exec(bContext *C, wmOperator *op)
eGP_SeparateModes mode = RNA_enum_get(op->ptr, "mode");
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_src);
+ const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd_src);
+
/* sanity checks */
if (ELEM(NULL, gpd_src)) {
return OPERATOR_CANCELLED;
@@ -4554,8 +4557,22 @@ static int gpencil_stroke_separate_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_src);
- const bool is_curve_edit = (bool)GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd_src);
+ /* Cancel if nothing selected. */
+ if (ELEM(mode, GP_SEPARATE_POINT, GP_SEPARATE_STROKE)) {
+ bool has_selected = false;
+ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
+ if (ED_gpencil_layer_has_selected_stroke(gpl, is_multiedit)) {
+ has_selected = true;
+ break;
+ }
+ }
+ CTX_DATA_END;
+
+ if (!has_selected) {
+ BKE_report(op->reports, RPT_ERROR, "Nothing selected");
+ return OPERATOR_CANCELLED;
+ }
+ }
/* Create a new object. */
/* Take into account user preferences for duplicating actions. */
@@ -4600,7 +4617,7 @@ static int gpencil_stroke_separate_exec(bContext *C, wmOperator *op)
if (gps->flag & GP_STROKE_SELECT) {
/* add layer if not created before */
if (gpl_dst == NULL) {
- gpl_dst = BKE_gpencil_layer_addnew(gpd_dst, gpl->info, false);
+ gpl_dst = BKE_gpencil_layer_addnew(gpd_dst, gpl->info, false, false);
}
/* add frame if not created before */
diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c
index 62d64c67b08..f74e211dd65 100644
--- a/source/blender/editors/gpencil/gpencil_fill.c
+++ b/source/blender/editors/gpencil/gpencil_fill.c
@@ -1689,7 +1689,7 @@ static tGPDfill *gpencil_session_init_fill(bContext *C, wmOperator *op)
tgpf->gpd = gpd;
tgpf->gpl = BKE_gpencil_layer_active_get(gpd);
if (tgpf->gpl == NULL) {
- tgpf->gpl = BKE_gpencil_layer_addnew(tgpf->gpd, DATA_("GP_Layer"), true);
+ tgpf->gpl = BKE_gpencil_layer_addnew(tgpf->gpd, DATA_("GP_Layer"), true, false);
}
tgpf->lock_axis = ts->gp_sculpt.lock_axis;
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index 09200125cb7..9f48c81c8f1 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -538,6 +538,7 @@ void GPENCIL_OT_material_lock_unused(struct wmOperatorType *ot);
void GPENCIL_OT_material_select(struct wmOperatorType *ot);
void GPENCIL_OT_material_set(struct wmOperatorType *ot);
void GPENCIL_OT_set_active_material(struct wmOperatorType *ot);
+void GPENCIL_OT_materials_copy_to_object(struct wmOperatorType *ot);
/* convert old 2.7 files to 2.8 */
void GPENCIL_OT_convert_old_files(struct wmOperatorType *ot);
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index 7d454eb3be1..698d784c3b0 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -651,6 +651,7 @@ void ED_operatortypes_gpencil(void)
WM_operatortype_append(GPENCIL_OT_material_to_vertex_color);
WM_operatortype_append(GPENCIL_OT_extract_palette_vertex);
+ WM_operatortype_append(GPENCIL_OT_materials_copy_to_object);
WM_operatortype_append(GPENCIL_OT_transform_fill);
WM_operatortype_append(GPENCIL_OT_reset_transform_fill);
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index d072d8a35df..30d85b09974 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -2120,7 +2120,7 @@ static void gpencil_paint_initstroke(tGPsdata *p,
/* get active layer (or add a new one if non-existent) */
p->gpl = BKE_gpencil_layer_active_get(p->gpd);
if (p->gpl == NULL) {
- p->gpl = BKE_gpencil_layer_addnew(p->gpd, DATA_("GP_Layer"), true);
+ p->gpl = BKE_gpencil_layer_addnew(p->gpd, DATA_("GP_Layer"), true, false);
changed = true;
if (p->custom_color[3]) {
copy_v3_v3(p->gpl->color, p->custom_color);
@@ -3677,14 +3677,6 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
* is essential for ensuring that they can quickly return to that view
*/
}
- else if ((event->type == EVT_BKEY) && (event->val == KM_RELEASE)) {
- /* Add Blank Frame
- * - Since this operator is non-modal, we can just call it here, and keep going...
- * - This operator is especially useful when animating
- */
- WM_operator_name_call(C, "GPENCIL_OT_blank_frame_add", WM_OP_EXEC_DEFAULT, NULL);
- estate = OPERATOR_RUNNING_MODAL;
- }
else if ((!ELEM(p->paintmode, GP_PAINTMODE_ERASER, GP_PAINTMODE_SET_CP))) {
gpencil_guide_event_handling(C, op, event, p);
estate = OPERATOR_RUNNING_MODAL;
diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c
index 3d20e32ed49..1b0a40b1be1 100644
--- a/source/blender/editors/gpencil/gpencil_primitive.c
+++ b/source/blender/editors/gpencil/gpencil_primitive.c
@@ -314,7 +314,7 @@ static void gpencil_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi)
/* if layer doesn't exist, create a new one */
if (gpl == NULL) {
- gpl = BKE_gpencil_layer_addnew(tgpi->gpd, DATA_("Primitives"), true);
+ gpl = BKE_gpencil_layer_addnew(tgpi->gpd, DATA_("Primitives"), true, false);
}
tgpi->gpl = gpl;
diff --git a/source/blender/editors/gpencil/gpencil_trace_ops.c b/source/blender/editors/gpencil/gpencil_trace_ops.c
index d2e5fa3db32..cd75f9313ad 100644
--- a/source/blender/editors/gpencil/gpencil_trace_ops.c
+++ b/source/blender/editors/gpencil/gpencil_trace_ops.c
@@ -207,7 +207,7 @@ static void trace_initialize_job_data(TraceJob *trace_job)
trace_job->gpd = (bGPdata *)trace_job->ob_gpencil->data;
trace_job->gpl = BKE_gpencil_layer_active_get(trace_job->gpd);
if (trace_job->gpl == NULL) {
- trace_job->gpl = BKE_gpencil_layer_addnew(trace_job->gpd, DATA_("Trace"), true);
+ trace_job->gpl = BKE_gpencil_layer_addnew(trace_job->gpd, DATA_("Trace"), true, false);
}
}
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index 8d42024a518..04764587ebe 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -543,6 +543,38 @@ bool gpencil_stroke_inside_circle(const float mval[2], int rad, int x0, int y0,
}
/* ******************************************************** */
+/* Selection Validity Testing */
+
+bool ED_gpencil_frame_has_selected_stroke(const bGPDframe *gpf)
+{
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ if (gps->flag & GP_STROKE_SELECT) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool ED_gpencil_layer_has_selected_stroke(const bGPDlayer *gpl, const bool is_multiedit)
+{
+ bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
+ for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
+ if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
+ if (ED_gpencil_frame_has_selected_stroke(gpf)) {
+ return true;
+ }
+ }
+ /* If not multiedit, exit loop. */
+ if (!is_multiedit) {
+ break;
+ }
+ }
+
+ return false;
+}
+
+/* ******************************************************** */
/* Stroke Validity Testing */
/* Check whether given stroke can be edited given the supplied context */
@@ -1244,7 +1276,6 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph,
}
else {
/* Geometry - Snap to surfaces of visible geometry */
- float ray_start[3];
float ray_normal[3];
/* magic value for initial depth copied from the default
* value of Python's Scene.ray_cast function
@@ -1253,13 +1284,14 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph,
float location[3] = {0.0f, 0.0f, 0.0f};
float normal[3] = {0.0f, 0.0f, 0.0f};
- ED_view3d_win_to_ray(region, xy, &ray_start[0], &ray_normal[0]);
+ ED_view3d_win_to_vector(region, xy, &ray_normal[0]);
+ BLI_assert(gps->flag & GP_STROKE_3DSPACE);
if (ED_transform_snap_object_project_ray(sctx,
depsgraph,
&(const struct SnapObjectParams){
.snap_select = SNAP_ALL,
},
- &ray_start[0],
+ &pt2.x,
&ray_normal[0],
&depth,
&location[0],
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index 1df3d993c39..bad080e1609 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -144,6 +144,8 @@ bool ED_gpencil_data_owner_is_annotation(struct PointerRNA *owner_ptr);
bool ED_gpencil_has_keyframe_v3d(struct Scene *scene, struct Object *ob, int cfra);
/* ----------- Stroke Editing Utilities ---------------- */
+bool ED_gpencil_frame_has_selected_stroke(const struct bGPDframe *gpf);
+bool ED_gpencil_layer_has_selected_stroke(const struct bGPDlayer *gpl, const bool is_multiedit);
bool ED_gpencil_stroke_can_use_direct(const struct ScrArea *area, const struct bGPDstroke *gps);
bool ED_gpencil_stroke_can_use(const struct bContext *C, const struct bGPDstroke *gps);
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 8279268bfd0..6f88ab4253a 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -247,6 +247,7 @@ void ED_object_texture_paint_mode_enter(struct bContext *C);
void ED_object_texture_paint_mode_exit_ex(struct Main *bmain, struct Scene *scene, Object *ob);
void ED_object_texture_paint_mode_exit(struct bContext *C);
+bool ED_object_particle_edit_mode_supported(const Object *ob);
void ED_object_particle_edit_mode_enter_ex(struct Depsgraph *depsgraph,
struct Scene *scene,
Object *ob);
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index c46f0f78eb5..bdd7ec571dc 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -200,8 +200,6 @@ ScrArea *ED_screen_areas_iter_next(const bScreen *screen, const ScrArea *area);
/* screens */
void ED_screens_init(struct Main *bmain, struct wmWindowManager *wm);
void ED_screen_draw_edges(struct wmWindow *win);
-void ED_screen_draw_join_highlight(struct ScrArea *sa1, struct ScrArea *sa2);
-void ED_screen_draw_split_preview(struct ScrArea *area, const int dir, const float fac);
void ED_screen_refresh(struct wmWindowManager *wm, struct wmWindow *win);
void ED_screen_ensure_updated(struct wmWindowManager *wm,
struct wmWindow *win,
@@ -450,10 +448,10 @@ enum {
};
/* SCREEN_OT_space_context_cycle direction */
-enum {
+typedef enum eScreenCycle {
SPACE_CONTEXT_CYCLE_PREV,
SPACE_CONTEXT_CYCLE_NEXT,
-};
+} eScreenCycle;
#ifdef __cplusplus
}
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 90d604b3190..a31efefd99c 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -2327,6 +2327,14 @@ bool ui_but_is_float(const uiBut *but)
return false;
}
+PropertyScaleType ui_but_scale_type(const uiBut *but)
+{
+ if (but->rnaprop) {
+ return RNA_property_ui_scale(but->rnaprop);
+ }
+ return PROP_SCALE_LINEAR;
+}
+
bool ui_but_is_bool(const uiBut *but)
{
if (ELEM(but->type,
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
index 178f663ff58..e4f502950ab 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -130,14 +130,19 @@ void eyedropper_draw_cursor_text_region(const struct bContext *C,
const char *name)
{
wmWindow *win = CTX_wm_window(C);
- const int x = win->eventstate->x - region->winrct.xmin;
- const int y = win->eventstate->y - region->winrct.ymin;
+ const int x = win->eventstate->x;
+ const int y = win->eventstate->y;
if ((name[0] == '\0') || (BLI_rcti_isect_pt(&region->winrct, x, y) == false)) {
return;
}
- eyedropper_draw_cursor_text_ex(x, y, name);
+ const int mval[2] = {
+ x - region->winrct.xmin,
+ y - region->winrct.ymin,
+ };
+
+ eyedropper_draw_cursor_text_ex(mval[0], mval[1], name);
}
/**
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 5a254db0eec..282d470c7ea 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -126,6 +126,24 @@
#define UI_MAX_PASSWORD_STR 128
/**
+ * This is a lower limit on the soft minimum of the range.
+ * Usually the derived lower limit from the visible precision is higher,
+ * so this number is the backup minimum.
+ *
+ * Logarithmic scale does not work with a minimum value of zero,
+ * but we want to support it anyway. It is set to 0.5e... for
+ * correct rounding since when the tweaked value is lower than
+ * the log minimum (lower limit), it will snap to 0.
+ */
+#define UI_PROP_SCALE_LOG_MIN 0.5e-8f
+/**
+ * This constant defines an offset for the precision change in
+ * snap rounding, when going to higher values. It is set to
+ * `0.5 - log10(3) = 0.03` to make the switch at `0.3` values.
+ */
+#define UI_PROP_SCALE_LOG_SNAP_OFFSET 0.03f
+
+/**
* When #USER_CONTINUOUS_MOUSE is disabled or tablet input is used,
* Use this as a maximum soft range for mapping cursor motion to the value.
* Otherwise min/max of #FLT_MAX, #INT_MAX cause small adjustments to jump to large numbers.
@@ -477,6 +495,7 @@ static bool ui_do_but_extra_operator_icon(bContext *C,
static void ui_do_but_extra_operator_icons_mousemove(uiBut *but,
uiHandleButtonData *data,
const wmEvent *event);
+static void ui_numedit_begin_set_values(uiBut *but, uiHandleButtonData *data);
#ifdef USE_DRAG_MULTINUM
static void ui_multibut_restore(bContext *C, uiHandleButtonData *data, uiBlock *block);
@@ -3361,6 +3380,8 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data)
if (is_num_but) {
BLI_assert(data->is_str_dynamic == false);
ui_but_convert_to_unit_alt_name(but, data->str, data->maxlen);
+
+ ui_numedit_begin_set_values(but, data);
}
/* won't change from now on */
@@ -3897,6 +3918,14 @@ static void ui_do_but_textedit_select(
/** \name Button Number Editing (various types)
* \{ */
+static void ui_numedit_begin_set_values(uiBut *but, uiHandleButtonData *data)
+{
+ data->startvalue = ui_but_value_get(but);
+ data->origvalue = data->startvalue;
+ data->value = data->origvalue;
+ but->editval = &data->value;
+}
+
static void ui_numedit_begin(uiBut *but, uiHandleButtonData *data)
{
if (but->type == UI_BTYPE_CURVE) {
@@ -3922,19 +3951,21 @@ static void ui_numedit_begin(uiBut *but, uiHandleButtonData *data)
but->editvec = data->vec;
}
else {
- float softrange, softmin, softmax;
+ ui_numedit_begin_set_values(but, data);
- data->startvalue = ui_but_value_get(but);
- data->origvalue = data->startvalue;
- data->value = data->origvalue;
- but->editval = &data->value;
+ float softmin = but->softmin;
+ float softmax = but->softmax;
+ float softrange = softmax - softmin;
+ const PropertyScaleType scale_type = ui_but_scale_type(but);
- softmin = but->softmin;
- softmax = but->softmax;
- softrange = softmax - softmin;
+ float log_min = (scale_type == PROP_SCALE_LOG) ? max_ff(softmin, UI_PROP_SCALE_LOG_MIN) : 0.0f;
if ((but->type == UI_BTYPE_NUM) && (ui_but_is_cursor_warp(but) == false)) {
uiButNumber *number_but = (uiButNumber *)but;
+
+ if (scale_type == PROP_SCALE_LOG) {
+ log_min = max_ff(log_min, powf(10, -number_but->precision) * 0.5f);
+ }
/* Use a minimum so we have a predictable range,
* otherwise some float buttons get a large range. */
const float value_step_float_min = 0.1f;
@@ -3983,7 +4014,31 @@ static void ui_numedit_begin(uiBut *but, uiHandleButtonData *data)
}
}
- data->dragfstart = (softrange == 0.0f) ? 0.0f : ((float)data->value - softmin) / softrange;
+ if (softrange == 0.0f) {
+ data->dragfstart = 0.0f;
+ }
+ else {
+ switch (scale_type) {
+ case PROP_SCALE_LINEAR: {
+ data->dragfstart = ((float)data->value - softmin) / softrange;
+ break;
+ }
+ case PROP_SCALE_LOG: {
+ BLI_assert(log_min != 0.0f);
+ const float base = softmax / log_min;
+ data->dragfstart = logf((float)data->value / log_min) / logf(base);
+ break;
+ }
+ case PROP_SCALE_CUBIC: {
+ const float cubic_min = cube_f(softmin);
+ const float cubic_max = cube_f(softmax);
+ const float cubic_range = cubic_max - cubic_min;
+ const float f = ((float)data->value - softmin) * cubic_range / softrange + cubic_min;
+ data->dragfstart = (cbrtf(f) - softmin) / softrange;
+ break;
+ }
+ }
+ }
data->dragf = data->dragfstart;
data->drag_map_soft_min = softmin;
@@ -4701,6 +4756,7 @@ static float ui_numedit_apply_snapf(
/* pass */
}
else {
+ const PropertyScaleType scale_type = ui_but_scale_type(but);
float softrange = softmax - softmin;
float fac = 1.0f;
@@ -4738,31 +4794,30 @@ static float ui_numedit_apply_snapf(
}
}
- if (snap == SNAP_ON) {
- if (softrange < 2.10f) {
- tempf = roundf(tempf * 10.0f) * 0.1f;
- }
- else if (softrange < 21.0f) {
- tempf = roundf(tempf);
- }
- else {
- tempf = roundf(tempf * 0.1f) * 10.0f;
- }
- }
- else if (snap == SNAP_ON_SMALL) {
- if (softrange < 2.10f) {
- tempf = roundf(tempf * 100.0f) * 0.01f;
- }
- else if (softrange < 21.0f) {
- tempf = roundf(tempf * 10.0f) * 0.1f;
+ BLI_assert(ELEM(snap, SNAP_ON, SNAP_ON_SMALL));
+ switch (scale_type) {
+ case PROP_SCALE_LINEAR:
+ case PROP_SCALE_CUBIC: {
+ const float snap_fac = (snap == SNAP_ON_SMALL ? 0.1f : 1.0f);
+ if (softrange < 2.10f) {
+ tempf = roundf(tempf * 10.0f / snap_fac) * 0.1f * snap_fac;
+ }
+ else if (softrange < 21.0f) {
+ tempf = roundf(tempf / snap_fac) * snap_fac;
+ }
+ else {
+ tempf = roundf(tempf * 0.1f / snap_fac) * 10.0f * snap_fac;
+ }
+ break;
}
- else {
- tempf = roundf(tempf);
+ case PROP_SCALE_LOG: {
+ const float snap_fac = powf(10.0f,
+ roundf(log10f(tempf) + UI_PROP_SCALE_LOG_SNAP_OFFSET) -
+ (snap == SNAP_ON_SMALL ? 2.0f : 1.0f));
+ tempf = roundf(tempf / snap_fac) * snap_fac;
+ break;
}
}
- else {
- BLI_assert(0);
- }
if (fac != 1.0f) {
tempf *= fac;
@@ -4807,6 +4862,7 @@ static bool ui_numedit_but_NUM(uiButNumber *number_but,
int lvalue, temp;
bool changed = false;
const bool is_float = ui_but_is_float(but);
+ const PropertyScaleType scale_type = ui_but_scale_type(but);
/* prevent unwanted drag adjustments, test motion so modifier keys refresh. */
if ((is_motion || data->draglock) && (ui_but_dragedit_update_mval(data, mx) == false)) {
@@ -4818,21 +4874,74 @@ static bool ui_numedit_but_NUM(uiButNumber *number_but,
const float softmax = but->softmax;
const float softrange = softmax - softmin;
+ const float log_min = (scale_type == PROP_SCALE_LOG) ?
+ max_ff(max_ff(softmin, UI_PROP_SCALE_LOG_MIN),
+ powf(10, -number_but->precision) * 0.5f) :
+ 0;
+
/* Mouse location isn't screen clamped to the screen so use a linear mapping
* 2px == 1-int, or 1px == 1-ClickStep */
if (is_float) {
fac *= 0.01f * number_but->step_size;
- tempf = (float)data->startvalue + ((float)(mx - data->dragstartx) * fac);
+ switch (scale_type) {
+ case PROP_SCALE_LINEAR: {
+ tempf = (float)data->startvalue + (float)(mx - data->dragstartx) * fac;
+ break;
+ }
+ case PROP_SCALE_LOG: {
+ const float startvalue = max_ff((float)data->startvalue, log_min);
+ tempf = expf((float)(mx - data->dragstartx) * fac) * startvalue;
+ if (tempf <= log_min) {
+ tempf = 0.0f;
+ }
+ break;
+ }
+ case PROP_SCALE_CUBIC: {
+ tempf = cbrtf((float)data->startvalue) + (float)(mx - data->dragstartx) * fac;
+ tempf *= tempf * tempf;
+ break;
+ }
+ }
+
tempf = ui_numedit_apply_snapf(but, tempf, softmin, softmax, snap);
#if 1 /* fake moving the click start, nicer for dragging back after passing the limit */
- if (tempf < softmin) {
- data->dragstartx -= (softmin - tempf) / fac;
- tempf = softmin;
- }
- else if (tempf > softmax) {
- data->dragstartx += (tempf - softmax) / fac;
- tempf = softmax;
+ switch (scale_type) {
+ case PROP_SCALE_LINEAR: {
+ if (tempf < softmin) {
+ data->dragstartx -= (softmin - tempf) / fac;
+ tempf = softmin;
+ }
+ else if (tempf > softmax) {
+ data->dragstartx -= (softmax - tempf) / fac;
+ tempf = softmax;
+ }
+ break;
+ }
+ case PROP_SCALE_LOG: {
+ if (tempf < log_min) {
+ data->dragstartx -= logf(log_min / (float)data->startvalue) / fac -
+ (float)(mx - data->dragstartx);
+ tempf = softmin;
+ }
+ else if (tempf > softmax) {
+ data->dragstartx -= logf(softmax / (float)data->startvalue) / fac -
+ (float)(mx - data->dragstartx);
+ tempf = softmax;
+ }
+ break;
+ }
+ case PROP_SCALE_CUBIC: {
+ if (tempf < softmin) {
+ data->dragstartx = mx - (int)((cbrtf(softmin) - cbrtf((float)data->startvalue)) / fac);
+ tempf = softmin;
+ }
+ else if (tempf > softmax) {
+ data->dragstartx = mx - (int)((cbrtf(softmax) - cbrtf((float)data->startvalue)) / fac);
+ tempf = softmax;
+ }
+ break;
+ }
}
#else
CLAMP(tempf, softmin, softmax);
@@ -4939,7 +5048,31 @@ static bool ui_numedit_but_NUM(uiButNumber *number_but,
}
data->draglastx = mx;
- tempf = (softmin + data->dragf * softrange);
+
+ switch (scale_type) {
+ case PROP_SCALE_LINEAR: {
+ tempf = (softmin + data->dragf * softrange);
+ break;
+ }
+ case PROP_SCALE_LOG: {
+ const float log_min = max_ff(max_ff(softmin, UI_PROP_SCALE_LOG_MIN),
+ powf(10.0f, -number_but->precision) * 0.5f);
+ const float base = softmax / log_min;
+ tempf = powf(base, data->dragf) * log_min;
+ if (tempf <= log_min) {
+ tempf = 0.0f;
+ }
+ break;
+ }
+ case PROP_SCALE_CUBIC: {
+ tempf = (softmin + data->dragf * softrange);
+ tempf *= tempf * tempf;
+ float cubic_min = softmin * softmin * softmin;
+ float cubic_max = softmax * softmax * softmax;
+ tempf = (tempf - cubic_min) / (cubic_max - cubic_min) * softrange + softmin;
+ break;
+ }
+ }
if (!is_float) {
temp = round_fl_to_int(tempf);
@@ -5186,9 +5319,19 @@ static int ui_do_but_NUM(
else {
/* Float Value. */
if (but->drawflag & (UI_BUT_ACTIVE_LEFT | UI_BUT_ACTIVE_RIGHT)) {
+ const PropertyScaleType scale_type = ui_but_scale_type(but);
+
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
- const double value_step = (double)number_but->step_size * UI_PRECISION_FLOAT_SCALE;
+ double value_step;
+ if (scale_type == PROP_SCALE_LOG) {
+ value_step = powf(10.0f,
+ (roundf(log10f(data->value) + UI_PROP_SCALE_LOG_SNAP_OFFSET) - 1.0f) +
+ log10f(number_but->step_size));
+ }
+ else {
+ value_step = (double)number_but->step_size * UI_PRECISION_FLOAT_SCALE;
+ }
BLI_assert(value_step > 0.0f);
const double value_test = (but->drawflag & UI_BUT_ACTIVE_LEFT) ?
(double)max_ff(but->softmin,
@@ -5236,6 +5379,8 @@ static bool ui_numedit_but_SLI(uiBut *but,
return changed;
}
+ const PropertyScaleType scale_type = ui_but_scale_type(but);
+
softmin = but->softmin;
softmax = but->softmax;
softrange = softmax - softmin;
@@ -5277,7 +5422,24 @@ static bool ui_numedit_but_SLI(uiBut *but,
#endif
/* done correcting mouse */
- tempf = softmin + f * softrange;
+ switch (scale_type) {
+ case PROP_SCALE_LINEAR: {
+ tempf = softmin + f * softrange;
+ break;
+ }
+ case PROP_SCALE_LOG: {
+ tempf = powf(softmax / softmin, f) * softmin;
+ break;
+ }
+ case PROP_SCALE_CUBIC: {
+ const float cubicmin = cube_f(softmin);
+ const float cubicmax = cube_f(softmax);
+ const float cubicrange = cubicmax - cubicmin;
+ tempf = cube_f(softmin + f * softrange);
+ tempf = (tempf - cubicmin) / cubicrange * softrange + softmin;
+ break;
+ }
+ }
temp = round_fl_to_int(tempf);
if (snap) {
@@ -5471,6 +5633,8 @@ static int ui_do_but_SLI(
if (click) {
if (click == 2) {
+ const PropertyScaleType scale_type = ui_but_scale_type(but);
+
/* nudge slider to the left or right */
float f, tempf, softmin, softmax, softrange;
int temp;
@@ -5495,14 +5659,20 @@ static int ui_do_but_SLI(
f = (float)(mx - but->rect.xmin) / (BLI_rctf_size_x(&but->rect));
}
- f = softmin + f * softrange;
+ if (scale_type == PROP_SCALE_LOG) {
+ f = powf(softmax / softmin, f) * softmin;
+ }
+ else {
+ f = softmin + f * softrange;
+ }
if (!ui_but_is_float(but)) {
+ int value_step = 1;
if (f < temp) {
- temp--;
+ temp -= value_step;
}
else {
- temp++;
+ temp += value_step;
}
if (temp >= softmin && temp <= softmax) {
@@ -5513,14 +5683,23 @@ static int ui_do_but_SLI(
}
}
else {
- if (f < tempf) {
- tempf -= 0.01f;
- }
- else {
- tempf += 0.01f;
- }
-
if (tempf >= softmin && tempf <= softmax) {
+ float value_step;
+ if (scale_type == PROP_SCALE_LOG) {
+ value_step = powf(10.0f, roundf(log10f(tempf) + UI_PROP_SCALE_LOG_SNAP_OFFSET) - 1.0f);
+ }
+ else {
+ value_step = 0.01f;
+ }
+
+ if (f < tempf) {
+ tempf -= value_step;
+ }
+ else {
+ tempf += value_step;
+ }
+
+ CLAMP(tempf, softmin, softmax);
data->value = tempf;
}
else {
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 333dc1beb22..40a3f0d330f 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -660,6 +660,7 @@ bool ui_but_context_poll_operator(struct bContext *C, struct wmOperatorType *ot,
extern void ui_but_update(uiBut *but);
extern void ui_but_update_edited(uiBut *but);
+extern PropertyScaleType ui_but_scale_type(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
extern bool ui_but_is_float(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
extern bool ui_but_is_bool(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
extern bool ui_but_is_unit(const uiBut *but) ATTR_WARN_UNUSED_RESULT;
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index c9c1f56dc98..d2e6165a20f 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -3752,12 +3752,35 @@ static void widget_numslider(
float factor, factor_ui;
float factor_discard = 1.0f; /* No discard. */
const float value = (float)ui_but_value_get(but);
-
- if (but->rnaprop && (RNA_property_subtype(but->rnaprop) == PROP_PERCENTAGE)) {
- factor = value / but->softmax;
- }
- else {
- factor = (value - but->softmin) / (but->softmax - but->softmin);
+ const float softmin = but->softmin;
+ const float softmax = but->softmax;
+ const float softrange = softmax - softmin;
+ const PropertyScaleType scale_type = ui_but_scale_type(but);
+
+ switch (scale_type) {
+ case PROP_SCALE_LINEAR: {
+ if (but->rnaprop && (RNA_property_subtype(but->rnaprop) == PROP_PERCENTAGE)) {
+ factor = value / softmax;
+ }
+ else {
+ factor = (value - softmin) / softrange;
+ }
+ break;
+ }
+ case PROP_SCALE_LOG: {
+ const float logmin = fmaxf(softmin, 0.5e-8f);
+ const float base = softmax / logmin;
+ factor = logf(value / logmin) / logf(base);
+ break;
+ }
+ case PROP_SCALE_CUBIC: {
+ const float cubicmin = cube_f(softmin);
+ const float cubicmax = cube_f(softmax);
+ const float cubicrange = cubicmax - cubicmin;
+ const float f = (value - softmin) * cubicrange / softrange + cubicmin;
+ factor = (cbrtf(f) - softmin) / softrange;
+ break;
+ }
}
const float width = (float)BLI_rcti_size_x(rect);
diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c
index 592467c2a85..28838d677f0 100644
--- a/source/blender/editors/io/io_alembic.c
+++ b/source/blender/editors/io/io_alembic.c
@@ -121,6 +121,7 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op)
.uvs = RNA_boolean_get(op->ptr, "uvs"),
.normals = RNA_boolean_get(op->ptr, "normals"),
.vcolors = RNA_boolean_get(op->ptr, "vcolors"),
+ .orcos = RNA_boolean_get(op->ptr, "orcos"),
.apply_subdiv = RNA_boolean_get(op->ptr, "apply_subdiv"),
.curves_as_mesh = RNA_boolean_get(op->ptr, "curves_as_mesh"),
.flatten_hierarchy = RNA_boolean_get(op->ptr, "flatten"),
@@ -210,6 +211,7 @@ static void ui_alembic_export_settings(uiLayout *layout, PointerRNA *imfptr)
uiItemR(col, imfptr, "normals", 0, NULL, ICON_NONE);
uiItemR(col, imfptr, "vcolors", 0, NULL, ICON_NONE);
+ uiItemR(col, imfptr, "orcos", 0, NULL, ICON_NONE);
uiItemR(col, imfptr, "face_sets", 0, NULL, ICON_NONE);
uiItemR(col, imfptr, "curves_as_mesh", 0, NULL, ICON_NONE);
@@ -378,6 +380,12 @@ void WM_OT_alembic_export(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "vcolors", 0, "Vertex Colors", "Export vertex colors");
+ RNA_def_boolean(ot->srna,
+ "orcos",
+ true,
+ "Generated Coordinates",
+ "Export undeformed mesh vertex coordinates");
+
RNA_def_boolean(
ot->srna, "face_sets", 0, "Face Sets", "Export per face shading group assignments");
diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt
index 77b5379ddd4..4338b043fc9 100644
--- a/source/blender/editors/object/CMakeLists.txt
+++ b/source/blender/editors/object/CMakeLists.txt
@@ -87,7 +87,7 @@ if(WITH_INTERNATIONAL)
endif()
if(WITH_EXPERIMENTAL_FEATURES)
- add_definitions(-DWITH_GEOMETRY_NODES)
+ add_definitions(-DWITH_SIMULATION_DATABLOCK)
add_definitions(-DWITH_POINT_CLOUD)
add_definitions(-DWITH_HAIR_NODES)
endif()
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index ce441e7b551..8cf7d60e6c4 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1311,6 +1311,8 @@ static int object_gpencil_add_exec(bContext *C, wmOperator *op)
bGPdata *gpd = (ob && (ob->type == OB_GPENCIL)) ? ob->data : NULL;
const int type = RNA_enum_get(op->ptr, "type");
+ const bool use_in_front = RNA_boolean_get(op->ptr, "use_in_front");
+ const int stroke_depth_order = RNA_enum_get(op->ptr, "stroke_depth_order");
ushort local_view_bits;
float loc[3], rot[3];
@@ -1338,6 +1340,7 @@ static int object_gpencil_add_exec(bContext *C, wmOperator *op)
break;
}
case GP_LRT_OBJECT:
+ case GP_LRT_SCENE:
case GP_LRT_COLLECTION: {
ob_name = "Line Art";
break;
@@ -1430,7 +1433,15 @@ static int object_gpencil_add_exec(bContext *C, wmOperator *op)
}
/* Stroke object is drawn in front of meshes by default. */
- ob->dtx |= OB_DRAW_IN_FRONT;
+ if (use_in_front) {
+ ob->dtx |= OB_DRAW_IN_FRONT;
+ }
+ else {
+ if (stroke_depth_order == GP_DRAWMODE_3D) {
+ gpd->draw_mode = GP_DRAWMODE_3D;
+ }
+ }
+
break;
}
default:
@@ -1449,6 +1460,38 @@ static int object_gpencil_add_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+static void object_add_ui(bContext *UNUSED(C), wmOperator *op)
+{
+ uiLayout *layout = op->layout;
+
+ uiLayoutSetPropSep(layout, true);
+
+ uiItemR(layout, op->ptr, "radius", 0, NULL, ICON_NONE);
+ uiItemR(layout, op->ptr, "align", 0, NULL, ICON_NONE);
+ uiItemR(layout, op->ptr, "location", 0, NULL, ICON_NONE);
+ uiItemR(layout, op->ptr, "rotation", 0, NULL, ICON_NONE);
+ uiItemR(layout, op->ptr, "type", 0, NULL, ICON_NONE);
+
+ int type = RNA_enum_get(op->ptr, "type");
+ if (type == GP_LRT_COLLECTION || type == GP_LRT_OBJECT || type == GP_LRT_SCENE) {
+ uiItemR(layout, op->ptr, "use_in_front", 0, NULL, ICON_NONE);
+ bool in_front = RNA_boolean_get(op->ptr, "use_in_front");
+ uiLayout *row = uiLayoutRow(layout, false);
+ uiLayoutSetActive(row, !in_front);
+ uiItemR(row, op->ptr, "stroke_depth_order", 0, NULL, ICON_NONE);
+ }
+}
+
+static EnumPropertyItem rna_enum_gpencil_add_stroke_depth_order_items[] = {
+ {GP_DRAWMODE_2D,
+ "2D",
+ 0,
+ "2D Layers",
+ "Display strokes using grease pencil layers to define order"},
+ {GP_DRAWMODE_3D, "3D", 0, "3D Location", "Display strokes using real 3D position in 3D space"},
+ {0, NULL, 0, NULL, NULL},
+};
+
void OBJECT_OT_gpencil_add(wmOperatorType *ot)
{
/* identifiers */
@@ -1464,11 +1507,26 @@ void OBJECT_OT_gpencil_add(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ /* ui */
+ ot->ui = object_add_ui;
+
/* properties */
ED_object_add_unit_props_radius(ot);
ED_object_add_generic_props(ot, false);
ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_gpencil_type_items, 0, "Type", "");
+ RNA_def_boolean(ot->srna,
+ "use_in_front",
+ false,
+ "In Front",
+ "Show line art grease pencil in front of everything");
+ RNA_def_enum(
+ ot->srna,
+ "stroke_depth_order",
+ rna_enum_gpencil_add_stroke_depth_order_items,
+ GP_DRAWMODE_3D,
+ "Stroke Depth Order",
+ "Defines how the strokes are ordered in 3D space for objects not displayed 'In Front'");
}
/** \} */
@@ -2841,6 +2899,7 @@ static int object_convert_exec(bContext *C, wmOperator *op)
me_eval = BKE_mesh_copy_for_eval(me_eval, false);
/* Full (edge-angle based) draw calculation should ideally be performed. */
BKE_mesh_edges_set_draw_render(me_eval);
+ BKE_object_material_from_eval_data(bmain, newob, &me_eval->id);
BKE_mesh_nomain_to_mesh(me_eval, newob->data, newob, &CD_MASK_MESH, true);
BKE_object_free_modifiers(newob, 0); /* after derivedmesh calls! */
}
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index f651f5bc3fd..3370476d466 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -669,9 +669,11 @@ static void bake_targets_clear(Main *bmain, const bool is_tangent)
}
/* create new mesh with edit mode changes and modifiers applied */
-static Mesh *bake_mesh_new_from_object(Object *object)
+static Mesh *bake_mesh_new_from_object(Depsgraph *depsgraph,
+ Object *object,
+ const bool preserve_origindex)
{
- Mesh *me = BKE_mesh_new_from_object(NULL, object, false);
+ Mesh *me = BKE_mesh_new_from_object(depsgraph, object, false, preserve_origindex);
if (me->flag & ME_AUTOSMOOTH) {
BKE_mesh_split_faces(me, true);
@@ -961,10 +963,39 @@ static bool bake_targets_init_vertex_colors(BakeTargets *targets, Object *ob, Re
return true;
}
+static int find_original_loop(const Mesh *me_orig,
+ const int *vert_origindex,
+ const int *poly_origindex,
+ const int poly_eval,
+ const int vert_eval)
+{
+ /* Get original vertex and polygon index. There is currently no loop mapping
+ * in modifier stack evaluation. */
+ const int vert_orig = vert_origindex[vert_eval];
+ const int poly_orig = poly_origindex[poly_eval];
+
+ if (vert_orig == ORIGINDEX_NONE || poly_orig == ORIGINDEX_NONE) {
+ return ORIGINDEX_NONE;
+ }
+
+ /* Find matching loop with original vertex in original polygon. */
+ MPoly *mpoly_orig = me_orig->mpoly + poly_orig;
+ MLoop *mloop_orig = me_orig->mloop + mpoly_orig->loopstart;
+ for (int j = 0; j < mpoly_orig->totloop; ++j, ++mloop_orig) {
+ if (mloop_orig->v == vert_orig) {
+ return mpoly_orig->loopstart + j;
+ }
+ }
+
+ return ORIGINDEX_NONE;
+}
+
static void bake_targets_populate_pixels_vertex_colors(BakeTargets *targets,
- Mesh *me,
+ Object *ob,
+ Mesh *me_eval,
BakePixel *pixel_array)
{
+ Mesh *me = ob->data;
const int num_pixels = targets->num_pixels;
/* Initialize blank pixels. */
@@ -983,16 +1014,31 @@ static void bake_targets_populate_pixels_vertex_colors(BakeTargets *targets,
}
/* Populate through adjacent triangles, first triangle wins. */
- const int tottri = poly_to_tri_count(me->totpoly, me->totloop);
+ const int tottri = poly_to_tri_count(me_eval->totpoly, me_eval->totloop);
MLoopTri *looptri = MEM_mallocN(sizeof(*looptri) * tottri, __func__);
- BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri);
+ BKE_mesh_recalc_looptri(
+ me_eval->mloop, me_eval->mpoly, me_eval->mvert, me_eval->totloop, me_eval->totpoly, looptri);
+
+ /* For mapping back to original mesh in case there are modifiers. */
+ const int *vert_origindex = CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX);
+ const int *poly_origindex = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX);
for (int i = 0; i < tottri; i++) {
const MLoopTri *lt = &looptri[i];
for (int j = 0; j < 3; j++) {
- const unsigned int l = lt->tri[j];
+ unsigned int l = lt->tri[j];
+ unsigned int v = me_eval->mloop[l].v;
+
+ /* Map back to original loop if there are modifiers. */
+ if (vert_origindex != NULL && poly_origindex != NULL) {
+ l = find_original_loop(me, vert_origindex, poly_origindex, lt->poly, v);
+ if (l == ORIGINDEX_NONE || l >= me->totloop) {
+ continue;
+ }
+ }
+
BakePixel *pixel = &pixel_array[l];
if (pixel->primitive_id != -1) {
@@ -1004,7 +1050,7 @@ static void bake_targets_populate_pixels_vertex_colors(BakeTargets *targets,
/* Seed is the vertex, so that sampling noise is coherent for the same
* vertex, but different corners can still have different normals,
* materials and UVs. */
- pixel->seed = me->mloop[l].v;
+ pixel->seed = v;
/* Barycentric coordinates, nudged a bit to avoid precision issues that
* may happen when exactly at the vertex coordinate. */
@@ -1043,7 +1089,7 @@ static void bake_result_add_to_rgba(float rgba[4], const float *result, const in
}
}
-static bool bake_targets_output_vertex_colors(BakeTargets *targets, Object *ob, Mesh *me_split)
+static bool bake_targets_output_vertex_colors(BakeTargets *targets, Object *ob)
{
Mesh *me = ob->data;
MPropCol *mcol = CustomData_get_layer(&me->vdata, CD_PROP_COLOR);
@@ -1052,11 +1098,6 @@ static bool bake_targets_output_vertex_colors(BakeTargets *targets, Object *ob,
const int num_channels = targets->num_channels;
const float *result = targets->result;
- /* We bake using a mesh with additional vertices for split normals, but the
- * number of loops must match to be able to transfer the vertex colors. */
- BLI_assert(me->totloop == me_split->totloop);
- UNUSED_VARS_NDEBUG(me_split);
-
if (mcol_valid) {
const int totvert = me->totvert;
const int totloop = me->totloop;
@@ -1111,16 +1152,17 @@ static bool bake_targets_output_vertex_colors(BakeTargets *targets, Object *ob,
static bool bake_targets_init(const BakeAPIRender *bkr,
BakeTargets *targets,
Object *ob,
+ Object *ob_eval,
ReportList *reports)
{
if (bkr->target == R_BAKE_TARGET_IMAGE_TEXTURES) {
if (bkr->save_mode == R_BAKE_SAVE_INTERNAL) {
- if (!bake_targets_init_internal(bkr, targets, ob, reports)) {
+ if (!bake_targets_init_internal(bkr, targets, ob_eval, reports)) {
return false;
}
}
else if (bkr->save_mode == R_BAKE_SAVE_EXTERNAL) {
- if (!bake_targets_init_external(bkr, targets, ob, reports)) {
+ if (!bake_targets_init_external(bkr, targets, ob_eval, reports)) {
return false;
}
}
@@ -1145,14 +1187,15 @@ static bool bake_targets_init(const BakeAPIRender *bkr,
static void bake_targets_populate_pixels(const BakeAPIRender *bkr,
BakeTargets *targets,
- Mesh *me,
+ Object *ob,
+ Mesh *me_eval,
BakePixel *pixel_array)
{
if (bkr->target == R_BAKE_TARGET_VERTEX_COLORS) {
- bake_targets_populate_pixels_vertex_colors(targets, me, pixel_array);
+ bake_targets_populate_pixels_vertex_colors(targets, ob, me_eval, pixel_array);
}
else {
- RE_bake_pixels_populate(me, pixel_array, targets->num_pixels, targets, bkr->uv_layer);
+ RE_bake_pixels_populate(me_eval, pixel_array, targets->num_pixels, targets, bkr->uv_layer);
}
}
@@ -1160,7 +1203,7 @@ static bool bake_targets_output(const BakeAPIRender *bkr,
BakeTargets *targets,
Object *ob,
Object *ob_eval,
- Mesh *me,
+ Mesh *me_eval,
BakePixel *pixel_array,
ReportList *reports)
{
@@ -1169,11 +1212,12 @@ static bool bake_targets_output(const BakeAPIRender *bkr,
return bake_targets_output_internal(bkr, targets, ob, pixel_array, reports);
}
if (bkr->save_mode == R_BAKE_SAVE_EXTERNAL) {
- return bake_targets_output_external(bkr, targets, ob, ob_eval, me, pixel_array, reports);
+ return bake_targets_output_external(
+ bkr, targets, ob, ob_eval, me_eval, pixel_array, reports);
}
}
else if (bkr->target == R_BAKE_TARGET_VERTEX_COLORS) {
- return bake_targets_output_vertex_colors(targets, ob, me);
+ return bake_targets_output_vertex_colors(targets, ob);
}
return false;
@@ -1213,8 +1257,8 @@ static int bake(const BakeAPIRender *bkr,
BakeHighPolyData *highpoly = NULL;
int tot_highpoly = 0;
- Mesh *me_low = NULL;
- Mesh *me_cage = NULL;
+ Mesh *me_low_eval = NULL;
+ Mesh *me_cage_eval = NULL;
MultiresModifierData *mmd_low = NULL;
int mmd_flags_low = 0;
@@ -1224,6 +1268,8 @@ static int bake(const BakeAPIRender *bkr,
BakeTargets targets = {NULL};
+ const bool preserve_origindex = (bkr->target == R_BAKE_TARGET_VERTEX_COLORS);
+
RE_bake_engine_set_engine_parameters(re, bmain, scene);
if (!RE_bake_has_engine(re)) {
@@ -1287,10 +1333,10 @@ static int bake(const BakeAPIRender *bkr,
ob_low_eval = DEG_get_evaluated_object(depsgraph, ob_low);
/* get the mesh as it arrives in the renderer */
- me_low = bake_mesh_new_from_object(ob_low_eval);
+ me_low_eval = bake_mesh_new_from_object(depsgraph, ob_low_eval, preserve_origindex);
/* Initialize bake targets. */
- if (!bake_targets_init(bkr, &targets, ob_low_eval, reports)) {
+ if (!bake_targets_init(bkr, &targets, ob_low, ob_low_eval, reports)) {
goto cleanup;
}
@@ -1298,7 +1344,7 @@ static int bake(const BakeAPIRender *bkr,
* it is populated later with the cage mesh (smoothed version of the mesh). */
pixel_array_low = MEM_mallocN(sizeof(BakePixel) * targets.num_pixels, "bake pixels low poly");
if ((bkr->is_selected_to_active && (ob_cage == NULL) && bkr->is_cage) == false) {
- bake_targets_populate_pixels(bkr, &targets, me_low, pixel_array_low);
+ bake_targets_populate_pixels(bkr, &targets, ob_low, me_low_eval, pixel_array_low);
}
if (bkr->is_selected_to_active) {
@@ -1307,8 +1353,9 @@ static int bake(const BakeAPIRender *bkr,
/* prepare cage mesh */
if (ob_cage) {
- me_cage = bake_mesh_new_from_object(ob_cage_eval);
- if ((me_low->totpoly != me_cage->totpoly) || (me_low->totloop != me_cage->totloop)) {
+ me_cage_eval = bake_mesh_new_from_object(depsgraph, ob_cage_eval, preserve_origindex);
+ if ((me_low_eval->totpoly != me_cage_eval->totpoly) ||
+ (me_low_eval->totloop != me_cage_eval->totloop)) {
BKE_report(reports,
RPT_ERROR,
"Invalid cage object, the cage mesh must have the same number "
@@ -1348,8 +1395,8 @@ static int bake(const BakeAPIRender *bkr,
BKE_object_handle_data_update(depsgraph, scene, ob_low_eval);
}
- me_cage = BKE_mesh_new_from_object(NULL, ob_low_eval, false);
- bake_targets_populate_pixels(bkr, &targets, me_cage, pixel_array_low);
+ me_cage_eval = BKE_mesh_new_from_object(NULL, ob_low_eval, false, preserve_origindex);
+ bake_targets_populate_pixels(bkr, &targets, ob_low, me_cage_eval, pixel_array_low);
}
highpoly = MEM_callocN(sizeof(BakeHighPolyData) * tot_highpoly, "bake high poly objects");
@@ -1367,7 +1414,7 @@ static int bake(const BakeAPIRender *bkr,
highpoly[i].ob_eval = DEG_get_evaluated_object(depsgraph, ob_iter);
highpoly[i].ob_eval->restrictflag &= ~OB_RESTRICT_RENDER;
highpoly[i].ob_eval->base_flag |= (BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER);
- highpoly[i].me = BKE_mesh_new_from_object(NULL, highpoly[i].ob_eval, false);
+ highpoly[i].me = BKE_mesh_new_from_object(NULL, highpoly[i].ob_eval, false, false);
/* Low-poly to high-poly transformation matrix. */
copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat);
@@ -1391,7 +1438,7 @@ static int bake(const BakeAPIRender *bkr,
pixel_array_high = MEM_mallocN(sizeof(BakePixel) * targets.num_pixels,
"bake pixels high poly");
- if (!RE_bake_pixels_populate_from_objects(me_low,
+ if (!RE_bake_pixels_populate_from_objects(me_low_eval,
pixel_array_low,
pixel_array_high,
highpoly,
@@ -1402,7 +1449,7 @@ static int bake(const BakeAPIRender *bkr,
bkr->max_ray_distance,
ob_low_eval->obmat,
(ob_cage ? ob_cage->obmat : ob_low_eval->obmat),
- me_cage)) {
+ me_cage_eval)) {
BKE_report(reports, RPT_ERROR, "Error handling selected objects");
goto cleanup;
}
@@ -1478,7 +1525,7 @@ static int bake(const BakeAPIRender *bkr,
targets.num_pixels,
targets.num_channels,
targets.result,
- me_low,
+ me_low_eval,
bkr->normal_swizzle,
ob_low_eval->obmat);
}
@@ -1497,8 +1544,8 @@ static int bake(const BakeAPIRender *bkr,
}
/* Evaluate modifiers again. */
- me_nores = BKE_mesh_new_from_object(NULL, ob_low_eval, false);
- bake_targets_populate_pixels(bkr, &targets, me_nores, pixel_array_low);
+ me_nores = BKE_mesh_new_from_object(NULL, ob_low_eval, false, false);
+ bake_targets_populate_pixels(bkr, &targets, ob_low, me_nores, pixel_array_low);
RE_bake_normal_world_to_tangent(pixel_array_low,
targets.num_pixels,
@@ -1527,7 +1574,7 @@ static int bake(const BakeAPIRender *bkr,
else {
/* save the results */
if (bake_targets_output(
- bkr, &targets, ob_low, ob_low_eval, me_low, pixel_array_low, reports)) {
+ bkr, &targets, ob_low, ob_low_eval, me_low_eval, pixel_array_low, reports)) {
op_result = OPERATOR_FINISHED;
}
else {
@@ -1562,12 +1609,12 @@ cleanup:
bake_targets_free(&targets);
- if (me_low != NULL) {
- BKE_id_free(NULL, &me_low->id);
+ if (me_low_eval != NULL) {
+ BKE_id_free(NULL, &me_low_eval->id);
}
- if (me_cage != NULL) {
- BKE_id_free(NULL, &me_cage->id);
+ if (me_cage_eval != NULL) {
+ BKE_id_free(NULL, &me_cage_eval->id);
}
DEG_graph_free(depsgraph);
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 07c8e7725e3..5be572baec5 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -1590,30 +1590,10 @@ static const EnumPropertyItem *object_mode_set_itemsf(bContext *C,
return rna_enum_object_mode_items;
}
- Object *ob = CTX_data_active_object(C);
+ const Object *ob = CTX_data_active_object(C);
if (ob) {
- const bool use_mode_particle_edit = (BLI_listbase_is_empty(&ob->particlesystem) == false) ||
- (ob->soft != NULL) ||
- (BKE_modifiers_findby_type(ob, eModifierType_Cloth) !=
- NULL);
while (input->identifier) {
- if ((input->value == OB_MODE_EDIT && OB_TYPE_SUPPORT_EDITMODE(ob->type)) ||
- (input->value == OB_MODE_POSE && (ob->type == OB_ARMATURE)) ||
- (input->value == OB_MODE_PARTICLE_EDIT && use_mode_particle_edit) ||
- (ELEM(input->value,
- OB_MODE_SCULPT,
- OB_MODE_VERTEX_PAINT,
- OB_MODE_WEIGHT_PAINT,
- OB_MODE_TEXTURE_PAINT) &&
- (ob->type == OB_MESH)) ||
- (ELEM(input->value,
- OB_MODE_EDIT_GPENCIL,
- OB_MODE_PAINT_GPENCIL,
- OB_MODE_SCULPT_GPENCIL,
- OB_MODE_WEIGHT_GPENCIL,
- OB_MODE_VERTEX_GPENCIL) &&
- (ob->type == OB_GPENCIL)) ||
- (input->value == OB_MODE_OBJECT)) {
+ if (ED_object_mode_compat_test(ob, input->value)) {
RNA_enum_item_add(&item, &totitem, input);
}
input++;
diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c
index ff1855cafc5..dcb294bcb12 100644
--- a/source/blender/editors/object/object_modes.c
+++ b/source/blender/editors/object/object_modes.c
@@ -115,43 +115,46 @@ static const char *object_mode_op_string(eObjectMode mode)
*/
bool ED_object_mode_compat_test(const Object *ob, eObjectMode mode)
{
- if (ob) {
- if (mode == OB_MODE_OBJECT) {
- return true;
- }
+ if (mode == OB_MODE_OBJECT) {
+ return true;
+ }
- switch (ob->type) {
- case OB_MESH:
- if (mode & (OB_MODE_EDIT | OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT |
- OB_MODE_TEXTURE_PAINT | OB_MODE_PARTICLE_EDIT)) {
- return true;
- }
- break;
- case OB_CURVE:
- case OB_SURF:
- case OB_FONT:
- case OB_MBALL:
- if (mode & OB_MODE_EDIT) {
- return true;
- }
- break;
- case OB_LATTICE:
- if (mode & (OB_MODE_EDIT | OB_MODE_WEIGHT_PAINT)) {
- return true;
- }
- break;
- case OB_ARMATURE:
- if (mode & (OB_MODE_EDIT | OB_MODE_POSE)) {
- return true;
- }
- break;
- case OB_GPENCIL:
- if (mode & (OB_MODE_EDIT | OB_MODE_EDIT_GPENCIL | OB_MODE_PAINT_GPENCIL |
- OB_MODE_SCULPT_GPENCIL | OB_MODE_WEIGHT_GPENCIL | OB_MODE_VERTEX_GPENCIL)) {
+ switch (ob->type) {
+ case OB_MESH:
+ if (mode & (OB_MODE_EDIT | OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT |
+ OB_MODE_TEXTURE_PAINT)) {
+ return true;
+ }
+ if (mode & OB_MODE_PARTICLE_EDIT) {
+ if (ED_object_particle_edit_mode_supported(ob)) {
return true;
}
- break;
- }
+ }
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ case OB_FONT:
+ case OB_MBALL:
+ if (mode & OB_MODE_EDIT) {
+ return true;
+ }
+ break;
+ case OB_LATTICE:
+ if (mode & (OB_MODE_EDIT | OB_MODE_WEIGHT_PAINT)) {
+ return true;
+ }
+ break;
+ case OB_ARMATURE:
+ if (mode & (OB_MODE_EDIT | OB_MODE_POSE)) {
+ return true;
+ }
+ break;
+ case OB_GPENCIL:
+ if (mode & (OB_MODE_EDIT_GPENCIL | OB_MODE_PAINT_GPENCIL | OB_MODE_SCULPT_GPENCIL |
+ OB_MODE_WEIGHT_GPENCIL | OB_MODE_VERTEX_GPENCIL)) {
+ return true;
+ }
+ break;
}
return false;
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 0d896f14888..e14e5cbd44b 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -63,6 +63,7 @@
#include "BKE_lattice.h"
#include "BKE_lib_id.h"
#include "BKE_main.h"
+#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_mesh_runtime.h"
@@ -210,7 +211,7 @@ ModifierData *ED_object_modifier_add(
/* special cases */
if (type == eModifierType_Softbody) {
if (!ob->soft) {
- ob->soft = sbNew(scene);
+ ob->soft = sbNew();
ob->softflag |= OB_SB_GOAL | OB_SB_EDGES;
}
}
@@ -772,6 +773,8 @@ static bool modifier_apply_obdata(
return false;
}
+ Main *bmain = DEG_get_bmain(depsgraph);
+ BKE_object_material_from_eval_data(bmain, ob, &mesh_applied->id);
BKE_mesh_nomain_to_mesh(mesh_applied, me, ob, &CD_MASK_MESH, true);
if (md_eval->type == eModifierType_Multires) {
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index a7308002e76..b685a93f27b 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -801,7 +801,7 @@ bool ED_object_parent_set(ReportList *reports,
* so we check this by assuming that the parent is selected too.
*/
/* XXX currently this should only happen for meshes, curves, surfaces,
- * and lattices - this stuff isn't available for metas yet */
+ * and lattices - this stuff isn't available for meta-balls yet. */
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
ModifierData *md;
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index de4ad913d6d..5b545784e5b 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -5375,8 +5375,7 @@ static bool particle_edit_toggle_poll(bContext *C)
return 0;
}
- return (ob->particlesystem.first || BKE_modifiers_findby_type(ob, eModifierType_Cloth) ||
- BKE_modifiers_findby_type(ob, eModifierType_Softbody));
+ return ED_object_particle_edit_mode_supported(ob);
}
static void free_all_psys_edit(Object *object)
@@ -5391,6 +5390,12 @@ static void free_all_psys_edit(Object *object)
}
}
+bool ED_object_particle_edit_mode_supported(const Object *ob)
+{
+ return (ob->particlesystem.first || BKE_modifiers_findby_type(ob, eModifierType_Cloth) ||
+ BKE_modifiers_findby_type(ob, eModifierType_Softbody));
+}
+
void ED_object_particle_edit_mode_enter_ex(Depsgraph *depsgraph, Scene *scene, Object *ob)
{
/* Needed so #ParticleSystemModifierData.mesh_final is set. */
diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c
index 81a8b57776b..fca3b5817b0 100644
--- a/source/blender/editors/physics/rigidbody_object.c
+++ b/source/blender/editors/physics/rigidbody_object.c
@@ -520,6 +520,26 @@ static int rigidbody_objects_calc_mass_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+static bool mass_calculate_poll_property(const bContext *UNUSED(C),
+ wmOperator *op,
+ const PropertyRNA *prop)
+{
+ const char *prop_id = RNA_property_identifier(prop);
+
+ /* Disable density input when not using the 'Custom' preset. */
+ if (STREQ(prop_id, "density")) {
+ int material = RNA_enum_get(op->ptr, "material");
+ if (material >= 0) {
+ RNA_def_property_clear_flag((PropertyRNA *)prop, PROP_EDITABLE);
+ }
+ else {
+ RNA_def_property_flag((PropertyRNA *)prop, PROP_EDITABLE);
+ }
+ }
+
+ return true;
+}
+
void RIGIDBODY_OT_mass_calculate(wmOperatorType *ot)
{
PropertyRNA *prop;
@@ -533,6 +553,7 @@ void RIGIDBODY_OT_mass_calculate(wmOperatorType *ot)
ot->invoke = WM_menu_invoke; /* XXX */
ot->exec = rigidbody_objects_calc_mass_exec;
ot->poll = ED_operator_rigidbody_active_poll;
+ ot->poll_property = mass_calculate_poll_property;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -554,7 +575,7 @@ void RIGIDBODY_OT_mass_calculate(wmOperatorType *ot)
FLT_MIN,
FLT_MAX,
"Density",
- "Custom density value (kg/m^3) to use instead of material preset",
+ "Density value (kg/m^3), allows custom value if the 'Custom' preset is used",
1.0f,
2500.0f);
}
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 157f2b3ecb4..e28fe8a5d04 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -70,6 +70,7 @@
#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_scene.h"
+#include "BKE_screen.h"
#include "BKE_texture.h"
#include "BKE_world.h"
@@ -776,16 +777,21 @@ static void object_preview_render(IconPreview *preview, IconPreviewSize *preview
U.pixelsize = 2.0f;
+ View3DShading shading;
+ BKE_screen_view3d_shading_init(&shading);
+ /* Enable shadows, makes it a bit easier to see the shape. */
+ shading.flag |= V3D_SHADING_SHADOW;
+
ImBuf *ibuf = ED_view3d_draw_offscreen_imbuf_simple(
depsgraph,
DEG_get_evaluated_scene(depsgraph),
- NULL,
- OB_SOLID,
+ &shading,
+ OB_TEXTURE,
DEG_get_evaluated_object(depsgraph, scene->camera),
preview_sized->sizex,
preview_sized->sizey,
IB_rect,
- V3D_OFSDRAW_NONE,
+ V3D_OFSDRAW_OVERRIDE_SCENE_SETTINGS,
R_ALPHAPREMUL,
NULL,
NULL,
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index bd2b1c4c553..b83eccdcfdd 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -1172,12 +1172,12 @@ static void region_azones_add(const bScreen *screen, ScrArea *area, ARegion *reg
}
/* dir is direction to check, not the splitting edge direction! */
-static int rct_fits(const rcti *rect, char dir, int size)
+static int rct_fits(const rcti *rect, const eScreenAxis dir_axis, int size)
{
- if (dir == 'h') {
+ if (dir_axis == SCREEN_AXIS_H) {
return BLI_rcti_size_x(rect) + 1 - size;
}
- /* 'v' */
+ /* Vertical. */
return BLI_rcti_size_y(rect) + 1 - size;
}
@@ -1398,7 +1398,8 @@ static void region_rect_recursive(
region->flag |= RGN_FLAG_TOO_SMALL;
}
}
- else if (rct_fits(remainder, 'v', 1) < 0 || rct_fits(remainder, 'h', 1) < 0) {
+ else if (rct_fits(remainder, SCREEN_AXIS_V, 1) < 0 ||
+ rct_fits(remainder, SCREEN_AXIS_H, 1) < 0) {
/* remainder is too small for any usage */
region->flag |= RGN_FLAG_TOO_SMALL;
}
@@ -1410,11 +1411,11 @@ static void region_rect_recursive(
else if (ELEM(alignment, RGN_ALIGN_TOP, RGN_ALIGN_BOTTOM)) {
rcti *winrct = (region->overlap) ? overlap_remainder : remainder;
- if ((prefsizey == 0) || (rct_fits(winrct, 'v', prefsizey) < 0)) {
+ if ((prefsizey == 0) || (rct_fits(winrct, SCREEN_AXIS_V, prefsizey) < 0)) {
region->flag |= RGN_FLAG_TOO_SMALL;
}
else {
- int fac = rct_fits(winrct, 'v', prefsizey);
+ int fac = rct_fits(winrct, SCREEN_AXIS_V, prefsizey);
if (fac < 0) {
prefsizey += fac;
@@ -1436,11 +1437,11 @@ static void region_rect_recursive(
else if (ELEM(alignment, RGN_ALIGN_LEFT, RGN_ALIGN_RIGHT)) {
rcti *winrct = (region->overlap) ? overlap_remainder : remainder;
- if ((prefsizex == 0) || (rct_fits(winrct, 'h', prefsizex) < 0)) {
+ if ((prefsizex == 0) || (rct_fits(winrct, SCREEN_AXIS_H, prefsizex) < 0)) {
region->flag |= RGN_FLAG_TOO_SMALL;
}
else {
- int fac = rct_fits(winrct, 'h', prefsizex);
+ int fac = rct_fits(winrct, SCREEN_AXIS_H, prefsizex);
if (fac < 0) {
prefsizex += fac;
@@ -1464,7 +1465,7 @@ static void region_rect_recursive(
region->winrct = *remainder;
if (alignment == RGN_ALIGN_HSPLIT) {
- if (rct_fits(remainder, 'h', prefsizex) > 4) {
+ if (rct_fits(remainder, SCREEN_AXIS_H, prefsizex) > 4) {
region->winrct.xmax = BLI_rcti_cent_x(remainder);
remainder->xmin = region->winrct.xmax + 1;
}
@@ -1473,7 +1474,7 @@ static void region_rect_recursive(
}
}
else {
- if (rct_fits(remainder, 'v', prefsizey) > 4) {
+ if (rct_fits(remainder, SCREEN_AXIS_V, prefsizey) > 4) {
region->winrct.ymax = BLI_rcti_cent_y(remainder);
remainder->ymin = region->winrct.ymax + 1;
}
diff --git a/source/blender/editors/screen/screen_draw.c b/source/blender/editors/screen/screen_draw.c
index 6d1409a9044..2c45524ef94 100644
--- a/source/blender/editors/screen/screen_draw.c
+++ b/source/blender/editors/screen/screen_draw.c
@@ -237,23 +237,25 @@ void ED_screen_draw_edges(wmWindow *win)
* \param sa1: Area from which the resultant originates.
* \param sa2: Target area that will be replaced.
*/
-void ED_screen_draw_join_highlight(ScrArea *sa1, ScrArea *sa2)
+void screen_draw_join_highlight(ScrArea *sa1, ScrArea *sa2)
{
- int dir = area_getorientation(sa1, sa2);
- if (dir == -1) {
+ const eScreenDir dir = area_getorientation(sa1, sa2);
+ if (dir == SCREEN_DIR_NONE) {
return;
}
/* Rect of the combined areas.*/
- bool vertical = ELEM(dir, 1, 3);
- rctf combined = {.xmin = vertical ? MAX2(sa1->totrct.xmin, sa2->totrct.xmin) :
- MIN2(sa1->totrct.xmin, sa2->totrct.xmin),
- .xmax = vertical ? MIN2(sa1->totrct.xmax, sa2->totrct.xmax) :
- MAX2(sa1->totrct.xmax, sa2->totrct.xmax),
- .ymin = vertical ? MIN2(sa1->totrct.ymin, sa2->totrct.ymin) :
- MAX2(sa1->totrct.ymin, sa2->totrct.ymin),
- .ymax = vertical ? MAX2(sa1->totrct.ymax, sa2->totrct.ymax) :
- MIN2(sa1->totrct.ymax, sa2->totrct.ymax)};
+ const bool vertical = SCREEN_DIR_IS_VERTICAL(dir);
+ const rctf combined = {
+ .xmin = vertical ? MAX2(sa1->totrct.xmin, sa2->totrct.xmin) :
+ MIN2(sa1->totrct.xmin, sa2->totrct.xmin),
+ .xmax = vertical ? MIN2(sa1->totrct.xmax, sa2->totrct.xmax) :
+ MAX2(sa1->totrct.xmax, sa2->totrct.xmax),
+ .ymin = vertical ? MIN2(sa1->totrct.ymin, sa2->totrct.ymin) :
+ MAX2(sa1->totrct.ymin, sa2->totrct.ymin),
+ .ymax = vertical ? MAX2(sa1->totrct.ymax, sa2->totrct.ymax) :
+ MIN2(sa1->totrct.ymax, sa2->totrct.ymax),
+ };
uint pos_id = GPU_vertformat_attr_add(
immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
@@ -320,7 +322,7 @@ void ED_screen_draw_join_highlight(ScrArea *sa1, ScrArea *sa2)
UI_draw_roundbox_4fv(&combined, false, 7 * U.pixelsize, (float[4]){1.0f, 1.0f, 1.0f, 0.8f});
}
-void ED_screen_draw_split_preview(ScrArea *area, const int dir, const float fac)
+void screen_draw_split_preview(ScrArea *area, const eScreenAxis dir_axis, const float fac)
{
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -332,7 +334,7 @@ void ED_screen_draw_split_preview(ScrArea *area, const int dir, const float fac)
immBegin(GPU_PRIM_LINES, 2);
- if (dir == 'h') {
+ if (dir_axis == SCREEN_AXIS_H) {
const float y = (1 - fac) * area->totrct.ymin + fac * area->totrct.ymax;
immVertex2f(pos, area->totrct.xmin, y);
@@ -350,7 +352,7 @@ void ED_screen_draw_split_preview(ScrArea *area, const int dir, const float fac)
immEnd();
}
else {
- BLI_assert(dir == 'v');
+ BLI_assert(dir_axis == SCREEN_AXIS_V);
const float x = (1 - fac) * area->totrct.xmin + fac * area->totrct.xmax;
immVertex2f(pos, x, area->totrct.ymin);
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 75aa709a5d1..6fb5f33d836 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -104,8 +104,12 @@ static void screen_delarea(bContext *C, bScreen *screen, ScrArea *area)
MEM_freeN(area);
}
-ScrArea *area_split(
- const wmWindow *win, bScreen *screen, ScrArea *area, char dir, float fac, int merge)
+ScrArea *area_split(const wmWindow *win,
+ bScreen *screen,
+ ScrArea *area,
+ const eScreenAxis dir_axis,
+ const float fac,
+ const bool merge)
{
ScrArea *newa = NULL;
@@ -116,7 +120,7 @@ ScrArea *area_split(
rcti window_rect;
WM_window_rect_calc(win, &window_rect);
- short split = screen_geom_find_area_split_point(area, &window_rect, dir, fac);
+ short split = screen_geom_find_area_split_point(area, &window_rect, dir_axis, fac);
if (split == 0) {
return NULL;
}
@@ -125,7 +129,7 @@ ScrArea *area_split(
* normally it shouldn't matter which is used since the copy should match the original
* however with viewport rendering and python console this isn't the case. - campbell */
- if (dir == 'h') {
+ if (dir_axis == SCREEN_AXIS_H) {
/* new vertices */
ScrVert *sv1 = screen_geom_vertex_add(screen, area->v1->vec.x, split);
ScrVert *sv2 = screen_geom_vertex_add(screen, area->v4->vec.x, split);
@@ -284,10 +288,10 @@ void screen_new_activate_prepare(const wmWindow *win, bScreen *screen_new)
* -1 = not valid check.
* used with join operator.
*/
-int area_getorientation(ScrArea *sa_a, ScrArea *sa_b)
+eScreenDir area_getorientation(ScrArea *sa_a, ScrArea *sa_b)
{
if (sa_a == NULL || sa_b == NULL || sa_a == sa_b) {
- return -1;
+ return SCREEN_DIR_NONE;
}
const vec2s *sa_bl = &sa_a->v1->vec;
@@ -327,29 +331,31 @@ int area_getorientation(ScrArea *sa_a, ScrArea *sa_b)
/**
* Get alignment offset of adjacent areas. 'dir' value is like #area_getorientation().
*/
-void area_getoffsets(ScrArea *sa_a, ScrArea *sa_b, const int dir, int *r_offset1, int *r_offset2)
+void area_getoffsets(
+ ScrArea *sa_a, ScrArea *sa_b, const eScreenDir dir, int *r_offset1, int *r_offset2)
{
if (sa_a == NULL || sa_b == NULL) {
*r_offset1 = INT_MAX;
*r_offset2 = INT_MAX;
}
- else if (dir == 0) { /* West: sa on right and sa_b to the left. */
+ else if (dir == SCREEN_DIR_W) { /* West: sa on right and sa_b to the left. */
*r_offset1 = sa_b->v3->vec.y - sa_a->v2->vec.y;
*r_offset2 = sa_b->v4->vec.y - sa_a->v1->vec.y;
}
- else if (dir == 1) { /* North: sa below and sa_b above. */
+ else if (dir == SCREEN_DIR_N) { /* North: sa below and sa_b above. */
*r_offset1 = sa_a->v2->vec.x - sa_b->v1->vec.x;
*r_offset2 = sa_a->v3->vec.x - sa_b->v4->vec.x;
}
- else if (dir == 2) { /* East: sa on left and sa_b to the right. */
+ else if (dir == SCREEN_DIR_E) { /* East: sa on left and sa_b to the right. */
*r_offset1 = sa_b->v2->vec.y - sa_a->v3->vec.y;
*r_offset2 = sa_b->v1->vec.y - sa_a->v4->vec.y;
}
- else if (dir == 3) { /* South: sa above and sa_b below. */
+ else if (dir == SCREEN_DIR_S) { /* South: sa above and sa_b below. */
*r_offset1 = sa_a->v1->vec.x - sa_b->v2->vec.x;
*r_offset2 = sa_a->v4->vec.x - sa_b->v3->vec.x;
}
else {
+ BLI_assert(dir == SCREEN_DIR_NONE);
*r_offset1 = INT_MAX;
*r_offset2 = INT_MAX;
}
@@ -386,11 +392,11 @@ static void screen_verts_valign(const wmWindow *win,
/* Adjust all screen edges to allow joining two areas. 'dir' value is like area_getorientation().
*/
static void screen_areas_align(
- bContext *C, bScreen *screen, ScrArea *sa1, ScrArea *sa2, const int dir)
+ bContext *C, bScreen *screen, ScrArea *sa1, ScrArea *sa2, const eScreenDir dir)
{
wmWindow *win = CTX_wm_window(C);
- if (ELEM(dir, 0, 2)) {
+ if (SCREEN_DIR_IS_HORIZONTAL(dir)) {
/* horizontal join, use average for new top and bottom. */
int top = (sa1->v2->vec.y + sa2->v2->vec.y) / 2;
int bottom = (sa1->v4->vec.y + sa2->v4->vec.y) / 2;
@@ -421,8 +427,8 @@ static void screen_areas_align(
/* Simple join of two areas without any splitting. Will return false if not possible. */
static bool screen_area_join_aligned(bContext *C, bScreen *screen, ScrArea *sa1, ScrArea *sa2)
{
- int dir = area_getorientation(sa1, sa2);
- if (dir == -1) {
+ const eScreenDir dir = area_getorientation(sa1, sa2);
+ if (dir == SCREEN_DIR_NONE) {
return false;
}
@@ -430,7 +436,7 @@ static bool screen_area_join_aligned(bContext *C, bScreen *screen, ScrArea *sa1,
int offset2;
area_getoffsets(sa1, sa2, dir, &offset1, &offset2);
- int tolerance = ELEM(dir, 0, 2) ? AREAJOINTOLERANCEY : AREAJOINTOLERANCEX;
+ int tolerance = SCREEN_DIR_IS_HORIZONTAL(dir) ? AREAJOINTOLERANCEY : AREAJOINTOLERANCEX;
if ((abs(offset1) >= tolerance) || (abs(offset2) >= tolerance)) {
return false;
}
@@ -438,27 +444,27 @@ static bool screen_area_join_aligned(bContext *C, bScreen *screen, ScrArea *sa1,
/* Align areas if they are not. */
screen_areas_align(C, screen, sa1, sa2, dir);
- if (dir == 0) { /* sa1 to right of sa2 = W */
- sa1->v1 = sa2->v1; /* BL */
- sa1->v2 = sa2->v2; /* TL */
+ if (dir == SCREEN_DIR_W) { /* sa1 to right of sa2 = West. */
+ sa1->v1 = sa2->v1; /* BL */
+ sa1->v2 = sa2->v2; /* TL */
screen_geom_edge_add(screen, sa1->v2, sa1->v3);
screen_geom_edge_add(screen, sa1->v1, sa1->v4);
}
- else if (dir == 1) { /* sa1 to bottom of sa2 = N */
- sa1->v2 = sa2->v2; /* TL */
- sa1->v3 = sa2->v3; /* TR */
+ else if (dir == SCREEN_DIR_N) { /* sa1 to bottom of sa2 = North. */
+ sa1->v2 = sa2->v2; /* TL */
+ sa1->v3 = sa2->v3; /* TR */
screen_geom_edge_add(screen, sa1->v1, sa1->v2);
screen_geom_edge_add(screen, sa1->v3, sa1->v4);
}
- else if (dir == 2) { /* sa1 to left of sa2 = E */
- sa1->v3 = sa2->v3; /* TR */
- sa1->v4 = sa2->v4; /* BR */
+ else if (dir == SCREEN_DIR_E) { /* sa1 to left of sa2 = East. */
+ sa1->v3 = sa2->v3; /* TR */
+ sa1->v4 = sa2->v4; /* BR */
screen_geom_edge_add(screen, sa1->v2, sa1->v3);
screen_geom_edge_add(screen, sa1->v1, sa1->v4);
}
- else if (dir == 3) { /* sa1 on top of sa2 = S */
- sa1->v1 = sa2->v1; /* BL */
- sa1->v4 = sa2->v4; /* BR */
+ else if (dir == SCREEN_DIR_S) { /* sa1 on top of sa2 = South. */
+ sa1->v1 = sa2->v1; /* BL */
+ sa1->v4 = sa2->v4; /* BR */
screen_geom_edge_add(screen, sa1->v1, sa1->v2);
screen_geom_edge_add(screen, sa1->v3, sa1->v4);
}
@@ -473,9 +479,9 @@ static bool screen_area_join_aligned(bContext *C, bScreen *screen, ScrArea *sa1,
/* Slice off and return new area. "Reverse" gives right/bottom, rather than left/top. */
static ScrArea *screen_area_trim(
- bContext *C, bScreen *screen, ScrArea **area, int size, int dir, bool reverse)
+ bContext *C, bScreen *screen, ScrArea **area, int size, eScreenDir dir, bool reverse)
{
- bool vertical = ELEM(dir, 1, 3);
+ const bool vertical = SCREEN_DIR_IS_VERTICAL(dir);
if (abs(size) < (vertical ? AREAJOINTOLERANCEX : AREAJOINTOLERANCEY)) {
return NULL;
}
@@ -484,7 +490,8 @@ static ScrArea *screen_area_trim(
float fac = abs(size) / (float)(vertical ? ((*area)->v3->vec.x - (*area)->v1->vec.x) :
((*area)->v3->vec.y - (*area)->v1->vec.y));
fac = (reverse == vertical) ? 1.0f - fac : fac;
- ScrArea *newsa = area_split(CTX_wm_window(C), screen, *area, vertical ? 'v' : 'h', fac, 1);
+ ScrArea *newsa = area_split(
+ CTX_wm_window(C), screen, *area, vertical ? SCREEN_AXIS_V : SCREEN_AXIS_H, fac, true);
/* area_split always returns smallest of the two areas, so might have to swap. */
if (((fac > 0.5f) == vertical) != reverse) {
@@ -500,8 +507,8 @@ static ScrArea *screen_area_trim(
static bool screen_area_join_ex(
bContext *C, bScreen *screen, ScrArea *sa1, ScrArea *sa2, bool close_all_remainders)
{
- int dir = area_getorientation(sa1, sa2);
- if (dir == -1) {
+ const eScreenDir dir = area_getorientation(sa1, sa2);
+ if (dir == SCREEN_DIR_NONE) {
return false;
}
@@ -534,7 +541,7 @@ int screen_area_join(bContext *C, bScreen *screen, ScrArea *sa1, ScrArea *sa2)
return screen_area_join_ex(C, screen, sa1, sa2, false);
}
-/* Close a screen area, allowing any neighbor to take its place. */
+/* Close a screen area, allowing most-aligned neighbor to take its place. */
bool screen_area_close(struct bContext *C, bScreen *screen, ScrArea *area)
{
if (area == NULL) {
@@ -542,32 +549,28 @@ bool screen_area_close(struct bContext *C, bScreen *screen, ScrArea *area)
}
ScrArea *sa2 = NULL;
-
- /* Find the most-aligned joinable area. Larger size breaks ties. */
- int min_alignment = INT_MAX;
- int max_size = 0;
- LISTBASE_FOREACH (ScrArea *, ar, &screen->areabase) {
- int dir = area_getorientation(area, ar);
- if (dir != -1) {
- int offset1;
- int offset2;
- area_getoffsets(area, ar, dir, &offset1, &offset2);
- int area_alignment = abs(offset1) + abs(offset2);
- if (area_alignment < min_alignment) {
- min_alignment = area_alignment;
- max_size = ar->winx * ar->winy;
- sa2 = ar;
- }
- else if (area_alignment == min_alignment) {
- int area_size = ar->winx * ar->winy;
- if (area_size > max_size) {
- max_size = area_size;
- sa2 = ar;
- }
+ float best_alignment = 0.0f;
+
+ LISTBASE_FOREACH (ScrArea *, neighbor, &screen->areabase) {
+ const eScreenDir dir = area_getorientation(area, neighbor);
+ /* Must at least partially share an edge and not be a global area. */
+ if ((dir != SCREEN_DIR_NONE) && (neighbor->global == NULL)) {
+ /* Winx/Winy might not be updated yet, so get lengths from verts. */
+ const bool vertical = SCREEN_DIR_IS_VERTICAL(dir);
+ const int area_length = vertical ? (area->v3->vec.x - area->v1->vec.x) :
+ (area->v3->vec.y - area->v1->vec.y);
+ const int ar_length = vertical ? (neighbor->v3->vec.x - neighbor->v1->vec.x) :
+ (neighbor->v3->vec.y - neighbor->v1->vec.y);
+ /* Calculate the ratio of the lengths of the shared edges. */
+ float alignment = MIN2(area_length, ar_length) / (float)MAX2(area_length, ar_length);
+ if (alignment > best_alignment) {
+ best_alignment = alignment;
+ sa2 = neighbor;
}
}
}
+ /* Join from neighbor into this area to close it. */
return screen_area_join_ex(C, screen, sa2, area, true);
}
diff --git a/source/blender/editors/screen/screen_geometry.c b/source/blender/editors/screen/screen_geometry.c
index ac159f4d633..51edad0332b 100644
--- a/source/blender/editors/screen/screen_geometry.c
+++ b/source/blender/editors/screen/screen_geometry.c
@@ -304,7 +304,7 @@ void screen_geom_vertices_scale(const wmWindow *win, bScreen *screen)
*/
short screen_geom_find_area_split_point(const ScrArea *area,
const rcti *window_rect,
- char dir,
+ const eScreenAxis dir_axis,
float fac)
{
const int cur_area_width = screen_geom_area_width(area);
@@ -313,17 +313,21 @@ short screen_geom_find_area_split_point(const ScrArea *area,
const short area_min_y = ED_area_headersize();
/* area big enough? */
- if ((dir == 'v') && (cur_area_width <= 2 * area_min_x)) {
- return 0;
+ if (dir_axis == SCREEN_AXIS_V) {
+ if (cur_area_width <= 2 * area_min_x) {
+ return 0;
+ }
}
- if ((dir == 'h') && (cur_area_height <= 2 * area_min_y)) {
- return 0;
+ else if (dir_axis == SCREEN_AXIS_H) {
+ if (cur_area_height <= 2 * area_min_y) {
+ return 0;
+ }
}
/* to be sure */
CLAMP(fac, 0.0f, 1.0f);
- if (dir == 'h') {
+ if (dir_axis == SCREEN_AXIS_H) {
short y = area->v1->vec.y + round_fl_to_short(fac * cur_area_height);
int area_min = area_min_y;
@@ -373,13 +377,13 @@ void screen_geom_select_connected_edge(const wmWindow *win, ScrEdge *edge)
{
bScreen *screen = WM_window_get_active_screen(win);
- /* 'dir' is the direction of EDGE */
- char dir;
+ /* 'dir_axis' is the direction of EDGE */
+ eScreenAxis dir_axis;
if (edge->v1->vec.x == edge->v2->vec.x) {
- dir = 'v';
+ dir_axis = SCREEN_AXIS_V;
}
else {
- dir = 'h';
+ dir_axis = SCREEN_AXIS_H;
}
ED_screen_verts_iter(win, screen, sv)
@@ -396,13 +400,13 @@ void screen_geom_select_connected_edge(const wmWindow *win, ScrEdge *edge)
oneselected = false;
LISTBASE_FOREACH (ScrEdge *, se, &screen->edgebase) {
if (se->v1->flag + se->v2->flag == 1) {
- if (dir == 'h') {
+ if (dir_axis == SCREEN_AXIS_H) {
if (se->v1->vec.y == se->v2->vec.y) {
se->v1->flag = se->v2->flag = 1;
oneselected = true;
}
}
- if (dir == 'v') {
+ else if (dir_axis == SCREEN_AXIS_V) {
if (se->v1->vec.x == se->v2->vec.x) {
se->v1->flag = se->v2->flag = 1;
oneselected = true;
diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h
index dd196f9621b..683f2844371 100644
--- a/source/blender/editors/screen/screen_intern.h
+++ b/source/blender/editors/screen/screen_intern.h
@@ -29,6 +29,29 @@ struct bContextDataResult;
/* internal exports only */
+typedef enum eScreenDir {
+ /** This can mean unset, unknown or invalid. */
+ SCREEN_DIR_NONE = -1,
+ /** West/Left. */
+ SCREEN_DIR_W = 0,
+ /** North/Up. */
+ SCREEN_DIR_N = 1,
+ /** East/Right. */
+ SCREEN_DIR_E = 2,
+ /** South/Down. */
+ SCREEN_DIR_S = 3,
+} eScreenDir;
+
+#define SCREEN_DIR_IS_VERTICAL(dir) (ELEM(dir, SCREEN_DIR_N, SCREEN_DIR_S))
+#define SCREEN_DIR_IS_HORIZONTAL(dir) (ELEM(dir, SCREEN_DIR_W, SCREEN_DIR_E))
+
+typedef enum eScreenAxis {
+ /** Horizontal. */
+ SCREEN_AXIS_H = 'h',
+ /** Vertical. */
+ SCREEN_AXIS_V = 'v',
+} eScreenAxis;
+
#define AZONESPOTW UI_HEADER_OFFSET /* width of corner #AZone - max */
#define AZONESPOTH (0.6f * U.widget_unit) /* height of corner #AZone */
#define AZONEFADEIN (5.0f * U.widget_unit) /* when #AZone is totally visible */
@@ -46,6 +69,10 @@ void ED_area_data_copy(ScrArea *area_dst, ScrArea *area_src, const bool do_free)
void ED_area_data_swap(ScrArea *area_dst, ScrArea *area_src);
void region_toggle_hidden(struct bContext *C, ARegion *region, const bool do_fade);
+/* screen_draw.c */
+void screen_draw_join_highlight(struct ScrArea *sa1, struct ScrArea *sa2);
+void screen_draw_split_preview(struct ScrArea *area, const eScreenAxis dir_axis, const float fac);
+
/* screen_edit.c */
bScreen *screen_add(struct Main *bmain, const char *name, const rcti *rect);
void screen_data_copy(bScreen *to, bScreen *from);
@@ -56,11 +83,16 @@ void screen_change_prepare(bScreen *screen_old,
struct Main *bmain,
struct bContext *C,
wmWindow *win);
-ScrArea *area_split(
- const wmWindow *win, bScreen *screen, ScrArea *area, char dir, float fac, int merge);
+ScrArea *area_split(const wmWindow *win,
+ bScreen *screen,
+ ScrArea *area,
+ const eScreenAxis dir_axis,
+ const float fac,
+ const bool merge);
int screen_area_join(struct bContext *C, bScreen *screen, ScrArea *sa1, ScrArea *sa2);
-int area_getorientation(ScrArea *sa_a, ScrArea *sa_b);
-void area_getoffsets(ScrArea *sa_a, ScrArea *sa_b, const int dir, int *r_offset1, int *r_offset2);
+eScreenDir area_getorientation(ScrArea *sa_a, ScrArea *sa_b);
+void area_getoffsets(
+ ScrArea *sa_a, ScrArea *sa_b, const eScreenDir dir, int *r_offset1, int *r_offset2);
bool screen_area_close(struct bContext *C, bScreen *screen, ScrArea *area);
struct AZone *ED_area_actionzone_find_xy(ScrArea *area, const int xy[2]);
@@ -83,7 +115,7 @@ ScrEdge *screen_geom_find_active_scredge(const wmWindow *win,
void screen_geom_vertices_scale(const wmWindow *win, bScreen *screen);
short screen_geom_find_area_split_point(const ScrArea *area,
const rcti *window_rect,
- char dir,
+ const eScreenAxis dir_axis,
float fac);
void screen_geom_select_connected_edge(const wmWindow *win, ScrEdge *edge);
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index eadc18de443..6b8d4e73f12 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -694,7 +694,9 @@ static bool screen_active_editable(bContext *C)
typedef struct sActionzoneData {
ScrArea *sa1, *sa2;
AZone *az;
- int x, y, gesture_dir, modifier;
+ int x, y;
+ eScreenDir gesture_dir;
+ int modifier;
} sActionzoneData;
/* quick poll to save operators to be created and handled */
@@ -1045,16 +1047,16 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* Calculate gesture cardinal direction. */
if (delta_y > abs(delta_x)) {
- sad->gesture_dir = 'n';
+ sad->gesture_dir = SCREEN_DIR_N;
}
else if (delta_x >= abs(delta_y)) {
- sad->gesture_dir = 'e';
+ sad->gesture_dir = SCREEN_DIR_E;
}
else if (delta_y < -abs(delta_x)) {
- sad->gesture_dir = 's';
+ sad->gesture_dir = SCREEN_DIR_S;
}
else {
- sad->gesture_dir = 'w';
+ sad->gesture_dir = SCREEN_DIR_W;
}
bool is_gesture;
@@ -1071,22 +1073,24 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* Are we still in same area? */
if (BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, event->x, event->y) == sad->sa1) {
/* Same area, so possible split. */
- WM_cursor_set(
- win, (ELEM(sad->gesture_dir, 'n', 's')) ? WM_CURSOR_H_SPLIT : WM_CURSOR_V_SPLIT);
+ WM_cursor_set(win,
+ SCREEN_DIR_IS_VERTICAL(sad->gesture_dir) ? WM_CURSOR_H_SPLIT :
+ WM_CURSOR_V_SPLIT);
is_gesture = (delta_max > split_threshold);
}
else {
/* Different area, so possible join. */
- if (sad->gesture_dir == 'n') {
+ if (sad->gesture_dir == SCREEN_DIR_N) {
WM_cursor_set(win, WM_CURSOR_N_ARROW);
}
- else if (sad->gesture_dir == 's') {
+ else if (sad->gesture_dir == SCREEN_DIR_S) {
WM_cursor_set(win, WM_CURSOR_S_ARROW);
}
- else if (sad->gesture_dir == 'e') {
+ else if (sad->gesture_dir == SCREEN_DIR_E) {
WM_cursor_set(win, WM_CURSOR_E_ARROW);
}
else {
+ BLI_assert(sad->gesture_dir == SCREEN_DIR_W);
WM_cursor_set(win, WM_CURSOR_W_ARROW);
}
is_gesture = (delta_max > join_threshold);
@@ -1480,7 +1484,7 @@ static void SCREEN_OT_area_close(wmOperatorType *ot)
typedef struct sAreaMoveData {
int bigger, smaller, origval, step;
- char dir;
+ eScreenAxis dir_axis;
enum AreaMoveSnapType {
/* Snapping disabled */
SNAP_NONE = 0,
@@ -1499,7 +1503,7 @@ typedef struct sAreaMoveData {
* need window bounds in order to get correct limits */
static void area_move_set_limits(wmWindow *win,
bScreen *screen,
- int dir,
+ const eScreenAxis dir_axis,
int *bigger,
int *smaller,
bool *use_bigger_smaller_snap)
@@ -1552,7 +1556,7 @@ static void area_move_set_limits(wmWindow *win,
WM_window_rect_calc(win, &window_rect);
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
- if (dir == 'h') {
+ if (dir_axis == SCREEN_AXIS_H) {
int areamin = ED_area_headersize();
if (area->v1->vec.y > window_rect.ymin) {
@@ -1615,8 +1619,8 @@ static bool area_move_init(bContext *C, wmOperator *op)
sAreaMoveData *md = MEM_callocN(sizeof(sAreaMoveData), "sAreaMoveData");
op->customdata = md;
- md->dir = screen_geom_edge_is_horizontal(actedge) ? 'h' : 'v';
- if (md->dir == 'h') {
+ md->dir_axis = screen_geom_edge_is_horizontal(actedge) ? SCREEN_AXIS_H : SCREEN_AXIS_V;
+ if (md->dir_axis == SCREEN_AXIS_H) {
md->origval = actedge->v1->vec.y;
}
else {
@@ -1631,7 +1635,8 @@ static bool area_move_init(bContext *C, wmOperator *op)
}
bool use_bigger_smaller_snap = false;
- area_move_set_limits(win, screen, md->dir, &md->bigger, &md->smaller, &use_bigger_smaller_snap);
+ area_move_set_limits(
+ win, screen, md->dir_axis, &md->bigger, &md->smaller, &use_bigger_smaller_snap);
md->snap_type = use_bigger_smaller_snap ? SNAP_BIGGER_SMALLER_ONLY : SNAP_AREAGRID;
@@ -1642,7 +1647,7 @@ static int area_snap_calc_location(const bScreen *screen,
const enum AreaMoveSnapType snap_type,
const int delta,
const int origval,
- const int dir,
+ const eScreenAxis dir_axis,
const int bigger,
const int smaller)
{
@@ -1667,7 +1672,7 @@ static int area_snap_calc_location(const bScreen *screen,
break;
case SNAP_FRACTION_AND_ADJACENT: {
- const int axis = (dir == 'v') ? 0 : 1;
+ const int axis = (dir_axis == SCREEN_AXIS_V) ? 0 : 1;
int snap_dist_best = INT_MAX;
{
const float div_array[] = {
@@ -1735,7 +1740,7 @@ static int area_snap_calc_location(const bScreen *screen,
static void area_move_apply_do(const bContext *C,
int delta,
const int origval,
- const int dir,
+ const eScreenAxis dir_axis,
const int bigger,
const int smaller,
const enum AreaMoveSnapType snap_type)
@@ -1753,11 +1758,12 @@ static void area_move_apply_do(const bContext *C,
final_loc = origval + delta;
}
else {
- final_loc = area_snap_calc_location(screen, snap_type, delta, origval, dir, bigger, smaller);
+ final_loc = area_snap_calc_location(
+ screen, snap_type, delta, origval, dir_axis, bigger, smaller);
}
BLI_assert(final_loc != -1);
- short axis = (dir == 'v') ? 0 : 1;
+ short axis = (dir_axis == SCREEN_AXIS_V) ? 0 : 1;
ED_screen_verts_iter(win, screen, v1)
{
@@ -1813,7 +1819,7 @@ static void area_move_apply(bContext *C, wmOperator *op)
sAreaMoveData *md = op->customdata;
int delta = RNA_int_get(op->ptr, "delta");
- area_move_apply_do(C, delta, md->origval, md->dir, md->bigger, md->smaller, md->snap_type);
+ area_move_apply_do(C, delta, md->origval, md->dir_axis, md->bigger, md->smaller, md->snap_type);
}
static void area_move_exit(bContext *C, wmOperator *op)
@@ -1878,7 +1884,7 @@ static int area_move_modal(bContext *C, wmOperator *op, const wmEvent *event)
int x = RNA_int_get(op->ptr, "x");
int y = RNA_int_get(op->ptr, "y");
- int delta = (md->dir == 'v') ? event->x - x : event->y - y;
+ const int delta = (md->dir_axis == SCREEN_AXIS_V) ? event->x - x : event->y - y;
RNA_int_set(op->ptr, "delta", delta);
area_move_apply(C, op);
@@ -1944,7 +1950,7 @@ static void SCREEN_OT_area_move(wmOperatorType *ot)
/*
* operator state vars:
* fac spit point
- * dir direction 'v' or 'h'
+ * dir direction #SCREEN_AXIS_V or #SCREEN_AXIS_H
*
* operator customdata:
* area pointer to (active) area
@@ -1981,7 +1987,7 @@ typedef struct sAreaSplitData {
int delta; /* delta move edge */
int origmin, origsize; /* to calculate fac, for property storage */
int previewmode; /* draw previewline, then split */
- void *draw_callback; /* call `ED_screen_draw_split_preview` */
+ void *draw_callback; /* call `screen_draw_split_preview` */
bool do_snap;
ScrEdge *nedge; /* new edge */
@@ -1996,10 +2002,10 @@ static void area_split_draw_cb(const struct wmWindow *UNUSED(win), void *userdat
sAreaSplitData *sd = op->customdata;
if (sd->sarea) {
- int dir = RNA_enum_get(op->ptr, "direction");
+ const eScreenAxis dir_axis = RNA_enum_get(op->ptr, "direction");
float fac = RNA_float_get(op->ptr, "factor");
- ED_screen_draw_split_preview(sd->sarea, dir, fac);
+ screen_draw_split_preview(sd->sarea, dir_axis, fac);
}
}
@@ -2026,14 +2032,18 @@ static bool area_split_init(bContext *C, wmOperator *op)
}
/* required properties */
- int dir = RNA_enum_get(op->ptr, "direction");
+ const eScreenAxis dir_axis = RNA_enum_get(op->ptr, "direction");
/* minimal size */
- if (dir == 'v' && area->winx < 2 * AREAMINX) {
- return false;
+ if (dir_axis == SCREEN_AXIS_V) {
+ if (area->winx < 2 * AREAMINX) {
+ return false;
+ }
}
- if (dir == 'h' && area->winy < 2 * ED_area_headersize()) {
- return false;
+ else {
+ if (area->winy < 2 * ED_area_headersize()) {
+ return false;
+ }
}
/* custom data */
@@ -2041,7 +2051,7 @@ static bool area_split_init(bContext *C, wmOperator *op)
op->customdata = sd;
sd->sarea = area;
- if (dir == 'v') {
+ if (dir_axis == SCREEN_AXIS_V) {
sd->origmin = area->v1->vec.x;
sd->origsize = area->v4->vec.x - sd->origmin;
}
@@ -2090,9 +2100,9 @@ static bool area_split_apply(bContext *C, wmOperator *op)
sAreaSplitData *sd = (sAreaSplitData *)op->customdata;
float fac = RNA_float_get(op->ptr, "factor");
- int dir = RNA_enum_get(op->ptr, "direction");
+ const eScreenAxis dir_axis = RNA_enum_get(op->ptr, "direction");
- sd->narea = area_split(win, screen, sd->sarea, dir, fac, 0); /* 0 = no merge */
+ sd->narea = area_split(win, screen, sd->sarea, dir_axis, fac, false); /* false = no merge */
if (sd->narea == NULL) {
return false;
@@ -2109,7 +2119,7 @@ static bool area_split_apply(bContext *C, wmOperator *op)
sd->nedge->v1->editflag = 1;
sd->nedge->v2->editflag = 1;
- if (dir == 'h') {
+ if (dir_axis == SCREEN_AXIS_H) {
sd->origval = sd->nedge->v1->vec.y;
}
else {
@@ -2158,8 +2168,8 @@ static void area_split_exit(bContext *C, wmOperator *op)
static void area_split_preview_update_cursor(bContext *C, wmOperator *op)
{
wmWindow *win = CTX_wm_window(C);
- int dir = RNA_enum_get(op->ptr, "direction");
- WM_cursor_set(win, dir == 'h' ? WM_CURSOR_H_SPLIT : WM_CURSOR_V_SPLIT);
+ const eScreenAxis dir_axis = RNA_enum_get(op->ptr, "direction");
+ WM_cursor_set(win, (dir_axis == SCREEN_AXIS_H) ? WM_CURSOR_H_SPLIT : WM_CURSOR_V_SPLIT);
}
/* UI callback, adds new handler */
@@ -2175,7 +2185,7 @@ static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event)
PropertyRNA *prop_factor = RNA_struct_find_property(op->ptr, "factor");
PropertyRNA *prop_cursor = RNA_struct_find_property(op->ptr, "cursor");
- int dir;
+ eScreenAxis dir_axis;
if (event->type == EVT_ACTIONZONE_AREA) {
sActionzoneData *sad = event->customdata;
@@ -2203,12 +2213,12 @@ static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event)
float factor;
/* Prepare operator state vars. */
- if (ELEM(sad->gesture_dir, 'n', 's')) {
- dir = 'h';
+ if (SCREEN_DIR_IS_VERTICAL(sad->gesture_dir)) {
+ dir_axis = SCREEN_AXIS_H;
factor = factor_h;
}
else {
- dir = 'v';
+ dir_axis = SCREEN_AXIS_V;
factor = factor_v;
}
@@ -2218,7 +2228,7 @@ static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event)
RNA_property_float_set(op->ptr, prop_factor, factor);
- RNA_property_enum_set(op->ptr, prop_dir, dir);
+ RNA_property_enum_set(op->ptr, prop_dir, dir_axis);
/* general init, also non-UI case, adds customdata, sets area and defaults */
if (!area_split_init(C, op)) {
@@ -2230,8 +2240,8 @@ static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event)
if (area == NULL) {
return OPERATOR_CANCELLED;
}
- dir = RNA_property_enum_get(op->ptr, prop_dir);
- if (dir == 'h') {
+ dir_axis = RNA_property_enum_get(op->ptr, prop_dir);
+ if (dir_axis == SCREEN_AXIS_H) {
RNA_property_float_set(
op->ptr, prop_factor, ((float)(event->x - area->v1->vec.x)) / (float)area->winx);
}
@@ -2264,9 +2274,9 @@ static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_CANCELLED;
}
- dir = screen_geom_edge_is_horizontal(actedge) ? 'v' : 'h';
+ dir_axis = screen_geom_edge_is_horizontal(actedge) ? SCREEN_AXIS_V : SCREEN_AXIS_H;
- RNA_property_enum_set(op->ptr, prop_dir, dir);
+ RNA_property_enum_set(op->ptr, prop_dir, dir_axis);
/* special case, adds customdata, sets defaults */
if (!area_split_menu_init(C, op)) {
@@ -2279,7 +2289,7 @@ static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event)
if (event->type == EVT_ACTIONZONE_AREA) {
/* do the split */
if (area_split_apply(C, op)) {
- area_move_set_limits(win, screen, dir, &sd->bigger, &sd->smaller, NULL);
+ area_move_set_limits(win, screen, dir_axis, &sd->bigger, &sd->smaller, NULL);
/* add temp handler for edge move or cancel */
G.moving |= G_TRANSFORM_WM;
@@ -2367,8 +2377,9 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event)
else {
if (event->val == KM_PRESS) {
if (sd->sarea) {
- int dir = RNA_property_enum_get(op->ptr, prop_dir);
- RNA_property_enum_set(op->ptr, prop_dir, (dir == 'v') ? 'h' : 'v');
+ const eScreenAxis dir_axis = RNA_property_enum_get(op->ptr, prop_dir);
+ RNA_property_enum_set(
+ op->ptr, prop_dir, (dir_axis == SCREEN_AXIS_V) ? SCREEN_AXIS_H : SCREEN_AXIS_V);
area_split_preview_update_cursor(C, op);
update_factor = true;
}
@@ -2389,9 +2400,9 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
if (update_factor) {
- const int dir = RNA_property_enum_get(op->ptr, prop_dir);
+ const eScreenAxis dir_axis = RNA_property_enum_get(op->ptr, prop_dir);
- sd->delta = (dir == 'v') ? event->x - sd->origval : event->y - sd->origval;
+ sd->delta = (dir_axis == SCREEN_AXIS_V) ? event->x - sd->origval : event->y - sd->origval;
if (sd->previewmode == 0) {
if (sd->do_snap) {
@@ -2399,12 +2410,12 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event)
SNAP_FRACTION_AND_ADJACENT,
sd->delta,
sd->origval,
- dir,
+ dir_axis,
sd->bigger,
sd->smaller);
sd->delta = snap_loc - sd->origval;
}
- area_move_apply_do(C, sd->delta, sd->origval, dir, sd->bigger, sd->smaller, SNAP_NONE);
+ area_move_apply_do(C, sd->delta, sd->origval, dir_axis, sd->bigger, sd->smaller, SNAP_NONE);
}
else {
if (sd->sarea) {
@@ -2415,7 +2426,7 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (sd->sarea) {
ScrArea *area = sd->sarea;
- if (dir == 'v') {
+ if (dir_axis == SCREEN_AXIS_V) {
sd->origmin = area->v1->vec.x;
sd->origsize = area->v4->vec.x - sd->origmin;
}
@@ -2431,7 +2442,7 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event)
SNAP_FRACTION_AND_ADJACENT,
sd->delta,
sd->origval,
- dir,
+ dir_axis,
sd->origmin + sd->origsize,
-sd->origmin);
@@ -2453,8 +2464,8 @@ static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
static const EnumPropertyItem prop_direction_items[] = {
- {'h', "HORIZONTAL", 0, "Horizontal", ""},
- {'v', "VERTICAL", 0, "Vertical", ""},
+ {SCREEN_AXIS_H, "HORIZONTAL", 0, "Horizontal", ""},
+ {SCREEN_AXIS_V, "VERTICAL", 0, "Vertical", ""},
{0, NULL, 0, NULL, NULL},
};
@@ -2475,7 +2486,7 @@ static void SCREEN_OT_area_split(wmOperatorType *ot)
ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL;
/* rna */
- RNA_def_enum(ot->srna, "direction", prop_direction_items, 'h', "Direction", "");
+ RNA_def_enum(ot->srna, "direction", prop_direction_items, SCREEN_AXIS_H, "Direction", "");
RNA_def_float(ot->srna, "factor", 0.5f, 0.0, 1.0, "Factor", "", 0.0, 1.0);
RNA_def_int_vector(
ot->srna, "cursor", 2, NULL, INT_MIN, INT_MAX, "Cursor", "", INT_MIN, INT_MAX);
@@ -3272,8 +3283,8 @@ static void SCREEN_OT_screen_full_area(wmOperatorType *ot)
typedef struct sAreaJoinData {
ScrArea *sa1; /* Potential source area (kept). */
ScrArea *sa2; /* Potential target area (removed or reduced). */
- int dir; /* Direction of potential join. */
- void *draw_callback; /* call 'ED_screen_draw_join_highlight' */
+ eScreenDir dir; /* Direction of potential join. */
+ void *draw_callback; /* call #screen_draw_join_highlight */
} sAreaJoinData;
@@ -3282,8 +3293,8 @@ static void area_join_draw_cb(const struct wmWindow *UNUSED(win), void *userdata
const wmOperator *op = userdata;
sAreaJoinData *sd = op->customdata;
- if (sd->sa1 && sd->sa2 && (sd->dir != -1)) {
- ED_screen_draw_join_highlight(sd->sa1, sd->sa2);
+ if (sd->sa1 && sd->sa2 && (sd->dir != SCREEN_DIR_NONE)) {
+ screen_draw_join_highlight(sd->sa1, sd->sa2);
}
}
@@ -3305,7 +3316,7 @@ static bool area_join_init(bContext *C, wmOperator *op, ScrArea *sa1, ScrArea *s
jd->sa1 = sa1;
jd->sa2 = sa2;
- jd->dir = -1;
+ jd->dir = SCREEN_DIR_NONE;
op->customdata = jd;
@@ -3318,7 +3329,7 @@ static bool area_join_init(bContext *C, wmOperator *op, ScrArea *sa1, ScrArea *s
static bool area_join_apply(bContext *C, wmOperator *op)
{
sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
- if (!jd || (jd->dir == -1)) {
+ if (!jd || (jd->dir == SCREEN_DIR_NONE)) {
return false;
}
@@ -3429,21 +3440,21 @@ static int area_join_modal(bContext *C, wmOperator *op, const wmEvent *event)
jd->dir = area_getorientation(jd->sa1, jd->sa2);
}
else if (area != jd->sa2) {
- jd->dir = -1;
+ jd->dir = SCREEN_DIR_NONE;
}
WM_event_add_notifier(C, NC_WINDOW, NULL);
- if (jd->dir == 1) {
+ if (jd->dir == SCREEN_DIR_N) {
WM_cursor_set(win, WM_CURSOR_N_ARROW);
}
- else if (jd->dir == 3) {
+ else if (jd->dir == SCREEN_DIR_S) {
WM_cursor_set(win, WM_CURSOR_S_ARROW);
}
- else if (jd->dir == 2) {
+ else if (jd->dir == SCREEN_DIR_E) {
WM_cursor_set(win, WM_CURSOR_E_ARROW);
}
- else if (jd->dir == 0) {
+ else if (jd->dir == SCREEN_DIR_W) {
WM_cursor_set(win, WM_CURSOR_W_ARROW);
}
else {
@@ -3454,7 +3465,7 @@ static int area_join_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
case LEFTMOUSE:
if (event->val == KM_RELEASE) {
- if (jd->dir == -1) {
+ if (jd->dir == SCREEN_DIR_NONE) {
area_join_cancel(C, op);
return OPERATOR_CANCELLED;
}
@@ -3528,7 +3539,7 @@ static int screen_area_options_invoke(bContext *C, wmOperator *op, const wmEvent
&ptr);
/* store initial mouse cursor position. */
RNA_int_set_array(&ptr, "cursor", &event->x);
- RNA_enum_set(&ptr, "direction", 'v');
+ RNA_enum_set(&ptr, "direction", SCREEN_AXIS_V);
/* Horizontal Split */
uiItemFullO(layout,
@@ -3541,7 +3552,7 @@ static int screen_area_options_invoke(bContext *C, wmOperator *op, const wmEvent
&ptr);
/* store initial mouse cursor position. */
RNA_int_set_array(&ptr, "cursor", &event->x);
- RNA_enum_set(&ptr, "direction", 'h');
+ RNA_enum_set(&ptr, "direction", SCREEN_AXIS_H);
if (sa1 && sa2) {
uiItemS(layout);
@@ -4126,7 +4137,7 @@ static void screen_area_menu_items(ScrArea *area, uiLayout *layout)
&ptr);
RNA_int_set_array(&ptr, "cursor", loc);
- RNA_enum_set(&ptr, "direction", 'v');
+ RNA_enum_set(&ptr, "direction", SCREEN_AXIS_V);
/* Horizontal Split */
uiItemFullO(layout,
@@ -4139,7 +4150,7 @@ static void screen_area_menu_items(ScrArea *area, uiLayout *layout)
&ptr);
RNA_int_set_array(&ptr, "cursor", &loc[0]);
- RNA_enum_set(&ptr, "direction", 'h');
+ RNA_enum_set(&ptr, "direction", SCREEN_AXIS_H);
uiItemS(layout);
@@ -5420,7 +5431,7 @@ static void context_cycle_prop_get(bScreen *screen,
static int space_context_cycle_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- const int direction = RNA_enum_get(op->ptr, "direction");
+ const eScreenCycle direction = RNA_enum_get(op->ptr, "direction");
PointerRNA ptr;
PropertyRNA *prop;
@@ -5469,7 +5480,7 @@ static int space_workspace_cycle_invoke(bContext *C, wmOperator *op, const wmEve
}
Main *bmain = CTX_data_main(C);
- const int direction = RNA_enum_get(op->ptr, "direction");
+ const eScreenCycle direction = RNA_enum_get(op->ptr, "direction");
WorkSpace *workspace_src = WM_window_get_active_workspace(win);
WorkSpace *workspace_dst = NULL;
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 7740fb42c37..3829aeebbeb 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -1324,6 +1324,13 @@ static bool paint_cursor_context_init(bContext *C,
copy_v3_fl(pcontext->outline_col, 0.8f);
}
+ const bool is_brush_tool = PAINT_brush_tool_poll(C);
+ if (!is_brush_tool) {
+ /* Use a default color for tools that are not brushes. */
+ pcontext->outline_alpha = 0.8f;
+ copy_v3_fl(pcontext->outline_col, 0.8f);
+ }
+
pcontext->is_stroke_active = pcontext->ups->stroke_active;
return true;
@@ -1610,9 +1617,11 @@ static void paint_cursor_draw_3d_view_brush_cursor_inactive(PaintCursorContext *
pcontext->radius);
}
+ const bool is_brush_tool = PAINT_brush_tool_poll(pcontext->C);
+
/* Pose brush updates and rotation origins. */
- if (brush->sculpt_tool == SCULPT_TOOL_POSE) {
+ if (is_brush_tool && brush->sculpt_tool == SCULPT_TOOL_POSE) {
/* Just after switching to the Pose Brush, the active vertex can be the same and the
* cursor won't be tagged to update, so always initialize the preview chain if it is
* null before drawing it. */
@@ -1645,7 +1654,7 @@ static void paint_cursor_draw_3d_view_brush_cursor_inactive(PaintCursorContext *
2);
}
- if (brush->sculpt_tool == SCULPT_TOOL_BOUNDARY) {
+ if (is_brush_tool && brush->sculpt_tool == SCULPT_TOOL_BOUNDARY) {
paint_cursor_preview_boundary_data_update(pcontext, update_previews);
paint_cursor_preview_boundary_data_pivot_draw(pcontext);
}
@@ -1666,17 +1675,18 @@ static void paint_cursor_draw_3d_view_brush_cursor_inactive(PaintCursorContext *
GPU_matrix_mul(pcontext->vc.obact->obmat);
/* Drawing Cursor overlays in 3D object space. */
- if (brush->sculpt_tool == SCULPT_TOOL_GRAB && (brush->flag & BRUSH_GRAB_ACTIVE_VERTEX)) {
+ if (is_brush_tool && brush->sculpt_tool == SCULPT_TOOL_GRAB &&
+ (brush->flag & BRUSH_GRAB_ACTIVE_VERTEX)) {
SCULPT_geometry_preview_lines_update(pcontext->C, pcontext->ss, pcontext->radius);
sculpt_geometry_preview_lines_draw(
pcontext->pos, pcontext->brush, pcontext->is_multires, pcontext->ss);
}
- if (brush->sculpt_tool == SCULPT_TOOL_POSE) {
+ if (is_brush_tool && brush->sculpt_tool == SCULPT_TOOL_POSE) {
paint_cursor_pose_brush_segments_draw(pcontext);
}
- if (brush->sculpt_tool == SCULPT_TOOL_BOUNDARY) {
+ if (is_brush_tool && brush->sculpt_tool == SCULPT_TOOL_BOUNDARY) {
SCULPT_boundary_edges_preview_draw(
pcontext->pos, pcontext->ss, pcontext->outline_col, pcontext->outline_alpha);
SCULPT_boundary_pivot_line_preview_draw(pcontext->pos, pcontext->ss);
@@ -1692,7 +1702,7 @@ static void paint_cursor_draw_3d_view_brush_cursor_inactive(PaintCursorContext *
paint_cursor_draw_main_inactive_cursor(pcontext);
/* Cloth brush local simulation areas. */
- if (brush->sculpt_tool == SCULPT_TOOL_CLOTH &&
+ if (is_brush_tool && brush->sculpt_tool == SCULPT_TOOL_CLOTH &&
brush->cloth_simulation_area_type != BRUSH_CLOTH_SIMULATION_AREA_GLOBAL) {
const float white[3] = {1.0f, 1.0f, 1.0f};
const float zero_v[3] = {0.0f};
@@ -1704,7 +1714,7 @@ static void paint_cursor_draw_3d_view_brush_cursor_inactive(PaintCursorContext *
}
/* Layer brush height. */
- if (brush->sculpt_tool == SCULPT_TOOL_LAYER) {
+ if (is_brush_tool && brush->sculpt_tool == SCULPT_TOOL_LAYER) {
SCULPT_layer_brush_height_preview_draw(pcontext->pos,
brush,
pcontext->radius,
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 3ca0d853d6a..3f5093222e9 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -87,7 +87,7 @@ struct ViewContext *paint_stroke_view_context(struct PaintStroke *stroke);
void *paint_stroke_mode_data(struct PaintStroke *stroke);
float paint_stroke_distance_get(struct PaintStroke *stroke);
void paint_stroke_set_mode_data(struct PaintStroke *stroke, void *mode_data);
-bool paint_poll(struct bContext *C);
+bool PAINT_brush_tool_poll(struct bContext *C);
void paint_cursor_start(struct Paint *p, bool (*poll)(struct bContext *C));
void paint_cursor_delete_textures(void);
diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c
index e1dc8fa30b9..fed89e02e8f 100644
--- a/source/blender/editors/sculpt_paint/paint_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_ops.c
@@ -139,13 +139,14 @@ static int brush_scale_size_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Paint *paint = BKE_paint_get_active_from_context(C);
Brush *brush = BKE_paint_brush(paint);
+ const bool is_gpencil = (brush && brush->gpencil_settings != NULL);
// Object *ob = CTX_data_active_object(C);
float scalar = RNA_float_get(op->ptr, "scalar");
if (brush) {
/* pixel radius */
{
- const int old_size = BKE_brush_size_get(scene, brush);
+ const int old_size = (!is_gpencil) ? BKE_brush_size_get(scene, brush) : brush->size;
int size = (int)(scalar * old_size);
if (abs(old_size - size) < U.pixelsize) {
@@ -156,6 +157,12 @@ static int brush_scale_size_exec(bContext *C, wmOperator *op)
size -= U.pixelsize;
}
}
+ /* Grease Pencil does not use unified size. */
+ if (is_gpencil) {
+ brush->size = max_ii(size, 1);
+ WM_main_add_notifier(NC_BRUSH | NA_EDITED, brush);
+ return OPERATOR_FINISHED;
+ }
BKE_brush_size_set(scene, brush, size);
}
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 49ddf2f82d8..b093f07226e 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -1462,7 +1462,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (paint_supports_smooth_stroke(br, mode)) {
stroke->stroke_cursor = WM_paint_cursor_activate(
- SPACE_TYPE_ANY, RGN_TYPE_ANY, paint_poll, paint_draw_smooth_cursor, stroke);
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, PAINT_brush_tool_poll, paint_draw_smooth_cursor, stroke);
}
stroke->stroke_init = true;
@@ -1489,7 +1489,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (br->flag & BRUSH_LINE) {
stroke->stroke_cursor = WM_paint_cursor_activate(
- SPACE_TYPE_ANY, RGN_TYPE_ANY, paint_poll, paint_draw_line_cursor, stroke);
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, PAINT_brush_tool_poll, paint_draw_line_cursor, stroke);
}
first_dab = true;
@@ -1659,7 +1659,7 @@ void paint_stroke_set_mode_data(PaintStroke *stroke, void *mode_data)
stroke->mode_data = mode_data;
}
-bool paint_poll(bContext *C)
+bool PAINT_brush_tool_poll(bContext *C)
{
Paint *p = BKE_paint_get_active_from_context(C);
Object *ob = CTX_data_active_object(C);
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 964e5bdaa90..2e1dd928f96 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -780,6 +780,10 @@ static void sculpt_vertex_neighbors_get_faces(SculptSession *ss,
iter->neighbors = iter->neighbors_fixed;
for (int i = 0; i < ss->pmap[index].count; i++) {
+ if (ss->face_sets[vert_map->indices[i]] < 0) {
+ /* Skip connectivity from hidden faces. */
+ continue;
+ }
const MPoly *p = &ss->mpoly[vert_map->indices[i]];
uint f_adj_v[2];
if (poly_get_adj_loops_from_vert(p, ss->mloop, index, f_adj_v) != -1) {
@@ -6602,7 +6606,7 @@ bool SCULPT_poll_view3d(bContext *C)
bool SCULPT_poll(bContext *C)
{
- return SCULPT_mode_poll(C) && paint_poll(C);
+ return SCULPT_mode_poll(C) && PAINT_brush_tool_poll(C);
}
static const char *sculpt_tool_name(Sculpt *sd)
diff --git a/source/blender/editors/sculpt_paint/sculpt_expand.c b/source/blender/editors/sculpt_paint/sculpt_expand.c
index 8b8ed42a694..40874375772 100644
--- a/source/blender/editors/sculpt_paint/sculpt_expand.c
+++ b/source/blender/editors/sculpt_paint/sculpt_expand.c
@@ -273,7 +273,7 @@ static bool sculpt_expand_state_get(SculptSession *ss, ExpandCache *expand_cache
*/
static bool sculpt_expand_face_state_get(SculptSession *ss, ExpandCache *expand_cache, const int f)
{
- if (ss->face_sets[f] <= 0) {
+ if (expand_cache->original_face_sets[f] <= 0) {
return false;
}
@@ -1398,6 +1398,13 @@ static void sculpt_expand_face_sets_restore(SculptSession *ss, ExpandCache *expa
{
const int totfaces = ss->totfaces;
for (int i = 0; i < totfaces; i++) {
+ if (expand_cache->original_face_sets[i] <= 0) {
+ /* Do not modify hidden Face Sets, even when restoring the IDs state. */
+ continue;
+ }
+ if (!sculpt_expand_is_face_in_active_component(ss, expand_cache, i)) {
+ continue;
+ }
ss->face_sets[i] = expand_cache->initial_face_sets[i];
}
}
@@ -1892,13 +1899,22 @@ static int sculpt_expand_modal(bContext *C, wmOperator *op, const wmEvent *event
* The faces that were using the `delete_id` Face Set are filled
* using the content from their neighbors.
*/
-static void sculpt_expand_delete_face_set_id(
- int *r_face_sets, Mesh *mesh, MeshElemMap *pmap, const int totface, const int delete_id)
+static void sculpt_expand_delete_face_set_id(int *r_face_sets,
+ SculptSession *ss,
+ ExpandCache *expand_cache,
+ Mesh *mesh,
+ const int delete_id)
{
+ const int totface = ss->totfaces;
+ MeshElemMap *pmap = ss->pmap;
+
/* Check that all the face sets IDs in the mesh are not equal to `delete_id`
* before attempting to delete it. */
bool all_same_id = true;
for (int i = 0; i < totface; i++) {
+ if (!sculpt_expand_is_face_in_active_component(ss, expand_cache, i)) {
+ continue;
+ }
if (r_face_sets[i] != delete_id) {
all_same_id = false;
break;
@@ -1921,6 +1937,7 @@ static void sculpt_expand_delete_face_set_id(
}
while (BLI_LINKSTACK_SIZE(queue)) {
+ bool any_updated = false;
while (BLI_LINKSTACK_SIZE(queue)) {
const int f_index = POINTER_AS_INT(BLI_LINKSTACK_POP(queue));
int other_id = delete_id;
@@ -1931,6 +1948,10 @@ static void sculpt_expand_delete_face_set_id(
for (int i = 0; i < vert_map->count; i++) {
const int neighbor_face_index = vert_map->indices[i];
+ if (expand_cache->original_face_sets[neighbor_face_index] <= 0) {
+ /* Skip picking IDs from hidden Face Sets. */
+ continue;
+ }
if (r_face_sets[neighbor_face_index] != delete_id) {
other_id = r_face_sets[neighbor_face_index];
}
@@ -1938,18 +1959,36 @@ static void sculpt_expand_delete_face_set_id(
}
if (other_id != delete_id) {
+ any_updated = true;
r_face_sets[f_index] = other_id;
}
else {
BLI_LINKSTACK_PUSH(queue_next, POINTER_FROM_INT(f_index));
}
}
+ if (!any_updated) {
+ /* No Face Sets where updated in this iteration, which means that no more content to keep
+ * filling the polys of the deleted Face Set was found. Break to avoid entering an infinite
+ * loop trying to search for those polys again. */
+ break;
+ }
BLI_LINKSTACK_SWAP(queue, queue_next);
}
BLI_LINKSTACK_FREE(queue);
BLI_LINKSTACK_FREE(queue_next);
+
+ /* Ensure that the visibility state of the modified Face Sets is the same as the original ones.
+ */
+ for (int i = 0; i < totface; i++) {
+ if (expand_cache->original_face_sets[i] >= 0) {
+ r_face_sets[i] = abs(r_face_sets[i]);
+ }
+ else {
+ r_face_sets[i] = -abs(r_face_sets[i]);
+ }
+ }
}
static void sculpt_expand_cache_initial_config_set(bContext *C,
@@ -2070,9 +2109,9 @@ static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *even
if (ss->expand_cache->modify_active_face_set) {
sculpt_expand_delete_face_set_id(ss->expand_cache->initial_face_sets,
+ ss,
+ ss->expand_cache,
ob->data,
- ss->pmap,
- ss->totfaces,
ss->expand_cache->next_face_set);
}
diff --git a/source/blender/editors/space_buttons/CMakeLists.txt b/source/blender/editors/space_buttons/CMakeLists.txt
index c71e5e49d8d..b5f6874fcfc 100644
--- a/source/blender/editors/space_buttons/CMakeLists.txt
+++ b/source/blender/editors/space_buttons/CMakeLists.txt
@@ -50,7 +50,7 @@ if(WITH_FREESTYLE)
endif()
if(WITH_EXPERIMENTAL_FEATURES)
- add_definitions(-DWITH_GEOMETRY_NODES)
+ add_definitions(-DWITH_SIMULATION_DATABLOCK)
add_definitions(-DWITH_POINT_CLOUD)
add_definitions(-DWITH_HAIR_NODES)
endif()
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index 1699e704a4d..aeb2c04656e 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -975,7 +975,8 @@ int /*eContextResult*/ buttons_context(const bContext *C,
if (matnr < 0) {
matnr = 0;
}
- CTX_data_pointer_set(result, &ob->id, &RNA_MaterialSlot, &ob->mat[matnr]);
+ /* Keep aligned with rna_Object_material_slots_get. */
+ CTX_data_pointer_set(result, &ob->id, &RNA_MaterialSlot, POINTER_FROM_INT(matnr + 1));
}
}
diff --git a/source/blender/editors/space_buttons/buttons_intern.h b/source/blender/editors/space_buttons/buttons_intern.h
index 74e7bc11c26..7564fa4b930 100644
--- a/source/blender/editors/space_buttons/buttons_intern.h
+++ b/source/blender/editors/space_buttons/buttons_intern.h
@@ -35,6 +35,7 @@ struct bContext;
struct bContextDataResult;
struct bNode;
struct bNodeTree;
+struct bNodeSocket;
struct wmOperatorType;
struct SpaceProperties_Runtime {
@@ -66,6 +67,7 @@ typedef struct ButsTextureUser {
struct bNodeTree *ntree;
struct bNode *node;
+ struct bNodeSocket *socket;
const char *category;
int icon;
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index 43128ed00fa..97e3cb750c1 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -75,15 +75,16 @@ static SpaceProperties *find_space_properties(const bContext *C);
/************************* Texture User **************************/
-static void buttons_texture_user_node_property_add(ListBase *users,
- ID *id,
- PointerRNA ptr,
- PropertyRNA *prop,
- bNodeTree *ntree,
- bNode *node,
- const char *category,
- int icon,
- const char *name)
+static void buttons_texture_user_socket_property_add(ListBase *users,
+ ID *id,
+ PointerRNA ptr,
+ PropertyRNA *prop,
+ bNodeTree *ntree,
+ bNode *node,
+ bNodeSocket *socket,
+ const char *category,
+ int icon,
+ const char *name)
{
ButsTextureUser *user = MEM_callocN(sizeof(ButsTextureUser), "ButsTextureUser");
@@ -92,6 +93,7 @@ static void buttons_texture_user_node_property_add(ListBase *users,
user->prop = prop;
user->ntree = ntree;
user->node = node;
+ user->socket = socket;
user->category = category;
user->icon = icon;
user->name = name;
@@ -181,25 +183,29 @@ static void buttons_texture_modifier_geonodes_users_add(Object *ob,
/* Recurse into the node group */
buttons_texture_modifier_geonodes_users_add(ob, nmd, (bNodeTree *)node->id, users);
}
- else if (node->type == GEO_NODE_ATTRIBUTE_SAMPLE_TEXTURE) {
- RNA_pointer_create(&node_tree->id, &RNA_Node, node, &ptr);
- prop = RNA_struct_find_property(&ptr, "texture");
- if (prop == NULL) {
+ LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
+ if (socket->flag & SOCK_UNAVAIL) {
+ continue;
+ }
+ if (socket->type != SOCK_TEXTURE) {
continue;
}
+ RNA_pointer_create(&node_tree->id, &RNA_NodeSocket, socket, &ptr);
+ prop = RNA_struct_find_property(&ptr, "default_value");
PointerRNA texptr = RNA_property_pointer_get(&ptr, prop);
Tex *tex = (RNA_struct_is_a(texptr.type, &RNA_Texture)) ? (Tex *)texptr.data : NULL;
if (tex != NULL) {
- buttons_texture_user_node_property_add(users,
- &ob->id,
- ptr,
- prop,
- node_tree,
- node,
- N_("Geometry Nodes"),
- RNA_struct_ui_icon(ptr.type),
- nmd->modifier.name);
+ buttons_texture_user_socket_property_add(users,
+ &ob->id,
+ ptr,
+ prop,
+ node_tree,
+ node,
+ socket,
+ N_("Geometry Nodes"),
+ RNA_struct_ui_icon(ptr.type),
+ nmd->modifier.name);
}
}
}
diff --git a/source/blender/editors/space_clip/tracking_ops_track.c b/source/blender/editors/space_clip/tracking_ops_track.c
index 9882304d97d..0a99d1020f6 100644
--- a/source/blender/editors/space_clip/tracking_ops_track.c
+++ b/source/blender/editors/space_clip/tracking_ops_track.c
@@ -24,8 +24,11 @@
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
+#include "BLI_string.h"
#include "BLI_utildefines.h"
+#include "BLT_translation.h"
+
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_main.h"
@@ -398,6 +401,28 @@ static int track_markers_modal(bContext *C, wmOperator *UNUSED(op), const wmEven
return OPERATOR_PASS_THROUGH;
}
+static char *track_markers_desc(bContext *UNUSED(C), wmOperatorType *UNUSED(op), PointerRNA *ptr)
+{
+ const bool backwards = RNA_boolean_get(ptr, "backwards");
+ const bool sequence = RNA_boolean_get(ptr, "sequence");
+
+ if (backwards && sequence) {
+ return BLI_strdup(TIP_("Track the selected markers backward for the entire clip"));
+ }
+ if (backwards && !sequence) {
+ return BLI_strdup(TIP_("Track the selected markers backward by one frame"));
+ }
+ if (!backwards && sequence) {
+ return BLI_strdup(TIP_("Track the selected markers forward for the entire clip"));
+ }
+ if (!backwards && !sequence) {
+ return BLI_strdup(TIP_("Track the selected markers forward by one frame"));
+ }
+
+ /* Use default description. */
+ return NULL;
+}
+
void CLIP_OT_track_markers(wmOperatorType *ot)
{
/* identifiers */
@@ -410,6 +435,7 @@ void CLIP_OT_track_markers(wmOperatorType *ot)
ot->invoke = track_markers_invoke;
ot->modal = track_markers_modal;
ot->poll = ED_space_clip_tracking_poll;
+ ot->get_description = track_markers_desc;
/* flags */
ot->flag = OPTYPE_UNDO;
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index c1dcf2e56d3..189b9b4c874 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -323,6 +323,7 @@ static void file_draw_preview(uiBlock *block,
int ex, ey;
bool show_outline = !is_icon &&
(file->typeflag & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_BLENDER));
+ const bool is_offline = (file->attributes & FILE_ATTR_OFFLINE);
BLI_assert(imb != NULL);
@@ -419,14 +420,14 @@ static void file_draw_preview(uiBlock *block,
icon_x, icon_y, icon, icon_aspect / U.dpi_fac, icon_opacity, 0.0f, icon_color, false);
}
- if (is_link) {
- /* Arrow icon to indicate it is a shortcut, link, or alias. */
+ if (is_link || is_offline) {
+ /* Icon at bottom to indicate it is a shortcut, link, alias, or offline. */
float icon_x, icon_y;
icon_x = xco + (2.0f * UI_DPI_FAC);
icon_y = yco + (2.0f * UI_DPI_FAC);
- const int arrow = ICON_LOOP_FORWARDS;
+ const int arrow = is_link ? ICON_LOOP_FORWARDS : ICON_URL;
if (!is_icon) {
- /* Arrow at very bottom-left if preview style. */
+ /* At very bottom-left if preview style. */
const uchar dark[4] = {0, 0, 0, 255};
const uchar light[4] = {255, 255, 255, 255};
UI_icon_draw_ex(icon_x + 1, icon_y - 1, arrow, 1.0f / U.dpi_fac, 0.2f, 0.0f, dark, false);
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index c2b3a7ac0ee..37a32164cfc 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -1601,37 +1601,51 @@ static void filelist_cache_previews_push(FileList *filelist, FileDirEntry *entry
BLI_assert(cache->flags & FLC_PREVIEWS_ACTIVE);
- if (!entry->preview_icon_id && !(entry->flags & FILE_ENTRY_INVALID_PREVIEW) &&
- (entry->typeflag & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT |
- FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB))) {
- FileListEntryPreview *preview = MEM_mallocN(sizeof(*preview), __func__);
- FileListInternEntry *intern_entry = filelist->filelist_intern.filtered[index];
+ if (!entry->preview_icon_id && (entry->attributes & FILE_ATTR_OFFLINE)) {
+ entry->flags |= FILE_ENTRY_INVALID_PREVIEW;
+ return;
+ }
- if (entry->redirection_path) {
- BLI_strncpy(preview->path, entry->redirection_path, FILE_MAXDIR);
- }
- else {
- BLI_join_dirfile(
- preview->path, sizeof(preview->path), filelist->filelist.root, entry->relpath);
- }
+ if (entry->preview_icon_id) {
+ return;
+ }
- preview->index = index;
- preview->flags = entry->typeflag;
- preview->in_memory_preview = intern_entry->local_data.preview_image;
- preview->icon_id = 0;
- // printf("%s: %d - %s - %p\n", __func__, preview->index, preview->path, preview->img);
+ if (entry->flags & FILE_ENTRY_INVALID_PREVIEW) {
+ return;
+ }
+
+ if (!(entry->typeflag & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_FTFONT |
+ FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP | FILE_TYPE_BLENDERLIB))) {
+ return;
+ }
- filelist_cache_preview_ensure_running(cache);
+ FileListEntryPreview *preview = MEM_mallocN(sizeof(*preview), __func__);
+ FileListInternEntry *intern_entry = filelist->filelist_intern.filtered[index];
- FileListEntryPreviewTaskData *preview_taskdata = MEM_mallocN(sizeof(*preview_taskdata),
- __func__);
- preview_taskdata->preview = preview;
- BLI_task_pool_push(cache->previews_pool,
- filelist_cache_preview_runf,
- preview_taskdata,
- true,
- filelist_cache_preview_freef);
+ if (entry->redirection_path) {
+ BLI_strncpy(preview->path, entry->redirection_path, FILE_MAXDIR);
+ }
+ else {
+ BLI_join_dirfile(
+ preview->path, sizeof(preview->path), filelist->filelist.root, entry->relpath);
}
+
+ preview->index = index;
+ preview->flags = entry->typeflag;
+ preview->in_memory_preview = intern_entry->local_data.preview_image;
+ preview->icon_id = 0;
+ // printf("%s: %d - %s - %p\n", __func__, preview->index, preview->path, preview->img);
+
+ filelist_cache_preview_ensure_running(cache);
+
+ FileListEntryPreviewTaskData *preview_taskdata = MEM_mallocN(sizeof(*preview_taskdata),
+ __func__);
+ preview_taskdata->preview = preview;
+ BLI_task_pool_push(cache->previews_pool,
+ filelist_cache_preview_runf,
+ preview_taskdata,
+ true,
+ filelist_cache_preview_freef);
}
static void filelist_cache_init(FileListEntryCache *cache, size_t cache_size)
@@ -2360,17 +2374,19 @@ bool filelist_file_cache_block(struct FileList *filelist, const int index)
// printf("Re-queueing previews...\n");
- /* Note we try to preview first images around given index - i.e. assumed visible ones. */
if (cache->flags & FLC_PREVIEWS_ACTIVE) {
- for (i = 0; ((index + i) < end_index) || ((index - i) >= start_index); i++) {
- if ((index - i) >= start_index) {
- const int idx = (cache->block_cursor + (index - start_index) - i) % cache_size;
- filelist_cache_previews_push(filelist, cache->block_entries[idx], index - i);
- }
- if ((index + i) < end_index) {
- const int idx = (cache->block_cursor + (index - start_index) + i) % cache_size;
- filelist_cache_previews_push(filelist, cache->block_entries[idx], index + i);
- }
+ /* Note we try to preview first images around given index - i.e. assumed visible ones. */
+ int block_index = cache->block_cursor + (index - start_index);
+ int offs_max = max_ii(end_index - index, index - start_index);
+ for (i = 0; i <= offs_max; i++) {
+ int offs = i;
+ do {
+ int offs_idx = index + offs;
+ if (start_index <= offs_idx && offs_idx < end_index) {
+ int offs_block_idx = (block_index + offs) % (int)cache_size;
+ filelist_cache_previews_push(filelist, cache->block_entries[offs_block_idx], offs_idx);
+ }
+ } while ((offs = -offs) < 0); /* Switch between negative and positive offset. */
}
}
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
index 8bf6f2698e0..7d4011e0812 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -266,7 +266,7 @@ static void nla_strip_get_color_inside(AnimData *adt, NlaStrip *strip, float col
}
else if (strip->type == NLASTRIP_TYPE_META) {
/* Meta Clip */
- /* TODO: should temporary metas get different colors too? */
+ /* TODO: should temporary meta-strips get different colors too? */
if (strip->flag & NLASTRIP_FLAG_SELECT) {
/* selected - use a bold purple color */
UI_GetThemeColor3fv(TH_NLA_META_SEL, color);
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 5110c14ef4d..6b4366b2966 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -456,7 +456,9 @@ static void node_draw_frame(const bContext *C,
}
/* label */
- node_draw_frame_label(ntree, node, snode->runtime->aspect);
+ if (node->label[0] != '\0') {
+ node_draw_frame_label(ntree, node, snode->runtime->aspect);
+ }
UI_block_end(C, node->block);
UI_block_draw(C, node->block);
@@ -3332,12 +3334,14 @@ static const float std_node_socket_colors[][4] = {
{0.39, 0.78, 0.39, 1.0}, /* SOCK_SHADER */
{0.80, 0.65, 0.84, 1.0}, /* SOCK_BOOLEAN */
{0.0, 0.0, 0.0, 1.0}, /*__SOCK_MESH (deprecated) */
- {0.25, 0.75, 0.26, 1.0}, /* SOCK_INT */
+ {0.35, 0.55, 0.36, 1.0}, /* SOCK_INT */
{0.44, 0.70, 1.00, 1.0}, /* SOCK_STRING */
{0.93, 0.62, 0.36, 1.0}, /* SOCK_OBJECT */
- {0.89, 0.76, 0.43, 1.0}, /* SOCK_IMAGE */
+ {0.39, 0.22, 0.39, 1.0}, /* SOCK_IMAGE */
{0.00, 0.84, 0.64, 1.0}, /* SOCK_GEOMETRY */
{0.96, 0.96, 0.96, 1.0}, /* SOCK_COLLECTION */
+ {0.62, 0.31, 0.64, 1.0}, /* SOCK_TEXTURE */
+ {0.92, 0.46, 0.51, 1.0}, /* SOCK_MATERIAL */
};
/* common color callbacks for standard types */
@@ -3478,6 +3482,14 @@ static void std_node_socket_draw(
uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, text, 0);
break;
}
+ case SOCK_TEXTURE: {
+ uiTemplateID(layout, C, ptr, "default_value", "texture.new", NULL, NULL, 0, ICON_NONE, NULL);
+ break;
+ }
+ case SOCK_MATERIAL: {
+ uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, text, 0);
+ break;
+ }
default:
node_socket_button_label(C, layout, ptr, node_ptr, text);
break;
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index d4780534a83..50fa8b28468 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -1713,8 +1713,6 @@ static int node_mute_exec(bContext *C, wmOperator *UNUSED(op))
}
}
- do_tag_update |= ED_node_is_geometry(snode);
-
snode_notify(C, snode);
if (do_tag_update) {
snode_dag_update(C, snode);
@@ -1755,8 +1753,6 @@ static int node_delete_exec(bContext *C, wmOperator *UNUSED(op))
}
}
- do_tag_update |= ED_node_is_geometry(snode);
-
ntreeUpdateTree(CTX_data_main(C), snode->edittree);
snode_notify(C, snode);
diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c
index 91fe8f5ec89..28c660b0632 100644
--- a/source/blender/editors/space_node/node_relationships.c
+++ b/source/blender/editors/space_node/node_relationships.c
@@ -852,8 +852,6 @@ static void node_link_exit(bContext *C, wmOperator *op, bool apply_links)
}
ntree->is_updating = false;
- do_tag_update |= ED_node_is_geometry(snode);
-
ntreeUpdateTree(bmain, ntree);
snode_notify(C, snode);
if (do_tag_update) {
@@ -1291,8 +1289,6 @@ static int cut_links_exec(bContext *C, wmOperator *op)
}
}
- do_tag_update |= ED_node_is_geometry(snode);
-
if (found) {
ntreeUpdateTree(CTX_data_main(C), snode->edittree);
snode_notify(C, snode);
@@ -1399,8 +1395,6 @@ static int mute_links_exec(bContext *C, wmOperator *op)
link->flag &= ~NODE_LINK_TEST;
}
- do_tag_update |= ED_node_is_geometry(snode);
-
ntreeUpdateTree(CTX_data_main(C), snode->edittree);
snode_notify(C, snode);
if (do_tag_update) {
@@ -1882,28 +1876,63 @@ void ED_node_link_intersect_test(ScrArea *area, int test)
}
}
-/* assumes sockets in list */
-static bNodeSocket *socket_best_match(ListBase *sockets)
-{
- /* find type range */
- int maxtype = 0;
+static int get_main_socket_priority(const bNodeSocket *socket)
+{
+ switch ((eNodeSocketDatatype)socket->type) {
+ case __SOCK_MESH:
+ case SOCK_CUSTOM:
+ return -1;
+ case SOCK_BOOLEAN:
+ return 0;
+ case SOCK_INT:
+ return 1;
+ case SOCK_FLOAT:
+ return 2;
+ case SOCK_VECTOR:
+ return 3;
+ case SOCK_RGBA:
+ return 4;
+ case SOCK_STRING:
+ case SOCK_SHADER:
+ case SOCK_OBJECT:
+ case SOCK_IMAGE:
+ case SOCK_GEOMETRY:
+ case SOCK_COLLECTION:
+ case SOCK_TEXTURE:
+ case SOCK_MATERIAL:
+ return 5;
+ }
+ return -1;
+}
+
+/** Get the "main" socket of a socket list using a heuristic based on socket types. */
+static bNodeSocket *get_main_socket(ListBase *sockets)
+{
+ /* find priority range */
+ int maxpriority = -1;
LISTBASE_FOREACH (bNodeSocket *, sock, sockets) {
- maxtype = max_ii(sock->type, maxtype);
+ if (sock->flag & SOCK_UNAVAIL) {
+ continue;
+ }
+ maxpriority = max_ii(get_main_socket_priority(sock), maxpriority);
}
- /* try all types, starting from 'highest' (i.e. colors, vectors, values) */
- for (int type = maxtype; type >= 0; type--) {
+ /* try all priorities, starting from 'highest' */
+ for (int priority = maxpriority; priority >= 0; priority--) {
LISTBASE_FOREACH (bNodeSocket *, sock, sockets) {
- if (!nodeSocketIsHidden(sock) && type == sock->type) {
+ if (!nodeSocketIsHidden(sock) && priority == get_main_socket_priority(sock)) {
return sock;
}
}
}
- /* no visible sockets, unhide first of highest type */
- for (int type = maxtype; type >= 0; type--) {
+ /* no visible sockets, unhide first of highest priority */
+ for (int priority = maxpriority; priority >= 0; priority--) {
LISTBASE_FOREACH (bNodeSocket *, sock, sockets) {
- if (type == sock->type) {
+ if (sock->flag & SOCK_UNAVAIL) {
+ continue;
+ }
+ if (priority == get_main_socket_priority(sock)) {
sock->flag &= ~SOCK_HIDDEN;
return sock;
}
@@ -2248,8 +2277,8 @@ void ED_node_link_insert(Main *bmain, ScrArea *area)
}
if (link) {
- bNodeSocket *best_input = socket_best_match(&select->inputs);
- bNodeSocket *best_output = socket_best_match(&select->outputs);
+ bNodeSocket *best_input = get_main_socket(&select->inputs);
+ bNodeSocket *best_output = get_main_socket(&select->outputs);
if (best_input && best_output) {
bNode *node = link->tonode;
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 456c2079f27..c532dd8accd 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -902,7 +902,7 @@ static void id_override_library_reset_fn(bContext *C,
}
static void id_override_library_resync_fn(bContext *C,
- ReportList *UNUSED(reports),
+ ReportList *reports,
Scene *scene,
TreeElement *te,
TreeStoreElem *UNUSED(tsep),
@@ -931,7 +931,7 @@ static void id_override_library_resync_fn(bContext *C,
}
BKE_lib_override_library_resync(
- bmain, scene, CTX_data_view_layer(C), id_root, NULL, do_hierarchy_enforce, true);
+ bmain, scene, CTX_data_view_layer(C), id_root, NULL, do_hierarchy_enforce, true, reports);
WM_event_add_notifier(C, NC_WINDOW, NULL);
}
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 7beb61e48d2..b55c8035fa3 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -885,10 +885,12 @@ static void draw_seq_background(Scene *scene,
immUniformColor4ubv(col);
if (seq->startstill) {
- immRectf(pos, seq->startdisp, y1, (float)(seq->start), y2);
+ const float content_start = min_ff(seq->enddisp, seq->start);
+ immRectf(pos, seq->startdisp, y1, content_start, y2);
}
if (seq->endstill) {
- immRectf(pos, (float)(seq->start + seq->len), y1, seq->enddisp, y2);
+ const float content_end = max_ff(seq->startdisp, seq->start + seq->len);
+ immRectf(pos, content_end, y1, seq->enddisp, y2);
}
}
@@ -1105,6 +1107,10 @@ static void draw_seq_strip(const bContext *C,
x2 = (seq->endstill) ? (seq->start + seq->len) : seq->enddisp;
y2 = seq->machine + SEQ_STRIP_OFSTOP;
+ /* Limit body to strip bounds. Meta strip can end up with content outside of strip range. */
+ x1 = min_ff(x1, seq->enddisp);
+ x2 = max_ff(x2, seq->startdisp);
+
float text_margin_y;
bool y_threshold;
if ((sseq->flag & SEQ_SHOW_STRIP_NAME) || (sseq->flag & SEQ_SHOW_STRIP_SOURCE) ||
@@ -1522,10 +1528,10 @@ static void *sequencer_OCIO_transform_ibuf(const bContext *C,
ImBuf *ibuf,
bool *r_glsl_used,
eGPUTextureFormat *r_format,
- eGPUDataFormat *r_data)
+ eGPUDataFormat *r_data,
+ void **r_buffer_cache_handle)
{
void *display_buffer;
- void *cache_handle = NULL;
bool force_fallback = false;
*r_glsl_used = false;
force_fallback |= (ED_draw_imbuf_method(ibuf) != IMAGE_DRAW_METHOD_GLSL);
@@ -1578,13 +1584,10 @@ static void *sequencer_OCIO_transform_ibuf(const bContext *C,
/* There is data to be displayed, but GLSL is not initialized
* properly, in this case we fallback to CPU-based display transform. */
if ((ibuf->rect || ibuf->rect_float) && !*r_glsl_used) {
- display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
+ display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, r_buffer_cache_handle);
*r_format = GPU_RGBA8;
*r_data = GPU_DATA_UBYTE;
}
- if (cache_handle) {
- IMB_display_buffer_release(cache_handle);
- }
return display_buffer;
}
@@ -1658,6 +1661,7 @@ static void sequencer_draw_display_buffer(const bContext *C,
bool draw_backdrop)
{
void *display_buffer;
+ void *buffer_cache_handle = NULL;
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) {
GPU_blend(GPU_BLEND_ALPHA);
@@ -1685,7 +1689,8 @@ static void sequencer_draw_display_buffer(const bContext *C,
data = GPU_DATA_UBYTE;
}
else {
- display_buffer = sequencer_OCIO_transform_ibuf(C, ibuf, &glsl_used, &format, &data);
+ display_buffer = sequencer_OCIO_transform_ibuf(
+ C, ibuf, &glsl_used, &format, &data, &buffer_cache_handle);
}
if (draw_backdrop) {
@@ -1745,6 +1750,10 @@ static void sequencer_draw_display_buffer(const bContext *C,
IMB_colormanagement_finish_glsl_draw();
}
+ if (buffer_cache_handle) {
+ IMB_display_buffer_release(buffer_cache_handle);
+ }
+
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) {
GPU_blend(GPU_BLEND_NONE);
}
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 9c204373ffc..ebd4c0090b4 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -290,7 +290,7 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op)
snap_frame = RNA_int_get(op->ptr, "frame");
- /* Check metas. */
+ /* Check meta-strips. */
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
if (seq->flag & SELECT && !(seq->depth == 0 && seq->flag & SEQ_LOCK) &&
SEQ_transform_sequence_can_be_translated(seq)) {
@@ -348,7 +348,7 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op)
}
}
- SEQ_sort(scene);
+ SEQ_sort(SEQ_active_seqbase_get(ed));
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -1443,7 +1443,7 @@ static int sequencer_split_exec(bContext *C, wmOperator *op)
}
}
- SEQ_sort(scene);
+ SEQ_sort(SEQ_active_seqbase_get(ed));
}
if (changed) {
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -1577,17 +1577,6 @@ void SEQUENCER_OT_split(struct wmOperatorType *ot)
/** \name Duplicate Strips Operator
* \{ */
-static int apply_unique_name_fn(Sequence *seq, void *arg_pt)
-{
- Scene *scene = (Scene *)arg_pt;
- char name[sizeof(seq->name) - 2];
-
- BLI_strncpy_utf8(name, seq->name + 2, sizeof(name));
- SEQ_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq);
- SEQ_dupe_animdata(scene, name, seq->name + 2);
- return 1;
-}
-
static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
@@ -1608,7 +1597,7 @@ static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
BLI_movelisttolist(ed->seqbasep, &nseqbase);
for (; seq; seq = seq->next) {
- SEQ_recursive_apply(seq, apply_unique_name_fn, scene);
+ SEQ_ensure_unique_name(seq, scene);
}
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -1829,7 +1818,7 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
}
}
- SEQ_sort(scene);
+ SEQ_sort(SEQ_active_seqbase_get(ed));
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -1867,13 +1856,13 @@ static int sequencer_meta_toggle_exec(bContext *C, wmOperator *UNUSED(op))
Sequence *active_seq = SEQ_select_active_get(scene);
if (active_seq && active_seq->type == SEQ_TYPE_META && active_seq->flag & SELECT) {
- /* Enter metastrip. */
+ /* Enter meta-strip. */
SEQ_meta_stack_alloc(ed, active_seq);
SEQ_seqbase_active_set(ed, &active_seq->seqbase);
SEQ_select_active_set(scene, NULL);
}
else {
- /* Exit metastrip if possible. */
+ /* Exit meta-strip if possible. */
if (BLI_listbase_is_empty(&ed->metastack)) {
return OPERATOR_CANCELLED;
}
@@ -1895,7 +1884,7 @@ void SEQUENCER_OT_meta_toggle(wmOperatorType *ot)
/* Identifiers. */
ot->name = "Toggle Meta Strip";
ot->idname = "SEQUENCER_OT_meta_toggle";
- ot->description = "Toggle a metastrip (to edit enclosed strips)";
+ ot->description = "Toggle a meta-strip (to edit enclosed strips)";
/* Api callbacks. */
ot->exec = sequencer_meta_toggle_exec;
@@ -1963,7 +1952,7 @@ void SEQUENCER_OT_meta_make(wmOperatorType *ot)
/* Identifiers. */
ot->name = "Make Meta Strip";
ot->idname = "SEQUENCER_OT_meta_make";
- ot->description = "Group selected strips into a metastrip";
+ ot->description = "Group selected strips into a meta-strip";
/* Api callbacks. */
ot->exec = sequencer_meta_make_exec;
@@ -2014,7 +2003,7 @@ static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op))
}
}
- SEQ_sort(scene);
+ SEQ_sort(active_seqbase);
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -2026,7 +2015,7 @@ void SEQUENCER_OT_meta_separate(wmOperatorType *ot)
/* Identifiers. */
ot->name = "UnMeta Strip";
ot->idname = "SEQUENCER_OT_meta_separate";
- ot->description = "Put the contents of a metastrip back in the sequencer";
+ ot->description = "Put the contents of a meta-strip back in the sequencer";
/* Api callbacks. */
ot->exec = sequencer_meta_separate_exec;
@@ -2237,7 +2226,7 @@ static int sequencer_swap_exec(bContext *C, wmOperator *op)
}
}
- SEQ_sort(scene);
+ SEQ_sort(SEQ_active_seqbase_get(ed));
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -2465,7 +2454,7 @@ static int sequencer_paste_exec(bContext *C, wmOperator *op)
for (iseq = iseq_first; iseq; iseq = iseq->next) {
/* Make sure, that pasted strips have unique names. */
- SEQ_recursive_apply(iseq, apply_unique_name_fn, scene);
+ SEQ_ensure_unique_name(iseq, scene);
/* Translate after name has been changed, otherwise this will affect animdata of original
* strip. */
SEQ_transform_translate_sequence(scene, iseq, ofs);
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index a9f8a70d61e..e386a48ed7e 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -26,7 +26,6 @@
#include <string.h>
#include "BLI_blenlib.h"
-#include "BLI_ghash.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -1187,7 +1186,7 @@ static int sequencer_select_side_of_frame_exec(bContext *C, wmOperator *op)
case 1:
test = (timeline_frame <= seq->startdisp);
break;
- case 0:
+ case 2:
test = (timeline_frame <= seq->enddisp) && (timeline_frame >= seq->startdisp);
break;
}
@@ -1210,6 +1209,7 @@ void SEQUENCER_OT_select_side_of_frame(wmOperatorType *ot)
static const EnumPropertyItem sequencer_select_left_right_types[] = {
{-1, "LEFT", 0, "Left", "Select to the left of the current frame"},
{1, "RIGHT", 0, "Right", "Select to the right of the current frame"},
+ {2, "CURRENT", 0, "Current frame", "Select intersecting with the current frame"},
{0, NULL, 0, NULL, NULL},
};
@@ -1622,64 +1622,47 @@ static bool select_grouped_time_overlap(Editing *ed, Sequence *actseq)
return changed;
}
-static bool select_grouped_effect_link(Editing *ed, Sequence *actseq, const int channel)
+/* Query strips that are in lower channel and intersect in time with seq_reference. */
+static void query_lower_channel_strips(Sequence *seq_reference,
+ ListBase *seqbase,
+ SeqCollection *collection)
{
- bool changed = false;
- const bool is_audio = ((actseq->type == SEQ_TYPE_META) || SEQ_IS_SOUND(actseq));
- int startdisp = actseq->startdisp;
- int enddisp = actseq->enddisp;
- int machine = actseq->machine;
- SeqIterator iter;
-
- LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) {
- seq->tmp = NULL;
- }
-
- actseq->tmp = POINTER_FROM_INT(true);
-
- Sequence *seq = NULL;
- for (SEQ_iterator_begin(ed, &iter, true); iter.valid; SEQ_iterator_next(&iter)) {
- seq = iter.seq;
-
- /* Ignore all seqs already selected. */
- /* Ignore all seqs not sharing some time with active one. */
- /* Ignore all seqs of incompatible types (audio vs video). */
- if (!SEQ_CHANNEL_CHECK(seq, channel) || (seq->flag & SELECT) || (seq->startdisp >= enddisp) ||
- (seq->enddisp < startdisp) || (!is_audio && SEQ_IS_SOUND(seq)) ||
- (is_audio && !((seq->type == SEQ_TYPE_META) || SEQ_IS_SOUND(seq)))) {
- continue;
+ LISTBASE_FOREACH (Sequence *, seq_test, seqbase) {
+ if (seq_test->machine > seq_reference->machine) {
+ continue; /* Not lower channel. */
}
+ if (seq_test->enddisp <= seq_reference->startdisp ||
+ seq_test->startdisp >= seq_reference->enddisp) {
+ continue; /* Not intersecting in time. */
+ }
+ SEQ_collection_append_strip(seq_test, collection);
+ }
+}
- /* If the seq is an effect one, we need extra checking. */
- if (SEQ_IS_EFFECT(seq) && ((seq->seq1 && seq->seq1->tmp) || (seq->seq2 && seq->seq2->tmp) ||
- (seq->seq3 && seq->seq3->tmp))) {
- if (startdisp > seq->startdisp) {
- startdisp = seq->startdisp;
- }
- if (enddisp < seq->enddisp) {
- enddisp = seq->enddisp;
- }
- if (machine < seq->machine) {
- machine = seq->machine;
- }
-
- seq->tmp = POINTER_FROM_INT(true);
+/* Select all strips within time range and with lower channel of initial selection. Then select
+ * effect chains of these strips. */
+static bool select_grouped_effect_link(Editing *ed,
+ Sequence *UNUSED(actseq),
+ const int UNUSED(channel))
+{
+ ListBase *seqbase = SEQ_active_seqbase_get(ed);
- seq->flag |= SELECT;
- changed = true;
+ /* Get collection of strips. */
+ SeqCollection *collection = SEQ_query_selected_strips(seqbase);
+ const int selected_strip_count = BLI_gset_len(collection->set);
+ SEQ_collection_expand(seqbase, collection, query_lower_channel_strips);
+ SEQ_collection_expand(seqbase, collection, SEQ_query_strip_effect_chain);
- /* Unfortunately, we must restart checks from the beginning. */
- SEQ_iterator_end(&iter);
- SEQ_iterator_begin(ed, &iter, true);
- }
+ /* Check if other strips will be affected. */
+ const bool changed = BLI_gset_len(collection->set) > selected_strip_count;
- /* Video strips below active one, or any strip for audio (order doesn't matter here). */
- else if (seq->machine < machine || is_audio) {
- seq->flag |= SELECT;
- changed = true;
- }
+ /* Actual logic. */
+ Sequence *seq;
+ SEQ_ITERATOR_FOREACH (seq, collection) {
+ seq->flag |= SELECT;
}
- SEQ_iterator_end(&iter);
+
+ SEQ_collection_free(collection);
return changed;
}
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index e6916c34a88..b5274c2357e 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -1595,7 +1595,6 @@ static void space_view3d_refresh(const bContext *C, ScrArea *UNUSED(area))
}
const char *view3d_context_dir[] = {
- "active_base",
"active_object",
NULL,
};
@@ -1608,20 +1607,6 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
if (CTX_data_dir(member)) {
CTX_data_dir_set(result, view3d_context_dir);
}
- else if (CTX_data_equals(member, "active_base")) {
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- if (view_layer->basact) {
- Object *ob = view_layer->basact->object;
- /* if hidden but in edit mode, we still display, can happen with animation */
- if ((view_layer->basact->flag & BASE_VISIBLE_DEPSGRAPH) != 0 ||
- (ob->mode != OB_MODE_OBJECT)) {
- CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, view_layer->basact);
- }
- }
-
- return 1;
- }
else if (CTX_data_equals(member, "active_object")) {
/* In most cases the active object is the `view_layer->basact->object`.
* For the 3D view however it can be NULL when hidden.
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index f3a279ee12b..0a89b7d0292 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -1288,6 +1288,11 @@ static void draw_viewport_name(ARegion *region, View3D *v3d, int xoffset, int *y
name_array[name_array_len++] = IFACE_(" (Local)");
}
+ /* Indicate that clipping region is enabled. */
+ if (rv3d->rflag & RV3D_CLIPPING) {
+ name_array[name_array_len++] = IFACE_(" (Clipped)");
+ }
+
if (name_array_len > 1) {
BLI_string_join_array(tmpstr, sizeof(tmpstr), name_array, name_array_len);
name = tmpstr;
@@ -2017,7 +2022,6 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Depsgraph *depsgraph,
source_shading_settings = shading_override;
}
memcpy(&v3d.shading, source_shading_settings, sizeof(View3DShading));
- v3d.shading.type = drawtype;
if (drawtype == OB_MATERIAL) {
v3d.shading.flag = V3D_SHADING_SCENE_WORLD | V3D_SHADING_SCENE_LIGHTS;
@@ -2027,6 +2031,12 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Depsgraph *depsgraph,
v3d.shading.flag = V3D_SHADING_SCENE_WORLD_RENDER | V3D_SHADING_SCENE_LIGHTS_RENDER;
v3d.shading.render_pass = SCE_PASS_COMBINED;
}
+ else if (drawtype == OB_TEXTURE) {
+ drawtype = OB_SOLID;
+ v3d.shading.light = V3D_LIGHTING_STUDIO;
+ v3d.shading.color_type = V3D_SHADING_TEXTURE_COLOR;
+ }
+ v3d.shading.type = drawtype;
v3d.flag2 = V3D_HIDE_OVERLAYS;
@@ -2067,7 +2077,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Depsgraph *depsgraph,
return ED_view3d_draw_offscreen_imbuf(depsgraph,
scene,
- drawtype,
+ v3d.shading.type,
&v3d,
&region,
width,
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
index 3134553c159..0d568363b00 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
@@ -446,7 +446,7 @@ static bool view3d_ruler_to_gpencil(bContext *C, wmGizmoGroup *gzgroup)
gpl = view3d_ruler_layer_get(gpd);
if (gpl == NULL) {
- gpl = BKE_gpencil_layer_addnew(gpd, ruler_name, false);
+ gpl = BKE_gpencil_layer_addnew(gpd, ruler_name, false, false);
copy_v4_v4(gpl->color, U.gpencil_new_layer_col);
gpl->thickness = 1;
gpl->flag |= GP_LAYER_HIDE | GP_LAYER_IS_RULER;
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index bb3afd77dba..ba8e5c1e2c6 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -782,7 +782,7 @@ static bool transform_event_modal_constraint(TransInfo *t, short modal_type)
}
else {
short orient_index = 1;
- if (t->orient_curr == 0 || ELEM(constraint_curr, -1, constraint_new)) {
+ if (t->orient_curr == O_DEFAULT || ELEM(constraint_curr, -1, constraint_new)) {
/* Successive presses on existing axis, cycle orientation modes. */
orient_index = (short)((t->orient_curr + 1) % (int)ARRAY_SIZE(t->orient));
}
@@ -1412,25 +1412,6 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
ToolSettings *ts = CTX_data_tool_settings(C);
PropertyRNA *prop;
- if (!(t->con.mode & CON_APPLY) && (t->flag & T_MODAL) &&
- ELEM(t->mode, TFM_TRANSLATION, TFM_RESIZE)) {
- /* When redoing these modes the first time, it's more convenient to save
- * in the Global orientation. */
- if (t->mode == TFM_TRANSLATION) {
- mul_m3_v3(t->spacemtx, t->values_final);
- }
- else {
- float tmat[3][3], sizemat[3][3];
- size_to_mat3(sizemat, t->values_final);
- mul_m3_m3m3(tmat, t->spacemtx, sizemat);
- mat3_to_size(t->values_final, tmat);
- }
-
- BLI_assert(t->orient_curr == 0);
- unit_m3(t->spacemtx);
- t->orient[0].type = V3D_ORIENT_GLOBAL;
- }
-
/* Save back mode in case we're in the generic operator */
if ((prop = RNA_struct_find_property(op->ptr, "mode"))) {
RNA_property_enum_set(op->ptr, prop, t->mode);
@@ -1638,7 +1619,7 @@ static void initSnapSpatial(TransInfo *t, float r_snap[2])
/**
* \note caller needs to free 't' on a 0 return
- * \warning \a event might be NULL (when tweaking from redo panel)
+ * \warning \a event might be NULL (when tweaking from redo panel)
* \see #saveTransform which writes these values back.
*/
bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event, int mode)
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 090b8b83dcc..a10a53b2983 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -596,11 +596,18 @@ typedef struct TransInfo {
* mouse button then.) */
bool is_launch_event_tweak;
+ bool is_orient_set;
+
struct {
short type;
float matrix[3][3];
} orient[3];
- short orient_curr;
+
+ enum {
+ O_DEFAULT = 0,
+ O_SCENE,
+ O_SET,
+ } orient_curr;
/** backup from view3d, to restore on end. */
short gizmo_flag;
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index 2037981e655..615467932a7 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -953,9 +953,8 @@ void startConstraint(TransInfo *t)
void stopConstraint(TransInfo *t)
{
- if (t->orient_curr != 0) {
- t->orient_curr = 0;
- transform_orientations_current_set(t, t->orient_curr);
+ if (t->orient_curr != O_DEFAULT) {
+ transform_orientations_current_set(t, O_DEFAULT);
}
t->con.mode &= ~(CON_APPLY | CON_SELECT);
@@ -971,8 +970,8 @@ void stopConstraint(TransInfo *t)
void initSelectConstraint(TransInfo *t)
{
- if (t->orient_curr == 0) {
- transform_orientations_current_set(t, 1);
+ if (t->orient_curr == O_DEFAULT) {
+ transform_orientations_current_set(t, O_SCENE);
}
setUserConstraint(t, CON_APPLY | CON_SELECT, "%s");
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index 98db27c83f7..b4175faacf4 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -37,6 +37,7 @@
#include "BKE_context.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
+#include "BKE_image.h"
#include "BKE_layer.h"
#include "BKE_lib_id.h"
#include "BKE_main.h"
@@ -505,9 +506,27 @@ bool clipUVTransform(TransInfo *t, float vec[2], const bool resize)
bool clipx = true, clipy = true;
float min[2], max[2];
- min[0] = min[1] = 0.0f;
- max[0] = t->aspect[0];
- max[1] = t->aspect[1];
+ /* Check if the current image in UV editor is a tiled image or not. */
+ const SpaceImage *sima = t->area->spacedata.first;
+ const Image *image = sima->image;
+ const bool is_tiled_image = image && (image->source == IMA_SRC_TILED);
+ /* Stores the coordinates of the closest UDIM tile.
+ * Also acts as an offset to the tile from the origin of UV space. */
+ float base_offset[2] = {0.0f, 0.0f};
+
+ /* If tiled image then constrain to correct/closest UDIM tile, else 0-1 UV space. */
+ if (is_tiled_image) {
+ int nearest_tile_index = BKE_image_find_nearest_tile(image, t->center_global);
+ if (nearest_tile_index != -1) {
+ nearest_tile_index -= 1001;
+ /* Getting coordinates of nearest tile from the tile index. */
+ base_offset[0] = nearest_tile_index % 10;
+ base_offset[1] = nearest_tile_index / 10;
+ }
+ }
+
+ min[0] = min[1] = FLT_MAX;
+ max[0] = max[1] = FLT_MIN;
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
@@ -520,42 +539,48 @@ bool clipUVTransform(TransInfo *t, float vec[2], const bool resize)
}
if (resize) {
- if (min[0] < 0.0f && t->center_global[0] > 0.0f && t->center_global[0] < t->aspect[0] * 0.5f) {
- vec[0] *= t->center_global[0] / (t->center_global[0] - min[0]);
+ if (min[0] < base_offset[0] && t->center_global[0] > base_offset[0] &&
+ t->center_global[0] < base_offset[0] + (t->aspect[0] * 0.5f)) {
+ vec[0] *= (t->center_global[0] - base_offset[0]) / (t->center_global[0] - min[0]);
}
- else if (max[0] > t->aspect[0] && t->center_global[0] < t->aspect[0]) {
- vec[0] *= (t->center_global[0] - t->aspect[0]) / (t->center_global[0] - max[0]);
+ else if (max[0] > (base_offset[0] + t->aspect[0]) &&
+ t->center_global[0] < (base_offset[0] + t->aspect[0])) {
+ vec[0] *= (t->center_global[0] - (base_offset[0] + t->aspect[0])) /
+ (t->center_global[0] - max[0]);
}
else {
clipx = 0;
}
- if (min[1] < 0.0f && t->center_global[1] > 0.0f && t->center_global[1] < t->aspect[1] * 0.5f) {
- vec[1] *= t->center_global[1] / (t->center_global[1] - min[1]);
+ if (min[1] < base_offset[1] && t->center_global[1] > base_offset[1] &&
+ t->center_global[1] < base_offset[1] + (t->aspect[1] * 0.5f)) {
+ vec[1] *= (t->center_global[1] - base_offset[1]) / (t->center_global[1] - min[1]);
}
- else if (max[1] > t->aspect[1] && t->center_global[1] < t->aspect[1]) {
- vec[1] *= (t->center_global[1] - t->aspect[1]) / (t->center_global[1] - max[1]);
+ else if (max[1] > (base_offset[1] + t->aspect[1]) &&
+ t->center_global[1] < (base_offset[1] + t->aspect[1])) {
+ vec[1] *= (t->center_global[1] - (base_offset[1] + t->aspect[1])) /
+ (t->center_global[1] - max[1]);
}
else {
clipy = 0;
}
}
else {
- if (min[0] < 0.0f) {
- vec[0] -= min[0];
+ if (min[0] < base_offset[0]) {
+ vec[0] += base_offset[0] - min[0];
}
- else if (max[0] > t->aspect[0]) {
- vec[0] -= max[0] - t->aspect[0];
+ else if (max[0] > base_offset[0] + t->aspect[0]) {
+ vec[0] -= max[0] - base_offset[0] - t->aspect[0];
}
else {
clipx = 0;
}
- if (min[1] < 0.0f) {
- vec[1] -= min[1];
+ if (min[1] < base_offset[1]) {
+ vec[1] += base_offset[1] - min[1];
}
- else if (max[1] > t->aspect[1]) {
- vec[1] -= max[1] - t->aspect[1];
+ else if (max[1] > base_offset[1] + t->aspect[1]) {
+ vec[1] -= max[1] - base_offset[1] - t->aspect[1];
}
else {
clipy = 0;
diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c
index 30418471d6d..34be89e5ed9 100644
--- a/source/blender/editors/transform/transform_convert_sequencer.c
+++ b/source/blender/editors/transform/transform_convert_sequencer.c
@@ -491,7 +491,7 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c
}
}
- SEQ_sort(t->scene);
+ SEQ_sort(seqbasep);
}
else {
/* Canceled, need to update the strips display */
@@ -707,7 +707,7 @@ static void flushTransSeq(TransInfo *t)
/* originally TFM_TIME_EXTEND, transform changes */
if (ELEM(t->mode, TFM_SEQ_SLIDE, TFM_TIME_TRANSLATE)) {
- /* Special annoying case here, need to calc metas with TFM_TIME_EXTEND only */
+ /* Special annoying case here, need to calc meta-strips with TFM_TIME_EXTEND only */
/* calc all meta's then effects T27953. */
for (seq = seqbasep->first; seq; seq = seq->next) {
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index c9b6bef5904..71c91221fbb 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -414,8 +414,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
int orient_type_set = -1;
int orient_type_matrix_set = -1;
- bool use_orient_axis = false;
-
if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) {
TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT];
orient_type_scene = orient_slot->type;
@@ -435,7 +433,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis"))) {
t->orient_axis = RNA_property_enum_get(op->ptr, prop);
- use_orient_axis = true;
}
if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho"))) {
@@ -457,28 +454,23 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
if (orient_type_set != -1) {
orient_type_default = orient_type_set;
+ t->is_orient_set = true;
}
else if (orient_type_matrix_set != -1) {
orient_type_default = orient_type_set = orient_type_matrix_set;
+ t->is_orient_set = true;
}
else if (t->con.mode & CON_APPLY) {
orient_type_default = orient_type_set = orient_type_scene;
}
else {
+ orient_type_default = orient_type_scene;
if (orient_type_scene == V3D_ORIENT_GLOBAL) {
orient_type_set = V3D_ORIENT_LOCAL;
}
else {
orient_type_set = V3D_ORIENT_GLOBAL;
}
-
- if ((t->flag & T_MODAL) && (use_orient_axis || transform_mode_is_changeable(t->mode)) &&
- (t->mode != TFM_ALIGN)) {
- orient_type_default = V3D_ORIENT_VIEW;
- }
- else {
- orient_type_default = orient_type_scene;
- }
}
BLI_assert(!ELEM(-1, orient_type_default, orient_type_set));
@@ -487,9 +479,9 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
orient_type_set = V3D_ORIENT_CUSTOM_MATRIX;
}
- orient_types[0] = (short)orient_type_default;
- orient_types[1] = (short)orient_type_scene;
- orient_types[2] = (short)orient_type_set;
+ orient_types[O_DEFAULT] = (short)orient_type_default;
+ orient_types[O_SCENE] = (short)orient_type_scene;
+ orient_types[O_SET] = (short)orient_type_set;
for (int i = 0; i < 3; i++) {
/* For efficiency, avoid calculating the same orientation twice. */
@@ -506,9 +498,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
}
- /* Set orient_curr to -1 in order to force the update in
- * `transform_orientations_current_set`. */
- t->orient_curr = -1;
transform_orientations_current_set(t, (t->con.mode & CON_APPLY) ? 2 : 0);
}
diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c
index 867a6cc4291..d61e7bb867c 100644
--- a/source/blender/editors/transform/transform_mode.c
+++ b/source/blender/editors/transform/transform_mode.c
@@ -45,6 +45,7 @@
#include "transform.h"
#include "transform_convert.h"
+#include "transform_orientations.h"
#include "transform_snap.h"
/* Own include. */
@@ -1271,4 +1272,38 @@ void transform_mode_init(TransInfo *t, wmOperator *op, const int mode)
* BLI_assert(t->mode == mode); */
}
+/**
+ * When in modal and not set, initializes a default orientation for the mode.
+ */
+void transform_mode_default_modal_orientation_set(TransInfo *t, int type)
+{
+ /* Currently only these types are supported. */
+ BLI_assert(ELEM(type, V3D_ORIENT_GLOBAL, V3D_ORIENT_VIEW));
+
+ if (t->is_orient_set) {
+ return;
+ }
+
+ if (!(t->flag & T_MODAL)) {
+ return;
+ }
+
+ if (t->orient[O_DEFAULT].type == type) {
+ return;
+ }
+
+ RegionView3D *rv3d = NULL;
+ if ((type == V3D_ORIENT_VIEW) && (t->spacetype == SPACE_VIEW3D) && t->region &&
+ (t->region->regiontype == RGN_TYPE_WINDOW)) {
+ rv3d = t->region->regiondata;
+ }
+
+ t->orient[O_DEFAULT].type = ED_transform_calc_orientation_from_type_ex(
+ NULL, t->orient[O_DEFAULT].matrix, NULL, rv3d, NULL, NULL, type, 0);
+
+ if (t->orient_curr == O_DEFAULT) {
+ /* Update Orientation. */
+ transform_orientations_current_set(t, O_DEFAULT);
+ }
+}
/** \} */
diff --git a/source/blender/editors/transform/transform_mode.h b/source/blender/editors/transform/transform_mode.h
index 6d7a0b528ae..106dc68c9ee 100644
--- a/source/blender/editors/transform/transform_mode.h
+++ b/source/blender/editors/transform/transform_mode.h
@@ -61,6 +61,7 @@ short getAnimEdit_SnapMode(TransInfo *t);
void doAnimEdit_SnapFrame(
TransInfo *t, TransData *td, TransData2D *td2d, struct AnimData *adt, short autosnap);
void transform_mode_init(TransInfo *t, struct wmOperator *op, const int mode);
+void transform_mode_default_modal_orientation_set(TransInfo *t, int type);
/* transform_mode_align.c */
void initAlign(TransInfo *t);
diff --git a/source/blender/editors/transform/transform_mode_edge_rotate_normal.c b/source/blender/editors/transform/transform_mode_edge_rotate_normal.c
index c78115561b2..b7b3de69731 100644
--- a/source/blender/editors/transform/transform_mode_edge_rotate_normal.c
+++ b/source/blender/editors/transform/transform_mode_edge_rotate_normal.c
@@ -148,5 +148,7 @@ void initNormalRotation(TransInfo *t)
storeCustomLNorValue(tc, bm);
}
+
+ transform_mode_default_modal_orientation_set(t, V3D_ORIENT_VIEW);
}
/** \} */
diff --git a/source/blender/editors/transform/transform_mode_resize.c b/source/blender/editors/transform/transform_mode_resize.c
index fcdc57a98e2..0d7d0be3c0e 100644
--- a/source/blender/editors/transform/transform_mode_resize.c
+++ b/source/blender/editors/transform/transform_mode_resize.c
@@ -193,5 +193,7 @@ void initResize(TransInfo *t)
t->num.unit_type[0] = B_UNIT_NONE;
t->num.unit_type[1] = B_UNIT_NONE;
t->num.unit_type[2] = B_UNIT_NONE;
+
+ transform_mode_default_modal_orientation_set(t, V3D_ORIENT_GLOBAL);
}
/** \} */
diff --git a/source/blender/editors/transform/transform_mode_rotate.c b/source/blender/editors/transform/transform_mode_rotate.c
index 8d8594d5775..0fdbfb25989 100644
--- a/source/blender/editors/transform/transform_mode_rotate.c
+++ b/source/blender/editors/transform/transform_mode_rotate.c
@@ -249,5 +249,7 @@ void initRotation(TransInfo *t)
if (t->flag & T_2D_EDIT) {
t->flag |= T_NO_CONSTRAINT;
}
+
+ transform_mode_default_modal_orientation_set(t, V3D_ORIENT_VIEW);
}
/** \} */
diff --git a/source/blender/editors/transform/transform_mode_shear.c b/source/blender/editors/transform/transform_mode_shear.c
index a41c49710b9..23ee55bf6c5 100644
--- a/source/blender/editors/transform/transform_mode_shear.c
+++ b/source/blender/editors/transform/transform_mode_shear.c
@@ -232,5 +232,7 @@ void initShear(TransInfo *t)
t->num.unit_type[0] = B_UNIT_NONE; /* Don't think we have any unit here? */
t->flag |= T_NO_CONSTRAINT;
+
+ transform_mode_default_modal_orientation_set(t, V3D_ORIENT_VIEW);
}
/** \} */
diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c
index 41fc6ee0aaf..0bef6364214 100644
--- a/source/blender/editors/transform/transform_mode_translate.c
+++ b/source/blender/editors/transform/transform_mode_translate.c
@@ -470,5 +470,7 @@ void initTranslation(TransInfo *t)
t->num.unit_type[1] = B_UNIT_NONE;
t->num.unit_type[2] = B_UNIT_NONE;
}
+
+ transform_mode_default_modal_orientation_set(t, V3D_ORIENT_GLOBAL);
}
/** \} */
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index 5a5f478fc2b..b3ed294845d 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -671,10 +671,6 @@ const char *transform_orientations_spacename_get(TransInfo *t, const short orien
void transform_orientations_current_set(TransInfo *t, const short orient_index)
{
- if (t->orient_curr == orient_index) {
- return;
- }
-
const short orientation = t->orient[orient_index].type;
const char *spacename = transform_orientations_spacename_get(t, orientation);