diff options
Diffstat (limited to 'source/blender/editors/space_view3d')
5 files changed, 214 insertions, 56 deletions
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index d5e52785937..3428a738dde 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -39,6 +39,8 @@ #include "BLT_translation.h" +#include "BLI_array_utils.h" +#include "BLI_bitmap.h" #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_utildefines.h" @@ -112,10 +114,94 @@ typedef struct { float ob_dims[3]; /* Floats only (treated as an array). */ TransformMedian ve_median, median; + bool tag_for_update; } TransformProperties; #define TRANSFORM_MEDIAN_ARRAY_LEN (sizeof(TransformMedian) / sizeof(float)) +static TransformProperties *v3d_transform_props_ensure(View3D *v3d); + +/* -------------------------------------------------------------------- */ +/** \name Edit Mesh Partial Updates + * \{ */ + +static void *editmesh_partial_update_begin_fn(struct bContext *UNUSED(C), + const struct uiBlockInteraction_Params *params, + void *arg1) +{ + const int retval_test = B_TRANSFORM_PANEL_MEDIAN; + if (BLI_array_findindex( + params->unique_retval_ids, params->unique_retval_ids_len, &retval_test) == -1) { + return NULL; + } + + BMEditMesh *em = arg1; + + int verts_mask_count = 0; + BMIter iter; + BMVert *eve; + int i; + + BLI_bitmap *verts_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__); + BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) { + if (!BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + continue; + } + BLI_BITMAP_ENABLE(verts_mask, i); + verts_mask_count += 1; + } + + BMPartialUpdate *bmpinfo = BM_mesh_partial_create_from_verts_group_single( + em->bm, + &(BMPartialUpdate_Params){ + .do_tessellate = true, + .do_normals = true, + }, + verts_mask, + verts_mask_count); + + MEM_freeN(verts_mask); + + return bmpinfo; +} + +static void editmesh_partial_update_end_fn(struct bContext *UNUSED(C), + const struct uiBlockInteraction_Params *UNUSED(params), + void *UNUSED(arg1), + void *user_data) +{ + BMPartialUpdate *bmpinfo = user_data; + if (bmpinfo == NULL) { + return; + } + BM_mesh_partial_destroy(bmpinfo); +} + +static void editmesh_partial_update_update_fn( + struct bContext *C, + const struct uiBlockInteraction_Params *UNUSED(params), + void *arg1, + void *user_data) +{ + BMPartialUpdate *bmpinfo = user_data; + if (bmpinfo == NULL) { + return; + } + + View3D *v3d = CTX_wm_view3d(C); + TransformProperties *tfp = v3d_transform_props_ensure(v3d); + if (tfp->tag_for_update == false) { + return; + } + tfp->tag_for_update = false; + + BMEditMesh *em = arg1; + + BKE_editmesh_looptri_and_normals_calc_with_partial(em, bmpinfo); +} + +/** \} */ + /* Helper function to compute a median changed value, * when the value should be clamped in [0.0, 1.0]. * Returns either 0.0, 1.0 (both can be applied directly), a positive scale factor @@ -840,6 +926,20 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } UI_block_align_end(block); + + if (ob->type == OB_MESH) { + Mesh *me = ob->data; + BMEditMesh *em = me->edit_mesh; + if (em != NULL) { + UI_block_interaction_set(block, + &(uiBlockInteraction_CallbackData){ + .begin_fn = editmesh_partial_update_begin_fn, + .end_fn = editmesh_partial_update_end_fn, + .update_fn = editmesh_partial_update_update_fn, + .arg1 = em, + }); + } + } } else { /* apply */ memcpy(&ve_median_basis, &tfp->ve_median, sizeof(tfp->ve_median)); @@ -927,9 +1027,8 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } if (apply_vcos) { - /* TODO: use the #BKE_editmesh_looptri_and_normals_calc_with_partial - * This requires begin/end states for UI interaction (which currently aren't supported). */ - BKE_editmesh_looptri_and_normals_calc(em); + /* Tell the update callback to run. */ + tfp->tag_for_update = true; } /* Edges */ @@ -1152,7 +1251,7 @@ static void do_view3d_vgroup_buttons(bContext *C, void *UNUSED(arg), int event) ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob = view_layer->basact->object; ED_vgroup_vert_active_mirror(ob, event - B_VGRP_PNL_EDIT_SINGLE); - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(ob->data, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); } @@ -1466,7 +1565,7 @@ static void v3d_posearmature_buts(uiLayout *layout, Object *ob) /* XXX: RNA buts show data in native types (i.e. quats, 4-component axis/angle, etc.) * but old-school UI shows in eulers always. Do we want to be able to still display in Eulers? - * Maybe needs RNA/ui options to display rotations as different types... */ + * Maybe needs RNA/UI options to display rotations as different types. */ v3d_transform_butsR(col, &pchanptr); } @@ -1570,7 +1669,7 @@ static void do_view3d_region_buttons(bContext *C, void *UNUSED(index), int event case B_TRANSFORM_PANEL_MEDIAN: if (ob) { v3d_editvertex_buts(NULL, v3d, ob, 1.0); - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + DEG_id_tag_update(ob->data, ID_RECALC_GEOMETRY); } break; case B_TRANSFORM_PANEL_DIMS: diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index ea9d9a8c010..c97ba7ba7e9 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1404,7 +1404,7 @@ static void draw_selected_name( /* color depends on whether there is a keyframe */ if (id_frame_has_keyframe( - (ID *)ob, /* BKE_scene_frame_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL)) { + (ID *)ob, /* BKE_scene_ctime_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL)) { UI_FontThemeColor(font_id, TH_TIME_KEYFRAME); } else if (ED_gpencil_has_keyframe_v3d(scene, ob, cfra)) { diff --git a/source/blender/editors/space_view3d/view3d_navigate_fly.c b/source/blender/editors/space_view3d/view3d_navigate_fly.c index e2fa0fdc6a5..5752837c40f 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_fly.c +++ b/source/blender/editors/space_view3d/view3d_navigate_fly.c @@ -122,7 +122,7 @@ void fly_modal_keymap(wmKeyConfig *keyconf) {FLY_MODAL_DECELERATE, "DECELERATE", 0, "Decelerate", ""}, {FLY_MODAL_AXIS_LOCK_X, "AXIS_LOCK_X", 0, "X Axis Correction", "X axis correction (toggle)"}, - {FLY_MODAL_AXIS_LOCK_Z, "AXIS_LOCK_Z", 0, "X Axis Correction", "Z axis correction (toggle)"}, + {FLY_MODAL_AXIS_LOCK_Z, "AXIS_LOCK_Z", 0, "Z Axis Correction", "Z axis correction (toggle)"}, {FLY_MODAL_PRECISION_ENABLE, "PRECISION_ENABLE", 0, "Precision", ""}, {FLY_MODAL_PRECISION_DISABLE, "PRECISION_DISABLE", 0, "Precision (Off)", ""}, diff --git a/source/blender/editors/space_view3d/view3d_navigate_walk.c b/source/blender/editors/space_view3d/view3d_navigate_walk.c index 435d74aa591..09936b41a74 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_walk.c +++ b/source/blender/editors/space_view3d/view3d_navigate_walk.c @@ -98,9 +98,10 @@ enum { WALK_MODAL_JUMP, WALK_MODAL_JUMP_STOP, WALK_MODAL_TELEPORT, - WALK_MODAL_TOGGLE, + WALK_MODAL_GRAVITY_TOGGLE, WALK_MODAL_ACCELERATE, WALK_MODAL_DECELERATE, + WALK_MODAL_AXIS_LOCK_Z, }; enum { @@ -129,6 +130,18 @@ typedef enum eWalkGravityState { WALK_GRAVITY_STATE_ON, } eWalkGravityState; +/* Relative view axis z axis locking. */ +typedef enum eWalkLockState { + /* Disabled. */ + WALK_AXISLOCK_STATE_OFF = 0, + + /* Moving. */ + WALK_AXISLOCK_STATE_ACTIVE = 2, + + /* Done moving, it cannot be activated again. */ + WALK_AXISLOCK_STATE_DONE = 3, +} eWalkLockState; + /* Called in transform_ops.c, on each regeneration of key-maps. */ void walk_modal_keymap(wmKeyConfig *keyconf) { @@ -164,7 +177,9 @@ void walk_modal_keymap(wmKeyConfig *keyconf) {WALK_MODAL_JUMP, "JUMP", 0, "Jump", "Jump when in walk mode"}, {WALK_MODAL_JUMP_STOP, "JUMP_STOP", 0, "Jump (Off)", "Stop pushing jump"}, - {WALK_MODAL_TOGGLE, "GRAVITY_TOGGLE", 0, "Toggle Gravity", "Toggle gravity effect"}, + {WALK_MODAL_GRAVITY_TOGGLE, "GRAVITY_TOGGLE", 0, "Toggle Gravity", "Toggle gravity effect"}, + + {WALK_MODAL_AXIS_LOCK_Z, "AXIS_LOCK_Z", 0, "Z Axis Correction", "Z axis correction"}, {0, NULL, 0, NULL, NULL}, }; @@ -292,6 +307,10 @@ typedef struct WalkInfo { /** To use for fast/slow speeds. */ float speed_factor; + eWalkLockState zlock; + /** Nicer dynamics. */ + float zlock_momentum; + struct SnapObjectContext *snap_context; struct View3DCameraControl *v3d_camera_control; @@ -540,6 +559,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) walk->jump_height = U.walk_navigation.jump_height; walk->speed = U.walk_navigation.walk_speed; walk->speed_factor = U.walk_navigation.walk_speed_factor; + walk->zlock = WALK_AXISLOCK_STATE_OFF; walk->gravity_state = WALK_GRAVITY_STATE_OFF; @@ -708,8 +728,6 @@ static void walkEvent(bContext *C, WalkInfo *walk, const wmEvent *event) walk->is_cursor_absolute = true; copy_v2_v2_int(walk->prev_mval, event->mval); copy_v2_v2_int(walk->center_mval, event->mval); - /* Without this we can't turn 180d with the default speed of 1.0. */ - walk->mouse_speed *= 4.0f; } #endif /* USE_TABLET_SUPPORT */ @@ -941,7 +959,7 @@ static void walkEvent(bContext *C, WalkInfo *walk, const wmEvent *event) #undef JUMP_TIME_MAX #undef JUMP_SPEED_MIN - case WALK_MODAL_TOGGLE: + case WALK_MODAL_GRAVITY_TOGGLE: if (walk->navigation_mode == WALK_MODE_GRAVITY) { walk_navigation_mode_set(walk, WALK_MODE_FREE); } @@ -949,6 +967,13 @@ static void walkEvent(bContext *C, WalkInfo *walk, const wmEvent *event) walk_navigation_mode_set(walk, WALK_MODE_GRAVITY); } break; + + case WALK_MODAL_AXIS_LOCK_Z: + if (walk->zlock != WALK_AXISLOCK_STATE_DONE) { + walk->zlock = WALK_AXISLOCK_STATE_ACTIVE; + walk->zlock_momentum = 0.0f; + } + break; } } } @@ -982,12 +1007,14 @@ static float getVelocityZeroTime(const float gravity, const float velocity) static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) { -#define WALK_ROTATE_RELATIVE_FAC 2.2f /* More is faster, relative to region size. */ -#define WALK_ROTATE_CONSTANT_FAC DEG2RAD(0.15f) /* More is faster, radians per-pixel. */ +#define WALK_ROTATE_TABLET_FAC 8.8f /* Higher is faster, relative to region size. */ +#define WALK_ROTATE_CONSTANT_FAC DEG2RAD(0.15f) /* Higher is faster, radians per-pixel. */ #define WALK_TOP_LIMIT DEG2RADF(85.0f) #define WALK_BOTTOM_LIMIT DEG2RADF(-80.0f) #define WALK_MOVE_SPEED base_speed #define WALK_BOOST_FACTOR ((void)0, walk->speed_factor) +#define WALK_ZUP_CORRECT_FAC 0.1f /* Amount to correct per step. */ +#define WALK_ZUP_CORRECT_ACCEL 0.05f /* Increase upright momentum each step. */ RegionView3D *rv3d = walk->rv3d; ARegion *region = walk->region; @@ -1022,20 +1049,25 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) /* Should we redraw? */ if ((walk->active_directions) || moffset[0] || moffset[1] || - walk->teleport.state == WALK_TELEPORT_STATE_ON || - walk->gravity_state != WALK_GRAVITY_STATE_OFF || is_confirm) { + walk->zlock == WALK_AXISLOCK_STATE_ACTIVE || + walk->gravity_state != WALK_GRAVITY_STATE_OFF || + walk->teleport.state == WALK_TELEPORT_STATE_ON || is_confirm) { float dvec_tmp[3]; /* time how fast it takes for us to redraw, * this is so simple scenes don't walk too fast */ double time_current; float time_redraw; + float time_redraw_clamped; #ifdef NDOF_WALK_DRAW_TOOMUCH walk->redraw = 1; #endif time_current = PIL_check_seconds_timer(); time_redraw = (float)(time_current - walk->time_lastdraw); + /* Clamp redraw time to avoid jitter in roll correction. */ + time_redraw_clamped = min_ff(0.05f, time_redraw); + walk->time_lastdraw = time_current; /* base speed in m/s */ @@ -1064,7 +1096,7 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) #ifdef USE_TABLET_SUPPORT if (walk->is_cursor_absolute) { y /= region->winy; - y *= WALK_ROTATE_RELATIVE_FAC; + y *= WALK_ROTATE_TABLET_FAC; } else #endif @@ -1113,7 +1145,7 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) #ifdef USE_TABLET_SUPPORT if (walk->is_cursor_absolute) { x /= region->winx; - x *= WALK_ROTATE_RELATIVE_FAC; + x *= WALK_ROTATE_TABLET_FAC; } else #endif @@ -1128,6 +1160,32 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) axis_angle_to_quat_single(tmp_quat, 'Z', x); mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); } + + if (walk->zlock == WALK_AXISLOCK_STATE_ACTIVE) { + float upvec[3]; + copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f); + mul_m3_v3(mat, upvec); + + /* Make sure we have some z rolling. */ + if (fabsf(upvec[2]) > 0.00001f) { + float roll = upvec[2] * 5.0f; + /* Rotate the view about this axis. */ + copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f); + mul_m3_v3(mat, upvec); + /* Rotate about the relative up vec. */ + axis_angle_to_quat(tmp_quat, + upvec, + roll * time_redraw_clamped * walk->zlock_momentum * + WALK_ZUP_CORRECT_FAC); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); + + walk->zlock_momentum += WALK_ZUP_CORRECT_ACCEL; + } + else { + /* Lock fixed, don't need to check it ever again. */ + walk->zlock = WALK_AXISLOCK_STATE_DONE; + } + } } /* WASD - 'move' translation code */ @@ -1318,7 +1376,8 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) add_v3_v3(rv3d->ofs, dvec_tmp); if (rv3d->persp == RV3D_CAMOB) { - walk->need_rotation_keyframe |= (moffset[0] || moffset[1]); + walk->need_rotation_keyframe |= (moffset[0] || moffset[1] || + walk->zlock == WALK_AXISLOCK_STATE_ACTIVE); walk->need_translation_keyframe |= (len_squared_v3(dvec_tmp) > FLT_EPSILON); walkMoveCamera( C, walk, walk->need_rotation_keyframe, walk->need_translation_keyframe, is_confirm); @@ -1333,7 +1392,7 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) } return OPERATOR_FINISHED; -#undef WALK_ROTATE_RELATIVE_FAC +#undef WALK_ROTATE_TABLET_FAC #undef WALK_TOP_LIMIT #undef WALK_BOTTOM_LIMIT #undef WALK_MOVE_SPEED diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index a19e92f229a..4482e5897ca 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -511,47 +511,47 @@ static int snap_selected_to_location(bContext *C, for (int ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; + if (ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) { + continue; + } - if ((ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) == 0) { - - float cursor_parent[3]; /* parent-relative */ - - if (use_offset) { - add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global); - } - else { - copy_v3_v3(cursor_parent, snap_target_global); - } + float cursor_parent[3]; /* parent-relative */ - sub_v3_v3(cursor_parent, ob->obmat[3]); + if (use_offset) { + add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global); + } + else { + copy_v3_v3(cursor_parent, snap_target_global); + } - if (ob->parent) { - float originmat[3][3], parentmat[4][4]; - /* Use the evaluated object here because sometimes - * `ob->parent->runtime.curve_cache` is required. */ - BKE_scene_graph_evaluated_ensure(depsgraph, bmain); - Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + sub_v3_v3(cursor_parent, ob->obmat[3]); - BKE_object_get_parent_matrix(ob_eval, ob_eval->parent, parentmat); - mul_m3_m4m4(originmat, parentmat, ob->parentinv); - invert_m3_m3(imat, originmat); - mul_m3_v3(imat, cursor_parent); - } - if ((ob->protectflag & OB_LOCK_LOCX) == 0) { - ob->loc[0] += cursor_parent[0]; - } - if ((ob->protectflag & OB_LOCK_LOCY) == 0) { - ob->loc[1] += cursor_parent[1]; - } - if ((ob->protectflag & OB_LOCK_LOCZ) == 0) { - ob->loc[2] += cursor_parent[2]; - } + if (ob->parent) { + float originmat[3][3], parentmat[4][4]; + /* Use the evaluated object here because sometimes + * `ob->parent->runtime.curve_cache` is required. */ + BKE_scene_graph_evaluated_ensure(depsgraph, bmain); + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + + BKE_object_get_parent_matrix(ob_eval, ob_eval->parent, parentmat); + mul_m3_m4m4(originmat, parentmat, ob->parentinv); + invert_m3_m3(imat, originmat); + mul_m3_v3(imat, cursor_parent); + } + if ((ob->protectflag & OB_LOCK_LOCX) == 0) { + ob->loc[0] += cursor_parent[0]; + } + if ((ob->protectflag & OB_LOCK_LOCY) == 0) { + ob->loc[1] += cursor_parent[1]; + } + if ((ob->protectflag & OB_LOCK_LOCZ) == 0) { + ob->loc[2] += cursor_parent[2]; + } - /* auto-keyframing */ - ED_autokeyframe_object(C, scene, ob, ks); + /* auto-keyframing */ + ED_autokeyframe_object(C, scene, ob, ks); - DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); - } + DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); } if (objects) { |