Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/armature/pose_slide.c
| Show First 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | |||||
| #include "WM_api.h" | #include "WM_api.h" | ||||
| #include "WM_types.h" | #include "WM_types.h" | ||||
| #include "UI_interface.h" | #include "UI_interface.h" | ||||
| #include "UI_resources.h" | #include "UI_resources.h" | ||||
| #include "ED_armature.h" | #include "ED_armature.h" | ||||
| #include "ED_keyframes_draw.h" | #include "ED_keyframes_keylist.h" | ||||
| #include "ED_markers.h" | #include "ED_markers.h" | ||||
| #include "ED_numinput.h" | #include "ED_numinput.h" | ||||
| #include "ED_screen.h" | #include "ED_screen.h" | ||||
| #include "ED_space_api.h" | #include "ED_space_api.h" | ||||
| #include "ED_util.h" | |||||
| #include "GPU_immediate.h" | #include "GPU_immediate.h" | ||||
| #include "GPU_immediate_util.h" | #include "GPU_immediate_util.h" | ||||
| #include "GPU_matrix.h" | #include "GPU_matrix.h" | ||||
| #include "GPU_state.h" | #include "GPU_state.h" | ||||
| #include "armature_intern.h" | #include "armature_intern.h" | ||||
| Show All 39 Lines | |||||
| } ePoseSlide_Channels; | } ePoseSlide_Channels; | ||||
| /** Temporary data shared between these operators. */ | /** Temporary data shared between these operators. */ | ||||
| typedef struct tPoseSlideOp { | typedef struct tPoseSlideOp { | ||||
| /** current scene */ | /** current scene */ | ||||
| Scene *scene; | Scene *scene; | ||||
| /** area that we're operating in (needed for modal()) */ | /** area that we're operating in (needed for modal()) */ | ||||
| ScrArea *area; | ScrArea *area; | ||||
| /** Header of the region used for drawing the slider. */ | /** Region we're operating in (needed for modal()). */ | ||||
| ARegion *region_header; | ARegion *region; | ||||
| /** len of the PoseSlideObject array. */ | /** len of the PoseSlideObject array. */ | ||||
| uint objects_len; | uint objects_len; | ||||
| /** links between posechannels and f-curves for all the pose objects. */ | /** links between posechannels and f-curves for all the pose objects. */ | ||||
| ListBase pfLinks; | ListBase pfLinks; | ||||
| /** binary tree for quicker searching for keyframes (when applicable) */ | /** binary tree for quicker searching for keyframes (when applicable) */ | ||||
| DLRBT_Tree keys; | DLRBT_Tree keys; | ||||
| Show All 13 Lines | typedef struct tPoseSlideOp { | ||||
| /* Store overlay settings when invoking the operator. Bones will be temporarily hidden. */ | /* Store overlay settings when invoking the operator. Bones will be temporarily hidden. */ | ||||
| int overlay_flag; | int overlay_flag; | ||||
| /** Which transforms/channels are affected. */ | /** Which transforms/channels are affected. */ | ||||
| ePoseSlide_Channels channels; | ePoseSlide_Channels channels; | ||||
| /** Axis-limits for transforms. */ | /** Axis-limits for transforms. */ | ||||
| ePoseSlide_AxisLock axislock; | ePoseSlide_AxisLock axislock; | ||||
| /** Allow overshoot or clamp between 0% and 100%. */ | struct tSlider *slider; | ||||
| bool overshoot; | |||||
| /** Reduces factor delta from mouse movement. */ | |||||
| bool precision; | |||||
| /** Move factor in 10% steps. */ | |||||
| bool increments; | |||||
| /** Draw callback handler. */ | |||||
| void *draw_handle; | |||||
| /** Accumulative, unclamped and unrounded factor. */ | |||||
| float raw_factor; | |||||
| /** 0-1 value for determining the influence of whatever is relevant. */ | |||||
| float factor; | |||||
| /** Last cursor position in screen space used for mouse movement delta calculation. */ | |||||
| int last_cursor_x; | |||||
| /** Numeric input. */ | /** Numeric input. */ | ||||
| NumInput num; | NumInput num; | ||||
| struct tPoseSlideObject *ob_data_array; | struct tPoseSlideObject *ob_data_array; | ||||
| } tPoseSlideOp; | } tPoseSlideOp; | ||||
| typedef struct tPoseSlideObject { | typedef struct tPoseSlideObject { | ||||
| Show All 28 Lines | static const EnumPropertyItem prop_axis_lock_types[] = { | ||||
| {PS_LOCK_Y, "Y", 0, "Y", "Only Y-axis transforms are affected"}, | {PS_LOCK_Y, "Y", 0, "Y", "Only Y-axis transforms are affected"}, | ||||
| {PS_LOCK_Z, "Z", 0, "Z", "Only Z-axis transforms are affected"}, | {PS_LOCK_Z, "Z", 0, "Z", "Only Z-axis transforms are affected"}, | ||||
| /* TODO: Combinations? */ | /* TODO: Combinations? */ | ||||
| {0, NULL, 0, NULL, NULL}, | {0, NULL, 0, NULL, NULL}, | ||||
| }; | }; | ||||
| /* ------------------------------------ */ | /* ------------------------------------ */ | ||||
| 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_factor, | |||||
| const float end_factor, | |||||
| const float line_start[2], | |||||
| const float base_tick_height, | |||||
| const float line_width, | |||||
| const uint8_t color_overshoot[4], | |||||
| const uint8_t color_line[4]) | |||||
| { | |||||
| /* Use factor represented as 0-100 int to avoid floating point precision problems. */ | |||||
| const int tick_increment = 10; | |||||
| /* Round initial_tick_factor up to the next tick_increment. */ | |||||
| int tick_percentage = ceil((start_factor * 100) / tick_increment) * tick_increment; | |||||
| while (tick_percentage <= (int)(end_factor * 100)) { | |||||
| float tick_height; | |||||
| /* 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[0] + | |||||
| (((float)tick_percentage / 100) - start_factor) * SLIDE_PIXEL_DISTANCE; | |||||
| const rctf tick_rect = { | |||||
| .xmin = x - (line_width / 2), | |||||
| .xmax = x + (line_width / 2), | |||||
| .ymin = line_start[1] - (tick_height / 2), | |||||
| .ymax = line_start[1] + (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 rctf *main_line_rect, | |||||
| const float factor, | |||||
| 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 - | |||||
| ((factor - 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 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 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 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 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_string_placeholder = "000%%"; | |||||
| BLF_width_and_height(fontid, | |||||
| percentage_string_placeholder, | |||||
| sizeof(percentage_string_placeholder), | |||||
| &string_pixel_size[0], | |||||
| &string_pixel_size[1]); | |||||
| const float pad[2] = {(region_y_size - base_tick_height) / 2, 2.0f * U.pixelsize}; | |||||
| const rctf backdrop_rect = { | |||||
| .xmin = main_line_rect->xmin - string_pixel_size[0] - pad[0], | |||||
| .xmax = main_line_rect->xmax + pad[0], | |||||
| .ymin = pad[1], | |||||
| .ymax = region_y_size - pad[1], | |||||
| }; | |||||
| 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_header) { | |||||
| 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; | |||||
| 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_factor = 0; | |||||
| int handle_pos_x = main_line_rect.xmin + SLIDE_PIXEL_DISTANCE * pso->factor; | |||||
| 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_factor = pso->factor - 0.5f - OVERSHOOT_RANGE_DELTA; | |||||
| handle_pos_x = region->winx / 2; | |||||
| } | |||||
| draw_backdrop(fontid, &main_line_rect, color_bg, pso->region_header->winy, base_tick_height); | |||||
| draw_main_line(&main_line_rect, pso->factor, pso->overshoot, color_overshoot, color_line); | |||||
| const float factor_range = pso->overshoot ? 1 + OVERSHOOT_RANGE_DELTA * 2 : 1; | |||||
| const float line_start_position[2] = {main_line_rect.xmin, line_y}; | |||||
| draw_ticks(line_start_factor, | |||||
| line_start_factor + factor_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->factor > 1 + OVERSHOOT_RANGE_DELTA + 0.5) { | |||||
| draw_overshoot_triangle(color_line, false, main_line_rect.xmin, line_y); | |||||
| } | |||||
| if (pso->factor < 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 factor. */ | |||||
| const 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->factor * 100); | |||||
| /* Draw percentage string. */ | |||||
| float percentage_string_pixel_size[2]; | |||||
| BLF_width_and_height(fontid, | |||||
| percentage_string, | |||||
| sizeof(percentage_string), | |||||
| &percentage_string_pixel_size[0], | |||||
| &percentage_string_pixel_size[1]); | |||||
| BLF_position(fontid, | |||||
| main_line_rect.xmin - 24.0 * U.pixelsize - percentage_string_pixel_size[0] / 2, | |||||
| (region->winy / 2) - percentage_string_pixel_size[1] / 2, | |||||
| 0.0f); | |||||
| BLF_draw(fontid, percentage_string, sizeof(percentage_string)); | |||||
| } | |||||
| /** Operator custom-data initialization. */ | /** Operator custom-data initialization. */ | ||||
| static int pose_slide_init(bContext *C, wmOperator *op, ePoseSlide_Modes mode) | static int pose_slide_init(bContext *C, wmOperator *op, ePoseSlide_Modes mode) | ||||
| { | { | ||||
| tPoseSlideOp *pso; | tPoseSlideOp *pso; | ||||
| /* Init slide-op data. */ | /* Init slide-op data. */ | ||||
| pso = op->customdata = MEM_callocN(sizeof(tPoseSlideOp), "tPoseSlideOp"); | pso = op->customdata = MEM_callocN(sizeof(tPoseSlideOp), "tPoseSlideOp"); | ||||
| /* Get info from context. */ | /* Get info from context. */ | ||||
| pso->scene = CTX_data_scene(C); | pso->scene = CTX_data_scene(C); | ||||
| pso->area = CTX_wm_area(C); /* Only really needed when doing modal(). */ | pso->area = CTX_wm_area(C); /* Only really needed when doing modal(). */ | ||||
| pso->region_header = CTX_wm_region(C); /* Only really needed when doing modal(). */ | pso->region = CTX_wm_region(C); /* Only really needed when doing modal(). */ | ||||
| pso->cframe = pso->scene->r.cfra; | pso->cframe = pso->scene->r.cfra; | ||||
| pso->mode = mode; | pso->mode = mode; | ||||
| /* Set range info from property values - these may get overridden for the invoke(). */ | /* Set range info from property values - these may get overridden for the invoke(). */ | ||||
| pso->factor = RNA_float_get(op->ptr, "factor"); | |||||
| pso->raw_factor = pso->factor; | |||||
| pso->prevFrame = RNA_int_get(op->ptr, "prev_frame"); | pso->prevFrame = RNA_int_get(op->ptr, "prev_frame"); | ||||
| pso->nextFrame = RNA_int_get(op->ptr, "next_frame"); | pso->nextFrame = RNA_int_get(op->ptr, "next_frame"); | ||||
| /* Get the set of properties/axes that can be operated on. */ | /* Get the set of properties/axes that can be operated on. */ | ||||
| pso->channels = RNA_enum_get(op->ptr, "channels"); | pso->channels = RNA_enum_get(op->ptr, "channels"); | ||||
| pso->axislock = RNA_enum_get(op->ptr, "axis_lock"); | pso->axislock = RNA_enum_get(op->ptr, "axis_lock"); | ||||
| pso->slider = ED_slider_create(C); | |||||
| ED_slider_factor_set(pso->slider, RNA_float_get(op->ptr, "factor")); | |||||
| /* For each Pose-Channel which gets affected, get the F-Curves for that channel | /* For each Pose-Channel which gets affected, get the F-Curves for that channel | ||||
| * and set the relevant transform flags. */ | * and set the relevant transform flags. */ | ||||
| poseAnim_mapping_get(C, &pso->pfLinks); | poseAnim_mapping_get(C, &pso->pfLinks); | ||||
| Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data( | Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data( | ||||
| CTX_data_view_layer(C), CTX_wm_view3d(C), &pso->objects_len, OB_MODE_POSE); | CTX_data_view_layer(C), CTX_wm_view3d(C), &pso->objects_len, OB_MODE_POSE); | ||||
| pso->ob_data_array = MEM_callocN(pso->objects_len * sizeof(tPoseSlideObject), | pso->ob_data_array = MEM_callocN(pso->objects_len * sizeof(tPoseSlideObject), | ||||
| "pose slide objects data"); | "pose slide objects data"); | ||||
| Show All 28 Lines | static int pose_slide_init(bContext *C, wmOperator *op, ePoseSlide_Modes mode) | ||||
| BLI_dlrbTree_init(&pso->keys); | BLI_dlrbTree_init(&pso->keys); | ||||
| /* Initialize numeric input. */ | /* Initialize numeric input. */ | ||||
| initNumInput(&pso->num); | initNumInput(&pso->num); | ||||
| pso->num.idx_max = 0; /* One axis. */ | pso->num.idx_max = 0; /* One axis. */ | ||||
| pso->num.val_flag[0] |= NUM_NO_NEGATIVE; | pso->num.val_flag[0] |= NUM_NO_NEGATIVE; | ||||
| pso->num.unit_type[0] = B_UNIT_NONE; /* Percentages don't have any units. */ | 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_header = 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 status is whether we've got all the data we were requested to get. */ | ||||
| return 1; | return 1; | ||||
| } | } | ||||
| /** | /** | ||||
| * Exiting the operator (free data). | * Exiting the operator (free data). | ||||
| */ | */ | ||||
| static void pose_slide_exit(wmOperator *op) | static void pose_slide_exit(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| tPoseSlideOp *pso = op->customdata; | tPoseSlideOp *pso = op->customdata; | ||||
| ED_slider_destroy(C, pso->slider); | |||||
| /* Hide Bone Overlay. */ | /* Hide Bone Overlay. */ | ||||
| View3D *v3d = pso->area->spacedata.first; | View3D *v3d = pso->area->spacedata.first; | ||||
| v3d->overlay.flag = pso->overlay_flag; | v3d->overlay.flag = pso->overlay_flag; | ||||
| /* Remove UI drawing callback. */ | |||||
| ED_region_draw_cb_exit(pso->region_header->type, pso->draw_handle); | |||||
| /* Free the temp pchan links and their data. */ | /* Free the temp pchan links and their data. */ | ||||
| poseAnim_mapping_free(&pso->pfLinks); | poseAnim_mapping_free(&pso->pfLinks); | ||||
| /* Free RB-BST for keyframes (if it contained data). */ | /* Free RB-BST for keyframes (if it contained data). */ | ||||
| BLI_dlrbTree_free(&pso->keys); | BLI_dlrbTree_free(&pso->keys); | ||||
| if (pso->ob_data_array != NULL) { | if (pso->ob_data_array != NULL) { | ||||
| MEM_freeN(pso->ob_data_array); | MEM_freeN(pso->ob_data_array); | ||||
| ▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, Object *ob, float *val) | ||||
| /* Previous/start. */ | /* Previous/start. */ | ||||
| sVal = evaluate_fcurve(fcu, prevFrameF); | sVal = evaluate_fcurve(fcu, prevFrameF); | ||||
| /* Next/end. */ | /* Next/end. */ | ||||
| eVal = evaluate_fcurve(fcu, nextFrameF); | eVal = evaluate_fcurve(fcu, nextFrameF); | ||||
| /* Calculate the relative weights of the endpoints. */ | /* Calculate the relative weights of the endpoints. */ | ||||
| if (pso->mode == POSESLIDE_BREAKDOWN) { | if (pso->mode == POSESLIDE_BREAKDOWN) { | ||||
| /* Get weights from the factor control. */ | /* Get weights from the factor control. */ | ||||
| w1 = pso->factor; /* This must come second. */ | w1 = ED_slider_factor_get(pso->slider); /* This must come second. */ | ||||
| w2 = 1.0f - w1; /* This must come first. */ | w2 = 1.0f - w1; /* This must come first. */ | ||||
| } | } | ||||
| else { | else { | ||||
| /* - these weights are derived from the relative distance of these | /* - these weights are derived from the relative distance of these | ||||
| * poses from the current frame | * poses from the current frame | ||||
| * - they then get normalized so that they only sum up to 1 | * - they then get normalized so that they only sum up to 1 | ||||
| */ | */ | ||||
| float wtot; | float wtot; | ||||
| Show All 9 Lines | static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, Object *ob, float *val) | ||||
| * - In all of these, the start+end values are multiplied by w2 and w1 (respectively), | * - In all of these, the start+end values are multiplied by w2 and w1 (respectively), | ||||
| * since multiplication in another order would decrease | * since multiplication in another order would decrease | ||||
| * the value the current frame is closer to. | * the value the current frame is closer to. | ||||
| */ | */ | ||||
| switch (pso->mode) { | switch (pso->mode) { | ||||
| case POSESLIDE_PUSH: /* Make the current pose more pronounced. */ | case POSESLIDE_PUSH: /* Make the current pose more pronounced. */ | ||||
| { | { | ||||
| /* Slide the pose away from the breakdown pose in the timeline */ | /* Slide the pose away from the breakdown pose in the timeline */ | ||||
| (*val) -= ((sVal * w2) + (eVal * w1) - (*val)) * pso->factor; | (*val) -= ((sVal * w2) + (eVal * w1) - (*val)) * ED_slider_factor_get(pso->slider); | ||||
| break; | break; | ||||
| } | } | ||||
| case POSESLIDE_RELAX: /* Make the current pose more like its surrounding ones. */ | case POSESLIDE_RELAX: /* Make the current pose more like its surrounding ones. */ | ||||
| { | { | ||||
| /* Slide the pose towards the breakdown pose in the timeline */ | /* Slide the pose towards the breakdown pose in the timeline */ | ||||
| (*val) += ((sVal * w2) + (eVal * w1) - (*val)) * pso->factor; | (*val) += ((sVal * w2) + (eVal * w1) - (*val)) * ED_slider_factor_get(pso->slider); | ||||
| break; | break; | ||||
| } | } | ||||
| case POSESLIDE_BREAKDOWN: /* Make the current pose slide around between the endpoints. */ | case POSESLIDE_BREAKDOWN: /* Make the current pose slide around between the endpoints. */ | ||||
| { | { | ||||
| /* Perform simple linear interpolation - | /* Perform simple linear interpolation - | ||||
| * coefficient for start must come from pso->factor. */ | * coefficient for start must come from pso->factor. */ | ||||
| /* TODO: make this use some kind of spline interpolation instead? */ | /* TODO: make this use some kind of spline interpolation instead? */ | ||||
| (*val) = ((sVal * w2) + (eVal * w1)); | (*val) = ((sVal * w2) + (eVal * w1)); | ||||
| ▲ Show 20 Lines • Show All 128 Lines • ▼ Show 20 Lines | static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl) | ||||
| FCurve *fcu_w = NULL, *fcu_x = NULL, *fcu_y = NULL, *fcu_z = NULL; | FCurve *fcu_w = NULL, *fcu_x = NULL, *fcu_y = NULL, *fcu_z = NULL; | ||||
| bPoseChannel *pchan = pfl->pchan; | bPoseChannel *pchan = pfl->pchan; | ||||
| LinkData *ld = NULL; | LinkData *ld = NULL; | ||||
| char *path = NULL; | char *path = NULL; | ||||
| float cframe; | float cframe; | ||||
| float prevFrameF, nextFrameF; | float prevFrameF, nextFrameF; | ||||
| if (!pose_frame_range_from_object_get(pso, pfl->ob, &prevFrameF, &nextFrameF)) { | if (!pose_frame_range_from_object_get(pso, pfl->ob, &prevFrameF, &nextFrameF)) { | ||||
| BLI_assert(!"Invalid pfl data"); | BLI_assert_msg(0, "Invalid pfl data"); | ||||
| return; | return; | ||||
| } | } | ||||
| /* Get the path to use - this should be quaternion rotations only (needs care). */ | /* Get the path to use - this should be quaternion rotations only (needs care). */ | ||||
| path = BLI_sprintfN("%s.%s", pfl->pchan_path, "rotation_quaternion"); | path = BLI_sprintfN("%s.%s", pfl->pchan_path, "rotation_quaternion"); | ||||
| /* Get the current frame number. */ | /* Get the current frame number. */ | ||||
| cframe = (float)pso->cframe; | cframe = (float)pso->cframe; | ||||
| Show All 38 Lines | if (pso->mode == POSESLIDE_BREAKDOWN) { | ||||
| quat_next[0] = evaluate_fcurve(fcu_w, nextFrameF); | quat_next[0] = evaluate_fcurve(fcu_w, nextFrameF); | ||||
| quat_next[1] = evaluate_fcurve(fcu_x, nextFrameF); | quat_next[1] = evaluate_fcurve(fcu_x, nextFrameF); | ||||
| quat_next[2] = evaluate_fcurve(fcu_y, nextFrameF); | quat_next[2] = evaluate_fcurve(fcu_y, nextFrameF); | ||||
| quat_next[3] = evaluate_fcurve(fcu_z, nextFrameF); | quat_next[3] = evaluate_fcurve(fcu_z, nextFrameF); | ||||
| normalize_qt(quat_prev); | normalize_qt(quat_prev); | ||||
| normalize_qt(quat_next); | normalize_qt(quat_next); | ||||
| interp_qt_qtqt(quat_final, quat_prev, quat_next, pso->factor); | interp_qt_qtqt(quat_final, quat_prev, quat_next, ED_slider_factor_get(pso->slider)); | ||||
| } | } | ||||
| else { | else { | ||||
| /* POSESLIDE_PUSH and POSESLIDE_RELAX. */ | /* POSESLIDE_PUSH and POSESLIDE_RELAX. */ | ||||
| float quat_breakdown[4]; | float quat_breakdown[4]; | ||||
| float quat_curr[4]; | float quat_curr[4]; | ||||
| copy_qt_qt(quat_curr, pchan->quat); | copy_qt_qt(quat_curr, pchan->quat); | ||||
| quat_breakdown[0] = evaluate_fcurve(fcu_w, cframe); | quat_breakdown[0] = evaluate_fcurve(fcu_w, cframe); | ||||
| quat_breakdown[1] = evaluate_fcurve(fcu_x, cframe); | quat_breakdown[1] = evaluate_fcurve(fcu_x, cframe); | ||||
| quat_breakdown[2] = evaluate_fcurve(fcu_y, cframe); | quat_breakdown[2] = evaluate_fcurve(fcu_y, cframe); | ||||
| quat_breakdown[3] = evaluate_fcurve(fcu_z, cframe); | quat_breakdown[3] = evaluate_fcurve(fcu_z, cframe); | ||||
| normalize_qt(quat_breakdown); | normalize_qt(quat_breakdown); | ||||
| normalize_qt(quat_curr); | normalize_qt(quat_curr); | ||||
| if (pso->mode == POSESLIDE_PUSH) { | if (pso->mode == POSESLIDE_PUSH) { | ||||
| interp_qt_qtqt(quat_final, quat_breakdown, quat_curr, 1.0f + pso->factor); | interp_qt_qtqt( | ||||
| quat_final, quat_breakdown, quat_curr, 1.0f + ED_slider_factor_get(pso->slider)); | |||||
| } | } | ||||
| else { | else { | ||||
| BLI_assert(pso->mode == POSESLIDE_RELAX); | BLI_assert(pso->mode == POSESLIDE_RELAX); | ||||
| interp_qt_qtqt(quat_final, quat_curr, quat_breakdown, pso->factor); | interp_qt_qtqt(quat_final, quat_curr, quat_breakdown, ED_slider_factor_get(pso->slider)); | ||||
| } | } | ||||
| } | } | ||||
| /* Apply final to the pose bone, keeping compatible for similar keyframe positions. */ | /* Apply final to the pose bone, keeping compatible for similar keyframe positions. */ | ||||
| quat_to_compatible_quat(pchan->quat, quat_final, pchan->quat); | quat_to_compatible_quat(pchan->quat, quat_final, pchan->quat); | ||||
| } | } | ||||
| /* Free the path now. */ | /* Free the path now. */ | ||||
| MEM_freeN(path); | MEM_freeN(path); | ||||
| } | } | ||||
| static void pose_slide_rest_pose_apply_vec3(tPoseSlideOp *pso, float vec[3], float default_value) | 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; | const int lock = pso->axislock; | ||||
| for (int idx = 0; idx < 3; idx++) { | for (int idx = 0; idx < 3; idx++) { | ||||
| if ((lock == 0) || ((lock & PS_LOCK_X) && (idx == 0)) || ((lock & PS_LOCK_Y) && (idx == 1)) || | if ((lock == 0) || ((lock & PS_LOCK_X) && (idx == 0)) || ((lock & PS_LOCK_Y) && (idx == 1)) || | ||||
| ((lock & PS_LOCK_Z) && (idx == 2))) { | ((lock & PS_LOCK_Z) && (idx == 2))) { | ||||
| float diff_val = default_value - vec[idx]; | float diff_val = default_value - vec[idx]; | ||||
| if (pso->mode == POSESLIDE_RELAX_REST) { | if (pso->mode == POSESLIDE_RELAX_REST) { | ||||
| vec[idx] += pso->factor * diff_val; | vec[idx] += ED_slider_factor_get(pso->slider) * diff_val; | ||||
| } | } | ||||
| else { | else { | ||||
| /* Push */ | /* Push */ | ||||
| vec[idx] -= pso->factor * diff_val; | vec[idx] -= ED_slider_factor_get(pso->slider) * diff_val; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void pose_slide_rest_pose_apply_other_rot(tPoseSlideOp *pso, float vec[4], bool quat) | 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}; | float default_values[] = {1.0f, 0.0f, 0.0f, 0.0f}; | ||||
| if (!quat) { | if (!quat) { | ||||
| /* Axis Angle */ | /* Axis Angle */ | ||||
| default_values[0] = 0.0f; | default_values[0] = 0.0f; | ||||
| default_values[2] = 1.0f; | default_values[2] = 1.0f; | ||||
| } | } | ||||
| for (int idx = 0; idx < 4; idx++) { | for (int idx = 0; idx < 4; idx++) { | ||||
| float diff_val = default_values[idx] - vec[idx]; | float diff_val = default_values[idx] - vec[idx]; | ||||
| if (pso->mode == POSESLIDE_RELAX_REST) { | if (pso->mode == POSESLIDE_RELAX_REST) { | ||||
| vec[idx] += pso->factor * diff_val; | vec[idx] += ED_slider_factor_get(pso->slider) * diff_val; | ||||
| } | } | ||||
| else { | else { | ||||
| /* Push */ | /* Push */ | ||||
| vec[idx] -= pso->factor * diff_val; | vec[idx] -= ED_slider_factor_get(pso->slider) * diff_val; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * apply() - perform the pose sliding between the current pose and the rest pose. | * apply() - perform the pose sliding between the current pose and the rest pose. | ||||
| */ | */ | ||||
| static void pose_slide_rest_pose_apply(bContext *C, tPoseSlideOp *pso) | static void pose_slide_rest_pose_apply(bContext *C, tPoseSlideOp *pso) | ||||
| ▲ Show 20 Lines • Show All 156 Lines • ▼ Show 20 Lines | |||||
| * TODO: Include hints about locks here. | * TODO: Include hints about locks here. | ||||
| */ | */ | ||||
| static void pose_slide_draw_status(bContext *C, tPoseSlideOp *pso) | static void pose_slide_draw_status(bContext *C, tPoseSlideOp *pso) | ||||
| { | { | ||||
| char status_str[UI_MAX_DRAW_STR]; | char status_str[UI_MAX_DRAW_STR]; | ||||
| char limits_str[UI_MAX_DRAW_STR]; | char limits_str[UI_MAX_DRAW_STR]; | ||||
| char axis_str[50]; | char axis_str[50]; | ||||
| char mode_str[32]; | char mode_str[32]; | ||||
| char overshoot_str[50]; | char slider_str[UI_MAX_DRAW_STR]; | ||||
| char precision_str[50]; | |||||
| char increments_str[50]; | |||||
| char bone_vis_str[50]; | char bone_vis_str[50]; | ||||
| switch (pso->mode) { | switch (pso->mode) { | ||||
| case POSESLIDE_PUSH: | case POSESLIDE_PUSH: | ||||
| strcpy(mode_str, TIP_("Push Pose")); | strcpy(mode_str, TIP_("Push Pose")); | ||||
| break; | break; | ||||
| case POSESLIDE_RELAX: | case POSESLIDE_RELAX: | ||||
| strcpy(mode_str, TIP_("Relax Pose")); | strcpy(mode_str, TIP_("Relax Pose")); | ||||
| ▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | switch (pso->channels) { | ||||
| case PS_TFM_PROPS: | case PS_TFM_PROPS: | ||||
| STRNCPY(limits_str, TIP_("G/R/S/B/[C] - Custom Properties only (C to clear) | %s")); | STRNCPY(limits_str, TIP_("G/R/S/B/[C] - Custom Properties only (C to clear) | %s")); | ||||
| break; | break; | ||||
| default: | default: | ||||
| STRNCPY(limits_str, TIP_("G/R/S/B/C - Limit to Transform/Property Set")); | STRNCPY(limits_str, TIP_("G/R/S/B/C - Limit to Transform/Property Set")); | ||||
| break; | break; | ||||
| } | } | ||||
| if (pso->overshoot) { | |||||
| STRNCPY(overshoot_str, TIP_("[E] - Disable overshoot")); | |||||
| } | |||||
| else { | |||||
| STRNCPY(overshoot_str, TIP_("[E] - Enable overshoot")); | |||||
| } | |||||
| if (pso->precision) { | |||||
| STRNCPY(precision_str, TIP_("[Shift] - Precision active")); | |||||
| } | |||||
| else { | |||||
| STRNCPY(precision_str, TIP_("Shift - Hold for precision")); | |||||
| } | |||||
| if (pso->increments) { | |||||
| STRNCPY(increments_str, TIP_("[Ctrl] - Increments active")); | |||||
| } | |||||
| else { | |||||
| STRNCPY(increments_str, TIP_("Ctrl - Hold for 10% increments")); | |||||
| } | |||||
| STRNCPY(bone_vis_str, TIP_("[H] - Toggle bone visibility")); | STRNCPY(bone_vis_str, TIP_("[H] - Toggle bone visibility")); | ||||
| ED_slider_status_string_get(pso->slider, slider_str, sizeof(slider_str)); | |||||
| if (hasNumInput(&pso->num)) { | if (hasNumInput(&pso->num)) { | ||||
| Scene *scene = pso->scene; | Scene *scene = pso->scene; | ||||
| char str_offs[NUM_STR_REP_LEN]; | char str_offs[NUM_STR_REP_LEN]; | ||||
| outputNumInput(&pso->num, str_offs, &scene->unit); | outputNumInput(&pso->num, str_offs, &scene->unit); | ||||
| BLI_snprintf(status_str, sizeof(status_str), "%s: %s | %s", mode_str, str_offs, limits_str); | BLI_snprintf(status_str, sizeof(status_str), "%s: %s | %s", mode_str, str_offs, limits_str); | ||||
| } | } | ||||
| else { | else { | ||||
| BLI_snprintf(status_str, | BLI_snprintf(status_str, | ||||
| sizeof(status_str), | sizeof(status_str), | ||||
| "%s: %s | %s | %s | %s | %s", | "%s: %s | %s | %s", | ||||
| mode_str, | mode_str, | ||||
| limits_str, | limits_str, | ||||
| overshoot_str, | slider_str, | ||||
| precision_str, | |||||
| increments_str, | |||||
| bone_vis_str); | bone_vis_str); | ||||
| } | } | ||||
| ED_workspace_status_text(C, status_str); | ED_workspace_status_text(C, status_str); | ||||
| ED_area_status_text(pso->area, ""); | ED_area_status_text(pso->area, ""); | ||||
| } | } | ||||
| /** | /** | ||||
| * Common code for invoke() methods. | * Common code for invoke() methods. | ||||
| */ | */ | ||||
| static int pose_slide_invoke_common(bContext *C, wmOperator *op, tPoseSlideOp *pso) | static int pose_slide_invoke_common(bContext *C, wmOperator *op, const wmEvent *event) | ||||
| { | { | ||||
| tPChanFCurveLink *pfl; | tPChanFCurveLink *pfl; | ||||
| wmWindow *win = CTX_wm_window(C); | wmWindow *win = CTX_wm_window(C); | ||||
| tPoseSlideOp *pso = op->customdata; | |||||
| ED_slider_init(pso->slider, event); | |||||
| /* For each link, add all its keyframes to the search tree. */ | /* For each link, add all its keyframes to the search tree. */ | ||||
| for (pfl = pso->pfLinks.first; pfl; pfl = pfl->next) { | for (pfl = pso->pfLinks.first; pfl; pfl = pfl->next) { | ||||
| LinkData *ld; | LinkData *ld; | ||||
| /* Do this for each F-Curve. */ | /* Do this for each F-Curve. */ | ||||
| for (ld = pfl->fcurves.first; ld; ld = ld->next) { | for (ld = pfl->fcurves.first; ld; ld = ld->next) { | ||||
| FCurve *fcu = (FCurve *)ld->data; | FCurve *fcu = (FCurve *)ld->data; | ||||
| fcurve_to_keylist(pfl->ob->adt, fcu, &pso->keys, 0); | fcurve_to_keylist(pfl->ob->adt, fcu, &pso->keys, 0); | ||||
| ▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | for (uint ob_index = 0; ob_index < pso->objects_len; ob_index++) { | ||||
| ob_data->ob->adt, pso->prevFrame, NLATIME_CONVERT_UNMAP); | ob_data->ob->adt, pso->prevFrame, NLATIME_CONVERT_UNMAP); | ||||
| ob_data->nextFrameF = BKE_nla_tweakedit_remap( | ob_data->nextFrameF = BKE_nla_tweakedit_remap( | ||||
| ob_data->ob->adt, pso->nextFrame, NLATIME_CONVERT_UNMAP); | ob_data->ob->adt, pso->nextFrame, NLATIME_CONVERT_UNMAP); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| BKE_report(op->reports, RPT_ERROR, "No keyframes to slide between"); | BKE_report(op->reports, RPT_ERROR, "No keyframes to slide between"); | ||||
| pose_slide_exit(op); | pose_slide_exit(C, op); | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| /* Initial apply for operator. */ | /* Initial apply for operator. */ | ||||
| /* TODO: need to calculate factor for initial round too. */ | /* TODO: need to calculate factor for initial round too. */ | ||||
| if (!ELEM(pso->mode, POSESLIDE_PUSH_REST, POSESLIDE_RELAX_REST)) { | if (!ELEM(pso->mode, POSESLIDE_PUSH_REST, POSESLIDE_RELAX_REST)) { | ||||
| pose_slide_apply(C, pso); | pose_slide_apply(C, pso); | ||||
| } | } | ||||
| else { | else { | ||||
| pose_slide_rest_pose_apply(C, pso); | pose_slide_rest_pose_apply(C, pso); | ||||
| } | } | ||||
| /* Depsgraph updates + redraws. */ | /* Depsgraph updates + redraws. */ | ||||
| pose_slide_refresh(C, pso); | pose_slide_refresh(C, pso); | ||||
| /* Set cursor to indicate modal. */ | /* Set cursor to indicate modal. */ | ||||
| WM_cursor_modal_set(win, WM_CURSOR_EW_SCROLL); | WM_cursor_modal_set(win, WM_CURSOR_EW_SCROLL); | ||||
| /* Header print. */ | /* Header print. */ | ||||
| pose_slide_draw_status(C, pso); | pose_slide_draw_status(C, pso); | ||||
| /* Add a modal handler for this operator. */ | /* Add a modal handler for this operator. */ | ||||
| WM_event_add_modal_handler(C, op); | WM_event_add_modal_handler(C, op); | ||||
| /* Hide Bone Overlay. */ | /* Save current bone visibility. */ | ||||
| View3D *v3d = pso->area->spacedata.first; | View3D *v3d = pso->area->spacedata.first; | ||||
| pso->overlay_flag = v3d->overlay.flag; | pso->overlay_flag = v3d->overlay.flag; | ||||
| v3d->overlay.flag |= V3D_OVERLAY_HIDE_BONES; | |||||
| return OPERATOR_RUNNING_MODAL; | return OPERATOR_RUNNING_MODAL; | ||||
| } | } | ||||
| /** | /** | ||||
| * Calculate factor based on mouse movement, clamp or round to increments if | |||||
| * enabled by the user. Store the new factor value. | |||||
| */ | |||||
| static void pose_slide_mouse_update_factor(tPoseSlideOp *pso, wmOperator *op, const wmEvent *event) | |||||
| { | |||||
| const float factor_delta = (event->x - pso->last_cursor_x) / ((float)(SLIDE_PIXEL_DISTANCE)); | |||||
| /* Reduced factor delta in precision mode (shift held). */ | |||||
| pso->raw_factor += pso->precision ? (factor_delta / 8) : factor_delta; | |||||
| pso->factor = pso->raw_factor; | |||||
| pso->last_cursor_x = event->x; | |||||
| if (!pso->overshoot) { | |||||
| pso->factor = clamp_f(pso->factor, 0, 1); | |||||
| } | |||||
| if (pso->increments) { | |||||
| pso->factor = round(pso->factor * 10) / 10; | |||||
| } | |||||
| RNA_float_set(op->ptr, "factor", pso->factor); | |||||
| } | |||||
| /** | |||||
| * Handle an event to toggle channels mode. | * Handle an event to toggle channels mode. | ||||
| */ | */ | ||||
| static void pose_slide_toggle_channels_mode(wmOperator *op, | static void pose_slide_toggle_channels_mode(wmOperator *op, | ||||
| tPoseSlideOp *pso, | tPoseSlideOp *pso, | ||||
| ePoseSlide_Channels channel) | ePoseSlide_Channels channel) | ||||
| { | { | ||||
| /* Turn channel on or off? */ | /* Turn channel on or off? */ | ||||
| if (pso->channels == channel) { | if (pso->channels == channel) { | ||||
| ▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | |||||
| static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) | static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) | ||||
| { | { | ||||
| tPoseSlideOp *pso = op->customdata; | tPoseSlideOp *pso = op->customdata; | ||||
| wmWindow *win = CTX_wm_window(C); | wmWindow *win = CTX_wm_window(C); | ||||
| bool do_pose_update = false; | bool do_pose_update = false; | ||||
| const bool has_numinput = hasNumInput(&pso->num); | const bool has_numinput = hasNumInput(&pso->num); | ||||
| do_pose_update = ED_slider_modal(pso->slider, event); | |||||
| switch (event->type) { | switch (event->type) { | ||||
| case LEFTMOUSE: /* Confirm. */ | case LEFTMOUSE: /* Confirm. */ | ||||
| case EVT_RETKEY: | case EVT_RETKEY: | ||||
| case EVT_PADENTER: { | case EVT_PADENTER: { | ||||
| if (event->val == KM_PRESS) { | if (event->val == KM_PRESS) { | ||||
| /* Return to normal cursor and header status. */ | /* Return to normal cursor and header status. */ | ||||
| ED_workspace_status_text(C, NULL); | ED_workspace_status_text(C, NULL); | ||||
| ED_area_status_text(pso->area, NULL); | ED_area_status_text(pso->area, NULL); | ||||
| WM_cursor_modal_restore(win); | WM_cursor_modal_restore(win); | ||||
| /* Depsgraph updates + redraws. Redraw needed to remove UI. */ | /* Depsgraph updates + redraws. Redraw needed to remove UI. */ | ||||
| pose_slide_refresh(C, pso); | pose_slide_refresh(C, pso); | ||||
| /* Insert keyframes as required. */ | /* Insert keyframes as required. */ | ||||
| pose_slide_autoKeyframe(C, pso); | pose_slide_autoKeyframe(C, pso); | ||||
| pose_slide_exit(op); | pose_slide_exit(C, op); | ||||
| /* Done! */ | /* Done! */ | ||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| case EVT_ESCKEY: /* Cancel. */ | case EVT_ESCKEY: /* Cancel. */ | ||||
| case RIGHTMOUSE: { | case RIGHTMOUSE: { | ||||
| if (event->val == KM_PRESS) { | if (event->val == KM_PRESS) { | ||||
| /* Return to normal cursor and header status. */ | /* Return to normal cursor and header status. */ | ||||
| ED_workspace_status_text(C, NULL); | ED_workspace_status_text(C, NULL); | ||||
| ED_area_status_text(pso->area, NULL); | ED_area_status_text(pso->area, NULL); | ||||
| WM_cursor_modal_restore(win); | WM_cursor_modal_restore(win); | ||||
| /* Reset transforms back to original state. */ | /* Reset transforms back to original state. */ | ||||
| pose_slide_reset(pso); | pose_slide_reset(pso); | ||||
| /* Depsgraph updates + redraws. */ | /* Depsgraph updates + redraws. */ | ||||
| pose_slide_refresh(C, pso); | pose_slide_refresh(C, pso); | ||||
| /* Clean up temp data. */ | /* Clean up temp data. */ | ||||
| pose_slide_exit(op); | pose_slide_exit(C, op); | ||||
| /* Canceled! */ | /* Canceled! */ | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| /* Factor Change... */ | /* Factor Change... */ | ||||
| case MOUSEMOVE: /* Calculate new position. */ | case MOUSEMOVE: /* Calculate new position. */ | ||||
| { | { | ||||
| /* Only handle mouse-move if not doing numinput. */ | /* Only handle mouse-move if not doing numinput. */ | ||||
| if (has_numinput == false) { | if (has_numinput == false) { | ||||
| /* Update factor based on position of mouse. */ | |||||
| pose_slide_mouse_update_factor(pso, op, event); | |||||
| /* Update pose to reflect the new values (see below). */ | /* Update pose to reflect the new values (see below). */ | ||||
| do_pose_update = true; | do_pose_update = true; | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| default: { | default: { | ||||
| if ((event->val == KM_PRESS) && handleNumInput(C, &pso->num, event)) { | if ((event->val == KM_PRESS) && handleNumInput(C, &pso->num, event)) { | ||||
| float value; | float value; | ||||
| /* Grab percentage from numeric input, and store this new value for redo | /* Grab percentage from numeric input, and store this new value for redo | ||||
| * NOTE: users see ints, while internally we use a 0-1 float | * NOTE: users see ints, while internally we use a 0-1 float | ||||
| */ | */ | ||||
| value = pso->factor * 100.0f; | value = ED_slider_factor_get(pso->slider) * 100.0f; | ||||
| applyNumInput(&pso->num, &value); | applyNumInput(&pso->num, &value); | ||||
| pso->factor = value / 100.0f; | float factor = value / 100; | ||||
| CLAMP(pso->factor, 0.0f, 1.0f); | CLAMP(factor, 0.0f, 1.0f); | ||||
| RNA_float_set(op->ptr, "factor", pso->factor); | ED_slider_factor_set(pso->slider, factor); | ||||
| RNA_float_set(op->ptr, "factor", ED_slider_factor_get(pso->slider)); | |||||
| /* Update pose to reflect the new values (see below) */ | /* Update pose to reflect the new values (see below) */ | ||||
| do_pose_update = true; | do_pose_update = true; | ||||
| break; | break; | ||||
| } | } | ||||
| if (event->val == KM_PRESS) { | if (event->val == KM_PRESS) { | ||||
| switch (event->type) { | switch (event->type) { | ||||
| /* Transform Channel Limits. */ | /* Transform Channel Limits. */ | ||||
| ▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | default: { | ||||
| } | } | ||||
| case EVT_ZKEY: { | case EVT_ZKEY: { | ||||
| if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_Z)) { | if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_Z)) { | ||||
| do_pose_update = true; | do_pose_update = true; | ||||
| } | } | ||||
| break; | 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. */ | /* Toggle Bone visibility. */ | ||||
| case EVT_HKEY: { | case EVT_HKEY: { | ||||
| View3D *v3d = pso->area->spacedata.first; | View3D *v3d = pso->area->spacedata.first; | ||||
| v3d->overlay.flag ^= V3D_OVERLAY_HIDE_BONES; | v3d->overlay.flag ^= V3D_OVERLAY_HIDE_BONES; | ||||
| ED_region_tag_redraw(pso->region); | |||||
| } | } | ||||
| default: /* Some other unhandled key... */ | default: /* Some other unhandled key... */ | ||||
| break; | 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 { | else { | ||||
| /* Unhandled event - maybe it was some view manipulation? */ | /* Unhandled event - maybe it was some view manipulation? */ | ||||
| /* Allow to pass through. */ | /* Allow to pass through. */ | ||||
| return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH; | return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| Show All 17 Lines | static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) | ||||
| /* Still running. */ | /* Still running. */ | ||||
| return OPERATOR_RUNNING_MODAL; | return OPERATOR_RUNNING_MODAL; | ||||
| } | } | ||||
| /** | /** | ||||
| * Common code for cancel() | * Common code for cancel() | ||||
| */ | */ | ||||
| static void pose_slide_cancel(bContext *UNUSED(C), wmOperator *op) | static void pose_slide_cancel(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| /* Cleanup and done. */ | /* Cleanup and done. */ | ||||
| pose_slide_exit(op); | pose_slide_exit(C, op); | ||||
| } | } | ||||
| /** | /** | ||||
| * Common code for exec() methods. | * Common code for exec() methods. | ||||
| */ | */ | ||||
| static int pose_slide_exec_common(bContext *C, wmOperator *op, tPoseSlideOp *pso) | static int pose_slide_exec_common(bContext *C, wmOperator *op, tPoseSlideOp *pso) | ||||
| { | { | ||||
| /* Settings should have been set up ok for applying, so just apply! */ | /* Settings should have been set up ok for applying, so just apply! */ | ||||
| if (!ELEM(pso->mode, POSESLIDE_PUSH_REST, POSESLIDE_RELAX_REST)) { | if (!ELEM(pso->mode, POSESLIDE_PUSH_REST, POSESLIDE_RELAX_REST)) { | ||||
| pose_slide_apply(C, pso); | pose_slide_apply(C, pso); | ||||
| } | } | ||||
| else { | else { | ||||
| pose_slide_rest_pose_apply(C, pso); | pose_slide_rest_pose_apply(C, pso); | ||||
| } | } | ||||
| /* Insert keyframes if needed. */ | /* Insert keyframes if needed. */ | ||||
| pose_slide_autoKeyframe(C, pso); | pose_slide_autoKeyframe(C, pso); | ||||
| /* Cleanup and done. */ | /* Cleanup and done. */ | ||||
| pose_slide_exit(op); | pose_slide_exit(C, op); | ||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| /** | /** | ||||
| * Common code for defining RNA properties. | * Common code for defining RNA properties. | ||||
| */ | */ | ||||
| static void pose_slide_opdef_properties(wmOperatorType *ot) | static void pose_slide_opdef_properties(wmOperatorType *ot) | ||||
| ▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | |||||
| /* ------------------------------------ */ | /* ------------------------------------ */ | ||||
| /** | /** | ||||
| * Operator `invoke()` callback for 'push from breakdown' mode. | * Operator `invoke()` callback for 'push from breakdown' mode. | ||||
| */ | */ | ||||
| static int pose_slide_push_invoke(bContext *C, wmOperator *op, const wmEvent *event) | static int pose_slide_push_invoke(bContext *C, wmOperator *op, const wmEvent *event) | ||||
| { | { | ||||
| tPoseSlideOp *pso; | |||||
| /* Initialize data. */ | /* Initialize data. */ | ||||
| if (pose_slide_init(C, op, POSESLIDE_PUSH) == 0) { | if (pose_slide_init(C, op, POSESLIDE_PUSH) == 0) { | ||||
| pose_slide_exit(op); | pose_slide_exit(C, op); | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| pso = op->customdata; | |||||
| pso->last_cursor_x = event->x; | |||||
| /* Initialize factor so that it won't pop on first mouse move. */ | |||||
| pose_slide_mouse_update_factor(pso, op, event); | |||||
| /* Do common setup work. */ | /* Do common setup work. */ | ||||
| return pose_slide_invoke_common(C, op, pso); | return pose_slide_invoke_common(C, op, event); | ||||
| } | } | ||||
| /** | /** | ||||
| * Operator `exec()` callback - for push. | * Operator `exec()` callback - for push. | ||||
| */ | */ | ||||
| static int pose_slide_push_exec(bContext *C, wmOperator *op) | static int pose_slide_push_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| tPoseSlideOp *pso; | tPoseSlideOp *pso; | ||||
| /* Initialize data (from RNA-props). */ | /* Initialize data (from RNA-props). */ | ||||
| if (pose_slide_init(C, op, POSESLIDE_PUSH) == 0) { | if (pose_slide_init(C, op, POSESLIDE_PUSH) == 0) { | ||||
| pose_slide_exit(op); | pose_slide_exit(C, op); | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| pso = op->customdata; | pso = op->customdata; | ||||
| /* Do common exec work. */ | /* Do common exec work. */ | ||||
| return pose_slide_exec_common(C, op, pso); | return pose_slide_exec_common(C, op, pso); | ||||
| } | } | ||||
| Show All 21 Lines | |||||
| /* ........................ */ | /* ........................ */ | ||||
| /** | /** | ||||
| * Invoke callback - for 'relax to breakdown' mode. | * Invoke callback - for 'relax to breakdown' mode. | ||||
| */ | */ | ||||
| static int pose_slide_relax_invoke(bContext *C, wmOperator *op, const wmEvent *event) | static int pose_slide_relax_invoke(bContext *C, wmOperator *op, const wmEvent *event) | ||||
| { | { | ||||
| tPoseSlideOp *pso; | |||||
| /* Initialize data. */ | /* Initialize data. */ | ||||
| if (pose_slide_init(C, op, POSESLIDE_RELAX) == 0) { | if (pose_slide_init(C, op, POSESLIDE_RELAX) == 0) { | ||||
| pose_slide_exit(op); | pose_slide_exit(C, op); | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| pso = op->customdata; | |||||
| pso->last_cursor_x = event->x; | |||||
| /* Initialize factor so that it won't pop on first mouse move. */ | |||||
| pose_slide_mouse_update_factor(pso, op, event); | |||||
| /* Do common setup work. */ | /* Do common setup work. */ | ||||
| return pose_slide_invoke_common(C, op, pso); | return pose_slide_invoke_common(C, op, event); | ||||
| } | } | ||||
| /** | /** | ||||
| * Operator exec() - for relax. | * Operator exec() - for relax. | ||||
| */ | */ | ||||
| static int pose_slide_relax_exec(bContext *C, wmOperator *op) | static int pose_slide_relax_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| tPoseSlideOp *pso; | tPoseSlideOp *pso; | ||||
| /* Initialize data (from RNA-props). */ | /* Initialize data (from RNA-props). */ | ||||
| if (pose_slide_init(C, op, POSESLIDE_RELAX) == 0) { | if (pose_slide_init(C, op, POSESLIDE_RELAX) == 0) { | ||||
| pose_slide_exit(op); | pose_slide_exit(C, op); | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| pso = op->customdata; | pso = op->customdata; | ||||
| /* Do common exec work. */ | /* Do common exec work. */ | ||||
| return pose_slide_exec_common(C, op, pso); | return pose_slide_exec_common(C, op, pso); | ||||
| } | } | ||||
| Show All 20 Lines | |||||
| } | } | ||||
| /* ........................ */ | /* ........................ */ | ||||
| /** | /** | ||||
| * Operator `invoke()` - for 'push from rest pose' mode. | * Operator `invoke()` - for 'push from rest pose' mode. | ||||
| */ | */ | ||||
| static int pose_slide_push_rest_invoke(bContext *C, wmOperator *op, const wmEvent *event) | static int pose_slide_push_rest_invoke(bContext *C, wmOperator *op, const wmEvent *event) | ||||
| { | { | ||||
| tPoseSlideOp *pso; | |||||
| /* Initialize data. */ | /* Initialize data. */ | ||||
| if (pose_slide_init(C, op, POSESLIDE_PUSH_REST) == 0) { | if (pose_slide_init(C, op, POSESLIDE_PUSH_REST) == 0) { | ||||
| pose_slide_exit(op); | pose_slide_exit(C, op); | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| pso = op->customdata; | |||||
| pso->last_cursor_x = event->x; | |||||
| /* Initialize factor so that it won't pop on first mouse move. */ | |||||
| pose_slide_mouse_update_factor(pso, op, event); | |||||
| /* do common setup work */ | /* do common setup work */ | ||||
| return pose_slide_invoke_common(C, op, pso); | return pose_slide_invoke_common(C, op, event); | ||||
| } | } | ||||
| /** | /** | ||||
| * Operator `exec()` - for push. | * Operator `exec()` - for push. | ||||
| */ | */ | ||||
| static int pose_slide_push_rest_exec(bContext *C, wmOperator *op) | static int pose_slide_push_rest_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| tPoseSlideOp *pso; | tPoseSlideOp *pso; | ||||
| /* Initialize data (from RNA-props). */ | /* Initialize data (from RNA-props). */ | ||||
| if (pose_slide_init(C, op, POSESLIDE_PUSH_REST) == 0) { | if (pose_slide_init(C, op, POSESLIDE_PUSH_REST) == 0) { | ||||
| pose_slide_exit(op); | pose_slide_exit(C, op); | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| pso = op->customdata; | pso = op->customdata; | ||||
| /* Do common exec work. */ | /* Do common exec work. */ | ||||
| return pose_slide_exec_common(C, op, pso); | return pose_slide_exec_common(C, op, pso); | ||||
| } | } | ||||
| Show All 21 Lines | |||||
| /* ........................ */ | /* ........................ */ | ||||
| /** | /** | ||||
| * Operator `invoke()` - for 'relax' mode. | * Operator `invoke()` - for 'relax' mode. | ||||
| */ | */ | ||||
| static int pose_slide_relax_rest_invoke(bContext *C, wmOperator *op, const wmEvent *event) | static int pose_slide_relax_rest_invoke(bContext *C, wmOperator *op, const wmEvent *event) | ||||
| { | { | ||||
| tPoseSlideOp *pso; | |||||
| /* Initialize data. */ | /* Initialize data. */ | ||||
| if (pose_slide_init(C, op, POSESLIDE_RELAX_REST) == 0) { | if (pose_slide_init(C, op, POSESLIDE_RELAX_REST) == 0) { | ||||
| pose_slide_exit(op); | pose_slide_exit(C, op); | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| pso = op->customdata; | |||||
| pso->last_cursor_x = event->x; | |||||
| /* Initialize factor so that it won't pop on first mouse move. */ | |||||
| pose_slide_mouse_update_factor(pso, op, event); | |||||
| /* Do common setup work. */ | /* Do common setup work. */ | ||||
| return pose_slide_invoke_common(C, op, pso); | return pose_slide_invoke_common(C, op, event); | ||||
| } | } | ||||
| /** | /** | ||||
| * Operator `exec()` - for relax. | * Operator `exec()` - for relax. | ||||
| */ | */ | ||||
| static int pose_slide_relax_rest_exec(bContext *C, wmOperator *op) | static int pose_slide_relax_rest_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| tPoseSlideOp *pso; | tPoseSlideOp *pso; | ||||
| /* Initialize data (from RNA-props). */ | /* Initialize data (from RNA-props). */ | ||||
| if (pose_slide_init(C, op, POSESLIDE_RELAX_REST) == 0) { | if (pose_slide_init(C, op, POSESLIDE_RELAX_REST) == 0) { | ||||
| pose_slide_exit(op); | pose_slide_exit(C, op); | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| pso = op->customdata; | pso = op->customdata; | ||||
| /* Do common exec work. */ | /* Do common exec work. */ | ||||
| return pose_slide_exec_common(C, op, pso); | return pose_slide_exec_common(C, op, pso); | ||||
| } | } | ||||
| Show All 21 Lines | |||||
| /* ........................ */ | /* ........................ */ | ||||
| /** | /** | ||||
| * Operator `invoke()` - for 'breakdown' mode. | * Operator `invoke()` - for 'breakdown' mode. | ||||
| */ | */ | ||||
| static int pose_slide_breakdown_invoke(bContext *C, wmOperator *op, const wmEvent *event) | static int pose_slide_breakdown_invoke(bContext *C, wmOperator *op, const wmEvent *event) | ||||
| { | { | ||||
| tPoseSlideOp *pso; | |||||
| /* Initialize data. */ | /* Initialize data. */ | ||||
| if (pose_slide_init(C, op, POSESLIDE_BREAKDOWN) == 0) { | if (pose_slide_init(C, op, POSESLIDE_BREAKDOWN) == 0) { | ||||
| pose_slide_exit(op); | pose_slide_exit(C, op); | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| pso = op->customdata; | |||||
| pso->last_cursor_x = event->x; | |||||
| /* Initialize factor so that it won't pop on first mouse move. */ | |||||
| pose_slide_mouse_update_factor(pso, op, event); | |||||
| /* Do common setup work. */ | /* Do common setup work. */ | ||||
| return pose_slide_invoke_common(C, op, pso); | return pose_slide_invoke_common(C, op, event); | ||||
| } | } | ||||
| /** | /** | ||||
| * Operator exec() - for breakdown. | * Operator exec() - for breakdown. | ||||
| */ | */ | ||||
| static int pose_slide_breakdown_exec(bContext *C, wmOperator *op) | static int pose_slide_breakdown_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| tPoseSlideOp *pso; | tPoseSlideOp *pso; | ||||
| /* Initialize data (from RNA-props). */ | /* Initialize data (from RNA-props). */ | ||||
| if (pose_slide_init(C, op, POSESLIDE_BREAKDOWN) == 0) { | if (pose_slide_init(C, op, POSESLIDE_BREAKDOWN) == 0) { | ||||
| pose_slide_exit(op); | pose_slide_exit(C, op); | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| pso = op->customdata; | pso = op->customdata; | ||||
| /* Do common exec work. */ | /* Do common exec work. */ | ||||
| return pose_slide_exec_common(C, op, pso); | return pose_slide_exec_common(C, op, pso); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 448 Lines • Show Last 20 Lines | |||||