diff options
Diffstat (limited to 'source/blender/editors')
137 files changed, 2618 insertions, 1379 deletions
diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c index b2225ec138f..e552a321bca 100644 --- a/source/blender/editors/animation/anim_deps.c +++ b/source/blender/editors/animation/anim_deps.c @@ -44,12 +44,13 @@ #include "BKE_gpencil.h" #include "BKE_main.h" #include "BKE_node.h" -#include "BKE_sequencer.h" #include "DEG_depsgraph.h" #include "RNA_access.h" +#include "SEQ_sequencer.h" + #include "ED_anim_api.h" /* **************************** depsgraph tagging ******************************** */ diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 5dff62459ac..2e65fff69f1 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -96,11 +96,12 @@ #include "BKE_material.h" #include "BKE_modifier.h" #include "BKE_node.h" -#include "BKE_sequencer.h" #include "ED_anim_api.h" #include "ED_markers.h" +#include "SEQ_sequencer.h" + #include "UI_resources.h" /* for TH_KEYFRAME_SCALE lookup */ /* ************************************************************ */ diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index b52ff131b43..9e622aea6ab 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -37,7 +37,6 @@ #include "BKE_main.h" #include "BKE_report.h" #include "BKE_scene.h" -#include "BKE_sequencer.h" #include "UI_view2d.h" @@ -56,6 +55,8 @@ #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" +#include "SEQ_sequencer.h" + #include "anim_intern.h" /* ********************** frame change operator ***************************/ diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c index fc622c7a52e..deebf1d1efc 100644 --- a/source/blender/editors/animation/fmodifier_ui.c +++ b/source/blender/editors/animation/fmodifier_ui.c @@ -21,13 +21,11 @@ * \ingroup edanimation */ -/* User-Interface Stuff for F-Modifiers: - * This file defines the (C-Coded) templates + editing callbacks needed - * by the interface stuff or F-Modifiers, as used by F-Curves in the Graph Editor, - * and NLA-Strips in the NLA Editor. +/** + * User Interface for F-Modifiers * - * Copy/Paste Buffer for F-Modifiers: - * For now, this is also defined in this file so that it can be shared between the + * This file defines templates and some editing callbacks needed by the interface for + * F-Modifiers, as used by F-Curves in the Graph Editor and NLA-Strips in the NLA Editor. */ #include <string.h> @@ -1047,8 +1045,12 @@ void ANIM_uiTemplate_fmodifier_draw(uiLayout *layout, } } -/* ********************************************** */ -/* COPY/PASTE BUFFER STUFF */ +/* -------------------------------------------------------------------- */ +/** \name Copy / Paste Buffer Code + * + * For now, this is also defined in this file so that it can be shared between the graph editor + * and the NLA editor. + * \{ */ /* Copy/Paste Buffer itself (list of FModifier 's) */ static ListBase fmodifier_copypaste_buf = {NULL, NULL}; @@ -1139,4 +1141,4 @@ bool ANIM_fmodifiers_paste_from_buf(ListBase *modifiers, bool replace, FCurve *c return ok; } -/* ********************************************** */ +/** \} */ diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c index 60a1434ed42..8bcaf72f678 100644 --- a/source/blender/editors/armature/armature_naming.c +++ b/source/blender/editors/armature/armature_naming.c @@ -606,7 +606,7 @@ void ARMATURE_OT_autoside_names(wmOperatorType *ot) }; /* identifiers */ - ot->name = "AutoName by Axis"; + ot->name = "Auto-Name by Axis"; ot->idname = "ARMATURE_OT_autoside_names"; ot->description = "Automatically renames the selected bones according to which side of the target axis they " diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index 27718b61d70..66c12a0d0d7 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -1550,10 +1550,10 @@ enum { static const EnumPropertyItem prop_similar_types[] = { {SIMEDBONE_CHILDREN, "CHILDREN", 0, "Children", ""}, - {SIMEDBONE_CHILDREN_IMMEDIATE, "CHILDREN_IMMEDIATE", 0, "Immediate children", ""}, + {SIMEDBONE_CHILDREN_IMMEDIATE, "CHILDREN_IMMEDIATE", 0, "Immediate Children", ""}, {SIMEDBONE_SIBLINGS, "SIBLINGS", 0, "Siblings", ""}, {SIMEDBONE_LENGTH, "LENGTH", 0, "Length", ""}, - {SIMEDBONE_DIRECTION, "DIRECTION", 0, "Direction (Y axis)", ""}, + {SIMEDBONE_DIRECTION, "DIRECTION", 0, "Direction (Y Axis)", ""}, {SIMEDBONE_PREFIX, "PREFIX", 0, "Prefix", ""}, {SIMEDBONE_SUFFIX, "SUFFIX", 0, "Suffix", ""}, {SIMEDBONE_LAYER, "LAYER", 0, "Layer", ""}, diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index e51e5ec5cef..3c0b6dacbf6 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -1547,7 +1547,8 @@ static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind } } else { - BKE_modifier_set_error(&mmd->modifier, "Failed to find bind solution (increase precision?)"); + BKE_modifier_set_error( + mmd->object, &mmd->modifier, "Failed to find bind solution (increase precision?)"); error("Mesh Deform: failed to find bind solution."); break; } diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c index 8a1c2a4afa8..91893af003f 100644 --- a/source/blender/editors/armature/pose_edit.c +++ b/source/blender/editors/armature/pose_edit.c @@ -638,7 +638,7 @@ void POSE_OT_autoside_names(wmOperatorType *ot) }; /* identifiers */ - ot->name = "AutoName by Axis"; + ot->name = "Auto-Name by Axis"; ot->idname = "POSE_OT_autoside_names"; ot->description = "Automatically renames the selected bones according to which side of the target axis they " diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 85d86849140..d39c7eb0d95 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -307,12 +307,8 @@ static void keyIndex_delNurb(EditNurb *editnurb, Nurb *nu) static void keyIndex_delNurbList(EditNurb *editnurb, ListBase *nubase) { - Nurb *nu = nubase->first; - - while (nu) { + LISTBASE_FOREACH (Nurb *, nu, nubase) { keyIndex_delNurb(editnurb, nu); - - nu = nu->next; } } @@ -476,19 +472,15 @@ static void keyIndex_switchDirection(EditNurb *editnurb, Nurb *nu) static void switch_keys_direction(Curve *cu, Nurb *actnu) { - KeyBlock *currkey; EditNurb *editnurb = cu->editnurb; ListBase *nubase = &editnurb->nurbs; - Nurb *nu; float *fp; int a; - currkey = cu->key->block.first; - while (currkey) { + LISTBASE_FOREACH (KeyBlock *, currkey, &cu->key->block) { fp = currkey->data; - nu = nubase->first; - while (nu) { + LISTBASE_FOREACH (Nurb *, nu, nubase) { if (nu->bezt) { BezTriple *bezt = nu->bezt; a = nu->pntsu; @@ -522,11 +514,7 @@ static void switch_keys_direction(Curve *cu, Nurb *actnu) fp += a * KEYELEM_FLOAT_LEN_BPOINT; } } - - nu = nu->next; } - - currkey = currkey->next; } } @@ -583,13 +571,11 @@ static void bezt_to_key(BezTriple *bezt, float *key) static void calc_keyHandles(ListBase *nurb, float *key) { - Nurb *nu; int a; float *fp = key; BezTriple *bezt; - nu = nurb->first; - while (nu) { + LISTBASE_FOREACH (Nurb *, nu, nurb) { if (nu->bezt) { BezTriple *prevp, *nextp; BezTriple cur, prev, next; @@ -649,8 +635,6 @@ static void calc_keyHandles(ListBase *nurb, float *key) a = nu->pntsu * nu->pntsv; fp += a * KEYELEM_FLOAT_LEN_BPOINT; } - - nu = nu->next; } } @@ -658,255 +642,247 @@ static void calc_shapeKeys(Object *obedit, ListBase *newnurbs) { Curve *cu = (Curve *)obedit->data; - /* are there keys? */ - if (cu->key) { - int a, i; - EditNurb *editnurb = cu->editnurb; - KeyBlock *currkey; - KeyBlock *actkey = BLI_findlink(&cu->key->block, editnurb->shapenr - 1); - BezTriple *bezt, *oldbezt; - BPoint *bp, *oldbp; - Nurb *nu, *newnu; - int totvert = BKE_keyblock_curve_element_count(&editnurb->nurbs); - - float(*ofs)[3] = NULL; - float *oldkey, *newkey, *ofp; - - /* editing the base key should update others */ - if (cu->key->type == KEY_RELATIVE) { - if (BKE_keyblock_is_basis(cu->key, editnurb->shapenr - 1)) { /* active key is a base */ - int totvec = 0; - - /* Calculate needed memory to store offset */ - nu = editnurb->nurbs.first; - while (nu) { - if (nu->bezt) { - /* Three vects to store handles and one for tilt. */ - totvec += nu->pntsu * 4; - } - else { - totvec += 2 * nu->pntsu * nu->pntsv; - } + if (cu->key == NULL) { + return; + } - nu = nu->next; + int a, i; + EditNurb *editnurb = cu->editnurb; + KeyBlock *actkey = BLI_findlink(&cu->key->block, editnurb->shapenr - 1); + BezTriple *bezt, *oldbezt; + BPoint *bp, *oldbp; + Nurb *newnu; + int totvert = BKE_keyblock_curve_element_count(&editnurb->nurbs); + + float(*ofs)[3] = NULL; + float *oldkey, *newkey, *ofp; + + /* editing the base key should update others */ + if (cu->key->type == KEY_RELATIVE) { + if (BKE_keyblock_is_basis(cu->key, editnurb->shapenr - 1)) { /* active key is a base */ + int totvec = 0; + + /* Calculate needed memory to store offset */ + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { + + if (nu->bezt) { + /* Three vects to store handles and one for tilt. */ + totvec += nu->pntsu * 4; } + else { + totvec += 2 * nu->pntsu * nu->pntsv; + } + } - ofs = MEM_callocN(sizeof(float[3]) * totvec, "currkey->data"); - nu = editnurb->nurbs.first; - i = 0; - while (nu) { - if (nu->bezt) { - bezt = nu->bezt; - a = nu->pntsu; - while (a--) { - oldbezt = getKeyIndexOrig_bezt(editnurb, bezt); + ofs = MEM_callocN(sizeof(float[3]) * totvec, "currkey->data"); + i = 0; + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { + if (nu->bezt) { + bezt = nu->bezt; + a = nu->pntsu; + while (a--) { + oldbezt = getKeyIndexOrig_bezt(editnurb, bezt); - if (oldbezt) { - int j; - for (j = 0; j < 3; j++) { - sub_v3_v3v3(ofs[i], bezt->vec[j], oldbezt->vec[j]); - i++; - } - ofs[i][0] = bezt->tilt - oldbezt->tilt; - ofs[i][1] = bezt->radius - oldbezt->radius; + if (oldbezt) { + int j; + for (j = 0; j < 3; j++) { + sub_v3_v3v3(ofs[i], bezt->vec[j], oldbezt->vec[j]); i++; } - else { - i += 4; - } - bezt++; + ofs[i][0] = bezt->tilt - oldbezt->tilt; + ofs[i][1] = bezt->radius - oldbezt->radius; + i++; } + else { + i += 4; + } + bezt++; } - else { - bp = nu->bp; - a = nu->pntsu * nu->pntsv; - while (a--) { - oldbp = getKeyIndexOrig_bp(editnurb, bp); - if (oldbp) { - sub_v3_v3v3(ofs[i], bp->vec, oldbp->vec); - ofs[i + 1][0] = bp->tilt - oldbp->tilt; - ofs[i + 1][1] = bp->radius - oldbp->radius; - } - i += 2; - bp++; + } + else { + bp = nu->bp; + a = nu->pntsu * nu->pntsv; + while (a--) { + oldbp = getKeyIndexOrig_bp(editnurb, bp); + if (oldbp) { + sub_v3_v3v3(ofs[i], bp->vec, oldbp->vec); + ofs[i + 1][0] = bp->tilt - oldbp->tilt; + ofs[i + 1][1] = bp->radius - oldbp->radius; } + i += 2; + bp++; } - - nu = nu->next; } } } + } - currkey = cu->key->block.first; - while (currkey) { - const bool apply_offset = (ofs && (currkey != actkey) && - (editnurb->shapenr - 1 == currkey->relative)); - - float *fp = newkey = MEM_callocN(cu->key->elemsize * totvert, "currkey->data"); - ofp = oldkey = currkey->data; + LISTBASE_FOREACH (KeyBlock *, currkey, &cu->key->block) { + const bool apply_offset = (ofs && (currkey != actkey) && + (editnurb->shapenr - 1 == currkey->relative)); - nu = editnurb->nurbs.first; - /* We need to restore to original curve into newnurb, *not* editcurve's nurbs. - * Otherwise, in case we update obdata *without* leaving editmode (e.g. viewport render), - * we would invalidate editcurve. */ - newnu = newnurbs->first; - i = 0; - while (nu) { - if (currkey == actkey) { - const bool restore = actkey != cu->key->refkey; + float *fp = newkey = MEM_callocN(cu->key->elemsize * totvert, "currkey->data"); + ofp = oldkey = currkey->data; - if (nu->bezt) { - bezt = nu->bezt; - a = nu->pntsu; - BezTriple *newbezt = newnu->bezt; - while (a--) { - int j; - oldbezt = getKeyIndexOrig_bezt(editnurb, bezt); + Nurb *nu = editnurb->nurbs.first; + /* We need to restore to original curve into newnurb, *not* editcurve's nurbs. + * Otherwise, in case we update obdata *without* leaving editmode (e.g. viewport render), + * we would invalidate editcurve. */ + newnu = newnurbs->first; + i = 0; + while (nu) { + if (currkey == actkey) { + const bool restore = actkey != cu->key->refkey; - for (j = 0; j < 3; j++, i++) { - copy_v3_v3(&fp[j * 3], bezt->vec[j]); + if (nu->bezt) { + bezt = nu->bezt; + a = nu->pntsu; + BezTriple *newbezt = newnu->bezt; + while (a--) { + int j; + oldbezt = getKeyIndexOrig_bezt(editnurb, bezt); - if (restore && oldbezt) { - copy_v3_v3(newbezt->vec[j], oldbezt->vec[j]); - } - } - fp[9] = bezt->tilt; - fp[10] = bezt->radius; + for (j = 0; j < 3; j++, i++) { + copy_v3_v3(&fp[j * 3], bezt->vec[j]); if (restore && oldbezt) { - newbezt->tilt = oldbezt->tilt; - newbezt->radius = oldbezt->radius; + copy_v3_v3(newbezt->vec[j], oldbezt->vec[j]); } + } + fp[9] = bezt->tilt; + fp[10] = bezt->radius; - fp += KEYELEM_FLOAT_LEN_BEZTRIPLE; - i++; - bezt++; - newbezt++; + if (restore && oldbezt) { + newbezt->tilt = oldbezt->tilt; + newbezt->radius = oldbezt->radius; } - } - else { - bp = nu->bp; - a = nu->pntsu * nu->pntsv; - BPoint *newbp = newnu->bp; - while (a--) { - oldbp = getKeyIndexOrig_bp(editnurb, bp); - copy_v3_v3(fp, bp->vec); + fp += KEYELEM_FLOAT_LEN_BEZTRIPLE; + i++; + bezt++; + newbezt++; + } + } + else { + bp = nu->bp; + a = nu->pntsu * nu->pntsv; + BPoint *newbp = newnu->bp; + while (a--) { + oldbp = getKeyIndexOrig_bp(editnurb, bp); - fp[3] = bp->tilt; - fp[4] = bp->radius; + copy_v3_v3(fp, bp->vec); - if (restore && oldbp) { - copy_v3_v3(newbp->vec, oldbp->vec); - newbp->tilt = oldbp->tilt; - newbp->radius = oldbp->radius; - } + fp[3] = bp->tilt; + fp[4] = bp->radius; - fp += KEYELEM_FLOAT_LEN_BPOINT; - bp++; - newbp++; - i += 2; + if (restore && oldbp) { + copy_v3_v3(newbp->vec, oldbp->vec); + newbp->tilt = oldbp->tilt; + newbp->radius = oldbp->radius; } + + fp += KEYELEM_FLOAT_LEN_BPOINT; + bp++; + newbp++; + i += 2; } } - else { - int index; - const float *curofp; - - if (oldkey) { - if (nu->bezt) { - bezt = nu->bezt; - a = nu->pntsu; + } + else { + int index; + const float *curofp; - while (a--) { - index = getKeyIndexOrig_keyIndex(editnurb, bezt); - if (index >= 0) { - int j; - curofp = ofp + index; + if (oldkey) { + if (nu->bezt) { + bezt = nu->bezt; + a = nu->pntsu; - for (j = 0; j < 3; j++, i++) { - copy_v3_v3(&fp[j * 3], &curofp[j * 3]); + while (a--) { + index = getKeyIndexOrig_keyIndex(editnurb, bezt); + if (index >= 0) { + int j; + curofp = ofp + index; - if (apply_offset) { - add_v3_v3(&fp[j * 3], ofs[i]); - } - } - fp[9] = curofp[9]; - fp[10] = curofp[10]; + for (j = 0; j < 3; j++, i++) { + copy_v3_v3(&fp[j * 3], &curofp[j * 3]); if (apply_offset) { - /* Apply tilt offsets. */ - add_v3_v3(fp + 9, ofs[i]); - i++; + add_v3_v3(&fp[j * 3], ofs[i]); } + } + fp[9] = curofp[9]; + fp[10] = curofp[10]; - fp += KEYELEM_FLOAT_LEN_BEZTRIPLE; + if (apply_offset) { + /* Apply tilt offsets. */ + add_v3_v3(fp + 9, ofs[i]); + i++; } - else { - int j; - for (j = 0; j < 3; j++, i++) { - copy_v3_v3(&fp[j * 3], bezt->vec[j]); - } - fp[9] = bezt->tilt; - fp[10] = bezt->radius; - fp += KEYELEM_FLOAT_LEN_BEZTRIPLE; + fp += KEYELEM_FLOAT_LEN_BEZTRIPLE; + } + else { + int j; + for (j = 0; j < 3; j++, i++) { + copy_v3_v3(&fp[j * 3], bezt->vec[j]); } - bezt++; + fp[9] = bezt->tilt; + fp[10] = bezt->radius; + + fp += KEYELEM_FLOAT_LEN_BEZTRIPLE; } + bezt++; } - else { - bp = nu->bp; - a = nu->pntsu * nu->pntsv; - while (a--) { - index = getKeyIndexOrig_keyIndex(editnurb, bp); + } + else { + bp = nu->bp; + a = nu->pntsu * nu->pntsv; + while (a--) { + index = getKeyIndexOrig_keyIndex(editnurb, bp); - if (index >= 0) { - curofp = ofp + index; - copy_v3_v3(fp, curofp); - fp[3] = curofp[3]; - fp[4] = curofp[4]; + if (index >= 0) { + curofp = ofp + index; + copy_v3_v3(fp, curofp); + fp[3] = curofp[3]; + fp[4] = curofp[4]; - if (apply_offset) { - add_v3_v3(fp, ofs[i]); - add_v3_v3(&fp[3], ofs[i + 1]); - } - } - else { - copy_v3_v3(fp, bp->vec); - fp[3] = bp->tilt; - fp[4] = bp->radius; + if (apply_offset) { + add_v3_v3(fp, ofs[i]); + add_v3_v3(&fp[3], ofs[i + 1]); } - - fp += KEYELEM_FLOAT_LEN_BPOINT; - bp++; - i += 2; } + else { + copy_v3_v3(fp, bp->vec); + fp[3] = bp->tilt; + fp[4] = bp->radius; + } + + fp += KEYELEM_FLOAT_LEN_BPOINT; + bp++; + i += 2; } } } - - nu = nu->next; - newnu = newnu->next; } - if (apply_offset) { - /* handles could become malicious after offsets applying */ - calc_keyHandles(&editnurb->nurbs, newkey); - } - - currkey->totelem = totvert; - if (currkey->data) { - MEM_freeN(currkey->data); - } - currkey->data = newkey; + nu = nu->next; + newnu = newnu->next; + } - currkey = currkey->next; + if (apply_offset) { + /* handles could become malicious after offsets applying */ + calc_keyHandles(&editnurb->nurbs, newkey); } - if (ofs) { - MEM_freeN(ofs); + currkey->totelem = totvert; + if (currkey->data) { + MEM_freeN(currkey->data); } + currkey->data = newkey; + } + + if (ofs) { + MEM_freeN(ofs); } } @@ -929,11 +905,10 @@ static void fcurve_path_rename(AnimData *adt, ListBase *orig_curves, ListBase *curves) { - FCurve *fcu, *nfcu, *nextfcu; + FCurve *nfcu; int len = strlen(orig_rna_path); - for (fcu = orig_curves->first; fcu; fcu = nextfcu) { - nextfcu = fcu->next; + LISTBASE_FOREACH_MUTABLE (FCurve *, fcu, orig_curves) { if (STREQLEN(fcu->rna_path, orig_rna_path, len)) { char *spath, *suffix = fcu->rna_path + len; nfcu = BKE_fcurve_copy(fcu); @@ -977,16 +952,15 @@ static void fcurve_remove(AnimData *adt, ListBase *orig_curves, FCurve *fcu) static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) { - int nu_index = 0, a, pt_index; + int a, pt_index; EditNurb *editnurb = cu->editnurb; - Nurb *nu; CVKeyIndex *keyIndex; char rna_path[64], orig_rna_path[64]; AnimData *adt = BKE_animdata_from_id(&cu->id); ListBase curves = {NULL, NULL}; - FCurve *fcu, *next; - for (nu = editnurb->nurbs.first, nu_index = 0; nu != NULL; nu = nu->next, nu_index++) { + int nu_index = 0; + LISTBASE_FOREACH_INDEX (Nurb *, nu, &editnurb->nurbs, nu_index) { if (nu->bezt) { BezTriple *bezt = nu->bezt; a = nu->pntsu; @@ -1054,9 +1028,7 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) /* remove paths for removed control points * need this to make further step with copying non-cv related curves copying * not touching cv's f-curves */ - for (fcu = orig_curves->first; fcu; fcu = next) { - next = fcu->next; - + LISTBASE_FOREACH_MUTABLE (FCurve *, fcu, orig_curves) { if (STREQLEN(fcu->rna_path, "splines", 7)) { const char *ch = strchr(fcu->rna_path, '.'); @@ -1066,7 +1038,8 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) } } - for (nu = editnurb->nurbs.first, nu_index = 0; nu != NULL; nu = nu->next, nu_index++) { + nu_index = 0; + LISTBASE_FOREACH_INDEX (Nurb *, nu, &editnurb->nurbs, nu_index) { keyIndex = NULL; if (nu->pntsu) { if (nu->bezt) { @@ -1086,9 +1059,7 @@ static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves) /* the remainders in orig_curves can be copied back (like follow path) */ /* (if it's not path to spline) */ - for (fcu = orig_curves->first; fcu; fcu = next) { - next = fcu->next; - + LISTBASE_FOREACH_MUTABLE (FCurve *, fcu, orig_curves) { if (STREQLEN(fcu->rna_path, "splines", 7)) { fcurve_remove(adt, orig_curves, fcu); } @@ -1141,13 +1112,11 @@ static int *init_index_map(Object *obedit, int *r_old_totvert) { Curve *curve = (Curve *)obedit->data; EditNurb *editnurb = curve->editnurb; - Nurb *nu; CVKeyIndex *keyIndex; int *old_to_new_map; - int old_totvert; - int vertex_index; - for (nu = curve->nurb.first, old_totvert = 0; nu != NULL; nu = nu->next) { + int old_totvert = 0; + LISTBASE_FOREACH (Nurb *, nu, &curve->nurb) { if (nu->bezt) { old_totvert += nu->pntsu * 3; } @@ -1161,7 +1130,8 @@ static int *init_index_map(Object *obedit, int *r_old_totvert) old_to_new_map[i] = -1; } - for (nu = editnurb->nurbs.first, vertex_index = 0; nu != NULL; nu = nu->next) { + int vertex_index = 0; + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { if (nu->bezt) { BezTriple *bezt = nu->bezt; int a = nu->pntsu; @@ -1205,7 +1175,6 @@ static int *init_index_map(Object *obedit, int *r_old_totvert) static void remap_hooks_and_vertex_parents(Main *bmain, Object *obedit) { - Object *object; Curve *curve = (Curve *)obedit->data; EditNurb *editnurb = curve->editnurb; int *old_to_new_map = NULL; @@ -1219,8 +1188,7 @@ static void remap_hooks_and_vertex_parents(Main *bmain, Object *obedit) return; } - for (object = bmain->objects.first; object; object = object->id.next) { - ModifierData *md; + LISTBASE_FOREACH (Object *, object, &bmain->objects) { int index; if ((object->parent) && (object->parent->data == curve) && ELEM(object->partype, PARVERT1, PARVERT3)) { @@ -1248,7 +1216,7 @@ static void remap_hooks_and_vertex_parents(Main *bmain, Object *obedit) } } if (object->data == curve) { - for (md = object->modifiers.first; md; md = md->next) { + LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { if (md->type == eModifierType_Hook) { HookModifierData *hmd = (HookModifierData *)md; int i, j; @@ -1290,13 +1258,12 @@ void ED_curve_editnurb_load(Main *bmain, Object *obedit) if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { Curve *cu = obedit->data; - Nurb *nu, *newnu; ListBase newnurb = {NULL, NULL}, oldnurb = cu->nurb; remap_hooks_and_vertex_parents(bmain, obedit); - for (nu = editnurb->first; nu; nu = nu->next) { - newnu = BKE_nurb_duplicate(nu); + LISTBASE_FOREACH (Nurb *, nu, editnurb) { + Nurb *newnu = BKE_nurb_duplicate(nu); BLI_addtail(&newnurb, newnu); if (nu->type == CU_NURBS) { @@ -1323,7 +1290,6 @@ void ED_curve_editnurb_make(Object *obedit) { Curve *cu = (Curve *)obedit->data; EditNurb *editnurb = cu->editnurb; - Nurb *nu, *newnu; KeyBlock *actkey; if (ELEM(obedit->type, OB_CURVE, OB_SURF)) { @@ -1346,12 +1312,10 @@ void ED_curve_editnurb_make(Object *obedit) cu->editnurb = editnurb; } - nu = cu->nurb.first; - while (nu) { - newnu = BKE_nurb_duplicate(nu); + LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) { + Nurb *newnu = BKE_nurb_duplicate(nu); BKE_nurb_test_2d(newnu); /* after join, or any other creation of curve */ BLI_addtail(&editnurb->nurbs, newnu); - nu = nu->next; } /* animation could be added in editmode even if there was no animdata in @@ -1722,11 +1686,10 @@ static void rotateflagNurb(ListBase *editnurb, const float rotmat[3][3]) { /* all verts with (flag & 'flag') rotate */ - Nurb *nu; BPoint *bp; int a; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_NURBS) { bp = nu->bp; a = nu->pntsu * nu->pntsv; @@ -1746,12 +1709,11 @@ static void rotateflagNurb(ListBase *editnurb, void ed_editnurb_translate_flag(ListBase *editnurb, uint8_t flag, const float vec[3]) { /* all verts with ('flag' & flag) translate */ - Nurb *nu; BezTriple *bezt; BPoint *bp; int a; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { a = nu->pntsu; bezt = nu->bezt; @@ -1785,11 +1747,10 @@ void ed_editnurb_translate_flag(ListBase *editnurb, uint8_t flag, const float ve static void weightflagNurb(ListBase *editnurb, short flag, float w) { - Nurb *nu; BPoint *bp; int a; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_NURBS) { a = nu->pntsu * nu->pntsv; bp = nu->bp; @@ -1808,16 +1769,12 @@ static void ed_surf_delete_selected(Object *obedit) { Curve *cu = obedit->data; ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu, *next; BPoint *bp, *bpn, *newbp; int a, b, newu, newv; BLI_assert(obedit->type == OB_SURF); - nu = editnurb->first; - while (nu) { - next = nu->next; - + LISTBASE_FOREACH_MUTABLE (Nurb *, nu, editnurb) { /* is entire nurb selected */ bp = nu->bp; a = nu->pntsu * nu->pntsv; @@ -1903,7 +1860,6 @@ static void ed_surf_delete_selected(Object *obedit) } } } - nu = next; } } @@ -1912,15 +1868,12 @@ static void ed_curve_delete_selected(Object *obedit, View3D *v3d) Curve *cu = obedit->data; EditNurb *editnurb = cu->editnurb; ListBase *nubase = &editnurb->nurbs; - Nurb *nu, *next; BezTriple *bezt, *bezt1; BPoint *bp, *bp1; int a, type, nuindex = 0; /* first loop, can we remove entire pieces? */ - nu = nubase->first; - while (nu) { - next = nu->next; + LISTBASE_FOREACH_MUTABLE (Nurb *, nu, nubase) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; @@ -1981,13 +1934,10 @@ static void ed_curve_delete_selected(Object *obedit, View3D *v3d) clamp_nurb_order_u(nu); } #endif - nu = next; nuindex++; } /* 2nd loop, delete small pieces: just for curves */ - nu = nubase->first; - while (nu) { - next = nu->next; + LISTBASE_FOREACH_MUTABLE (Nurb *, nu, nubase) { type = 0; if (nu->type == CU_BEZIER) { bezt = nu->bezt; @@ -2047,21 +1997,17 @@ static void ed_curve_delete_selected(Object *obedit, View3D *v3d) BKE_nurb_order_clamp_u(nu); BKE_nurb_knot_calc_u(nu); } - nu = next; } } /* only for OB_SURF */ bool ed_editnurb_extrude_flag(EditNurb *editnurb, const uint8_t flag) { - Nurb *nu; BPoint *bp, *bpn, *newbp; int a, u, v, len; bool ok = false; - nu = editnurb->nurbs.first; - while (nu) { - + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { if (nu->pntsv == 1) { bp = nu->bp; a = nu->pntsu; @@ -2166,7 +2112,6 @@ bool ed_editnurb_extrude_flag(EditNurb *editnurb, const uint8_t flag) } } } - nu = nu->next; } return ok; @@ -2197,14 +2142,15 @@ static void adduplicateflagNurb( Object *obedit, View3D *v3d, ListBase *newnurb, const uint8_t flag, const bool split) { ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu, *newnu; + Nurb *newnu; BezTriple *bezt, *bezt1; BPoint *bp, *bp1, *bp2, *bp3; Curve *cu = (Curve *)obedit->data; - int a, b, c, starta, enda, diffa, cyclicu, cyclicv, newu, newv, i; + int a, b, c, starta, enda, diffa, cyclicu, cyclicv, newu, newv; char *usel; - for (i = 0, nu = editnurb->first; nu; i++, nu = nu->next) { + int i = 0; + LISTBASE_FOREACH_INDEX (Nurb *, nu, editnurb, i) { cyclicu = cyclicv = 0; if (nu->type == CU_BEZIER) { for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) { @@ -2569,7 +2515,7 @@ static void adduplicateflagNurb( } if (BLI_listbase_is_empty(newnurb) == false) { - for (nu = newnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, newnurb) { if (nu->type == CU_BEZIER) { if (split) { /* recalc first and last */ @@ -2619,10 +2565,9 @@ static int switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) } EditNurb *editnurb = cu->editnurb; - Nurb *nu; - int i; - for (nu = editnurb->nurbs.first, i = 0; nu; nu = nu->next, i++) { + int i = 0; + LISTBASE_FOREACH_INDEX (Nurb *, nu, &editnurb->nurbs, i) { if (ED_curve_nurb_select_check(v3d, nu)) { BKE_nurb_direction_switch(nu); keyData_switchDirectionNurb(cu, nu); @@ -2674,13 +2619,12 @@ static int set_goal_weight_exec(bContext *C, wmOperator *op) for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; BezTriple *bezt; BPoint *bp; float weight = RNA_float_get(op->ptr, "weight"); int a; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->bezt) { for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) { if (bezt->f2 & SELECT) { @@ -2741,13 +2685,12 @@ static int set_radius_exec(bContext *C, wmOperator *op) for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; BezTriple *bezt; BPoint *bp; float radius = RNA_float_get(op->ptr, "radius"); int a; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->bezt) { for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) { if (bezt->f2 & SELECT) { @@ -2853,12 +2796,11 @@ static int smooth_exec(bContext *C, wmOperator *UNUSED(op)) for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; int a, a_end; bool changed = false; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->bezt) { /* duplicate the curve to use in weight calculation */ const BezTriple *bezt_orig = MEM_dupallocN(nu->bezt); @@ -2960,7 +2902,6 @@ void CURVE_OT_smooth(wmOperatorType *ot) static void curve_smooth_value(ListBase *editnurb, const int bezt_offsetof, const int bp_offset) { - Nurb *nu; BezTriple *bezt; BPoint *bp; int a; @@ -2970,7 +2911,7 @@ static void curve_smooth_value(ListBase *editnurb, const int bezt_offsetof, cons int start_sel, end_sel; /* selection indices, inclusive */ float start_rad, end_rad, fac, range; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->bezt) { #define BEZT_VALUE(bezt) (*((float *)((char *)(bezt) + bezt_offsetof))) @@ -3289,12 +3230,11 @@ static int hide_exec(bContext *C, wmOperator *op) } ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; BPoint *bp; BezTriple *bezt; int a, sel; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; @@ -3385,13 +3325,12 @@ static int reveal_exec(bContext *C, wmOperator *op) for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; BPoint *bp; BezTriple *bezt; int a; bool changed = false; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { nu->hide = 0; if (nu->type == CU_BEZIER) { bezt = nu->bezt; @@ -3462,7 +3401,6 @@ static void subdividenurb(Object *obedit, View3D *v3d, int number_cuts) { Curve *cu = obedit->data; EditNurb *editnurb = cu->editnurb; - Nurb *nu; BezTriple *bezt, *beztnew, *beztn; BPoint *bp, *prevbp, *bpnew, *bpn; float vec[15]; @@ -3471,7 +3409,7 @@ static void subdividenurb(Object *obedit, View3D *v3d, int number_cuts) // printf("*** subdivideNurb: entering subdivide\n"); - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { amount = 0; if (nu->type == CU_BEZIER) { BezTriple *nextbezt; @@ -3925,7 +3863,6 @@ static int set_spline_type_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); View3D *v3d = CTX_wm_view3d(C); ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; bool changed = false; bool changed_size = false; const bool use_handles = RNA_boolean_get(op->ptr, "use_handles"); @@ -3936,7 +3873,7 @@ static int set_spline_type_exec(bContext *C, wmOperator *op) continue; } - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (ED_curve_nurb_select_check(v3d, nu)) { const int pntsu_prev = nu->pntsu; const char *err_msg = NULL; @@ -4225,12 +4162,11 @@ static void make_selection_list_nurb(View3D *v3d, ListBase *editnurb, ListBase * { ListBase nbase = {NULL, NULL}; NurbSort *nus, *nustest, *headdo, *taildo; - Nurb *nu; BPoint *bp; float dist, headdist, taildist; int a; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (ED_curve_nurb_select_check(v3d, nu)) { nus = (NurbSort *)MEM_callocN(sizeof(NurbSort), "sort"); @@ -4996,7 +4932,6 @@ bool ed_editnurb_spin( { Curve *cu = (Curve *)obedit->data; ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; float cmat[3][3], tmat[3][3], imat[3][3]; float bmat[3][3], rotmat[3][3], scalemat1[3][3], scalemat2[3][3]; float persmat[3][3], persinv[3][3]; @@ -5056,7 +4991,7 @@ bool ed_editnurb_spin( } if (ok) { - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (ED_curve_nurb_select_check(v3d, nu)) { nu->orderv = 4; nu->flagv |= CU_NURB_CYCLIC; @@ -5427,8 +5362,6 @@ static int ed_editcurve_addvert(Curve *cu, View3D *v3d, const float location_init[3]) { - Nurb *nu; - float center[3]; float temp[3]; uint verts_len; @@ -5437,7 +5370,7 @@ static int ed_editcurve_addvert(Curve *cu, zero_v3(center); verts_len = 0; - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { int i; if (nu->type == CU_BEZIER) { BezTriple *bezt; @@ -5472,7 +5405,7 @@ static int ed_editcurve_addvert(Curve *cu, ofs[2] = 0.0f; } - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { if (nu->type == CU_BEZIER) { BezTriple *bezt; for (i = 0, bezt = nu->bezt; i < nu->pntsu; i++, bezt++) { @@ -5511,7 +5444,7 @@ static int ed_editcurve_addvert(Curve *cu, } /* nothing selected: create a new curve */ - nu = BKE_curve_nurb_active_get(cu); + Nurb *nu = BKE_curve_nurb_active_get(cu); if (!nu || nu->type == CU_BEZIER) { Nurb *nurb_new; @@ -5764,8 +5697,7 @@ static int curve_extrude_exec(bContext *C, wmOperator *UNUSED(op)) /* First test: curve? */ if (obedit->type != OB_CURVE) { - Nurb *nu; - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { if ((nu->pntsv == 1) && (ED_curve_nurb_select_count(v3d, nu) == 1)) { as_curve = true; break; @@ -5819,13 +5751,12 @@ void CURVE_OT_extrude(wmOperatorType *ot) static bool curve_toggle_cyclic(View3D *v3d, ListBase *editnurb, int direction) { - Nurb *nu; BezTriple *bezt; BPoint *bp; int a; bool changed = false; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->pntsu > 1 || nu->pntsv > 1) { if (nu->type == CU_POLY) { a = nu->pntsu; @@ -5932,10 +5863,9 @@ static int toggle_cyclic_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS ListBase *editnurb = object_editcurve_get(obedit); uiPopupMenu *pup; uiLayout *layout; - Nurb *nu; if (obedit->type == OB_SURF) { - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->pntsu > 1 || nu->pntsv > 1) { if (nu->type == CU_NURBS) { pup = UI_popup_menu_begin(C, IFACE_("Direction"), ICON_NONE); @@ -6064,12 +5994,12 @@ static bool curve_delete_segments(Object *obedit, View3D *v3d, const bool split) Curve *cu = obedit->data; EditNurb *editnurb = cu->editnurb; ListBase *nubase = &editnurb->nurbs, newnurb = {NULL, NULL}; - Nurb *nu, *nu1; + Nurb *nu1; BezTriple *bezt, *bezt1, *bezt2; BPoint *bp, *bp1, *bp2; int a, b, starta, enda, cut, cyclicut; - for (nu = nubase->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, nubase) { nu1 = NULL; starta = enda = cut = -1; cyclicut = 0; @@ -6452,7 +6382,7 @@ static bool curve_delete_segments(Object *obedit, View3D *v3d, const bool split) } } - for (nu = newnurb.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &newnurb) { if (nu->type == CU_BEZIER) { if (split) { /* deselect for split operator */ @@ -6620,9 +6550,8 @@ static int curve_dissolve_exec(bContext *C, wmOperator *UNUSED(op)) } ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if ((nu->type == CU_BEZIER) && (nu->pntsu > 2)) { uint span_step[2] = {nu->pntsu, nu->pntsu}; uint span_len; @@ -6766,9 +6695,8 @@ static int curve_decimate_exec(bContext *C, wmOperator *op) { ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { if ((nu->pntsu > 2) && nurb_bezt_flag_any(nu, SELECT)) { const int error_target_len = max_ii(2, nu->pntsu * ratio); @@ -6917,7 +6845,6 @@ int ED_curve_join_objects_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); Object *ob_active = CTX_data_active_object(C); Curve *cu; - Nurb *nu, *newnu; BezTriple *bezt; BPoint *bp; ListBase tempbase; @@ -6955,9 +6882,8 @@ int ED_curve_join_objects_exec(bContext *C, wmOperator *op) /* watch it: switch order here really goes wrong */ mul_m4_m4m4(cmat, imat, ob_iter->obmat); - nu = cu->nurb.first; - while (nu) { - newnu = BKE_nurb_duplicate(nu); + LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) { + Nurb *newnu = BKE_nurb_duplicate(nu); if (ob_active->totcol) { /* TODO, merge material lists */ CLAMP(newnu->mat_nr, 0, ob_active->totcol - 1); } @@ -6983,7 +6909,6 @@ int ED_curve_join_objects_exec(bContext *C, wmOperator *op) bp++; } } - nu = nu->next; } } @@ -7035,12 +6960,11 @@ static int clear_tilt_exec(bContext *C, wmOperator *UNUSED(op)) } ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; BezTriple *bezt; BPoint *bp; int a; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->bezt) { bezt = nu->bezt; a = nu->pntsu; diff --git a/source/blender/editors/curve/editcurve_query.c b/source/blender/editors/curve/editcurve_query.c index 48571ab2a9b..369137cbe25 100644 --- a/source/blender/editors/curve/editcurve_query.c +++ b/source/blender/editors/curve/editcurve_query.c @@ -26,6 +26,7 @@ #include "MEM_guardedalloc.h" +#include "BLI_listbase.h" #include "BLI_math.h" #include "BKE_curve.h" @@ -170,7 +171,6 @@ void ED_curve_nurb_vert_selected_find( /* in nu and (bezt or bp) selected are written if there's 1 sel. */ /* if more points selected in 1 spline: return only nu, bezt and bp are 0 */ ListBase *editnurb = &cu->editnurb->nurbs; - Nurb *nu1; BezTriple *bezt1; BPoint *bp1; int a; @@ -179,7 +179,7 @@ void ED_curve_nurb_vert_selected_find( *r_bezt = NULL; *r_bp = NULL; - for (nu1 = editnurb->first; nu1; nu1 = nu1->next) { + LISTBASE_FOREACH (Nurb *, nu1, editnurb) { if (nu1->type == CU_BEZIER) { bezt1 = nu1->bezt; a = nu1->pntsu; diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c index aa4ba332b66..4097275a2b9 100644 --- a/source/blender/editors/curve/editcurve_select.c +++ b/source/blender/editors/curve/editcurve_select.c @@ -237,9 +237,7 @@ int ED_curve_select_count(View3D *v3d, struct EditNurb *editnurb) bool ED_curve_select_check(View3D *v3d, struct EditNurb *editnurb) { - Nurb *nu; - - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { if (ED_curve_nurb_select_check(v3d, nu)) { return true; } @@ -284,13 +282,12 @@ bool ED_curve_deselect_all_multi(struct bContext *C) bool ED_curve_select_swap(EditNurb *editnurb, bool hide_handles) { - Nurb *nu; BPoint *bp; BezTriple *bezt; int a; bool changed = false; - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; @@ -331,7 +328,6 @@ static void select_adjacent_cp(ListBase *editnurb, const bool cont, const bool selstatus) { - Nurb *nu; BezTriple *bezt; BPoint *bp; int a; @@ -341,7 +337,7 @@ static void select_adjacent_cp(ListBase *editnurb, return; } - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { lastsel = false; if (nu->type == CU_BEZIER) { a = nu->pntsu; @@ -412,7 +408,6 @@ static void select_adjacent_cp(ListBase *editnurb, static void selectend_nurb(Object *obedit, eEndPoint_Types selfirst, bool doswap, bool selstatus) { ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; BPoint *bp; BezTriple *bezt; Curve *cu; @@ -425,7 +420,7 @@ static void selectend_nurb(Object *obedit, eEndPoint_Types selfirst, bool doswap cu = (Curve *)obedit->data; cu->actvert = CU_ACT_NONE; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { a = nu->pntsu; @@ -632,10 +627,9 @@ static int select_linked_exec(bContext *C, wmOperator *UNUSED(op)) Curve *cu = obedit->data; EditNurb *editnurb = cu->editnurb; ListBase *nurbs = &editnurb->nurbs; - Nurb *nu; bool changed = false; - for (nu = nurbs->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, nurbs) { if (ED_curve_nurb_select_check(v3d, nu)) { changed |= ED_curve_nurb_select_all(nu); } @@ -887,7 +881,6 @@ void CURVE_OT_select_previous(wmOperatorType *ot) static void curve_select_more(Object *obedit) { ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; BPoint *bp, *tempbp; int a; short sel = 0; @@ -897,7 +890,7 @@ static void curve_select_more(Object *obedit) /* The algorithm is designed to work in planar cases so it */ /* may not be optimal always (example: end of NURBS sphere) */ if (obedit->type == OB_SURF) { - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { BLI_bitmap *selbpoints; a = nu->pntsu * nu->pntsv; bp = nu->bp; @@ -997,7 +990,6 @@ void CURVE_OT_select_more(wmOperatorType *ot) static void curve_select_less(Object *obedit) { ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; BPoint *bp; BezTriple *bezt; int a; @@ -1005,7 +997,7 @@ static void curve_select_less(Object *obedit) bool lastsel = false; if (obedit->type == OB_SURF) { - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { BLI_bitmap *selbpoints; a = nu->pntsu * nu->pntsv; bp = nu->bp; @@ -1077,7 +1069,7 @@ static void curve_select_less(Object *obedit) } } else { - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { lastsel = false; /* check what type of curve/nurb it is */ if (nu->type == CU_BEZIER) { @@ -1210,14 +1202,13 @@ void CURVE_OT_select_less(wmOperatorType *ot) static void curve_select_random(ListBase *editnurb, float randfac, int seed, bool select) { - Nurb *nu; BezTriple *bezt; BPoint *bp; int a; RNG *rng = BLI_rng_new_srandom(seed); - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; @@ -1431,9 +1422,7 @@ void CURVE_OT_select_nth(wmOperatorType *ot) } /* -------------------------------------------------------------------- */ -/* Select Similar */ - -/** \name Select Similar +/** \name Select Similar Operator * \{ */ static const EnumPropertyItem curve_prop_similar_compare_types[] = { @@ -1702,8 +1691,7 @@ static int curve_select_similar_exec(bContext *C, wmOperator *op) Curve *cu = obedit->data; EditNurb *editnurb = cu->editnurb; - Nurb *nu; - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { if (!ED_curve_nurb_select_check(v3d, nu)) { continue; } @@ -1736,9 +1724,8 @@ static int curve_select_similar_exec(bContext *C, wmOperator *op) Curve *cu = obedit->data; EditNurb *editnurb = cu->editnurb; bool changed = false; - Nurb *nu; - for (nu = editnurb->nurbs.first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) { switch (optype) { case SIMCURHAND_TYPE: { if (nu->type & type_ref) { @@ -1797,9 +1784,7 @@ void CURVE_OT_select_similar(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ -/* Select Shortest Path */ - -/** \name Select Path +/** \name Select Shortest Path Operator * \{ */ static float curve_calc_dist_pair(const Nurb *nu, int a, int b) diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index 2a880c11afb..1eb35b2c647 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -626,7 +626,7 @@ void FONT_OT_text_paste_from_file(wmOperatorType *ot) FILE_OPENFILE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); } /** \} */ @@ -635,7 +635,10 @@ void FONT_OT_text_paste_from_file(wmOperatorType *ot) /** \name Text To Object * \{ */ -static void txt_add_object(bContext *C, TextLine *firstline, int totline, const float offset[3]) +static void txt_add_object(bContext *C, + const TextLine *firstline, + int totline, + const float offset[3]) { Main *bmain = CTX_data_main(C); Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); @@ -644,7 +647,7 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, const Curve *cu; Object *obedit; Base *base; - struct TextLine *tmp; + const struct TextLine *tmp; int nchars = 0, nbytes = 0; char *s; int a; @@ -709,10 +712,10 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, const WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, obedit); } -void ED_text_to_object(bContext *C, Text *text, const bool split_lines) +void ED_text_to_object(bContext *C, const Text *text, const bool split_lines) { RegionView3D *rv3d = CTX_wm_region_view3d(C); - TextLine *line; + const TextLine *line; float offset[3]; int linenum = 0; @@ -2157,7 +2160,7 @@ void FONT_OT_open(wmOperatorType *ot) FILE_OPENFILE, WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); } /** \} */ diff --git a/source/blender/editors/curve/editfont_undo.c b/source/blender/editors/curve/editfont_undo.c index ef9bb7e0c88..61c05f62af7 100644 --- a/source/blender/editors/curve/editfont_undo.c +++ b/source/blender/editors/curve/editfont_undo.c @@ -74,6 +74,7 @@ typedef struct UndoFont { #ifdef USE_ARRAY_STORE +/* -------------------------------------------------------------------- */ /** \name Array Store * \{ */ diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index d54bdf552eb..6258e6e8481 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -2737,12 +2737,12 @@ static bool gpencil_snap_poll(bContext *C) static int gpencil_snap_to_grid(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); - RegionView3D *rv3d = CTX_wm_region_data(C); + ARegion *region = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); Scene *scene = CTX_data_scene(C); Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); Object *obact = CTX_data_active_object(C); - const float gridf = ED_view3d_grid_view_scale(scene, v3d, rv3d, NULL); + const float gridf = ED_view3d_grid_view_scale(scene, v3d, region, NULL); LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { /* only editable and visible layers are considered */ @@ -3152,8 +3152,8 @@ void GPENCIL_OT_stroke_cyclical_set(wmOperatorType *ot) PropertyRNA *prop; static const EnumPropertyItem cyclic_type[] = { - {GP_STROKE_CYCLIC_CLOSE, "CLOSE", 0, "Close all", ""}, - {GP_STROKE_CYCLIC_OPEN, "OPEN", 0, "Open all", ""}, + {GP_STROKE_CYCLIC_CLOSE, "CLOSE", 0, "Close All", ""}, + {GP_STROKE_CYCLIC_OPEN, "OPEN", 0, "Open All", ""}, {GP_STROKE_CYCLIC_TOGGLE, "TOGGLE", 0, "Toggle", ""}, {0, NULL, 0, NULL, NULL}, }; @@ -3398,24 +3398,50 @@ static void gpencil_stroke_join_strokes(bGPDstroke *gps_a, } /* define start and end points of each stroke */ - float area[3], sb[3], ea[3], eb[3]; + float start_a[3], start_b[3], end_a[3], end_b[3]; pt = &gps_a->points[0]; - copy_v3_v3(area, &pt->x); + copy_v3_v3(start_a, &pt->x); pt = &gps_a->points[gps_a->totpoints - 1]; - copy_v3_v3(ea, &pt->x); + copy_v3_v3(end_a, &pt->x); pt = &gps_b->points[0]; - copy_v3_v3(sb, &pt->x); + copy_v3_v3(start_b, &pt->x); pt = &gps_b->points[gps_b->totpoints - 1]; - copy_v3_v3(eb, &pt->x); + copy_v3_v3(end_b, &pt->x); + + /* Check if need flip strokes. */ + float dist = len_squared_v3v3(end_a, start_b); + bool flip_a = false; + bool flip_b = false; + float lowest = dist; + + dist = len_squared_v3v3(end_a, end_b); + if (dist < lowest) { + lowest = dist; + flip_a = false; + flip_b = true; + } + + dist = len_squared_v3v3(start_a, start_b); + if (dist < lowest) { + lowest = dist; + flip_a = true; + flip_b = false; + } + + dist = len_squared_v3v3(start_a, end_b); + if (dist < lowest) { + lowest = dist; + flip_a = true; + flip_b = true; + } - /* review if need flip stroke B */ - float ea_sb = len_squared_v3v3(ea, sb); - float ea_eb = len_squared_v3v3(ea, eb); - /* flip if distance to end point is shorter */ - if (ea_eb < ea_sb) { + if (flip_a) { + gpencil_flip_stroke(gps_a); + } + if (flip_b) { gpencil_flip_stroke(gps_b); } @@ -3439,16 +3465,71 @@ static void gpencil_stroke_join_strokes(bGPDstroke *gps_a, } } +typedef struct tJoinStrokes { + bGPDframe *gpf; + bGPDstroke *gps; + bool used; +} tJoinStrokes; + +static int gpencil_get_nearest_stroke_index(tJoinStrokes *strokes_list, + const bGPDstroke *gps, + const int totstrokes) +{ + int index = -1; + float min_dist = FLT_MAX; + float dist, start_a[3], end_a[3], start_b[3], end_b[3]; + + bGPDspoint *pt = &gps->points[0]; + copy_v3_v3(start_a, &pt->x); + + pt = &gps->points[gps->totpoints - 1]; + copy_v3_v3(end_a, &pt->x); + + for (int i = 0; i < totstrokes; i++) { + tJoinStrokes *elem = &strokes_list[i]; + if (elem->used) { + continue; + } + pt = &elem->gps->points[0]; + copy_v3_v3(start_b, &pt->x); + + pt = &elem->gps->points[elem->gps->totpoints - 1]; + copy_v3_v3(end_b, &pt->x); + + dist = len_squared_v3v3(start_a, start_b); + if (dist < min_dist) { + min_dist = dist; + index = i; + } + dist = len_squared_v3v3(start_a, end_b); + if (dist < min_dist) { + min_dist = dist; + index = i; + } + dist = len_squared_v3v3(end_a, start_b); + if (dist < min_dist) { + min_dist = dist; + index = i; + } + dist = len_squared_v3v3(end_a, end_b); + if (dist < min_dist) { + min_dist = dist; + index = i; + } + } + + return index; +} + static int gpencil_stroke_join_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *activegpl = BKE_gpencil_layer_active_get(gpd); Object *ob = CTX_data_active_object(C); - - bGPDframe *gpf_a = NULL; - bGPDstroke *stroke_a = NULL; - bGPDstroke *stroke_b = NULL; - bGPDstroke *new_stroke = NULL; + /* Limit the number of strokes to join. It makes no sense to allow an very high number of strokes + * for CPU time and because to have a stroke with thousands of points is unpractical, so limit + * this number avoid to joining a full frame scene in one single stroke. */ + const int max_join_strokes = 128; const int type = RNA_enum_get(op->ptr, "type"); const bool leave_gaps = RNA_boolean_get(op->ptr, "leave_gaps"); @@ -3464,87 +3545,89 @@ static int gpencil_stroke_join_exec(bContext *C, wmOperator *op) BLI_assert(ELEM(type, GP_STROKE_JOIN, GP_STROKE_JOINCOPY)); - /* read all selected strokes */ - bool first = false; + int tot_strokes = 0; + /** Alloc memory */ + tJoinStrokes *strokes_list = MEM_malloc_arrayN(sizeof(tJoinStrokes), max_join_strokes, __func__); + tJoinStrokes *elem = NULL; + /* Read all selected strokes to create a list. */ CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) { bGPDframe *gpf = gpl->actframe; if (gpf == NULL) { continue; } - LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) { + /* Add all stroke selected of the frame. */ + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { if (gps->flag & GP_STROKE_SELECT) { /* skip strokes that are invalid for current view */ if (ED_gpencil_stroke_can_use(C, gps) == false) { continue; } - /* check if the color is editable */ + /* check if the color is editable. */ if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { continue; } - - /* to join strokes, cyclic must be disabled */ - gps->flag &= ~GP_STROKE_CYCLIC; - - /* saves first frame and stroke */ - if (!first) { - first = true; - gpf_a = gpf; - stroke_a = gps; + elem = &strokes_list[tot_strokes]; + elem->gpf = gpf; + elem->gps = gps; + elem->used = false; + + tot_strokes++; + /* Limit the number of strokes. */ + if (tot_strokes == max_join_strokes) { + BKE_reportf(op->reports, + RPT_WARNING, + "Too many strokes selected. Only joined first %d strokes.", + max_join_strokes); + break; } - else { - stroke_b = gps; - - /* create a new stroke if was not created before (only created if something to join) */ - if (new_stroke == NULL) { - new_stroke = BKE_gpencil_stroke_duplicate(stroke_a, true); + } + } + } + CTX_DATA_END; - /* if new, set current color */ - if (type == GP_STROKE_JOINCOPY) { - new_stroke->mat_nr = stroke_a->mat_nr; - } - } + /* Nothing to join. */ + if (tot_strokes < 2) { + MEM_SAFE_FREE(strokes_list); + return OPERATOR_CANCELLED; + } - /* join new_stroke and stroke B. New stroke will contain all the previous data */ - gpencil_stroke_join_strokes(new_stroke, stroke_b, leave_gaps); + /* Take first stroke. */ + elem = &strokes_list[0]; + elem->used = true; - /* if join only, delete old strokes */ - if (type == GP_STROKE_JOIN) { - if (stroke_a) { - /* Calc geometry data. */ - BKE_gpencil_stroke_geometry_update(new_stroke); + /* Create a new stroke. */ + bGPDstroke *gps_new = BKE_gpencil_stroke_duplicate(elem->gps, true); + gps_new->flag &= ~GP_STROKE_CYCLIC; + BLI_insertlinkbefore(&elem->gpf->strokes, elem->gps, gps_new); - BLI_insertlinkbefore(&gpf_a->strokes, stroke_a, new_stroke); - BLI_remlink(&gpf->strokes, stroke_a); - BKE_gpencil_free_stroke(stroke_a); - stroke_a = NULL; - } - if (stroke_b) { - BLI_remlink(&gpf->strokes, stroke_b); - BKE_gpencil_free_stroke(stroke_b); - stroke_b = NULL; - } - } - } - } + /* Join all strokes until the list is completed. */ + while (true) { + int i = gpencil_get_nearest_stroke_index(strokes_list, gps_new, tot_strokes); + if (i < 0) { + break; } + elem = &strokes_list[i]; + /* Join new_stroke and stroke B. */ + gpencil_stroke_join_strokes(gps_new, elem->gps, leave_gaps); + elem->used = true; } - CTX_DATA_END; - /* add new stroke if was not added before */ - if (type == GP_STROKE_JOINCOPY) { - if (new_stroke) { - /* Add a new frame if needed */ - if (activegpl->actframe == NULL) { - activegpl->actframe = BKE_gpencil_frame_addnew(activegpl, gpf_a->framenum); - } - /* Calc geometry data. */ - BKE_gpencil_stroke_geometry_update(new_stroke); + /* Calc geometry data for new stroke. */ + BKE_gpencil_stroke_geometry_update(gps_new); - BLI_addtail(&activegpl->actframe->strokes, new_stroke); + /* If join only, delete old strokes. */ + if (type == GP_STROKE_JOIN) { + for (int i = 0; i < tot_strokes; i++) { + elem = &strokes_list[i]; + BLI_remlink(&elem->gpf->strokes, elem->gps); + BKE_gpencil_free_stroke(elem->gps); } } + /* Free memory. */ + MEM_SAFE_FREE(strokes_list); + /* notifiers */ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); @@ -4678,7 +4761,9 @@ typedef bool (*GPencilTestFn)(bGPDstroke *gps, const float diff_mat[4][4], void *user_data); -static void gpencil_cutter_dissolve(bGPDlayer *hit_layer, bGPDstroke *hit_stroke) +static void gpencil_cutter_dissolve(bGPDlayer *hit_layer, + bGPDstroke *hit_stroke, + const bool flat_caps) { bGPDspoint *pt = NULL; bGPDspoint *pt1 = NULL; @@ -4722,6 +4807,17 @@ static void gpencil_cutter_dissolve(bGPDlayer *hit_layer, bGPDstroke *hit_stroke pt->flag &= ~GP_SPOINT_TAG; } } + /* If flat caps mode check extremes. */ + if (flat_caps) { + if (hit_stroke->points[0].flag & GP_SPOINT_TAG) { + hit_stroke->caps[0] = GP_STROKE_CAP_FLAT; + } + + if (hit_stroke->points[hit_stroke->totpoints - 1].flag & GP_SPOINT_TAG) { + hit_stroke->caps[1] = GP_STROKE_CAP_FLAT; + } + } + gpencil_stroke_delete_tagged_points( hit_layer->actframe, hit_stroke, gpsn, GP_SPOINT_TAG, false, 1); } @@ -4736,6 +4832,7 @@ static int gpencil_cutter_lasso_select(bContext *C, ScrArea *area = CTX_wm_area(C); ToolSettings *ts = CTX_data_tool_settings(C); const float scale = ts->gp_sculpt.isect_threshold; + const bool flat_caps = RNA_boolean_get(op->ptr, "flat_caps"); bGPDspoint *pt; GP_SpaceConversion gsc = {NULL}; @@ -4810,7 +4907,7 @@ static int gpencil_cutter_lasso_select(bContext *C, } LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) { if (gps->flag & GP_STROKE_SELECT) { - gpencil_cutter_dissolve(gpl, gps); + gpencil_cutter_dissolve(gpl, gps, flat_caps); } } } @@ -4884,6 +4981,8 @@ void GPENCIL_OT_stroke_cutter(wmOperatorType *ot) /* properties */ WM_operator_properties_gesture_lasso(ot); + + RNA_def_boolean(ot->srna, "flat_caps", 0, "Flat Caps", ""); } bool ED_object_gpencil_exit(struct Main *bmain, Object *ob) diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c index 2e13566402b..3a3a9bde38b 100644 --- a/source/blender/editors/gpencil/gpencil_interpolate.c +++ b/source/blender/editors/gpencil/gpencil_interpolate.c @@ -220,7 +220,7 @@ static bool gpencil_interpolate_check_todo(bContext *C, bGPdata *gpd) int fFrame; /* only selected */ - if ((flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && + if ((GPENCIL_EDIT_MODE(gpd)) && (flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) { continue; } @@ -305,7 +305,7 @@ static void gpencil_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi) bool valid = true; /* only selected */ - if ((tgpi->flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && + if ((GPENCIL_EDIT_MODE(gpd)) && (tgpi->flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) { valid = false; } @@ -1023,7 +1023,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) for (gps_from = prevFrame->strokes.first; gps_from; gps_from = gps_from->next) { /* only selected */ - if ((flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && + if ((GPENCIL_EDIT_MODE(gpd)) && (flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) { continue; } diff --git a/source/blender/editors/gpencil/gpencil_mesh.c b/source/blender/editors/gpencil/gpencil_mesh.c index e4862617d12..c136ef2070e 100644 --- a/source/blender/editors/gpencil/gpencil_mesh.c +++ b/source/blender/editors/gpencil/gpencil_mesh.c @@ -25,12 +25,15 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" +#include "BLI_ghash.h" #include "BLI_math.h" +#include "DNA_anim_types.h" #include "DNA_gpencil_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" +#include "BKE_anim_data.h" #include "BKE_context.h" #include "BKE_duplilist.h" #include "BKE_global.h" @@ -86,6 +89,35 @@ typedef struct GpBakeOb { Object *ob; } GpBakeOb; +/* Get list of keyframes used by selected objects. */ +static void animdata_keyframe_list_get(ListBase *ob_list, + const bool only_selected, + GHash *r_keyframes) +{ + /* Loop all objects to get the list of keyframes used. */ + LISTBASE_FOREACH (GpBakeOb *, elem, ob_list) { + Object *ob = elem->ob; + AnimData *adt = BKE_animdata_from_id(&ob->id); + if ((adt == NULL) || (adt->action == NULL)) { + continue; + } + LISTBASE_FOREACH (FCurve *, fcurve, &adt->action->curves) { + int i; + BezTriple *bezt; + for (i = 0, bezt = fcurve->bezt; i < fcurve->totvert; i++, bezt++) { + /* Keyframe number is x value of point. */ + if ((bezt->f2 & SELECT) || (!only_selected)) { + /* Insert only one key for each keyframe number. */ + int key = (int)bezt->vec[1][0]; + if (!BLI_ghash_haskey(r_keyframes, POINTER_FROM_INT(key))) { + BLI_ghash_insert(r_keyframes, POINTER_FROM_INT(key), POINTER_FROM_INT(key)); + } + } + } + } + } +} + static void gpencil_bake_duplilist(Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *list) { GpBakeOb *elem = NULL; @@ -161,13 +193,13 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op) View3D *v3d = CTX_wm_view3d(C); Object *ob_gpencil = NULL; - ListBase list = {NULL, NULL}; - gpencil_bake_ob_list(C, depsgraph, scene, &list); + ListBase ob_selected_list = {NULL, NULL}; + gpencil_bake_ob_list(C, depsgraph, scene, &ob_selected_list); /* Cannot check this in poll because the active object changes. */ - if (list.first == NULL) { + if (ob_selected_list.first == NULL) { BKE_report(op->reports, RPT_INFO, "No valid object selected"); - gpencil_bake_free_ob_list(&list); + gpencil_bake_free_ob_list(&ob_selected_list); return OPERATOR_CANCELLED; } @@ -186,29 +218,20 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op) const int thickness = RNA_int_get(op->ptr, "thickness"); const bool use_seams = RNA_boolean_get(op->ptr, "seams"); const bool use_faces = RNA_boolean_get(op->ptr, "faces"); + const bool only_selected = RNA_boolean_get(op->ptr, "only_selected"); const float offset = RNA_float_get(op->ptr, "offset"); const int frame_offset = RNA_int_get(op->ptr, "frame_target") - frame_start; - char target[64]; - RNA_string_get(op->ptr, "target", target); const int project_type = RNA_enum_get(op->ptr, "project_type"); + ob_gpencil = (Object *)RNA_pointer_get(op->ptr, "target").data; /* Create a new grease pencil object in origin. */ bool newob = false; - if (STREQ(target, "*NEW")) { + if (ob_gpencil == NULL) { ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0; const float loc[3] = {0.0f, 0.0f, 0.0f}; ob_gpencil = ED_gpencil_add_object(C, loc, local_view_bits); newob = true; } - else { - ob_gpencil = BLI_findstring(&bmain->objects, target, offsetof(ID, name) + 2); - } - - if ((ob_gpencil == NULL) || (ob_gpencil->type != OB_GPENCIL)) { - BKE_report(op->reports, RPT_ERROR, "Target grease pencil object not valid"); - gpencil_bake_free_ob_list(&list); - return OPERATOR_CANCELLED; - } bGPdata *gpd = (bGPdata *)ob_gpencil->data; gpd->draw_mode = (project_type == GP_REPROJECT_KEEP) ? GP_DRAWMODE_3D : GP_DRAWMODE_2D; @@ -237,6 +260,13 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op) /* Loop all frame range. */ int oldframe = (int)DEG_get_ctime(depsgraph); int key = -1; + + /* Get list of keyframes. */ + GHash *keyframe_list = BLI_ghash_int_new(__func__); + if (only_selected) { + animdata_keyframe_list_get(&ob_selected_list, only_selected, keyframe_list); + } + for (int i = frame_start; i < frame_end + 1; i++) { key++; /* Jump if not step limit but include last frame always. */ @@ -244,12 +274,17 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op) continue; } + /* Check if frame is in the list of frames to be exported. */ + if ((only_selected) && (!BLI_ghash_haskey(keyframe_list, POINTER_FROM_INT(i)))) { + continue; + } + /* Move scene to new frame. */ CFRA = i; BKE_scene_graph_update_for_newframe(depsgraph); /* Loop all objects in the list. */ - LISTBASE_FOREACH (GpBakeOb *, elem, &list) { + LISTBASE_FOREACH (GpBakeOb *, elem, &ob_selected_list) { Object *ob_eval = (Object *)DEG_get_evaluated_object(depsgraph, elem->ob); /* Generate strokes. */ @@ -270,13 +305,14 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op) if (project_type != GP_REPROJECT_KEEP) { LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { bGPDframe *gpf = gpl->actframe; - if (gpf != NULL) { - LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { - if ((gps->flag & GP_STROKE_TAG) == 0) { - ED_gpencil_stroke_reproject( - depsgraph, &gsc, sctx, gpl, gpf, gps, project_type, false); - gps->flag |= GP_STROKE_TAG; - } + if (gpf == NULL) { + continue; + } + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + if ((gps->flag & GP_STROKE_TAG) == 0) { + ED_gpencil_stroke_reproject( + depsgraph, &gsc, sctx, gpl, gpf, gps, project_type, false); + gps->flag |= GP_STROKE_TAG; } } } @@ -314,10 +350,14 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op) } /* Free memory. */ - gpencil_bake_free_ob_list(&list); + gpencil_bake_free_ob_list(&ob_selected_list); if (sctx != NULL) { ED_transform_snap_object_context_destroy(sctx); } + /* Free temp hash table. */ + if (keyframe_list != NULL) { + BLI_ghash_free(keyframe_list, NULL, NULL); + } /* notifiers */ if (newob) { @@ -334,6 +374,19 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static int gpencil_bake_mesh_animation_invoke(bContext *C, + wmOperator *op, + const wmEvent *UNUSED(event)) +{ + /* Show popup dialog to allow editing. */ + /* FIXME: hard-coded dimensions here are just arbitrary. */ + return WM_operator_props_dialog_popup(C, op, 250); +} + +static bool rna_GPencil_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value) +{ + return ((Object *)value.owner_id)->type == OB_GPENCIL; +} void GPENCIL_OT_bake_mesh_animation(wmOperatorType *ot) { static const EnumPropertyItem reproject_type[] = { @@ -363,6 +416,7 @@ void GPENCIL_OT_bake_mesh_animation(wmOperatorType *ot) ot->description = "Bake Mesh Animation to Grease Pencil strokes"; /* callbacks */ + ot->invoke = gpencil_bake_mesh_animation_invoke; ot->exec = gpencil_bake_mesh_animation_exec; ot->poll = gpencil_bake_mesh_animation_poll; @@ -370,7 +424,15 @@ void GPENCIL_OT_bake_mesh_animation(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - ot->prop = RNA_def_int( + ot->prop = RNA_def_pointer_runtime(ot->srna, + "target", + &RNA_Object, + "Target Object", + "Target grease pencil object. Leave empty for new object"); + RNA_def_property_poll_runtime(ot->prop, rna_GPencil_object_poll); + RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); + + prop = RNA_def_int( ot->srna, "frame_start", 1, 1, 100000, "Start Frame", "The start frame", 1, 100000); prop = RNA_def_int( @@ -379,6 +441,8 @@ void GPENCIL_OT_bake_mesh_animation(wmOperatorType *ot) prop = RNA_def_int(ot->srna, "step", 1, 1, 100, "Step", "Step between generated frames", 1, 100); + RNA_def_int(ot->srna, "thickness", 1, 1, 100, "Thickness", "", 1, 100); + prop = RNA_def_float_rotation(ot->srna, "angle", 0, @@ -391,18 +455,22 @@ void GPENCIL_OT_bake_mesh_animation(wmOperatorType *ot) DEG2RADF(180.0f)); RNA_def_property_float_default(prop, DEG2RADF(70.0f)); - RNA_def_int(ot->srna, "thickness", 1, 1, 100, "Thickness", "", 1, 100); + RNA_def_float_distance(ot->srna, + "offset", + 0.001f, + 0.0, + 100.0, + "Stroke Offset", + "Offset strokes from fill", + 0.0, + 100.00); + RNA_def_boolean(ot->srna, "seams", 0, "Only Seam Edges", "Convert only seam edges"); RNA_def_boolean(ot->srna, "faces", 1, "Export Faces", "Export faces as filled strokes"); - RNA_def_float_distance( - ot->srna, "offset", 0.001f, 0.0, 100.0, "Offset", "Offset strokes from fill", 0.0, 100.00); - RNA_def_int(ot->srna, "frame_target", 1, 1, 100000, "Frame Target", "", 1, 100000); - RNA_def_string(ot->srna, - "target", - "*NEW", - 64, - "Target Object", - "Target grease pencil object name. Leave empty for new object"); + RNA_def_boolean( + ot->srna, "only_selected", 0, "Only Selected Keyframes", "Convert only selected keyframes"); + RNA_def_int( + ot->srna, "frame_target", 1, 1, 100000, "Target Frame", "Destination frame", 1, 100000); RNA_def_enum(ot->srna, "project_type", reproject_type, GP_REPROJECT_VIEW, "Projection Type", ""); } diff --git a/source/blender/editors/gpencil/gpencil_trace.h b/source/blender/editors/gpencil/gpencil_trace.h index 3adde7651cd..85eb4e0609f 100644 --- a/source/blender/editors/gpencil/gpencil_trace.h +++ b/source/blender/editors/gpencil/gpencil_trace.h @@ -56,6 +56,10 @@ struct bGPDframe; #define BM_INV(bm, x, y) (bm_safe(bm, x, y) ? BM_UINV(bm, x, y) : 0) #define BM_PUT(bm, x, y, b) (bm_safe(bm, x, y) ? BM_UPUT(bm, x, y, b) : 0) +/* Trace modes */ +#define GPENCIL_TRACE_MODE_SINGLE 0 +#define GPENCIL_TRACE_MODE_SEQUENCE 1 + void ED_gpencil_trace_bitmap_print(FILE *f, const potrace_bitmap_t *bm); potrace_bitmap_t *ED_gpencil_trace_bitmap_new(int32_t w, int32_t h); diff --git a/source/blender/editors/gpencil/gpencil_trace_ops.c b/source/blender/editors/gpencil/gpencil_trace_ops.c index 4391abee5a1..2d04c31e60d 100644 --- a/source/blender/editors/gpencil/gpencil_trace_ops.c +++ b/source/blender/editors/gpencil/gpencil_trace_ops.c @@ -35,8 +35,10 @@ #include "BKE_context.h" #include "BKE_duplilist.h" +#include "BKE_global.h" #include "BKE_gpencil.h" #include "BKE_image.h" +#include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_object.h" @@ -45,11 +47,15 @@ #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" +#include "UI_interface.h" +#include "UI_resources.h" + #include "WM_api.h" #include "WM_types.h" #include "RNA_access.h" #include "RNA_define.h" +#include "RNA_enum_types.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -61,34 +67,50 @@ #include "gpencil_trace.h" #include "potracelib.h" +typedef struct TraceJob { + /* from wmJob */ + struct Object *owner; + short *stop, *do_update; + float *progress; + + bContext *C; + wmWindowManager *wm; + Main *bmain; + Scene *scene; + View3D *v3d; + Base *base_active; + Object *ob_active; + Image *image; + Object *ob_gpencil; + bGPdata *gpd; + bGPDlayer *gpl; + + bool was_ob_created; + + int32_t frame_target; + float threshold; + float scale; + float sample; + int32_t resolution; + int32_t thickness; + int32_t turnpolicy; + int32_t mode; + + bool success; + bool was_canceled; +} TraceJob; + /** * Trace a image. - * \param C: Context - * \param op: Operator - * \param ob: Grease pencil object, can be NULL - * \param ima: Image - * \param gpf: Destination frame + * \param ibuf: Image buffer. + * \param gpf: Destination frame. */ -static bool gpencil_trace_image( - bContext *C, wmOperator *op, Object *ob, Image *ima, bGPDframe *gpf) +static bool gpencil_trace_image(TraceJob *trace_job, ImBuf *ibuf, bGPDframe *gpf) { - Main *bmain = CTX_data_main(C); - potrace_bitmap_t *bm = NULL; potrace_param_t *param = NULL; potrace_state_t *st = NULL; - const float threshold = RNA_float_get(op->ptr, "threshold"); - const float scale = RNA_float_get(op->ptr, "scale"); - const float sample = RNA_float_get(op->ptr, "sample"); - const int32_t resolution = RNA_int_get(op->ptr, "resolution"); - const int32_t thickness = RNA_int_get(op->ptr, "thickness"); - const int32_t turnpolicy = RNA_enum_get(op->ptr, "turnpolicy"); - - ImBuf *ibuf; - void *lock; - ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); - /* Create an empty BW bitmap. */ bm = ED_gpencil_trace_bitmap_new(ibuf->x, ibuf->y); if (!bm) { @@ -101,10 +123,10 @@ static bool gpencil_trace_image( return false; } param->turdsize = 0; - param->turnpolicy = turnpolicy; + param->turnpolicy = trace_job->turnpolicy; /* Load BW bitmap with image. */ - ED_gpencil_trace_image_to_bitmap(ibuf, bm, threshold); + ED_gpencil_trace_image_to_bitmap(ibuf, bm, trace_job->threshold); /* Trace the bitmap. */ st = potrace_trace(param, bm); @@ -128,23 +150,26 @@ static bool gpencil_trace_image( * Really, there isn't documented in Potrace about how the scale is calculated, * but after doing a lot of tests, it looks is using a VGA resolution (640) as a base. * Maybe there are others ways to get the right scale conversion, but this solution works. */ - float scale_potrace = scale * (640.0f / (float)ibuf->x) * ((float)ibuf->x / (float)ibuf->y); + float scale_potrace = trace_job->scale * (640.0f / (float)ibuf->x) * + ((float)ibuf->x / (float)ibuf->y); if (ibuf->x > ibuf->y) { scale_potrace *= (float)ibuf->y / (float)ibuf->x; } - ED_gpencil_trace_data_to_strokes( - bmain, st, ob, gpf, offset, scale_potrace, sample, resolution, thickness); + ED_gpencil_trace_data_to_strokes(trace_job->bmain, + st, + trace_job->ob_gpencil, + gpf, + offset, + scale_potrace, + trace_job->sample, + trace_job->resolution, + trace_job->thickness); /* Free memory. */ potrace_state_free(st); potrace_param_free(param); - /* Release ibuf. */ - if (ibuf) { - BKE_image_release_ibuf(ima, ibuf, lock); - } - return true; } @@ -157,68 +182,192 @@ static bool gpencil_trace_image_poll(bContext *C) return false; } + Image *image = (Image *)ob->data; + if (!ELEM(image->source, IMA_SRC_FILE, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) { + CTX_wm_operator_poll_msg_set(C, "No valid image format selected"); + return false; + } + return true; } -static int gpencil_trace_image_exec(bContext *C, wmOperator *op) +static void trace_initialize_job_data(TraceJob *trace_job) { - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - View3D *v3d = CTX_wm_view3d(C); - Base *base_active = CTX_data_active_base(C); - Object *ob_active = base_active->object; - Image *image = (Image *)ob_active->data; - bool ob_created = false; - - const int32_t frame_target = CFRA; - Object *ob_gpencil = (Object *)RNA_pointer_get(op->ptr, "target").data; - /* Create a new grease pencil object. */ - if (ob_gpencil == NULL) { - ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0; - ob_gpencil = ED_gpencil_add_object(C, ob_active->loc, local_view_bits); + if (trace_job->ob_gpencil == NULL) { + ushort local_view_bits = (trace_job->v3d && trace_job->v3d->localvd) ? + trace_job->v3d->local_view_uuid : + 0; + trace_job->ob_gpencil = ED_gpencil_add_object( + trace_job->C, trace_job->ob_active->loc, local_view_bits); /* Apply image rotation. */ - copy_v3_v3(ob_gpencil->rot, ob_active->rot); + copy_v3_v3(trace_job->ob_gpencil->rot, trace_job->ob_active->rot); /* Grease pencil is rotated 90 degrees in X axis by default. */ - ob_gpencil->rot[0] -= DEG2RADF(90.0f); - ob_created = true; + trace_job->ob_gpencil->rot[0] -= DEG2RADF(90.0f); + trace_job->was_ob_created = true; /* Apply image Scale. */ - copy_v3_v3(ob_gpencil->scale, ob_active->scale); + copy_v3_v3(trace_job->ob_gpencil->scale, trace_job->ob_active->scale); + /* The default display size of the image is 5.0 and this is used as scale = 1.0. */ + mul_v3_fl(trace_job->ob_gpencil->scale, trace_job->ob_active->empty_drawsize / 5.0f); } - if ((ob_gpencil == NULL) || (ob_gpencil->type != OB_GPENCIL)) { - BKE_report(op->reports, RPT_ERROR, "Target grease pencil object not valid"); - return OPERATOR_CANCELLED; + /* Create Layer. */ + trace_job->gpd = (bGPdata *)trace_job->ob_gpencil->data; + trace_job->gpl = BKE_gpencil_layer_active_get(trace_job->gpd); + if (trace_job->gpl == NULL) { + trace_job->gpl = BKE_gpencil_layer_addnew(trace_job->gpd, DATA_("Trace"), true); } +} - /* Create Layer. */ - bGPdata *gpd = (bGPdata *)ob_gpencil->data; - bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); - if (gpl == NULL) { - gpl = BKE_gpencil_layer_addnew(gpd, DATA_("Trace"), true); +static void trace_start_job(void *customdata, short *stop, short *do_update, float *progress) +{ + TraceJob *trace_job = customdata; + + trace_job->stop = stop; + trace_job->do_update = do_update; + trace_job->progress = progress; + trace_job->was_canceled = false; + + G.is_break = false; + + /* Single Image. */ + + if ((trace_job->image->source == IMA_SRC_FILE) || + (trace_job->mode == GPENCIL_TRACE_MODE_SINGLE)) { + void *lock; + ImBuf *ibuf = BKE_image_acquire_ibuf(trace_job->image, NULL, &lock); + if (ibuf) { + /* Create frame. */ + bGPDframe *gpf = BKE_gpencil_layer_frame_get( + trace_job->gpl, trace_job->frame_target, GP_GETFRAME_ADD_NEW); + gpencil_trace_image(trace_job, ibuf, gpf); + BKE_image_release_ibuf(trace_job->image, ibuf, lock); + *(trace_job->progress) = 1.0f; + } + } + /* Image sequence. */ + else if (trace_job->image->type == IMA_TYPE_IMAGE) { + ImageUser *iuser = trace_job->ob_active->iuser; + for (int i = 0; i < iuser->frames; i++) { + if (G.is_break) { + trace_job->was_canceled = true; + break; + } + + *(trace_job->progress) = (float)i / (float)iuser->frames; + *do_update = true; + + iuser->framenr = i + 1; + + void *lock; + ImBuf *ibuf = BKE_image_acquire_ibuf(trace_job->image, iuser, &lock); + if (ibuf) { + /* Create frame. */ + bGPDframe *gpf = BKE_gpencil_layer_frame_get( + trace_job->gpl, trace_job->frame_target + i, GP_GETFRAME_ADD_NEW); + gpencil_trace_image(trace_job, ibuf, gpf); + + BKE_image_release_ibuf(trace_job->image, ibuf, lock); + } + } } - /* Create frame. */ - bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, frame_target, GP_GETFRAME_ADD_NEW); - gpencil_trace_image(C, op, ob_gpencil, image, gpf); + trace_job->success = !trace_job->was_canceled; + *do_update = true; + *stop = 0; +} - /* Back to active base. */ - ED_object_base_activate(C, base_active); +static void trace_end_job(void *customdata) +{ + TraceJob *trace_job = customdata; + + /* If canceled, delete all previously created object and data-block. */ + if ((trace_job->was_canceled) && (trace_job->was_ob_created) && (trace_job->ob_gpencil)) { + bGPdata *gpd = trace_job->ob_gpencil->data; + BKE_id_delete(trace_job->bmain, &trace_job->ob_gpencil->id); + BKE_id_delete(trace_job->bmain, &gpd->id); + } - /* notifiers */ - if (ob_created) { - DEG_relations_tag_update(bmain); + if (trace_job->success) { + DEG_relations_tag_update(trace_job->bmain); + + DEG_id_tag_update(&trace_job->scene->id, ID_RECALC_SELECT); + DEG_id_tag_update(&trace_job->gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); + + WM_main_add_notifier(NC_OBJECT | NA_ADDED, NULL); + WM_main_add_notifier(NC_SCENE | ND_OB_ACTIVE, trace_job->scene); } +} - DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); - DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); +static void trace_free_job(void *customdata) +{ + TraceJob *tj = customdata; + MEM_freeN(tj); +} - WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL); - WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); +static int gpencil_trace_image_exec(bContext *C, wmOperator *op) +{ + TraceJob *job = MEM_mallocN(sizeof(TraceJob), "TraceJob"); + job->C = C; + job->owner = CTX_data_active_object(C); + job->wm = CTX_wm_manager(C); + job->bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + job->scene = scene; + job->v3d = CTX_wm_view3d(C); + job->base_active = CTX_data_active_base(C); + job->ob_active = job->base_active->object; + job->image = (Image *)job->ob_active->data; + job->frame_target = CFRA; + + job->ob_gpencil = (Object *)RNA_pointer_get(op->ptr, "target").data; + job->was_ob_created = false; + + job->threshold = RNA_float_get(op->ptr, "threshold"); + job->scale = RNA_float_get(op->ptr, "scale"); + job->sample = RNA_float_get(op->ptr, "sample"); + job->resolution = RNA_int_get(op->ptr, "resolution"); + job->thickness = RNA_int_get(op->ptr, "thickness"); + job->turnpolicy = RNA_enum_get(op->ptr, "turnpolicy"); + job->mode = RNA_enum_get(op->ptr, "mode"); + + trace_initialize_job_data(job); + + /* Back to active base. */ + ED_object_base_activate(job->C, job->base_active); + + if (job->image->source == IMA_SRC_FILE) { + short stop = 0, do_update = true; + float progress; + trace_start_job(job, &stop, &do_update, &progress); + trace_end_job(job); + trace_free_job(job); + } + else { + wmJob *wm_job = WM_jobs_get(job->wm, + CTX_wm_window(C), + job->scene, + "Trace Image", + WM_JOB_PROGRESS, + WM_JOB_TYPE_TRACE_IMAGE); + + WM_jobs_customdata_set(wm_job, job, trace_free_job); + WM_jobs_timer(wm_job, 0.1, NC_GEOM | ND_DATA, NC_GEOM | ND_DATA); + WM_jobs_callbacks(wm_job, trace_start_job, NULL, NULL, trace_end_job); + + WM_jobs_start(CTX_wm_manager(C), wm_job); + } return OPERATOR_FINISHED; } +static int gpencil_trace_image_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + /* Show popup dialog to allow editing. */ + /* FIXME: hard-coded dimensions here are just arbitrary. */ + return WM_operator_props_dialog_popup(C, op, 250); +} + static bool rna_GPencil_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value) { return ((Object *)value.owner_id)->type == OB_GPENCIL; @@ -257,12 +406,19 @@ void GPENCIL_OT_trace_image(wmOperatorType *ot) {0, NULL, 0, NULL, NULL}, }; + static const EnumPropertyItem trace_modes[] = { + {GPENCIL_TRACE_MODE_SINGLE, "SINGLE", 0, "Single", "Trace the current frame of the image"}, + {GPENCIL_TRACE_MODE_SEQUENCE, "SEQUENCE", 0, "Sequence", "Trace full sequence"}, + {0, NULL, 0, NULL, NULL}, + }; + /* identifiers */ ot->name = "Trace Image to Grease Pencil"; ot->idname = "GPENCIL_OT_trace_image"; ot->description = "Extract Grease Pencil strokes from image"; /* callbacks */ + ot->invoke = gpencil_trace_image_invoke; ot->exec = gpencil_trace_image_exec; ot->poll = gpencil_trace_image_poll; @@ -270,9 +426,16 @@ void GPENCIL_OT_trace_image(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - prop = RNA_def_pointer_runtime(ot->srna, "target", &RNA_Object, "Target", ""); + prop = RNA_def_pointer_runtime( + ot->srna, + "target", + &RNA_Object, + "Target Object", + "Target grease pencil object name. Leave empty to create a new object"); RNA_def_property_poll_runtime(prop, rna_GPencil_object_poll); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + RNA_def_int(ot->srna, "thickness", 10, 1, 1000, "Thickness", "", 1, 1000); RNA_def_int( ot->srna, "resolution", 5, 1, 20, "Resolution", "Resolution of the generated curves", 1, 20); @@ -301,7 +464,7 @@ void GPENCIL_OT_trace_image(wmOperatorType *ot) 0.0f, 1.0f, "Color Threshold", - "Determine what is considered white and what black", + "Determine the lightness threshold above which strokes are generated", 0.0f, 1.0f); RNA_def_enum(ot->srna, @@ -310,4 +473,10 @@ void GPENCIL_OT_trace_image(wmOperatorType *ot) POTRACE_TURNPOLICY_MINORITY, "Turn Policy", "Determines how to resolve ambiguities during decomposition of bitmaps into paths"); + RNA_def_enum(ot->srna, + "mode", + trace_modes, + GPENCIL_TRACE_MODE_SINGLE, + "Mode", + "Determines if trace simple image or full sequence"); } diff --git a/source/blender/editors/include/ED_buttons.h b/source/blender/editors/include/ED_buttons.h index 5d153757900..90d3a527b0c 100644 --- a/source/blender/editors/include/ED_buttons.h +++ b/source/blender/editors/include/ED_buttons.h @@ -26,6 +26,7 @@ extern "C" { #endif +struct bContext; struct SpaceProperties; int ED_buttons_tabs_list(struct SpaceProperties *sbuts, short *context_tabs_array); @@ -35,6 +36,8 @@ void ED_buttons_search_string_set(struct SpaceProperties *sbuts, const char *val int ED_buttons_search_string_length(struct SpaceProperties *sbuts); const char *ED_buttons_search_string_get(struct SpaceProperties *sbuts); +void ED_buttons_set_context(const struct bContext *C, PointerRNA *ptr, const int context); + #ifdef __cplusplus } #endif diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h index f9b1d9cdc64..8015a665970 100644 --- a/source/blender/editors/include/ED_curve.h +++ b/source/blender/editors/include/ED_curve.h @@ -84,7 +84,7 @@ void ED_curve_editfont_load(struct Object *obedit); void ED_curve_editfont_make(struct Object *obedit); void ED_curve_editfont_free(struct Object *obedit); -void ED_text_to_object(struct bContext *C, struct Text *text, const bool split_lines); +void ED_text_to_object(struct bContext *C, const struct Text *text, const bool split_lines); void ED_curve_beztcpy(struct EditNurb *editnurb, struct BezTriple *dst, diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h index 341f97943a5..84808416074 100644 --- a/source/blender/editors/include/ED_fileselect.h +++ b/source/blender/editors/include/ED_fileselect.h @@ -35,6 +35,7 @@ struct SpaceFile; struct bContext; struct bScreen; struct uiBlock; +struct wmOperator; struct wmWindow; struct wmWindowManager; @@ -145,6 +146,9 @@ void ED_fileselect_window_params_get(const struct wmWindow *win, int win_size[2], bool *is_maximized); +struct ScrArea *ED_fileselect_handler_area_find(const struct wmWindow *win, + const struct wmOperator *file_operator); + int ED_path_extension_type(const char *path); int ED_file_extension_icon(const char *path); diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 6fdd65fdcc9..2e9b711c99a 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -160,6 +160,7 @@ extern struct EnumPropertyItem prop_clear_parent_types[]; extern struct EnumPropertyItem prop_make_parent_types[]; #endif +/* Set the object's parent, return true iff successful. */ bool ED_object_parent_set(struct ReportList *reports, const struct bContext *C, struct Scene *scene, diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index b8500ba0c37..dc1c43c0337 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -199,6 +199,7 @@ int ED_region_global_size_y(void); void ED_area_update_region_sizes(struct wmWindowManager *wm, struct wmWindow *win, struct ScrArea *area); +bool ED_area_has_shared_border(struct ScrArea *a, struct ScrArea *b); ScrArea *ED_screen_areas_iter_first(const struct wmWindow *win, const bScreen *screen); ScrArea *ED_screen_areas_iter_next(const bScreen *screen, const ScrArea *area); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index d3eb6c00f57..f64c6a42f18 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -693,7 +693,7 @@ void ED_view3d_grid_steps(const struct Scene *scene, float *r_grid_steps); float ED_view3d_grid_view_scale(struct Scene *scene, struct View3D *v3d, - struct RegionView3D *rv3d, + struct ARegion *region, const char **r_grid_unit); void ED_scene_draw_fps(const struct Scene *scene, int xoffset, int *yoffset); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index dc20e6f1813..d2f9b31cecd 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -772,6 +772,95 @@ static void ui_but_extra_icons_update_from_old_but(const uiBut *new_but, const u } /** + * Update pointers and other information in the old active button based on new information in the + * corresponding new button from the current layout pass. + * + * \param oldbut: The button from the last layout pass that will be moved to the new block. + * \param but: The newly added button with much of the up to date information, to be feed later. + * + * \note #uiBut has ownership of many of its pointers. When the button is freed all these + * pointers are freed as well, so ownership has to be moved out of \a but in order to free it. + */ +static void ui_but_update_old_active_from_new(uiBut *oldbut, uiBut *but) +{ + BLI_assert(oldbut->active); + + /* flags from the buttons we want to refresh, may want to add more here... */ + const int flag_copy = UI_BUT_REDALERT | UI_HAS_ICON; + const int drawflag_copy = 0; /* None currently. */ + + /* still stuff needs to be copied */ + oldbut->rect = but->rect; + oldbut->context = but->context; /* set by Layout */ + + /* drawing */ + oldbut->icon = but->icon; + oldbut->iconadd = but->iconadd; + oldbut->alignnr = but->alignnr; + + /* typically the same pointers, but not on undo/redo */ + /* XXX some menu buttons store button itself in but->poin. Ugly */ + if (oldbut->poin != (char *)oldbut) { + SWAP(char *, oldbut->poin, but->poin); + SWAP(void *, oldbut->func_argN, but->func_argN); + } + + /* Move tooltip from new to old. */ + SWAP(uiButToolTipFunc, oldbut->tip_func, but->tip_func); + SWAP(void *, oldbut->tip_argN, but->tip_argN); + + oldbut->flag = (oldbut->flag & ~flag_copy) | (but->flag & flag_copy); + oldbut->drawflag = (oldbut->drawflag & ~drawflag_copy) | (but->drawflag & drawflag_copy); + + ui_but_extra_icons_update_from_old_but(but, oldbut); + SWAP(ListBase, but->extra_op_icons, oldbut->extra_op_icons); + + if (oldbut->type == UI_BTYPE_SEARCH_MENU) { + uiButSearch *search_oldbut = (uiButSearch *)oldbut, *search_but = (uiButSearch *)but; + + SWAP(uiButSearchArgFreeFn, search_oldbut->arg_free_fn, search_but->arg_free_fn); + SWAP(void *, search_oldbut->arg, search_but->arg); + } + + /* copy hardmin for list rows to prevent 'sticking' highlight to mouse position + * when scrolling without moving mouse (see T28432) */ + if (ELEM(oldbut->type, UI_BTYPE_ROW, UI_BTYPE_LISTROW)) { + oldbut->hardmax = but->hardmax; + } + + if (oldbut->type == UI_BTYPE_PROGRESS_BAR) { + uiButProgressbar *progress_oldbut = (uiButProgressbar *)oldbut; + uiButProgressbar *progress_but = (uiButProgressbar *)but; + progress_oldbut->progress = progress_but->progress; + } + + /* move/copy string from the new button to the old */ + /* needed for alt+mouse wheel over enums */ + if (but->str != but->strdata) { + if (oldbut->str != oldbut->strdata) { + SWAP(char *, but->str, oldbut->str); + } + else { + oldbut->str = but->str; + but->str = but->strdata; + } + } + else { + if (oldbut->str != oldbut->strdata) { + MEM_freeN(oldbut->str); + oldbut->str = oldbut->strdata; + } + BLI_strncpy(oldbut->strdata, but->strdata, sizeof(oldbut->strdata)); + } + + if (but->dragpoin && (but->dragflag & UI_BUT_DRAGPOIN_FREE)) { + SWAP(void *, but->dragpoin, oldbut->dragpoin); + } + + /* note: if layout hasn't been applied yet, it uses old button pointers... */ +} + +/** * \return true when \a but_p is set (only done for active buttons). */ static bool ui_but_update_from_old_block(const bContext *C, @@ -779,57 +868,36 @@ static bool ui_but_update_from_old_block(const bContext *C, uiBut **but_p, uiBut **but_old_p) { - const int drawflag_copy = 0; /* None currently. */ - uiBlock *oldblock = block->oldblock; - uiBut *oldbut = NULL, *but = *but_p; - bool found_active = false; + uiBut *but = *but_p; #if 0 - /* simple/stupid - search every time */ - oldbut = ui_but_find_old(oldblock, but); - (void)but_old_p; + /* Simple method - search every time. Keep this for easy testing of the "fast path." */ + uiBut *oldbut = ui_but_find_old(oldblock, but); + UNUSED_VARS(but_old_p); #else BLI_assert(*but_old_p == NULL || BLI_findindex(&oldblock->buttons, *but_old_p) != -1); - /* Fast-path - avoid loop-in-loop, calling #ui_but_find_old - * as long as old/new buttons are aligned. */ + /* As long as old and new buttons are aligned, avoid loop-in-loop (calling #ui_but_find_old). */ + uiBut *oldbut; if (LIKELY(*but_old_p && ui_but_equals_old(but, *but_old_p))) { oldbut = *but_old_p; } else { - /* fallback to block search */ + /* Fallback to block search. */ oldbut = ui_but_find_old(oldblock, but); } (*but_old_p) = oldbut ? oldbut->next : NULL; #endif + bool found_active = false; + if (!oldbut) { - return found_active; + return false; } if (oldbut->active) { - /* flags from the buttons we want to refresh, may want to add more here... */ - const int flag_copy = UI_BUT_REDALERT | UI_HAS_ICON; - - found_active = true; - -#if 0 - but->flag = oldbut->flag; - but->active = oldbut->active; - but->pos = oldbut->pos; - but->ofs = oldbut->ofs; - but->editstr = oldbut->editstr; - but->editval = oldbut->editval; - but->editvec = oldbut->editvec; - but->selsta = oldbut->selsta; - but->selend = oldbut->selend; - but->softmin = oldbut->softmin; - but->softmax = oldbut->softmax; - oldbut->active = NULL; -#endif - - /* move button over from oldblock to new block */ + /* Move button over from oldblock to new block. */ BLI_remlink(&oldblock->buttons, oldbut); BLI_insertlinkafter(&block->buttons, but, oldbut); /* Add the old button to the button groups in the new block. */ @@ -837,82 +905,16 @@ static bool ui_but_update_from_old_block(const bContext *C, oldbut->block = block; *but_p = oldbut; - /* still stuff needs to be copied */ - oldbut->rect = but->rect; - oldbut->context = but->context; /* set by Layout */ - - /* drawing */ - oldbut->icon = but->icon; - oldbut->iconadd = but->iconadd; - oldbut->alignnr = but->alignnr; - - /* typically the same pointers, but not on undo/redo */ - /* XXX some menu buttons store button itself in but->poin. Ugly */ - if (oldbut->poin != (char *)oldbut) { - SWAP(char *, oldbut->poin, but->poin); - SWAP(void *, oldbut->func_argN, but->func_argN); - } - - /* Move tooltip from new to old. */ - SWAP(uiButToolTipFunc, oldbut->tip_func, but->tip_func); - SWAP(void *, oldbut->tip_argN, but->tip_argN); - - oldbut->flag = (oldbut->flag & ~flag_copy) | (but->flag & flag_copy); - oldbut->drawflag = (oldbut->drawflag & ~drawflag_copy) | (but->drawflag & drawflag_copy); - - ui_but_extra_icons_update_from_old_but(but, oldbut); - SWAP(ListBase, but->extra_op_icons, oldbut->extra_op_icons); - - if (oldbut->type == UI_BTYPE_SEARCH_MENU) { - uiButSearch *search_oldbut = (uiButSearch *)oldbut, *search_but = (uiButSearch *)but; - - SWAP(uiButSearchArgFreeFn, search_oldbut->arg_free_fn, search_but->arg_free_fn); - SWAP(void *, search_oldbut->arg, search_but->arg); - } - - /* copy hardmin for list rows to prevent 'sticking' highlight to mouse position - * when scrolling without moving mouse (see T28432) */ - if (ELEM(oldbut->type, UI_BTYPE_ROW, UI_BTYPE_LISTROW)) { - oldbut->hardmax = but->hardmax; - } - - if (oldbut->type == UI_BTYPE_PROGRESS_BAR) { - uiButProgressbar *progress_oldbut = (uiButProgressbar *)oldbut; - uiButProgressbar *progress_but = (uiButProgressbar *)but; - progress_oldbut->progress = progress_but->progress; - } + ui_but_update_old_active_from_new(oldbut, but); if (!BLI_listbase_is_empty(&block->butstore)) { UI_butstore_register_update(block, oldbut, but); } - /* move/copy string from the new button to the old */ - /* needed for alt+mouse wheel over enums */ - if (but->str != but->strdata) { - if (oldbut->str != oldbut->strdata) { - SWAP(char *, but->str, oldbut->str); - } - else { - oldbut->str = but->str; - but->str = but->strdata; - } - } - else { - if (oldbut->str != oldbut->strdata) { - MEM_freeN(oldbut->str); - oldbut->str = oldbut->strdata; - } - BLI_strncpy(oldbut->strdata, but->strdata, sizeof(oldbut->strdata)); - } - - if (but->dragpoin && (but->dragflag & UI_BUT_DRAGPOIN_FREE)) { - SWAP(void *, but->dragpoin, oldbut->dragpoin); - } - BLI_remlink(&block->buttons, but); ui_but_free(C, but); - /* note: if layout hasn't been applied yet, it uses old button pointers... */ + found_active = true; } else { const int flag_copy = UI_BUT_DRAG_MULTI; @@ -928,9 +930,11 @@ static bool ui_but_update_from_old_block(const bContext *C, return found_active; } -/* needed for temporarily rename buttons, such as in outliner or file-select, - * they should keep calling uiDefButs to keep them alive */ -/* returns 0 when button removed */ +/** + * Needed for temporarily rename buttons, such as in outliner or file-select, + * they should keep calling #uiDefBut to keep them alive. + * \return false when button removed. + */ bool UI_but_active_only_ex( const bContext *C, ARegion *region, uiBlock *block, uiBut *but, const bool remove_on_failure) { @@ -1581,6 +1585,7 @@ void ui_but_override_flag(Main *bmain, uiBut *but) } } +/* -------------------------------------------------------------------- */ /** \name Button Extra Operator Icons * * Extra icons are shown on the right hand side of buttons. They can be clicked to invoke custom diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c index a740a152f1c..4d0e1584156 100644 --- a/source/blender/editors/interface/interface_eyedropper.c +++ b/source/blender/editors/interface/interface_eyedropper.c @@ -78,7 +78,7 @@ wmKeyMap *eyedropper_colorband_modal_keymap(wmKeyConfig *keyconf) { static const EnumPropertyItem modal_items_point[] = { {EYE_MODAL_POINT_CANCEL, "CANCEL", 0, "Cancel", ""}, - {EYE_MODAL_POINT_SAMPLE, "SAMPLE_SAMPLE", 0, "Sample a point", ""}, + {EYE_MODAL_POINT_SAMPLE, "SAMPLE_SAMPLE", 0, "Sample a Point", ""}, {EYE_MODAL_POINT_CONFIRM, "SAMPLE_CONFIRM", 0, "Confirm Sampling", ""}, {EYE_MODAL_POINT_RESET, "SAMPLE_RESET", 0, "Reset Sampling", ""}, {0, NULL, 0, NULL, NULL}, diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index b77f8bf3b63..ac31148340a 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -4550,10 +4550,22 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons button_activate_state(C, but, BUTTON_STATE_EXIT); return WM_UI_HANDLER_BREAK; } - if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) { - /* Support alt+wheel on expanded enum rows */ + if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) { + /* Support ctrl-wheel to cycle values on expanded enum rows. */ if (but->type == UI_BTYPE_ROW) { - const int direction = (event->type == WHEELDOWNMOUSE) ? -1 : 1; + int type = event->type; + int val = event->val; + + /* Convert pan to scroll-wheel. */ + if (type == MOUSEPAN) { + ui_pan_to_scroll(event, &type, &val); + + if (type == MOUSEPAN) { + return WM_UI_HANDLER_BREAK; + } + } + + const int direction = (type == WHEELDOWNMOUSE) ? -1 : 1; uiBut *but_select = ui_but_find_select_in_enum(but, direction); if (but_select) { uiBut *but_other = (direction == -1) ? but_select->next : but_select->prev; @@ -5648,8 +5660,20 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co return WM_UI_HANDLER_BREAK; } if (ui_but_supports_cycling(but)) { - if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) { - const int direction = (event->type == WHEELDOWNMOUSE) ? 1 : -1; + if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) { + int type = event->type; + int val = event->val; + + /* Convert pan to scroll-wheel. */ + if (type == MOUSEPAN) { + ui_pan_to_scroll(event, &type, &val); + + if (type == MOUSEPAN) { + return WM_UI_HANDLER_BREAK; + } + } + + const int direction = (type == WHEELDOWNMOUSE) ? 1 : -1; data->value = ui_but_menu_step(but, direction); @@ -7693,6 +7717,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * } #ifdef USE_DRAG_MULTINUM + data = but->active; if (data) { if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) || /* if we started dragging, progress on any event */ diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 01eb8f95d18..1a8b1ae0a1a 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -995,8 +995,9 @@ void ui_draw_preview_item( #define UI_TEXT_MARGIN_X 0.4f #define UI_POPUP_MARGIN (UI_DPI_FAC * 12) -/* margin at top of screen for popups */ -#define UI_POPUP_MENU_TOP (int)(8 * UI_DPI_FAC) +/* Margin at top of screen for popups. Note this value must be sufficient + to draw a popover arrow to avoid cropping it. */ +#define UI_POPUP_MENU_TOP (int)(10 * UI_DPI_FAC) #define UI_PIXEL_AA_JITTER 8 extern const float ui_pixel_jitter[UI_PIXEL_AA_JITTER][2]; diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index ad260274e78..efb29fe75c3 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -964,7 +964,11 @@ static uiBut *ui_item_with_label(uiLayout *layout, UI_block_layout_set_current(block, layout); /* Only add new row if more than 1 item will be added. */ - if (name[0] || use_prop_decorate) { + if (name[0] +#ifdef UI_PROP_DECORATE + || use_prop_decorate +#endif + ) { /* Also avoid setting 'align' if possible. Set the space to zero instead as aligning a large * number of labels can end up aligning thousands of buttons when displaying key-map search (a * heavy operation), see: T78636. */ @@ -972,8 +976,8 @@ static uiBut *ui_item_with_label(uiLayout *layout, sub->space = 0; } -#ifdef UI_PROP_DECORATE if (name[0]) { +#ifdef UI_PROP_DECORATE if (use_prop_sep) { layout_prop_decorate = uiItemL_respect_property_split(layout, name, 0); } @@ -2148,7 +2152,6 @@ void uiItemFullR(uiLayout *layout, uiLayout *layout_split = uiLayoutSplit( layout_row ? layout_row : layout, UI_ITEM_PROP_SEP_DIVIDE, true); bool label_added = false; - layout_split->space = 0; uiLayout *layout_sub = uiLayoutColumn(layout_split, true); layout_sub->space = 0; @@ -3186,7 +3189,6 @@ uiPropertySplitWrapper uiItemPropertySplitWrapperCreate(uiLayout *parent_layout) uiLayout *layout_row = uiLayoutRow(parent_layout, true); uiLayout *layout_split = uiLayoutSplit(layout_row, UI_ITEM_PROP_SEP_DIVIDE, true); - layout_split->space = 0; split_wrapper.label_column = uiLayoutColumn(layout_split, true); split_wrapper.label_column->alignment = UI_LAYOUT_ALIGN_RIGHT; split_wrapper.property_row = ui_item_prop_split_layout_hack(parent_layout, layout_split); diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index bfe5dc223c8..de281724afe 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -313,7 +313,7 @@ Panel *UI_panel_add_instanced(const bContext *C, Panel *new_panel = panel_add_instanced(region, panels, panel_type, custom_data); - /* Do this after #panel_add_instatnced so all subpanels are added. */ + /* Do this after #panel_add_instatnced so all sub-panels are added. */ panel_set_expansion_from_list_data(C, new_panel); return new_panel; @@ -325,7 +325,7 @@ Panel *UI_panel_add_instanced(const bContext *C, */ void UI_list_panel_unique_str(Panel *panel, char *r_name) { - /* The panel sortorder will be unique for a specific panel type because the instanced + /* The panel sort-order will be unique for a specific panel type because the instanced * panel list is regenerated for every change in the data order / length. */ snprintf(r_name, INSTANCED_PANEL_UNIQUE_STR_LEN, "%d", panel->sortorder); } @@ -805,7 +805,7 @@ static float panel_region_offset_x_get(const ARegion *region) /** * Starting from the "block size" set in #UI_panel_end, calculate the full size - * of the panel including the subpanel headers and buttons. + * of the panel including the sub-panel headers and buttons. */ static void panel_calculate_size_recursive(ARegion *region, Panel *panel) { @@ -854,7 +854,7 @@ static void panel_calculate_size_recursive(ARegion *region, Panel *panel) void UI_panel_end(Panel *panel, int width, int height) { /* Store the size of the buttons layout in the panel. The actual panel size - * (including subpanels) is calculated in #UI_panels_end. */ + * (including sub-panels) is calculated in #UI_panels_end. */ panel->blocksizex = width; panel->blocksizey = height; } @@ -907,25 +907,22 @@ bool UI_panel_matches_search_filter(const Panel *panel) } /** - * Set the flag telling the panel to use its search result status for - * its expansion. Also activate animation if that changes the expansion. + * Set the flag telling the panel to use its search result status for its expansion. */ static void panel_set_expansion_from_seach_filter_recursive(const bContext *C, Panel *panel, - const bool use_search_closed, - const bool use_animation) + const bool use_search_closed) { /* This has to run on inactive panels that may not have a type, - * but we can prevent running on headerless panels in some cases. */ + * but we can prevent running on header-less panels in some cases. */ if (panel->type == NULL || !(panel->type->flag & PNL_NO_HEADER)) { SET_FLAG_FROM_TEST(panel->runtime_flag, use_search_closed, PANEL_USE_CLOSED_FROM_SEARCH); } LISTBASE_FOREACH (Panel *, child_panel, &panel->children) { - /* Don't check if the subpanel is active, otherwise the + /* Don't check if the sub-panel is active, otherwise the * expansion won't be reset when the parent is closed. */ - panel_set_expansion_from_seach_filter_recursive( - C, child_panel, use_search_closed, use_animation); + panel_set_expansion_from_seach_filter_recursive(C, child_panel, use_search_closed); } } @@ -934,11 +931,10 @@ static void panel_set_expansion_from_seach_filter_recursive(const bContext *C, */ static void region_panels_set_expansion_from_seach_filter(const bContext *C, ARegion *region, - const bool use_search_closed, - const bool use_animation) + const bool use_search_closed) { LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { - panel_set_expansion_from_seach_filter_recursive(C, panel, use_search_closed, use_animation); + panel_set_expansion_from_seach_filter_recursive(C, panel, use_search_closed); } set_panels_list_data_expand_flag(C, region); } @@ -960,8 +956,8 @@ static void panel_remove_invisible_layouts_recursive(Panel *panel, const Panel * } } else if (UI_panel_is_closed(panel)) { - /* If subpanels have no search results but the parent panel does, then the parent panel open - * and the subpanels will close. In that case there must be a way to hide the buttons in the + /* If sub-panels have no search results but the parent panel does, then the parent panel open + * and the sub-panels will close. In that case there must be a way to hide the buttons in the * panel but keep the header buttons. */ LISTBASE_FOREACH (uiButtonGroup *, button_group, &block->button_groups) { if (button_group->flag & UI_BUTTON_GROUP_PANEL_HEADER) { @@ -1902,10 +1898,10 @@ void UI_panels_end(const bContext *C, ARegion *region, int *r_x, int *r_y) const bool region_search_filter_active = region->flag & RGN_FLAG_SEARCH_FILTER_ACTIVE; if (properties_space_needs_realign(area, region)) { - region_panels_set_expansion_from_seach_filter(C, region, region_search_filter_active, false); + region_panels_set_expansion_from_seach_filter(C, region, region_search_filter_active); } else if (region->flag & RGN_FLAG_SEARCH_FILTER_UPDATE) { - region_panels_set_expansion_from_seach_filter(C, region, region_search_filter_active, true); + region_panels_set_expansion_from_seach_filter(C, region, region_search_filter_active); } if (region->flag & RGN_FLAG_SEARCH_FILTER_ACTIVE) { diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index d4d24b3e3c2..678dbe868e7 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -3304,7 +3304,6 @@ static void colorband_buttons_layout(uiLayout *layout, row = uiLayoutRow(split, false); uiItemR(row, &ptr, "position", 0, IFACE_("Pos"), ICON_NONE); bt = block->buttons.last; - bt->a1 = 1.0f; /* gives a bit more precision for modifying position */ UI_but_func_set(bt, colorband_update_cb, bt, coba); row = uiLayoutRow(layout, false); @@ -3336,7 +3335,6 @@ static void colorband_buttons_layout(uiLayout *layout, row = uiLayoutRow(subsplit, false); uiItemR(row, &ptr, "position", UI_ITEM_R_SLIDER, IFACE_("Pos"), ICON_NONE); bt = block->buttons.last; - bt->a1 = 1.0f; /* gives a bit more precision for modifying position */ UI_but_func_set(bt, colorband_update_cb, bt, coba); row = uiLayoutRow(split, false); @@ -5330,7 +5328,7 @@ static void ui_template_palette_menu(bContext *UNUSED(C), uiLayout *layout, void { uiLayout *row; - uiItemL(layout, IFACE_("Sort by:"), ICON_NONE); + uiItemL(layout, IFACE_("Sort By:"), ICON_NONE); row = uiLayoutRow(layout, false); uiItemEnumO_value(row, IFACE_("Hue"), ICON_NONE, "PALETTE_OT_sort", "type", 1); row = uiLayoutRow(layout, false); diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 6bc644ce5b5..1abde7cf714 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -645,10 +645,10 @@ bool UI_but_online_manual_id_from_active(const struct bContext *C, char *r_str, } /* -------------------------------------------------------------------- */ -/* Modal Button Store API */ - /** \name Button Store * + * Modal Button Store API. + * * Store for modal operators & handlers to register button pointers * which are maintained while drawing or NULL when removed. * diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 49760b99d2e..e2250c764b1 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -2426,19 +2426,23 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle, } } else if (but->drawflag & UI_BUT_TEXT_LEFT) { - - /* Reduce the left padding for labels without an icon. */ - if ((but->type == UI_BTYPE_LABEL) && !(but->flag & UI_HAS_ICON) && - !ui_block_is_menu(but->block)) { - text_padding /= 2; - } - rect->xmin += text_padding; } else if (but->drawflag & UI_BUT_TEXT_RIGHT) { rect->xmax -= text_padding; } } + else { + /* In case a separate text label and some other button are placed under each other, + and the outline of the button does not contrast with the background. + Add an offset (thickness of the outline) so that the text does not stick out visually. */ + if (but->drawflag & UI_BUT_TEXT_LEFT) { + rect->xmin += U.pixelsize; + } + else if (but->drawflag & UI_BUT_TEXT_RIGHT) { + rect->xmax -= U.pixelsize; + } + } /* Menu contains sub-menu items with triangle icon on their right. Shortcut * strings should be drawn with some padding to the right then. */ @@ -4053,7 +4057,7 @@ static void widget_optionbut(uiWidgetColors *wcol, } /* smaller */ - delta = 1 + BLI_rcti_size_y(&recttemp) / 8; + delta = (BLI_rcti_size_y(&recttemp) - 2 * U.pixelsize) / 6; BLI_rcti_resize( &recttemp, BLI_rcti_size_x(&recttemp) - delta * 2, BLI_rcti_size_y(&recttemp) - delta * 2); /* Keep one edge in place. */ @@ -4575,6 +4579,9 @@ void ui_draw_but(const bContext *C, struct ARegion *region, uiStyle *style, uiBu wt->wcol_theme = &tui->wcol_menu_back; wt->state = widget_state; } + if (!(but->flag & UI_HAS_ICON)) { + but->drawflag |= UI_BUT_NO_TEXT_PADDING; + } break; case UI_BTYPE_SEPR: diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index d8ebbbca023..258516a1c61 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -1122,8 +1122,9 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op) dy *= -1; } - /* continuous zoom shouldn't move that fast... */ - if (U.viewzoom == USER_ZOOM_CONT) { /* XXX store this setting as RNA prop? */ + /* Check if the 'timer' is initialized, as zooming with the trackpad + * never uses the "Continuous" zoom method, and the 'timer' is not initialized. */ + if ((U.viewzoom == USER_ZOOM_CONT) && vzd->timer) { /* XXX store this setting as RNA prop? */ const double time = PIL_check_seconds_timer(); const float time_step = (float)(time - vzd->timer_lastdraw); @@ -1232,6 +1233,11 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, const wmEvent *even v2d = vzd->v2d; if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) { + ARegion *region = CTX_wm_region(C); + + /* Store initial mouse position (in view space). */ + UI_view2d_region_to_view( + ®ion->v2d, event->mval[0], event->mval[1], &vzd->mx_2d, &vzd->my_2d); vzd->zoom_to_mouse_pos = true; } @@ -1278,14 +1284,6 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, const wmEvent *even /* for modal exit test */ vzd->invoke_event = event->type; - if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) { - ARegion *region = CTX_wm_region(C); - - /* store initial mouse position (in view space) */ - UI_view2d_region_to_view( - ®ion->v2d, event->mval[0], event->mval[1], &vzd->mx_2d, &vzd->my_2d); - } - if (v2d->keepofs & V2D_LOCKOFS_X) { WM_cursor_modal_set(window, WM_CURSOR_NS_SCROLL); } diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c index 292d8e6066c..70125ff35fc 100644 --- a/source/blender/editors/io/io_alembic.c +++ b/source/blender/editors/io/io_alembic.c @@ -292,7 +292,7 @@ void WM_OT_alembic_export(wmOperatorType *ot) FILE_SAVE, WM_FILESEL_FILEPATH | WM_FILESEL_SHOW_PROPS, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); RNA_def_int(ot->srna, "start", @@ -677,7 +677,7 @@ void WM_OT_alembic_import(wmOperatorType *ot) FILE_OPENFILE, WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_SHOW_PROPS, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); RNA_def_float( ot->srna, diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c index 045a293f71b..b73b8abccfe 100644 --- a/source/blender/editors/io/io_cache.c +++ b/source/blender/editors/io/io_cache.c @@ -134,7 +134,7 @@ void CACHEFILE_OT_open(wmOperatorType *ot) FILE_SAVE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); } /* ***************************** Reload Operator **************************** */ diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index 54ef5e6b8c5..af505043e6a 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -507,7 +507,7 @@ void WM_OT_collada_export(wmOperatorType *ot) FILE_SAVE, WM_FILESEL_FILEPATH | WM_FILESEL_SHOW_PROPS, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); RNA_def_enum(func, "prop_bc_export_ui_section", @@ -828,7 +828,7 @@ void WM_OT_collada_import(wmOperatorType *ot) FILE_OPENFILE, WM_FILESEL_FILEPATH | WM_FILESEL_SHOW_PROPS, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); RNA_def_boolean(ot->srna, "import_units", diff --git a/source/blender/editors/io/io_usd.c b/source/blender/editors/io/io_usd.c index 45ea52bdebc..0eadb38abb5 100644 --- a/source/blender/editors/io/io_usd.c +++ b/source/blender/editors/io/io_usd.c @@ -185,7 +185,7 @@ void WM_OT_usd_export(struct wmOperatorType *ot) FILE_SAVE, WM_FILESEL_FILEPATH | WM_FILESEL_SHOW_PROPS, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); RNA_def_boolean(ot->srna, "selected_objects_only", diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index a90d6530453..b8badd207fe 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -127,15 +127,10 @@ enum { static float get_bevel_offset(wmOperator *op) { - float val; - if (RNA_enum_get(op->ptr, "offset_type") == BEVEL_AMT_PERCENT) { - val = RNA_float_get(op->ptr, "offset_pct"); - } - else { - val = RNA_float_get(op->ptr, "offset"); + return RNA_float_get(op->ptr, "offset_pct"); } - return val; + return RNA_float_get(op->ptr, "offset"); } static void edbm_bevel_update_status_text(bContext *C, wmOperator *op) @@ -145,14 +140,12 @@ static void edbm_bevel_update_status_text(bContext *C, wmOperator *op) char *p = buf; int available_len = sizeof(buf); Scene *sce = CTX_data_scene(C); - char offset_str[NUM_STR_REP_LEN]; - const char *mode_str, *omiter_str, *imiter_str, *vmesh_str, *profile_type_str, *affect_str; - PropertyRNA *prop; #define WM_MODALKEY(_id) \ WM_modalkeymap_operator_items_to_string_buf( \ op->type, (_id), true, UI_MAX_SHORTCUT_STR, &available_len, &p) + char offset_str[NUM_STR_REP_LEN]; if (RNA_enum_get(op->ptr, "offset_type") == BEVEL_AMT_PERCENT) { BLI_snprintf(offset_str, NUM_STR_REP_LEN, "%.1f%%", RNA_float_get(op->ptr, "offset_pct")); } @@ -167,6 +160,8 @@ static void edbm_bevel_update_status_text(bContext *C, wmOperator *op) true); } + PropertyRNA *prop; + const char *mode_str, *omiter_str, *imiter_str, *vmesh_str, *profile_type_str, *affect_str; prop = RNA_struct_find_property(op->ptr, "offset_type"); RNA_property_enum_name_gettexted( C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &mode_str); @@ -240,18 +235,17 @@ static void edbm_bevel_update_status_text(bContext *C, wmOperator *op) static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal) { Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); ToolSettings *ts = CTX_data_tool_settings(C); - BevelData *opdata; ViewLayer *view_layer = CTX_data_view_layer(C); - float pixels_per_inch; - int i, otype; if (is_modal) { RNA_float_set(op->ptr, "offset", 0.0f); RNA_float_set(op->ptr, "offset_pct", 0.0f); } - op->customdata = opdata = MEM_mallocN(sizeof(BevelData), "beveldata_mesh_operator"); + op->customdata = MEM_mallocN(sizeof(BevelData), "beveldata_mesh_operator"); + BevelData *opdata = op->customdata; uint objects_used_len = 0; opdata->max_obj_scale = FLT_MIN; @@ -261,7 +255,7 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal) { uint ob_store_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( - view_layer, CTX_wm_view3d(C), &ob_store_len); + view_layer, v3d, &ob_store_len); opdata->ob_store = MEM_malloc_arrayN(ob_store_len, sizeof(*opdata->ob_store), __func__); for (uint ob_index = 0; ob_index < ob_store_len; ob_index++) { Object *obedit = objects[ob_index]; @@ -278,12 +272,12 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal) } opdata->is_modal = is_modal; - otype = RNA_enum_get(op->ptr, "offset_type"); + int otype = RNA_enum_get(op->ptr, "offset_type"); opdata->value_mode = (otype == BEVEL_AMT_PERCENT) ? OFFSET_VALUE_PERCENT : OFFSET_VALUE; opdata->segments = (float)RNA_int_get(op->ptr, "segments"); - pixels_per_inch = U.dpi * U.pixelsize; + float pixels_per_inch = U.dpi * U.pixelsize; - for (i = 0; i < NUM_VALUE_KINDS; i++) { + for (int i = 0; i < NUM_VALUE_KINDS; i++) { opdata->shift_value[i] = -1.0f; opdata->initial_length[i] = -1.0f; /* note: scale for OFFSET_VALUE will get overwritten in edbm_bevel_invoke */ @@ -304,7 +298,6 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal) /* avoid the cost of allocating a bm copy */ if (is_modal) { - View3D *v3d = CTX_wm_view3d(C); ARegion *region = CTX_wm_region(C); for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) { @@ -491,23 +484,21 @@ static int edbm_bevel_exec(bContext *C, wmOperator *op) static void edbm_bevel_calc_initial_length(wmOperator *op, const wmEvent *event, bool mode_changed) { - BevelData *opdata; - float mlen[2], len, value, sc, st; - int vmode; - - opdata = op->customdata; - mlen[0] = opdata->mcenter[0] - event->mval[0]; - mlen[1] = opdata->mcenter[1] - event->mval[1]; - len = len_v2(mlen); - vmode = opdata->value_mode; + BevelData *opdata = op->customdata; + const float mlen[2] = { + opdata->mcenter[0] - event->mval[0], + opdata->mcenter[1] - event->mval[1], + }; + float len = len_v2(mlen); + int vmode = opdata->value_mode; if (mode_changed || opdata->initial_length[vmode] == -1.0f) { /* If current value is not default start value, adjust len so that * the scaling and offset in edbm_bevel_mouse_set_value will * start at current value */ - value = (vmode == SEGMENTS_VALUE) ? opdata->segments : - RNA_float_get(op->ptr, value_rna_name[vmode]); - sc = opdata->scale[vmode]; - st = value_start[vmode]; + float value = (vmode == SEGMENTS_VALUE) ? opdata->segments : + RNA_float_get(op->ptr, value_rna_name[vmode]); + float sc = opdata->scale[vmode]; + float st = value_start[vmode]; if (value != value_start[vmode]) { len = (st + sc * (len - MVAL_PIXEL_MARGIN) - value) / sc; } @@ -518,18 +509,17 @@ static void edbm_bevel_calc_initial_length(wmOperator *op, const wmEvent *event, static int edbm_bevel_invoke(bContext *C, wmOperator *op, const wmEvent *event) { RegionView3D *rv3d = CTX_wm_region_view3d(C); - BevelData *opdata; - float center_3d[3]; if (!edbm_bevel_init(C, op, true)) { return OPERATOR_CANCELLED; } - opdata = op->customdata; + BevelData *opdata = op->customdata; opdata->launch_event = WM_userdef_event_type_from_keymap_type(event->type); /* initialize mouse values */ + float center_3d[3]; if (!calculateTransformCenter(C, V3D_AROUND_CENTER_MEDIAN, center_3d, opdata->mcenter)) { /* in this case the tool will likely do nothing, * ideally this will never happen and should be checked for above */ @@ -561,13 +551,13 @@ static void edbm_bevel_mouse_set_value(wmOperator *op, const wmEvent *event) { BevelData *opdata = op->customdata; int vmode = opdata->value_mode; - float mdiff[2]; - float value; - mdiff[0] = opdata->mcenter[0] - event->mval[0]; - mdiff[1] = opdata->mcenter[1] - event->mval[1]; + const float mdiff[2] = { + opdata->mcenter[0] - event->mval[0], + opdata->mcenter[1] - event->mval[1], + }; - value = ((len_v2(mdiff) - MVAL_PIXEL_MARGIN) - opdata->initial_length[vmode]); + float value = ((len_v2(mdiff) - MVAL_PIXEL_MARGIN) - opdata->initial_length[vmode]); /* Scale according to value mode */ value = value_start[vmode] + value * opdata->scale[vmode]; @@ -599,12 +589,10 @@ static void edbm_bevel_mouse_set_value(wmOperator *op, const wmEvent *event) static void edbm_bevel_numinput_set_value(wmOperator *op) { BevelData *opdata = op->customdata; - float value; - int vmode; - vmode = opdata->value_mode; - value = (vmode == SEGMENTS_VALUE) ? opdata->segments : - RNA_float_get(op->ptr, value_rna_name[vmode]); + int vmode = opdata->value_mode; + float value = (vmode == SEGMENTS_VALUE) ? opdata->segments : + RNA_float_get(op->ptr, value_rna_name[vmode]); applyNumInput(&opdata->num_input[vmode], &value); CLAMP(value, value_clamp_min[vmode], value_clamp_max[vmode]); if (vmode == SEGMENTS_VALUE) { @@ -616,82 +604,61 @@ static void edbm_bevel_numinput_set_value(wmOperator *op) } } -/* Hide one of offset or offset_pct, depending on offset_type */ -static bool edbm_bevel_poll_property(const bContext *UNUSED(C), - wmOperator *op, - const PropertyRNA *prop) -{ - const char *prop_id = RNA_property_identifier(prop); - - if (STRPREFIX(prop_id, "offset")) { - int offset_type = RNA_enum_get(op->ptr, "offset_type"); - - if (STREQ(prop_id, "offset") && offset_type == BEVEL_AMT_PERCENT) { - return false; - } - if (STREQ(prop_id, "offset_pct") && offset_type != BEVEL_AMT_PERCENT) { - return false; - } - } - - return true; -} - wmKeyMap *bevel_modal_keymap(wmKeyConfig *keyconf) { static const EnumPropertyItem modal_items[] = { {BEV_MODAL_CANCEL, "CANCEL", 0, "Cancel", "Cancel bevel"}, {BEV_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", "Confirm bevel"}, - {BEV_MODAL_VALUE_OFFSET, "VALUE_OFFSET", 0, "Change offset", "Value changes offset"}, - {BEV_MODAL_VALUE_PROFILE, "VALUE_PROFILE", 0, "Change profile", "Value changes profile"}, - {BEV_MODAL_VALUE_SEGMENTS, "VALUE_SEGMENTS", 0, "Change segments", "Value changes segments"}, - {BEV_MODAL_SEGMENTS_UP, "SEGMENTS_UP", 0, "Increase segments", "Increase segments"}, - {BEV_MODAL_SEGMENTS_DOWN, "SEGMENTS_DOWN", 0, "Decrease segments", "Decrease segments"}, + {BEV_MODAL_VALUE_OFFSET, "VALUE_OFFSET", 0, "Change Offset", "Value changes offset"}, + {BEV_MODAL_VALUE_PROFILE, "VALUE_PROFILE", 0, "Change Profile", "Value changes profile"}, + {BEV_MODAL_VALUE_SEGMENTS, "VALUE_SEGMENTS", 0, "Change Segments", "Value changes segments"}, + {BEV_MODAL_SEGMENTS_UP, "SEGMENTS_UP", 0, "Increase Segments", "Increase segments"}, + {BEV_MODAL_SEGMENTS_DOWN, "SEGMENTS_DOWN", 0, "Decrease Segments", "Decrease segments"}, {BEV_MODAL_OFFSET_MODE_CHANGE, "OFFSET_MODE_CHANGE", 0, - "Change offset mode", + "Change Offset Mode", "Cycle through offset modes"}, {BEV_MODAL_CLAMP_OVERLAP_TOGGLE, "CLAMP_OVERLAP_TOGGLE", 0, - "Toggle clamp overlap", + "Toggle Clamp Overlap", "Toggle clamp overlap flag"}, {BEV_MODAL_AFFECT_CHANGE, "AFFECT_CHANGE", 0, - "Change affect type", + "Change Affect Type", "Change which geometry type the operation affects, edges or vertices"}, {BEV_MODAL_HARDEN_NORMALS_TOGGLE, "HARDEN_NORMALS_TOGGLE", 0, - "Toggle harden normals", + "Toggle Harden Normals", "Toggle harden normals flag"}, {BEV_MODAL_MARK_SEAM_TOGGLE, "MARK_SEAM_TOGGLE", 0, - "Toggle mark seam", + "Toggle Mark Seam", "Toggle mark seam flag"}, {BEV_MODAL_MARK_SHARP_TOGGLE, "MARK_SHARP_TOGGLE", 0, - "Toggle mark sharp", + "Toggle Mark Sharp", "Toggle mark sharp flag"}, {BEV_MODAL_OUTER_MITER_CHANGE, "OUTER_MITER_CHANGE", 0, - "Change outer miter", + "Change Outer Miter", "Cycle through outer miter kinds"}, {BEV_MODAL_INNER_MITER_CHANGE, "INNER_MITER_CHANGE", 0, - "Change inner miter", + "Change Inner Miter", "Cycle through inner miter kinds"}, {BEV_MODAL_PROFILE_TYPE_CHANGE, "PROFILE_TYPE_CHANGE", 0, "Cycle through profile types", ""}, {BEV_MODAL_VERTEX_MESH_CHANGE, "VERTEX_MESH_CHANGE", 0, - "Change intersection method", + "Change Intersection Method", "Cycle through intersection methods"}, {0, NULL, 0, NULL, NULL}, }; @@ -1109,7 +1076,6 @@ void MESH_OT_bevel(wmOperatorType *ot) ot->modal = edbm_bevel_modal; ot->cancel = edbm_bevel_cancel; ot->poll = ED_operator_editmesh; - ot->poll_property = edbm_bevel_poll_property; ot->ui = edbm_bevel_ui; /* flags */ diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c index 528ad57b9bf..e2112f91060 100644 --- a/source/blender/editors/mesh/editmesh_intersect.c +++ b/source/blender/editors/mesh/editmesh_intersect.c @@ -121,11 +121,10 @@ static void edbm_intersect_select(BMEditMesh *em, struct Mesh *me, bool do_selec } /* -------------------------------------------------------------------- */ -/* Cut intersections into geometry */ - /** \name Simple Intersect (self-intersect) - * \{ - */ + * + * Cut intersections into geometry. + * \{ */ enum { ISECT_SEL = 0, @@ -331,15 +330,11 @@ void MESH_OT_intersect(struct wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ -/* Boolean (a kind of intersect) */ - /** \name Boolean Intersect * * \note internally this is nearly exactly the same as 'MESH_OT_intersect', * however from a user perspective they are quite different, so expose as different tools. - * - * \{ - */ + * \{ */ static int edbm_intersect_boolean_exec(bContext *C, wmOperator *op) { @@ -488,9 +483,7 @@ void MESH_OT_intersect_boolean(struct wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ -/* Face Split by Edges */ - -/** \name Face/Edge Split +/** \name Face Split by Edges * \{ */ static void bm_face_split_by_edges(BMesh *bm, diff --git a/source/blender/editors/mesh/editmesh_select_similar.c b/source/blender/editors/mesh/editmesh_select_similar.c index f94d3ba5a70..00349983c57 100644 --- a/source/blender/editors/mesh/editmesh_select_similar.c +++ b/source/blender/editors/mesh/editmesh_select_similar.c @@ -83,7 +83,7 @@ static const EnumPropertyItem prop_similar_types[] = { {SIMFACE_SIDES, "SIDES", 0, "Polygon Sides", ""}, {SIMFACE_PERIMETER, "PERIMETER", 0, "Perimeter", ""}, {SIMFACE_NORMAL, "NORMAL", 0, "Normal", ""}, - {SIMFACE_COPLANAR, "COPLANAR", 0, "Co-planar", ""}, + {SIMFACE_COPLANAR, "COPLANAR", 0, "Coplanar", ""}, {SIMFACE_SMOOTH, "SMOOTH", 0, "Flat/Smooth", ""}, {SIMFACE_FACEMAP, "FACE_MAP", 0, "Face-Map", ""}, #ifdef WITH_FREESTYLE diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c index 41d840c4a2d..43cad2db185 100644 --- a/source/blender/editors/mesh/editmesh_undo.c +++ b/source/blender/editors/mesh/editmesh_undo.c @@ -118,6 +118,7 @@ typedef struct UndoMesh { #ifdef USE_ARRAY_STORE +/* -------------------------------------------------------------------- */ /** \name Array Store * \{ */ diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index ae1aae27b7f..bb8597bf02c 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -97,7 +97,6 @@ typedef struct MultiresBakerJobData { int len; } ob_image; DerivedMesh *lores_dm, *hires_dm; - bool simple; int lvl, tot_lvl; ListBase images; } MultiresBakerJobData; @@ -247,7 +246,7 @@ static DerivedMesh *multiresbake_create_loresdm(Scene *scene, Object *ob, int *l return dm; } -static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *lvl, bool *simple) +static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *lvl) { Mesh *me = (Mesh *)ob->data; MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0); @@ -264,7 +263,6 @@ static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *l CustomData_set_only_copy(&cddm->polyData, CD_MASK_BAREMESH.pmask); *lvl = mmd->totlvl; - *simple = mmd->simple != 0; tmp_mmd.lvl = mmd->totlvl; tmp_mmd.sculptlvl = mmd->totlvl; @@ -386,7 +384,7 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op) bkr.ob_image.array = bake_object_image_get_array(ob); bkr.ob_image.len = ob->totcol; - bkr.hires_dm = multiresbake_create_hiresdm(scene, ob, &bkr.tot_lvl, &bkr.simple); + bkr.hires_dm = multiresbake_create_hiresdm(scene, ob, &bkr.tot_lvl); bkr.lores_dm = multiresbake_create_loresdm(scene, ob, &bkr.lvl); RE_multires_bake_images(&bkr); @@ -441,7 +439,7 @@ static void init_multiresbake_job(bContext *C, MultiresBakeJob *bkj) data->ob_image.len = ob->totcol; /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */ - data->hires_dm = multiresbake_create_hiresdm(scene, ob, &data->tot_lvl, &data->simple); + data->hires_dm = multiresbake_create_hiresdm(scene, ob, &data->tot_lvl); data->lores_dm = multiresbake_create_loresdm(scene, ob, &lvl); data->lvl = lvl; @@ -491,7 +489,6 @@ static void multiresbake_startjob(void *bkv, short *stop, short *do_update, floa bkr.hires_dm = data->hires_dm; bkr.tot_lvl = data->tot_lvl; bkr.lvl = data->lvl; - bkr.simple = data->simple; /* needed for proper progress bar */ bkr.tot_obj = tot_obj; diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index 5cfe02dbc59..91c9916d227 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -238,12 +238,11 @@ static void select_editlattice_hook(Object *obedit, HookModifierData *hmd) static int return_editcurve_indexar(Object *obedit, int *r_tot, int **r_indexar, float r_cent[3]) { ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; BPoint *bp; BezTriple *bezt; int *index, a, nr, totvert = 0; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; @@ -280,7 +279,7 @@ static int return_editcurve_indexar(Object *obedit, int *r_tot, int **r_indexar, nr = 0; zero_v3(r_cent); - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; @@ -377,12 +376,11 @@ static bool object_hook_index_array(Main *bmain, static void select_editcurve_hook(Object *obedit, HookModifierData *hmd) { ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu; BPoint *bp; BezTriple *bezt; int index = 0, a, nr = 0; - for (nu = editnurb->first; nu; nu = nu->next) { + LISTBASE_FOREACH (Nurb *, nu, editnurb) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 4eed9187d66..ce08c5926f2 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -31,6 +31,7 @@ #include "DNA_armature_types.h" #include "DNA_curve_types.h" #include "DNA_key_types.h" +#include "DNA_lattice_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_force_types.h" @@ -679,16 +680,15 @@ static int modifier_apply_shape(Main *bmain, return 0; } - /* - * It should be ridiculously easy to extract the original verts that we want - * and form the shape data. We can probably use the CD KEYINDEX layer (or - * whatever I ended up calling it, too tired to check now), though this would - * by necessity have to make some potentially ugly assumptions about the order - * of the mesh data :-/ you can probably assume in 99% of cases that the first - * element of a given index is the original, and any subsequent duplicates are - * copies/interpolates, but that's an assumption that would need to be tested - * and then predominantly stated in comments in a half dozen headers. - */ + /* We could investigate using the #CD_ORIGINDEX layer + * to support other kinds of modifiers besides deforming modifiers. + * as this is done in many other places, see: #BKE_mesh_foreach_mapped_vert_coords_get. + * + * This isn't high priority in practice since most modifiers users + * want to apply as a shape are deforming modifiers. + * + * If a compelling use-case comes up where we want to support other kinds of modifiers + * we can look into supporting them. */ if (ob->type == OB_MESH) { Mesh *mesh_applied; @@ -721,7 +721,7 @@ static int modifier_apply_shape(Main *bmain, BKE_id_free(NULL, mesh_applied); } else { - /* TODO: implement for hair, pointclouds and volumes. */ + /* TODO: implement for hair, point-clouds and volumes. */ BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type"); return 0; } @@ -798,8 +798,27 @@ static int modifier_apply_obdata( DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); } + else if (ob->type == OB_LATTICE) { + Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); + Lattice *lattice = ob->data; + ModifierEvalContext mectx = {depsgraph, object_eval, 0}; + + if (ELEM(mti->type, eModifierTypeType_Constructive, eModifierTypeType_Nonconstructive)) { + BKE_report(reports, RPT_ERROR, "Constructive modifiers cannot be applied"); + return 0; + } + + int numVerts; + float(*vertexCos)[3] = BKE_lattice_vert_coords_alloc(lattice, &numVerts); + mti->deformVerts(md_eval, &mectx, NULL, vertexCos, numVerts); + BKE_lattice_vert_coords_apply(lattice, vertexCos); + + MEM_freeN(vertexCos); + + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + } else { - /* TODO: implement for hair, pointclouds and volumes. */ + /* TODO: implement for hair, point-clouds and volumes. */ BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type"); return 0; } @@ -1478,8 +1497,8 @@ static char *modifier_apply_as_shapekey_get_description(struct bContext *UNUSED( void OBJECT_OT_modifier_apply_as_shapekey(wmOperatorType *ot) { - ot->name = "Apply Modifier As Shapekey"; - ot->description = "Apply modifier as a new shapekey and remove from the stack"; + ot->name = "Apply Modifier as Shape Key"; + ot->description = "Apply modifier as a new shape key and remove from the stack"; ot->idname = "OBJECT_OT_modifier_apply_as_shapekey"; ot->invoke = modifier_apply_as_shapekey_invoke; @@ -1887,7 +1906,7 @@ void OBJECT_OT_multires_external_save(wmOperatorType *ot) FILE_SAVE, WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); edit_modifier_properties(ot); } diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index de3e5f3d5f9..46624a76999 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -696,7 +696,7 @@ bool ED_object_parent_set(ReportList *reports, /* Preconditions. */ if (ob == par) { /* Parenting an object to itself is impossible. */ - return true; + return false; } if (BKE_object_parent_loop_check(par, ob)) { @@ -981,6 +981,12 @@ struct ParentingContext { static bool parent_set_nonvertex_parent(bContext *C, struct ParentingContext *parenting_context) { CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { + if (ob == parenting_context->par) { + /* ED_object_parent_set() will fail (and thus return false), but this case shouldn't break + * this loop. It's expected that the active object is also selected. */ + continue; + } + if (!ED_object_parent_set(parenting_context->reports, C, parenting_context->scene, @@ -1005,6 +1011,12 @@ static bool parent_set_vertex_parent_with_kdtree(bContext *C, int vert_par[3] = {0, 0, 0}; CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { + if (ob == parenting_context->par) { + /* ED_object_parent_set() will fail (and thus return false), but this case shouldn't break + * this loop. It's expected that the active object is also selected. */ + continue; + } + parent_set_vert_find(tree, ob, vert_par, parenting_context->is_vertex_tri); if (!ED_object_parent_set(parenting_context->reports, C, @@ -1359,7 +1371,7 @@ enum { static const EnumPropertyItem prop_make_track_types[] = { {CREATE_TRACK_DAMPTRACK, "DAMPTRACK", 0, "Damped Track Constraint", ""}, - {CREATE_TRACK_TRACKTO, "TRACKTO", 0, "Track To Constraint", ""}, + {CREATE_TRACK_TRACKTO, "TRACKTO", 0, "Track to Constraint", ""}, {CREATE_TRACK_LOCKTRACK, "LOCKTRACK", 0, "Lock Track Constraint", ""}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index e92b3323441..b48b854c238 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -2664,12 +2664,23 @@ static void vgroup_assign_verts(Object *ob, const float weight) static bool vertex_group_supported_poll_ex(bContext *C, const Object *ob) { if (!ED_operator_object_active_local_editable_ex(C, ob)) { + CTX_wm_operator_poll_msg_set(C, "No active editable object"); return false; } + + if (!OB_TYPE_SUPPORT_VGROUP(ob->type)) { + CTX_wm_operator_poll_msg_set(C, "Object type does not support vertex groups"); + return false; + } + + /* Data checks. */ const ID *data = ob->data; - return (OB_TYPE_SUPPORT_VGROUP(ob->type) && - /* Data checks. */ - (data != NULL) && !ID_IS_LINKED(data) && !ID_IS_OVERRIDE_LIBRARY(data)); + if (data == NULL || ID_IS_LINKED(data) || ID_IS_OVERRIDE_LIBRARY(data)) { + CTX_wm_operator_poll_msg_set(C, "Object type \"%s\" does not have editable data"); + return false; + } + + return true; } static bool vertex_group_supported_poll(bContext *C) @@ -2678,48 +2689,61 @@ static bool vertex_group_supported_poll(bContext *C) return vertex_group_supported_poll_ex(C, ob); } -static bool vertex_group_poll(bContext *C) +static bool vertex_group_poll_ex(bContext *C, Object *ob) { - Object *ob = ED_object_context(C); + if (!vertex_group_supported_poll_ex(C, ob)) { + return false; + } + + if (BLI_listbase_is_empty(&ob->defbase)) { + CTX_wm_operator_poll_msg_set(C, "Object has no vertex groups"); + return false; + } - return (vertex_group_supported_poll(C) && ob->defbase.first); + return true; } -static bool vertex_group_mesh_poll(bContext *C) +static bool vertex_group_poll(bContext *C) { Object *ob = ED_object_context(C); - - return (vertex_group_poll(C) && ob->type == OB_MESH); + return vertex_group_poll_ex(C, ob); } -static bool vertex_group_mesh_with_dvert_poll(bContext *C) +static bool vertex_group_mesh_poll_ex(bContext *C, Object *ob) { - Object *ob = ED_object_context(C); - - if (!vertex_group_mesh_poll(C)) { + if (!vertex_group_poll_ex(C, ob)) { return false; } - Mesh *me = ob->data; - if (me->dvert == NULL) { + if (ob->type != OB_MESH) { + CTX_wm_operator_poll_msg_set(C, "Only mesh objects are supported"); return false; } return true; } -static bool UNUSED_FUNCTION(vertex_group_mesh_supported_poll)(bContext *C) +static bool vertex_group_mesh_with_dvert_poll(bContext *C) { Object *ob = ED_object_context(C); + if (!vertex_group_mesh_poll_ex(C, ob)) { + return false; + } + + Mesh *me = ob->data; + if (me->dvert == NULL) { + CTX_wm_operator_poll_msg_set(C, "The active mesh object has no vertex group data"); + return false; + } - return (vertex_group_supported_poll(C) && ob->type == OB_MESH); + return true; } static bool UNUSED_FUNCTION(vertex_group_poll_edit)(bContext *C) { Object *ob = ED_object_context(C); - if (!vertex_group_supported_poll(C)) { + if (!vertex_group_supported_poll_ex(C, ob)) { return false; } @@ -2733,7 +2757,7 @@ static bool vertex_group_vert_poll_ex(bContext *C, { Object *ob = ED_object_context(C); - if (!vertex_group_supported_poll(C)) { + if (!vertex_group_supported_poll_ex(C, ob)) { return false; } @@ -2786,7 +2810,7 @@ static bool vertex_group_vert_select_unlocked_poll(bContext *C) { Object *ob = ED_object_context(C); - if (!vertex_group_supported_poll(C)) { + if (!vertex_group_supported_poll_ex(C, ob)) { return false; } @@ -2807,7 +2831,7 @@ static bool vertex_group_vert_select_mesh_poll(bContext *C) { Object *ob = ED_object_context(C); - if (!vertex_group_supported_poll(C)) { + if (!vertex_group_supported_poll_ex(C, ob)) { return false; } diff --git a/source/blender/editors/object/object_volume.c b/source/blender/editors/object/object_volume.c index c5dc7f9f24d..5aa61139468 100644 --- a/source/blender/editors/object/object_volume.c +++ b/source/blender/editors/object/object_volume.c @@ -184,7 +184,7 @@ void OBJECT_OT_volume_import(wmOperatorType *ot) WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILES | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); RNA_def_boolean( ot->srna, diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index 56bdc5c21f4..017cd63d9d5 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -691,7 +691,7 @@ void PARTICLE_OT_disconnect_hair(wmOperatorType *ot) ot->flag = OPTYPE_UNDO; RNA_def_boolean( - ot->srna, "all", 0, "All hair", "Disconnect all hair systems from the emitter mesh"); + ot->srna, "all", 0, "All Hair", "Disconnect all hair systems from the emitter mesh"); } /* from/to_world_space : whether from/to particles are in world or hair space @@ -981,7 +981,7 @@ void PARTICLE_OT_connect_hair(wmOperatorType *ot) /* No REGISTER, redo does not work due to missing update, see T47750. */ ot->flag = OPTYPE_UNDO; - RNA_def_boolean(ot->srna, "all", 0, "All hair", "Connect all hair systems to the emitter mesh"); + RNA_def_boolean(ot->srna, "all", 0, "All Hair", "Connect all hair systems to the emitter mesh"); } /************************ particle system copy operator *********************/ diff --git a/source/blender/editors/physics/rigidbody_world.c b/source/blender/editors/physics/rigidbody_world.c index 42f270874e3..f2e2d7589df 100644 --- a/source/blender/editors/physics/rigidbody_world.c +++ b/source/blender/editors/physics/rigidbody_world.c @@ -210,5 +210,5 @@ void RIGIDBODY_OT_world_export(wmOperatorType *ot) FILE_SAVE, FILE_RELPATH, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); } diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 7ca711cd2b8..3dbf70aa4bc 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -57,7 +57,6 @@ #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_screen.h" -#include "BKE_sequencer.h" #include "BKE_undo_system.h" #include "DEG_depsgraph.h" @@ -83,6 +82,8 @@ #include "RNA_access.h" #include "RNA_define.h" +#include "SEQ_sequencer.h" + #include "BLO_undofile.h" #include "render_intern.h" @@ -435,20 +436,6 @@ static void make_renderinfo_string(const RenderStats *rs, } } else { - if (rs->totvert || rs->totface || rs->totlamp) { - spos += sprintf(spos, "| "); - } - - if (rs->totvert) { - spos += sprintf(spos, TIP_("Ve:%d "), rs->totvert); - } - if (rs->totface) { - spos += sprintf(spos, TIP_("Fa:%d "), rs->totface); - } - if (rs->totlamp) { - spos += sprintf(spos, TIP_("Li:%d "), rs->totlamp); - } - if (rs->mem_peak == 0.0f) { spos += sprintf(spos, TIP_("| Mem:%.2fM (Peak %.2fM) "), megs_used_memory, megs_peak_memory); } diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 8d410e36ca6..5d355ada77c 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -54,7 +54,6 @@ #include "BKE_main.h" #include "BKE_report.h" #include "BKE_scene.h" -#include "BKE_sequencer.h" #include "BKE_writeavi.h" #include "DEG_depsgraph.h" @@ -78,6 +77,8 @@ #include "RNA_access.h" #include "RNA_define.h" +#include "SEQ_sequencer.h" + #include "GPU_framebuffer.h" #include "GPU_matrix.h" diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index f5962f36412..cffcb1cb4dc 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -1871,6 +1871,11 @@ void ED_area_update_region_sizes(wmWindowManager *wm, wmWindow *win, ScrArea *ar area->flag &= ~AREA_FLAG_REGION_SIZE_UPDATE; } +bool ED_area_has_shared_border(struct ScrArea *a, struct ScrArea *b) +{ + return area_getorientation(a, b) != -1; +} + /* called in screen_refresh, or screens_init, also area size changes */ void ED_area_init(wmWindowManager *wm, wmWindow *win, ScrArea *area) { diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index 3924c334541..af09100b8e6 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -48,7 +48,6 @@ #include "BKE_gpencil.h" #include "BKE_layer.h" #include "BKE_object.h" -#include "BKE_sequencer.h" #include "RNA_access.h" @@ -56,6 +55,8 @@ #include "ED_armature.h" #include "ED_gpencil.h" +#include "SEQ_sequencer.h" + #include "UI_interface.h" #include "WM_api.h" diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 27a1d4e4a50..6f80165ed3c 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -5523,8 +5523,8 @@ static void keymap_modal_set(wmKeyConfig *keyconf) static const EnumPropertyItem modal_items[] = { {KM_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, {KM_MODAL_APPLY, "APPLY", 0, "Apply", ""}, - {KM_MODAL_SNAP_ON, "SNAP", 0, "Snap on", ""}, - {KM_MODAL_SNAP_OFF, "SNAP_OFF", 0, "Snap off", ""}, + {KM_MODAL_SNAP_ON, "SNAP", 0, "Snap On", ""}, + {KM_MODAL_SNAP_OFF, "SNAP_OFF", 0, "Snap Off", ""}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index 5d0ae292ffa..7d7a3340dc3 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -249,7 +249,7 @@ void SCREEN_OT_screenshot(wmOperatorType *ot) FILE_SAVE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); RNA_def_boolean(ot->srna, "full", 1, diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c index cab2d32bdcf..5430137f5ca 100644 --- a/source/blender/editors/screen/workspace_edit.c +++ b/source/blender/editors/screen/workspace_edit.c @@ -57,6 +57,7 @@ #include "screen_intern.h" +/* -------------------------------------------------------------------- */ /** \name Workspace API * * \brief API for managing workspaces and their data. @@ -231,6 +232,7 @@ void ED_workspace_scene_data_sync(WorkSpaceInstanceHook *hook, Scene *scene) /** \} Workspace API */ +/* -------------------------------------------------------------------- */ /** \name Workspace Operators * * \{ */ diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index f0285c8faf3..550913fc8af 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -1310,6 +1310,11 @@ static bool paint_cursor_context_init(bContext *C, Object *active_object = pcontext->vc.obact; pcontext->ss = active_object ? active_object->sculpt : NULL; + if (pcontext->ss && pcontext->ss->draw_faded_cursor) { + pcontext->outline_alpha = 0.3f; + copy_v3_fl(pcontext->outline_col, 0.8f); + } + pcontext->is_stroke_active = pcontext->ups->stroke_active; return true; diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index cc0d20089b4..26abd19d5e8 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -246,8 +246,16 @@ typedef struct LassoGestureData { } LassoGestureData; typedef struct LineGestureData { + /* Plane aligned to the gesture line. */ float true_plane[4]; float plane[4]; + + /* Planes to limit the action to the length of the gesture segment at both sides of the affected + * area. */ + float side_plane[2][4]; + float true_side_plane[2][4]; + bool use_side_planes; + bool flip; } LineGestureData; @@ -320,6 +328,13 @@ static void sculpt_gesture_operator_properties(wmOperatorType *ot) false, "Front Faces Only", "Affect only faces facing towards the view"); + + RNA_def_boolean(ot->srna, + "use_limit_to_segment", + false, + "Limit to Segment", + "Apply the gesture action only to the area that is contained within the " + "segement without extending its effect to the entire line"); } static void sculpt_gesture_context_init_common(bContext *C, @@ -332,6 +347,7 @@ static void sculpt_gesture_context_init_common(bContext *C, /* Operator properties. */ sgcontext->front_faces_only = RNA_boolean_get(op->ptr, "use_front_faces_only"); + sgcontext->line.use_side_planes = RNA_boolean_get(op->ptr, "use_limit_to_segment"); /* SculptSession */ sgcontext->ss = ob->sculpt; @@ -448,6 +464,50 @@ static SculptGestureContext *sculpt_gesture_init_from_box(bContext *C, wmOperato return sgcontext; } +static void sculpt_gesture_line_plane_from_tri(float *r_plane, + SculptGestureContext *sgcontext, + const bool flip, + const float p1[3], + const float p2[3], + const float p3[3]) +{ + float normal[3]; + normal_tri_v3(normal, p1, p2, p3); + mul_v3_mat3_m4v3(normal, sgcontext->vc.obact->imat, normal); + if (flip) { + mul_v3_fl(normal, -1.0f); + } + float plane_point_object_space[3]; + mul_v3_m4v3(plane_point_object_space, sgcontext->vc.obact->imat, p1); + plane_from_point_normal_v3(r_plane, plane_point_object_space, normal); +} + +/* Creates 4 points in the plane defined by the line and 2 extra points with an offset relative to + * this plane. */ +static void sculpt_gesture_line_calculate_plane_points(SculptGestureContext *sgcontext, + float line_points[2][2], + float r_plane_points[4][3], + float r_offset_plane_points[2][3]) +{ + float depth_point[3]; + add_v3_v3v3(depth_point, sgcontext->true_view_origin, sgcontext->true_view_normal); + ED_view3d_win_to_3d( + sgcontext->vc.v3d, sgcontext->vc.region, depth_point, line_points[0], r_plane_points[0]); + ED_view3d_win_to_3d( + sgcontext->vc.v3d, sgcontext->vc.region, depth_point, line_points[1], r_plane_points[3]); + + madd_v3_v3v3fl(depth_point, sgcontext->true_view_origin, sgcontext->true_view_normal, 10.0f); + ED_view3d_win_to_3d( + sgcontext->vc.v3d, sgcontext->vc.region, depth_point, line_points[0], r_plane_points[1]); + ED_view3d_win_to_3d( + sgcontext->vc.v3d, sgcontext->vc.region, depth_point, line_points[1], r_plane_points[2]); + + float normal[3]; + normal_tri_v3(normal, r_plane_points[0], r_plane_points[1], r_plane_points[2]); + add_v3_v3v3(r_offset_plane_points[0], r_plane_points[0], normal); + add_v3_v3v3(r_offset_plane_points[1], r_plane_points[3], normal); +} + static SculptGestureContext *sculpt_gesture_init_from_line(bContext *C, wmOperator *op) { SculptGestureContext *sgcontext = MEM_callocN(sizeof(SculptGestureContext), @@ -464,36 +524,33 @@ static SculptGestureContext *sculpt_gesture_init_from_line(bContext *C, wmOperat sgcontext->line.flip = RNA_boolean_get(op->ptr, "flip"); - float depth_point[3]; - float plane_points[3][3]; - - /* Calculate a triangle in the line's plane. */ - add_v3_v3v3(depth_point, sgcontext->true_view_origin, sgcontext->true_view_normal); - ED_view3d_win_to_3d( - sgcontext->vc.v3d, sgcontext->vc.region, depth_point, line_points[0], plane_points[0]); - - madd_v3_v3v3fl(depth_point, sgcontext->true_view_origin, sgcontext->true_view_normal, 10.0f); - ED_view3d_win_to_3d( - sgcontext->vc.v3d, sgcontext->vc.region, depth_point, line_points[0], plane_points[1]); - ED_view3d_win_to_3d( - sgcontext->vc.v3d, sgcontext->vc.region, depth_point, line_points[1], plane_points[2]); - - /* Calculate final line plane and normal using the triangle. */ - float normal[3]; - normal_tri_v3(normal, plane_points[0], plane_points[1], plane_points[2]); - if (!sgcontext->vc.rv3d->is_persp) { - mul_v3_fl(normal, -1.0f); - } - - /* Apply flip. */ - if (sgcontext->line.flip) { - mul_v3_fl(normal, -1.0f); - } - - mul_v3_mat3_m4v3(normal, sgcontext->vc.obact->imat, normal); - float plane_point_object_space[3]; - mul_v3_m4v3(plane_point_object_space, sgcontext->vc.obact->imat, plane_points[0]); - plane_from_point_normal_v3(sgcontext->line.true_plane, plane_point_object_space, normal); + float plane_points[4][3]; + float offset_plane_points[2][3]; + sculpt_gesture_line_calculate_plane_points( + sgcontext, line_points, plane_points, offset_plane_points); + + /* Calculate line plane and normal. */ + const bool flip = sgcontext->line.flip ^ !sgcontext->vc.rv3d->is_persp; + sculpt_gesture_line_plane_from_tri(sgcontext->line.true_plane, + sgcontext, + flip, + plane_points[0], + plane_points[1], + plane_points[2]); + + /* Calculate the side planes. */ + sculpt_gesture_line_plane_from_tri(sgcontext->line.true_side_plane[0], + sgcontext, + false, + plane_points[1], + plane_points[0], + offset_plane_points[0]); + sculpt_gesture_line_plane_from_tri(sgcontext->line.true_side_plane[1], + sgcontext, + false, + plane_points[3], + plane_points[2], + offset_plane_points[1]); return sgcontext; } @@ -544,14 +601,20 @@ static void sculpt_gesture_flip_for_symmetry_pass(SculptGestureContext *sgcontex flip_v3_v3(sgcontext->view_normal, sgcontext->true_view_normal, symmpass); flip_v3_v3(sgcontext->view_origin, sgcontext->true_view_origin, symmpass); flip_plane(sgcontext->line.plane, sgcontext->line.true_plane, symmpass); + flip_plane(sgcontext->line.side_plane[0], sgcontext->line.true_side_plane[0], symmpass); + flip_plane(sgcontext->line.side_plane[1], sgcontext->line.true_side_plane[1], symmpass); } static void sculpt_gesture_update_effected_nodes_by_line_plane(SculptGestureContext *sgcontext) { SculptSession *ss = sgcontext->ss; - float clip_planes[1][4]; + float clip_planes[3][4]; copy_v4_v4(clip_planes[0], sgcontext->line.plane); - PBVHFrustumPlanes frustum = {.planes = clip_planes, .num_planes = 1}; + copy_v4_v4(clip_planes[1], sgcontext->line.side_plane[0]); + copy_v4_v4(clip_planes[2], sgcontext->line.side_plane[1]); + + const int num_planes = sgcontext->line.use_side_planes ? 3 : 1; + PBVHFrustumPlanes frustum = {.planes = clip_planes, .num_planes = num_planes}; BKE_pbvh_search_gather(ss->pbvh, BKE_pbvh_node_frustum_contain_AABB, &frustum, @@ -630,6 +693,11 @@ static bool sculpt_gesture_is_vertex_effected(SculptGestureContext *sgcontext, P case SCULPT_GESTURE_SHAPE_LASSO: return sculpt_gesture_is_effected_lasso(sgcontext, vd->co); case SCULPT_GESTURE_SHAPE_LINE: + if (sgcontext->line.use_side_planes) { + return plane_point_side_v3(sgcontext->line.plane, vd->co) > 0.0f && + plane_point_side_v3(sgcontext->line.side_plane[0], vd->co) > 0.0f && + plane_point_side_v3(sgcontext->line.side_plane[1], vd->co) > 0.0f; + } return plane_point_side_v3(sgcontext->line.plane, vd->co) > 0.0f; } return false; @@ -862,6 +930,24 @@ static EnumPropertyItem prop_trim_operation_types[] = { {0, NULL, 0, NULL, NULL}, }; +typedef enum eSculptTrimOrientationType { + SCULPT_GESTURE_TRIM_ORIENTATION_VIEW, + SCULPT_GESTURE_TRIM_ORIENTATION_SURFACE, +} eSculptTrimOrientationType; +static EnumPropertyItem prop_trim_orientation_types[] = { + {SCULPT_GESTURE_TRIM_ORIENTATION_VIEW, + "VIEW", + 0, + "View", + "Use the view to orientate the trimming shape"}, + {SCULPT_GESTURE_TRIM_ORIENTATION_SURFACE, + "SURFACE", + 0, + "Surface", + "Use the surface normal to orientate the trimming shape"}, + {0, NULL, 0, NULL, NULL}, +}; + typedef struct SculptGestureTrimOperation { SculptGestureOperation op; @@ -874,6 +960,7 @@ typedef struct SculptGestureTrimOperation { bool use_cursor_depth; eSculptTrimOperationType mode; + eSculptTrimOrientationType orientation; } SculptGestureTrimOperation; static void sculpt_gesture_trim_normals_update(SculptGestureContext *sgcontext) @@ -910,6 +997,29 @@ static void sculpt_gesture_trim_normals_update(SculptGestureContext *sgcontext) trim_operation->mesh = result; } +/* Get the origin and normal that are going to be used for calculating the depth and position the + * trimming geometry. */ +static void sculpt_gesture_trim_shape_origin_normal_get(SculptGestureContext *sgcontext, + float *r_origin, + float *r_normal) +{ + SculptGestureTrimOperation *trim_operation = (SculptGestureTrimOperation *)sgcontext->operation; + /* Use the view origin and normal in world space. The trimming mesh coordinates are + * calculated in world space, aligned to the view, and then converted to object space to + * store them in the final trimming mesh which is going to be used in the boolean operation. + */ + switch (trim_operation->orientation) { + case SCULPT_GESTURE_TRIM_ORIENTATION_VIEW: + copy_v3_v3(r_origin, sgcontext->world_space_view_origin); + copy_v3_v3(r_normal, sgcontext->world_space_view_normal); + break; + case SCULPT_GESTURE_TRIM_ORIENTATION_SURFACE: + mul_v3_m4v3(r_origin, sgcontext->vc.obact->obmat, sgcontext->ss->gesture_initial_location); + mul_v3_m4v3(r_normal, sgcontext->vc.obact->obmat, sgcontext->ss->gesture_initial_normal); + break; + } +} + static void sculpt_gesture_trim_calculate_depth(bContext *C, SculptGestureContext *sgcontext) { SculptGestureTrimOperation *trim_operation = (SculptGestureTrimOperation *)sgcontext->operation; @@ -919,11 +1029,11 @@ static void sculpt_gesture_trim_calculate_depth(bContext *C, SculptGestureContex const int totvert = SCULPT_vertex_count_get(ss); - float view_plane[4]; - const float *view_origin = sgcontext->world_space_view_origin; - const float *view_normal = sgcontext->world_space_view_normal; - - plane_from_point_normal_v3(view_plane, view_origin, view_normal); + float shape_plane[4]; + float shape_origin[3]; + float shape_normal[3]; + sculpt_gesture_trim_shape_origin_normal_get(sgcontext, shape_origin, shape_normal); + plane_from_point_normal_v3(shape_plane, shape_origin, shape_normal); trim_operation->depth_front = FLT_MAX; trim_operation->depth_back = -FLT_MAX; @@ -935,7 +1045,7 @@ static void sculpt_gesture_trim_calculate_depth(bContext *C, SculptGestureContex * store them. */ float world_space_vco[3]; mul_v3_m4v3(world_space_vco, vc->obact->obmat, vco); - const float dist = dist_signed_to_plane_v3(world_space_vco, view_plane); + const float dist = dist_signed_to_plane_v3(world_space_vco, shape_plane); trim_operation->depth_front = min_ff(dist, trim_operation->depth_front); trim_operation->depth_back = max_ff(dist, trim_operation->depth_back); } @@ -944,11 +1054,22 @@ static void sculpt_gesture_trim_calculate_depth(bContext *C, SculptGestureContex float world_space_gesture_initial_location[3]; mul_v3_m4v3( world_space_gesture_initial_location, vc->obact->obmat, ss->gesture_initial_location); - const float mid_point_depth = ss->gesture_initial_hit ? - dist_signed_to_plane_v3(world_space_gesture_initial_location, - view_plane) : - (trim_operation->depth_back + trim_operation->depth_front) * - 0.5f; + + float mid_point_depth; + if (trim_operation->orientation == SCULPT_GESTURE_TRIM_ORIENTATION_VIEW) { + mid_point_depth = ss->gesture_initial_hit ? + dist_signed_to_plane_v3(world_space_gesture_initial_location, + shape_plane) : + (trim_operation->depth_back + trim_operation->depth_front) * 0.5f; + } + else { + /* When using normal orientation, if the stroke started over the mesh, position the mid point + * at 0 distance from the shape plane. This positions the trimming shape half inside of the + * surface. */ + mid_point_depth = ss->gesture_initial_hit ? + 0.0f : + (trim_operation->depth_back + trim_operation->depth_front) * 0.5f; + } Sculpt *sd = CTX_data_tool_settings(C)->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); @@ -986,30 +1107,41 @@ static void sculpt_gesture_trim_geometry_generate(SculptGestureContext *sgcontex depth_back += 0.1f; } - /* Use the view origin and normal in world space. The trimming mesh coordinates are calculated in - * world space, aligned to the view, and then converted to object space to store them in the - * final trimming mesh which is going to be used in the boolean operation. - */ - const float *view_origin = sgcontext->world_space_view_origin; - const float *view_normal = sgcontext->world_space_view_normal; + float shape_origin[3]; + float shape_normal[3]; + float shape_plane[4]; + sculpt_gesture_trim_shape_origin_normal_get(sgcontext, shape_origin, shape_normal); + plane_from_point_normal_v3(shape_plane, shape_origin, shape_normal); const float(*ob_imat)[4] = vc->obact->imat; /* Write vertices coordinates for the front face. */ float depth_point[3]; - madd_v3_v3v3fl(depth_point, view_origin, view_normal, depth_front); + madd_v3_v3v3fl(depth_point, shape_origin, shape_normal, depth_front); for (int i = 0; i < tot_screen_points; i++) { float new_point[3]; - ED_view3d_win_to_3d(vc->v3d, region, depth_point, screen_points[i], new_point); + if (trim_operation->orientation == SCULPT_GESTURE_TRIM_ORIENTATION_VIEW) { + ED_view3d_win_to_3d(vc->v3d, region, depth_point, screen_points[i], new_point); + } + else { + ED_view3d_win_to_3d_on_plane(region, shape_plane, screen_points[i], false, new_point); + madd_v3_v3fl(new_point, shape_normal, depth_front); + } mul_v3_m4v3(trim_operation->mesh->mvert[i].co, ob_imat, new_point); mul_v3_m4v3(trim_operation->true_mesh_co[i], ob_imat, new_point); } /* Write vertices coordinates for the back face. */ - madd_v3_v3v3fl(depth_point, view_origin, view_normal, depth_back); + madd_v3_v3v3fl(depth_point, shape_origin, shape_normal, depth_back); for (int i = 0; i < tot_screen_points; i++) { float new_point[3]; - ED_view3d_win_to_3d(vc->v3d, region, depth_point, screen_points[i], new_point); + if (trim_operation->orientation == SCULPT_GESTURE_TRIM_ORIENTATION_VIEW) { + ED_view3d_win_to_3d(vc->v3d, region, depth_point, screen_points[i], new_point); + } + else { + ED_view3d_win_to_3d_on_plane(region, shape_plane, screen_points[i], false, new_point); + madd_v3_v3fl(new_point, shape_normal, depth_back); + } mul_v3_m4v3(trim_operation->mesh->mvert[i + tot_screen_points].co, ob_imat, new_point); mul_v3_m4v3(trim_operation->true_mesh_co[i + tot_screen_points], ob_imat, new_point); } @@ -1224,6 +1356,12 @@ static void sculpt_gesture_init_trim_properties(SculptGestureContext *sgcontext, trim_operation->mode = RNA_enum_get(op->ptr, "trim_mode"); trim_operation->use_cursor_depth = RNA_boolean_get(op->ptr, "use_cursor_depth"); + trim_operation->orientation = RNA_enum_get(op->ptr, "trim_orientation"); + + /* If the cursor was not over the mesh, force the orientation to view. */ + if (!sgcontext->ss->gesture_initial_hit) { + trim_operation->orientation = SCULPT_GESTURE_TRIM_ORIENTATION_VIEW; + } } static void sculpt_trim_gesture_operator_properties(wmOperatorType *ot) @@ -1240,6 +1378,12 @@ static void sculpt_trim_gesture_operator_properties(wmOperatorType *ot) false, "Use Cursor for Depth", "Use cursor location and radius for the dimensions and position of the trimming shape"); + RNA_def_enum(ot->srna, + "trim_orientation", + prop_trim_orientation_types, + SCULPT_GESTURE_TRIM_ORIENTATION_VIEW, + "Shape Orientation", + NULL); } /* Project Gesture Operation. */ @@ -1425,6 +1569,7 @@ static int sculpt_trim_gesture_box_invoke(bContext *C, wmOperator *op, const wmE ss->gesture_initial_hit = SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false); if (ss->gesture_initial_hit) { copy_v3_v3(ss->gesture_initial_location, sgi.location); + copy_v3_v3(ss->gesture_initial_normal, sgi.normal); } return WM_gesture_box_invoke(C, op, event); @@ -1460,6 +1605,7 @@ static int sculpt_trim_gesture_lasso_invoke(bContext *C, wmOperator *op, const w ss->gesture_initial_hit = SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false); if (ss->gesture_initial_hit) { copy_v3_v3(ss->gesture_initial_location, sgi.location); + copy_v3_v3(ss->gesture_initial_normal, sgi.normal); } return WM_gesture_lasso_invoke(C, op, event); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 56b5a494df0..ecd45bfb5e9 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -76,6 +76,11 @@ #include "IMB_colormanagement.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" +#include "GPU_state.h" + #include "WM_api.h" #include "WM_message.h" #include "WM_toolsystem.h" @@ -84,6 +89,7 @@ #include "ED_object.h" #include "ED_screen.h" #include "ED_sculpt.h" +#include "ED_space_api.h" #include "ED_view3d.h" #include "paint_intern.h" #include "sculpt_intern.h" @@ -1159,6 +1165,7 @@ void SCULPT_floodfill_free(SculptFloodFill *flood) flood->queue = NULL; } +/* -------------------------------------------------------------------- */ /** \name Tool Capabilities * * Avoid duplicate checks, internal logic only, @@ -1380,6 +1387,7 @@ static void sculpt_project_v3_normal_align(SculptSession *ss, grab_delta, ss->cache->sculpt_normal_symm, (len_signed * normal_weight) * len_view_scale); } +/* -------------------------------------------------------------------- */ /** \name SculptProjectVector * * Fast-path for #project_plane_v3_v3v3 @@ -1887,6 +1895,7 @@ static float calc_symmetry_feather(Sculpt *sd, StrokeCache *cache) return 1.0f; } +/* -------------------------------------------------------------------- */ /** \name Calculate Normal and Center * * Calculate geometry surrounding the brush center. @@ -2338,7 +2347,7 @@ static float brush_strength(const Sculpt *sd, final_pressure = pressure * pressure; return final_pressure * overlap * feather; case SCULPT_TOOL_SMEAR: - return pressure * overlap * feather; + return alpha * pressure * overlap * feather; case SCULPT_TOOL_CLAY_STRIPS: /* Clay Strips needs less strength to compensate the curve. */ final_pressure = powf(pressure, 1.5f); @@ -3007,6 +3016,7 @@ static void do_mask_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) } } +/* -------------------------------------------------------------------- */ /** \name Sculpt Multires Displacement Eraser Brush * \{ */ @@ -3229,7 +3239,6 @@ static void do_draw_sharp_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to } /* -------------------------------------------------------------------- */ - /** \name Sculpt Topology Brush * \{ */ @@ -3805,20 +3814,33 @@ static void do_grab_brush_task_cb_ex(void *__restrict userdata, ss, &test, data->brush->falloff_shape); const int thread_id = BLI_task_parallel_thread_id(tls); + const bool grab_silhouette = brush->flag2 & BRUSH_GRAB_SILHOUETTE; + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); if (sculpt_brush_test_sq_fn(&test, orig_data.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - orig_data.co, - sqrtf(test.dist), - orig_data.no, - NULL, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + orig_data.co, + sqrtf(test.dist), + orig_data.no, + NULL, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + if (grab_silhouette) { + float silhouette_test_dir[3]; + normalize_v3_v3(silhouette_test_dir, grab_delta); + if (dot_v3v3(ss->cache->initial_normal, ss->cache->grab_delta_symmetry) < 0.0f) { + mul_v3_fl(silhouette_test_dir, -1.0f); + } + float vno[3]; + normal_short_to_float_v3(vno, orig_data.no); + fade *= max_ff(dot_v3v3(vno, silhouette_test_dir), 0.0f); + } mul_v3_v3fl(proxy[vd.i], grab_delta, fade); @@ -4752,7 +4774,6 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno } /* -------------------------------------------------------------------- */ - /** \name Sculpt Clay Brush * \{ */ @@ -5277,7 +5298,6 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod } /* -------------------------------------------------------------------- */ - /** \name Sculpt Clay Thumb Brush * \{ */ @@ -5666,15 +5686,11 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe /* Check for unsupported features. */ PBVHType type = BKE_pbvh_type(ss->pbvh); if (brush->sculpt_tool == SCULPT_TOOL_PAINT && type != PBVH_FACES) { - if (!U.experimental.use_sculpt_vertex_colors) { - return; - } + return; } if (brush->sculpt_tool == SCULPT_TOOL_SMEAR && type != PBVH_FACES) { - if (!U.experimental.use_sculpt_vertex_colors) { - return; - } + return; } /* Build a list of all nodes that are potentially within the brush's area of influence */ @@ -8126,6 +8142,7 @@ static void SCULPT_OT_symmetrize(wmOperatorType *ot) /**** Toggle operator for turning sculpt mode on or off ****/ +/** \warning Expects a fully evaluated depsgraph. */ static void sculpt_init_session(Depsgraph *depsgraph, Scene *scene, Object *ob) { /* Create persistent sculpt mode data. */ @@ -8190,6 +8207,7 @@ void ED_object_sculptmode_enter_ex(Main *bmain, if (flush_recalc) { DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + BKE_scene_graph_evaluated_ensure(depsgraph, bmain); } /* Create sculpt mode session data. */ @@ -8197,10 +8215,6 @@ void ED_object_sculptmode_enter_ex(Main *bmain, BKE_sculptsession_free(ob); } - /* Make sure derived final from original object does not reference possibly - * freed memory. */ - BKE_object_free_derived_caches(ob); - /* Copy the current mesh visibility to the Face Sets. */ BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(me); @@ -9231,6 +9245,325 @@ static void SCULPT_OT_mask_by_color(wmOperatorType *ot) 1.0f); } +/* -------------------------------------------------------------------- */ +/** \name Dyntopo Detail Size Edit Operator + * \{ */ + +/* Defines how much the mouse movement will modify the detail size value. */ +#define DETAIL_SIZE_DELTA_SPEED 0.08f +#define DETAIL_SIZE_DELTA_ACCURATE_SPEED 0.004f + +typedef struct DyntopoDetailSizeEditCustomData { + void *draw_handle; + Object *active_object; + + float init_mval[2]; + float accurate_mval[2]; + + float outline_col[4]; + + bool accurate_mode; + bool sample_mode; + + float init_detail_size; + float accurate_detail_size; + float detail_size; + float radius; + + float preview_tri[3][3]; + float gizmo_mat[4][4]; +} DyntopoDetailSizeEditCustomData; + +static void dyntopo_detail_size_parallel_lines_draw(uint pos3d, + DyntopoDetailSizeEditCustomData *cd, + const float start_co[3], + const float end_co[3], + bool flip, + const float angle) +{ + float object_space_constant_detail = 1.0f / + (cd->detail_size * mat4_to_scale(cd->active_object->obmat)); + + /* The constant detail represents the maximum edge length allowed before subdividing it. If the + * triangle grid preview is created with this value it will represent an ideal mesh density where + * all edges have the exact maximum length, which never happens in practice. As the minimum edge + * length for dyntopo is 0.4 * max_edge_length, this adjust the detail size to the average + * between max and min edge length so the preview is more accurate. */ + object_space_constant_detail *= 0.7f; + + const float total_len = len_v3v3(cd->preview_tri[0], cd->preview_tri[1]); + const int tot_lines = (int)(total_len / object_space_constant_detail) + 1; + const float tot_lines_fl = total_len / object_space_constant_detail; + float spacing_disp[3]; + sub_v3_v3v3(spacing_disp, end_co, start_co); + normalize_v3(spacing_disp); + + float line_disp[3]; + rotate_v2_v2fl(line_disp, spacing_disp, DEG2RAD(angle)); + mul_v3_fl(spacing_disp, total_len / tot_lines_fl); + + immBegin(GPU_PRIM_LINES, (uint)tot_lines * 2); + for (int i = 0; i < tot_lines; i++) { + float line_length; + if (flip) { + line_length = total_len * ((float)i / (float)tot_lines_fl); + } + else { + line_length = total_len * (1.0f - ((float)i / (float)tot_lines_fl)); + } + float line_start[3]; + copy_v3_v3(line_start, start_co); + madd_v3_v3v3fl(line_start, line_start, spacing_disp, i); + float line_end[3]; + madd_v3_v3v3fl(line_end, line_start, line_disp, line_length); + immVertex3fv(pos3d, line_start); + immVertex3fv(pos3d, line_end); + } + immEnd(); +} + +static void dyntopo_detail_size_edit_draw(const bContext *UNUSED(C), + ARegion *UNUSED(ar), + void *arg) +{ + DyntopoDetailSizeEditCustomData *cd = arg; + GPU_blend(GPU_BLEND_ALPHA); + GPU_line_smooth(true); + + uint pos3d = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + GPU_matrix_push(); + GPU_matrix_mul(cd->gizmo_mat); + + /* Draw Cursor */ + immUniformColor4fv(cd->outline_col); + GPU_line_width(3.0f); + + imm_draw_circle_wire_3d(pos3d, 0, 0, cd->radius, 80); + + /* Draw Triangle. */ + immUniformColor4f(0.9f, 0.9f, 0.9f, 0.8f); + immBegin(GPU_PRIM_LINES, 6); + immVertex3fv(pos3d, cd->preview_tri[0]); + immVertex3fv(pos3d, cd->preview_tri[1]); + + immVertex3fv(pos3d, cd->preview_tri[1]); + immVertex3fv(pos3d, cd->preview_tri[2]); + + immVertex3fv(pos3d, cd->preview_tri[2]); + immVertex3fv(pos3d, cd->preview_tri[0]); + immEnd(); + + /* Draw Grid */ + GPU_line_width(1.0f); + dyntopo_detail_size_parallel_lines_draw( + pos3d, cd, cd->preview_tri[0], cd->preview_tri[1], false, 60.0f); + dyntopo_detail_size_parallel_lines_draw( + pos3d, cd, cd->preview_tri[0], cd->preview_tri[1], true, 120.0f); + dyntopo_detail_size_parallel_lines_draw( + pos3d, cd, cd->preview_tri[0], cd->preview_tri[2], false, -60.0f); + GPU_matrix_pop(); + + GPU_blend(GPU_BLEND_NONE); + GPU_line_smooth(false); +} + +static void dyntopo_detail_size_edit_cancel(bContext *C, wmOperator *op) +{ + Object *active_object = CTX_data_active_object(C); + SculptSession *ss = active_object->sculpt; + ARegion *ar = CTX_wm_region(C); + DyntopoDetailSizeEditCustomData *cd = op->customdata; + ED_region_draw_cb_exit(ar->type, cd->draw_handle); + ss->draw_faded_cursor = false; + MEM_freeN(op->customdata); + ED_workspace_status_text(C, NULL); +} + +static void dyntopo_detail_size_sample_from_surface(Object *ob, + DyntopoDetailSizeEditCustomData *cd) +{ + SculptSession *ss = ob->sculpt; + const int active_vertex = SCULPT_active_vertex_get(ss); + + float len_accum = 0; + int num_neighbors = 0; + SculptVertexNeighborIter ni; + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, active_vertex, ni) { + len_accum += len_v3v3(SCULPT_vertex_co_get(ss, active_vertex), + SCULPT_vertex_co_get(ss, ni.index)); + num_neighbors++; + } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); + + if (num_neighbors > 0) { + const float avg_edge_len = len_accum / num_neighbors; + /* Use 0.7 as the average of min and max dyntopo edge length. */ + const float detail_size = 0.7f / (avg_edge_len * mat4_to_scale(cd->active_object->obmat)); + cd->detail_size = clamp_f(detail_size, 1.0f, 500.0f); + } +} + +static void dyntopo_detail_size_update_from_mouse_delta(DyntopoDetailSizeEditCustomData *cd, + const wmEvent *event) +{ + const float mval[2] = {event->mval[0], event->mval[1]}; + + float detail_size_delta; + if (cd->accurate_mode) { + detail_size_delta = mval[0] - cd->accurate_mval[0]; + cd->detail_size = cd->accurate_detail_size + + detail_size_delta * DETAIL_SIZE_DELTA_ACCURATE_SPEED; + } + else { + detail_size_delta = mval[0] - cd->init_mval[0]; + cd->detail_size = cd->init_detail_size + detail_size_delta * DETAIL_SIZE_DELTA_SPEED; + } + + if (event->type == EVT_LEFTSHIFTKEY && event->val == KM_PRESS) { + cd->accurate_mode = true; + copy_v2_v2(cd->accurate_mval, mval); + cd->accurate_detail_size = cd->detail_size; + } + if (event->type == EVT_LEFTSHIFTKEY && event->val == KM_RELEASE) { + cd->accurate_mode = false; + cd->accurate_detail_size = 0.0f; + } + + cd->detail_size = clamp_f(cd->detail_size, 1.0f, 500.0f); +} + +static int dyntopo_detail_size_edit_modal(bContext *C, wmOperator *op, const wmEvent *event) +{ + Object *active_object = CTX_data_active_object(C); + SculptSession *ss = active_object->sculpt; + ARegion *ar = CTX_wm_region(C); + DyntopoDetailSizeEditCustomData *cd = op->customdata; + Sculpt *sd = CTX_data_tool_settings(C)->sculpt; + + /* Cancel modal operator */ + if ((event->type == EVT_ESCKEY && event->val == KM_PRESS) || + (event->type == RIGHTMOUSE && event->val == KM_PRESS)) { + dyntopo_detail_size_edit_cancel(C, op); + ED_region_tag_redraw(ar); + return OPERATOR_FINISHED; + } + + /* Finish modal operator */ + if ((event->type == LEFTMOUSE && event->val == KM_RELEASE) || + (event->type == EVT_RETKEY && event->val == KM_PRESS) || + (event->type == EVT_PADENTER && event->val == KM_PRESS)) { + ED_region_draw_cb_exit(ar->type, cd->draw_handle); + sd->constant_detail = cd->detail_size; + ss->draw_faded_cursor = false; + MEM_freeN(op->customdata); + ED_region_tag_redraw(ar); + ED_workspace_status_text(C, NULL); + return OPERATOR_FINISHED; + } + + ED_region_tag_redraw(ar); + + if (event->type == EVT_LEFTCTRLKEY && event->val == KM_PRESS) { + cd->sample_mode = true; + } + if (event->type == EVT_LEFTCTRLKEY && event->val == KM_RELEASE) { + cd->sample_mode = false; + } + + /* Sample mode sets the detail size sampling the average edge length under the surface. */ + if (cd->sample_mode) { + dyntopo_detail_size_sample_from_surface(active_object, cd); + return OPERATOR_RUNNING_MODAL; + } + /* Regular mode, changes the detail size by moving the cursor. */ + dyntopo_detail_size_update_from_mouse_delta(cd, event); + + return OPERATOR_RUNNING_MODAL; +} + +static int dyntopo_detail_size_edit_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + ARegion *ar = CTX_wm_region(C); + Object *active_object = CTX_data_active_object(C); + Sculpt *sd = CTX_data_tool_settings(C)->sculpt; + Brush *brush = BKE_paint_brush(&sd->paint); + + DyntopoDetailSizeEditCustomData *cd = MEM_callocN(sizeof(DyntopoDetailSizeEditCustomData), + "Dyntopo Detail Size Edit OP Custom Data"); + + /* Initial operator Custom Data setup. */ + cd->draw_handle = ED_region_draw_cb_activate( + ar->type, dyntopo_detail_size_edit_draw, cd, REGION_DRAW_POST_VIEW); + cd->active_object = active_object; + cd->init_mval[0] = event->mval[0]; + cd->init_mval[1] = event->mval[1]; + cd->detail_size = sd->constant_detail; + cd->init_detail_size = sd->constant_detail; + copy_v4_v4(cd->outline_col, brush->add_col); + op->customdata = cd; + + SculptSession *ss = active_object->sculpt; + cd->radius = ss->cursor_radius; + + /* Generates the matrix to position the gizmo in the surface of the mesh using the same location + * and orientation as the brush cursor. */ + float cursor_trans[4][4], cursor_rot[4][4]; + const float z_axis[4] = {0.0f, 0.0f, 1.0f, 0.0f}; + float quat[4]; + copy_m4_m4(cursor_trans, active_object->obmat); + translate_m4( + cursor_trans, ss->cursor_location[0], ss->cursor_location[1], ss->cursor_location[2]); + rotation_between_vecs_to_quat(quat, z_axis, ss->cursor_normal); + quat_to_mat4(cursor_rot, quat); + copy_m4_m4(cd->gizmo_mat, cursor_trans); + mul_m4_m4_post(cd->gizmo_mat, cursor_rot); + + /* Initize the position of the triangle vertices. */ + const float y_axis[3] = {0.0f, cd->radius, 0.0f}; + for (int i = 0; i < 3; i++) { + zero_v3(cd->preview_tri[i]); + rotate_v2_v2fl(cd->preview_tri[i], y_axis, DEG2RAD(120.0f * i)); + } + + SCULPT_vertex_random_access_ensure(ss); + + WM_event_add_modal_handler(C, op); + ED_region_tag_redraw(ar); + + ss->draw_faded_cursor = true; + + const char *status_str = TIP_( + "Move the mouse to change the dyntopo detail size. LMB: confirm size, ESC/RMB: cancel"); + ED_workspace_status_text(C, status_str); + + return OPERATOR_RUNNING_MODAL; +} + +static bool dyntopo_detail_size_edit_poll(bContext *C) +{ + Object *ob = CTX_data_active_object(C); + Sculpt *sd = CTX_data_tool_settings(C)->sculpt; + + return SCULPT_mode_poll(C) && ob->sculpt->bm && (sd->flags & SCULPT_DYNTOPO_DETAIL_CONSTANT); +} + +static void SCULPT_OT_dyntopo_detail_size_edit(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Edit Dyntopo Detail Size"; + ot->description = "Modify the constant detail size of dyntopo interactively"; + ot->idname = "SCULPT_OT_dyntopo_detail_size_edit"; + + /* api callbacks */ + ot->poll = dyntopo_detail_size_edit_poll; + ot->invoke = dyntopo_detail_size_edit_invoke; + ot->modal = dyntopo_detail_size_edit_modal; + ot->cancel = dyntopo_detail_size_edit_cancel; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + void ED_operatortypes_sculpt(void) { WM_operatortype_append(SCULPT_OT_brush_stroke); @@ -9264,4 +9597,5 @@ void ED_operatortypes_sculpt(void) WM_operatortype_append(SCULPT_OT_vertex_to_loop_colors); WM_operatortype_append(SCULPT_OT_color_filter); WM_operatortype_append(SCULPT_OT_mask_by_color); + WM_operatortype_append(SCULPT_OT_dyntopo_detail_size_edit); } diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c index 67129d5da50..20b164fa80c 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.c +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c @@ -139,14 +139,14 @@ static float cloth_brush_simulation_falloff_get(const Brush *brush, const float falloff = radius + (radius * brush->cloth_sim_limit * brush->cloth_sim_falloff); if (distance > limit) { - /* Outiside the limits. */ + /* Outside the limits. */ return 0.0f; } if (distance < falloff) { /* Before the falloff area. */ return 1.0f; } - /* Do a smoothstep transition inside the falloff area. */ + /* Do a smooth-step transition inside the falloff area. */ float p = 1.0f - ((distance - falloff) / (limit - falloff)); return 3.0f * p * p - 2.0f * p * p * p; } @@ -214,7 +214,7 @@ static void cloth_brush_add_length_constraint(SculptSession *ss, /* Reallocation if the array capacity is exceeded. */ cloth_brush_reallocate_constraints(cloth_sim); - /* Add the constraint to the GSet to avoid creating it again. */ + /* Add the constraint to the #GSet to avoid creating it again. */ BLI_edgeset_add(cloth_sim->created_length_constraints, v1, v2); } @@ -326,12 +326,15 @@ static void do_cloth_brush_build_constraints_task_cb_ex( * positions. */ const bool cloth_is_deform_brush = ss->cache != NULL && brush != NULL && SCULPT_is_cloth_deform_brush(brush); + + const bool use_falloff_plane = brush->cloth_force_falloff_type == + BRUSH_CLOTH_FORCE_FALLOFF_PLANE; float radius_squared = 0.0f; if (cloth_is_deform_brush) { radius_squared = ss->cache->initial_radius * ss->cache->initial_radius; } - /* Only limit the contraint creation to a radius when the simulation is local. */ + /* Only limit the constraint creation to a radius when the simulation is local. */ const float cloth_sim_radius_squared = brush->cloth_simulation_area_type == BRUSH_CLOTH_SIMULATION_AREA_LOCAL ? data->cloth_sim_radius * data->cloth_sim_radius : @@ -380,12 +383,21 @@ static void do_cloth_brush_build_constraints_task_cb_ex( if (brush && brush->sculpt_tool == SCULPT_TOOL_CLOTH) { /* The cloth brush works by applying forces in most of its modes, but some of them require * deformation coordinates to make the simulation stable. */ - if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB && len_squared < radius_squared) { - /* When the grab brush brush is used as part of the cloth brush, deformation constraints - * are created with different strengths and only inside the radius of the brush. */ - const float fade = BKE_brush_curve_strength(brush, sqrtf(len_squared), ss->cache->radius); - cloth_brush_add_deformation_constraint( - data->cloth_sim, node_index, vd.index, fade * CLOTH_DEFORMATION_GRAB_STRENGTH); + if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB) { + if (use_falloff_plane) { + /* With plane falloff the strength of the constraints is set when applying the + * deformation forces. */ + cloth_brush_add_deformation_constraint( + data->cloth_sim, node_index, vd.index, CLOTH_DEFORMATION_GRAB_STRENGTH); + } + else if (len_squared < radius_squared) { + /* With radial falloff deformation constraints are created with different strengths and + * only inside the radius of the brush. */ + const float fade = BKE_brush_curve_strength( + brush, sqrtf(len_squared), ss->cache->radius); + cloth_brush_add_deformation_constraint( + data->cloth_sim, node_index, vd.index, fade * CLOTH_DEFORMATION_GRAB_STRENGTH); + } } else if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_SNAKE_HOOK) { /* Cloth Snake Hook creates deformation constraint with fixed strength because the strength @@ -436,9 +448,8 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, const float *grab_delta = data->grab_delta; float(*imat)[4] = data->mat; - const bool use_falloff_plane = !SCULPT_is_cloth_deform_brush(brush) && - brush->cloth_force_falloff_type == - BRUSH_CLOTH_FORCE_FALLOFF_PLANE; + const bool use_falloff_plane = brush->cloth_force_falloff_type == + BRUSH_CLOTH_FORCE_FALLOFF_PLANE; PBVHVertexIter vd; const float bstrength = ss->cache->bstrength; @@ -448,7 +459,7 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, ss, &test, data->brush->falloff_shape); const int thread_id = BLI_task_parallel_thread_id(tls); - /* For Pich Perpendicular Deform Type. */ + /* For Pinch Perpendicular Deform Type. */ float x_object_space[3]; float z_object_space[3]; if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_PINCH_PERPENDICULAR) { @@ -470,12 +481,6 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, madd_v3_v3fl(gravity, ss->cache->gravity_direction, -data->sd->gravity_factor); } - /* Original data for deform brushes. */ - SculptOrigVertData orig_data; - if (SCULPT_is_cloth_deform_brush(brush)) { - SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]); - } - BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { float force[3]; @@ -486,8 +491,7 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, float current_vertex_location[3]; if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB) { - SCULPT_orig_vert_data_update(&orig_data, &vd); - copy_v3_v3(current_vertex_location, orig_data.co); + copy_v3_v3(current_vertex_location, ss->cache->cloth_sim->init_pos[vd.index]); } else { copy_v3_v3(current_vertex_location, vd.co); @@ -504,7 +508,7 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, float dist = sqrtf(test.dist); if (use_falloff_plane) { - dist = dist_to_plane_v3(vd.co, deform_plane); + dist = dist_to_plane_v3(current_vertex_location, deform_plane); } const float fade = sim_factor * bstrength * @@ -539,9 +543,15 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, break; case BRUSH_CLOTH_DEFORM_GRAB: madd_v3_v3v3fl(cloth_sim->deformation_pos[vd.index], - orig_data.co, + cloth_sim->init_pos[vd.index], ss->cache->grab_delta_symmetry, fade); + if (use_falloff_plane) { + cloth_sim->deformation_strength[vd.index] = clamp_f(fade, 0.0f, 1.0f); + } + else { + cloth_sim->deformation_strength[vd.index] = 1.0f; + } zero_v3(force); break; case BRUSH_CLOTH_DEFORM_SNAKE_HOOK: @@ -920,7 +930,7 @@ static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, PBVHNode **nod BKE_curvemapping_init(brush->curve); - /* Init the grab delta. */ + /* Initialize the grab delta. */ copy_v3_v3(grab_delta, ss->cache->grab_delta_symmetry); normalize_v3(grab_delta); @@ -930,7 +940,7 @@ static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, PBVHNode **nod return; } - /* Calcuate push offset. */ + /* Calculate push offset. */ if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_PUSH) { mul_v3_v3fl(offset, ss->cache->sculpt_normal_symm, ss->cache->radius); @@ -944,7 +954,7 @@ static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, PBVHNode **nod brush->cloth_force_falloff_type == BRUSH_CLOTH_FORCE_FALLOFF_PLANE) { SCULPT_calc_brush_plane(sd, ob, nodes, totnode, area_no, area_co); - /* Init stroke local space matrix. */ + /* Initialize stroke local space matrix. */ cross_v3_v3v3(mat[0], area_no, ss->cache->grab_delta_symmetry); mat[0][3] = 0.0f; cross_v3_v3v3(mat[1], area_no, mat[0]); @@ -965,8 +975,8 @@ static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, PBVHNode **nod } } - if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_SNAKE_HOOK) { - /* Set the deformation strength to 0. Snake hook will initialize the strength in the required + if (ELEM(brush->cloth_deform_type, BRUSH_CLOTH_DEFORM_SNAKE_HOOK, BRUSH_CLOTH_DEFORM_GRAB)) { + /* Set the deformation strength to 0. Brushes will initialize the strength in the required * area. */ const int totverts = SCULPT_vertex_count_get(ss); for (int i = 0; i < totverts; i++) { @@ -1058,7 +1068,7 @@ void SCULPT_cloth_brush_ensure_nodes_constraints( PBVHNode **nodes, int totnode, SculptClothSimulation *cloth_sim, - /* Cannot be const, because it is assigned to a non-const variable. + /* Cannot be `const`, because it is assigned to a `non-const` variable. * NOLINTNEXTLINE: readability-non-const-parameter. */ float initial_location[3], const float radius) @@ -1178,7 +1188,7 @@ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode sculpt_cloth_ensure_constraints_in_simulation_area(sd, ob, nodes, totnode); } /* The first step of a symmetry pass is never simulated as deformation modes need valid delta - * for brush tip alignement. */ + * for brush tip alignment. */ return; } @@ -1253,9 +1263,14 @@ void SCULPT_cloth_plane_falloff_preview_draw(const uint gpuattr, const float outline_col[3], float outline_alpha) { - float local_mat_inv[4][4]; - invert_m4_m4(local_mat_inv, ss->cache->stroke_local_mat); - GPU_matrix_mul(ss->cache->stroke_local_mat); + float local_mat[4][4]; + copy_m4_m4(local_mat, ss->cache->stroke_local_mat); + + if (ss->cache->brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB) { + add_v3_v3v3(local_mat[3], ss->cache->true_location, ss->cache->grab_delta); + } + + GPU_matrix_mul(local_mat); const float dist = ss->cache->radius; const float arrow_x = ss->cache->radius * 0.2f; @@ -1299,7 +1314,7 @@ static EnumPropertyItem prop_cloth_filter_type[] = { "SCALE", 0, "Scale", - "Scales the mesh as a softbody using the origin of the object as scale"}, + "Scales the mesh as a soft-body using the origin of the object as scale"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.c index af6a06caf69..3c87407b2db 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.c +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.c @@ -1018,6 +1018,7 @@ void SCULPT_OT_face_sets_randomize_colors(wmOperatorType *ot) typedef enum eSculptFaceSetEditMode { SCULPT_FACE_SET_EDIT_GROW = 0, SCULPT_FACE_SET_EDIT_SHRINK = 1, + SCULPT_FACE_SET_EDIT_DELETE_GEOMETRY = 2, } eSculptFaceSetEditMode; static EnumPropertyItem prop_sculpt_face_sets_edit_types[] = { @@ -1035,6 +1036,13 @@ static EnumPropertyItem prop_sculpt_face_sets_edit_types[] = { "Shrink Face Set", "Shrinks the Face Sets boundary by one face based on mesh topology", }, + { + SCULPT_FACE_SET_EDIT_DELETE_GEOMETRY, + "DELETE_GEOMETRY", + 0, + "Delete Geometry", + "Deletes the faces that are assigned to the Face Set", + }, {0, NULL, 0, NULL, NULL}, }; @@ -1096,6 +1104,78 @@ static void sculpt_face_set_shrink(Object *ob, } } +static bool check_single_face_set(SculptSession *ss, int *face_sets, const bool check_visible_only) +{ + + int first_face_set = SCULPT_FACE_SET_NONE; + if (check_visible_only) { + for (int f = 0; f < ss->totfaces; f++) { + if (face_sets[f] > 0) { + first_face_set = face_sets[f]; + break; + } + } + } + else { + first_face_set = abs(face_sets[0]); + } + + if (first_face_set == SCULPT_FACE_SET_NONE) { + return true; + } + + for (int f = 0; f < ss->totfaces; f++) { + const int face_set_id = check_visible_only ? face_sets[f] : abs(face_sets[f]); + if (face_set_id != first_face_set) { + return false; + } + } + return true; +} + +static void sculpt_face_set_delete_geometry(Object *ob, + SculptSession *ss, + const int active_face_set_id, + const bool modify_hidden) +{ + + Mesh *mesh = ob->data; + const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh); + BMesh *bm = BM_mesh_create(&allocsize, + &((struct BMeshCreateParams){ + .use_toolflags = true, + })); + + BM_mesh_bm_from_me(bm, + mesh, + (&(struct BMeshFromMeshParams){ + .calc_face_normal = true, + })); + + BM_mesh_elem_table_init(bm, BM_FACE); + BM_mesh_elem_table_ensure(bm, BM_FACE); + BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false); + BMIter iter; + BMFace *f; + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + const int face_index = BM_elem_index_get(f); + const int face_set_id = modify_hidden ? abs(ss->face_sets[face_index]) : + ss->face_sets[face_index]; + BM_elem_flag_set(f, BM_ELEM_TAG, face_set_id == active_face_set_id); + } + BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_FACES); + BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false); + + BM_mesh_bm_to_me(NULL, + bm, + ob->data, + (&(struct BMeshToMeshParams){ + .calc_object_remap = false, + })); + + BM_mesh_free(bm); +} + static void sculpt_face_set_apply_edit(Object *ob, const int active_face_set_id, const int mode, @@ -1103,80 +1183,135 @@ static void sculpt_face_set_apply_edit(Object *ob, { SculptSession *ss = ob->sculpt; - int *prev_face_sets = MEM_dupallocN(ss->face_sets); - switch (mode) { - case SCULPT_FACE_SET_EDIT_GROW: + case SCULPT_FACE_SET_EDIT_GROW: { + int *prev_face_sets = MEM_dupallocN(ss->face_sets); sculpt_face_set_grow(ob, ss, prev_face_sets, active_face_set_id, modify_hidden); + MEM_SAFE_FREE(prev_face_sets); break; - case SCULPT_FACE_SET_EDIT_SHRINK: + } + case SCULPT_FACE_SET_EDIT_SHRINK: { + int *prev_face_sets = MEM_dupallocN(ss->face_sets); sculpt_face_set_shrink(ob, ss, prev_face_sets, active_face_set_id, modify_hidden); + MEM_SAFE_FREE(prev_face_sets); + break; + } + case SCULPT_FACE_SET_EDIT_DELETE_GEOMETRY: + sculpt_face_set_delete_geometry(ob, ss, active_face_set_id, modify_hidden); break; } - - MEM_SAFE_FREE(prev_face_sets); } -static int sculpt_face_set_edit_invoke(bContext *C, wmOperator *op, const wmEvent *event) +static bool sculpt_face_set_edit_is_operation_valid(SculptSession *ss, + const eSculptFaceSetEditMode mode, + const bool modify_hidden) { - Object *ob = CTX_data_active_object(C); - SculptSession *ss = ob->sculpt; - Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); - - const int mode = RNA_enum_get(op->ptr, "mode"); - - /* Dyntopo not supported. */ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { + /* Dyntopo is not supported. */ return OPERATOR_CANCELLED; } - /* Ignore other events to avoid repeated operations. */ - if (event->val != KM_PRESS) { - return OPERATOR_CANCELLED; + if (mode == SCULPT_FACE_SET_EDIT_DELETE_GEOMETRY) { + if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) { + /* Modification of base mesh geometry requires special remapping of multires displacement, + * which does not happen here. + * Disable delete operation. It can be supported in the future by doing similar displacement + * data remapping as what happens in the mesh edit mode. */ + return false; + } + if (check_single_face_set(ss, ss->face_sets, !modify_hidden)) { + /* Cancel the operator if the mesh only contains one Face Set to avoid deleting the + * entire object. */ + return false; + } } + return true; +} - BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false); +static void sculpt_face_set_edit_modify_geometry(bContext *C, + Object *ob, + const int active_face_set, + const eSculptFaceSetEditMode mode, + const bool modify_hidden) +{ + ED_sculpt_undo_geometry_begin(ob, "edit face set delete geometry"); + sculpt_face_set_apply_edit(ob, abs(active_face_set), mode, modify_hidden); + ED_sculpt_undo_geometry_end(ob); + BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL); + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); +} - /* Update the current active Face Set and Vertex as the operator can be used directly from the - * tool without brush cursor. */ - SculptCursorGeometryInfo sgi; - float mouse[2]; - mouse[0] = event->mval[0]; - mouse[1] = event->mval[1]; - SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false); +static void face_set_edit_do_post_visibility_updates(Object *ob, PBVHNode **nodes, int totnode) +{ + SculptSession *ss = ob->sculpt; + PBVH *pbvh = ss->pbvh; + + /* Sync face sets visibility and vertex visibility as now all Face Sets are visible. */ + SCULPT_visibility_sync_all_face_sets_to_vertices(ob); + + for (int i = 0; i < totnode; i++) { + BKE_pbvh_node_mark_update_visibility(nodes[i]); + } + + BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateVisibility); + + if (BKE_pbvh_type(pbvh) == PBVH_FACES) { + BKE_mesh_flush_hidden_from_verts(ob->data); + } +} +static void sculpt_face_set_edit_modify_face_sets(Object *ob, + const int active_face_set, + const eSculptFaceSetEditMode mode, + const bool modify_hidden) +{ PBVH *pbvh = ob->sculpt->pbvh; PBVHNode **nodes; int totnode; BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode); if (!nodes) { - return OPERATOR_CANCELLED; + return; } - SCULPT_undo_push_begin("face set edit"); SCULPT_undo_push_node(ob, nodes[0], SCULPT_UNDO_FACE_SETS); - - const int active_face_set = SCULPT_active_face_set_get(ss); - const bool modify_hidden = RNA_boolean_get(op->ptr, "modify_hidden"); - sculpt_face_set_apply_edit(ob, abs(active_face_set), mode, modify_hidden); - SCULPT_undo_push_end(); + face_set_edit_do_post_visibility_updates(ob, nodes, totnode); + MEM_freeN(nodes); +} - /* Sync face sets visibility and vertex visibility as now all Face Sets are visible. */ - SCULPT_visibility_sync_all_face_sets_to_vertices(ob); +static int sculpt_face_set_edit_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + Object *ob = CTX_data_active_object(C); + SculptSession *ss = ob->sculpt; + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); - for (int i = 0; i < totnode; i++) { - BKE_pbvh_node_mark_update_visibility(nodes[i]); + const int mode = RNA_enum_get(op->ptr, "mode"); + const bool modify_hidden = RNA_boolean_get(op->ptr, "modify_hidden"); + + if (!sculpt_face_set_edit_is_operation_valid(ss, mode, modify_hidden)) { + return OPERATOR_CANCELLED; } - BKE_pbvh_update_vertex_data(ss->pbvh, PBVH_UpdateVisibility); + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false); - MEM_SAFE_FREE(nodes); + /* Update the current active Face Set and Vertex as the operator can be used directly from the + * tool without brush cursor. */ + SculptCursorGeometryInfo sgi; + const float mouse[2] = {event->mval[0], event->mval[1]}; + SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false); + const int active_face_set = SCULPT_active_face_set_get(ss); - if (BKE_pbvh_type(pbvh) == PBVH_FACES) { - BKE_mesh_flush_hidden_from_verts(ob->data); + switch (mode) { + case SCULPT_FACE_SET_EDIT_DELETE_GEOMETRY: + sculpt_face_set_edit_modify_geometry(C, ob, active_face_set, mode, modify_hidden); + break; + case SCULPT_FACE_SET_EDIT_GROW: + case SCULPT_FACE_SET_EDIT_SHRINK: + sculpt_face_set_edit_modify_face_sets(ob, active_face_set, mode, modify_hidden); + break; } SCULPT_tag_update_overlays(C); diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index f1410ffad1b..f4f30c903aa 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -1477,8 +1477,6 @@ static void sculpt_undosys_step_decode( { Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - /* Sculpt needs evaluated state. */ - BKE_scene_view_layer_graph_evaluated_ensure(bmain, scene, view_layer); Object *ob = OBACT(view_layer); if (ob && (ob->type == OB_MESH)) { if (ob->mode & OB_MODE_SCULPT) { @@ -1486,6 +1484,12 @@ static void sculpt_undosys_step_decode( } else { ED_object_mode_generic_exit(bmain, depsgraph, scene, ob); + + /* Sculpt needs evaluated state. + * Note: needs to be done here, as #ED_object_mode_generic_exit will usually invalidate + * (some) evaluated data. */ + BKE_scene_graph_evaluated_ensure(depsgraph, bmain); + Mesh *me = ob->data; /* Don't add sculpt topology undo steps when reading back undo state. * The undo steps must enter/exit for us. */ diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index e5f6b61a2ae..8e2bb6a4813 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -46,13 +46,14 @@ #include "BKE_packedFile.h" #include "BKE_report.h" #include "BKE_scene.h" -#include "BKE_sequencer.h" #include "BKE_sound.h" #include "RNA_access.h" #include "RNA_define.h" #include "RNA_enum_types.h" +#include "SEQ_sequencer.h" + #include "UI_interface.h" #include "WM_api.h" @@ -170,7 +171,7 @@ static void SOUND_OT_open(wmOperatorType *ot) FILE_OPENFILE, WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory"); RNA_def_boolean(ot->srna, "mono", false, "Mono", "Merge all the sound's channels into one"); } @@ -197,7 +198,7 @@ static void SOUND_OT_open_mono(wmOperatorType *ot) FILE_OPENFILE, WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory"); RNA_def_boolean(ot->srna, "mono", true, "Mono", "Mixdown the sound to mono"); } @@ -721,7 +722,7 @@ static void SOUND_OT_mixdown(wmOperatorType *ot) FILE_SAVE, WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_SHOW_PROPS, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); #ifdef WITH_AUDASPACE RNA_def_int( ot->srna, diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index 60ce86740cd..8fc16e66466 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -56,6 +56,7 @@ #include "RNA_access.h" +#include "ED_buttons.h" #include "ED_physics.h" #include "ED_screen.h" @@ -512,11 +513,11 @@ static bool buttons_context_linestyle_pinnable(const bContext *C, ViewLayer *vie } #endif -static bool buttons_context_path(const bContext *C, ButsContextPath *path, int mainb, int flag) +static bool buttons_context_path( + const bContext *C, SpaceProperties *sbuts, ButsContextPath *path, int mainb, int flag) { /* Note we don't use CTX_data here, instead we get it from the window. * Otherwise there is a loop reading the context that we are setting. */ - SpaceProperties *sbuts = CTX_wm_space_properties(C); wmWindow *window = CTX_wm_window(C); Scene *scene = WM_window_get_active_scene(window); ViewLayer *view_layer = WM_window_get_active_view_layer(window); @@ -660,14 +661,14 @@ void buttons_context_compute(const bContext *C, SpaceProperties *sbuts) int flag = 0; /* Set scene path. */ - buttons_context_path(C, path, BCONTEXT_SCENE, pflag); + buttons_context_path(C, sbuts, path, BCONTEXT_SCENE, pflag); buttons_texture_context_compute(C, sbuts); /* for each context, see if we can compute a valid path to it, if * this is the case, we know we have to display the button */ for (int i = 0; i < BCONTEXT_TOT; i++) { - if (buttons_context_path(C, path, i, pflag)) { + if (buttons_context_path(C, sbuts, path, i, pflag)) { flag |= (1 << i); /* setting icon for data context */ @@ -713,7 +714,7 @@ void buttons_context_compute(const bContext *C, SpaceProperties *sbuts) } } - buttons_context_path(C, path, sbuts->mainb, pflag); + buttons_context_path(C, sbuts, path, sbuts->mainb, pflag); if (!(flag & (1 << sbuts->mainb))) { if (flag & (1 << BCONTEXT_OBJECT)) { @@ -734,6 +735,39 @@ void buttons_context_compute(const bContext *C, SpaceProperties *sbuts) sbuts->pathflag = flag; } +static bool is_pointer_in_path(ButsContextPath *path, PointerRNA *ptr) +{ + for (int i = 0; i < path->len; ++i) { + if (ptr->owner_id == path->ptr[i].owner_id) { + return true; + } + } + return false; +} + +void ED_buttons_set_context(const bContext *C, PointerRNA *ptr, const int context) +{ + ScrArea *active_area = CTX_wm_area(C); + bScreen *screen = CTX_wm_screen(C); + + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + /* Only update for properties editors that are visible and share a border. */ + if (area->spacetype != SPACE_PROPERTIES) { + continue; + } + if (!ED_area_has_shared_border(active_area, area)) { + continue; + } + + SpaceProperties *sbuts = (SpaceProperties *)area->spacedata.first; + ButsContextPath path; + if (buttons_context_path(C, sbuts, &path, context, 0) && is_pointer_in_path(&path, ptr)) { + sbuts->mainbuser = context; + sbuts->mainb = sbuts->mainbuser; + } + } +} + /************************* Context Callback ************************/ const char *buttons_context_dir[] = { diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c index 87cf8507dd4..8bdc2ed993f 100644 --- a/source/blender/editors/space_buttons/buttons_ops.c +++ b/source/blender/editors/space_buttons/buttons_ops.c @@ -378,7 +378,7 @@ void BUTTONS_OT_file_browse(wmOperatorType *ot) FILE_OPENFILE, WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); } /* Second operator, only difference from BUTTONS_OT_file_browse is WM_FILESEL_DIRECTORY. */ @@ -405,7 +405,7 @@ void BUTTONS_OT_directory_browse(wmOperatorType *ot) FILE_OPENFILE, WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); } /** \} */ diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index 26fa5b8a06c..1b962a92be5 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -329,7 +329,7 @@ void CLIP_OT_open(wmOperatorType *ot) FILE_OPENFILE, WM_FILESEL_RELPATH | WM_FILESEL_FILES | WM_FILESEL_DIRECTORY, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); } /** \} */ diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index 0631b6ea8a0..4d3e6cf4d6a 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -1043,13 +1043,13 @@ static int clear_track_path_exec(bContext *C, wmOperator *op) void CLIP_OT_clear_track_path(wmOperatorType *ot) { static const EnumPropertyItem clear_path_actions[] = { - {TRACK_CLEAR_UPTO, "UPTO", 0, "Clear up-to", "Clear path up to current frame"}, + {TRACK_CLEAR_UPTO, "UPTO", 0, "Clear Up To", "Clear path up to current frame"}, {TRACK_CLEAR_REMAINED, "REMAINED", 0, - "Clear remained", + "Clear Remained", "Clear path at remaining frames (after current)"}, - {TRACK_CLEAR_ALL, "ALL", 0, "Clear all", "Clear the whole path"}, + {TRACK_CLEAR_ALL, "ALL", 0, "Clear All", "Clear the whole path"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/editors/space_clip/tracking_select.c b/source/blender/editors/space_clip/tracking_select.c index 478d22c7582..063ea9592aa 100644 --- a/source/blender/editors/space_clip/tracking_select.c +++ b/source/blender/editors/space_clip/tracking_select.c @@ -975,15 +975,15 @@ static int select_grouped_exec(bContext *C, wmOperator *op) void CLIP_OT_select_grouped(wmOperatorType *ot) { static const EnumPropertyItem select_group_items[] = { - {0, "KEYFRAMED", 0, "Keyframed tracks", "Select all keyframed tracks"}, - {1, "ESTIMATED", 0, "Estimated tracks", "Select all estimated tracks"}, - {2, "TRACKED", 0, "Tracked tracks", "Select all tracked tracks"}, - {3, "LOCKED", 0, "Locked tracks", "Select all locked tracks"}, - {4, "DISABLED", 0, "Disabled tracks", "Select all disabled tracks"}, + {0, "KEYFRAMED", 0, "Keyframed Tracks", "Select all keyframed tracks"}, + {1, "ESTIMATED", 0, "Estimated Tracks", "Select all estimated tracks"}, + {2, "TRACKED", 0, "Tracked Tracks", "Select all tracked tracks"}, + {3, "LOCKED", 0, "Locked Tracks", "Select all locked tracks"}, + {4, "DISABLED", 0, "Disabled Tracks", "Select all disabled tracks"}, {5, "COLOR", 0, - "Tracks with same color", + "Tracks with Same Color", "Select all tracks with same color as active track"}, {6, "FAILED", 0, "Failed Tracks", "Select all tracks which failed to be reconstructed"}, {0, NULL, 0, NULL, NULL}, diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 91653fb7785..93367ad3d3c 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -1351,18 +1351,17 @@ static int file_column_sort_ui_context_invoke(bContext *C, if (column_type != COLUMN_NONE) { const FileAttributeColumn *column = &sfile->layout->attribute_columns[column_type]; - if (column->sort_type != FILE_SORT_NONE) { - if (sfile->params->sort == column->sort_type) { - /* Already sorting by selected column -> toggle sort invert (three state logic). */ - sfile->params->flag ^= FILE_SORT_INVERT; - } - else { - sfile->params->sort = column->sort_type; - sfile->params->flag &= ~FILE_SORT_INVERT; - } - - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); + BLI_assert(column->sort_type != FILE_SORT_DEFAULT); + if (sfile->params->sort == column->sort_type) { + /* Already sorting by selected column -> toggle sort invert (three state logic). */ + sfile->params->flag ^= FILE_SORT_INVERT; } + else { + sfile->params->sort = column->sort_type; + sfile->params->flag &= ~FILE_SORT_INVERT; + } + + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL); } } @@ -2415,7 +2414,8 @@ void file_directory_enter_handle(bContext *C, void *UNUSED(arg_unused), void *UN WM_operator_properties_create_ptr(&ptr, ot); RNA_string_set(&ptr, "directory", sfile->params->dir); RNA_boolean_set(&ptr, "open", true); - /* Enable confirmation prompt, else it's too easy to accidentally create new directories. */ + /* Enable confirmation prompt, else it's too easy + * to accidentally create new directories. */ RNA_boolean_set(&ptr, "confirm", true); if (lastdir) { diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 3004aadb5dd..9e51b6ca4ba 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -294,9 +294,6 @@ enum { typedef struct FileList { FileDirEntryArr filelist; - short prv_w; - short prv_h; - short flags; short sort; @@ -586,7 +583,7 @@ static int compare_extension(void *user_data, const void *a1, const void *a2) void filelist_sort(struct FileList *filelist) { - if ((filelist->flags & FL_NEED_SORTING) && (filelist->sort != FILE_SORT_NONE)) { + if (filelist->flags & FL_NEED_SORTING) { void *sort_cb = NULL; switch (filelist->sort) { @@ -602,7 +599,7 @@ void filelist_sort(struct FileList *filelist) case FILE_SORT_EXTENSION: sort_cb = compare_extension; break; - case FILE_SORT_NONE: /* Should never reach this point! */ + case FILE_SORT_DEFAULT: default: BLI_assert(0); break; @@ -951,12 +948,6 @@ void filelist_free_icons(void) } } -void filelist_imgsize(struct FileList *filelist, short w, short h) -{ - filelist->prv_w = w; - filelist->prv_h = h; -} - static FileDirEntry *filelist_geticon_get_file(struct FileList *filelist, const int index) { BLI_assert(G.background == false); @@ -1303,6 +1294,8 @@ static void filelist_cache_preview_runf(TaskPool *__restrict pool, void *taskdat } IMB_thumb_path_lock(preview->path); + /* Always generate biggest preview size for now, it's simpler and avoids having to re-generate in + * case user switch to a bigger preview size. */ preview->img = IMB_thumb_manage(preview->path, THB_LARGE, source); IMB_thumb_path_unlock(preview->path); @@ -1569,7 +1562,6 @@ void filelist_free(struct FileList *filelist) memset(&filelist->filter_data, 0, sizeof(filelist->filter_data)); filelist->flags &= ~(FL_NEED_SORTING | FL_NEED_FILTERING); - filelist->sort = FILE_SORT_NONE; } void filelist_freelib(struct FileList *filelist) diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h index 051b811b001..4b8cc052382 100644 --- a/source/blender/editors/space_file/filelist.h +++ b/source/blender/editors/space_file/filelist.h @@ -69,7 +69,6 @@ void filelist_filter(struct FileList *filelist); void filelist_init_icons(void); void filelist_free_icons(void); -void filelist_imgsize(struct FileList *filelist, short w, short h); struct ImBuf *filelist_getimage(struct FileList *filelist, const int index); struct ImBuf *filelist_geticon_image(struct FileList *filelist, const int index); int filelist_geticon(struct FileList *filelist, const int index, const bool is_main); diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 42b2806814b..15c6972c5f5 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -61,6 +61,7 @@ #include "BLF_api.h" #include "ED_fileselect.h" +#include "ED_screen.h" #include "WM_api.h" #include "WM_types.h" @@ -266,15 +267,16 @@ short ED_fileselect_set_params(SpaceFile *sfile) params->display = RNA_property_enum_get(op->ptr, prop); } + if (params->display == FILE_DEFAULTDISPLAY) { + params->display = U_default.file_space_data.display_type; + } + if ((prop = RNA_struct_find_property(op->ptr, "sort_method"))) { params->sort = RNA_property_enum_get(op->ptr, prop); } - else { - params->sort = U_default.file_space_data.sort_type; - } - if (params->display == FILE_DEFAULTDISPLAY) { - params->display = U_default.file_space_data.display_type; + if (params->sort == FILE_SORT_DEFAULT) { + params->sort = U_default.file_space_data.sort_type; } if (is_relative_path) { @@ -326,8 +328,9 @@ short ED_fileselect_set_params(SpaceFile *sfile) return 1; } -/* The subset of FileSelectParams.flag items we store into preferences. */ -#define PARAMS_FLAGS_REMEMBERED (FILE_HIDE_DOT | FILE_SORT_INVERT) +/* The subset of FileSelectParams.flag items we store into preferences. Note that FILE_SORT_ALPHA + * may also be remembered, but only conditionally. */ +#define PARAMS_FLAGS_REMEMBERED (FILE_HIDE_DOT) void ED_fileselect_window_params_get(const wmWindow *win, int win_size[2], bool *is_maximized) { @@ -340,6 +343,22 @@ void ED_fileselect_window_params_get(const wmWindow *win, int win_size[2], bool *is_maximized = WM_window_is_maximized(win); } +static bool file_select_use_default_display_type(const SpaceFile *sfile) +{ + PropertyRNA *prop; + return (sfile->op == NULL) || + !(prop = RNA_struct_find_property(sfile->op->ptr, "display_type")) || + (RNA_property_enum_get(sfile->op->ptr, prop) == FILE_DEFAULTDISPLAY); +} + +static bool file_select_use_default_sort_type(const SpaceFile *sfile) +{ + PropertyRNA *prop; + return (sfile->op == NULL) || + !(prop = RNA_struct_find_property(sfile->op->ptr, "sort_method")) || + (RNA_property_enum_get(sfile->op->ptr, prop) == FILE_SORT_DEFAULT); +} + void ED_fileselect_set_params_from_userdef(SpaceFile *sfile) { wmOperator *op = sfile->op; @@ -351,12 +370,6 @@ void ED_fileselect_set_params_from_userdef(SpaceFile *sfile) return; } - if (!RNA_struct_property_is_set(op->ptr, "display_type")) { - sfile->params->display = sfile_udata->display_type; - } - if (!RNA_struct_property_is_set(op->ptr, "sort_method")) { - sfile->params->sort = sfile_udata->sort_type; - } sfile->params->thumbnail_size = sfile_udata->thumbnail_size; sfile->params->details_flags = sfile_udata->details_flags; sfile->params->filter_id = sfile_udata->filter_id; @@ -364,6 +377,16 @@ void ED_fileselect_set_params_from_userdef(SpaceFile *sfile) /* Combine flags we take from params with the flags we take from userdef. */ sfile->params->flag = (sfile->params->flag & ~PARAMS_FLAGS_REMEMBERED) | (sfile_udata->flag & PARAMS_FLAGS_REMEMBERED); + + if (file_select_use_default_display_type(sfile)) { + sfile->params->display = sfile_udata->display_type; + } + if (file_select_use_default_sort_type(sfile)) { + sfile->params->sort = sfile_udata->sort_type; + /* For the default sorting, also take invert flag from userdef. */ + sfile->params->flag = (sfile->params->flag & ~FILE_SORT_INVERT) | + (sfile_udata->flag & FILE_SORT_INVERT); + } } /** @@ -380,13 +403,24 @@ void ED_fileselect_params_to_userdef(SpaceFile *sfile, UserDef_FileSpaceData *sfile_udata_new = &U.file_space_data; UserDef_FileSpaceData sfile_udata_old = U.file_space_data; - sfile_udata_new->display_type = sfile->params->display; sfile_udata_new->thumbnail_size = sfile->params->thumbnail_size; - sfile_udata_new->sort_type = sfile->params->sort; sfile_udata_new->details_flags = sfile->params->details_flags; sfile_udata_new->flag = sfile->params->flag & PARAMS_FLAGS_REMEMBERED; sfile_udata_new->filter_id = sfile->params->filter_id; + /* In some rare cases, operators ask for a specific display or sort type (e.g. chronological + * sorting for "Recover Auto Save"). So the settings are optimized for a specific operation. + * Don't let that change the userdef memory for more general cases. */ + if (file_select_use_default_display_type(sfile)) { + sfile_udata_new->display_type = sfile->params->display; + } + if (file_select_use_default_sort_type(sfile)) { + sfile_udata_new->sort_type = sfile->params->sort; + /* In this case also remember the invert flag. */ + sfile_udata_new->flag = (sfile_udata_new->flag & ~FILE_SORT_INVERT) | + (sfile->params->flag & FILE_SORT_INVERT); + } + if (temp_win_size && !is_maximized) { sfile_udata_new->temp_win_sizex = temp_win_size[0]; sfile_udata_new->temp_win_sizey = temp_win_size[1]; @@ -1050,3 +1084,20 @@ void file_params_renamefile_activate(SpaceFile *sfile, FileSelectParams *params) params->rename_flag = 0; } } + +ScrArea *ED_fileselect_handler_area_find(const wmWindow *win, const wmOperator *file_operator) +{ + bScreen *screen = WM_window_get_active_screen(win); + + ED_screen_areas_iter (win, screen, area) { + if (area->spacetype == SPACE_FILE) { + SpaceFile *sfile = area->spacedata.first; + + if (sfile->op == file_operator) { + return area; + } + } + } + + return NULL; +} diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c index 329b5fe67fd..b7d47902fe8 100644 --- a/source/blender/editors/space_file/fsmenu.c +++ b/source/blender/editors/space_file/fsmenu.c @@ -203,7 +203,7 @@ static void fsmenu_xdg_insert_entry(GHash *xdg_map, xdg_path = xdg_path_buf; } fsmenu_insert_entry( - fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, xdg_path, IFACE_(default_path), icon, FS_INSERT_LAST); + fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, xdg_path, N_(default_path), icon, FS_INSERT_LAST); } /** \} */ @@ -698,49 +698,49 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) fsmenu_add_windows_folder(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, &FOLDERID_Profile, - IFACE_("Home"), + N_("Home"), ICON_HOME, FS_INSERT_LAST); fsmenu_add_windows_folder(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, &FOLDERID_Desktop, - IFACE_("Desktop"), + N_("Desktop"), ICON_DESKTOP, FS_INSERT_LAST); fsmenu_add_windows_folder(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, &FOLDERID_Documents, - IFACE_("Documents"), + N_("Documents"), ICON_DOCUMENTS, FS_INSERT_LAST); fsmenu_add_windows_folder(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, &FOLDERID_Downloads, - IFACE_("Downloads"), + N_("Downloads"), ICON_IMPORT, FS_INSERT_LAST); fsmenu_add_windows_folder(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, &FOLDERID_Music, - IFACE_("Music"), + N_("Music"), ICON_FILE_SOUND, FS_INSERT_LAST); fsmenu_add_windows_folder(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, &FOLDERID_Pictures, - IFACE_("Pictures"), + N_("Pictures"), ICON_FILE_IMAGE, FS_INSERT_LAST); fsmenu_add_windows_folder(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, &FOLDERID_Videos, - IFACE_("Videos"), + N_("Videos"), ICON_FILE_MOVIE, FS_INSERT_LAST); fsmenu_add_windows_folder(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, &FOLDERID_Fonts, - IFACE_("Fonts"), + N_("Fonts"), ICON_FILE_FONT, FS_INSERT_LAST); @@ -757,16 +757,12 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) { /* We store some known macOS system paths and corresponding icons * and names in the FS_CATEGORY_OTHER (not displayed directly) category. */ - fsmenu_insert_entry(fsmenu, - FS_CATEGORY_OTHER, - "/Library/Fonts/", - IFACE_("Fonts"), - ICON_FILE_FONT, - FS_INSERT_LAST); + fsmenu_insert_entry( + fsmenu, FS_CATEGORY_OTHER, "/Library/Fonts/", N_("Fonts"), ICON_FILE_FONT, FS_INSERT_LAST); fsmenu_insert_entry(fsmenu, FS_CATEGORY_OTHER, "/Applications/", - IFACE_("Applications"), + N_("Applications"), ICON_FILE_FOLDER, FS_INSERT_LAST); @@ -777,13 +773,13 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) fsmenu_insert_entry(fsmenu, FS_CATEGORY_OTHER, line, name, icon, FS_INSERT_LAST); FS_MACOS_PATH("%s/", NULL, ICON_HOME) - FS_MACOS_PATH("%s/Desktop/", IFACE_("Desktop"), ICON_DESKTOP) - FS_MACOS_PATH("%s/Documents/", IFACE_("Documents"), ICON_DOCUMENTS) - FS_MACOS_PATH("%s/Downloads/", IFACE_("Downloads"), ICON_IMPORT) - FS_MACOS_PATH("%s/Movies/", IFACE_("Movies"), ICON_FILE_MOVIE) - FS_MACOS_PATH("%s/Music/", IFACE_("Music"), ICON_FILE_SOUND) - FS_MACOS_PATH("%s/Pictures/", IFACE_("Pictures"), ICON_FILE_IMAGE) - FS_MACOS_PATH("%s/Library/Fonts/", IFACE_("Fonts"), ICON_FILE_FONT) + FS_MACOS_PATH("%s/Desktop/", N_("Desktop"), ICON_DESKTOP) + FS_MACOS_PATH("%s/Documents/", N_("Documents"), ICON_DOCUMENTS) + FS_MACOS_PATH("%s/Downloads/", N_("Downloads"), ICON_IMPORT) + FS_MACOS_PATH("%s/Movies/", N_("Movies"), ICON_FILE_MOVIE) + FS_MACOS_PATH("%s/Music/", N_("Music"), ICON_FILE_SOUND) + FS_MACOS_PATH("%s/Pictures/", N_("Pictures"), ICON_FILE_IMAGE) + FS_MACOS_PATH("%s/Library/Fonts/", N_("Fonts"), ICON_FILE_FONT) # undef FS_MACOS_PATH @@ -902,7 +898,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) if (read_bookmarks && home) { fsmenu_insert_entry( - fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, home, IFACE_("Home"), ICON_HOME, FS_INSERT_LAST); + fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, home, N_("Home"), ICON_HOME, FS_INSERT_LAST); /* Follow the XDG spec, check if these are available. */ GHash *xdg_map = fsmenu_xdg_user_dirs_parse(home); diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 7fc1329df64..9523810aa07 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -1863,6 +1863,75 @@ void GRAPH_OT_bake(wmOperatorType *ot) /* TODO: add props for start/end frames (Joshua Leung 2009) */ } +/* ******************** Un-Bake F-Curve Operator *********************** */ +/* This operator unbakes the data of the selected F-Points to F-Curves. */ + +/* Un-Bake F-Points into F-Curves. */ +static void unbake_graph_curves(bAnimContext *ac, int start, int end) +{ + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + + /* Filter data. */ + const int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_SEL | + ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* Loop through filtered data and add keys between selected keyframes on every frame. */ + for (ale = anim_data.first; ale; ale = ale->next) { + FCurve *fcu = (FCurve *)ale->key_data; + + fcurve_samples_to_keyframes(fcu, start, end); + + ale->update |= ANIM_UPDATE_DEPS; + } + + ANIM_animdata_update(ac, &anim_data); + ANIM_animdata_freelist(&anim_data); +} + +/* ------------------- */ + +static int graphkeys_unbake_exec(bContext *C, wmOperator *UNUSED(op)) +{ + bAnimContext ac; + Scene *scene = NULL; + int start, end; + + /* Get editor data. */ + if (ANIM_animdata_get_context(C, &ac) == 0) { + return OPERATOR_CANCELLED; + } + + scene = ac.scene; + start = PSFRA; + end = PEFRA; + + /* Unbake keyframes. */ + unbake_graph_curves(&ac, start, end); + + /* Set notifier that keyframes have changed. */ + /* NOTE: some distinction between order/number of keyframes and type should be made? */ + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + + return OPERATOR_FINISHED; +} + +void GRAPH_OT_unbake(wmOperatorType *ot) +{ + /* Identifiers */ + ot->name = "Un-Bake Curve"; + ot->idname = "GRAPH_OT_unbake"; + ot->description = "Un-Bake selected F-Points to F-Curves"; + + /* API callbacks */ + ot->exec = graphkeys_unbake_exec; + ot->poll = graphop_selected_fcurve_poll; + + /* Flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + #ifdef WITH_AUDASPACE /* ******************** Sound Bake F-Curve Operator *********************** */ @@ -2021,7 +2090,7 @@ void GRAPH_OT_sound_bake(wmOperatorType *ot) FILE_OPENFILE, WM_FILESEL_FILEPATH | WM_FILESEL_SHOW_PROPS, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); RNA_def_float(ot->srna, "low", 0.0f, @@ -3507,7 +3576,7 @@ void GRAPH_OT_fmodifier_paste(wmOperatorType *ot) /* Properties */ RNA_def_boolean( - ot->srna, "only_active", true, "Only Active", "Only paste F-Modifiers on active F-Curve"); + ot->srna, "only_active", false, "Only Active", "Only paste F-Modifiers on active F-Curve"); RNA_def_boolean( ot->srna, "replace", diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h index eaa14fedb93..7add2f7cbb8 100644 --- a/source/blender/editors/space_graph/graph_intern.h +++ b/source/blender/editors/space_graph/graph_intern.h @@ -103,6 +103,7 @@ void GRAPH_OT_clean(struct wmOperatorType *ot); void GRAPH_OT_decimate(struct wmOperatorType *ot); void GRAPH_OT_sample(struct wmOperatorType *ot); void GRAPH_OT_bake(struct wmOperatorType *ot); +void GRAPH_OT_unbake(struct wmOperatorType *ot); void GRAPH_OT_sound_bake(struct wmOperatorType *ot); void GRAPH_OT_smooth(struct wmOperatorType *ot); void GRAPH_OT_euler_filter(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index fd68303e759..63acc2a1774 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -459,6 +459,7 @@ void graphedit_operatortypes(void) WM_operatortype_append(GRAPH_OT_easing_type); WM_operatortype_append(GRAPH_OT_sample); WM_operatortype_append(GRAPH_OT_bake); + WM_operatortype_append(GRAPH_OT_unbake); WM_operatortype_append(GRAPH_OT_sound_bake); WM_operatortype_append(GRAPH_OT_smooth); WM_operatortype_append(GRAPH_OT_clean); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index e36c7d6b6e7..6f511d30aa9 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1486,7 +1486,7 @@ void IMAGE_OT_open(wmOperatorType *ot) WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILES | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); RNA_def_boolean( ot->srna, @@ -1638,7 +1638,7 @@ void IMAGE_OT_replace(wmOperatorType *ot) FILE_OPENFILE, WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); } /** \} */ @@ -2038,7 +2038,7 @@ void IMAGE_OT_save_as(wmOperatorType *ot) FILE_SAVE, WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_SHOW_PROPS, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); } /** \} */ @@ -2047,36 +2047,17 @@ void IMAGE_OT_save_as(wmOperatorType *ot) /** \name Save Image Operator * \{ */ -static bool image_file_path_saveable(bContext *C, Image *ima, ImageUser *iuser) +/** + * \param iuser: Image user or NULL when called outside the image space. + */ +static bool image_file_format_writable(Image *ima, ImageUser *iuser) { - /* Can always repack images. */ - if (BKE_image_has_packedfile(ima)) { - return true; - } - - /* Test for valid filepath. */ void *lock; ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock); bool ret = false; - if (ibuf) { - Main *bmain = CTX_data_main(C); - char name[FILE_MAX]; - BLI_strncpy(name, ibuf->name, FILE_MAX); - BLI_path_abs(name, BKE_main_blendfile_path(bmain)); - - if (BLI_exists(name) == false) { - CTX_wm_operator_poll_msg_set(C, "image file not found"); - } - else if (!BLI_file_is_writable(name)) { - CTX_wm_operator_poll_msg_set(C, "image path can't be written to"); - } - else if (!BKE_image_buffer_format_writable(ibuf)) { - CTX_wm_operator_poll_msg_set(C, "image format is read-only"); - } - else { - ret = true; - } + if (ibuf && BKE_image_buffer_format_writable(ibuf)) { + ret = true; } BKE_image_release_ibuf(ima, ibuf, lock); @@ -2090,16 +2071,12 @@ static bool image_save_poll(bContext *C) return false; } - Image *ima = image_from_context(C); - ImageUser *iuser = image_user_from_context(C); - - /* Images without a filepath will go to save as. */ - if (!BKE_image_has_filepath(ima)) { - return true; - } + /* Check if there is a valid file path and image format we can write + * outside of the 'poll' so we can show a report with a pop-up. */ - /* Check if there is a valid file path and image format we can write. */ - return image_file_path_saveable(C, ima, iuser); + /* Can always repack images. + * Images without a filepath will go to "Save As". */ + return true; } static int image_save_exec(bContext *C, wmOperator *op) @@ -2114,6 +2091,8 @@ static int image_save_exec(bContext *C, wmOperator *op) if (BKE_image_has_packedfile(image)) { /* Save packed files to memory. */ BKE_image_memorypack(image); + /* Report since this can be called from key shortcuts. */ + BKE_reportf(op->reports, RPT_INFO, "Packed to memory image \"%s\"", image->filepath); return OPERATOR_FINISHED; } @@ -2123,16 +2102,15 @@ static int image_save_exec(bContext *C, wmOperator *op) } image_save_options_from_op(bmain, &opts, op, NULL); - if (BLI_exists(opts.filepath) && BLI_file_is_writable(opts.filepath)) { - if (save_image_op(bmain, image, iuser, op, &opts)) { - /* report since this can be called from key-shortcuts */ - BKE_reportf(op->reports, RPT_INFO, "Saved Image '%s'", opts.filepath); - ok = true; - } - } - else { + /* Check if file write permission is ok. */ + if (BLI_exists(opts.filepath) && !BLI_file_is_writable(opts.filepath)) { BKE_reportf( - op->reports, RPT_ERROR, "Cannot save image, path '%s' is not writable", opts.filepath); + op->reports, RPT_ERROR, "Cannot save image, path \"%s\" is not writable", opts.filepath); + } + else if (save_image_op(bmain, image, iuser, op, &opts)) { + /* Report since this can be called from key shortcuts. */ + BKE_reportf(op->reports, RPT_INFO, "Saved image \"%s\"", opts.filepath); + ok = true; } BKE_color_managed_view_settings_free(&opts.im_format.view_settings); @@ -2147,8 +2125,11 @@ static int image_save_exec(bContext *C, wmOperator *op) static int image_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Image *ima = image_from_context(C); + ImageUser *iuser = image_user_from_context(C); - if (!BKE_image_has_packedfile(ima) && !BKE_image_has_filepath(ima)) { + /* Not writable formats or images without a file-path will go to "Save As". */ + if (!BKE_image_has_packedfile(ima) && + (!BKE_image_has_filepath(ima) || !image_file_format_writable(ima, iuser))) { WM_operator_name_call(C, "IMAGE_OT_save_as", WM_OP_INVOKE_DEFAULT, NULL); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c index 0544a2cbefa..1435b95c9bf 100644 --- a/source/blender/editors/space_info/info_ops.c +++ b/source/blender/editors/space_info/info_ops.c @@ -516,7 +516,7 @@ void FILE_OT_find_missing_files(wmOperatorType *ot) FILE_OPENFILE, WM_FILESEL_DIRECTORY, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); } /********************* report box operator *********************/ diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index db8b6240558..bf21b383ba6 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -503,7 +503,7 @@ static void get_stats_string( else if (obedit->type == OB_ARMATURE) { *ofs += BLI_snprintf(info + *ofs, len - *ofs, - TIP_("Verts:%s/%s | Bones:%s/%s"), + TIP_("Joints:%s/%s | Bones:%s/%s"), stats_fmt->totvertsel, stats_fmt->totvert, stats_fmt->totbonesel, @@ -664,6 +664,7 @@ void ED_info_draw_stats( EDGES, FACES, TRIS, + JOINTS, BONES, LAYERS, FRAMES, @@ -678,6 +679,7 @@ void ED_info_draw_stats( STRNCPY(labels[EDGES], IFACE_("Edges")); STRNCPY(labels[FACES], IFACE_("Faces")); STRNCPY(labels[TRIS], IFACE_("Triangles")); + STRNCPY(labels[JOINTS], IFACE_("Joints")); STRNCPY(labels[BONES], IFACE_("Bones")); STRNCPY(labels[LAYERS], IFACE_("Layers")); STRNCPY(labels[FRAMES], IFACE_("Frames")); @@ -709,7 +711,7 @@ void ED_info_draw_stats( stats_row(col1, labels[TRIS], col2, stats_fmt.tottri, NULL, y, height); } else if (obedit->type == OB_ARMATURE) { - stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsel, stats_fmt.totvert, y, height); + stats_row(col1, labels[JOINTS], col2, stats_fmt.totvertsel, stats_fmt.totvert, y, height); stats_row(col1, labels[BONES], col2, stats_fmt.totbonesel, stats_fmt.totbone, y, height); } else { diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 66da2887427..16bbca2a0c3 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -748,6 +748,7 @@ static void node_shader_buts_vect_transform(uiLayout *layout, bContext *UNUSED(C static void node_shader_buts_attribute(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { + uiItemR(layout, ptr, "attribute_type", DEFAULT_FLAGS, IFACE_("Type"), ICON_NONE); uiItemR(layout, ptr, "attribute_name", DEFAULT_FLAGS, IFACE_("Name"), ICON_NONE); } diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c index f8382a17c59..508c0a47e21 100644 --- a/source/blender/editors/space_node/node_add.c +++ b/source/blender/editors/space_node/node_add.c @@ -404,7 +404,7 @@ void NODE_OT_add_file(wmOperatorType *ot) FILE_OPENFILE, WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME - 2, "Name", "Data-block name to assign"); } diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index 04e452d5270..aa59b7293a3 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -266,7 +266,7 @@ extern const char *node_context_dir[]; #define NODE_SOCKDY (0.08f * U.widget_unit) #define NODE_WIDTH(node) (node->width * UI_DPI_FAC) #define NODE_HEIGHT(node) (node->height * UI_DPI_FAC) -#define NODE_MARGIN_X (0.95f * U.widget_unit) +#define NODE_MARGIN_X (1.10f * U.widget_unit) #define NODE_SOCKSIZE (0.25f * U.widget_unit) #define NODE_RESIZE_MARGIN (0.20f * U.widget_unit) #define NODE_LINK_RESOL 12 diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index c6b5f2e2d2b..beba1fc9e8d 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -27,12 +27,16 @@ #include "DNA_armature_types.h" #include "DNA_collection_types.h" +#include "DNA_constraint_types.h" +#include "DNA_gpencil_modifier_types.h" #include "DNA_gpencil_types.h" #include "DNA_light_types.h" #include "DNA_material_types.h" +#include "DNA_modifier_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_sequence_types.h" +#include "DNA_shader_fx_types.h" #include "DNA_world_types.h" #include "BLI_listbase.h" @@ -40,21 +44,26 @@ #include "BKE_armature.h" #include "BKE_collection.h" +#include "BKE_constraint.h" #include "BKE_context.h" #include "BKE_gpencil.h" +#include "BKE_gpencil_modifier.h" #include "BKE_layer.h" #include "BKE_main.h" +#include "BKE_modifier.h" #include "BKE_object.h" #include "BKE_paint.h" +#include "BKE_particle.h" #include "BKE_report.h" #include "BKE_scene.h" -#include "BKE_sequencer.h" +#include "BKE_shader_fx.h" #include "BKE_workspace.h" #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" #include "ED_armature.h" +#include "ED_buttons.h" #include "ED_gpencil.h" #include "ED_object.h" #include "ED_outliner.h" @@ -63,6 +72,8 @@ #include "ED_sequencer.h" #include "ED_undo.h" +#include "SEQ_sequencer.h" + #include "WM_api.h" #include "WM_toolsystem.h" #include "WM_types.h" @@ -812,15 +823,26 @@ static eOLDrawState tree_element_active_psys(bContext *C, } static int tree_element_active_constraint(bContext *C, - Scene *UNUSED(scene), - ViewLayer *UNUSED(sl), - TreeElement *UNUSED(te), + Scene *scene, + ViewLayer *view_layer, + TreeElement *te, TreeStoreElem *tselem, const eOLSetState set) { if (set != OL_SETSEL_NONE) { Object *ob = (Object *)tselem->id; + /* Activate the parent bone if this is a bone constraint. */ + te = te->parent; + while (te) { + tselem = TREESTORE(te); + if (tselem->type == TSE_POSE_CHANNEL) { + tree_element_active_posechannel(C, scene, view_layer, ob, te, tselem, set, false); + return OL_DRAWSEL_NONE; + } + te = te->parent; + } + WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob); } @@ -1052,6 +1074,7 @@ eOLDrawState tree_element_type_active(bContext *C, case TSE_POSE_CHANNEL: return tree_element_active_posechannel( C, tvc->scene, tvc->view_layer, tvc->ob_pose, te, tselem, set, recursive); + case TSE_CONSTRAINT_BASE: case TSE_CONSTRAINT: return tree_element_active_constraint(C, tvc->scene, tvc->view_layer, te, tselem, set); case TSE_R_LAYER: @@ -1092,6 +1115,169 @@ bPoseChannel *outliner_find_parent_bone(TreeElement *te, TreeElement **r_bone_te return NULL; } +static void outliner_set_properties_tab(bContext *C, TreeElement *te, TreeStoreElem *tselem) +{ + PointerRNA ptr = {0}; + int context = 0; + + /* ID Types */ + if (tselem->type == 0) { + RNA_id_pointer_create(tselem->id, &ptr); + + switch (te->idcode) { + case ID_SCE: + context = BCONTEXT_SCENE; + break; + case ID_OB: + context = BCONTEXT_OBJECT; + break; + case ID_ME: + case ID_CU: + case ID_MB: + case ID_IM: + case ID_LT: + case ID_LA: + case ID_CA: + case ID_KE: + case ID_SPK: + case ID_AR: + case ID_GD: + case ID_LP: + case ID_HA: + case ID_PT: + case ID_VO: + context = BCONTEXT_DATA; + break; + case ID_MA: + context = BCONTEXT_MATERIAL; + break; + case ID_WO: + context = BCONTEXT_WORLD; + break; + } + } + else { + switch (tselem->type) { + case TSE_DEFGROUP_BASE: + case TSE_DEFGROUP: + RNA_id_pointer_create(tselem->id, &ptr); + context = BCONTEXT_DATA; + break; + case TSE_CONSTRAINT_BASE: + case TSE_CONSTRAINT: { + TreeElement *bone_te = NULL; + bPoseChannel *pchan = outliner_find_parent_bone(te, &bone_te); + + if (pchan) { + RNA_pointer_create(TREESTORE(bone_te)->id, &RNA_PoseBone, pchan, &ptr); + context = BCONTEXT_BONE_CONSTRAINT; + } + else { + RNA_id_pointer_create(tselem->id, &ptr); + context = BCONTEXT_CONSTRAINT; + } + + /* Expand the selected constraint in the properties editor. */ + if (tselem->type != TSE_CONSTRAINT_BASE) { + BKE_constraint_panel_expand(te->directdata); + } + break; + } + case TSE_MODIFIER_BASE: + case TSE_MODIFIER: + RNA_id_pointer_create(tselem->id, &ptr); + context = BCONTEXT_MODIFIER; + + if (tselem->type != TSE_MODIFIER_BASE) { + Object *ob = (Object *)tselem->id; + + if (ob->type == OB_GPENCIL) { + BKE_gpencil_modifier_panel_expand(te->directdata); + } + else { + BKE_modifier_panel_expand(te->directdata); + } + } + break; + case TSE_GPENCIL_EFFECT_BASE: + case TSE_GPENCIL_EFFECT: + RNA_id_pointer_create(tselem->id, &ptr); + context = BCONTEXT_SHADERFX; + + if (tselem->type != TSE_GPENCIL_EFFECT_BASE) { + BKE_shaderfx_panel_expand(te->directdata); + } + break; + case TSE_BONE: { + bArmature *arm = (bArmature *)tselem->id; + Bone *bone = te->directdata; + + RNA_pointer_create(&arm->id, &RNA_Bone, bone, &ptr); + context = BCONTEXT_BONE; + break; + } + case TSE_EBONE: { + bArmature *arm = (bArmature *)tselem->id; + EditBone *ebone = te->directdata; + + RNA_pointer_create(&arm->id, &RNA_EditBone, ebone, &ptr); + context = BCONTEXT_BONE; + break; + } + case TSE_POSE_CHANNEL: { + Object *ob = (Object *)tselem->id; + bArmature *arm = ob->data; + bPoseChannel *pchan = te->directdata; + + RNA_pointer_create(&arm->id, &RNA_PoseBone, pchan, &ptr); + context = BCONTEXT_BONE; + break; + } + case TSE_POSE_BASE: { + Object *ob = (Object *)tselem->id; + bArmature *arm = ob->data; + + RNA_pointer_create(&arm->id, &RNA_Armature, arm, &ptr); + context = BCONTEXT_DATA; + break; + } + case TSE_R_LAYER_BASE: + case TSE_R_LAYER: { + ViewLayer *view_layer = te->directdata; + + RNA_pointer_create(tselem->id, &RNA_ViewLayer, view_layer, &ptr); + context = BCONTEXT_VIEW_LAYER; + break; + } + case TSE_POSEGRP_BASE: + case TSE_POSEGRP: { + Object *ob = (Object *)tselem->id; + bArmature *arm = ob->data; + + RNA_pointer_create(&arm->id, &RNA_Armature, arm, &ptr); + context = BCONTEXT_DATA; + break; + } + case TSE_LINKED_PSYS: { + Object *ob = (Object *)tselem->id; + ParticleSystem *psys = psys_get_current(ob); + + RNA_pointer_create(&ob->id, &RNA_ParticleSystem, psys, &ptr); + context = BCONTEXT_PARTICLE; + break; + } + case TSE_GP_LAYER: + RNA_id_pointer_create(tselem->id, &ptr); + context = BCONTEXT_DATA; + break; + } + } + + if (ptr.data) { + ED_buttons_set_context(C, &ptr, context); + } +} + /* ================================================ */ /** @@ -1116,14 +1302,8 @@ static void do_outliner_item_activate_tree_element(bContext *C, TSE_SEQUENCE_DUP, TSE_EBONE, TSE_LAYER_COLLECTION)) { - /* Note about TSE_EBONE: In case of a same ID_AR datablock shared among several objects, - * we do not want to switch out of edit mode (see T48328 for details). */ - } - else if (tselem->id && OB_DATA_SUPPORT_EDITMODE(te->idcode)) { - /* Support edit-mode toggle, keeping the active object as is. */ - } - else if (tselem->type == TSE_POSE_BASE) { - /* Support pose mode toggle, keeping the active object as is. */ + /* Note about TSE_EBONE: In case of a same ID_AR datablock shared among several + * objects, we do not want to switch out of edit mode (see T48328 for details). */ } else if (do_activate_data) { tree_element_set_active_object(C, @@ -1198,6 +1378,8 @@ static void do_outliner_item_activate_tree_element(bContext *C, extend ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL, recursive); } + + outliner_set_properties_tab(C, te, tselem); } /* Select the item using the set flags */ diff --git a/source/blender/editors/space_outliner/outliner_sync.c b/source/blender/editors/space_outliner/outliner_sync.c index 3055d15725b..e1a96da1c91 100644 --- a/source/blender/editors/space_outliner/outliner_sync.c +++ b/source/blender/editors/space_outliner/outliner_sync.c @@ -39,7 +39,6 @@ #include "BKE_layer.h" #include "BKE_main.h" #include "BKE_object.h" -#include "BKE_sequencer.h" #include "DEG_depsgraph.h" @@ -47,6 +46,8 @@ #include "ED_object.h" #include "ED_outliner.h" +#include "SEQ_sequencer.h" + #include "WM_api.h" #include "WM_types.h" diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index cbdeb350ba4..159a4616ba7 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -65,7 +65,6 @@ #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_screen.h" -#include "BKE_sequencer.h" #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" @@ -89,6 +88,8 @@ #include "RNA_define.h" #include "RNA_enum_types.h" +#include "SEQ_sequencer.h" + #include "outliner_intern.h" /* -------------------------------------------------------------------- */ diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index 4fbb394c38f..9cd38ac07f5 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -69,7 +69,6 @@ #include "BKE_main.h" #include "BKE_modifier.h" #include "BKE_outliner_treehash.h" -#include "BKE_sequencer.h" #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" @@ -81,6 +80,8 @@ #include "RNA_access.h" +#include "SEQ_sequencer.h" + #include "UI_interface.h" #include "outliner_intern.h" @@ -2206,6 +2207,9 @@ static int outliner_exclude_filter_get(const SpaceOutliner *space_outliner) case SO_FILTER_OB_ACTIVE: exclude_filter |= SO_FILTER_OB_STATE_ACTIVE; break; + case SO_FILTER_OB_SELECTABLE: + exclude_filter |= SO_FILTER_OB_STATE_SELECTABLE; + break; } return exclude_filter; @@ -2288,6 +2292,11 @@ static bool outliner_element_visible_get(ViewLayer *view_layer, return false; } } + else if (exclude_filter & SO_FILTER_OB_STATE_SELECTABLE) { + if ((base->flag & BASE_SELECTABLE) == 0) { + return false; + } + } else { BLI_assert(exclude_filter & SO_FILTER_OB_STATE_ACTIVE); if (base != BASACT(view_layer)) { diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index 0725109944a..7cf5218cfaa 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -43,7 +43,6 @@ #include "BKE_mask.h" #include "BKE_movieclip.h" #include "BKE_report.h" -#include "BKE_sequencer.h" #include "WM_api.h" #include "WM_types.h" @@ -51,6 +50,8 @@ #include "RNA_define.h" #include "RNA_enum_types.h" +#include "SEQ_sequencer.h" + /* For menu, popup, icons, etc. */ #include "ED_screen.h" #include "ED_sequencer.h" @@ -724,7 +725,7 @@ void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot) WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_FILES | WM_FILESEL_SHOW_PROPS | WM_FILESEL_DIRECTORY, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME); RNA_def_boolean(ot->srna, "sound", true, "Sound", "Load sound with the movie"); RNA_def_boolean(ot->srna, @@ -779,7 +780,7 @@ void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot) WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_FILES | WM_FILESEL_SHOW_PROPS | WM_FILESEL_DIRECTORY, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME); RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory"); RNA_def_boolean(ot->srna, "mono", false, "Mono", "Merge all the sound's channels into one"); @@ -971,7 +972,7 @@ void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot) WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH | WM_FILESEL_FILES | WM_FILESEL_SHOW_PROPS | WM_FILESEL_DIRECTORY, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_ENDFRAME); RNA_def_boolean(ot->srna, diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index e9c5b003420..eb35cced95b 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -44,7 +44,6 @@ #include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_scene.h" -#include "BKE_sequencer.h" #include "BKE_sound.h" #include "IMB_colormanagement.h" @@ -69,6 +68,8 @@ #include "BIF_glutil.h" +#include "SEQ_sequencer.h" + #include "UI_interface.h" #include "UI_resources.h" #include "UI_view2d.h" diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 8a705ef49dd..e405864432a 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -43,9 +43,10 @@ #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_report.h" -#include "BKE_sequencer.h" #include "BKE_sound.h" +#include "SEQ_sequencer.h" + #include "WM_api.h" #include "WM_types.h" @@ -97,11 +98,11 @@ EnumPropertyItem sequencer_prop_effect_types[] = { #define SEQ_SIDE_MOUSE -1 EnumPropertyItem prop_side_types[] = { - {SEQ_SIDE_MOUSE, "MOUSE", 0, "Mouse position", ""}, + {SEQ_SIDE_MOUSE, "MOUSE", 0, "Mouse Position", ""}, {SEQ_SIDE_LEFT, "LEFT", 0, "Left", ""}, {SEQ_SIDE_RIGHT, "RIGHT", 0, "Right", ""}, {SEQ_SIDE_BOTH, "BOTH", 0, "Both", ""}, - {SEQ_SIDE_NO_CHANGE, "NO_CHANGE", 0, "No change", ""}, + {SEQ_SIDE_NO_CHANGE, "NO_CHANGE", 0, "No Change", ""}, {0, NULL, 0, NULL, NULL}, }; @@ -3918,7 +3919,7 @@ void SEQUENCER_OT_change_path(struct wmOperatorType *ot) WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH | WM_FILESEL_FILEPATH | WM_FILESEL_FILES, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); RNA_def_boolean(ot->srna, "use_placeholders", false, @@ -4063,7 +4064,7 @@ void SEQUENCER_OT_export_subtitles(struct wmOperatorType *ot) FILE_SAVE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); } /** \} */ diff --git a/source/blender/editors/space_sequencer/sequencer_modifier.c b/source/blender/editors/space_sequencer/sequencer_modifier.c index 50f2a5084ef..fb09afc6ca5 100644 --- a/source/blender/editors/space_sequencer/sequencer_modifier.c +++ b/source/blender/editors/space_sequencer/sequencer_modifier.c @@ -27,7 +27,6 @@ #include "DNA_scene_types.h" #include "BKE_context.h" -#include "BKE_sequencer.h" #include "WM_api.h" #include "WM_types.h" @@ -35,6 +34,8 @@ #include "RNA_define.h" #include "RNA_enum_types.h" +#include "SEQ_sequencer.h" + /* Own include. */ #include "sequencer_intern.h" diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c index 0a7aa1a6072..bdf6e4ece7f 100644 --- a/source/blender/editors/space_sequencer/sequencer_ops.c +++ b/source/blender/editors/space_sequencer/sequencer_ops.c @@ -34,7 +34,7 @@ #include "ED_sequencer.h" #include "ED_transform.h" /* Transform keymap. */ -#include "BKE_sequencer.h" +#include "SEQ_sequencer.h" #include "sequencer_intern.h" diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c index 0a4a1ae92d9..2af708494cb 100644 --- a/source/blender/editors/space_sequencer/sequencer_select.c +++ b/source/blender/editors/space_sequencer/sequencer_select.c @@ -33,13 +33,14 @@ #include "BKE_context.h" #include "BKE_report.h" -#include "BKE_sequencer.h" #include "WM_api.h" #include "WM_types.h" #include "RNA_define.h" +#include "SEQ_sequencer.h" + /* For menu, popup, icons, etc. */ #include "ED_outliner.h" diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c index 491c475b596..75d92d5f00d 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.c +++ b/source/blender/editors/space_sequencer/sequencer_view.c @@ -28,7 +28,6 @@ #include "DNA_scene_types.h" #include "BKE_context.h" -#include "BKE_sequencer.h" #include "WM_api.h" #include "WM_types.h" @@ -39,6 +38,8 @@ #include "RNA_define.h" +#include "SEQ_sequencer.h" + /* For menu, popup, icons, etc. */ #include "ED_anim_api.h" #include "ED_screen.h" diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 289477c8353..45c7bac54f8 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -38,7 +38,6 @@ #include "BKE_global.h" #include "BKE_lib_id.h" #include "BKE_screen.h" -#include "BKE_sequencer.h" #include "BKE_sequencer_offscreen.h" #include "ED_screen.h" @@ -52,6 +51,8 @@ #include "RNA_access.h" +#include "SEQ_sequencer.h" + #include "UI_interface.h" #include "UI_resources.h" #include "UI_view2d.h" diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 5c7f84ea386..7c592519384 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -159,6 +159,15 @@ static bool text_new_poll(bContext *UNUSED(C)) return 1; } +static bool text_data_poll(bContext *C) +{ + Text *text = CTX_data_edit_text(C); + if (!text) { + return false; + } + return true; +} + static bool text_edit_poll(bContext *C) { Text *text = CTX_data_edit_text(C); @@ -407,9 +416,9 @@ void TEXT_OT_open(wmOperatorType *ot) FILE_OPENFILE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); /* TODO: relative_path. */ + FILE_SORT_DEFAULT); /* TODO: relative_path. */ RNA_def_boolean( - ot->srna, "internal", 0, "Make internal", "Make text file internal after loading"); + ot->srna, "internal", 0, "Make Internal", "Make text file internal after loading"); } /** \} */ @@ -573,17 +582,6 @@ void TEXT_OT_make_internal(wmOperatorType *ot) /** \name Save Operator * \{ */ -static bool text_save_poll(bContext *C) -{ - Text *text = CTX_data_edit_text(C); - - if (!text_edit_poll(C)) { - return 0; - } - - return (text->filepath != NULL && !(text->flags & TXT_ISMEM)); -} - static void txt_write_file(Main *bmain, Text *text, ReportList *reports) { FILE *fp; @@ -594,6 +592,13 @@ static void txt_write_file(Main *bmain, Text *text, ReportList *reports) BLI_strncpy(filepath, text->filepath, FILE_MAX); BLI_path_abs(filepath, BKE_main_blendfile_path(bmain)); + /* Check if file write permission is ok. */ + if (BLI_exists(filepath) && !BLI_file_is_writable(filepath)) { + BKE_reportf( + reports, RPT_ERROR, "Cannot save text file, path \"%s\" is not writable", filepath); + return; + } + fp = BLI_fopen(filepath, "w"); if (fp == NULL) { BKE_reportf(reports, @@ -616,8 +621,8 @@ static void txt_write_file(Main *bmain, Text *text, ReportList *reports) if (BLI_stat(filepath, &st) == 0) { text->mtime = st.st_mtime; - /* report since this can be called from key-shortcuts */ - BKE_reportf(reports, RPT_INFO, "Saved Text '%s'", filepath); + /* Report since this can be called from key shortcuts. */ + BKE_reportf(reports, RPT_INFO, "Saved text \"%s\"", filepath); } else { text->mtime = 0; @@ -644,6 +649,18 @@ static int text_save_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static int text_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + Text *text = CTX_data_edit_text(C); + + /* Internal and texts without a filepath will go to "Save As". */ + if (text->filepath == NULL || (text->flags & TXT_ISMEM)) { + WM_operator_name_call(C, "TEXT_OT_save_as", WM_OP_INVOKE_DEFAULT, NULL); + return OPERATOR_CANCELLED; + } + return text_save_exec(C, op); +} + void TEXT_OT_save(wmOperatorType *ot) { /* identifiers */ @@ -653,7 +670,8 @@ void TEXT_OT_save(wmOperatorType *ot) /* api callbacks */ ot->exec = text_save_exec; - ot->poll = text_save_poll; + ot->invoke = text_save_invoke; + ot->poll = text_edit_poll; } /** \} */ @@ -733,7 +751,7 @@ void TEXT_OT_save_as(wmOperatorType *ot) FILE_SAVE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); /* XXX TODO, relative_path. */ + FILE_SORT_DEFAULT); /* XXX TODO, relative_path. */ } /** \} */ @@ -742,11 +760,6 @@ void TEXT_OT_save_as(wmOperatorType *ot) /** \name Run Script Operator * \{ */ -static bool text_run_script_poll(bContext *C) -{ - return (CTX_data_edit_text(C) != NULL); -} - static int text_run_script(bContext *C, ReportList *reports) { #ifdef WITH_PYTHON @@ -808,7 +821,7 @@ void TEXT_OT_run_script(wmOperatorType *ot) ot->description = "Run active script"; /* api callbacks */ - ot->poll = text_run_script_poll; + ot->poll = text_data_poll; ot->exec = text_run_script_exec; /* flags */ @@ -3693,7 +3706,7 @@ void TEXT_OT_replace(wmOperatorType *ot) /* properties */ PropertyRNA *prop; - prop = RNA_def_boolean(ot->srna, "all", false, "Replace all", "Replace all occurrences"); + prop = RNA_def_boolean(ot->srna, "all", false, "Replace All", "Replace all occurrences"); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } @@ -3781,6 +3794,17 @@ static const EnumPropertyItem resolution_items[] = { {0, NULL, 0, NULL, NULL}, }; +static bool text_resolve_conflict_poll(bContext *C) +{ + Text *text = CTX_data_edit_text(C); + + if (!text_edit_poll(C)) { + return false; + } + + return ((text->filepath != NULL) && !(text->flags & TXT_ISMEM)); +} + static int text_resolve_conflict_exec(bContext *C, wmOperator *op) { Text *text = CTX_data_edit_text(C); @@ -3872,7 +3896,7 @@ void TEXT_OT_resolve_conflict(wmOperatorType *ot) /* api callbacks */ ot->exec = text_resolve_conflict_exec; ot->invoke = text_resolve_conflict_invoke; - ot->poll = text_save_poll; + ot->poll = text_resolve_conflict_poll; /* properties */ RNA_def_enum(ot->srna, @@ -3891,7 +3915,7 @@ void TEXT_OT_resolve_conflict(wmOperatorType *ot) static int text_to_3d_object_exec(bContext *C, wmOperator *op) { - Text *text = CTX_data_edit_text(C); + const Text *text = CTX_data_edit_text(C); const bool split_lines = RNA_boolean_get(op->ptr, "split_lines"); ED_text_to_object(C, text, split_lines); @@ -3908,7 +3932,7 @@ void TEXT_OT_to_3d_object(wmOperatorType *ot) /* api callbacks */ ot->exec = text_to_3d_object_exec; - ot->poll = text_edit_poll; + ot->poll = text_data_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 8e03ed6e11d..f67eb73bbd1 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -283,7 +283,6 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float else if (ob->type == OB_CURVE || ob->type == OB_SURF) { TransformMedian_Curve *median = &median_basis.curve; Curve *cu = ob->data; - Nurb *nu; BPoint *bp; BezTriple *bezt; int a; @@ -291,8 +290,7 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float StructRNA *seltype = NULL; void *selp = NULL; - nu = nurbs->first; - while (nu) { + LISTBASE_FOREACH (Nurb *, nu, nurbs) { if (nu->type == CU_BEZIER) { bezt = nu->bezt; a = nu->pntsu; @@ -343,7 +341,6 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float bp++; } } - nu = nu->next; } if (totcurvedata == 1) { @@ -973,15 +970,13 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float const TransformMedian_Curve *median = &median_basis.curve, *ve_median = &ve_median_basis.curve; Curve *cu = ob->data; - Nurb *nu; BPoint *bp; BezTriple *bezt; int a; ListBase *nurbs = BKE_curve_editNurbs_get(cu); const float scale_w = compute_scale_factor(ve_median->weight, median->weight); - nu = nurbs->first; - while (nu) { + LISTBASE_FOREACH (Nurb *, nu, nurbs) { if (nu->type == CU_BEZIER) { for (a = nu->pntsu, bezt = nu->bezt; a--; bezt++) { if (bezt->f2 & SELECT) { @@ -1038,8 +1033,6 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float } BKE_nurb_test_2d(nu); BKE_nurb_handles_test(nu, true, false); /* test for bezier too */ - - nu = nu->next; } } else if ((ob->type == OB_LATTICE) && (apply_vcos || median_basis.lattice.weight)) { diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 633344837a1..d4c85eeb3d2 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -949,15 +949,16 @@ void ED_view3d_grid_steps(const Scene *scene, * Currently the simulation is only done when RV3D_VIEW_IS_AXIS. */ float ED_view3d_grid_view_scale(Scene *scene, View3D *v3d, - RegionView3D *rv3d, + ARegion *region, const char **r_grid_unit) { float grid_scale; + RegionView3D *rv3d = region->regiondata; if (!rv3d->is_persp && RV3D_VIEW_IS_AXIS(rv3d->view)) { /* Decrease the distance between grid snap points depending on zoom. */ /* `0.38` was a value visually obtained in order to get a snap distance * that matches previous versions Blender.*/ - float min_dist = 0.38f * (rv3d->dist / v3d->lens); + float min_dist = 16.0f / (region->sizex * rv3d->winmat[0][0]); float grid_steps[STEPS_LEN]; ED_view3d_grid_steps(scene, v3d, rv3d, grid_steps); /* Skip last item, in case the 'mid_dist' is greater than the largest unit. */ @@ -1468,12 +1469,13 @@ static void draw_selected_name( } static void draw_grid_unit_name( - Scene *scene, RegionView3D *rv3d, View3D *v3d, int xoffset, int *yoffset) + Scene *scene, ARegion *region, View3D *v3d, int xoffset, int *yoffset) { + RegionView3D *rv3d = region->regiondata; if (!rv3d->is_persp && RV3D_VIEW_IS_AXIS(rv3d->view)) { const char *grid_unit = NULL; int font_id = BLF_default(); - ED_view3d_grid_view_scale(scene, v3d, rv3d, &grid_unit); + ED_view3d_grid_view_scale(scene, v3d, region, &grid_unit); if (grid_unit) { char numstr[32] = ""; @@ -1558,7 +1560,7 @@ void view3d_draw_region_info(const bContext *C, ARegion *region) if (v3d->gridflag & (V3D_SHOW_FLOOR | V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_Z)) { /* draw below the viewport name */ - draw_grid_unit_name(scene, rv3d, v3d, xoffset, &yoffset); + draw_grid_unit_name(scene, region, v3d, xoffset, &yoffset); } DRW_draw_region_engine_info(xoffset, &yoffset, VIEW3D_OVERLAY_LINEHEIGHT); diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 7ec6bddd6a3..6e24dfd1db9 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -4828,7 +4828,7 @@ void VIEW3D_OT_background_image_add(wmOperatorType *ot) FILE_OPENFILE, WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, - FILE_SORT_ALPHA); + FILE_SORT_DEFAULT); } /** \} */ diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index 265cb04c7b2..148a0986c5c 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -73,14 +73,14 @@ static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph); Object *obact = CTX_data_active_object(C); Scene *scene = CTX_data_scene(C); - RegionView3D *rv3d = CTX_wm_region_data(C); + ARegion *region = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); TransVertStore tvs = {NULL}; TransVert *tv; float gridf, imat[3][3], bmat[3][3], vec[3]; int a; - gridf = ED_view3d_grid_view_scale(scene, v3d, rv3d, NULL); + gridf = ED_view3d_grid_view_scale(scene, v3d, region, NULL); if (OBEDIT_FROM_OBACT(obact)) { ViewLayer *view_layer = CTX_data_view_layer(C); @@ -657,11 +657,11 @@ void VIEW3D_OT_snap_selected_to_active(wmOperatorType *ot) static int snap_curs_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - RegionView3D *rv3d = CTX_wm_region_data(C); + ARegion *region = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); float gridf, *curs; - gridf = ED_view3d_grid_view_scale(scene, v3d, rv3d, NULL); + gridf = ED_view3d_grid_view_scale(scene, v3d, region, NULL); curs = scene->cursor.location; curs[0] = gridf * floorf(0.5f + curs[0] / gridf); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 4e08b6b1c5d..9f4777a716d 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -646,12 +646,12 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf) static const EnumPropertyItem modal_items[] = { {TFM_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, {TFM_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, - {TFM_MODAL_AXIS_X, "AXIS_X", 0, "X axis", ""}, - {TFM_MODAL_AXIS_Y, "AXIS_Y", 0, "Y axis", ""}, - {TFM_MODAL_AXIS_Z, "AXIS_Z", 0, "Z axis", ""}, - {TFM_MODAL_PLANE_X, "PLANE_X", 0, "X plane", ""}, - {TFM_MODAL_PLANE_Y, "PLANE_Y", 0, "Y plane", ""}, - {TFM_MODAL_PLANE_Z, "PLANE_Z", 0, "Z plane", ""}, + {TFM_MODAL_AXIS_X, "AXIS_X", 0, "X Axis", ""}, + {TFM_MODAL_AXIS_Y, "AXIS_Y", 0, "Y Axis", ""}, + {TFM_MODAL_AXIS_Z, "AXIS_Z", 0, "Z Axis", ""}, + {TFM_MODAL_PLANE_X, "PLANE_X", 0, "X Plane", ""}, + {TFM_MODAL_PLANE_Y, "PLANE_Y", 0, "Y Plane", ""}, + {TFM_MODAL_PLANE_Z, "PLANE_Z", 0, "Z Plane", ""}, {TFM_MODAL_CONS_OFF, "CONS_OFF", 0, "Clear Constraints", ""}, {TFM_MODAL_SNAP_INV_ON, "SNAP_INV_ON", 0, "Snap Invert", ""}, {TFM_MODAL_SNAP_INV_OFF, "SNAP_INV_OFF", 0, "Snap Invert (Off)", ""}, @@ -672,13 +672,13 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf) 0, "Decrease Max AutoIK Chain Length", ""}, - {TFM_MODAL_EDGESLIDE_UP, "EDGESLIDE_EDGE_NEXT", 0, "Select next Edge Slide Edge", ""}, - {TFM_MODAL_EDGESLIDE_DOWN, "EDGESLIDE_PREV_NEXT", 0, "Select previous Edge Slide Edge", ""}, + {TFM_MODAL_EDGESLIDE_UP, "EDGESLIDE_EDGE_NEXT", 0, "Select Next Edge Slide Edge", ""}, + {TFM_MODAL_EDGESLIDE_DOWN, "EDGESLIDE_PREV_NEXT", 0, "Select Previous Edge Slide Edge", ""}, {TFM_MODAL_PROPSIZE, "PROPORTIONAL_SIZE", 0, "Adjust Proportional Influence", ""}, {TFM_MODAL_INSERTOFS_TOGGLE_DIR, "INSERTOFS_TOGGLE_DIR", 0, - "Toggle Direction for Node Auto-offset", + "Toggle Direction for Node Auto-Offset", ""}, {TFM_MODAL_TRANSLATE, "TRANSLATE", 0, "Move", ""}, {TFM_MODAL_ROTATE, "ROTATE", 0, "Rotate", ""}, @@ -1626,11 +1626,9 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) static void initSnapSpatial(TransInfo *t, float r_snap[2]) { if (t->spacetype == SPACE_VIEW3D) { - RegionView3D *rv3d = t->region->regiondata; - - if (rv3d) { + if (t->region->regiondata) { View3D *v3d = t->area->spacedata.first; - r_snap[0] = ED_view3d_grid_view_scale(t->scene, v3d, rv3d, NULL) * 1.0f; + r_snap[0] = ED_view3d_grid_view_scale(t->scene, v3d, t->region, NULL) * 1.0f; r_snap[1] = r_snap[0] * 0.1f; } } diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c index 307fbbdf80b..3f86ef3e81b 100644 --- a/source/blender/editors/transform/transform_convert_sequencer.c +++ b/source/blender/editors/transform/transform_convert_sequencer.c @@ -29,10 +29,11 @@ #include "BKE_context.h" #include "BKE_report.h" -#include "BKE_sequencer.h" #include "ED_markers.h" +#include "SEQ_sequencer.h" + #include "UI_view2d.h" #include "transform.h" diff --git a/source/blender/editors/transform/transform_gizmo_2d.c b/source/blender/editors/transform/transform_gizmo_2d.c index c40f3d3f140..09100bb50cc 100644 --- a/source/blender/editors/transform/transform_gizmo_2d.c +++ b/source/blender/editors/transform/transform_gizmo_2d.c @@ -53,7 +53,7 @@ /* -------------------------------------------------------------------- */ /** \name Shared Callback's - */ + * \{ */ static bool gizmo2d_generic_poll(const bContext *C, wmGizmoGroupType *gzgt) { diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c index c525bc0e6ea..67b3a16627f 100644 --- a/source/blender/editors/transform/transform_mode.c +++ b/source/blender/editors/transform/transform_mode.c @@ -520,9 +520,7 @@ static void constraintSizeLim(TransInfo *t, TransData *td) } /* -------------------------------------------------------------------- */ -/* Transform (Rotation Utils) */ - -/** \name Transform Rotation Utils +/** \name Transform (Rotation Utils) * \{ */ /* Used by Transform Rotation and Transform Normal Rotation */ void headerRotation(TransInfo *t, char str[UI_MAX_DRAW_STR], float final) @@ -815,9 +813,7 @@ void ElementRotation( /** \} */ /* -------------------------------------------------------------------- */ -/* Transform (Resize Utils) */ - -/** \name Transform Resize Utils +/** \name Transform (Resize Utils) * \{ */ void headerResize(TransInfo *t, const float vec[3], char str[UI_MAX_DRAW_STR]) { @@ -1040,9 +1036,7 @@ void ElementResize(TransInfo *t, TransDataContainer *tc, TransData *td, float ma /** \} */ /* -------------------------------------------------------------------- */ -/* Transform (Frame Utils) */ - -/** \name Transform Frame Utils +/** \name Transform (Frame Utils) * \{ */ /** diff --git a/source/blender/editors/transform/transform_mode_align.c b/source/blender/editors/transform/transform_mode_align.c index 4fd4599b940..f16021914f1 100644 --- a/source/blender/editors/transform/transform_mode_align.c +++ b/source/blender/editors/transform/transform_mode_align.c @@ -35,9 +35,7 @@ #include "transform_mode.h" /* -------------------------------------------------------------------- */ -/* Transform (Align) */ - -/** \name Transform Align +/** \name Transform (Align) * \{ */ static void applyAlign(TransInfo *t, const int UNUSED(mval[2])) diff --git a/source/blender/editors/transform/transform_mode_baketime.c b/source/blender/editors/transform/transform_mode_baketime.c index 6470776e1a2..5efed6920dc 100644 --- a/source/blender/editors/transform/transform_mode_baketime.c +++ b/source/blender/editors/transform/transform_mode_baketime.c @@ -40,9 +40,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (Bake-Time) */ - -/** \name Transform Bake-Time +/** \name Transform (Bake-Time) * \{ */ static void applyBakeTime(TransInfo *t, const int mval[2]) diff --git a/source/blender/editors/transform/transform_mode_bbone_resize.c b/source/blender/editors/transform/transform_mode_bbone_resize.c index 57e809a566a..e827e604327 100644 --- a/source/blender/editors/transform/transform_mode_bbone_resize.c +++ b/source/blender/editors/transform/transform_mode_bbone_resize.c @@ -41,9 +41,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (EditBone (B-bone) width scaling) */ - -/** \name Transform B-bone width scaling +/** \name Transform (EditBone B-Bone width scaling) * \{ */ static void headerBoneSize(TransInfo *t, const float vec[3], char str[UI_MAX_DRAW_STR]) diff --git a/source/blender/editors/transform/transform_mode_bend.c b/source/blender/editors/transform/transform_mode_bend.c index ca22263712c..21a6a1ebafc 100644 --- a/source/blender/editors/transform/transform_mode_bend.c +++ b/source/blender/editors/transform/transform_mode_bend.c @@ -47,9 +47,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (Bend) */ - -/** \name Transform Bend +/** \name Transform (Bend) * \{ */ struct BendCustomData { diff --git a/source/blender/editors/transform/transform_mode_boneenvelope.c b/source/blender/editors/transform/transform_mode_boneenvelope.c index 1a25ee50543..ced159a76c9 100644 --- a/source/blender/editors/transform/transform_mode_boneenvelope.c +++ b/source/blender/editors/transform/transform_mode_boneenvelope.c @@ -40,9 +40,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (Bone Envelope) */ - -/** \name Transform Bone Envelope +/** \name Transform (Bone Envelope) * \{ */ static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2])) diff --git a/source/blender/editors/transform/transform_mode_boneroll.c b/source/blender/editors/transform/transform_mode_boneroll.c index cd277517d6b..da6c0b44c3a 100644 --- a/source/blender/editors/transform/transform_mode_boneroll.c +++ b/source/blender/editors/transform/transform_mode_boneroll.c @@ -40,9 +40,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (EditBone Roll) */ - -/** \name Transform EditBone Roll +/** \name Transform (EditBone Roll) * \{ */ static void applyBoneRoll(TransInfo *t, const int UNUSED(mval[2])) diff --git a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c index 1935264d6d0..ee63bf4be6f 100644 --- a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c +++ b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c @@ -40,9 +40,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (Curve Shrink/Fatten) */ - -/** \name Transform Curve Shrink/Fatten +/** \name Transform (Curve Shrink/Fatten) * \{ */ static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) diff --git a/source/blender/editors/transform/transform_mode_edge_bevelweight.c b/source/blender/editors/transform/transform_mode_edge_bevelweight.c index 2f7707cdee4..3ce52ed3296 100644 --- a/source/blender/editors/transform/transform_mode_edge_bevelweight.c +++ b/source/blender/editors/transform/transform_mode_edge_bevelweight.c @@ -40,9 +40,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (Bevel Weight) */ - -/** \name Transform Bevel Weight +/** \name Transform (Bevel Weight) * \{ */ static void applyBevelWeight(TransInfo *t, const int UNUSED(mval[2])) diff --git a/source/blender/editors/transform/transform_mode_edge_crease.c b/source/blender/editors/transform/transform_mode_edge_crease.c index e2e0afc0a8f..23fa20b68ff 100644 --- a/source/blender/editors/transform/transform_mode_edge_crease.c +++ b/source/blender/editors/transform/transform_mode_edge_crease.c @@ -40,9 +40,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (Crease) */ - -/** \name Transform Crease +/** \name Transform (Crease) * \{ */ static void applyCrease(TransInfo *t, const int UNUSED(mval[2])) diff --git a/source/blender/editors/transform/transform_mode_edge_rotate_normal.c b/source/blender/editors/transform/transform_mode_edge_rotate_normal.c index 4b083a0529f..32f0d4bd365 100644 --- a/source/blender/editors/transform/transform_mode_edge_rotate_normal.c +++ b/source/blender/editors/transform/transform_mode_edge_rotate_normal.c @@ -39,9 +39,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (Normal Rotation) */ - -/** \name Transform Normal Rotation +/** \name Transform (Normal Rotation) * \{ */ static void storeCustomLNorValue(TransDataContainer *tc, BMesh *bm) diff --git a/source/blender/editors/transform/transform_mode_edge_seq_slide.c b/source/blender/editors/transform/transform_mode_edge_seq_slide.c index 5222d4d4e5a..dfa5c164acf 100644 --- a/source/blender/editors/transform/transform_mode_edge_seq_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_seq_slide.c @@ -42,9 +42,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (Sequencer Slide) */ - -/** \name Transform Sequencer Slide +/** \name Transform (Sequencer Slide) * \{ */ static void headerSeqSlide(TransInfo *t, const float val[2], char str[UI_MAX_DRAW_STR]) diff --git a/source/blender/editors/transform/transform_mode_edge_slide.c b/source/blender/editors/transform/transform_mode_edge_slide.c index c887b69c792..dae3fe6f7b4 100644 --- a/source/blender/editors/transform/transform_mode_edge_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_slide.c @@ -56,9 +56,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (Edge Slide) */ - -/** \name Transform Edge Slide +/** \name Transform (Edge Slide) * \{ */ typedef struct TransDataEdgeSlideVert { diff --git a/source/blender/editors/transform/transform_mode_gpopacity.c b/source/blender/editors/transform/transform_mode_gpopacity.c index 5eb390d7cbd..103eb17c273 100644 --- a/source/blender/editors/transform/transform_mode_gpopacity.c +++ b/source/blender/editors/transform/transform_mode_gpopacity.c @@ -40,9 +40,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (GPencil Opacity) */ - -/** \name Transform GPencil Strokes Opacity +/** \name Transform (GPencil Strokes Opacity) * \{ */ static void applyGPOpacity(TransInfo *t, const int UNUSED(mval[2])) diff --git a/source/blender/editors/transform/transform_mode_gpshrinkfatten.c b/source/blender/editors/transform/transform_mode_gpshrinkfatten.c index 2d886b55a04..14e7c1df4f4 100644 --- a/source/blender/editors/transform/transform_mode_gpshrinkfatten.c +++ b/source/blender/editors/transform/transform_mode_gpshrinkfatten.c @@ -40,9 +40,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (GPencil Shrink/Fatten) */ - -/** \name Transform GPencil Strokes Shrink/Fatten +/** \name Transform (GPencil Strokes Shrink/Fatten) * \{ */ static void applyGPShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) diff --git a/source/blender/editors/transform/transform_mode_maskshrinkfatten.c b/source/blender/editors/transform/transform_mode_maskshrinkfatten.c index 1c5b5000f5c..3019984d70b 100644 --- a/source/blender/editors/transform/transform_mode_maskshrinkfatten.c +++ b/source/blender/editors/transform/transform_mode_maskshrinkfatten.c @@ -40,9 +40,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (Mask Shrink/Fatten) */ - -/** \name Transform Mask Shrink/Fatten +/** \name Transform (Mask Shrink/Fatten) * \{ */ static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) diff --git a/source/blender/editors/transform/transform_mode_mirror.c b/source/blender/editors/transform/transform_mode_mirror.c index 8d953610eb8..1440553de51 100644 --- a/source/blender/editors/transform/transform_mode_mirror.c +++ b/source/blender/editors/transform/transform_mode_mirror.c @@ -38,9 +38,7 @@ #include "transform_mode.h" /* -------------------------------------------------------------------- */ -/* Transform (Mirror) */ - -/** \name Transform Mirror +/** \name Transform (Mirror) * \{ */ static void applyMirror(TransInfo *t, const int UNUSED(mval[2])) diff --git a/source/blender/editors/transform/transform_mode_push_pull.c b/source/blender/editors/transform/transform_mode_push_pull.c index 860dd51da94..8a92978f33f 100644 --- a/source/blender/editors/transform/transform_mode_push_pull.c +++ b/source/blender/editors/transform/transform_mode_push_pull.c @@ -41,9 +41,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (Push/Pull) */ - -/** \name Transform Push/Pull +/** \name Transform (Push/Pull) * \{ */ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2])) diff --git a/source/blender/editors/transform/transform_mode_resize.c b/source/blender/editors/transform/transform_mode_resize.c index 33303b82567..62a4fbd6f04 100644 --- a/source/blender/editors/transform/transform_mode_resize.c +++ b/source/blender/editors/transform/transform_mode_resize.c @@ -39,9 +39,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (Resize) */ - -/** \name Transform Resize +/** \name Transform (Resize) * \{ */ static float ResizeBetween(TransInfo *t, const float p1[3], const float p2[3]) diff --git a/source/blender/editors/transform/transform_mode_rotate.c b/source/blender/editors/transform/transform_mode_rotate.c index d8857dbc31e..856e71a0df6 100644 --- a/source/blender/editors/transform/transform_mode_rotate.c +++ b/source/blender/editors/transform/transform_mode_rotate.c @@ -37,9 +37,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (Rotation) */ - -/** \name Transform Rotation +/** \name Transform (Rotation) * \{ */ static float RotationBetween(TransInfo *t, const float p1[3], const float p2[3]) diff --git a/source/blender/editors/transform/transform_mode_shear.c b/source/blender/editors/transform/transform_mode_shear.c index dfc6f69b341..a41c49710b9 100644 --- a/source/blender/editors/transform/transform_mode_shear.c +++ b/source/blender/editors/transform/transform_mode_shear.c @@ -44,9 +44,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (Shear) */ - -/** \name Transform Shear +/** \name Transform (Shear) * \{ */ static void initShear_mouseInputMode(TransInfo *t) diff --git a/source/blender/editors/transform/transform_mode_shrink_fatten.c b/source/blender/editors/transform/transform_mode_shrink_fatten.c index af33c2bb090..cdea388529f 100644 --- a/source/blender/editors/transform/transform_mode_shrink_fatten.c +++ b/source/blender/editors/transform/transform_mode_shrink_fatten.c @@ -42,9 +42,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (Shrink-Fatten) */ - -/** \name Transform Shrink-Fatten +/** \name Transform (Shrink-Fatten) * \{ */ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) diff --git a/source/blender/editors/transform/transform_mode_skin_resize.c b/source/blender/editors/transform/transform_mode_skin_resize.c index a1a6f0ce8f8..b4c919cbb86 100644 --- a/source/blender/editors/transform/transform_mode_skin_resize.c +++ b/source/blender/editors/transform/transform_mode_skin_resize.c @@ -38,9 +38,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (Skin) */ - -/** \name Transform Skin +/** \name Transform (Skin) * \{ */ static void applySkinResize(TransInfo *t, const int UNUSED(mval[2])) diff --git a/source/blender/editors/transform/transform_mode_tilt.c b/source/blender/editors/transform/transform_mode_tilt.c index 07e0e156803..d3b72fdf503 100644 --- a/source/blender/editors/transform/transform_mode_tilt.c +++ b/source/blender/editors/transform/transform_mode_tilt.c @@ -40,9 +40,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (Tilt) */ - -/** \name Transform Tilt +/** \name Transform (Tilt) * \{ */ static void applyTilt(TransInfo *t, const int UNUSED(mval[2])) diff --git a/source/blender/editors/transform/transform_mode_timescale.c b/source/blender/editors/transform/transform_mode_timescale.c index dbe06a6f1f6..7ae97c66660 100644 --- a/source/blender/editors/transform/transform_mode_timescale.c +++ b/source/blender/editors/transform/transform_mode_timescale.c @@ -42,9 +42,7 @@ #include "transform_mode.h" /* -------------------------------------------------------------------- */ -/* Transform (Animation Time Scale) */ - -/** \name Transform Animation Time Scale +/** \name Transform (Animation Time Scale) * \{ */ static void headerTimeScale(TransInfo *t, char str[UI_MAX_DRAW_STR]) diff --git a/source/blender/editors/transform/transform_mode_timeslide.c b/source/blender/editors/transform/transform_mode_timeslide.c index 9636b4f6e42..34d3251f9cf 100644 --- a/source/blender/editors/transform/transform_mode_timeslide.c +++ b/source/blender/editors/transform/transform_mode_timeslide.c @@ -45,9 +45,7 @@ #include "transform_mode.h" /* -------------------------------------------------------------------- */ -/* Transform (Animation Time Slide) */ - -/** \name Transform Animation Time Slide +/** \name Transform (Animation Time Slide) * \{ */ static void headerTimeSlide(TransInfo *t, const float sval, char str[UI_MAX_DRAW_STR]) diff --git a/source/blender/editors/transform/transform_mode_timetranslate.c b/source/blender/editors/transform/transform_mode_timetranslate.c index 226e8a377ea..adebc19c2b9 100644 --- a/source/blender/editors/transform/transform_mode_timetranslate.c +++ b/source/blender/editors/transform/transform_mode_timetranslate.c @@ -43,9 +43,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (Animation Translation) */ - -/** \name Transform Animation Translation +/** \name Transform (Animation Translation) * \{ */ static void headerTimeTranslate(TransInfo *t, char str[UI_MAX_DRAW_STR]) diff --git a/source/blender/editors/transform/transform_mode_tosphere.c b/source/blender/editors/transform/transform_mode_tosphere.c index f49462ccc65..c7a278fe5ea 100644 --- a/source/blender/editors/transform/transform_mode_tosphere.c +++ b/source/blender/editors/transform/transform_mode_tosphere.c @@ -40,9 +40,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (ToSphere) */ - -/** \name Transform ToSphere +/** \name Transform (ToSphere) * \{ */ static void applyToSphere(TransInfo *t, const int UNUSED(mval[2])) diff --git a/source/blender/editors/transform/transform_mode_trackball.c b/source/blender/editors/transform/transform_mode_trackball.c index 32019e151a1..5a57a69f986 100644 --- a/source/blender/editors/transform/transform_mode_trackball.c +++ b/source/blender/editors/transform/transform_mode_trackball.c @@ -40,9 +40,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (Rotation - Trackball) */ - -/** \name Transform Rotation - Trackball +/** \name Transform (Rotation - Trackball) * \{ */ static void applyTrackballValue(TransInfo *t, diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c index d4748e7933b..183fc8f5dc3 100644 --- a/source/blender/editors/transform/transform_mode_translate.c +++ b/source/blender/editors/transform/transform_mode_translate.c @@ -49,9 +49,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (Translation) */ - -/** \name Transform Translation +/** \name Transform (Translation) * \{ */ static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_DRAW_STR]) diff --git a/source/blender/editors/transform/transform_mode_vert_slide.c b/source/blender/editors/transform/transform_mode_vert_slide.c index 289ed76c731..1e5d027e253 100644 --- a/source/blender/editors/transform/transform_mode_vert_slide.c +++ b/source/blender/editors/transform/transform_mode_vert_slide.c @@ -53,9 +53,7 @@ #include "transform_snap.h" /* -------------------------------------------------------------------- */ -/* Transform (Vert Slide) */ - -/** \name Transform Vert Slide +/** \name Transform (Vert Slide) * \{ */ typedef struct TransDataVertSlideVert { diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index b164d0d443f..9f39099ea4b 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -825,6 +825,17 @@ static void TRANSFORM_OT_trackball(struct wmOperatorType *ot) Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER); } +/* Similar to #transform_shear_poll. */ +static bool transform_rotate_poll(bContext *C) +{ + if (!ED_operator_screenactive(C)) { + return false; + } + + ScrArea *area = CTX_wm_area(C); + return area && !ELEM(area->spacetype, SPACE_ACTION); +} + static void TRANSFORM_OT_rotate(struct wmOperatorType *ot) { /* identifiers */ @@ -838,7 +849,7 @@ static void TRANSFORM_OT_rotate(struct wmOperatorType *ot) ot->exec = transform_exec; ot->modal = transform_modal; ot->cancel = transform_cancel; - ot->poll = ED_operator_screenactive; + ot->poll = transform_rotate_poll; ot->poll_property = transform_poll_property; RNA_def_float_rotation( @@ -902,6 +913,7 @@ static void TRANSFORM_OT_bend(struct wmOperatorType *ot) Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT | P_CENTER); } +/* Similar to #transform_rotate_poll. */ static bool transform_shear_poll(bContext *C) { if (!ED_operator_screenactive(C)) { diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index e461bcb88e9..f1c4c243780 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -38,10 +38,11 @@ #include "BKE_layer.h" #include "BKE_object.h" #include "BKE_scene.h" -#include "BKE_sequencer.h" #include "RNA_access.h" +#include "SEQ_sequencer.h" + #include "WM_types.h" #include "ED_gizmo_library.h" diff --git a/source/blender/editors/util/ed_util_imbuf.c b/source/blender/editors/util/ed_util_imbuf.c index 9a2b346132e..9ae5cbbdfe9 100644 --- a/source/blender/editors/util/ed_util_imbuf.c +++ b/source/blender/editors/util/ed_util_imbuf.c @@ -30,7 +30,6 @@ #include "BKE_image.h" #include "BKE_main.h" #include "BKE_screen.h" -#include "BKE_sequencer.h" #include "ED_image.h" #include "ED_screen.h" @@ -43,6 +42,8 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "SEQ_sequencer.h" + #include "UI_view2d.h" #include "WM_api.h" |