diff options
author | Campbell Barton <ideasman42@gmail.com> | 2017-03-11 19:00:06 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2017-03-11 19:00:06 +0300 |
commit | fbb1b311ea189b4d215cdfca3f507acb29ad2f3f (patch) | |
tree | da426f375bb7ffc5cad6227931fa99ee8a5e9919 /source/blender/editors | |
parent | cdb7498f663e539f05bc314c4e80c55ba45cdc02 (diff) | |
parent | bcc8c04db4a111b692660a7706757290a5f03465 (diff) |
Merge branch 'master' into blender2.8
Diffstat (limited to 'source/blender/editors')
-rw-r--r-- | source/blender/editors/animation/anim_channels_defines.c | 2 | ||||
-rw-r--r-- | source/blender/editors/animation/anim_ops.c | 10 | ||||
-rw-r--r-- | source/blender/editors/armature/pose_slide.c | 284 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_eyedropper.c | 2 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_layout.c | 5 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_ops.c | 1 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_widgets.c | 2 | ||||
-rw-r--r-- | source/blender/editors/io/io_alembic.c | 6 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_intersect.c | 11 | ||||
-rw-r--r-- | source/blender/editors/space_graph/graph_buttons.c | 32 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/drawobject.c | 7 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/drawvolume.c | 2 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 128 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_snap_object.c | 19 |
14 files changed, 413 insertions, 98 deletions
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 57379ccb4a1..166889037ef 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -2781,7 +2781,7 @@ static bAnimChannelType ACF_DSMCLIP = acf_generic_indention_1, /* indent level */ acf_generic_basic_offset, /* offset */ - acf_generic_idblock_name , /* name */ + acf_generic_idblock_name, /* name */ acf_generic_idfill_name_prop, /* name prop */ acf_dsmclip_icon, /* icon */ diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index bb73cbf03b4..0eb6508f7b2 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -103,11 +103,12 @@ static void change_frame_apply(bContext *C, wmOperator *op) } /* set the new frame number */ - CFRA = (int)frame; if (scene->r.flag & SCER_SHOW_SUBFRAME) { + CFRA = (int)frame; SUBFRA = frame - (int)frame; } else { + CFRA = iroundf(frame); SUBFRA = 0.0f; } FRAMENUMBER_MIN_CLAMP(CFRA); @@ -134,15 +135,12 @@ static float frame_from_event(bContext *C, const wmEvent *event) { ARegion *region = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); - float viewx; float frame; /* convert from region coordinates to View2D 'tot' space */ - viewx = UI_view2d_region_to_view_x(®ion->v2d, event->mval[0]); - - /* round result to nearest int (frames are ints!) */ - frame = viewx; + frame = UI_view2d_region_to_view_x(®ion->v2d, event->mval[0]); + /* respect preview range restrictions (if only allowed to move around within that range) */ if (scene->r.flag & SCER_LOCK_FRAME_SELECTION) { CLAMP(frame, PSFRA, PEFRA); } diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c index 8e8345d34c9..21cb405c32b 100644 --- a/source/blender/editors/armature/pose_slide.c +++ b/source/blender/editors/armature/pose_slide.c @@ -98,8 +98,11 @@ typedef struct tPoseSlideOp { int prevFrame; /* frame before current frame (blend-from) */ int nextFrame; /* frame after current frame (blend-to) */ - int mode; /* sliding mode (ePoseSlide_Modes) */ - int flag; /* unused for now, but can later get used for storing runtime settings.... */ + short mode; /* sliding mode (ePoseSlide_Modes) */ + short flag; /* unused for now, but can later get used for storing runtime settings.... */ + + short channels; /* which transforms/channels are affected (ePoseSlide_Channels) */ + short axislock; /* axis-limits for transforms (ePoseSlide_AxisLock) */ float percentage; /* 0-1 value for determining the influence of whatever is relevant */ @@ -113,6 +116,49 @@ typedef enum ePoseSlide_Modes { POSESLIDE_BREAKDOWN, /* slide between the endpoint poses, finding a 'soft' spot */ } ePoseSlide_Modes; + +/* Transforms/Channels to Affect */ +typedef enum ePoseSlide_Channels { + PS_TFM_ALL = 0, /* All transforms and properties */ + + PS_TFM_LOC, /* Loc/Rot/Scale */ + PS_TFM_ROT, + PS_TFM_SIZE, + + PS_TFM_BBONE_SHAPE, /* Bendy Bones */ + + PS_TFM_PROPS /* Custom Properties */ +} ePoseSlide_Channels; + +/* Property enum for ePoseSlide_Channels */ +static EnumPropertyItem prop_channels_types[] = { + {PS_TFM_ALL, "ALL", 0, "All Properties", + "All properties, including transforms, bendy bone shape, and custom properties"}, + {PS_TFM_LOC, "LOC", 0, "Location", "Location only"}, + {PS_TFM_ROT, "ROT", 0, "Rotation", "Rotation only"}, + {PS_TFM_SIZE, "SIZE", 0, "Scale", "Scale only"}, + {PS_TFM_BBONE_SHAPE, "BBONE", 0, "Bendy Bone", "Bendy Bone shape properties"}, + {PS_TFM_PROPS, "CUSTOM", 0, "Custom Properties", "Custom properties"}, + {0, NULL, 0, NULL, NULL} +}; + +/* Axis Locks */ +typedef enum ePoseSlide_AxisLock { + PS_LOCK_X = (1 << 0), + PS_LOCK_Y = (1 << 1), + PS_LOCK_Z = (1 << 2) +} ePoseSlide_AxisLock; + +/* Property enum for ePoseSlide_AxisLock */ +static EnumPropertyItem prop_axis_lock_types[] = { + {0, "FREE", 0, "Free", "All axes are affected"}, + {PS_LOCK_X, "X", 0, "X", "Only X-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"}, + /* TODO: Combinations? */ + {0, NULL, 0, NULL, NULL} +}; + /* ------------------------------------ */ /* operator init */ @@ -139,6 +185,10 @@ static int pose_slide_init(bContext *C, wmOperator *op, short mode) pso->prevFrame = RNA_int_get(op->ptr, "prev_frame"); pso->nextFrame = RNA_int_get(op->ptr, "next_frame"); + /* get the set of properties/axes that can be operated on */ + pso->channels = RNA_enum_get(op->ptr, "channels"); + pso->axislock = RNA_enum_get(op->ptr, "axis_lock"); + /* check the settings from the context */ if (ELEM(NULL, pso->ob, pso->arm, pso->ob->adt, pso->ob->adt->action)) return 0; @@ -293,10 +343,20 @@ static void pose_slide_apply_vec3(tPoseSlideOp *pso, tPChanFCurveLink *pfl, floa /* using this path, find each matching F-Curve for the variables we're interested in */ while ( (ld = poseAnim_mapping_getNextFCurve(&pfl->fcurves, ld, path)) ) { FCurve *fcu = (FCurve *)ld->data; - - /* just work on these channels one by one... there's no interaction between values */ + const int idx = fcu->array_index; + const int lock = pso->axislock; + + /* check if this F-Curve is ok given the current axis locks */ BLI_assert(fcu->array_index < 3); - pose_slide_apply_val(pso, fcu, &vec[fcu->array_index]); + + if ((lock == 0) || + ((lock & PS_LOCK_X) && (idx == 0)) || + ((lock & PS_LOCK_Y) && (idx == 1)) || + ((lock & PS_LOCK_Z) && (idx == 2))) + { + /* just work on these channels one by one... there's no interaction between values */ + pose_slide_apply_val(pso, fcu, &vec[fcu->array_index]); + } } /* free the temp path we got */ @@ -494,17 +554,17 @@ static void pose_slide_apply(bContext *C, tPoseSlideOp *pso) */ bPoseChannel *pchan = pfl->pchan; - if (pchan->flag & POSE_LOC) { + if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_LOC) && (pchan->flag & POSE_LOC)) { /* calculate these for the 'location' vector, and use location curves */ pose_slide_apply_vec3(pso, pfl, pchan->loc, "location"); } - if (pchan->flag & POSE_SIZE) { + if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_SIZE) && (pchan->flag & POSE_SIZE)) { /* calculate these for the 'scale' vector, and use scale curves */ pose_slide_apply_vec3(pso, pfl, pchan->size, "scale"); } - if (pchan->flag & POSE_ROT) { + if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_ROT) && (pchan->flag & POSE_ROT)) { /* everything depends on the rotation mode */ if (pchan->rotmode > 0) { /* eulers - so calculate these for the 'eul' vector, and use euler_rotation curves */ @@ -519,12 +579,12 @@ static void pose_slide_apply(bContext *C, tPoseSlideOp *pso) } } - if (pchan->flag & POSE_BBONE_SHAPE) { + if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_BBONE_SHAPE) && (pchan->flag & POSE_BBONE_SHAPE)) { /* bbone properties - they all start a "bbone_" prefix */ pose_slide_apply_props(pso, pfl, "bbone_"); } - if (pfl->oldprops) { + if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_PROPS) && (pfl->oldprops)) { /* not strictly a transform, but custom properties contribute to the pose produced in many rigs * (e.g. the facial rigs used in Sintel) */ @@ -553,9 +613,12 @@ static void pose_slide_reset(tPoseSlideOp *pso) /* ------------------------------------ */ /* draw percentage indicator in header */ +// TODO: Include hints about locks here... static void pose_slide_draw_status(tPoseSlideOp *pso) { char status_str[UI_MAX_DRAW_STR]; + char limits_str[UI_MAX_DRAW_STR]; + char axis_str[50]; char mode_str[32]; switch (pso->mode) { @@ -575,16 +638,58 @@ static void pose_slide_draw_status(tPoseSlideOp *pso) break; } + switch (pso->axislock) { + case PS_LOCK_X: + BLI_strncpy(axis_str, "[X]/Y/Z axis only (X to clear)", sizeof(axis_str)); + break; + case PS_LOCK_Y: + BLI_strncpy(axis_str, "X/[Y]/Z axis only (Y to clear)", sizeof(axis_str)); + break; + case PS_LOCK_Z: + BLI_strncpy(axis_str, "X/Y/[Z] axis only (Z to clear)", sizeof(axis_str)); + break; + + default: + if (ELEM(pso->channels, PS_TFM_LOC, PS_TFM_ROT, PS_TFM_SIZE)) { + BLI_strncpy(axis_str, "X/Y/Z = Axis Constraint", sizeof(axis_str)); + } + else { + axis_str[0] = '\0'; + } + break; + } + + switch (pso->channels) { + case PS_TFM_LOC: + BLI_snprintf(limits_str, sizeof(limits_str), "[G]/R/S/B/C - Location only (G to clear) | %s", axis_str); + break; + case PS_TFM_ROT: + BLI_snprintf(limits_str, sizeof(limits_str), "G/[R]/S/B/C - Rotation only (R to clear) | %s", axis_str); + break; + case PS_TFM_SIZE: + BLI_snprintf(limits_str, sizeof(limits_str), "G/R/[S]/B/C - Scale only (S to clear) | %s", axis_str); + break; + case PS_TFM_BBONE_SHAPE: + BLI_strncpy(limits_str, "G/R/S/[B]/C - Bendy Bone properties only (B to clear) | %s", sizeof(limits_str)); + break; + case PS_TFM_PROPS: + BLI_strncpy(limits_str, "G/R/S/B/[C] - Custom Properties only (C to clear) | %s", sizeof(limits_str)); + break; + default: + BLI_strncpy(limits_str, "G/R/S/B/C - Limit to Transform/Property Set", sizeof(limits_str)); + break; + } + if (hasNumInput(&pso->num)) { Scene *scene = pso->scene; char str_offs[NUM_STR_REP_LEN]; outputNumInput(&pso->num, str_offs, &scene->unit); - BLI_snprintf(status_str, sizeof(status_str), "%s: %s", mode_str, str_offs); + 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 %%", mode_str, (int)(pso->percentage * 100.0f)); + BLI_snprintf(status_str, sizeof(status_str), "%s: %d %% | %s", mode_str, (int)(pso->percentage * 100.0f), limits_str); } ED_area_headerprint(pso->sa, status_str); @@ -675,11 +780,58 @@ static void pose_slide_mouse_update_percentage(tPoseSlideOp *pso, wmOperator *op RNA_float_set(op->ptr, "percentage", pso->percentage); } +/* handle an event to toggle channels mode */ +static void pose_slide_toggle_channels_mode(wmOperator *op, tPoseSlideOp *pso, ePoseSlide_Channels channel) +{ + /* Turn channel on or off? */ + if (pso->channels == channel) { + /* Already limiting to transform only, so pressing this again turns it off */ + pso->channels = PS_TFM_ALL; + } + else { + /* Only this set of channels */ + pso->channels = channel; + } + RNA_enum_set(op->ptr, "channels", pso->channels); + + + /* Reset axis limits too for good measure */ + pso->axislock = 0; + RNA_enum_set(op->ptr, "axis_lock", pso->axislock); +} + +/* handle an event to toggle axis locks - returns whether any change in state is needed */ +static bool pose_slide_toggle_axis_locks(wmOperator *op, tPoseSlideOp *pso, ePoseSlide_AxisLock axis) +{ + /* Axis can only be set when a transform is set - it doesn't make sense otherwise */ + if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_BBONE_SHAPE, PS_TFM_PROPS)) { + pso->axislock = 0; + RNA_enum_set(op->ptr, "axis_lock", pso->axislock); + return false; + } + + /* Turn on or off? */ + if (pso->axislock == axis) { + /* Already limiting on this axis, so turn off */ + pso->axislock = 0; + } + else { + /* Only this axis */ + pso->axislock = axis; + } + RNA_enum_set(op->ptr, "axis_lock", pso->axislock); + + /* Setting changed, so pose update is needed */ + return true; +} + /* common code for modal() */ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) { tPoseSlideOp *pso = op->customdata; wmWindow *win = CTX_wm_window(C); + bool do_pose_update = false; + const bool has_numinput = hasNumInput(&pso->num); switch (event->type) { @@ -718,7 +870,8 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) /* canceled! */ return OPERATOR_CANCELLED; } - + + /* Percentage Chane... */ case MOUSEMOVE: /* calculate new position */ { /* only handle mousemove if not doing numinput */ @@ -726,14 +879,8 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) /* update percentage based on position of mouse */ pose_slide_mouse_update_percentage(pso, op, event); - /* update percentage indicator in header */ - pose_slide_draw_status(pso); - - /* reset transforms (to avoid accumulation errors) */ - pose_slide_reset(pso); - - /* apply... */ - pose_slide_apply(C, pso); + /* update pose to reflect the new values (see below) */ + do_pose_update = true; } break; } @@ -751,16 +898,75 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) CLAMP(pso->percentage, 0.0f, 1.0f); RNA_float_set(op->ptr, "percentage", pso->percentage); - /* update percentage indicator in header */ - pose_slide_draw_status(pso); - - /* reset transforms (to avoid accumulation errors) */ - pose_slide_reset(pso); - - /* apply... */ - pose_slide_apply(C, pso); + /* Update pose to reflect the new values (see below) */ + do_pose_update = true; break; } + else if (event->val == KM_PRESS) { + switch (event->type) { + /* Transform Channel Limits */ + /* XXX: Replace these hardcoded hotkeys with a modalmap that can be customised */ + case GKEY: /* Location */ + { + pose_slide_toggle_channels_mode(op, pso, PS_TFM_LOC); + do_pose_update = true; + break; + } + case RKEY: /* Rotation */ + { + pose_slide_toggle_channels_mode(op, pso, PS_TFM_ROT); + do_pose_update = true; + break; + } + case SKEY: /* Scale */ + { + pose_slide_toggle_channels_mode(op, pso, PS_TFM_SIZE); + do_pose_update = true; + break; + } + case BKEY: /* Bendy Bones */ + { + pose_slide_toggle_channels_mode(op, pso, PS_TFM_BBONE_SHAPE); + do_pose_update = true; + break; + } + case CKEY: /* Custom Properties */ + { + pose_slide_toggle_channels_mode(op, pso, PS_TFM_PROPS); + do_pose_update = true; + break; + } + + + /* Axis Locks */ + /* XXX: Hardcoded... */ + case XKEY: + { + if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_X)) { + do_pose_update = true; + } + break; + } + case YKEY: + { + if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_Y)) { + do_pose_update = true; + } + break; + } + case ZKEY: + { + if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_Z)) { + do_pose_update = true; + } + break; + } + + + default: /* Some other unhandled key... */ + break; + } + } else { /* unhandled event - maybe it was some view manip? */ /* allow to pass through */ @@ -768,6 +974,19 @@ 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) { + /* update percentage indicator in header */ + pose_slide_draw_status(pso); + + /* reset transforms (to avoid accumulation errors) */ + pose_slide_reset(pso); + + /* apply... */ + pose_slide_apply(C, pso); + } + /* still running... */ return OPERATOR_RUNNING_MODAL; } @@ -795,11 +1014,16 @@ static int pose_slide_exec_common(bContext *C, wmOperator *op, tPoseSlideOp *pso } /* common code for defining RNA properties */ +/* TODO: Skip save on these? */ static void pose_slide_opdef_properties(wmOperatorType *ot) { + RNA_def_float_percentage(ot->srna, "percentage", 0.5f, 0.0f, 1.0f, "Percentage", "Weighting factor for which keyframe is favored more", 0.3, 0.7); + RNA_def_int(ot->srna, "prev_frame", 0, MINAFRAME, MAXFRAME, "Previous Keyframe", "Frame number of keyframe immediately before the current frame", 0, 50); RNA_def_int(ot->srna, "next_frame", 0, MINAFRAME, MAXFRAME, "Next Keyframe", "Frame number of keyframe immediately after the current frame", 0, 50); - RNA_def_float_percentage(ot->srna, "percentage", 0.5f, 0.0f, 1.0f, "Percentage", "Weighting factor for the sliding operation", 0.3, 0.7); + + RNA_def_enum(ot->srna, "channels", prop_channels_types, PS_TFM_ALL, "Channels", "Set of properties that are affected"); + RNA_def_enum(ot->srna, "axis_lock", prop_axis_lock_types, 0, "Axis Lock", "Transform axis to restrict effects to"); } /* ------------------------------------ */ diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c index a50c0f5a4f4..f0a8527f9a4 100644 --- a/source/blender/editors/interface/interface_eyedropper.c +++ b/source/blender/editors/interface/interface_eyedropper.c @@ -1082,7 +1082,7 @@ static int depthdropper_poll(bContext *C) return 1; } } - else { + else { RegionView3D *rv3d = CTX_wm_region_view3d(C); if (rv3d && rv3d->persp == RV3D_CAMOB) { View3D *v3d = CTX_wm_view3d(C); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index ce1153911da..f6347388cc4 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -2238,8 +2238,9 @@ static void ui_litem_layout_row(uiLayout *litem) /* add extra pixel */ uiItem *last_item = litem->items.last; extra_pixel = litem->w - (x - litem->x); - if (extra_pixel > 0 && litem->alignment == UI_LAYOUT_ALIGN_EXPAND && - last_free_item && last_item && last_item->flag & UI_ITEM_FIXED) { + if (extra_pixel > 0 && litem->alignment == UI_LAYOUT_ALIGN_EXPAND && + last_free_item && last_item && last_item->flag & UI_ITEM_FIXED) + { ui_item_move(last_free_item, 0, extra_pixel); for (item = last_free_item->next; item; item = item->next) ui_item_move(item, extra_pixel, extra_pixel); diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 40ebc946e79..fb95cdf389b 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -739,6 +739,7 @@ static int editsource_text_edit( if (text == NULL) { text = BKE_text_load(bmain, filepath, bmain->name); + id_us_ensure_real(&text->id); } if (text == NULL) { diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 74eef14fda1..441378691f9 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1598,7 +1598,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB /* Icons on the left with optional text label on the right */ else if (but->flag & UI_HAS_ICON || show_menu_icon) { const BIFIconID icon = (but->flag & UI_HAS_ICON) ? but->icon + but->iconadd : ICON_NONE; - const float icon_size = ICON_DEFAULT_WIDTH; + const float icon_size = ICON_DEFAULT_WIDTH_SCALE; /* menu item - add some more padding so menus don't feel cramped. it must * be part of the button so that this area is still clickable */ diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c index a991f59e8e2..3f9eb33e239 100644 --- a/source/blender/editors/io/io_alembic.c +++ b/source/blender/editors/io/io_alembic.c @@ -124,9 +124,9 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op) .use_subdiv_schema = RNA_boolean_get(op->ptr, "subdiv_schema"), .compression_type = RNA_enum_get(op->ptr, "compression_type"), .packuv = RNA_boolean_get(op->ptr, "packuv"), - .triangulate = RNA_boolean_get(op->ptr, "triangulate"), - .quad_method = RNA_enum_get(op->ptr, "quad_method"), - .ngon_method = RNA_enum_get(op->ptr, "ngon_method"), + .triangulate = RNA_boolean_get(op->ptr, "triangulate"), + .quad_method = RNA_enum_get(op->ptr, "quad_method"), + .ngon_method = RNA_enum_get(op->ptr, "ngon_method"), .global_scale = RNA_float_get(op->ptr, "global_scale"), }; diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c index bc9088401db..49bfde77032 100644 --- a/source/blender/editors/mesh/editmesh_intersect.c +++ b/source/blender/editors/mesh/editmesh_intersect.c @@ -51,6 +51,7 @@ #include "mesh_intern.h" /* own include */ #include "tools/bmesh_intersect.h" +#include "tools/bmesh_separate.h" /* detect isolated holes and fill them */ @@ -196,13 +197,9 @@ static int edbm_intersect_exec(bContext *C, wmOperator *op) if (use_separate_cut) { /* detach selected/un-selected faces */ - BMOperator bmop; - EDBM_op_init(em, &bmop, op, "split geom=%hf use_only_faces=%b", BM_ELEM_SELECT, true); - BMO_op_exec(em->bm, &bmop); - if (!EDBM_op_finish(em, &bmop, op, true)) { - /* should never happen! */ - BKE_report(op->reports, RPT_ERROR, "Error separating"); - } + BM_mesh_separate_faces( + bm, + BM_elem_cb_check_hflag_enabled_simple(const BMFace *, BM_ELEM_SELECT)); } if (has_isect) { diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index 516814b63b4..cbb8e98e7e0 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -616,30 +616,31 @@ static void graph_panel_driverVar__rotDiff(uiLayout *layout, ID *id, DriverVar * Object *ob2 = (Object *)dtar2->id; PointerRNA dtar_ptr, dtar2_ptr; uiLayout *col; - + /* initialize RNA pointer to the target */ - RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr); - RNA_pointer_create(id, &RNA_DriverTarget, dtar2, &dtar2_ptr); - - /* Bone 1 */ + RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr); + RNA_pointer_create(id, &RNA_DriverTarget, dtar2, &dtar2_ptr); + + /* Object 1 */ col = uiLayoutColumn(layout, true); uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */ - uiItemR(col, &dtar_ptr, "id", 0, IFACE_("Bone 1"), ICON_NONE); - + uiItemR(col, &dtar_ptr, "id", 0, IFACE_("Object 1"), ICON_NONE); + if (dtar->id && GS(dtar->id->name) == ID_OB && ob1->pose) { PointerRNA tar_ptr; - + RNA_pointer_create(dtar->id, &RNA_Pose, ob1->pose, &tar_ptr); uiItemPointerR(col, &dtar_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA); } - + + /* Object 2 */ col = uiLayoutColumn(layout, true); uiLayoutSetRedAlert(col, (dtar2->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */ - uiItemR(col, &dtar2_ptr, "id", 0, IFACE_("Bone 2"), ICON_NONE); - + uiItemR(col, &dtar2_ptr, "id", 0, IFACE_("Object 2"), ICON_NONE); + if (dtar2->id && GS(dtar2->id->name) == ID_OB && ob2->pose) { PointerRNA tar_ptr; - + RNA_pointer_create(dtar2->id, &RNA_Pose, ob2->pose, &tar_ptr); uiItemPointerR(col, &dtar2_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA); } @@ -658,8 +659,8 @@ static void graph_panel_driverVar__locDiff(uiLayout *layout, ID *id, DriverVar * /* initialize RNA pointer to the target */ RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr); RNA_pointer_create(id, &RNA_DriverTarget, dtar2, &dtar2_ptr); - - /* Bone 1 */ + + /* Object 1 */ col = uiLayoutColumn(layout, true); uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */ uiItemR(col, &dtar_ptr, "id", 0, IFACE_("Object 1"), ICON_NONE); @@ -673,7 +674,8 @@ static void graph_panel_driverVar__locDiff(uiLayout *layout, ID *id, DriverVar * uiLayoutSetRedAlert(col, false); /* we can clear it again now - it's only needed when creating the ID/Bone fields */ uiItemR(col, &dtar_ptr, "transform_space", 0, NULL, ICON_NONE); - + + /* Object 2 */ col = uiLayoutColumn(layout, true); uiLayoutSetRedAlert(col, (dtar2->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */ uiItemR(col, &dtar2_ptr, "id", 0, IFACE_("Object 2"), ICON_NONE); diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 8df34f4f890..556cf74ecf0 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -8159,8 +8159,9 @@ static void drawtexspace(Object *ob, const unsigned char ob_wire_col[3]) } /* draws wire outline */ -static void drawObjectSelect(Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base, - const unsigned char ob_wire_col[4]) +static void draw_object_selected_outline( + Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base, + const unsigned char ob_wire_col[4]) { RegionView3D *rv3d = ar->regiondata; Object *ob = base->object; @@ -8648,7 +8649,7 @@ void draw_object(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *b if ((v3d->flag & V3D_SELECT_OUTLINE) && !render_override && ob->type != OB_MESH) { if (dt > OB_WIRE && (ob->mode & OB_MODE_EDIT) == 0 && (dflag & DRAW_SCENESET) == 0) { if (!(ob->dtx & OB_DRAWWIRE) && (base->flag & BASE_SELECTED) && !(dflag & (DRAW_PICKING | DRAW_CONSTCOLOR))) { - drawObjectSelect(scene, sl, v3d, ar, base, ob_wire_col); + draw_object_selected_outline(scene, sl, v3d, ar, base, ob_wire_col); } } } diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c index c8f4fa5d172..e246d5f53ef 100644 --- a/source/blender/editors/space_view3d/drawvolume.c +++ b/source/blender/editors/space_view3d/drawvolume.c @@ -737,7 +737,7 @@ static void add_streamline(float (*verts)[3], float(*colors)[3], float center[3] copy_v3_v3(verts[(*offset)++], center); } -typedef void (*vector_draw_func)(float(*)[3], float(*)[3], float*, float*, float, float, int*); +typedef void (*vector_draw_func)(float(*)[3], float(*)[3], float *, float *, float, float, int *); #endif /* WITH_SMOKE */ void draw_smoke_velocity(SmokeDomainSettings *domain, float viewnormal[3]) diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 763966fa93a..97221f588bb 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -1963,9 +1963,12 @@ void flushTransParticles(TransInfo *t) /* ********************* mesh ****************** */ -static bool bmesh_test_dist_add(BMVert *v, BMVert *v_other, - float *dists, const float *dists_prev, - float mtx[3][3]) +static bool bmesh_test_dist_add( + BMVert *v, BMVert *v_other, + float *dists, const float *dists_prev, + /* optionally track original index */ + int *index, const int *index_prev, + float mtx[3][3]) { if ((BM_elem_flag_test(v_other, BM_ELEM_SELECT) == 0) && (BM_elem_flag_test(v_other, BM_ELEM_HIDDEN) == 0)) @@ -1980,6 +1983,9 @@ static bool bmesh_test_dist_add(BMVert *v, BMVert *v_other, dist_other = dists_prev[i] + len_v3(vec); if (dist_other < dists[i_other]) { dists[i_other] = dist_other; + if (index != NULL) { + index[i_other] = index_prev[i]; + } return true; } } @@ -1987,11 +1993,13 @@ static bool bmesh_test_dist_add(BMVert *v, BMVert *v_other, return false; } -static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float *dists) +/** + * \parm mtx: Measure disatnce in this space. + * \parm dists: Store the closest connected distance to selected vertices. + * \parm index: Optionally store the original index we're measuring the distance to (can be NULL). + */ +static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float *dists, int *index) { - /* need to be very careful of feedback loops here, store previous dist's to avoid feedback */ - float *dists_prev = MEM_mallocN(bm->totvert * sizeof(float), __func__); - BLI_LINKSTACK_DECLARE(queue, BMVert *); /* any BM_ELEM_TAG'd vertex is in 'queue_next', so we don't add in twice */ @@ -2012,17 +2020,27 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float if (BM_elem_flag_test(v, BM_ELEM_SELECT) == 0 || BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { dist = FLT_MAX; + if (index != NULL) { + index[i] = i; + } } else { BLI_LINKSTACK_PUSH(queue, v); dist = 0.0f; + if (index != NULL) { + index[i] = i; + } } - dists[i] = dists_prev[i] = dist; + dists[i] = dist; } bm->elem_index_dirty &= ~BM_VERT; } + /* need to be very careful of feedback loops here, store previous dist's to avoid feedback */ + float *dists_prev = MEM_dupallocN(dists); + int *index_prev = MEM_dupallocN(index); /* may be NULL */ + do { BMVert *v; LinkNode *lnk; @@ -2051,7 +2069,7 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float /* edge distance */ { BMVert *v_other = BM_edge_other_vert(e_iter, v); - if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) { + if (bmesh_test_dist_add(v, v_other, dists, dists_prev, index, index_prev, mtx)) { if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) { BM_elem_flag_enable(v_other, BM_ELEM_TAG); BLI_LINKSTACK_PUSH(queue_next, v_other); @@ -2076,7 +2094,7 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float (BM_elem_flag_test(l_iter_radial->f, BM_ELEM_HIDDEN) == 0)) { BMVert *v_other = l_iter_radial->next->next->v; - if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) { + if (bmesh_test_dist_add(v, v_other, dists, dists_prev, index, index_prev, mtx)) { if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) { BM_elem_flag_enable(v_other, BM_ELEM_TAG); BLI_LINKSTACK_PUSH(queue_next, v_other); @@ -2100,6 +2118,9 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float /* keep in sync, avoid having to do full memcpy each iteration */ dists_prev[i] = dists[i]; + if (index != NULL) { + index_prev[i] = index[i]; + } } BLI_LINKSTACK_SWAP(queue, queue_next); @@ -2113,9 +2134,14 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float BLI_LINKSTACK_FREE(queue_next); MEM_freeN(dists_prev); + if (index_prev != NULL) { + MEM_freeN(index_prev); + } } -static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em, int *r_island_tot, int **r_island_vert_map) +static struct TransIslandData *editmesh_islands_info_calc( + BMEditMesh *em, int *r_island_tot, int **r_island_vert_map, + bool calc_single_islands) { BMesh *bm = em->bm; struct TransIslandData *trans_islands; @@ -2227,6 +2253,42 @@ static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em, int *r MEM_freeN(groups_array); MEM_freeN(group_index); + /* for PET we need islands of 1 so connected vertices can use it with V3D_AROUND_LOCAL_ORIGINS */ + if (calc_single_islands) { + BMIter viter; + BMVert *v; + int group_tot_single = 0; + + BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { + if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) { + group_tot_single += 1; + } + } + + if (group_tot_single != 0) { + trans_islands = MEM_reallocN(trans_islands, group_tot + group_tot_single); + + BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { + if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) { + struct TransIslandData *v_island = &trans_islands[group_tot]; + vert_map[i] = group_tot; + + copy_v3_v3(v_island->co, v->co); + + if (is_zero_v3(v->no) != 0.0f) { + axis_dominant_v3_to_m3(v_island->axismtx, v->no); + invert_m3(v_island->axismtx); + } + else { + unit_m3(v_island->axismtx); + } + + group_tot += 1; + } + } + } + } + *r_island_tot = group_tot; *r_island_vert_map = vert_map; @@ -2326,6 +2388,11 @@ static void createTransEditVerts(TransInfo *t) int island_info_tot; int *island_vert_map = NULL; + const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS) && (t->mode != TFM_TRANSLATION); + /* Original index of our connected vertex when connected distances are calculated. + * Optional, allocate if needed. */ + int *dists_index = NULL; + if (t->flag & T_MIRROR) { EDBM_verts_mirror_cache_begin(em, 0, false, (t->flag & T_PROP_EDIT) == 0, use_topology); mirror = 1; @@ -2357,8 +2424,12 @@ static void createTransEditVerts(TransInfo *t) t->total = count; /* allocating scratch arrays */ - if (prop_mode & T_PROP_CONNECTED) - dists = MEM_mallocN(em->bm->totvert * sizeof(float), "scratch nears"); + if (prop_mode & T_PROP_CONNECTED) { + dists = MEM_mallocN(em->bm->totvert * sizeof(float), __func__); + if (is_island_center) { + dists_index = MEM_mallocN(em->bm->totvert * sizeof(int), __func__); + } + } } else { t->total = bm->totvertsel; @@ -2380,7 +2451,7 @@ static void createTransEditVerts(TransInfo *t) pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); if (prop_mode & T_PROP_CONNECTED) { - editmesh_set_connectivity_distance(em->bm, mtx, dists); + editmesh_set_connectivity_distance(em->bm, mtx, dists, dists_index); } /* Only in case of rotation and resize, we want the elements of the edited @@ -2388,8 +2459,14 @@ static void createTransEditVerts(TransInfo *t) * * TODO: use island_info to detect the closest point when the "Snap Target" * in Blender UI is "Closest" */ - if ((t->around == V3D_AROUND_LOCAL_ORIGINS) && (t->mode != TFM_TRANSLATION)) { - island_info = editmesh_islands_info_calc(em, &island_info_tot, &island_vert_map); + if (is_island_center) { + /* In this specific case, near-by vertices will need to know the island of the nearest connected vertex. */ + const bool calc_single_islands = ( + (prop_mode & T_PROP_CONNECTED) && + (t->around == V3D_AROUND_LOCAL_ORIGINS) && + (em->selectmode & SCE_SELECT_VERTEX)); + + island_info = editmesh_islands_info_calc(em, &island_info_tot, &island_vert_map, calc_single_islands); } /* detect CrazySpace [tm] */ @@ -2439,10 +2516,16 @@ static void createTransEditVerts(TransInfo *t) BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) { if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) { - struct TransIslandData *v_island = (island_info && island_vert_map[a] != -1) ? - &island_info[island_vert_map[a]] : NULL; + struct TransIslandData *v_island = NULL; float *bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) : NULL; + if (island_info) { + const int connected_index = (dists_index && dists_index[a] != -1) ? dists_index[a] : a; + v_island = (island_vert_map[connected_index] != -1) ? + &island_info[island_vert_map[connected_index]] : NULL; + } + + VertsToTransData(t, tob, tx, em, eve, bweight, v_island); if (tx) tx++; @@ -2521,6 +2604,8 @@ cleanup: MEM_freeN(defmats); if (dists) MEM_freeN(dists); + if (dists_index) + MEM_freeN(dists_index); if (t->flag & T_MIRROR) { EDBM_verts_mirror_cache_end(em); @@ -8022,7 +8107,12 @@ void createTransData(bContext *C, TransInfo *t) if (t->data && t->flag & T_PROP_EDIT) { if (ELEM(t->obedit->type, OB_CURVE, OB_MESH)) { sort_trans_data(t); // makes selected become first in array - set_prop_dist(t, 0); + if ((t->obedit->type == OB_MESH) && (t->flag & T_PROP_CONNECTED)) { + /* already calculated by editmesh_set_connectivity_distance */ + } + else { + set_prop_dist(t, 0); + } sort_trans_data_dist(t); } else { diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index cbd3827154b..89eb8f787bc 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -936,9 +936,10 @@ static bool snapEmpty( float tmp_co[3]; copy_v3_v3(tmp_co, obmat[3]); if (test_projected_vert_dist( - snapdata->depth_range, snapdata->mval, tmp_co, - snapdata->pmat, snapdata->win_half, is_persp, &dist_px_sq, - r_loc)) { + snapdata->depth_range, snapdata->mval, tmp_co, + snapdata->pmat, snapdata->win_half, is_persp, &dist_px_sq, + r_loc)) + { *dist_px = sqrtf(dist_px_sq); *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir); retval = true; @@ -1119,8 +1120,8 @@ static bool snapDerivedMesh( /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */ if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { float dist_px_sq = dist_squared_to_projected_aabb_simple( - lpmat, snapdata->win_half, ray_min_dist, snapdata->mval, - ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]); + lpmat, snapdata->win_half, ray_min_dist, snapdata->mval, + ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]); if (dist_px_sq > SQUARE(*dist_px)) { return retval; @@ -2078,10 +2079,10 @@ static bool transform_snap_context_project_view3d_mixed_impl( for (int i = 0; i < 3; i++) { if (snap_to_flag & (1 << i)) { if (ED_transform_snap_object_project_view3d( - sctx, - elem_type[i], params, - mval, dist_px, &ray_depth, - r_co, r_no)) + sctx, + elem_type[i], params, + mval, dist_px, &ray_depth, + r_co, r_no)) { is_hit = true; break; |