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:
authorChristoph Lendenfeld <ChrisLend>2021-04-15 11:59:52 +0300
committerSybren A. Stüvel <sybren@blender.org>2021-04-15 11:59:52 +0300
commit60d1d130464572c518fef89a252bc7d302506e64 (patch)
treea7a48de884f552c47838c3fb2eaa468ba2388c7a
parent2c3a9caffee61d52cc50a70ff9b2ec3984ee0fc5 (diff)
Pose Sliding tools improvementstemp-pose-slide-D9054
### Executive Summary This patch improves pose sliding tools: Breakdowner, Push, and Relax. The problems with the old tools: - **No UI**. Even though it's clear how the tool works when you move the mouse, there is no visual indication as to the actual scale of the movement required. - **No mouse wrapping**. This means that you have to carefully plan the initial position of the mouse when using the tools, because that impacts which values are available. This makes it hard to use it from the menu, as that forces the mouse to be in a certain position. - **No precision mode** by pressing shift. - **No overshoot protection**, so it's very easy to go below 0% or above 100%. These problems are **all solved in this patch**. ##### Demo video Here {key Shift E} is used to start the Pose Breakdowner. {F9929705} ### Original description **Problem** The existing Push, Relax and Breakdowner tools are great, but the fact that they use the whole area range is less than ideal. In theory, the tools support going beyond 0% and 100% to create an overshoot, but since they use the whole are, you might be blocked by the edges of the screen. **Solution** Set a pixel value as defined distance from 0% to 100% (scales with gui) To indicate that, draw a UI under the cursor. The percentage is now calculated accumulative to enable precision support when holding SHIFT Info about new modifier keys is printed to the workspace status {F9891261} Update 2020_10_12: All lines have outlines now and handle is orange for better readability on white. Update 2021_01_18: Static indicators moved to bottom. tick spacing now every 10% Update 2021_03_14: Remove the slider and replace with a simple percentage indicator. (Cursor not visible in screenshot) Update 2021_04_11: Brought the slider back. Spawns centered at the bottom of the screen {F9929709} By default the percentage is clamped to 0-1. But by pressing E you can enable overshoot. Update 2020_10_12: slider range in overshoot mode is now 150% to better indicate that it can go further Update 2021_03_14: Since the slider was removed, the percentage amount is simply displayed under the cursor Update 2021_04_11: Overshoot now scrolls in place {F9929712} **Limitations and future improvements** As mentioned in the comments below it would be a good idea to write a more general version of the slider to be used in various areas of Blender. **Build** [[ https://blender.community/c/graphicall/dqbbbc/ | Windows build on graphicall ]] **Edit** Split off the operator into it's own patch D9137 Reviewed By: zeddb, brecht, Severin, looch Maniphest Tasks: T81836 Differential Revision: https://developer.blender.org/D9054
-rw-r--r--source/blender/editors/armature/CMakeLists.txt1
-rw-r--r--source/blender/editors/armature/pose_slide.c387
2 files changed, 357 insertions, 31 deletions
diff --git a/source/blender/editors/armature/CMakeLists.txt b/source/blender/editors/armature/CMakeLists.txt
index 98c050950be..7266b1b88d7 100644
--- a/source/blender/editors/armature/CMakeLists.txt
+++ b/source/blender/editors/armature/CMakeLists.txt
@@ -19,6 +19,7 @@ set(INC
../include
../../blenkernel
../../blenlib
+ ../../blenfont
../../blentranslation
../../depsgraph
../../gpu
diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c
index 93d36abe792..9b285f06d14 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"
@@ -50,15 +51,27 @@
#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.dpi_fac)
+
/* **************************************************** */
/* == POSE 'SLIDING' TOOLS ==
*
@@ -110,15 +123,43 @@ 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;
+
+ /* Pixel value in area space where the slider starts. */
+ int slider_start[2];
+
+ /* 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 */
+ /* Cursor position in region space. */
+ int cursor_region_x;
+ int cursor_region_y;
+
+ /* 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 +228,135 @@ static const EnumPropertyItem prop_axis_lock_types[] = {
/* ------------------------------------ */
+/* Draw a given string centered at the given coordinates. */
+static void draw_centered_string_with_background(
+ const char *string, const float x, const float y, const uchar color_bg[4], const int fontid)
+{
+ const int bg_margin = 5 * U.dpi_fac;
+ float string_pixel_size[2];
+ /* Get width and height of printed string to center above ticks. */
+ BLF_width_and_height(
+ fontid, string, sizeof(string), &string_pixel_size[0], &string_pixel_size[1]);
+ const unsigned char col[3] = {color_bg[0], color_bg[1], color_bg[2]};
+ const rctf background_rect = {.xmin = x - string_pixel_size[0] / 2 - bg_margin,
+ .xmax = x + string_pixel_size[0] / 2 + bg_margin,
+ .ymin = y - string_pixel_size[1] / 2 - bg_margin,
+ .ymax = y + string_pixel_size[1] / 2 + bg_margin};
+ UI_draw_roundbox_3ub_alpha(&background_rect, true, 4.0f, col, color_bg[3]);
+ BLF_position(fontid, x - string_pixel_size[0] / 2, y - string_pixel_size[1] / 2, 0.0f);
+ BLF_draw(fontid, string, sizeof(string));
+}
+
+/* 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;
+ }
+
+ uchar color_text[4];
+ uchar color_line[4];
+ uchar color_handle[4];
+ uchar color_bg[4];
+
+ char percentage_string[256];
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* Get theme colors. Text gets a different color when the value is clamped.*/
+ UI_GetThemeColor4ubv(TH_TEXT, color_text);
+ UI_GetThemeColor4ubv(TH_TEXT, color_line);
+ UI_GetThemeColor4ubv(TH_ACTIVE, color_handle);
+ UI_GetThemeColor4ubv(TH_HEADER, color_bg);
+ color_bg[3] = 160;
+
+ /* 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 = 4 * U.dpi_fac;
+ const float base_tick_height = 16.0 * U.dpi_fac;
+ const float text_offset = 24.0 * U.dpi_fac;
+ const float overshoot_range_delta = 0.2;
+ int initial_tick_percentage;
+ int handle_pos_x;
+ float overshoot_length_delta;
+
+ if (pso->overshoot) {
+ initial_tick_percentage = (int)((pso->percentage - 0.5f - overshoot_range_delta) * 100);
+ handle_pos_x = pso->slider_start[0] + (SLIDE_PIXEL_DISTANCE / 2);
+ overshoot_length_delta = SLIDE_PIXEL_DISTANCE * overshoot_range_delta;
+ }
+ else {
+ initial_tick_percentage = 0;
+ handle_pos_x = pso->slider_start[0] + SLIDE_PIXEL_DISTANCE * pso->percentage;
+ overshoot_length_delta = 0;
+ }
+
+ /* Draw main line. */
+ const struct rctf main_line_rect = {.xmin = pso->slider_start[0] - overshoot_length_delta,
+ .xmax = pso->slider_start[0] + SLIDE_PIXEL_DISTANCE +
+ overshoot_length_delta,
+ .ymin = pso->slider_start[1] - line_width / 2,
+ .ymax = pso->slider_start[1] + line_width / 2};
+ UI_draw_roundbox_3ub_alpha(&main_line_rect, true, 0, color_line, 255);
+ UI_draw_roundbox_3ub_alpha(&main_line_rect, false, 0, color_bg, 255);
+
+ /* Draw percentage ticks. */
+ const int tick_increment = 10;
+ const int percentage_range = pso->overshoot ? 100 + 100 * overshoot_range_delta * 2 : 100;
+
+ /* Round initial_tick_percentage up to the next tick_increment. */
+ int tick_percentage = ceil((float)initial_tick_percentage / tick_increment) * tick_increment;
+
+ for (; tick_percentage <= initial_tick_percentage + percentage_range;
+ tick_percentage += tick_increment) {
+ const float x = handle_pos_x +
+ SLIDE_PIXEL_DISTANCE * (((float)tick_percentage / 100) - pso->percentage);
+ /* 0.5 steps are considered main ticks and are drawn thicker with
+ * percentage indicator string below. */
+ const bool is_main_tick = tick_percentage % 50 == 0;
+ const float tick_height = is_main_tick ? base_tick_height : base_tick_height / 2;
+
+ const struct rctf tick_rect = {.xmin = x - (line_width / 2),
+ .xmax = x + (line_width / 2),
+ .ymin = pso->slider_start[1] - (tick_height / 2),
+ .ymax = pso->slider_start[1] + (tick_height / 2)};
+
+ UI_draw_roundbox_3ub_alpha(&tick_rect, true, 1, color_line, 255);
+ UI_draw_roundbox_3ub_alpha(&tick_rect, false, 1, color_bg, 255);
+
+ /* Draw percentage on main ticks. */
+ if (is_main_tick) {
+ BLI_snprintf(percentage_string, sizeof(percentage_string), "%d%%", tick_percentage);
+ draw_centered_string_with_background(
+ percentage_string, x, pso->slider_start[1] - text_offset, color_bg, fontid);
+ }
+ }
+
+ /* Draw handle indicating current percentage. */
+ const struct rctf handle_rect = {.xmin = handle_pos_x - (line_width),
+ .xmax = handle_pos_x + (line_width),
+ .ymin = pso->slider_start[1] - (base_tick_height / 2),
+ .ymax = pso->slider_start[1] + (base_tick_height / 2)};
+
+ UI_draw_roundbox_3ub_alpha(&handle_rect, true, 1, color_handle, 255);
+ UI_draw_roundbox_3ub_alpha(&handle_rect, false, 1, color_bg, 255);
+
+ BLI_snprintf(percentage_string, sizeof(percentage_string), "%.0f%%", pso->percentage * 100);
+ draw_centered_string_with_background(
+ percentage_string, handle_pos_x, pso->slider_start[1] + text_offset, color_bg, fontid);
+
+ GPU_blend(GPU_BLEND_NONE);
+ immUnbindProgram();
+}
+
/* operator init */
static int pose_slide_init(bContext *C, wmOperator *op, ePoseSlide_Modes mode)
{
@@ -205,6 +375,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 +428,10 @@ 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. */
+ pso->draw_handle = ED_region_draw_cb_activate(
+ pso->region->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 +441,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 +784,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 +803,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 +971,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 +1057,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",
- mode_str,
- (int)(pso->percentage * 100.0f),
- limits_str);
+ sizeof(status_str),
+ "%s: %d %% | %s | %s | %s | %s | %s",
+ mode_str,
+ (int)(pso->percentage * 100.0f),
+ 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);
}
/* common code for invoke() methods */
@@ -975,24 +1187,74 @@ 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;
+ /* Modulo mval so the value wraps properly in area space with the cursor. */
+ if (event->mval[0] > 0) {
+ pso->cursor_region_x = event->mval[0] % pso->region->winx;
+ }
+ else {
+ pso->cursor_region_x = (event->mval[0] % pso->region->winx) + pso->region->winx;
+ }
+ pso->cursor_region_y = event->mval[1];
+
+ 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);
}
+/* Calculate the starting percentage so that 0% or 100% will always be in the area. */
+static void pose_slide_calculate_start_percentage(tPoseSlideOp *pso, const wmEvent *event)
+{
+ pso->last_cursor_x = event->x;
+ /* A bit of padding to both sides so the text stays on screen. */
+ const int padding = 16 * U.dpi_fac;
+
+ /* Clamp it so 0% or 100% is always on screen. */
+ /* Catching edge case where slider doesn't fit in window. */
+ if (padding < pso->region->winx - SLIDE_PIXEL_DISTANCE - padding) {
+ pso->last_cursor_x = clamp_i(pso->last_cursor_x,
+ pso->region->winrct.xmin + padding + SLIDE_PIXEL_DISTANCE / 2,
+ pso->region->winrct.xmax - padding - SLIDE_PIXEL_DISTANCE / 2);
+ }
+ else {
+ pso->last_cursor_x = clamp_i(pso->last_cursor_x,
+ pso->region->winrct.xmin + padding + SLIDE_PIXEL_DISTANCE / 2,
+ INT_MAX);
+ }
+ pso->slider_start[0] = (pso->region->winx / 2) - (SLIDE_PIXEL_DISTANCE / 2);
+ pso->slider_start[1] = 64 * U.dpi_fac;
+}
+
/* handle an event to toggle channels mode */
static void pose_slide_toggle_channels_mode(wmOperator *op,
tPoseSlideOp *pso,
@@ -1056,9 +1318,12 @@ 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_area_status_text(pso->area, NULL);
+ ED_workspace_status_text(C, 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 +1338,13 @@ 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_area_status_text(pso->area, NULL);
+ ED_workspace_status_text(C, 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 +1443,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 +1506,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 +1562,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 +1625,8 @@ static int pose_slide_push_invoke(bContext *C, wmOperator *op, const wmEvent *ev
pso = op->customdata;
+ pose_slide_calculate_start_percentage(pso, event);
+
/* Initialize percentage so that it won't pop on first mouse move. */
pose_slide_mouse_update_percentage(pso, op, event);
@@ -1349,7 +1666,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 +1687,8 @@ static int pose_slide_relax_invoke(bContext *C, wmOperator *op, const wmEvent *e
pso = op->customdata;
+ pose_slide_calculate_start_percentage(pso, event);
+
/* Initialize percentage so that it won't pop on first mouse move. */
pose_slide_mouse_update_percentage(pso, op, event);
@@ -1409,7 +1728,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 +1748,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 +1789,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 +1810,8 @@ static int pose_slide_relax_rest_invoke(bContext *C, wmOperator *op, const wmEve
pso = op->customdata;
+ pose_slide_calculate_start_percentage(pso, event);
+
/* Initialize percentage so that it won't pop on first mouse move. */
pose_slide_mouse_update_percentage(pso, op, event);
@@ -1528,7 +1851,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 +1872,8 @@ static int pose_slide_breakdown_invoke(bContext *C, wmOperator *op, const wmEven
pso = op->customdata;
+ pose_slide_calculate_start_percentage(pso, event);
+
/* Initialize percentage so that it won't pop on first mouse move. */
pose_slide_mouse_update_percentage(pso, op, event);
@@ -1588,7 +1913,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);