Fix #106993: Slowness with Orbiting around select + Mesh Symmetry #107203
@ -151,6 +151,10 @@ short ED_transform_calc_orientation_from_type_ex(const struct Scene *scene,
|
||||
int pivot_point,
|
||||
float r_mat[3][3]);
|
||||
|
||||
bool ED_transform_calc_pivot_pos(const struct bContext *C,
|
||||
const short pivot_type,
|
||||
float r_pivot_pos[3]);
|
||||
|
||||
/* transform gizmos */
|
||||
|
||||
void VIEW3D_GGT_xform_gizmo(struct wmGizmoGroupType *gzgt);
|
||||
@ -201,7 +205,8 @@ struct TransformCalcParams {
|
||||
*/
|
||||
int ED_transform_calc_gizmo_stats(const struct bContext *C,
|
||||
const struct TransformCalcParams *params,
|
||||
struct TransformBounds *tbounds);
|
||||
struct TransformBounds *tbounds,
|
||||
struct RegionView3D *rv3d);
|
||||
|
||||
/**
|
||||
* Iterates over all the strips and finds the closest snapping candidate of either \a frame_1 or \a
|
||||
|
@ -138,13 +138,15 @@ static void WIDGETGROUP_tool_generic_refresh(const bContext *C, wmGizmoGroup *gz
|
||||
orientation = V3D_ORIENT_GLOBAL; /* dummy, use view. */
|
||||
}
|
||||
|
||||
RegionView3D *rv3d = CTX_wm_region_data(C);
|
||||
struct TransformBounds tbounds;
|
||||
const bool hide = ED_transform_calc_gizmo_stats(C,
|
||||
&(struct TransformCalcParams){
|
||||
.use_only_center = true,
|
||||
.orientation_index = orientation + 1,
|
||||
},
|
||||
&tbounds) == 0;
|
||||
&tbounds,
|
||||
rv3d) == 0;
|
||||
|
||||
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, hide);
|
||||
if (hide) {
|
||||
|
@ -304,7 +304,7 @@ bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
|
||||
}
|
||||
else {
|
||||
/* If there's no selection, `lastofs` is unmodified and last value since static. */
|
||||
is_set = calculateTransformCenter(C, V3D_AROUND_CENTER_MEDIAN, lastofs, nullptr);
|
||||
is_set = ED_transform_calc_pivot_pos(C, V3D_AROUND_CENTER_MEDIAN, lastofs);
|
||||
}
|
||||
|
||||
copy_v3_v3(r_dyn_ofs, lastofs);
|
||||
|
@ -438,19 +438,6 @@ static void calc_tw_center(TransformBounds *tbounds, const float co[3])
|
||||
}
|
||||
}
|
||||
|
||||
static void calc_tw_center_with_matrix(TransformBounds *tbounds,
|
||||
const float co[3],
|
||||
const bool use_matrix,
|
||||
const float matrix[4][4])
|
||||
{
|
||||
float co_world[3];
|
||||
if (use_matrix) {
|
||||
mul_v3_m4v3(co_world, matrix, co);
|
||||
co = co_world;
|
||||
}
|
||||
calc_tw_center(tbounds, co);
|
||||
}
|
||||
|
||||
static void protectflag_to_drawflags(short protectflag, short *drawflags)
|
||||
{
|
||||
if (protectflag & OB_LOCK_LOCX) {
|
||||
@ -484,51 +471,56 @@ static void protectflag_to_drawflags(short protectflag, short *drawflags)
|
||||
}
|
||||
}
|
||||
|
||||
/* for pose mode */
|
||||
static void protectflag_to_drawflags_pchan(RegionView3D *rv3d,
|
||||
const bPoseChannel *pchan,
|
||||
short orientation_index)
|
||||
{
|
||||
/* Protect-flags apply to local space in pose mode, so only let them influence axis
|
||||
* visibility if we show the global orientation, otherwise it's confusing. */
|
||||
if (ELEM(orientation_index, V3D_ORIENT_LOCAL, V3D_ORIENT_GIMBAL)) {
|
||||
protectflag_to_drawflags(pchan->protectflag, &rv3d->twdrawflag);
|
||||
}
|
||||
}
|
||||
|
||||
/* For editmode. */
|
||||
static void protectflag_to_drawflags_ebone(RegionView3D *rv3d, const EditBone *ebo)
|
||||
{
|
||||
if (ebo->flag & BONE_EDITMODE_LOCKED) {
|
||||
protectflag_to_drawflags(OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE, &rv3d->twdrawflag);
|
||||
}
|
||||
}
|
||||
|
||||
int ED_transform_calc_gizmo_stats(const bContext *C,
|
||||
const TransformCalcParams *params,
|
||||
TransformBounds *tbounds)
|
||||
/**
|
||||
|
||||
* Run \a user_fn for each coordinate of elements selected in View3D (vertices, particles...).
|
||||
* \note Each coordinate has the space matrix of the active object.
|
||||
*
|
||||
* \param orient_index: A #TransformOrientationSlot.type. Here used for calculating \a r_drawflags.
|
||||
Campbell Barton
commented
Pass Pass `r_` prefixed arguments last.
|
||||
* \param use_curve_handles: If true, the handles of curves are traversed.
|
||||
* \param use_only_center: For objects in object mode, defines whether the corners of the bounds or
|
||||
Campbell Barton
commented
By convention, the By convention, the `data` pointer is typically the after the callback that uses it (although this kind of thing might be worth documenting).
|
||||
* just the center are traversed.
|
||||
* \param user_fn: Callback that runs on each coordinate.
|
||||
* \param user_data: User argument passed to \a user_fn.
|
||||
* \param r_mat: Returns the space matrix of the coordinates.
|
||||
* \param r_drawflags: Drawing flags for gizmos. Usually stored in #RegionView3D::drawflags.
|
||||
Campbell Barton
commented
This name doesn't seem correct anymore, This name doesn't seem correct anymore, `calc_tw_center_with_matrix` is simply calling `callback` which might calculate anything.
|
||||
*/
|
||||
static int gizmo_3d_foreach_selected(const bContext *C,
|
||||
const short orient_index,
|
||||
mano-wii marked this conversation as resolved
Outdated
Campbell Barton
commented
Prefer the term Prefer the term `user_data`, as it's clearer the data is caller-defined (`data` is vague).
|
||||
const bool use_curve_handles,
|
||||
const bool use_only_center,
|
||||
void (*user_fn)(const float[3], void *),
|
||||
void *user_data,
|
||||
const float (**r_mat)[4],
|
||||
short *r_drawflags)
|
||||
{
|
||||
using namespace blender;
|
||||
|
||||
const auto run_coord_with_matrix = [](const float co[3],
|
||||
const bool use_matrix,
|
||||
const float matrix[4][4],
|
||||
void (*user_fn)(const float[3], void *),
|
||||
void *user_data) {
|
||||
float co_world[3];
|
||||
if (use_matrix) {
|
||||
mul_v3_m4v3(co_world, matrix, co);
|
||||
co = co_world;
|
||||
}
|
||||
user_fn(co, user_data);
|
||||
};
|
||||
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
/* TODO(sergey): This function is used from operator's modal() and from gizmo's refresh().
|
||||
* Is it fine to possibly evaluate dependency graph here? */
|
||||
Depsgraph *depsgraph = CTX_data_expect_evaluated_depsgraph(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
View3D *v3d = static_cast<View3D *>(area->spacedata.first);
|
||||
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
|
||||
Base *base;
|
||||
bGPdata *gpd = CTX_data_gpencil_data(C);
|
||||
const bool is_gp_edit = GPENCIL_ANY_MODE(gpd);
|
||||
const bool is_curve_edit = GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd);
|
||||
int a, totsel = 0;
|
||||
|
||||
const int pivot_point = scene->toolsettings->transform_pivot_point;
|
||||
const short orient_index = params->orientation_index ?
|
||||
(params->orientation_index - 1) :
|
||||
BKE_scene_orientation_get_index(scene, SCE_ORIENT_DEFAULT);
|
||||
|
||||
BKE_view_layer_synced_ensure(scene, view_layer);
|
||||
Object *ob = BKE_view_layer_active_object_get(view_layer);
|
||||
Object *obedit = OBEDIT_FROM_OBACT(ob);
|
||||
@ -539,42 +531,6 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
|
||||
}
|
||||
}
|
||||
|
||||
tbounds->use_matrix_space = false;
|
||||
|
||||
/* transform widget matrix */
|
||||
unit_m4(rv3d->twmat);
|
||||
|
||||
unit_m3(rv3d->tw_axis_matrix);
|
||||
zero_v3(rv3d->tw_axis_min);
|
||||
zero_v3(rv3d->tw_axis_max);
|
||||
|
||||
rv3d->twdrawflag = short(0xFFFF);
|
||||
|
||||
/* global, local or normal orientation?
|
||||
* if we could check 'totsel' now, this should be skipped with no selection. */
|
||||
if (ob) {
|
||||
float mat[3][3];
|
||||
ED_transform_calc_orientation_from_type_ex(
|
||||
scene, view_layer, v3d, rv3d, ob, obedit, orient_index, pivot_point, mat);
|
||||
copy_m4_m3(rv3d->twmat, mat);
|
||||
}
|
||||
|
||||
/* transform widget centroid/center */
|
||||
reset_tw_center(tbounds);
|
||||
|
||||
copy_m3_m4(tbounds->axis, rv3d->twmat);
|
||||
if (params->use_local_axis && (ob && ob->mode & (OB_MODE_EDIT | OB_MODE_POSE))) {
|
||||
float diff_mat[3][3];
|
||||
copy_m3_m4(diff_mat, ob->object_to_world);
|
||||
normalize_m3(diff_mat);
|
||||
invert_m3(diff_mat);
|
||||
mul_m3_m3m3(tbounds->axis, tbounds->axis, diff_mat);
|
||||
normalize_m3(tbounds->axis);
|
||||
|
||||
tbounds->use_matrix_space = true;
|
||||
copy_m4_m4(tbounds->matrix_space, ob->object_to_world);
|
||||
}
|
||||
|
||||
if (is_gp_edit) {
|
||||
float diff_mat[4][4];
|
||||
const bool use_mat_local = true;
|
||||
@ -605,7 +561,8 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
|
||||
if (gpc_pt->flag & GP_CURVE_POINT_SELECT) {
|
||||
for (uint32_t j = 0; j < 3; j++) {
|
||||
if (BEZT_ISSEL_IDX(bezt, j)) {
|
||||
calc_tw_center_with_matrix(tbounds, bezt->vec[j], use_mat_local, diff_mat);
|
||||
run_coord_with_matrix(
|
||||
bezt->vec[j], use_mat_local, diff_mat, user_fn, user_data);
|
||||
totsel++;
|
||||
}
|
||||
}
|
||||
@ -622,7 +579,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
|
||||
/* Change selection status of all points, then make the stroke match */
|
||||
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
|
||||
if (pt->flag & GP_SPOINT_SELECT) {
|
||||
calc_tw_center_with_matrix(tbounds, &pt->x, use_mat_local, diff_mat);
|
||||
run_coord_with_matrix(&pt->x, use_mat_local, diff_mat, user_fn, user_data);
|
||||
totsel++;
|
||||
}
|
||||
}
|
||||
@ -631,11 +588,6 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* selection center */
|
||||
if (totsel) {
|
||||
mul_v3_fl(tbounds->center, 1.0f / float(totsel)); /* centroid! */
|
||||
}
|
||||
}
|
||||
else if (obedit) {
|
||||
|
||||
@ -676,7 +628,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
|
||||
BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
|
||||
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
|
||||
if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
|
||||
calc_tw_center_with_matrix(tbounds, eve->co, use_mat_local, mat_local);
|
||||
run_coord_with_matrix(eve->co, use_mat_local, mat_local, user_fn, user_data);
|
||||
totsel++;
|
||||
}
|
||||
}
|
||||
@ -695,18 +647,24 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
|
||||
LISTBASE_FOREACH (EditBone *, ebo, arm->edbo) {
|
||||
if (EBONE_VISIBLE(arm, ebo)) {
|
||||
if (ebo->flag & BONE_TIPSEL) {
|
||||
calc_tw_center_with_matrix(tbounds, ebo->tail, use_mat_local, mat_local);
|
||||
run_coord_with_matrix(ebo->tail, use_mat_local, mat_local, user_fn, user_data);
|
||||
totsel++;
|
||||
}
|
||||
if ((ebo->flag & BONE_ROOTSEL) &&
|
||||
/* don't include same point multiple times */
|
||||
((ebo->flag & BONE_CONNECTED) && (ebo->parent != nullptr) &&
|
||||
(ebo->parent->flag & BONE_TIPSEL) && EBONE_VISIBLE(arm, ebo->parent)) == 0) {
|
||||
calc_tw_center_with_matrix(tbounds, ebo->head, use_mat_local, mat_local);
|
||||
run_coord_with_matrix(ebo->head, use_mat_local, mat_local, user_fn, user_data);
|
||||
totsel++;
|
||||
}
|
||||
|
||||
if (r_drawflags) {
|
||||
if (ebo->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) {
|
||||
protectflag_to_drawflags_ebone(rv3d, ebo);
|
||||
if (ebo->flag & BONE_EDITMODE_LOCKED) {
|
||||
protectflag_to_drawflags(OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE,
|
||||
r_drawflags);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -737,23 +695,24 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
|
||||
*/
|
||||
if (v3d->overlay.handle_display == CURVE_HANDLE_NONE) {
|
||||
if (bezt->f2 & SELECT) {
|
||||
calc_tw_center_with_matrix(tbounds, bezt->vec[1], use_mat_local, mat_local);
|
||||
run_coord_with_matrix(
|
||||
bezt->vec[1], use_mat_local, mat_local, user_fn, user_data);
|
||||
totsel++;
|
||||
}
|
||||
}
|
||||
else if (bezt->f2 & SELECT) {
|
||||
calc_tw_center_with_matrix(tbounds, bezt->vec[1], use_mat_local, mat_local);
|
||||
run_coord_with_matrix(bezt->vec[1], use_mat_local, mat_local, user_fn, user_data);
|
||||
totsel++;
|
||||
}
|
||||
else {
|
||||
if (bezt->f1 & SELECT) {
|
||||
const float *co = bezt->vec[(pivot_point == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 0];
|
||||
calc_tw_center_with_matrix(tbounds, co, use_mat_local, mat_local);
|
||||
const float *co = bezt->vec[!use_curve_handles ? 1 : 0];
|
||||
run_coord_with_matrix(co, use_mat_local, mat_local, user_fn, user_data);
|
||||
totsel++;
|
||||
}
|
||||
if (bezt->f3 & SELECT) {
|
||||
const float *co = bezt->vec[(pivot_point == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 2];
|
||||
calc_tw_center_with_matrix(tbounds, co, use_mat_local, mat_local);
|
||||
const float *co = bezt->vec[!use_curve_handles ? 1 : 2];
|
||||
run_coord_with_matrix(co, use_mat_local, mat_local, user_fn, user_data);
|
||||
totsel++;
|
||||
}
|
||||
}
|
||||
@ -765,7 +724,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
|
||||
a = nu->pntsu * nu->pntsv;
|
||||
while (a--) {
|
||||
if (bp->f1 & SELECT) {
|
||||
calc_tw_center_with_matrix(tbounds, bp->vec, use_mat_local, mat_local);
|
||||
run_coord_with_matrix(bp->vec, use_mat_local, mat_local, user_fn, user_data);
|
||||
totsel++;
|
||||
}
|
||||
bp++;
|
||||
@ -787,7 +746,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
|
||||
|
||||
LISTBASE_FOREACH (MetaElem *, ml, mb->editelems) {
|
||||
if (ml->flag & SELECT) {
|
||||
calc_tw_center_with_matrix(tbounds, &ml->x, use_mat_local, mat_local);
|
||||
run_coord_with_matrix(&ml->x, use_mat_local, mat_local, user_fn, user_data);
|
||||
totsel++;
|
||||
}
|
||||
}
|
||||
@ -807,7 +766,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
|
||||
|
||||
while (a--) {
|
||||
if (bp->f1 & SELECT) {
|
||||
calc_tw_center_with_matrix(tbounds, bp->vec, use_mat_local, mat_local);
|
||||
run_coord_with_matrix(bp->vec, use_mat_local, mat_local, user_fn, user_data);
|
||||
totsel++;
|
||||
}
|
||||
bp++;
|
||||
@ -832,7 +791,8 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
|
||||
const Span<float3> positions = deformation.positions;
|
||||
totsel += selected_points.size();
|
||||
for (const int point_i : selected_points) {
|
||||
calc_tw_center_with_matrix(tbounds, positions[point_i], use_mat_local, mat_local.ptr());
|
||||
run_coord_with_matrix(
|
||||
positions[point_i], use_mat_local, mat_local.ptr(), user_fn, user_data);
|
||||
}
|
||||
}
|
||||
FOREACH_EDIT_OBJECT_END();
|
||||
@ -840,14 +800,6 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
|
||||
|
||||
#undef FOREACH_EDIT_OBJECT_BEGIN
|
||||
#undef FOREACH_EDIT_OBJECT_END
|
||||
|
||||
/* selection center */
|
||||
if (totsel) {
|
||||
mul_v3_fl(tbounds->center, 1.0f / float(totsel)); /* centroid! */
|
||||
mul_m4_v3(obedit->object_to_world, tbounds->center);
|
||||
mul_m4_v3(obedit->object_to_world, tbounds->min);
|
||||
mul_m4_v3(obedit->object_to_world, tbounds->max);
|
||||
}
|
||||
}
|
||||
else if (ob && (ob->mode & OB_MODE_POSE)) {
|
||||
invert_m4_m4(ob->world_to_object, ob->object_to_world);
|
||||
@ -873,27 +825,24 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
|
||||
if (!(pchan->bone->flag & BONE_TRANSFORM)) {
|
||||
continue;
|
||||
}
|
||||
calc_tw_center_with_matrix(tbounds, pchan->pose_head, use_mat_local, mat_local);
|
||||
protectflag_to_drawflags_pchan(rv3d, pchan, orient_index);
|
||||
run_coord_with_matrix(pchan->pose_head, use_mat_local, mat_local, user_fn, user_data);
|
||||
totsel++;
|
||||
|
||||
if (r_drawflags) {
|
||||
/* Protect-flags apply to local space in pose mode, so only let them influence axis
|
||||
* visibility if we show the global orientation, otherwise it's confusing. */
|
||||
if (ELEM(orient_index, V3D_ORIENT_LOCAL, V3D_ORIENT_GIMBAL)) {
|
||||
protectflag_to_drawflags(pchan->protectflag, r_drawflags);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
MEM_freeN(objects);
|
||||
|
||||
if (totsel) {
|
||||
mul_v3_fl(tbounds->center, 1.0f / float(totsel)); /* centroid! */
|
||||
mul_m4_v3(ob->object_to_world, tbounds->center);
|
||||
mul_m4_v3(ob->object_to_world, tbounds->min);
|
||||
mul_m4_v3(ob->object_to_world, tbounds->max);
|
||||
}
|
||||
}
|
||||
else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) {
|
||||
if (ob->mode & OB_MODE_SCULPT) {
|
||||
totsel = 1;
|
||||
calc_tw_center_with_matrix(tbounds, ob->sculpt->pivot_pos, false, ob->object_to_world);
|
||||
mul_m4_v3(ob->object_to_world, tbounds->center);
|
||||
mul_m4_v3(ob->object_to_world, tbounds->min);
|
||||
mul_m4_v3(ob->object_to_world, tbounds->max);
|
||||
run_coord_with_matrix(ob->sculpt->pivot_pos, false, ob->object_to_world, user_fn, user_data);
|
||||
}
|
||||
}
|
||||
else if (ob && ob->mode & OB_MODE_PARTICLE_EDIT) {
|
||||
@ -911,16 +860,11 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
|
||||
|
||||
for (k = 0, ek = point->keys; k < point->totkey; k++, ek++) {
|
||||
if (ek->flag & PEK_SELECT) {
|
||||
calc_tw_center(tbounds, (ek->flag & PEK_USE_WCO) ? ek->world_co : ek->co);
|
||||
user_fn((ek->flag & PEK_USE_WCO) ? ek->world_co : ek->co, user_data);
|
||||
totsel++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* selection center */
|
||||
if (totsel) {
|
||||
mul_v3_fl(tbounds->center, 1.0f / float(totsel)); /* centroid! */
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -944,46 +888,141 @@ int ED_transform_calc_gizmo_stats(const bContext *C,
|
||||
|
||||
/* Get the boundbox out of the evaluated object. */
|
||||
const BoundBox *bb = nullptr;
|
||||
if (params->use_only_center == false) {
|
||||
if (use_only_center == false) {
|
||||
bb = BKE_object_boundbox_get(base->object);
|
||||
}
|
||||
|
||||
if (params->use_only_center || (bb == nullptr)) {
|
||||
calc_tw_center(tbounds, base->object->object_to_world[3]);
|
||||
if (use_only_center || (bb == nullptr)) {
|
||||
user_fn(base->object->object_to_world[3], user_data);
|
||||
}
|
||||
else {
|
||||
for (uint j = 0; j < 8; j++) {
|
||||
float co[3];
|
||||
mul_v3_m4v3(co, base->object->object_to_world, bb->vec[j]);
|
||||
calc_tw_center(tbounds, co);
|
||||
user_fn(co, user_data);
|
||||
}
|
||||
}
|
||||
|
||||
totsel++;
|
||||
if (r_drawflags) {
|
||||
if (orient_index == V3D_ORIENT_GLOBAL) {
|
||||
/* Protect-flags apply to world space in object mode,
|
||||
* so only let them influence axis visibility if we show the global orientation,
|
||||
* otherwise it's confusing. */
|
||||
protectflag_to_drawflags(base->object->protectflag & OB_LOCK_LOC, &rv3d->twdrawflag);
|
||||
protectflag_to_drawflags(base->object->protectflag & OB_LOCK_LOC, r_drawflags);
|
||||
}
|
||||
else if (ELEM(orient_index, V3D_ORIENT_LOCAL, V3D_ORIENT_GIMBAL)) {
|
||||
protectflag_to_drawflags(base->object->protectflag, &rv3d->twdrawflag);
|
||||
protectflag_to_drawflags(base->object->protectflag, r_drawflags);
|
||||
}
|
||||
}
|
||||
}
|
||||
totsel++;
|
||||
}
|
||||
|
||||
/* selection center */
|
||||
if (r_mat && ob) {
|
||||
*r_mat = ob->object_to_world;
|
||||
}
|
||||
|
||||
return totsel;
|
||||
}
|
||||
|
||||
int ED_transform_calc_gizmo_stats(const bContext *C,
|
||||
const TransformCalcParams *params,
|
||||
TransformBounds *tbounds,
|
||||
RegionView3D *rv3d)
|
||||
{
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
View3D *v3d = static_cast<View3D *>(area->spacedata.first);
|
||||
int totsel = 0;
|
||||
|
||||
const int pivot_point = scene->toolsettings->transform_pivot_point;
|
||||
const short orient_index = params->orientation_index ?
|
||||
(params->orientation_index - 1) :
|
||||
BKE_scene_orientation_get_index(scene, SCE_ORIENT_DEFAULT);
|
||||
|
||||
BKE_view_layer_synced_ensure(scene, view_layer);
|
||||
Object *ob = BKE_view_layer_active_object_get(view_layer);
|
||||
Object *obedit = OBEDIT_FROM_OBACT(ob);
|
||||
if (ob && ob->mode & OB_MODE_WEIGHT_PAINT) {
|
||||
Object *obpose = BKE_object_pose_armature_get(ob);
|
||||
if (obpose != nullptr) {
|
||||
ob = obpose;
|
||||
}
|
||||
}
|
||||
|
||||
tbounds->use_matrix_space = false;
|
||||
unit_m3(tbounds->axis);
|
||||
|
||||
/* global, local or normal orientation?
|
||||
* if we could check 'totsel' now, this should be skipped with no selection. */
|
||||
if (ob) {
|
||||
float mat[3][3];
|
||||
ED_transform_calc_orientation_from_type_ex(
|
||||
scene, view_layer, v3d, rv3d, ob, obedit, orient_index, pivot_point, mat);
|
||||
copy_m3_m3(tbounds->axis, mat);
|
||||
}
|
||||
|
||||
reset_tw_center(tbounds);
|
||||
|
||||
if (rv3d) {
|
||||
/* transform widget centroid/center */
|
||||
copy_m4_m3(rv3d->twmat, tbounds->axis);
|
||||
rv3d->twdrawflag = short(0xFFFF);
|
||||
}
|
||||
|
||||
if (params->use_local_axis && (ob && ob->mode & (OB_MODE_EDIT | OB_MODE_POSE))) {
|
||||
float diff_mat[3][3];
|
||||
copy_m3_m4(diff_mat, ob->object_to_world);
|
||||
normalize_m3(diff_mat);
|
||||
invert_m3(diff_mat);
|
||||
mul_m3_m3m3(tbounds->axis, tbounds->axis, diff_mat);
|
||||
normalize_m3(tbounds->axis);
|
||||
|
||||
tbounds->use_matrix_space = true;
|
||||
copy_m4_m4(tbounds->matrix_space, ob->object_to_world);
|
||||
}
|
||||
|
||||
const auto gizmo_3d_tbounds_calc_fn = [](const float co[3], void *data) {
|
||||
TransformBounds *tbounds = static_cast<TransformBounds *>(data);
|
||||
calc_tw_center(tbounds, co);
|
||||
};
|
||||
|
||||
totsel = gizmo_3d_foreach_selected(C,
|
||||
orient_index,
|
||||
(pivot_point != V3D_AROUND_LOCAL_ORIGINS),
|
||||
params->use_only_center,
|
||||
gizmo_3d_tbounds_calc_fn,
|
||||
tbounds,
|
||||
nullptr,
|
||||
rv3d ? &rv3d->twdrawflag : nullptr);
|
||||
|
||||
if (totsel) {
|
||||
mul_v3_fl(tbounds->center, 1.0f / float(totsel)); /* centroid! */
|
||||
|
||||
bGPdata *gpd = CTX_data_gpencil_data(C);
|
||||
const bool is_gp_edit = GPENCIL_ANY_MODE(gpd);
|
||||
if (!is_gp_edit && (obedit || (ob && (ob->mode & (OB_MODE_POSE | OB_MODE_SCULPT))))) {
|
||||
if (ob && (ob->mode & OB_MODE_POSE)) {
|
||||
invert_m4_m4(ob->world_to_object, ob->object_to_world);
|
||||
}
|
||||
mul_m4_v3(ob->object_to_world, tbounds->center);
|
||||
mul_m4_v3(ob->object_to_world, tbounds->min);
|
||||
mul_m4_v3(ob->object_to_world, tbounds->max);
|
||||
}
|
||||
}
|
||||
|
||||
if (rv3d) {
|
||||
if (totsel == 0) {
|
||||
unit_m4(rv3d->twmat);
|
||||
unit_m3(rv3d->tw_axis_matrix);
|
||||
zero_v3(rv3d->tw_axis_min);
|
||||
zero_v3(rv3d->tw_axis_max);
|
||||
}
|
||||
else {
|
||||
copy_m3_m3(rv3d->tw_axis_matrix, tbounds->axis);
|
||||
copy_v3_v3(rv3d->tw_axis_min, tbounds->axis_min);
|
||||
copy_v3_v3(rv3d->tw_axis_max, tbounds->axis_max);
|
||||
copy_m3_m3(rv3d->tw_axis_matrix, tbounds->axis);
|
||||
}
|
||||
}
|
||||
|
||||
return totsel;
|
||||
@ -999,46 +1038,89 @@ static void gizmo_get_idot(const RegionView3D *rv3d, float r_idot[3])
|
||||
}
|
||||
}
|
||||
|
||||
void gizmo_prepare_mat(const bContext *C, RegionView3D *rv3d, const TransformBounds *tbounds)
|
||||
static bool gizmo_3d_calc_pos(const bContext *C,
|
||||
const Scene *scene,
|
||||
const TransformBounds *tbounds,
|
||||
const short pivot_type,
|
||||
float r_pivot_pos[3])
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
zero_v3(r_pivot_pos);
|
||||
|
||||
switch (scene->toolsettings->transform_pivot_point) {
|
||||
case V3D_AROUND_CENTER_BOUNDS:
|
||||
switch (pivot_type) {
|
||||
case V3D_AROUND_CURSOR:
|
||||
copy_v3_v3(r_pivot_pos, scene->cursor.location);
|
||||
return true;
|
||||
case V3D_AROUND_ACTIVE: {
|
||||
mid_v3_v3v3(rv3d->twmat[3], tbounds->min, tbounds->max);
|
||||
|
||||
if (scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) {
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
BKE_view_layer_synced_ensure(scene, view_layer);
|
||||
Object *ob = BKE_view_layer_active_object_get(view_layer);
|
||||
if (ob != nullptr) {
|
||||
/* Grease Pencil uses object origin. */
|
||||
bGPdata *gpd = CTX_data_gpencil_data(C);
|
||||
if (gpd && (gpd->flag & GP_DATA_STROKE_EDITMODE)) {
|
||||
ED_object_calc_active_center(ob, false, rv3d->twmat[3]);
|
||||
}
|
||||
else {
|
||||
if ((ob->mode & OB_MODE_ALL_SCULPT) && ob->sculpt) {
|
||||
SculptSession *ss = ob->sculpt;
|
||||
copy_v3_v3(rv3d->twmat[3], ss->pivot_pos);
|
||||
copy_v3_v3(r_pivot_pos, ss->pivot_pos);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
ED_object_calc_active_center(ob, false, rv3d->twmat[3]);
|
||||
else if (ED_object_calc_active_center(ob, false, r_pivot_pos)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
[[fallthrough]];
|
||||
case V3D_AROUND_CENTER_BOUNDS: {
|
||||
TransformBounds tbounds_stack;
|
||||
if (tbounds == nullptr) {
|
||||
TransformCalcParams calc_params{};
|
||||
calc_params.use_only_center = true;
|
||||
if (ED_transform_calc_gizmo_stats(C, &calc_params, &tbounds_stack, nullptr)) {
|
||||
tbounds = &tbounds_stack;
|
||||
}
|
||||
}
|
||||
if (tbounds) {
|
||||
mid_v3_v3v3(r_pivot_pos, tbounds->min, tbounds->max);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case V3D_AROUND_LOCAL_ORIGINS:
|
||||
case V3D_AROUND_CENTER_MEDIAN:
|
||||
copy_v3_v3(rv3d->twmat[3], tbounds->center);
|
||||
break;
|
||||
case V3D_AROUND_CURSOR:
|
||||
copy_v3_v3(rv3d->twmat[3], scene->cursor.location);
|
||||
break;
|
||||
case V3D_AROUND_CENTER_MEDIAN: {
|
||||
if (tbounds) {
|
||||
copy_v3_v3(r_pivot_pos, tbounds->center);
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto gizmo_3d_calc_center_fn = [](const float co[3], void *data) {
|
||||
float *center = static_cast<float *>(data);
|
||||
add_v3_v3(center, co);
|
||||
};
|
||||
const float(*r_mat)[4] = nullptr;
|
||||
int totsel;
|
||||
totsel = gizmo_3d_foreach_selected(C,
|
||||
0,
|
||||
(pivot_type != V3D_AROUND_LOCAL_ORIGINS),
|
||||
true,
|
||||
gizmo_3d_calc_center_fn,
|
||||
r_pivot_pos,
|
||||
&r_mat,
|
||||
nullptr);
|
||||
if (totsel) {
|
||||
mul_v3_fl(r_pivot_pos, 1.0f / float(totsel));
|
||||
if (r_mat) {
|
||||
mul_m4_v3(r_mat, r_pivot_pos);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void gizmo_prepare_mat(const struct bContext *C,
|
||||
struct RegionView3D *rv3d,
|
||||
const struct TransformBounds *tbounds)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
gizmo_3d_calc_pos(C, scene, tbounds, scene->toolsettings->transform_pivot_point, rv3d->twmat[3]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1598,7 +1680,7 @@ static int gizmo_modal(bContext *C,
|
||||
|
||||
TransformCalcParams calc_params{};
|
||||
calc_params.use_only_center = true;
|
||||
if (ED_transform_calc_gizmo_stats(C, &calc_params, &tbounds)) {
|
||||
if (ED_transform_calc_gizmo_stats(C, &calc_params, &tbounds, rv3d)) {
|
||||
gizmo_prepare_mat(C, rv3d, &tbounds);
|
||||
for (wmGizmo *gz = static_cast<wmGizmo *>(gzgroup->gizmos.first); gz; gz = gz->next) {
|
||||
WM_gizmo_set_matrix_location(gz, rv3d->twmat[3]);
|
||||
@ -1875,11 +1957,12 @@ static void WIDGETGROUP_gizmo_refresh(const bContext *C, wmGizmoGroup *gzgroup)
|
||||
TransformCalcParams calc_params{};
|
||||
calc_params.use_only_center = true;
|
||||
calc_params.orientation_index = orient_index + 1;
|
||||
if ((ggd->all_hidden = (ED_transform_calc_gizmo_stats(C, &calc_params, &tbounds) == 0))) {
|
||||
if ((ggd->all_hidden = (ED_transform_calc_gizmo_stats(C, &calc_params, &tbounds, rv3d) == 0))) {
|
||||
return;
|
||||
}
|
||||
|
||||
gizmo_prepare_mat(C, rv3d, &tbounds);
|
||||
gizmo_3d_calc_pos(
|
||||
C, scene, &tbounds, scene->toolsettings->transform_pivot_point, rv3d->twmat[3]);
|
||||
|
||||
gizmogroup_refresh_from_matrix(gzgroup, rv3d->twmat, nullptr, false);
|
||||
}
|
||||
@ -2378,3 +2461,11 @@ void transform_gizmo_3d_model_from_constraint_and_mode_restore(TransInfo *t)
|
||||
}
|
||||
MAN_ITER_AXES_END;
|
||||
}
|
||||
|
||||
bool ED_transform_calc_pivot_pos(const struct bContext *C,
|
||||
const short pivot_type,
|
||||
float r_pivot_pos[3])
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
return gizmo_3d_calc_pos(C, scene, nullptr, pivot_type, r_pivot_pos);
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ static void WIDGETGROUP_xform_cage_refresh(const bContext *C, wmGizmoGroup *gzgr
|
||||
TransformCalcParams calc_params{};
|
||||
calc_params.use_local_axis = true;
|
||||
calc_params.orientation_index = orient_index + 1;
|
||||
if ((ED_transform_calc_gizmo_stats(C, &calc_params, &tbounds) == 0) ||
|
||||
if ((ED_transform_calc_gizmo_stats(C, &calc_params, &tbounds, rv3d) == 0) ||
|
||||
equals_v3v3(rv3d->tw_axis_min, rv3d->tw_axis_max)) {
|
||||
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ static void WIDGETGROUP_xform_shear_refresh(const bContext *C, wmGizmoGroup *gzg
|
||||
TransformCalcParams calc_params{};
|
||||
calc_params.use_local_axis = false;
|
||||
calc_params.orientation_index = orient_index + 1;
|
||||
if (ED_transform_calc_gizmo_stats(C, &calc_params, &tbounds) == 0) {
|
||||
if (ED_transform_calc_gizmo_stats(C, &calc_params, &tbounds, rv3d) == 0) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
wmGizmo *gz = xgzgroup->gizmo[i][j];
|
||||
|
@ -233,6 +233,7 @@ static void gizmo_mesh_extrude_refresh(const bContext *C, wmGizmoGroup *gzgroup)
|
||||
}
|
||||
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
RegionView3D *rv3d = CTX_wm_region_data(C);
|
||||
|
||||
int axis_type;
|
||||
{
|
||||
@ -255,7 +256,8 @@ static void gizmo_mesh_extrude_refresh(const bContext *C, wmGizmoGroup *gzgroup)
|
||||
&(struct TransformCalcParams){
|
||||
.orientation_index = V3D_ORIENT_NORMAL + 1,
|
||||
},
|
||||
&tbounds_normal)) {
|
||||
&tbounds_normal,
|
||||
rv3d)) {
|
||||
unit_m3(tbounds_normal.axis);
|
||||
}
|
||||
copy_m3_m3(ggd->data.normal_mat3, tbounds_normal.axis);
|
||||
@ -266,7 +268,8 @@ static void gizmo_mesh_extrude_refresh(const bContext *C, wmGizmoGroup *gzgroup)
|
||||
&(struct TransformCalcParams){
|
||||
.orientation_index = ggd->data.orientation_index + 1,
|
||||
},
|
||||
&tbounds)) {
|
||||
&tbounds,
|
||||
rv3d)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user
As this function is reasonably involved, it would be good to add a doc-string giving an overview of the function and the parameters.